| 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/test_launcher.h" | 5 #include "base/test/launcher/test_launcher.h" |
| 6 | 6 |
| 7 #if defined(OS_POSIX) | 7 #if defined(OS_POSIX) |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| 11 #include "base/at_exit.h" | 11 #include "base/at_exit.h" |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/environment.h" | 14 #include "base/environment.h" |
| 15 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
| 16 #include "base/files/file_util.h" | 16 #include "base/files/file_util.h" |
| 17 #include "base/files/scoped_file.h" | 17 #include "base/files/scoped_file.h" |
| 18 #include "base/format_macros.h" | 18 #include "base/format_macros.h" |
| 19 #include "base/hash.h" | 19 #include "base/hash.h" |
| 20 #include "base/lazy_instance.h" | 20 #include "base/lazy_instance.h" |
| 21 #include "base/location.h" | |
| 22 #include "base/logging.h" | 21 #include "base/logging.h" |
| 23 #include "base/memory/scoped_ptr.h" | 22 #include "base/memory/scoped_ptr.h" |
| 24 #include "base/message_loop/message_loop.h" | 23 #include "base/message_loop/message_loop.h" |
| 25 #include "base/process/kill.h" | 24 #include "base/process/kill.h" |
| 26 #include "base/process/launch.h" | 25 #include "base/process/launch.h" |
| 27 #include "base/single_thread_task_runner.h" | |
| 28 #include "base/strings/string_number_conversions.h" | 26 #include "base/strings/string_number_conversions.h" |
| 29 #include "base/strings/string_split.h" | 27 #include "base/strings/string_split.h" |
| 30 #include "base/strings/string_util.h" | 28 #include "base/strings/string_util.h" |
| 31 #include "base/strings/stringize_macros.h" | 29 #include "base/strings/stringize_macros.h" |
| 32 #include "base/strings/stringprintf.h" | 30 #include "base/strings/stringprintf.h" |
| 33 #include "base/strings/utf_string_conversions.h" | 31 #include "base/strings/utf_string_conversions.h" |
| 34 #include "base/test/gtest_util.h" | 32 #include "base/test/gtest_util.h" |
| 35 #include "base/test/launcher/test_results_tracker.h" | 33 #include "base/test/launcher/test_results_tracker.h" |
| 36 #include "base/test/sequenced_worker_pool_owner.h" | 34 #include "base/test/sequenced_worker_pool_owner.h" |
| 37 #include "base/test/test_switches.h" | 35 #include "base/test/test_switches.h" |
| 38 #include "base/test/test_timeouts.h" | 36 #include "base/test/test_timeouts.h" |
| 39 #include "base/thread_task_runner_handle.h" | |
| 40 #include "base/threading/thread_checker.h" | 37 #include "base/threading/thread_checker.h" |
| 41 #include "base/time/time.h" | 38 #include "base/time/time.h" |
| 42 #include "testing/gtest/include/gtest/gtest.h" | 39 #include "testing/gtest/include/gtest/gtest.h" |
| 43 | 40 |
| 44 #if defined(OS_MACOSX) | 41 #if defined(OS_MACOSX) |
| 45 #include "base/mac/scoped_nsautorelease_pool.h" | 42 #include "base/mac/scoped_nsautorelease_pool.h" |
| 46 #endif | 43 #endif |
| 47 | 44 |
| 48 #if defined(OS_WIN) | 45 #if defined(OS_WIN) |
| 49 #include "base/win/windows_version.h" | 46 #include "base/win/windows_version.h" |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 bool was_timeout, | 342 bool was_timeout, |
| 346 const std::string& output) { | 343 const std::string& output) { |
| 347 callback.Run(exit_code, elapsed_time, was_timeout, output); | 344 callback.Run(exit_code, elapsed_time, was_timeout, output); |
| 348 } | 345 } |
| 349 | 346 |
| 350 void DoLaunchChildTestProcess( | 347 void DoLaunchChildTestProcess( |
| 351 const CommandLine& command_line, | 348 const CommandLine& command_line, |
| 352 TimeDelta timeout, | 349 TimeDelta timeout, |
| 353 int flags, | 350 int flags, |
| 354 bool redirect_stdio, | 351 bool redirect_stdio, |
| 355 SingleThreadTaskRunner* task_runner, | 352 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
| 356 const TestLauncher::LaunchChildGTestProcessCallback& callback) { | 353 const TestLauncher::LaunchChildGTestProcessCallback& callback) { |
| 357 TimeTicks start_time = TimeTicks::Now(); | 354 TimeTicks start_time = TimeTicks::Now(); |
| 358 | 355 |
| 359 // Redirect child process output to a file. | 356 // Redirect child process output to a file. |
| 360 FilePath output_file; | 357 FilePath output_file; |
| 361 CHECK(CreateTemporaryFile(&output_file)); | 358 CHECK(CreateTemporaryFile(&output_file)); |
| 362 | 359 |
| 363 LaunchOptions options; | 360 LaunchOptions options; |
| 364 #if defined(OS_WIN) | 361 #if defined(OS_WIN) |
| 365 win::ScopedHandle handle; | 362 win::ScopedHandle handle; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 std::string output_file_contents; | 416 std::string output_file_contents; |
| 420 CHECK(ReadFileToString(output_file, &output_file_contents)); | 417 CHECK(ReadFileToString(output_file, &output_file_contents)); |
| 421 | 418 |
| 422 if (!DeleteFile(output_file, false)) { | 419 if (!DeleteFile(output_file, false)) { |
| 423 // This needs to be non-fatal at least for Windows. | 420 // This needs to be non-fatal at least for Windows. |
| 424 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe(); | 421 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe(); |
| 425 } | 422 } |
| 426 | 423 |
| 427 // Run target callback on the thread it was originating from, not on | 424 // Run target callback on the thread it was originating from, not on |
| 428 // a worker pool thread. | 425 // a worker pool thread. |
| 429 task_runner->PostTask(FROM_HERE, Bind(&RunCallback, callback, exit_code, | 426 message_loop_proxy->PostTask( |
| 430 TimeTicks::Now() - start_time, | 427 FROM_HERE, |
| 431 was_timeout, output_file_contents)); | 428 Bind(&RunCallback, |
| 429 callback, |
| 430 exit_code, |
| 431 TimeTicks::Now() - start_time, |
| 432 was_timeout, |
| 433 output_file_contents)); |
| 432 } | 434 } |
| 433 | 435 |
| 434 } // namespace | 436 } // namespace |
| 435 | 437 |
| 436 const char kGTestFilterFlag[] = "gtest_filter"; | 438 const char kGTestFilterFlag[] = "gtest_filter"; |
| 437 const char kGTestHelpFlag[] = "gtest_help"; | 439 const char kGTestHelpFlag[] = "gtest_help"; |
| 438 const char kGTestListTestsFlag[] = "gtest_list_tests"; | 440 const char kGTestListTestsFlag[] = "gtest_list_tests"; |
| 439 const char kGTestRepeatFlag[] = "gtest_repeat"; | 441 const char kGTestRepeatFlag[] = "gtest_repeat"; |
| 440 const char kGTestRunDisabledTestsFlag[] = "gtest_also_run_disabled_tests"; | 442 const char kGTestRunDisabledTestsFlag[] = "gtest_also_run_disabled_tests"; |
| 441 const char kGTestOutputFlag[] = "gtest_output"; | 443 const char kGTestOutputFlag[] = "gtest_output"; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 g_shutdown_pipe[0], | 497 g_shutdown_pipe[0], |
| 496 true, | 498 true, |
| 497 MessageLoopForIO::WATCH_READ, | 499 MessageLoopForIO::WATCH_READ, |
| 498 &controller, | 500 &controller, |
| 499 &watcher)); | 501 &watcher)); |
| 500 #endif // defined(OS_POSIX) | 502 #endif // defined(OS_POSIX) |
| 501 | 503 |
| 502 // Start the watchdog timer. | 504 // Start the watchdog timer. |
| 503 watchdog_timer_.Reset(); | 505 watchdog_timer_.Reset(); |
| 504 | 506 |
| 505 ThreadTaskRunnerHandle::Get()->PostTask( | 507 MessageLoop::current()->PostTask( |
| 506 FROM_HERE, Bind(&TestLauncher::RunTestIteration, Unretained(this))); | 508 FROM_HERE, |
| 509 Bind(&TestLauncher::RunTestIteration, Unretained(this))); |
| 507 | 510 |
| 508 MessageLoop::current()->Run(); | 511 MessageLoop::current()->Run(); |
| 509 | 512 |
| 510 if (requested_cycles != 1) | 513 if (requested_cycles != 1) |
| 511 results_tracker_.PrintSummaryOfAllIterations(); | 514 results_tracker_.PrintSummaryOfAllIterations(); |
| 512 | 515 |
| 513 MaybeSaveSummaryAsJSON(); | 516 MaybeSaveSummaryAsJSON(); |
| 514 | 517 |
| 515 return run_result_; | 518 return run_result_; |
| 516 } | 519 } |
| 517 | 520 |
| 518 void TestLauncher::LaunchChildGTestProcess( | 521 void TestLauncher::LaunchChildGTestProcess( |
| 519 const CommandLine& command_line, | 522 const CommandLine& command_line, |
| 520 const std::string& wrapper, | 523 const std::string& wrapper, |
| 521 TimeDelta timeout, | 524 TimeDelta timeout, |
| 522 int flags, | 525 int flags, |
| 523 const LaunchChildGTestProcessCallback& callback) { | 526 const LaunchChildGTestProcessCallback& callback) { |
| 524 DCHECK(thread_checker_.CalledOnValidThread()); | 527 DCHECK(thread_checker_.CalledOnValidThread()); |
| 525 | 528 |
| 526 // Record the exact command line used to launch the child. | 529 // Record the exact command line used to launch the child. |
| 527 CommandLine new_command_line( | 530 CommandLine new_command_line( |
| 528 PrepareCommandLineForGTest(command_line, wrapper)); | 531 PrepareCommandLineForGTest(command_line, wrapper)); |
| 529 | 532 |
| 530 // When running in parallel mode we need to redirect stdio to avoid mixed-up | 533 // When running in parallel mode we need to redirect stdio to avoid mixed-up |
| 531 // output. We also always redirect on the bots to get the test output into | 534 // output. We also always redirect on the bots to get the test output into |
| 532 // JSON summary. | 535 // JSON summary. |
| 533 bool redirect_stdio = (parallel_jobs_ > 1) || BotModeEnabled(); | 536 bool redirect_stdio = (parallel_jobs_ > 1) || BotModeEnabled(); |
| 534 | 537 |
| 535 worker_pool_owner_->pool()->PostWorkerTask( | 538 worker_pool_owner_->pool()->PostWorkerTask( |
| 536 FROM_HERE, Bind(&DoLaunchChildTestProcess, new_command_line, timeout, | 539 FROM_HERE, |
| 537 flags, redirect_stdio, ThreadTaskRunnerHandle::Get(), | 540 Bind(&DoLaunchChildTestProcess, |
| 538 Bind(&TestLauncher::OnLaunchTestProcessFinished, | 541 new_command_line, |
| 539 Unretained(this), callback))); | 542 timeout, |
| 543 flags, |
| 544 redirect_stdio, |
| 545 MessageLoopProxy::current(), |
| 546 Bind(&TestLauncher::OnLaunchTestProcessFinished, |
| 547 Unretained(this), |
| 548 callback))); |
| 540 } | 549 } |
| 541 | 550 |
| 542 void TestLauncher::OnTestFinished(const TestResult& result) { | 551 void TestLauncher::OnTestFinished(const TestResult& result) { |
| 543 ++test_finished_count_; | 552 ++test_finished_count_; |
| 544 | 553 |
| 545 bool print_snippet = false; | 554 bool print_snippet = false; |
| 546 std::string print_test_stdio("auto"); | 555 std::string print_test_stdio("auto"); |
| 547 if (CommandLine::ForCurrentProcess()->HasSwitch( | 556 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 548 switches::kTestLauncherPrintTestStdio)) { | 557 switches::kTestLauncherPrintTestStdio)) { |
| 549 print_test_stdio = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 558 print_test_stdio = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 test_names.push_back(test_name); | 950 test_names.push_back(test_name); |
| 942 } | 951 } |
| 943 | 952 |
| 944 test_started_count_ = launcher_delegate_->RunTests(this, test_names); | 953 test_started_count_ = launcher_delegate_->RunTests(this, test_names); |
| 945 | 954 |
| 946 if (test_started_count_ == 0) { | 955 if (test_started_count_ == 0) { |
| 947 fprintf(stdout, "0 tests run\n"); | 956 fprintf(stdout, "0 tests run\n"); |
| 948 fflush(stdout); | 957 fflush(stdout); |
| 949 | 958 |
| 950 // No tests have actually been started, so kick off the next iteration. | 959 // No tests have actually been started, so kick off the next iteration. |
| 951 ThreadTaskRunnerHandle::Get()->PostTask( | 960 MessageLoop::current()->PostTask( |
| 952 FROM_HERE, Bind(&TestLauncher::RunTestIteration, Unretained(this))); | 961 FROM_HERE, |
| 962 Bind(&TestLauncher::RunTestIteration, Unretained(this))); |
| 953 } | 963 } |
| 954 } | 964 } |
| 955 | 965 |
| 956 void TestLauncher::RunTestIteration() { | 966 void TestLauncher::RunTestIteration() { |
| 957 if (cycles_ == 0) { | 967 if (cycles_ == 0) { |
| 958 MessageLoop::current()->Quit(); | 968 MessageLoop::current()->Quit(); |
| 959 return; | 969 return; |
| 960 } | 970 } |
| 961 | 971 |
| 962 // Special value "-1" means "repeat indefinitely". | 972 // Special value "-1" means "repeat indefinitely". |
| 963 cycles_ = (cycles_ == -1) ? cycles_ : cycles_ - 1; | 973 cycles_ = (cycles_ == -1) ? cycles_ : cycles_ - 1; |
| 964 | 974 |
| 965 test_started_count_ = 0; | 975 test_started_count_ = 0; |
| 966 test_finished_count_ = 0; | 976 test_finished_count_ = 0; |
| 967 test_success_count_ = 0; | 977 test_success_count_ = 0; |
| 968 test_broken_count_ = 0; | 978 test_broken_count_ = 0; |
| 969 retry_count_ = 0; | 979 retry_count_ = 0; |
| 970 tests_to_retry_.clear(); | 980 tests_to_retry_.clear(); |
| 971 results_tracker_.OnTestIterationStarting(); | 981 results_tracker_.OnTestIterationStarting(); |
| 972 | 982 |
| 973 ThreadTaskRunnerHandle::Get()->PostTask( | 983 MessageLoop::current()->PostTask( |
| 974 FROM_HERE, Bind(&TestLauncher::RunTests, Unretained(this))); | 984 FROM_HERE, Bind(&TestLauncher::RunTests, Unretained(this))); |
| 975 } | 985 } |
| 976 | 986 |
| 977 void TestLauncher::MaybeSaveSummaryAsJSON() { | 987 void TestLauncher::MaybeSaveSummaryAsJSON() { |
| 978 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 988 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 979 if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) { | 989 if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) { |
| 980 FilePath summary_path(command_line->GetSwitchValuePath( | 990 FilePath summary_path(command_line->GetSwitchValuePath( |
| 981 switches::kTestLauncherSummaryOutput)); | 991 switches::kTestLauncherSummaryOutput)); |
| 982 if (!results_tracker_.SaveSummaryAsJSON(summary_path)) { | 992 if (!results_tracker_.SaveSummaryAsJSON(summary_path)) { |
| 983 LOG(ERROR) << "Failed to save test launcher output summary."; | 993 LOG(ERROR) << "Failed to save test launcher output summary."; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1010 fflush(stdout); | 1020 fflush(stdout); |
| 1011 } else { | 1021 } else { |
| 1012 // Signal failure, but continue to run all requested test iterations. | 1022 // Signal failure, but continue to run all requested test iterations. |
| 1013 // With the summary of all iterations at the end this is a good default. | 1023 // With the summary of all iterations at the end this is a good default. |
| 1014 run_result_ = false; | 1024 run_result_ = false; |
| 1015 } | 1025 } |
| 1016 | 1026 |
| 1017 results_tracker_.PrintSummaryOfCurrentIteration(); | 1027 results_tracker_.PrintSummaryOfCurrentIteration(); |
| 1018 | 1028 |
| 1019 // Kick off the next iteration. | 1029 // Kick off the next iteration. |
| 1020 ThreadTaskRunnerHandle::Get()->PostTask( | 1030 MessageLoop::current()->PostTask( |
| 1021 FROM_HERE, Bind(&TestLauncher::RunTestIteration, Unretained(this))); | 1031 FROM_HERE, |
| 1032 Bind(&TestLauncher::RunTestIteration, Unretained(this))); |
| 1022 } | 1033 } |
| 1023 | 1034 |
| 1024 void TestLauncher::OnOutputTimeout() { | 1035 void TestLauncher::OnOutputTimeout() { |
| 1025 DCHECK(thread_checker_.CalledOnValidThread()); | 1036 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1026 | 1037 |
| 1027 AutoLock lock(g_live_processes_lock.Get()); | 1038 AutoLock lock(g_live_processes_lock.Get()); |
| 1028 | 1039 |
| 1029 fprintf(stdout, "Still waiting for the following processes to finish:\n"); | 1040 fprintf(stdout, "Still waiting for the following processes to finish:\n"); |
| 1030 | 1041 |
| 1031 for (std::map<ProcessHandle, CommandLine>::iterator i = | 1042 for (std::map<ProcessHandle, CommandLine>::iterator i = |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 } | 1081 } |
| 1071 | 1082 |
| 1072 std::string snippet(full_output.substr(run_pos)); | 1083 std::string snippet(full_output.substr(run_pos)); |
| 1073 if (end_pos != std::string::npos) | 1084 if (end_pos != std::string::npos) |
| 1074 snippet = full_output.substr(run_pos, end_pos - run_pos); | 1085 snippet = full_output.substr(run_pos, end_pos - run_pos); |
| 1075 | 1086 |
| 1076 return snippet; | 1087 return snippet; |
| 1077 } | 1088 } |
| 1078 | 1089 |
| 1079 } // namespace base | 1090 } // namespace base |
| OLD | NEW |