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:
CTSGTestListener(JNIEnv * env,jobject activity)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
~CTSGTestListener()39 ~CTSGTestListener() {
40 delete[] mMessageBuffer;
41 }
42
43 private:
44 jobject mActivity;
45 JNIEnv * mEnv;
46 jmethodID mSendStatusID;
47 char * mMessageBuffer;
48
OnTestIterationStart(const UnitTest & unit_test,int iteration)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
OnTestStart(const TestInfo & test_info)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
OnTestPartResult(const TestPartResult & result)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
OnTestEnd(const TestInfo & test_info)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
OnTestIterationEnd(const UnitTest & unit_test,int iteration)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:
OnTestIterationStart(const UnitTest & unit_test,int iteration)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
OnEnvironmentsSetUpStart(const UnitTest & unit_test)115 virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) {
116 LOGI("[==========] Global test environment set-up.\n");
117 }
118
OnTestCaseStart(const TestCase & test_case)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
OnTestStart(const TestInfo & test_info)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
OnTestPartResult(const TestPartResult & result)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
OnTestEnd(const TestInfo & test_info)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
OnTestCaseEnd(const TestCase & test_case)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
OnEnvironmentsTearDownStart(const UnitTest & unit_test)157 virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) {
158 LOGI("[==========] Global test environment tear-down.\n");
159 }
160
PrintFailedTests(const UnitTest & unit_test)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 }
OnTestIterationEnd(const UnitTest & unit_test,int iteration)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
getWindow()206 ANativeWindow* GLTestHelper::getWindow() {
207 return mWindow;
208 }
209
setWindow(JNIEnv * env,jobject obj,jobject surface)210 void GLTestHelper::setWindow(JNIEnv *env, jobject obj, jobject surface) {
211 mWindow = ANativeWindow_fromSurface(env, surface);
212 }
213
runGTests(TestEventListener * listener,char * filter)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
runTests(JNIEnv * env,jobject obj,jstring filter)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
runTestsCTS(JNIEnv * env,jobject obj,jobject activity)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
registerNative(JNIEnv * env)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