blob: d1f29d51fddfcf8bc180884ce86dac3269a9307a [file] [log] [blame]
/*
* Copyright 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "GLTest"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#include <android/log.h>
#include <android/native_window.h>
#include <GLTestHelper.h>
// this listener is used to forward the subset of
// gtest output needed to generate CTS results
class CTSGTestListener : public EmptyTestEventListener {
public:
CTSGTestListener(JNIEnv *env, jobject activity)
: mActivity(activity), mEnv(env) {
jclass clazz = env->FindClass(
"android/test/wrappedgtest/WrappedGTestActivity");
mSendStatusID = env->GetMethodID(clazz, "sendStatus",
"(Ljava/lang/String;)V");
mMessageBuffer = new char[2048];
}
~CTSGTestListener() {
delete[] mMessageBuffer;
}
private:
jobject mActivity;
JNIEnv * mEnv;
jmethodID mSendStatusID;
char * mMessageBuffer;
virtual void OnTestIterationStart(const UnitTest& unit_test,
int iteration) {
snprintf(mMessageBuffer, sizeof(char) * 2048,
"[==========] Running %i tests from %i test cases.",
unit_test.test_to_run_count(),
unit_test.test_case_to_run_count());
mEnv->CallVoidMethod(mActivity, mSendStatusID,
mEnv->NewStringUTF(mMessageBuffer));
}
virtual void OnTestStart(const TestInfo& test_info) {
snprintf(mMessageBuffer, sizeof(char) * 2048, "[ RUN ] %s.%s",
test_info.test_case_name(), test_info.name());
mEnv->CallVoidMethod(mActivity, mSendStatusID,
mEnv->NewStringUTF(mMessageBuffer));
}
virtual void OnTestPartResult(const TestPartResult& result) {
if (result.type() == TestPartResult::kSuccess) {
return;
}
snprintf(mMessageBuffer, sizeof(char) * 2048, "%s:%i: Failure\n%s",
result.file_name(), result.line_number(), result.message());
mEnv->CallVoidMethod(mActivity, mSendStatusID,
mEnv->NewStringUTF(mMessageBuffer));
}
virtual void OnTestEnd(const TestInfo& test_info) {
const char * result = test_info.result()->Passed() ?
"[ OK ] " : "[ FAILED ] ";
snprintf(mMessageBuffer, sizeof(char) * 2048, "%s%s.%s (%lli ms)",
result, test_info.test_case_name(), test_info.name(),
test_info.result()->elapsed_time());
mEnv->CallVoidMethod(mActivity, mSendStatusID,
mEnv->NewStringUTF(mMessageBuffer));
}
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) {
snprintf(mMessageBuffer, sizeof(char) * 2048,
"[==========] %i tests from %i test cases ran. (%lli ms total)",
unit_test.test_to_run_count(),
unit_test.test_case_to_run_count(), unit_test.elapsed_time());
mEnv->CallVoidMethod(mActivity, mSendStatusID,
mEnv->NewStringUTF(mMessageBuffer));
}
};
// this listener is similar to the default gtest listener
// but it outputs the results to the log instead of stdout
class LogGTestListener : public EmptyTestEventListener {
private:
virtual void OnTestIterationStart(const UnitTest& unit_test,
int iteration) {
LOGI("[==========] Running %i tests from %i test cases.\n",
unit_test.test_to_run_count(),
unit_test.test_case_to_run_count());
}
virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) {
LOGI("[==========] Global test environment set-up.\n");
}
virtual void OnTestCaseStart(const TestCase& test_case) {
LOGI("[----------] %i tests from %s\n",
test_case.test_to_run_count(),
test_case.name());
}
virtual void OnTestStart(const TestInfo& test_info) {
LOGI("[ RUN ] %s.%s\n", test_info.test_case_name(),
test_info.name());
}
virtual void OnTestPartResult(const TestPartResult& result) {
if (result.type() == TestPartResult::kSuccess) {
return;
}
LOGI("%s:%i: Failure\n%s\n", result.file_name(), result.line_number(),
result.message());
}
virtual void OnTestEnd(const TestInfo& test_info) {
const char * result = test_info.result()->Passed() ?
"[ OK ] " : "[ FAILED ] ";
LOGI("%s%s.%s (%lli ms)\n", result, test_info.test_case_name(),
test_info.name(), test_info.result()->elapsed_time());
}
virtual void OnTestCaseEnd(const TestCase& test_case) {
LOGI("[----------] %i tests from %s (%lli ms total)\n",
test_case.test_to_run_count(), test_case.name(),
test_case.elapsed_time());
}
virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) {
LOGI("[==========] Global test environment tear-down.\n");
}
void PrintFailedTests(const UnitTest& unit_test) {
const int failed_test_count = unit_test.failed_test_count();
if (failed_test_count == 0) {
return;
}
for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
const TestCase& test_case = *unit_test.GetTestCase(i);
if (!test_case.should_run() || test_case.failed_test_count() == 0) {
continue;
}
for (int j = 0; j < test_case.total_test_count(); ++j) {
const TestInfo& test_info = *test_case.GetTestInfo(j);
if (!test_info.should_run() || test_info.result()->Passed()) {
continue;
}
LOGI("[ FAILED ] %s.%s\n", test_case.name(),
test_info.name());
}
}
}
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) {
LOGI("[==========] %i tests from %i test cases ran. (%lli ms total)\n",
unit_test.test_to_run_count(),
unit_test.test_case_to_run_count(), unit_test.elapsed_time());
LOGI("[ PASSED ] %i tests\n", unit_test.successful_test_count());
if(unit_test.Passed()) {
return;
}
LOGI("[ FAILED ] %i tests, listed below:\n",
unit_test.failed_test_count());
PrintFailedTests(unit_test);
LOGI("\n%2d FAILED TESTS\n", unit_test.failed_test_count());
}
};
ANativeWindow* GLTestHelper::mWindow;
ANativeWindow* GLTestHelper::getWindow() {
return mWindow;
}
void GLTestHelper::setWindow(JNIEnv *env, jobject obj, jobject surface) {
mWindow = ANativeWindow_fromSurface(env, surface);
}
int GLTestHelper::runGTests(TestEventListener * listener, char * filter) {
if (filter) {
::testing::GTEST_FLAG(filter) = filter;
}
int argc = 0;
InitGoogleTest(&argc, (char**)NULL);
TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
delete listeners.Release(listeners.default_result_printer());
listeners.Append(listener);
int result = RUN_ALL_TESTS();
return result;
}
int GLTestHelper::runTests(JNIEnv *env, jobject obj, jstring filter) {
LogGTestListener * listener = new LogGTestListener();
char * filter_cstr = NULL;
// set filter if there is one
if (filter) {
filter_cstr = new char[512];
const char * ptr = env->GetStringUTFChars(filter, NULL);
snprintf(filter_cstr, sizeof(char) * 512, "%s", ptr);
env->ReleaseStringUTFChars(filter, ptr);
}
int result = runGTests(listener, filter_cstr);
if (filter_cstr) {
delete[] filter_cstr;
}
delete listener;
return result;
}
int GLTestHelper::runTestsCTS(JNIEnv *env, jobject obj, jobject activity) {
CTSGTestListener * listener = new CTSGTestListener(env, activity);
int result = runGTests(listener, NULL);
delete listener;
return result;
}
int GLTestHelper::registerNative(JNIEnv * env) {
jclass clazz = env->FindClass("com/android/opengl/cts/GLTestActivity");
jthrowable exception = env->ExceptionOccurred();
// CTS class not found, assume stand-alone application
if (exception) {
env->ExceptionClear();
if (!env->IsInstanceOf(env->ExceptionOccurred(),
env->FindClass("java/lang/NoClassDefFoundError"))) {
env->Throw(exception);
}
//
JNINativeMethod standaloneMethods[] = {
// name, signature, function
{ "setSurface", "(Landroid/view/Surface;)V", (void*)(GLTestHelper::setWindow) },
{ "runTests", "(Ljava/lang/String;)V", (void*)(GLTestHelper::runTests) },
};
return env->RegisterNatives(
env->FindClass("com/android/gltest/GLTestActivity"),
standaloneMethods,
sizeof(standaloneMethods) / sizeof(JNINativeMethod));
}
// GLTestActivity methods
JNINativeMethod glTestActMethods[] = {
// name, signature, function
{ "setSurface", "(Landroid/view/Surface;)V", (void*)(GLTestHelper::setWindow) },
};
int result = env->RegisterNatives(clazz, glTestActMethods,
sizeof(glTestActMethods) / sizeof(JNINativeMethod));
if (result) {
return result;
}
// WrappedGTestActivity methods
JNINativeMethod wrappedGTestActMethods[] = {
// name, signature, function
{ "runTests", "(Landroid/test/wrappedgtest/WrappedGTestActivity;)I",
(void*)(GLTestHelper::runTestsCTS) },
};
return env->RegisterNatives(
env->FindClass("android/test/wrappedgtest/WrappedGTestActivity"),
wrappedGTestActMethods,
sizeof(wrappedGTestActMethods) / sizeof(JNINativeMethod));
}