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

Side by Side Diff: base/test/launcher/unit_test_launcher.cc

Issue 879883002: Refactoring in unit_test_launcher.cc: (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 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
« no previous file with comments | « base/test/launcher/unit_test_launcher.h ('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 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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 void InitGoogleTestChar(int* argc, char** argv) { 209 void InitGoogleTestChar(int* argc, char** argv) {
210 testing::InitGoogleTest(argc, argv); 210 testing::InitGoogleTest(argc, argv);
211 } 211 }
212 212
213 #if defined(OS_WIN) 213 #if defined(OS_WIN)
214 void InitGoogleTestWChar(int* argc, wchar_t** argv) { 214 void InitGoogleTestWChar(int* argc, wchar_t** argv) {
215 testing::InitGoogleTest(argc, argv); 215 testing::InitGoogleTest(argc, argv);
216 } 216 }
217 #endif // defined(OS_WIN) 217 #endif // defined(OS_WIN)
218 218
219 } // namespace 219 // Interprets test results and reports to the test launcher. Returns true
220 220 // on success.
221 int LaunchUnitTests(int argc, 221 bool ProcessTestResults(
222 char** argv,
223 const RunTestSuiteCallback& run_test_suite) {
224 CommandLine::Init(argc, argv);
225 return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(),
226 true, Bind(&InitGoogleTestChar, &argc, argv));
227 }
228
229 int LaunchUnitTestsSerially(int argc,
230 char** argv,
231 const RunTestSuiteCallback& run_test_suite) {
232 CommandLine::Init(argc, argv);
233 return LaunchUnitTestsInternal(run_test_suite, 1, true,
234 Bind(&InitGoogleTestChar, &argc, argv));
235 }
236
237 #if defined(OS_WIN)
238 int LaunchUnitTests(int argc,
239 wchar_t** argv,
240 bool use_job_objects,
241 const RunTestSuiteCallback& run_test_suite) {
242 // Windows CommandLine::Init ignores argv anyway.
243 CommandLine::Init(argc, NULL);
244 return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(),
245 use_job_objects,
246 Bind(&InitGoogleTestWChar, &argc, argv));
247 }
248 #endif // defined(OS_WIN)
249
250 UnitTestLauncherDelegate::UnitTestLauncherDelegate(
251 UnitTestPlatformDelegate* platform_delegate,
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) {
257 }
258
259 UnitTestLauncherDelegate::~UnitTestLauncherDelegate() {
260 DCHECK(thread_checker_.CalledOnValidThread());
261 }
262
263 UnitTestLauncherDelegate::GTestCallbackState::GTestCallbackState() {
264 }
265
266 UnitTestLauncherDelegate::GTestCallbackState::~GTestCallbackState() {
267 }
268
269 bool UnitTestLauncherDelegate::GetTests(std::vector<SplitTestName>* output) {
270 DCHECK(thread_checker_.CalledOnValidThread());
271 return platform_delegate_->GetTests(output);
272 }
273
274 bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name,
275 const std::string& test_name) {
276 DCHECK(thread_checker_.CalledOnValidThread());
277
278 // There is no additional logic to disable specific tests.
279 return true;
280 }
281
282 size_t UnitTestLauncherDelegate::RunTests(
283 TestLauncher* test_launcher,
284 const std::vector<std::string>& test_names) {
285 DCHECK(thread_checker_.CalledOnValidThread());
286
287 std::vector<std::string> batch;
288 for (size_t i = 0; i < test_names.size(); i++) {
289 batch.push_back(test_names[i]);
290
291 // Use 0 to indicate unlimited batch size.
292 if (batch.size() >= batch_limit_ && batch_limit_ != 0) {
293 RunBatch(test_launcher, batch);
294 batch.clear();
295 }
296 }
297
298 RunBatch(test_launcher, batch);
299
300 return test_names.size();
301 }
302
303 size_t UnitTestLauncherDelegate::RetryTests(
304 TestLauncher* test_launcher,
305 const std::vector<std::string>& test_names) {
306 MessageLoop::current()->PostTask(
307 FROM_HERE, Bind(&UnitTestLauncherDelegate::RunSerially, Unretained(this),
308 test_launcher, test_names));
309 return test_names.size();
310 }
311
312 void UnitTestLauncherDelegate::RunSerially(
313 TestLauncher* test_launcher,
314 const std::vector<std::string>& test_names) {
315 if (test_names.empty())
316 return;
317
318 std::vector<std::string> new_test_names(test_names);
319 std::string test_name(new_test_names.back());
320 new_test_names.pop_back();
321
322 // Create a dedicated temporary directory to store the xml result data
323 // per run to ensure clean state and make it possible to launch multiple
324 // processes in parallel.
325 base::FilePath output_file;
326 CHECK(platform_delegate_->CreateTemporaryFile(&output_file));
327
328 std::vector<std::string> current_test_names;
329 current_test_names.push_back(test_name);
330 CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess(
331 current_test_names, output_file));
332
333 GTestCallbackState callback_state;
334 callback_state.test_launcher = test_launcher;
335 callback_state.test_names = current_test_names;
336 callback_state.output_file = output_file;
337
338 test_launcher->LaunchChildGTestProcess(
339 cmd_line,
340 platform_delegate_->GetWrapperForChildGTestProcess(),
341 TestTimeouts::test_launcher_timeout(),
342 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0,
343 Bind(&UnitTestLauncherDelegate::SerialGTestCallback, Unretained(this),
344 callback_state, new_test_names));
345 }
346
347 void UnitTestLauncherDelegate::RunBatch(
348 TestLauncher* test_launcher,
349 const std::vector<std::string>& test_names) {
350 DCHECK(thread_checker_.CalledOnValidThread());
351
352 if (test_names.empty())
353 return;
354
355 // Create a dedicated temporary directory to store the xml result data
356 // per run to ensure clean state and make it possible to launch multiple
357 // processes in parallel.
358 base::FilePath output_file;
359 CHECK(platform_delegate_->CreateTemporaryFile(&output_file));
360
361 CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess(
362 test_names, output_file));
363
364 // Adjust the timeout depending on how many tests we're running
365 // (note that e.g. the last batch of tests will be smaller).
366 // TODO(phajdan.jr): Consider an adaptive timeout, which can change
367 // depending on how many tests ran and how many remain.
368 // Note: do NOT parse child's stdout to do that, it's known to be
369 // unreliable (e.g. buffering issues can mix up the output).
370 base::TimeDelta timeout =
371 test_names.size() * TestTimeouts::test_launcher_timeout();
372
373 GTestCallbackState callback_state;
374 callback_state.test_launcher = test_launcher;
375 callback_state.test_names = test_names;
376 callback_state.output_file = output_file;
377
378 test_launcher->LaunchChildGTestProcess(
379 cmd_line,
380 platform_delegate_->GetWrapperForChildGTestProcess(),
381 timeout,
382 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0,
383 Bind(&UnitTestLauncherDelegate::GTestCallback, Unretained(this),
384 callback_state));
385 }
386
387 void UnitTestLauncherDelegate::GTestCallback(
388 const GTestCallbackState& callback_state,
389 int exit_code,
390 const TimeDelta& elapsed_time,
391 bool was_timeout,
392 const std::string& output) {
393 DCHECK(thread_checker_.CalledOnValidThread());
394 std::vector<std::string> tests_to_relaunch;
395 ProcessTestResults(callback_state.test_launcher, callback_state.test_names,
396 callback_state.output_file, output, exit_code, was_timeout,
397 &tests_to_relaunch);
398
399 // Relaunch requested tests in parallel, but only use single
400 // test per batch for more precise results (crashes, test passes
401 // but non-zero exit codes etc).
402 for (size_t i = 0; i < tests_to_relaunch.size(); i++) {
403 std::vector<std::string> batch;
404 batch.push_back(tests_to_relaunch[i]);
405 RunBatch(callback_state.test_launcher, batch);
406 }
407
408 // The temporary file's directory is also temporary.
409 DeleteFile(callback_state.output_file.DirName(), true);
410 }
411
412 void UnitTestLauncherDelegate::SerialGTestCallback(
413 const GTestCallbackState& callback_state,
414 const std::vector<std::string>& test_names,
415 int exit_code,
416 const TimeDelta& elapsed_time,
417 bool was_timeout,
418 const std::string& output) {
419 DCHECK(thread_checker_.CalledOnValidThread());
420 std::vector<std::string> tests_to_relaunch;
421 bool called_any_callbacks =
422 ProcessTestResults(callback_state.test_launcher,
423 callback_state.test_names, callback_state.output_file,
424 output, exit_code, was_timeout, &tests_to_relaunch);
425
426 // There is only one test, there cannot be other tests to relaunch
427 // due to a crash.
428 DCHECK(tests_to_relaunch.empty());
429
430 // There is only one test, we should have called back with its result.
431 DCHECK(called_any_callbacks);
432
433 // The temporary file's directory is also temporary.
434 DeleteFile(callback_state.output_file.DirName(), true);
435
436 MessageLoop::current()->PostTask(
437 FROM_HERE, Bind(&UnitTestLauncherDelegate::RunSerially, Unretained(this),
438 callback_state.test_launcher, test_names));
439 }
440
441 // static
442 bool UnitTestLauncherDelegate::ProcessTestResults(
443 TestLauncher* test_launcher, 222 TestLauncher* test_launcher,
444 const std::vector<std::string>& test_names, 223 const std::vector<std::string>& test_names,
445 const base::FilePath& output_file, 224 const base::FilePath& output_file,
446 const std::string& output, 225 const std::string& output,
447 int exit_code, 226 int exit_code,
448 bool was_timeout, 227 bool was_timeout,
449 std::vector<std::string>* tests_to_relaunch) { 228 std::vector<std::string>* tests_to_relaunch) {
450 std::vector<TestResult> test_results; 229 std::vector<TestResult> test_results;
451 bool crashed = false; 230 bool crashed = false;
452 bool have_test_results = 231 bool have_test_results =
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 test_result.full_name = test_names[i]; 346 test_result.full_name = test_names[i];
568 test_result.status = TestResult::TEST_UNKNOWN; 347 test_result.status = TestResult::TEST_UNKNOWN;
569 test_launcher->OnTestFinished(test_result); 348 test_launcher->OnTestFinished(test_result);
570 called_any_callback = true; 349 called_any_callback = true;
571 } 350 }
572 } 351 }
573 352
574 return called_any_callback; 353 return called_any_callback;
575 } 354 }
576 355
356 // TODO(phajdan.jr): Pass parameters directly with C++11 variadic templates.
357 struct GTestCallbackState {
358 TestLauncher* test_launcher;
359 UnitTestPlatformDelegate* platform_delegate;
360 std::vector<std::string> test_names;
361 int launch_flags;
362 FilePath output_file;
363 };
364
365 void GTestCallback(
366 const GTestCallbackState& callback_state,
367 int exit_code,
368 const TimeDelta& elapsed_time,
369 bool was_timeout,
370 const std::string& output) {
371 std::vector<std::string> tests_to_relaunch;
372 ProcessTestResults(callback_state.test_launcher, callback_state.test_names,
373 callback_state.output_file, output, exit_code, was_timeout,
374 &tests_to_relaunch);
375
376 // Relaunch requested tests in parallel, but only use single
377 // test per batch for more precise results (crashes, test passes
378 // but non-zero exit codes etc).
379 for (size_t i = 0; i < tests_to_relaunch.size(); i++) {
380 std::vector<std::string> batch;
381 batch.push_back(tests_to_relaunch[i]);
382 RunUnitTestsBatch(callback_state.test_launcher,
383 callback_state.platform_delegate,
384 batch,
385 callback_state.launch_flags);
386 }
387
388 // The temporary file's directory is also temporary.
389 DeleteFile(callback_state.output_file.DirName(), true);
390 }
391
392 void SerialGTestCallback(
393 const GTestCallbackState& callback_state,
394 const std::vector<std::string>& test_names,
395 int exit_code,
396 const TimeDelta& elapsed_time,
397 bool was_timeout,
398 const std::string& output) {
399 std::vector<std::string> tests_to_relaunch;
400 bool called_any_callbacks =
401 ProcessTestResults(callback_state.test_launcher,
402 callback_state.test_names, callback_state.output_file,
403 output, exit_code, was_timeout, &tests_to_relaunch);
404
405 // There is only one test, there cannot be other tests to relaunch
406 // due to a crash.
407 DCHECK(tests_to_relaunch.empty());
408
409 // There is only one test, we should have called back with its result.
410 DCHECK(called_any_callbacks);
411
412 // The temporary file's directory is also temporary.
413 DeleteFile(callback_state.output_file.DirName(), true);
414
415 MessageLoop::current()->PostTask(
416 FROM_HERE,
417 Bind(&RunUnitTestsSerially,
418 callback_state.test_launcher,
419 callback_state.platform_delegate,
420 test_names,
421 callback_state.launch_flags));
422 }
423
424 } // namespace
425
426 int LaunchUnitTests(int argc,
427 char** argv,
428 const RunTestSuiteCallback& run_test_suite) {
429 CommandLine::Init(argc, argv);
430 return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(),
431 true, Bind(&InitGoogleTestChar, &argc, argv));
432 }
433
434 int LaunchUnitTestsSerially(int argc,
435 char** argv,
436 const RunTestSuiteCallback& run_test_suite) {
437 CommandLine::Init(argc, argv);
438 return LaunchUnitTestsInternal(run_test_suite, 1, true,
439 Bind(&InitGoogleTestChar, &argc, argv));
440 }
441
442 #if defined(OS_WIN)
443 int LaunchUnitTests(int argc,
444 wchar_t** argv,
445 bool use_job_objects,
446 const RunTestSuiteCallback& run_test_suite) {
447 // Windows CommandLine::Init ignores argv anyway.
448 CommandLine::Init(argc, NULL);
449 return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(),
450 use_job_objects,
451 Bind(&InitGoogleTestWChar, &argc, argv));
452 }
453 #endif // defined(OS_WIN)
454
455 void RunUnitTestsSerially(
456 TestLauncher* test_launcher,
457 UnitTestPlatformDelegate* platform_delegate,
458 const std::vector<std::string>& test_names,
459 int launch_flags) {
460 if (test_names.empty())
461 return;
462
463 std::vector<std::string> new_test_names(test_names);
464 std::string test_name(new_test_names.back());
465 new_test_names.pop_back();
466
467 // Create a dedicated temporary directory to store the xml result data
468 // per run to ensure clean state and make it possible to launch multiple
469 // processes in parallel.
470 base::FilePath output_file;
471 CHECK(platform_delegate->CreateTemporaryFile(&output_file));
472
473 std::vector<std::string> current_test_names;
474 current_test_names.push_back(test_name);
475 CommandLine cmd_line(platform_delegate->GetCommandLineForChildGTestProcess(
476 current_test_names, output_file));
477
478 GTestCallbackState callback_state;
479 callback_state.test_launcher = test_launcher;
480 callback_state.platform_delegate = platform_delegate;
481 callback_state.test_names = current_test_names;
482 callback_state.launch_flags = launch_flags;
483 callback_state.output_file = output_file;
484
485 test_launcher->LaunchChildGTestProcess(
486 cmd_line,
487 platform_delegate->GetWrapperForChildGTestProcess(),
488 TestTimeouts::test_launcher_timeout(),
489 launch_flags,
490 Bind(&SerialGTestCallback, callback_state, new_test_names));
491 }
492
493 void RunUnitTestsBatch(
494 TestLauncher* test_launcher,
495 UnitTestPlatformDelegate* platform_delegate,
496 const std::vector<std::string>& test_names,
497 int launch_flags) {
498 if (test_names.empty())
499 return;
500
501 // Create a dedicated temporary directory to store the xml result data
502 // per run to ensure clean state and make it possible to launch multiple
503 // processes in parallel.
504 base::FilePath output_file;
505 CHECK(platform_delegate->CreateTemporaryFile(&output_file));
506
507 CommandLine cmd_line(platform_delegate->GetCommandLineForChildGTestProcess(
508 test_names, output_file));
509
510 // Adjust the timeout depending on how many tests we're running
511 // (note that e.g. the last batch of tests will be smaller).
512 // TODO(phajdan.jr): Consider an adaptive timeout, which can change
513 // depending on how many tests ran and how many remain.
514 // Note: do NOT parse child's stdout to do that, it's known to be
515 // unreliable (e.g. buffering issues can mix up the output).
516 base::TimeDelta timeout =
517 test_names.size() * TestTimeouts::test_launcher_timeout();
518
519 GTestCallbackState callback_state;
520 callback_state.test_launcher = test_launcher;
521 callback_state.platform_delegate = platform_delegate;
522 callback_state.test_names = test_names;
523 callback_state.launch_flags = launch_flags;
524 callback_state.output_file = output_file;
525
526 test_launcher->LaunchChildGTestProcess(
527 cmd_line,
528 platform_delegate->GetWrapperForChildGTestProcess(),
529 timeout,
530 launch_flags,
531 Bind(&GTestCallback, callback_state));
532 }
533
534 UnitTestLauncherDelegate::UnitTestLauncherDelegate(
535 UnitTestPlatformDelegate* platform_delegate,
536 size_t batch_limit,
537 bool use_job_objects)
538 : platform_delegate_(platform_delegate),
539 batch_limit_(batch_limit),
540 use_job_objects_(use_job_objects) {
541 }
542
543 UnitTestLauncherDelegate::~UnitTestLauncherDelegate() {
544 DCHECK(thread_checker_.CalledOnValidThread());
545 }
546
547 bool UnitTestLauncherDelegate::GetTests(std::vector<SplitTestName>* output) {
548 DCHECK(thread_checker_.CalledOnValidThread());
549 return platform_delegate_->GetTests(output);
550 }
551
552 bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name,
553 const std::string& test_name) {
554 DCHECK(thread_checker_.CalledOnValidThread());
555
556 // There is no additional logic to disable specific tests.
557 return true;
558 }
559
560 size_t UnitTestLauncherDelegate::RunTests(
561 TestLauncher* test_launcher,
562 const std::vector<std::string>& test_names) {
563 DCHECK(thread_checker_.CalledOnValidThread());
564
565 int launch_flags = use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0;
566
567 std::vector<std::string> batch;
568 for (size_t i = 0; i < test_names.size(); i++) {
569 batch.push_back(test_names[i]);
570
571 // Use 0 to indicate unlimited batch size.
572 if (batch.size() >= batch_limit_ && batch_limit_ != 0) {
573 RunUnitTestsBatch(test_launcher, platform_delegate_, batch, launch_flags);
574 batch.clear();
575 }
576 }
577
578 RunUnitTestsBatch(test_launcher, platform_delegate_, batch, launch_flags);
579
580 return test_names.size();
581 }
582
583 size_t UnitTestLauncherDelegate::RetryTests(
584 TestLauncher* test_launcher,
585 const std::vector<std::string>& test_names) {
586 MessageLoop::current()->PostTask(
587 FROM_HERE,
588 Bind(&RunUnitTestsSerially,
589 test_launcher,
590 platform_delegate_,
591 test_names,
592 use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0));
593 return test_names.size();
594 }
595
577 } // namespace base 596 } // namespace base
OLDNEW
« no previous file with comments | « base/test/launcher/unit_test_launcher.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698