Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: base/test/android/native_test_launcher.cc

Issue 9834037: apk-based test runner work. Not enabled yet. This CL is a combination of upstreaming, ndk/ant-ifi… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: one more line tweak Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698