| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include <stdio.h> | 
|  | 6 | 
|  | 7 #include "base/android/jni_android.h" | 
|  | 8 #include "base/android/jni_string.h" | 
|  | 9 #include "base/android/path_utils.h" | 
|  | 10 #include "base/at_exit.h" | 
|  | 11 #include "base/command_line.h" | 
|  | 12 #include "base/file_path.h" | 
|  | 13 #include "base/file_util.h" | 
|  | 14 #include "base/logging.h" | 
|  | 15 #include "base/stringprintf.h" | 
|  | 16 #include "base/string_tokenizer.h" | 
|  | 17 #include "base/string_util.h" | 
|  | 18 #include "base/test/test_suite.h" | 
|  | 19 #include "jni/chrome_native_test_activity_jni.h" | 
|  | 20 #include "gtest/gtest.h" | 
|  | 21 | 
|  | 22 // GTest's main function. | 
|  | 23 extern int main(int argc, char** argv); | 
|  | 24 | 
|  | 25 namespace { | 
|  | 26 | 
|  | 27 void ParseArgsFromString(const std::string& command_line, | 
|  | 28                          std::vector<std::string>* args) { | 
|  | 29   StringTokenizer tokenizer(command_line, kWhitespaceASCII); | 
|  | 30   tokenizer.set_quote_chars("\""); | 
|  | 31   while (tokenizer.GetNext()) { | 
|  | 32     std::string token; | 
|  | 33     RemoveChars(tokenizer.token(), "\"", &token); | 
|  | 34     args->push_back(token); | 
|  | 35   } | 
|  | 36 } | 
|  | 37 | 
|  | 38 void ParseArgsFromCommandLineFile(const FilePath& internal_data_path, | 
|  | 39                                   std::vector<std::string>* args) { | 
|  | 40   static const char kCommandLineFile[] = "chrome-native-tests-command-line"; | 
|  | 41   FilePath command_line(internal_data_path.Append(FilePath(kCommandLineFile))); | 
|  | 42   std::string command_line_string; | 
|  | 43   if (file_util::ReadFileToString(command_line, &command_line_string)) { | 
|  | 44     ParseArgsFromString(command_line_string, args); | 
|  | 45   } | 
|  | 46 } | 
|  | 47 | 
|  | 48 void ArgsToArgv(const std::vector<std::string>& args, | 
|  | 49                 std::vector<char*>* argv) { | 
|  | 50   // We need to pass in a non-const char**. | 
|  | 51   int argc = args.size(); | 
|  | 52   argv->resize(argc); | 
|  | 53   for (int i = 0; i < argc; ++i) | 
|  | 54     (*argv)[i] = const_cast<char*>(args[i].c_str()); | 
|  | 55 } | 
|  | 56 | 
|  | 57 // As we are the native side of an Android app, we don't have any 'console', so | 
|  | 58 // gtest's standard output goes nowhere. | 
|  | 59 // Instead, we inject an "EventListener" in gtest and then we print the results | 
|  | 60 // using LOG, which goes to adb logcat. | 
|  | 61 class AndroidLogPrinter : public ::testing::EmptyTestEventListener { | 
|  | 62  public: | 
|  | 63   void Init(int* argc, char** argv); | 
|  | 64 | 
|  | 65   // EmptyTestEventListener | 
|  | 66   virtual void OnTestProgramStart( | 
|  | 67       const ::testing::UnitTest& unit_test) OVERRIDE; | 
|  | 68   virtual void OnTestStart(const ::testing::TestInfo& test_info) OVERRIDE; | 
|  | 69   virtual void OnTestPartResult( | 
|  | 70       const ::testing::TestPartResult& test_part_result) OVERRIDE; | 
|  | 71   virtual void OnTestEnd(const ::testing::TestInfo& test_info) OVERRIDE; | 
|  | 72   virtual void OnTestProgramEnd(const ::testing::UnitTest& unit_test) OVERRIDE; | 
|  | 73 }; | 
|  | 74 | 
|  | 75 void AndroidLogPrinter::Init(int* argc, char** argv) { | 
|  | 76   // InitGoogleTest must be called befure we add ourselves as a listener. | 
|  | 77   ::testing::InitGoogleTest(argc, argv); | 
|  | 78   ::testing::TestEventListeners& listeners = | 
|  | 79       ::testing::UnitTest::GetInstance()->listeners(); | 
|  | 80   // Adds a listener to the end.  Google Test takes the ownership. | 
|  | 81   listeners.Append(this); | 
|  | 82 } | 
|  | 83 | 
|  | 84 void AndroidLogPrinter::OnTestProgramStart( | 
|  | 85     const ::testing::UnitTest& unit_test) { | 
|  | 86   std::string msg = StringPrintf("[ START      ] %d", | 
|  | 87                                  unit_test.test_to_run_count()); | 
|  | 88   LOG(ERROR) << msg; | 
|  | 89 } | 
|  | 90 | 
|  | 91 void AndroidLogPrinter::OnTestStart(const ::testing::TestInfo& test_info) { | 
|  | 92   std::string msg = StringPrintf("[ RUN      ] %s.%s", | 
|  | 93                                  test_info.test_case_name(), test_info.name()); | 
|  | 94   LOG(ERROR) << msg; | 
|  | 95 } | 
|  | 96 | 
|  | 97 void AndroidLogPrinter::OnTestPartResult( | 
|  | 98     const ::testing::TestPartResult& test_part_result) { | 
|  | 99   std::string msg = StringPrintf( | 
|  | 100       "%s in %s:%d\n%s\n", | 
|  | 101       test_part_result.failed() ? "*** Failure" : "Success", | 
|  | 102       test_part_result.file_name(), | 
|  | 103       test_part_result.line_number(), | 
|  | 104       test_part_result.summary()); | 
|  | 105   LOG(ERROR) << msg; | 
|  | 106 } | 
|  | 107 | 
|  | 108 void AndroidLogPrinter::OnTestEnd(const ::testing::TestInfo& test_info) { | 
|  | 109   std::string msg = StringPrintf("%s %s.%s", | 
|  | 110       test_info.result()->Failed() ? "[  FAILED  ]" : "[       OK ]", | 
|  | 111       test_info.test_case_name(), test_info.name()); | 
|  | 112   LOG(ERROR) << msg; | 
|  | 113 } | 
|  | 114 | 
|  | 115 void AndroidLogPrinter::OnTestProgramEnd( | 
|  | 116     const ::testing::UnitTest& unit_test) { | 
|  | 117   std::string msg = StringPrintf("[ END      ] %d", | 
|  | 118          unit_test.successful_test_count()); | 
|  | 119   LOG(ERROR) << msg; | 
|  | 120 } | 
|  | 121 | 
|  | 122 void LibraryLoadedOnMainThread(JNIEnv* env) { | 
|  | 123   static const char* const kInitialArgv[] = { "ChromeTestActivity" }; | 
|  | 124 | 
|  | 125   { | 
|  | 126     // We need a test suite to be created before we do any tracing or | 
|  | 127     // logging: it creates a global at_exit_manager and initializes | 
|  | 128     // internal gtest data structures based on the command line. | 
|  | 129     // It needs to be scoped as it also resets the CommandLine. | 
|  | 130     std::vector<std::string> args; | 
|  | 131     FilePath path("/data/user/0/org.chromium.native_tests/files/"); | 
|  | 132     ParseArgsFromCommandLineFile(path, &args); | 
|  | 133     std::vector<char*> argv; | 
|  | 134     ArgsToArgv(args, &argv); | 
|  | 135     base::TestSuite test_suite(argv.size(), &argv[0]); | 
|  | 136   } | 
|  | 137 | 
|  | 138   CommandLine::Init(arraysize(kInitialArgv), kInitialArgv); | 
|  | 139 | 
|  | 140   logging::InitLogging(NULL, | 
|  | 141                        logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, | 
|  | 142                        logging::DONT_LOCK_LOG_FILE, | 
|  | 143                        logging::DELETE_OLD_LOG_FILE, | 
|  | 144                        logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS); | 
|  | 145   // To view log output with IDs and timestamps use "adb logcat -v threadtime". | 
|  | 146   logging::SetLogItems(false,    // Process ID | 
|  | 147                        false,    // Thread ID | 
|  | 148                        false,    // Timestamp | 
|  | 149                        false);   // Tick count | 
|  | 150   VLOG(0) << "Chromium logging enabled: level = " << logging::GetMinLogLevel() | 
|  | 151           << ", default verbosity = " << logging::GetVlogVerbosity(); | 
|  | 152   base::android::RegisterPathUtils(env); | 
|  | 153 } | 
|  | 154 | 
|  | 155 }  // namespace | 
|  | 156 | 
|  | 157 // This method is called on a separate java thread so that we won't trigger | 
|  | 158 // an ANR. | 
|  | 159 static void RunTests(JNIEnv* env, jobject obj, jstring jfiles_dir) { | 
|  | 160   FilePath files_dir(base::android::ConvertJavaStringToUTF8(env, jfiles_dir)); | 
|  | 161   // A few options, such "--gtest_list_tests", will just use printf directly | 
|  | 162   // and won't use the "AndroidLogPrinter". Redirect stdout to a known file. | 
|  | 163   FilePath stdout_path(files_dir.Append(FilePath("stdout.txt"))); | 
|  | 164   freopen(stdout_path.value().c_str(), "w", stdout); | 
|  | 165 | 
|  | 166   std::vector<std::string> args; | 
|  | 167   ParseArgsFromCommandLineFile(files_dir, &args); | 
|  | 168 | 
|  | 169   // We need to pass in a non-const char**. | 
|  | 170   std::vector<char*> argv; | 
|  | 171   ArgsToArgv(args, &argv); | 
|  | 172 | 
|  | 173   int argc = argv.size(); | 
|  | 174   // This object is owned by gtest. | 
|  | 175   AndroidLogPrinter* log = new AndroidLogPrinter(); | 
|  | 176   log->Init(&argc, &argv[0]); | 
|  | 177 | 
|  | 178   main(argc, &argv[0]); | 
|  | 179 } | 
|  | 180 | 
|  | 181 // This is called by the VM when the shared library is first loaded. | 
|  | 182 JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { | 
|  | 183   base::android::InitVM(vm); | 
|  | 184   JNIEnv* env = base::android::AttachCurrentThread(); | 
|  | 185   if (!RegisterNativesImpl(env)) { | 
|  | 186     return -1; | 
|  | 187   } | 
|  | 188   LibraryLoadedOnMainThread(env); | 
|  | 189   return JNI_VERSION_1_4; | 
|  | 190 } | 
| OLD | NEW | 
|---|