Home | History | Annotate | Download | only in jni
      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