OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "base/test/launcher/unit_test_launcher.h" | 5 #include "base/test/launcher/unit_test_launcher.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 " auto means to print it when the test failed.\n" | 78 " auto means to print it when the test failed.\n" |
79 "\n" | 79 "\n" |
80 " --test-launcher-total-shards=N\n" | 80 " --test-launcher-total-shards=N\n" |
81 " Sets the total number of shards to N.\n" | 81 " Sets the total number of shards to N.\n" |
82 "\n" | 82 "\n" |
83 " --test-launcher-shard-index=N\n" | 83 " --test-launcher-shard-index=N\n" |
84 " Sets the shard index to run to N (from 0 to TOTAL - 1).\n"); | 84 " Sets the shard index to run to N (from 0 to TOTAL - 1).\n"); |
85 fflush(stdout); | 85 fflush(stdout); |
86 } | 86 } |
87 | 87 |
88 // Returns command line for child GTest process based on the command line | 88 class DefaultUnitTestPlatformDelegate : public UnitTestPlatformDelegate { |
89 // of current process. |test_names| is a vector of test full names | 89 public: |
90 // (e.g. "A.B"), |output_file| is path to the GTest XML output file. | 90 DefaultUnitTestPlatformDelegate() { |
91 CommandLine GetCommandLineForChildGTestProcess( | 91 } |
92 const std::vector<std::string>& test_names, | |
93 const base::FilePath& output_file) { | |
94 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); | |
95 | 92 |
96 new_cmd_line.AppendSwitchPath(switches::kTestLauncherOutput, output_file); | 93 private: |
97 new_cmd_line.AppendSwitchASCII(kGTestFilterFlag, JoinString(test_names, ":")); | 94 // UnitTestPlatformDelegate: |
98 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); | 95 bool GetTests(std::vector<SplitTestName>* output) override { |
| 96 *output = GetCompiledInTests(); |
| 97 return true; |
| 98 } |
99 | 99 |
100 return new_cmd_line; | 100 bool CreateTemporaryFile(base::FilePath* path) override { |
101 } | 101 if (!CreateNewTempDirectory(FilePath::StringType(), path)) |
| 102 return false; |
| 103 *path = path->AppendASCII("test_results.xml"); |
| 104 return true; |
| 105 } |
| 106 |
| 107 CommandLine GetCommandLineForChildGTestProcess( |
| 108 const std::vector<std::string>& test_names, |
| 109 const base::FilePath& output_file) override { |
| 110 CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); |
| 111 |
| 112 new_cmd_line.AppendSwitchPath(switches::kTestLauncherOutput, output_file); |
| 113 new_cmd_line.AppendSwitchASCII(kGTestFilterFlag, |
| 114 JoinString(test_names, ":")); |
| 115 new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); |
| 116 |
| 117 return new_cmd_line; |
| 118 } |
| 119 |
| 120 std::string GetWrapperForChildGTestProcess() override { |
| 121 return std::string(); |
| 122 } |
| 123 |
| 124 DISALLOW_COPY_AND_ASSIGN(DefaultUnitTestPlatformDelegate); |
| 125 }; |
102 | 126 |
103 bool GetSwitchValueAsInt(const std::string& switch_name, int* result) { | 127 bool GetSwitchValueAsInt(const std::string& switch_name, int* result) { |
104 if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) | 128 if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) |
105 return true; | 129 return true; |
106 | 130 |
107 std::string switch_value = | 131 std::string switch_value = |
108 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name); | 132 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name); |
109 if (!StringToInt(switch_value, result) || *result < 1) { | 133 if (!StringToInt(switch_value, result) || *result < 1) { |
110 LOG(ERROR) << "Invalid value for " << switch_name << ": " << switch_value; | 134 LOG(ERROR) << "Invalid value for " << switch_name << ": " << switch_value; |
111 return false; | 135 return false; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 186 |
163 fprintf(stdout, | 187 fprintf(stdout, |
164 "IMPORTANT DEBUGGING NOTE: batches of tests are run inside their\n" | 188 "IMPORTANT DEBUGGING NOTE: batches of tests are run inside their\n" |
165 "own process. For debugging a test inside a debugger, use the\n" | 189 "own process. For debugging a test inside a debugger, use the\n" |
166 "--gtest_filter=<your_test_name> flag along with\n" | 190 "--gtest_filter=<your_test_name> flag along with\n" |
167 "--single-process-tests.\n"); | 191 "--single-process-tests.\n"); |
168 fflush(stdout); | 192 fflush(stdout); |
169 | 193 |
170 MessageLoopForIO message_loop; | 194 MessageLoopForIO message_loop; |
171 | 195 |
172 UnitTestLauncherDelegate delegate(batch_limit, use_job_objects); | 196 DefaultUnitTestPlatformDelegate platform_delegate; |
| 197 UnitTestLauncherDelegate delegate( |
| 198 &platform_delegate, batch_limit, use_job_objects); |
173 base::TestLauncher launcher(&delegate, default_jobs); | 199 base::TestLauncher launcher(&delegate, default_jobs); |
174 bool success = launcher.Run(); | 200 bool success = launcher.Run(); |
175 | 201 |
176 fprintf(stdout, "Tests took %" PRId64 " seconds.\n", | 202 fprintf(stdout, "Tests took %" PRId64 " seconds.\n", |
177 (base::TimeTicks::Now() - start_time).InSeconds()); | 203 (base::TimeTicks::Now() - start_time).InSeconds()); |
178 fflush(stdout); | 204 fflush(stdout); |
179 | 205 |
180 return (success ? 0 : 1); | 206 return (success ? 0 : 1); |
181 } | 207 } |
182 | 208 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 bool use_job_objects, | 240 bool use_job_objects, |
215 const RunTestSuiteCallback& run_test_suite) { | 241 const RunTestSuiteCallback& run_test_suite) { |
216 // Windows CommandLine::Init ignores argv anyway. | 242 // Windows CommandLine::Init ignores argv anyway. |
217 CommandLine::Init(argc, NULL); | 243 CommandLine::Init(argc, NULL); |
218 return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(), | 244 return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(), |
219 use_job_objects, | 245 use_job_objects, |
220 Bind(&InitGoogleTestWChar, &argc, argv)); | 246 Bind(&InitGoogleTestWChar, &argc, argv)); |
221 } | 247 } |
222 #endif // defined(OS_WIN) | 248 #endif // defined(OS_WIN) |
223 | 249 |
224 UnitTestLauncherDelegate::UnitTestLauncherDelegate(size_t batch_limit, | 250 UnitTestLauncherDelegate::UnitTestLauncherDelegate( |
225 bool use_job_objects) | 251 UnitTestPlatformDelegate* platform_delegate, |
226 : batch_limit_(batch_limit), use_job_objects_(use_job_objects) { | 252 size_t batch_limit, |
| 253 bool use_job_objects) |
| 254 : platform_delegate_(platform_delegate), |
| 255 batch_limit_(batch_limit), |
| 256 use_job_objects_(use_job_objects) { |
227 } | 257 } |
228 | 258 |
229 UnitTestLauncherDelegate::~UnitTestLauncherDelegate() { | 259 UnitTestLauncherDelegate::~UnitTestLauncherDelegate() { |
230 DCHECK(thread_checker_.CalledOnValidThread()); | 260 DCHECK(thread_checker_.CalledOnValidThread()); |
231 } | 261 } |
232 | 262 |
233 UnitTestLauncherDelegate::GTestCallbackState::GTestCallbackState() { | 263 UnitTestLauncherDelegate::GTestCallbackState::GTestCallbackState() { |
234 } | 264 } |
235 | 265 |
236 UnitTestLauncherDelegate::GTestCallbackState::~GTestCallbackState() { | 266 UnitTestLauncherDelegate::GTestCallbackState::~GTestCallbackState() { |
237 } | 267 } |
238 | 268 |
239 bool UnitTestLauncherDelegate::GetTests(std::vector<SplitTestName>* output) { | 269 bool UnitTestLauncherDelegate::GetTests(std::vector<SplitTestName>* output) { |
240 DCHECK(thread_checker_.CalledOnValidThread()); | 270 DCHECK(thread_checker_.CalledOnValidThread()); |
241 *output = GetCompiledInTests(); | 271 return platform_delegate_->GetTests(output); |
242 return true; | |
243 } | 272 } |
244 | 273 |
245 bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name, | 274 bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name, |
246 const std::string& test_name) { | 275 const std::string& test_name) { |
247 DCHECK(thread_checker_.CalledOnValidThread()); | 276 DCHECK(thread_checker_.CalledOnValidThread()); |
248 | 277 |
249 // There is no additional logic to disable specific tests. | 278 // There is no additional logic to disable specific tests. |
250 return true; | 279 return true; |
251 } | 280 } |
252 | 281 |
253 size_t UnitTestLauncherDelegate::RunTests( | 282 size_t UnitTestLauncherDelegate::RunTests( |
254 TestLauncher* test_launcher, | 283 TestLauncher* test_launcher, |
255 const std::vector<std::string>& test_names) { | 284 const std::vector<std::string>& test_names) { |
256 DCHECK(thread_checker_.CalledOnValidThread()); | 285 DCHECK(thread_checker_.CalledOnValidThread()); |
257 | 286 |
258 std::vector<std::string> batch; | 287 std::vector<std::string> batch; |
259 for (size_t i = 0; i < test_names.size(); i++) { | 288 for (size_t i = 0; i < test_names.size(); i++) { |
260 batch.push_back(test_names[i]); | 289 batch.push_back(test_names[i]); |
261 | 290 |
262 if (batch.size() >= batch_limit_) { | 291 // Use 0 to indicate unlimited batch size. |
| 292 if (batch.size() >= batch_limit_ && batch_limit_ != 0) { |
263 RunBatch(test_launcher, batch); | 293 RunBatch(test_launcher, batch); |
264 batch.clear(); | 294 batch.clear(); |
265 } | 295 } |
266 } | 296 } |
267 | 297 |
268 RunBatch(test_launcher, batch); | 298 RunBatch(test_launcher, batch); |
269 | 299 |
270 return test_names.size(); | 300 return test_names.size(); |
271 } | 301 } |
272 | 302 |
(...skipping 13 matching lines...) Expand all Loading... |
286 return; | 316 return; |
287 | 317 |
288 std::vector<std::string> new_test_names(test_names); | 318 std::vector<std::string> new_test_names(test_names); |
289 std::string test_name(new_test_names.back()); | 319 std::string test_name(new_test_names.back()); |
290 new_test_names.pop_back(); | 320 new_test_names.pop_back(); |
291 | 321 |
292 // Create a dedicated temporary directory to store the xml result data | 322 // Create a dedicated temporary directory to store the xml result data |
293 // per run to ensure clean state and make it possible to launch multiple | 323 // per run to ensure clean state and make it possible to launch multiple |
294 // processes in parallel. | 324 // processes in parallel. |
295 base::FilePath output_file; | 325 base::FilePath output_file; |
296 CHECK(CreateNewTempDirectory(FilePath::StringType(), &output_file)); | 326 CHECK(platform_delegate_->CreateTemporaryFile(&output_file)); |
297 output_file = output_file.AppendASCII("test_results.xml"); | |
298 | 327 |
299 std::vector<std::string> current_test_names; | 328 std::vector<std::string> current_test_names; |
300 current_test_names.push_back(test_name); | 329 current_test_names.push_back(test_name); |
301 CommandLine cmd_line( | 330 CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess( |
302 GetCommandLineForChildGTestProcess(current_test_names, output_file)); | 331 current_test_names, output_file)); |
303 | 332 |
304 GTestCallbackState callback_state; | 333 GTestCallbackState callback_state; |
305 callback_state.test_launcher = test_launcher; | 334 callback_state.test_launcher = test_launcher; |
306 callback_state.test_names = current_test_names; | 335 callback_state.test_names = current_test_names; |
307 callback_state.output_file = output_file; | 336 callback_state.output_file = output_file; |
308 | 337 |
309 test_launcher->LaunchChildGTestProcess( | 338 test_launcher->LaunchChildGTestProcess( |
310 cmd_line, std::string(), TestTimeouts::test_launcher_timeout(), | 339 cmd_line, |
| 340 platform_delegate_->GetWrapperForChildGTestProcess(), |
| 341 TestTimeouts::test_launcher_timeout(), |
311 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, | 342 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, |
312 Bind(&UnitTestLauncherDelegate::SerialGTestCallback, Unretained(this), | 343 Bind(&UnitTestLauncherDelegate::SerialGTestCallback, Unretained(this), |
313 callback_state, new_test_names)); | 344 callback_state, new_test_names)); |
314 } | 345 } |
315 | 346 |
316 void UnitTestLauncherDelegate::RunBatch( | 347 void UnitTestLauncherDelegate::RunBatch( |
317 TestLauncher* test_launcher, | 348 TestLauncher* test_launcher, |
318 const std::vector<std::string>& test_names) { | 349 const std::vector<std::string>& test_names) { |
319 DCHECK(thread_checker_.CalledOnValidThread()); | 350 DCHECK(thread_checker_.CalledOnValidThread()); |
320 | 351 |
321 if (test_names.empty()) | 352 if (test_names.empty()) |
322 return; | 353 return; |
323 | 354 |
324 // Create a dedicated temporary directory to store the xml result data | 355 // Create a dedicated temporary directory to store the xml result data |
325 // per run to ensure clean state and make it possible to launch multiple | 356 // per run to ensure clean state and make it possible to launch multiple |
326 // processes in parallel. | 357 // processes in parallel. |
327 base::FilePath output_file; | 358 base::FilePath output_file; |
328 CHECK(CreateNewTempDirectory(FilePath::StringType(), &output_file)); | 359 CHECK(platform_delegate_->CreateTemporaryFile(&output_file)); |
329 output_file = output_file.AppendASCII("test_results.xml"); | |
330 | 360 |
331 CommandLine cmd_line( | 361 CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess( |
332 GetCommandLineForChildGTestProcess(test_names, output_file)); | 362 test_names, output_file)); |
333 | 363 |
334 // Adjust the timeout depending on how many tests we're running | 364 // Adjust the timeout depending on how many tests we're running |
335 // (note that e.g. the last batch of tests will be smaller). | 365 // (note that e.g. the last batch of tests will be smaller). |
336 // TODO(phajdan.jr): Consider an adaptive timeout, which can change | 366 // TODO(phajdan.jr): Consider an adaptive timeout, which can change |
337 // depending on how many tests ran and how many remain. | 367 // depending on how many tests ran and how many remain. |
338 // Note: do NOT parse child's stdout to do that, it's known to be | 368 // Note: do NOT parse child's stdout to do that, it's known to be |
339 // unreliable (e.g. buffering issues can mix up the output). | 369 // unreliable (e.g. buffering issues can mix up the output). |
340 base::TimeDelta timeout = | 370 base::TimeDelta timeout = |
341 test_names.size() * TestTimeouts::test_launcher_timeout(); | 371 test_names.size() * TestTimeouts::test_launcher_timeout(); |
342 | 372 |
343 GTestCallbackState callback_state; | 373 GTestCallbackState callback_state; |
344 callback_state.test_launcher = test_launcher; | 374 callback_state.test_launcher = test_launcher; |
345 callback_state.test_names = test_names; | 375 callback_state.test_names = test_names; |
346 callback_state.output_file = output_file; | 376 callback_state.output_file = output_file; |
347 | 377 |
348 test_launcher->LaunchChildGTestProcess( | 378 test_launcher->LaunchChildGTestProcess( |
349 cmd_line, std::string(), timeout, | 379 cmd_line, |
| 380 platform_delegate_->GetWrapperForChildGTestProcess(), |
| 381 timeout, |
350 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, | 382 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, |
351 Bind(&UnitTestLauncherDelegate::GTestCallback, Unretained(this), | 383 Bind(&UnitTestLauncherDelegate::GTestCallback, Unretained(this), |
352 callback_state)); | 384 callback_state)); |
353 } | 385 } |
354 | 386 |
355 void UnitTestLauncherDelegate::GTestCallback( | 387 void UnitTestLauncherDelegate::GTestCallback( |
356 const GTestCallbackState& callback_state, | 388 const GTestCallbackState& callback_state, |
357 int exit_code, | 389 int exit_code, |
358 const TimeDelta& elapsed_time, | 390 const TimeDelta& elapsed_time, |
359 bool was_timeout, | 391 bool was_timeout, |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 test_result.status = TestResult::TEST_UNKNOWN; | 568 test_result.status = TestResult::TEST_UNKNOWN; |
537 test_launcher->OnTestFinished(test_result); | 569 test_launcher->OnTestFinished(test_result); |
538 called_any_callback = true; | 570 called_any_callback = true; |
539 } | 571 } |
540 } | 572 } |
541 | 573 |
542 return called_any_callback; | 574 return called_any_callback; |
543 } | 575 } |
544 | 576 |
545 } // namespace base | 577 } // namespace base |
OLD | NEW |