1 /* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "GLTest" 18 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 19 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 20 21 #include <android/log.h> 22 #include <android/native_window.h> 23 #include <GLTestHelper.h> 24 25 // this listener is used to forward the subset of 26 // gtest output needed to generate CTS results 27 class CTSGTestListener : public EmptyTestEventListener { 28 public: 29 CTSGTestListener(JNIEnv *env, jobject activity) 30 : mActivity(activity), mEnv(env) { 31 32 jclass clazz = env->FindClass( 33 "android/test/wrappedgtest/WrappedGTestActivity"); 34 mSendStatusID = env->GetMethodID(clazz, "sendStatus", 35 "(Ljava/lang/String;)V"); 36 mMessageBuffer = new char[2048]; 37 } 38 39 ~CTSGTestListener() { 40 delete[] mMessageBuffer; 41 } 42 43 private: 44 jobject mActivity; 45 JNIEnv * mEnv; 46 jmethodID mSendStatusID; 47 char * mMessageBuffer; 48 49 virtual void OnTestIterationStart(const UnitTest& unit_test, 50 int iteration) { 51 snprintf(mMessageBuffer, sizeof(char) * 2048, 52 "[==========] Running %i tests from %i test cases.", 53 unit_test.test_to_run_count(), 54 unit_test.test_case_to_run_count()); 55 56 mEnv->CallVoidMethod(mActivity, mSendStatusID, 57 mEnv->NewStringUTF(mMessageBuffer)); 58 } 59 60 virtual void OnTestStart(const TestInfo& test_info) { 61 snprintf(mMessageBuffer, sizeof(char) * 2048, "[ RUN ] %s.%s", 62 test_info.test_case_name(), test_info.name()); 63 64 mEnv->CallVoidMethod(mActivity, mSendStatusID, 65 mEnv->NewStringUTF(mMessageBuffer)); 66 } 67 68 virtual void OnTestPartResult(const TestPartResult& result) { 69 if (result.type() == TestPartResult::kSuccess) { 70 return; 71 } 72 73 snprintf(mMessageBuffer, sizeof(char) * 2048, "%s:%i: Failure\n%s", 74 result.file_name(), result.line_number(), result.message()); 75 76 mEnv->CallVoidMethod(mActivity, mSendStatusID, 77 mEnv->NewStringUTF(mMessageBuffer)); 78 } 79 80 virtual void OnTestEnd(const TestInfo& test_info) { 81 const char * result = test_info.result()->Passed() ? 82 "[ OK ] " : "[ FAILED ] "; 83 84 snprintf(mMessageBuffer, sizeof(char) * 2048, "%s%s.%s (%lli ms)", 85 result, test_info.test_case_name(), test_info.name(), 86 test_info.result()->elapsed_time()); 87 88 mEnv->CallVoidMethod(mActivity, mSendStatusID, 89 mEnv->NewStringUTF(mMessageBuffer)); 90 } 91 92 virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) { 93 snprintf(mMessageBuffer, sizeof(char) * 2048, 94 "[==========] %i tests from %i test cases ran. (%lli ms total)", 95 unit_test.test_to_run_count(), 96 unit_test.test_case_to_run_count(), unit_test.elapsed_time()); 97 98 mEnv->CallVoidMethod(mActivity, mSendStatusID, 99 mEnv->NewStringUTF(mMessageBuffer)); 100 } 101 }; 102 103 // this listener is similar to the default gtest listener 104 // but it outputs the results to the log instead of stdout 105 class LogGTestListener : public EmptyTestEventListener { 106 107 private: 108 virtual void OnTestIterationStart(const UnitTest& unit_test, 109 int iteration) { 110 LOGI("[==========] Running %i tests from %i test cases.\n", 111 unit_test.test_to_run_count(), 112 unit_test.test_case_to_run_count()); 113 } 114 115 virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) { 116 LOGI("[==========] Global test environment set-up.\n"); 117 } 118 119 virtual void OnTestCaseStart(const TestCase& test_case) { 120 LOGI("[----------] %i tests from %s\n", 121 test_case.test_to_run_count(), 122 test_case.name()); 123 124 } 125 126 virtual void OnTestStart(const TestInfo& test_info) { 127 LOGI("[ RUN ] %s.%s\n", test_info.test_case_name(), 128 test_info.name()); 129 130 } 131 132 virtual void OnTestPartResult(const TestPartResult& result) { 133 if (result.type() == TestPartResult::kSuccess) { 134 return; 135 } 136 137 LOGI("%s:%i: Failure\n%s\n", result.file_name(), result.line_number(), 138 result.message()); 139 } 140 141 virtual void OnTestEnd(const TestInfo& test_info) { 142 const char * result = test_info.result()->Passed() ? 143 "[ OK ] " : "[ FAILED ] "; 144 145 LOGI("%s%s.%s (%lli ms)\n", result, test_info.test_case_name(), 146 test_info.name(), test_info.result()->elapsed_time()); 147 } 148 149 150 virtual void OnTestCaseEnd(const TestCase& test_case) { 151 LOGI("[----------] %i tests from %s (%lli ms total)\n", 152 test_case.test_to_run_count(), test_case.name(), 153 test_case.elapsed_time()); 154 155 } 156 157 virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) { 158 LOGI("[==========] Global test environment tear-down.\n"); 159 } 160 161 void PrintFailedTests(const UnitTest& unit_test) { 162 const int failed_test_count = unit_test.failed_test_count(); 163 if (failed_test_count == 0) { 164 return; 165 } 166 167 for (int i = 0; i < unit_test.total_test_case_count(); ++i) { 168 const TestCase& test_case = *unit_test.GetTestCase(i); 169 170 if (!test_case.should_run() || test_case.failed_test_count() == 0) { 171 continue; 172 } 173 174 for (int j = 0; j < test_case.total_test_count(); ++j) { 175 const TestInfo& test_info = *test_case.GetTestInfo(j); 176 if (!test_info.should_run() || test_info.result()->Passed()) { 177 continue; 178 } 179 LOGI("[ FAILED ] %s.%s\n", test_case.name(), 180 test_info.name()); 181 } 182 } 183 } 184 virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) { 185 LOGI("[==========] %i tests from %i test cases ran. (%lli ms total)\n", 186 unit_test.test_to_run_count(), 187 unit_test.test_case_to_run_count(), unit_test.elapsed_time()); 188 189 LOGI("[ PASSED ] %i tests\n", unit_test.successful_test_count()); 190 191 if(unit_test.Passed()) { 192 return; 193 } 194 195 LOGI("[ FAILED ] %i tests, listed below:\n", 196 unit_test.failed_test_count()); 197 198 PrintFailedTests(unit_test); 199 200 LOGI("\n%2d FAILED TESTS\n", unit_test.failed_test_count()); 201 } 202 }; 203 204 ANativeWindow* GLTestHelper::mWindow; 205 206 ANativeWindow* GLTestHelper::getWindow() { 207 return mWindow; 208 } 209 210 void GLTestHelper::setWindow(JNIEnv *env, jobject obj, jobject surface) { 211 mWindow = ANativeWindow_fromSurface(env, surface); 212 } 213 214 int GLTestHelper::runGTests(TestEventListener * listener, char * filter) { 215 216 if (filter) { 217 ::testing::GTEST_FLAG(filter) = filter; 218 } 219 220 int argc = 0; 221 InitGoogleTest(&argc, (char**)NULL); 222 223 TestEventListeners& listeners = UnitTest::GetInstance()->listeners(); 224 delete listeners.Release(listeners.default_result_printer()); 225 226 listeners.Append(listener); 227 int result = RUN_ALL_TESTS(); 228 return result; 229 } 230 231 int GLTestHelper::runTests(JNIEnv *env, jobject obj, jstring filter) { 232 LogGTestListener * listener = new LogGTestListener(); 233 234 char * filter_cstr = NULL; 235 236 // set filter if there is one 237 if (filter) { 238 filter_cstr = new char[512]; 239 const char * ptr = env->GetStringUTFChars(filter, NULL); 240 snprintf(filter_cstr, sizeof(char) * 512, "%s", ptr); 241 env->ReleaseStringUTFChars(filter, ptr); 242 } 243 244 int result = runGTests(listener, filter_cstr); 245 246 if (filter_cstr) { 247 delete[] filter_cstr; 248 } 249 250 delete listener; 251 return result; 252 } 253 254 int GLTestHelper::runTestsCTS(JNIEnv *env, jobject obj, jobject activity) { 255 CTSGTestListener * listener = new CTSGTestListener(env, activity); 256 int result = runGTests(listener, NULL); 257 delete listener; 258 return result; 259 } 260 261 int GLTestHelper::registerNative(JNIEnv * env) { 262 263 jclass clazz = env->FindClass("com/android/opengl/cts/GLTestActivity"); 264 265 jthrowable exception = env->ExceptionOccurred(); 266 // CTS class not found, assume stand-alone application 267 if (exception) { 268 env->ExceptionClear(); 269 270 if (!env->IsInstanceOf(env->ExceptionOccurred(), 271 env->FindClass("java/lang/NoClassDefFoundError"))) { 272 env->Throw(exception); 273 } 274 275 // 276 JNINativeMethod standaloneMethods[] = { 277 // name, signature, function 278 { "setSurface", "(Landroid/view/Surface;)V", (void*)(GLTestHelper::setWindow) }, 279 { "runTests", "(Ljava/lang/String;)V", (void*)(GLTestHelper::runTests) }, 280 }; 281 282 return env->RegisterNatives( 283 env->FindClass("com/android/gltest/GLTestActivity"), 284 standaloneMethods, 285 sizeof(standaloneMethods) / sizeof(JNINativeMethod)); 286 } 287 288 // GLTestActivity methods 289 JNINativeMethod glTestActMethods[] = { 290 // name, signature, function 291 { "setSurface", "(Landroid/view/Surface;)V", (void*)(GLTestHelper::setWindow) }, 292 }; 293 294 int result = env->RegisterNatives(clazz, glTestActMethods, 295 sizeof(glTestActMethods) / sizeof(JNINativeMethod)); 296 297 if (result) { 298 return result; 299 } 300 301 // WrappedGTestActivity methods 302 JNINativeMethod wrappedGTestActMethods[] = { 303 // name, signature, function 304 { "runTests", "(Landroid/test/wrappedgtest/WrappedGTestActivity;)I", 305 (void*)(GLTestHelper::runTestsCTS) }, 306 }; 307 308 return env->RegisterNatives( 309 env->FindClass("android/test/wrappedgtest/WrappedGTestActivity"), 310 wrappedGTestActMethods, 311 sizeof(wrappedGTestActMethods) / sizeof(JNINativeMethod)); 312 } 313