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

Side by Side Diff: content/public/test/test_launcher.cc

Issue 23757033: GTTF: Support running browser tests in parallel (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 3 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
« no previous file with comments | « base/test/unit_test_launcher.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/public/test/test_launcher.h" 5 #include "content/public/test/test_launcher.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/containers/hash_tables.h" 11 #include "base/containers/hash_tables.h"
12 #include "base/environment.h" 12 #include "base/environment.h"
13 #include "base/file_util.h" 13 #include "base/file_util.h"
14 #include "base/files/scoped_temp_dir.h" 14 #include "base/files/scoped_temp_dir.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/linked_ptr.h" 16 #include "base/memory/linked_ptr.h"
17 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
18 #include "base/message_loop/message_loop.h" 18 #include "base/message_loop/message_loop.h"
19 #include "base/stl_util.h"
19 #include "base/strings/string_number_conversions.h" 20 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h" 22 #include "base/strings/utf_string_conversions.h"
23 #include "base/test/parallel_test_launcher.h"
22 #include "base/test/test_launcher.h" 24 #include "base/test/test_launcher.h"
23 #include "base/test/test_suite.h" 25 #include "base/test/test_suite.h"
26 #include "base/test/test_switches.h"
24 #include "base/test/test_timeouts.h" 27 #include "base/test/test_timeouts.h"
25 #include "base/time/time.h" 28 #include "base/time/time.h"
26 #include "content/public/app/content_main.h" 29 #include "content/public/app/content_main.h"
27 #include "content/public/app/content_main_delegate.h" 30 #include "content/public/app/content_main_delegate.h"
28 #include "content/public/app/startup_helper_win.h" 31 #include "content/public/app/startup_helper_win.h"
29 #include "content/public/common/content_switches.h" 32 #include "content/public/common/content_switches.h"
30 #include "content/public/common/sandbox_init.h" 33 #include "content/public/common/sandbox_init.h"
31 #include "content/public/test/browser_test.h" 34 #include "content/public/test/browser_test.h"
32 #include "net/base/escape.h" 35 #include "net/base/escape.h"
33 #include "testing/gtest/include/gtest/gtest.h" 36 #include "testing/gtest/include/gtest/gtest.h"
(...skipping 16 matching lines...) Expand all
50 // that span browser restarts. 53 // that span browser restarts.
51 const char kPreTestPrefix[] = "PRE_"; 54 const char kPreTestPrefix[] = "PRE_";
52 55
53 // Manual tests only run when --run-manual is specified. This allows writing 56 // Manual tests only run when --run-manual is specified. This allows writing
54 // tests that don't run automatically but are still in the same test binary. 57 // tests that don't run automatically but are still in the same test binary.
55 // This is useful so that a team that wants to run a few tests doesn't have to 58 // This is useful so that a team that wants to run a few tests doesn't have to
56 // add a new binary that must be compiled on all builds. 59 // add a new binary that must be compiled on all builds.
57 const char kManualTestPrefix[] = "MANUAL_"; 60 const char kManualTestPrefix[] = "MANUAL_";
58 61
59 TestLauncherDelegate* g_launcher_delegate; 62 TestLauncherDelegate* g_launcher_delegate;
60 }
61 63
62 namespace { 64 std::string RemoveAnyPrePrefixes(const std::string& test_name) {
63 65 std::string result(test_name);
64 int DoRunTestInternal(const testing::TestCase* test_case, 66 ReplaceSubstringsAfterOffset(&result, 0, kPreTestPrefix, std::string());
65 const std::string& test_name, 67 return result;
66 const CommandLine& command_line,
67 base::TimeDelta default_timeout,
68 bool* was_timeout) {
69 if (test_case) {
70 std::string pre_test_name = test_name;
71 std::string replace_string = std::string(".") + kPreTestPrefix;
72 ReplaceFirstSubstringAfterOffset(&pre_test_name, 0, ".", replace_string);
73 for (int i = 0; i < test_case->total_test_count(); ++i) {
74 const testing::TestInfo* test_info = test_case->GetTestInfo(i);
75 std::string cur_test_name = test_info->test_case_name();
76 cur_test_name.append(".");
77 cur_test_name.append(test_info->name());
78 if (cur_test_name == pre_test_name) {
79 int exit_code = DoRunTestInternal(test_case,
80 pre_test_name,
81 command_line,
82 default_timeout,
83 was_timeout);
84 if (exit_code != 0)
85 return exit_code;
86 }
87 }
88 }
89
90 CommandLine new_cmd_line(command_line.GetProgram());
91 CommandLine::SwitchMap switches = command_line.GetSwitches();
92
93 // Strip out gtest_output flag because otherwise we would overwrite results
94 // of the other tests.
95 switches.erase(base::kGTestOutputFlag);
96
97 for (CommandLine::SwitchMap::const_iterator iter = switches.begin();
98 iter != switches.end(); ++iter) {
99 new_cmd_line.AppendSwitchNative(iter->first, iter->second);
100 }
101
102 // Always enable disabled tests. This method is not called with disabled
103 // tests unless this flag was specified to the browser test executable.
104 new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests");
105 new_cmd_line.AppendSwitchASCII("gtest_filter", test_name);
106 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag);
107
108 char* browser_wrapper = getenv("BROWSER_WRAPPER");
109 int exit_code = base::LaunchChildGTestProcess(
110 new_cmd_line,
111 browser_wrapper ? browser_wrapper : std::string(),
112 default_timeout,
113 was_timeout);
114 if (*was_timeout) {
115 LOG(ERROR) << "Test timeout (" << default_timeout.InMilliseconds()
116 << " ms) exceeded for " << test_name;
117 }
118
119 return exit_code;
120 }
121
122 // Runs test specified by |test_name| in a child process,
123 // and returns the exit code.
124 int DoRunTest(TestLauncherDelegate* launcher_delegate,
125 const testing::TestCase* test_case,
126 const std::string& test_name,
127 base::TimeDelta default_timeout,
128 bool* was_timeout) {
129 if (was_timeout)
130 *was_timeout = false;
131
132 #if defined(OS_MACOSX)
133 // Some of the below method calls will leak objects if there is no
134 // autorelease pool in place.
135 base::mac::ScopedNSAutoreleasePool pool;
136 #endif
137
138 base::ScopedTempDir temp_dir;
139 // Create a new data dir and pass it to the child.
140 if (!temp_dir.CreateUniqueTempDir() || !temp_dir.IsValid()) {
141 LOG(ERROR) << "Error creating temp data directory";
142 return -1;
143 }
144
145 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess());
146 if (!launcher_delegate->AdjustChildProcessCommandLine(&new_cmd_line,
147 temp_dir.path())) {
148 return -1;
149 }
150
151 return DoRunTestInternal(
152 test_case, test_name, new_cmd_line, default_timeout, was_timeout);
153 } 68 }
154 69
155 void PrintUsage() { 70 void PrintUsage() {
156 fprintf(stdout, 71 fprintf(stdout,
157 "Runs tests using the gtest framework, each test being run in its own\n" 72 "Runs tests using the gtest framework, each test being run in its own\n"
158 "process. Any gtest flags can be specified.\n" 73 "process. Any gtest flags can be specified.\n"
159 " --single_process\n" 74 " --single_process\n"
160 " Runs the tests and the launcher in the same process. Useful for \n" 75 " Runs the tests and the launcher in the same process. Useful for \n"
161 " debugging a specific test in a debugger.\n" 76 " debugging a specific test in a debugger.\n"
162 " --single-process\n" 77 " --single-process\n"
163 " Same as above, and also runs Chrome in single-process mode.\n" 78 " Same as above, and also runs Chrome in single-process mode.\n"
164 " --help\n" 79 " --help\n"
165 " Shows this message.\n" 80 " Shows this message.\n"
166 " --gtest_help\n" 81 " --gtest_help\n"
167 " Shows the gtest help message.\n"); 82 " Shows the gtest help message.\n");
168 } 83 }
169 84
170 // Implementation of base::TestLauncherDelegate. This is also a test launcher, 85 // Implementation of base::TestLauncherDelegate. This is also a test launcher,
171 // wrapping a lower-level test launcher with content-specific code. 86 // wrapping a lower-level test launcher with content-specific code.
172 class WrapperTestLauncherDelegate : public base::TestLauncherDelegate { 87 class WrapperTestLauncherDelegate : public base::TestLauncherDelegate {
173 public: 88 public:
174 explicit WrapperTestLauncherDelegate( 89 WrapperTestLauncherDelegate(content::TestLauncherDelegate* launcher_delegate,
175 content::TestLauncherDelegate* launcher_delegate) 90 size_t jobs)
176 : launcher_delegate_(launcher_delegate), 91 : launcher_delegate_(launcher_delegate),
177 timeout_count_(0), 92 timeout_count_(0),
178 printed_timeout_message_(false) { 93 printed_timeout_message_(false),
94 parallel_launcher_(jobs) {
95 CHECK(temp_dir_.CreateUniqueTempDir());
179 } 96 }
180 97
181 // base::TestLauncherDelegate: 98 // base::TestLauncherDelegate:
99 virtual std::string GetTestNameForFiltering(
100 const testing::TestCase* test_case,
101 const testing::TestInfo* test_info) OVERRIDE;
182 virtual bool ShouldRunTest(const testing::TestCase* test_case, 102 virtual bool ShouldRunTest(const testing::TestCase* test_case,
183 const testing::TestInfo* test_info) OVERRIDE; 103 const testing::TestInfo* test_info) OVERRIDE;
184 virtual void RunTest( 104 virtual void RunTest(
185 const testing::TestCase* test_case, 105 const testing::TestCase* test_case,
186 const testing::TestInfo* test_info, 106 const testing::TestInfo* test_info,
187 const base::TestLauncherDelegate::TestResultCallback& callback) OVERRIDE; 107 const base::TestLauncherDelegate::TestResultCallback& callback) OVERRIDE;
188 virtual void RunRemainingTests() OVERRIDE; 108 virtual void RunRemainingTests() OVERRIDE;
189 109
190 private: 110 private:
111 struct TestInfo {
112 std::string test_case_name;
113 std::string test_name;
114 base::TestLauncherDelegate::TestResultCallback callback;
115 };
116
117 friend bool CompareTestInfo(const TestInfo& a, const TestInfo& b);
118
119 // Launches test from |test_info| using |command_line| and parallel launcher.
120 void DoRunTest(const TestInfo& test_info, const CommandLine& command_line);
121
122 // Callback to receive result of a test.
123 void GTestCallback(
124 const TestInfo& test_info,
125 int exit_code,
126 const base::TimeDelta& elapsed_time,
127 bool was_timeout,
128 const std::string& output);
129
191 content::TestLauncherDelegate* launcher_delegate_; 130 content::TestLauncherDelegate* launcher_delegate_;
192 131
193 // Number of times a test timeout occurred. 132 // Number of times a test timeout occurred.
194 size_t timeout_count_; 133 size_t timeout_count_;
195 134
196 // True after a message about too many timeouts has been printed, 135 // True after a message about too many timeouts has been printed,
197 // to avoid doing it more than once. 136 // to avoid doing it more than once.
198 bool printed_timeout_message_; 137 bool printed_timeout_message_;
199 138
139 base::ParallelTestLauncher parallel_launcher_;
140
141 // Store all tests to run before running any of them to properly
142 // handle PRE_ tests.
143 std::vector<TestInfo> tests_to_run_;
144
145 // Temporary directory for user data directories.
146 base::ScopedTempDir temp_dir_;
147
200 DISALLOW_COPY_AND_ASSIGN(WrapperTestLauncherDelegate); 148 DISALLOW_COPY_AND_ASSIGN(WrapperTestLauncherDelegate);
201 }; 149 };
202 150
151 std::string WrapperTestLauncherDelegate::GetTestNameForFiltering(
152 const testing::TestCase* test_case,
153 const testing::TestInfo* test_info) {
154 return RemoveAnyPrePrefixes(
155 std::string(test_case->name()) + "." + test_info->name());
156 }
157
203 bool WrapperTestLauncherDelegate::ShouldRunTest( 158 bool WrapperTestLauncherDelegate::ShouldRunTest(
204 const testing::TestCase* test_case, 159 const testing::TestCase* test_case,
205 const testing::TestInfo* test_info) { 160 const testing::TestInfo* test_info) {
206 std::string test_name =
207 std::string(test_case->name()) + "." + test_info->name();
208
209 if (StartsWithASCII(test_info->name(), kPreTestPrefix, true))
210 return false;
211
212 if (StartsWithASCII(test_info->name(), kManualTestPrefix, true) && 161 if (StartsWithASCII(test_info->name(), kManualTestPrefix, true) &&
213 !CommandLine::ForCurrentProcess()->HasSwitch(kRunManualTestsFlag)) { 162 !CommandLine::ForCurrentProcess()->HasSwitch(kRunManualTestsFlag)) {
214 return false; 163 return false;
215 } 164 }
216 165
217 // Stop test execution after too many timeouts. 166 // Stop test execution after too many timeouts.
218 if (timeout_count_ > 5) { 167 if (timeout_count_ > 5) {
219 if (!printed_timeout_message_) { 168 if (!printed_timeout_message_) {
220 printed_timeout_message_ = true; 169 printed_timeout_message_ = true;
221 printf("Too many timeouts, aborting test\n"); 170 printf("Too many timeouts, aborting test\n");
222 } 171 }
223 return false; 172 return false;
224 } 173 }
225 174
226 return true; 175 return true;
227 } 176 }
228 177
229 void WrapperTestLauncherDelegate::RunTest( 178 void WrapperTestLauncherDelegate::RunTest(
230 const testing::TestCase* test_case, 179 const testing::TestCase* test_case,
231 const testing::TestInfo* test_info, 180 const testing::TestInfo* test_info,
232 const base::TestLauncherDelegate::TestResultCallback& callback) { 181 const base::TestLauncherDelegate::TestResultCallback& callback) {
233 base::TimeTicks start_time = base::TimeTicks::Now(); 182 TestInfo run_test_info;
234 bool was_timeout = false; 183 run_test_info.test_case_name = test_case->name();
235 std::string test_name = 184 run_test_info.test_name = test_info->name();
236 std::string(test_case->name()) + "." + test_info->name(); 185 run_test_info.callback = callback;
237 int exit_code = DoRunTest(launcher_delegate_, 186 tests_to_run_.push_back(run_test_info);
238 test_case, 187 }
239 test_name,
240 TestTimeouts::action_max_timeout(),
241 &was_timeout);
242 if (was_timeout)
243 timeout_count_++;
244 188
189 bool CompareTestInfo(const WrapperTestLauncherDelegate::TestInfo& a,
190 const WrapperTestLauncherDelegate::TestInfo& b) {
191 if (a.test_case_name == b.test_case_name) {
192 // Put PRE_ tests before tests that depend on them (e.g. PRE_Foo before Foo,
193 // and PRE_PRE_Foo before PRE_Foo).
194 if (std::string(kPreTestPrefix) + a.test_name == b.test_name)
loislo 2013/09/26 05:47:33 This comparer doesn't work properly. It doesn't Tr
jam 2013/09/26 21:36:03 Pawel: ping can this cause PRE tests to run in the
Paweł Hajdan Jr. 2013/09/26 23:32:28 Given this comparator is not StrictWeakOrdering, a
195 return false;
196 if (a.test_name == std::string(kPreTestPrefix) + b.test_name)
197 return true;
198 }
199
200 // Otherwise sort by full names, disregarding PRE_ completely so that
201 // this can still be Strict Weak Ordering.
202 std::string a_full(
203 RemoveAnyPrePrefixes(a.test_case_name + "." + a.test_name));
204 std::string b_full(
205 RemoveAnyPrePrefixes(b.test_case_name + "." + b.test_name));
206
207 return a_full < b_full;
208 }
209
210 void WrapperTestLauncherDelegate::RunRemainingTests() {
211 std::sort(tests_to_run_.begin(), tests_to_run_.end(), CompareTestInfo);
212
213 // PRE_ tests and tests that depend on them must share the same
214 // data directory. Using test name as directory name leads to too long
215 // names (exceeding UNIX_PATH_MAX, which creates a problem with
216 // process_singleton_linux). Create a randomly-named temporary directory
217 // and keep track of the names so that PRE_ tests can still re-use them.
218 std::map<std::string, base::FilePath> temp_directories;
219
220 for (size_t i = 0; i < tests_to_run_.size(); i++) {
221 TestInfo test_info(tests_to_run_[i]);
222
223 // Make sure PRE_ tests and tests that depend on them share the same
224 // data directory - based it on the test name without prefixes.
225 std::string test_name_no_pre = RemoveAnyPrePrefixes(
226 test_info.test_case_name + "." + test_info.test_name);
227 if (!ContainsKey(temp_directories, test_name_no_pre)) {
228 base::FilePath temp_dir;
229 CHECK(file_util::CreateTemporaryDirInDir(
230 temp_dir_.path(), FILE_PATH_LITERAL("d"), &temp_dir));
231 temp_directories[test_name_no_pre] = temp_dir;
232 }
233
234 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess());
235 CHECK(launcher_delegate_->AdjustChildProcessCommandLine(
236 &new_cmd_line, temp_directories[test_name_no_pre]));
237
238 DoRunTest(test_info, new_cmd_line);
239 }
240 }
241
242 void WrapperTestLauncherDelegate::DoRunTest(const TestInfo& test_info,
243 const CommandLine& command_line) {
244 CommandLine new_cmd_line(command_line.GetProgram());
245 CommandLine::SwitchMap switches = command_line.GetSwitches();
246
247 // Strip out gtest_output flag because otherwise we would overwrite results
248 // of the other tests.
249 switches.erase(base::kGTestOutputFlag);
250
251 for (CommandLine::SwitchMap::const_iterator iter = switches.begin();
252 iter != switches.end(); ++iter) {
253 new_cmd_line.AppendSwitchNative(iter->first, iter->second);
254 }
255
256 // Always enable disabled tests. This method is not called with disabled
257 // tests unless this flag was specified to the browser test executable.
258 new_cmd_line.AppendSwitch("gtest_also_run_disabled_tests");
259 new_cmd_line.AppendSwitchASCII(
260 "gtest_filter",
261 test_info.test_case_name + "." + test_info.test_name);
262 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag);
263
264 char* browser_wrapper = getenv("BROWSER_WRAPPER");
265
266 // PRE_ tests and tests that depend on them should share the sequence token
267 // name, so that they are run serially.
268 std::string test_name_no_pre = RemoveAnyPrePrefixes(
269 test_info.test_case_name + "." + test_info.test_name);
270
271 parallel_launcher_.LaunchNamedSequencedChildGTestProcess(
272 test_name_no_pre,
273 new_cmd_line,
274 browser_wrapper ? browser_wrapper : std::string(),
275 TestTimeouts::action_max_timeout(),
276 base::Bind(&WrapperTestLauncherDelegate::GTestCallback,
277 base::Unretained(this),
278 test_info));
279 }
280
281 void WrapperTestLauncherDelegate::GTestCallback(
282 const TestInfo& test_info,
283 int exit_code,
284 const base::TimeDelta& elapsed_time,
285 bool was_timeout,
286 const std::string& output) {
245 base::TestResult result; 287 base::TestResult result;
246 result.test_case_name = test_case->name(); 288 result.test_case_name = test_info.test_case_name;
247 result.test_name = test_info->name(); 289 result.test_name = test_info.test_name;
248 290
249 // TODO(phajdan.jr): Recognize crashes. 291 // TODO(phajdan.jr): Recognize crashes.
250 if (exit_code == 0) 292 if (exit_code == 0)
251 result.status = base::TestResult::TEST_SUCCESS; 293 result.status = base::TestResult::TEST_SUCCESS;
252 else if (was_timeout) 294 else if (was_timeout)
253 result.status = base::TestResult::TEST_TIMEOUT; 295 result.status = base::TestResult::TEST_TIMEOUT;
254 else 296 else
255 result.status = base::TestResult::TEST_FAILURE; 297 result.status = base::TestResult::TEST_FAILURE;
256 298
257 result.elapsed_time = (base::TimeTicks::Now() - start_time); 299 result.elapsed_time = elapsed_time;
258 300
259 callback.Run(result); 301 // TODO(phajdan.jr): Use base::PrintTestOutputSnippetOnFailure after migrating
302 // away from run_test_cases.py (http://crbug.com/236893).
303 fprintf(stdout, "%s", output.c_str());
304 fflush(stdout);
305
306 test_info.callback.Run(result);
307 parallel_launcher_.ResetOutputWatchdog();
260 } 308 }
261 309
262 void WrapperTestLauncherDelegate::RunRemainingTests() { 310 bool GetSwitchValueAsInt(const std::string& switch_name, int* result) {
263 // No need to do anything else here, we launch tests synchronously. 311 if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name))
312 return true;
313
314 std::string switch_value =
315 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name);
316 if (!base::StringToInt(switch_value, result) || *result < 1) {
317 LOG(ERROR) << "Invalid value for " << switch_name << ": " << switch_value;
318 return false;
319 }
320
321 return true;
264 } 322 }
265 323
266 } // namespace 324 } // namespace
267 325
268 // The following is kept for historical reasons (so people that are used to 326 // The following is kept for historical reasons (so people that are used to
269 // using it don't get surprised). 327 // using it don't get surprised).
270 const char kChildProcessFlag[] = "child"; 328 const char kChildProcessFlag[] = "child";
271 329
272 const char kHelpFlag[] = "help"; 330 const char kHelpFlag[] = "help";
273 331
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 "For debugging a test inside a debugger, use the\n" 408 "For debugging a test inside a debugger, use the\n"
351 "--gtest_filter=<your_test_name> flag along with either\n" 409 "--gtest_filter=<your_test_name> flag along with either\n"
352 "--single_process (to run the test in one launcher/browser process) or\n" 410 "--single_process (to run the test in one launcher/browser process) or\n"
353 "--single-process (to do the above, and also run Chrome in single-" 411 "--single-process (to do the above, and also run Chrome in single-"
354 "process mode).\n"); 412 "process mode).\n");
355 413
356 base::AtExitManager at_exit; 414 base::AtExitManager at_exit;
357 testing::InitGoogleTest(&argc, argv); 415 testing::InitGoogleTest(&argc, argv);
358 TestTimeouts::Initialize(); 416 TestTimeouts::Initialize();
359 417
418 int jobs = 1; // TODO(phajdan.jr): Default to half the number of CPU cores.
419 if (!GetSwitchValueAsInt(switches::kTestLauncherJobs, &jobs))
420 return 1;
421
360 base::MessageLoopForIO message_loop; 422 base::MessageLoopForIO message_loop;
361 423
362 WrapperTestLauncherDelegate delegate(launcher_delegate); 424 WrapperTestLauncherDelegate delegate(launcher_delegate, jobs);
363 return base::LaunchTests(&delegate, argc, argv); 425 return base::LaunchTests(&delegate, argc, argv);
364 } 426 }
365 427
366 TestLauncherDelegate* GetCurrentTestLauncherDelegate() { 428 TestLauncherDelegate* GetCurrentTestLauncherDelegate() {
367 return g_launcher_delegate; 429 return g_launcher_delegate;
368 } 430 }
369 431
370 } // namespace content 432 } // namespace content
OLDNEW
« no previous file with comments | « base/test/unit_test_launcher.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698