test_launcher.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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 3// found in the LICENSE file. 4 5#include "base/test/launcher/test_launcher.h" 6 7#if defined(OS_POSIX) 8#include <fcntl.h> 9#endif 10 11#include "base/at_exit.h" 12#include "base/bind.h" 13#include "base/command_line.h" 14#include "base/environment.h" 15#include "base/file_util.h" 16#include "base/files/file_path.h" 17#include "base/files/scoped_file.h" 18#include "base/format_macros.h" 19#include "base/hash.h" 20#include "base/lazy_instance.h" 21#include "base/logging.h" 22#include "base/memory/scoped_ptr.h" 23#include "base/message_loop/message_loop.h" 24#include "base/process/kill.h" 25#include "base/process/launch.h" 26#include "base/strings/string_number_conversions.h" 27#include "base/strings/string_split.h" 28#include "base/strings/string_util.h" 29#include "base/strings/stringize_macros.h" 30#include "base/strings/stringprintf.h" 31#include "base/strings/utf_string_conversions.h" 32#include "base/test/launcher/test_results_tracker.h" 33#include "base/test/sequenced_worker_pool_owner.h" 34#include "base/test/test_switches.h" 35#include "base/test/test_timeouts.h" 36#include "base/threading/thread_checker.h" 37#include "base/time/time.h" 38#include "testing/gtest/include/gtest/gtest.h" 39 40#if defined(OS_MACOSX) 41#include "base/mac/scoped_nsautorelease_pool.h" 42#endif 43 44namespace base { 45 46// See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/uT3FaE_sgkAJ . 47using ::operator<<; 48 49// The environment variable name for the total number of test shards. 50const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; 51// The environment variable name for the test shard index. 52const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; 53 54namespace { 55 56// Global tag for test runs where the results are incomplete or unreliable 57// for any reason, e.g. early exit because of too many broken tests. 58const char kUnreliableResultsTag[] = "UNRELIABLE_RESULTS"; 59 60// Maximum time of no output after which we print list of processes still 61// running. This deliberately doesn't use TestTimeouts (which is otherwise 62// a recommended solution), because they can be increased. This would defeat 63// the purpose of this timeout, which is 1) to avoid buildbot "no output for 64// X seconds" timeout killing the process 2) help communicate status of 65// the test launcher to people looking at the output (no output for a long 66// time is mysterious and gives no info about what is happening) 3) help 67// debugging in case the process hangs anyway. 68const int kOutputTimeoutSeconds = 15; 69 70// Set of live launch test processes with corresponding lock (it is allowed 71// for callers to launch processes on different threads). 72LazyInstance<std::map<ProcessHandle, CommandLine> > g_live_processes 73 = LAZY_INSTANCE_INITIALIZER; 74LazyInstance<Lock> g_live_processes_lock = LAZY_INSTANCE_INITIALIZER; 75 76#if defined(OS_POSIX) 77// Self-pipe that makes it possible to do complex shutdown handling 78// outside of the signal handler. 79int g_shutdown_pipe[2] = { -1, -1 }; 80 81void ShutdownPipeSignalHandler(int signal) { 82 HANDLE_EINTR(write(g_shutdown_pipe[1], "q", 1)); 83} 84 85void KillSpawnedTestProcesses() { 86 // Keep the lock until exiting the process to prevent further processes 87 // from being spawned. 88 AutoLock lock(g_live_processes_lock.Get()); 89 90 fprintf(stdout, 91 "Sending SIGTERM to %" PRIuS " child processes... ", 92 g_live_processes.Get().size()); 93 fflush(stdout); 94 95 for (std::map<ProcessHandle, CommandLine>::iterator i = 96 g_live_processes.Get().begin(); 97 i != g_live_processes.Get().end(); 98 ++i) { 99 // Send the signal to entire process group. 100 kill((-1) * (i->first), SIGTERM); 101 } 102 103 fprintf(stdout, 104 "done.\nGiving processes a chance to terminate cleanly... "); 105 fflush(stdout); 106 107 PlatformThread::Sleep(TimeDelta::FromMilliseconds(500)); 108 109 fprintf(stdout, "done.\n"); 110 fflush(stdout); 111 112 fprintf(stdout, 113 "Sending SIGKILL to %" PRIuS " child processes... ", 114 g_live_processes.Get().size()); 115 fflush(stdout); 116 117 for (std::map<ProcessHandle, CommandLine>::iterator i = 118 g_live_processes.Get().begin(); 119 i != g_live_processes.Get().end(); 120 ++i) { 121 // Send the signal to entire process group. 122 kill((-1) * (i->first), SIGKILL); 123 } 124 125 fprintf(stdout, "done.\n"); 126 fflush(stdout); 127} 128 129// I/O watcher for the reading end of the self-pipe above. 130// Terminates any launched child processes and exits the process. 131class SignalFDWatcher : public MessageLoopForIO::Watcher { 132 public: 133 SignalFDWatcher() { 134 } 135 136 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE { 137 fprintf(stdout, "\nCaught signal. Killing spawned test processes...\n"); 138 fflush(stdout); 139 140 KillSpawnedTestProcesses(); 141 142 // The signal would normally kill the process, so exit now. 143 exit(1); 144 } 145 146 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE { 147 NOTREACHED(); 148 } 149 150 private: 151 DISALLOW_COPY_AND_ASSIGN(SignalFDWatcher); 152}; 153#endif // defined(OS_POSIX) 154 155// Parses the environment variable var as an Int32. If it is unset, returns 156// true. If it is set, unsets it then converts it to Int32 before 157// returning it in |result|. Returns true on success. 158bool TakeInt32FromEnvironment(const char* const var, int32* result) { 159 scoped_ptr<Environment> env(Environment::Create()); 160 std::string str_val; 161 162 if (!env->GetVar(var, &str_val)) 163 return true; 164 165 if (!env->UnSetVar(var)) { 166 LOG(ERROR) << "Invalid environment: we could not unset " << var << ".\n"; 167 return false; 168 } 169 170 if (!StringToInt(str_val, result)) { 171 LOG(ERROR) << "Invalid environment: " << var << " is not an integer.\n"; 172 return false; 173 } 174 175 return true; 176} 177 178// Unsets the environment variable |name| and returns true on success. 179// Also returns true if the variable just doesn't exist. 180bool UnsetEnvironmentVariableIfExists(const std::string& name) { 181 scoped_ptr<Environment> env(Environment::Create()); 182 std::string str_val; 183 184 if (!env->GetVar(name.c_str(), &str_val)) 185 return true; 186 187 return env->UnSetVar(name.c_str()); 188} 189 190// Returns true if bot mode has been requested, i.e. defaults optimized 191// for continuous integration bots. This way developers don't have to remember 192// special command-line flags. 193bool BotModeEnabled() { 194 scoped_ptr<Environment> env(Environment::Create()); 195 return CommandLine::ForCurrentProcess()->HasSwitch( 196 switches::kTestLauncherBotMode) || 197 env->HasVar("CHROMIUM_TEST_LAUNCHER_BOT_MODE"); 198} 199 200void RunCallback( 201 const TestLauncher::LaunchChildGTestProcessCallback& callback, 202 int exit_code, 203 const TimeDelta& elapsed_time, 204 bool was_timeout, 205 const std::string& output) { 206 callback.Run(exit_code, elapsed_time, was_timeout, output); 207} 208 209void DoLaunchChildTestProcess( 210 const CommandLine& command_line, 211 base::TimeDelta timeout, 212 bool redirect_stdio, 213 scoped_refptr<MessageLoopProxy> message_loop_proxy, 214 const TestLauncher::LaunchChildGTestProcessCallback& callback) { 215 TimeTicks start_time = TimeTicks::Now(); 216 217 // Redirect child process output to a file. 218 base::FilePath output_file; 219 CHECK(base::CreateTemporaryFile(&output_file)); 220 221 LaunchOptions options; 222#if defined(OS_WIN) 223 win::ScopedHandle handle; 224 225 if (redirect_stdio) { 226 // Make the file handle inheritable by the child. 227 SECURITY_ATTRIBUTES sa_attr; 228 sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES); 229 sa_attr.lpSecurityDescriptor = NULL; 230 sa_attr.bInheritHandle = TRUE; 231 232 handle.Set(CreateFile(output_file.value().c_str(), 233 GENERIC_WRITE, 234 FILE_SHARE_READ | FILE_SHARE_DELETE, 235 &sa_attr, 236 OPEN_EXISTING, 237 FILE_ATTRIBUTE_TEMPORARY, 238 NULL)); 239 CHECK(handle.IsValid()); 240 options.inherit_handles = true; 241 options.stdin_handle = INVALID_HANDLE_VALUE; 242 options.stdout_handle = handle.Get(); 243 options.stderr_handle = handle.Get(); 244 } 245#elif defined(OS_POSIX) 246 options.new_process_group = true; 247 248 base::FileHandleMappingVector fds_mapping; 249 base::ScopedFD output_file_fd; 250 251 if (redirect_stdio) { 252 output_file_fd.reset(open(output_file.value().c_str(), O_RDWR)); 253 CHECK(output_file_fd.is_valid()); 254 255 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDOUT_FILENO)); 256 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDERR_FILENO)); 257 options.fds_to_remap = &fds_mapping; 258 } 259#endif 260 261 bool was_timeout = false; 262 int exit_code = LaunchChildTestProcessWithOptions( 263 command_line, options, timeout, &was_timeout); 264 265 if (redirect_stdio) { 266#if defined(OS_WIN) 267 FlushFileBuffers(handle.Get()); 268 handle.Close(); 269#elif defined(OS_POSIX) 270 output_file_fd.reset(); 271#endif 272 } 273 274 std::string output_file_contents; 275 CHECK(base::ReadFileToString(output_file, &output_file_contents)); 276 277 if (!base::DeleteFile(output_file, false)) { 278 // This needs to be non-fatal at least for Windows. 279 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe(); 280 } 281 282 // Run target callback on the thread it was originating from, not on 283 // a worker pool thread. 284 message_loop_proxy->PostTask( 285 FROM_HERE, 286 Bind(&RunCallback, 287 callback, 288 exit_code, 289 TimeTicks::Now() - start_time, 290 was_timeout, 291 output_file_contents)); 292} 293 294} // namespace 295 296const char kGTestFilterFlag[] = "gtest_filter"; 297const char kGTestHelpFlag[] = "gtest_help"; 298const char kGTestListTestsFlag[] = "gtest_list_tests"; 299const char kGTestRepeatFlag[] = "gtest_repeat"; 300const char kGTestRunDisabledTestsFlag[] = "gtest_also_run_disabled_tests"; 301const char kGTestOutputFlag[] = "gtest_output"; 302 303TestLauncherDelegate::~TestLauncherDelegate() { 304} 305 306TestLauncher::TestLauncher(TestLauncherDelegate* launcher_delegate, 307 size_t parallel_jobs) 308 : launcher_delegate_(launcher_delegate), 309 total_shards_(1), 310 shard_index_(0), 311 cycles_(1), 312 test_started_count_(0), 313 test_finished_count_(0), 314 test_success_count_(0), 315 test_broken_count_(0), 316 retry_count_(0), 317 retry_limit_(0), 318 run_result_(true), 319 watchdog_timer_(FROM_HERE, 320 TimeDelta::FromSeconds(kOutputTimeoutSeconds), 321 this, 322 &TestLauncher::OnOutputTimeout), 323 parallel_jobs_(parallel_jobs) { 324 if (BotModeEnabled()) { 325 fprintf(stdout, 326 "Enabling defaults optimized for continuous integration bots.\n"); 327 fflush(stdout); 328 329 // Enable test retries by default for bots. This can be still overridden 330 // from command line using --test-launcher-retry-limit flag. 331 retry_limit_ = 3; 332 } else { 333 // Default to serial test execution if not running on a bot. This makes it 334 // possible to disable stdio redirection and can still be overridden with 335 // --test-launcher-jobs flag. 336 parallel_jobs_ = 1; 337 } 338} 339 340TestLauncher::~TestLauncher() { 341 if (worker_pool_owner_) 342 worker_pool_owner_->pool()->Shutdown(); 343} 344 345bool TestLauncher::Run(int argc, char** argv) { 346 if (!Init()) 347 return false; 348 349 // Value of |cycles_| changes after each iteration. Keep track of the 350 // original value. 351 int requested_cycles = cycles_; 352 353#if defined(OS_POSIX) 354 CHECK_EQ(0, pipe(g_shutdown_pipe)); 355 356 struct sigaction action; 357 memset(&action, 0, sizeof(action)); 358 sigemptyset(&action.sa_mask); 359 action.sa_handler = &ShutdownPipeSignalHandler; 360 361 CHECK_EQ(0, sigaction(SIGINT, &action, NULL)); 362 CHECK_EQ(0, sigaction(SIGQUIT, &action, NULL)); 363 CHECK_EQ(0, sigaction(SIGTERM, &action, NULL)); 364 365 MessageLoopForIO::FileDescriptorWatcher controller; 366 SignalFDWatcher watcher; 367 368 CHECK(MessageLoopForIO::current()->WatchFileDescriptor( 369 g_shutdown_pipe[0], 370 true, 371 MessageLoopForIO::WATCH_READ, 372 &controller, 373 &watcher)); 374#endif // defined(OS_POSIX) 375 376 // Start the watchdog timer. 377 watchdog_timer_.Reset(); 378 379 MessageLoop::current()->PostTask( 380 FROM_HERE, 381 Bind(&TestLauncher::RunTestIteration, Unretained(this))); 382 383 MessageLoop::current()->Run(); 384 385 if (requested_cycles != 1) 386 results_tracker_.PrintSummaryOfAllIterations(); 387 388 MaybeSaveSummaryAsJSON(); 389 390 return run_result_; 391} 392 393void TestLauncher::LaunchChildGTestProcess( 394 const CommandLine& command_line, 395 const std::string& wrapper, 396 base::TimeDelta timeout, 397 const LaunchChildGTestProcessCallback& callback) { 398 DCHECK(thread_checker_.CalledOnValidThread()); 399 400 // Record the exact command line used to launch the child. 401 CommandLine new_command_line( 402 PrepareCommandLineForGTest(command_line, wrapper)); 403 404 // When running in parallel mode we need to redirect stdio to avoid mixed-up 405 // output. We also always redirect on the bots to get the test output into 406 // JSON summary. 407 bool redirect_stdio = (parallel_jobs_ > 1) || BotModeEnabled(); 408 409 worker_pool_owner_->pool()->PostWorkerTask( 410 FROM_HERE, 411 Bind(&DoLaunchChildTestProcess, 412 new_command_line, 413 timeout, 414 redirect_stdio, 415 MessageLoopProxy::current(), 416 Bind(&TestLauncher::OnLaunchTestProcessFinished, 417 Unretained(this), 418 callback))); 419} 420 421void TestLauncher::OnTestFinished(const TestResult& result) { 422 ++test_finished_count_; 423 424 bool print_snippet = false; 425 std::string print_test_stdio("auto"); 426 if (CommandLine::ForCurrentProcess()->HasSwitch( 427 switches::kTestLauncherPrintTestStdio)) { 428 print_test_stdio = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 429 switches::kTestLauncherPrintTestStdio); 430 } 431 if (print_test_stdio == "auto") { 432 print_snippet = (result.status != TestResult::TEST_SUCCESS); 433 } else if (print_test_stdio == "always") { 434 print_snippet = true; 435 } else if (print_test_stdio == "never") { 436 print_snippet = false; 437 } else { 438 LOG(WARNING) << "Invalid value of " << switches::kTestLauncherPrintTestStdio 439 << ": " << print_test_stdio; 440 } 441 if (print_snippet) { 442 fprintf(stdout, "%s", result.output_snippet.c_str()); 443 fflush(stdout); 444 } 445 446 if (result.status == TestResult::TEST_SUCCESS) { 447 ++test_success_count_; 448 } else { 449 tests_to_retry_.insert(result.full_name); 450 } 451 452 if (result.status == TestResult::TEST_UNKNOWN) 453 results_tracker_.AddGlobalTag(kUnreliableResultsTag); 454 455 results_tracker_.AddTestResult(result); 456 457 // TODO(phajdan.jr): Align counter (padding). 458 std::string status_line( 459 StringPrintf("[%" PRIuS "/%" PRIuS "] %s ", 460 test_finished_count_, 461 test_started_count_, 462 result.full_name.c_str())); 463 if (result.completed()) { 464 status_line.append(StringPrintf("(%" PRId64 " ms)", 465 result.elapsed_time.InMilliseconds())); 466 } else if (result.status == TestResult::TEST_TIMEOUT) { 467 status_line.append("(TIMED OUT)"); 468 } else if (result.status == TestResult::TEST_CRASH) { 469 status_line.append("(CRASHED)"); 470 } else if (result.status == TestResult::TEST_SKIPPED) { 471 status_line.append("(SKIPPED)"); 472 } else if (result.status == TestResult::TEST_UNKNOWN) { 473 status_line.append("(UNKNOWN)"); 474 } else { 475 // Fail very loudly so it's not ignored. 476 CHECK(false) << "Unhandled test result status: " << result.status; 477 } 478 fprintf(stdout, "%s\n", status_line.c_str()); 479 fflush(stdout); 480 481 // We just printed a status line, reset the watchdog timer. 482 watchdog_timer_.Reset(); 483 484 // Do not waste time on timeouts. We include tests with unknown results here 485 // because sometimes (e.g. hang in between unit tests) that's how a timeout 486 // gets reported. 487 if (result.status == TestResult::TEST_TIMEOUT || 488 result.status == TestResult::TEST_UNKNOWN) { 489 test_broken_count_++; 490 } 491 size_t broken_threshold = 492 std::max(static_cast<size_t>(20), test_started_count_ / 10); 493 if (test_broken_count_ >= broken_threshold) { 494 fprintf(stdout, "Too many badly broken tests (%" PRIuS "), exiting now.\n", 495 test_broken_count_); 496 fflush(stdout); 497 498#if defined(OS_POSIX) 499 KillSpawnedTestProcesses(); 500#endif // defined(OS_POSIX) 501 502 results_tracker_.AddGlobalTag("BROKEN_TEST_EARLY_EXIT"); 503 results_tracker_.AddGlobalTag(kUnreliableResultsTag); 504 MaybeSaveSummaryAsJSON(); 505 506 exit(1); 507 } 508 509 if (test_finished_count_ != test_started_count_) 510 return; 511 512 if (tests_to_retry_.empty() || retry_count_ >= retry_limit_) { 513 OnTestIterationFinished(); 514 return; 515 } 516 517 if (tests_to_retry_.size() >= broken_threshold) { 518 fprintf(stdout, 519 "Too many failing tests (%" PRIuS "), skipping retries.\n", 520 tests_to_retry_.size()); 521 fflush(stdout); 522 523 results_tracker_.AddGlobalTag("BROKEN_TEST_SKIPPED_RETRIES"); 524 results_tracker_.AddGlobalTag(kUnreliableResultsTag); 525 526 OnTestIterationFinished(); 527 return; 528 } 529 530 retry_count_++; 531 532 std::vector<std::string> test_names(tests_to_retry_.begin(), 533 tests_to_retry_.end()); 534 535 tests_to_retry_.clear(); 536 537 size_t retry_started_count = launcher_delegate_->RetryTests(this, test_names); 538 if (retry_started_count == 0) { 539 // Signal failure, but continue to run all requested test iterations. 540 // With the summary of all iterations at the end this is a good default. 541 run_result_ = false; 542 543 OnTestIterationFinished(); 544 return; 545 } 546 547 fprintf(stdout, "Retrying %" PRIuS " test%s (retry #%" PRIuS ")\n", 548 retry_started_count, 549 retry_started_count > 1 ? "s" : "", 550 retry_count_); 551 fflush(stdout); 552 553 test_started_count_ += retry_started_count; 554} 555 556bool TestLauncher::Init() { 557 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 558 559 // Initialize sharding. Command line takes precedence over legacy environment 560 // variables. 561 if (command_line->HasSwitch(switches::kTestLauncherTotalShards) && 562 command_line->HasSwitch(switches::kTestLauncherShardIndex)) { 563 if (!StringToInt( 564 command_line->GetSwitchValueASCII( 565 switches::kTestLauncherTotalShards), 566 &total_shards_)) { 567 LOG(ERROR) << "Invalid value for " << switches::kTestLauncherTotalShards; 568 return false; 569 } 570 if (!StringToInt( 571 command_line->GetSwitchValueASCII( 572 switches::kTestLauncherShardIndex), 573 &shard_index_)) { 574 LOG(ERROR) << "Invalid value for " << switches::kTestLauncherShardIndex; 575 return false; 576 } 577 fprintf(stdout, 578 "Using sharding settings from command line. This is shard %d/%d\n", 579 shard_index_, total_shards_); 580 fflush(stdout); 581 } else { 582 if (!TakeInt32FromEnvironment(kTestTotalShards, &total_shards_)) 583 return false; 584 if (!TakeInt32FromEnvironment(kTestShardIndex, &shard_index_)) 585 return false; 586 fprintf(stdout, 587 "Using sharding settings from environment. This is shard %d/%d\n", 588 shard_index_, total_shards_); 589 fflush(stdout); 590 } 591 if (shard_index_ < 0 || 592 total_shards_ < 0 || 593 shard_index_ >= total_shards_) { 594 LOG(ERROR) << "Invalid sharding settings: we require 0 <= " 595 << kTestShardIndex << " < " << kTestTotalShards 596 << ", but you have " << kTestShardIndex << "=" << shard_index_ 597 << ", " << kTestTotalShards << "=" << total_shards_ << ".\n"; 598 return false; 599 } 600 601 // Make sure we don't pass any sharding-related environment to the child 602 // processes. This test launcher implements the sharding completely. 603 CHECK(UnsetEnvironmentVariableIfExists("GTEST_TOTAL_SHARDS")); 604 CHECK(UnsetEnvironmentVariableIfExists("GTEST_SHARD_INDEX")); 605 606 if (command_line->HasSwitch(kGTestRepeatFlag) && 607 !StringToInt(command_line->GetSwitchValueASCII(kGTestRepeatFlag), 608 &cycles_)) { 609 LOG(ERROR) << "Invalid value for " << kGTestRepeatFlag; 610 return false; 611 } 612 613 if (CommandLine::ForCurrentProcess()->HasSwitch( 614 switches::kTestLauncherRetryLimit)) { 615 int retry_limit = -1; 616 if (!StringToInt(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 617 switches::kTestLauncherRetryLimit), &retry_limit) || 618 retry_limit < 0) { 619 LOG(ERROR) << "Invalid value for " << switches::kTestLauncherRetryLimit; 620 return false; 621 } 622 623 retry_limit_ = retry_limit; 624 } 625 626 if (CommandLine::ForCurrentProcess()->HasSwitch( 627 switches::kTestLauncherJobs)) { 628 int jobs = -1; 629 if (!StringToInt(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 630 switches::kTestLauncherJobs), &jobs) || 631 jobs < 0) { 632 LOG(ERROR) << "Invalid value for " << switches::kTestLauncherJobs; 633 return false; 634 } 635 636 parallel_jobs_ = jobs; 637 } 638 fprintf(stdout, "Using %" PRIuS " parallel jobs.\n", parallel_jobs_); 639 fflush(stdout); 640 worker_pool_owner_.reset( 641 new SequencedWorkerPoolOwner(parallel_jobs_, "test_launcher")); 642 643 if (command_line->HasSwitch(switches::kTestLauncherFilterFile) && 644 command_line->HasSwitch(kGTestFilterFlag)) { 645 LOG(ERROR) << "Only one of --test-launcher-filter-file and --gtest_filter " 646 << "at a time is allowed."; 647 return false; 648 } 649 650 if (command_line->HasSwitch(switches::kTestLauncherFilterFile)) { 651 std::string filter; 652 if (!ReadFileToString( 653 command_line->GetSwitchValuePath(switches::kTestLauncherFilterFile), 654 &filter)) { 655 LOG(ERROR) << "Failed to read the filter file."; 656 return false; 657 } 658 659 std::vector<std::string> filter_lines; 660 SplitString(filter, '\n', &filter_lines); 661 for (size_t i = 0; i < filter_lines.size(); i++) { 662 if (filter_lines[i].empty()) 663 continue; 664 665 if (filter_lines[i][0] == '-') 666 negative_test_filter_.push_back(filter_lines[i].substr(1)); 667 else 668 positive_test_filter_.push_back(filter_lines[i]); 669 } 670 } else { 671 // Split --gtest_filter at '-', if there is one, to separate into 672 // positive filter and negative filter portions. 673 std::string filter = command_line->GetSwitchValueASCII(kGTestFilterFlag); 674 size_t dash_pos = filter.find('-'); 675 if (dash_pos == std::string::npos) { 676 SplitString(filter, ':', &positive_test_filter_); 677 } else { 678 // Everything up to the dash. 679 SplitString(filter.substr(0, dash_pos), ':', &positive_test_filter_); 680 681 // Everything after the dash. 682 SplitString(filter.substr(dash_pos + 1), ':', &negative_test_filter_); 683 } 684 } 685 686 if (!results_tracker_.Init(*command_line)) { 687 LOG(ERROR) << "Failed to initialize test results tracker."; 688 return 1; 689 } 690 691#if defined(NDEBUG) 692 results_tracker_.AddGlobalTag("MODE_RELEASE"); 693#else 694 results_tracker_.AddGlobalTag("MODE_DEBUG"); 695#endif 696 697 // Operating systems (sorted alphabetically). 698 // Note that they can deliberately overlap, e.g. OS_LINUX is a subset 699 // of OS_POSIX. 700#if defined(OS_ANDROID) 701 results_tracker_.AddGlobalTag("OS_ANDROID"); 702#endif 703 704#if defined(OS_BSD) 705 results_tracker_.AddGlobalTag("OS_BSD"); 706#endif 707 708#if defined(OS_FREEBSD) 709 results_tracker_.AddGlobalTag("OS_FREEBSD"); 710#endif 711 712#if defined(OS_IOS) 713 results_tracker_.AddGlobalTag("OS_IOS"); 714#endif 715 716#if defined(OS_LINUX) 717 results_tracker_.AddGlobalTag("OS_LINUX"); 718#endif 719 720#if defined(OS_MACOSX) 721 results_tracker_.AddGlobalTag("OS_MACOSX"); 722#endif 723 724#if defined(OS_NACL) 725 results_tracker_.AddGlobalTag("OS_NACL"); 726#endif 727 728#if defined(OS_OPENBSD) 729 results_tracker_.AddGlobalTag("OS_OPENBSD"); 730#endif 731 732#if defined(OS_POSIX) 733 results_tracker_.AddGlobalTag("OS_POSIX"); 734#endif 735 736#if defined(OS_SOLARIS) 737 results_tracker_.AddGlobalTag("OS_SOLARIS"); 738#endif 739 740#if defined(OS_WIN) 741 results_tracker_.AddGlobalTag("OS_WIN"); 742#endif 743 744 // CPU-related tags. 745#if defined(ARCH_CPU_32_BITS) 746 results_tracker_.AddGlobalTag("CPU_32_BITS"); 747#endif 748 749#if defined(ARCH_CPU_64_BITS) 750 results_tracker_.AddGlobalTag("CPU_64_BITS"); 751#endif 752 753 return true; 754} 755 756void TestLauncher::RunTests() { 757 testing::UnitTest* const unit_test = testing::UnitTest::GetInstance(); 758 759 std::vector<std::string> test_names; 760 761 for (int i = 0; i < unit_test->total_test_case_count(); ++i) { 762 const testing::TestCase* test_case = unit_test->GetTestCase(i); 763 for (int j = 0; j < test_case->total_test_count(); ++j) { 764 const testing::TestInfo* test_info = test_case->GetTestInfo(j); 765 std::string test_name = test_info->test_case_name(); 766 test_name.append("."); 767 test_name.append(test_info->name()); 768 769 results_tracker_.AddTest(test_name); 770 771 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 772 if (test_name.find("DISABLED") != std::string::npos) { 773 results_tracker_.AddDisabledTest(test_name); 774 775 // Skip disabled tests unless explicitly requested. 776 if (!command_line->HasSwitch(kGTestRunDisabledTestsFlag)) 777 continue; 778 } 779 780 // Skip the test that doesn't match the filter (if given). 781 if (!positive_test_filter_.empty()) { 782 bool found = false; 783 for (size_t k = 0; k < positive_test_filter_.size(); ++k) { 784 if (MatchPattern(test_name, positive_test_filter_[k])) { 785 found = true; 786 break; 787 } 788 } 789 790 if (!found) 791 continue; 792 } 793 bool excluded = false; 794 for (size_t k = 0; k < negative_test_filter_.size(); ++k) { 795 if (MatchPattern(test_name, negative_test_filter_[k])) { 796 excluded = true; 797 break; 798 } 799 } 800 if (excluded) 801 continue; 802 803 if (!launcher_delegate_->ShouldRunTest(test_case, test_info)) 804 continue; 805 806 if (base::Hash(test_name) % total_shards_ != 807 static_cast<uint32>(shard_index_)) { 808 continue; 809 } 810 811 test_names.push_back(test_name); 812 } 813 } 814 815 test_started_count_ = launcher_delegate_->RunTests(this, test_names); 816 817 if (test_started_count_ == 0) { 818 fprintf(stdout, "0 tests run\n"); 819 fflush(stdout); 820 821 // No tests have actually been started, so kick off the next iteration. 822 MessageLoop::current()->PostTask( 823 FROM_HERE, 824 Bind(&TestLauncher::RunTestIteration, Unretained(this))); 825 } 826} 827 828void TestLauncher::RunTestIteration() { 829 if (cycles_ == 0) { 830 MessageLoop::current()->Quit(); 831 return; 832 } 833 834 // Special value "-1" means "repeat indefinitely". 835 cycles_ = (cycles_ == -1) ? cycles_ : cycles_ - 1; 836 837 test_started_count_ = 0; 838 test_finished_count_ = 0; 839 test_success_count_ = 0; 840 test_broken_count_ = 0; 841 retry_count_ = 0; 842 tests_to_retry_.clear(); 843 results_tracker_.OnTestIterationStarting(); 844 845 MessageLoop::current()->PostTask( 846 FROM_HERE, Bind(&TestLauncher::RunTests, Unretained(this))); 847} 848 849void TestLauncher::MaybeSaveSummaryAsJSON() { 850 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 851 if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) { 852 FilePath summary_path(command_line->GetSwitchValuePath( 853 switches::kTestLauncherSummaryOutput)); 854 if (!results_tracker_.SaveSummaryAsJSON(summary_path)) { 855 LOG(ERROR) << "Failed to save test launcher output summary."; 856 } 857 } 858} 859 860void TestLauncher::OnLaunchTestProcessFinished( 861 const LaunchChildGTestProcessCallback& callback, 862 int exit_code, 863 const TimeDelta& elapsed_time, 864 bool was_timeout, 865 const std::string& output) { 866 DCHECK(thread_checker_.CalledOnValidThread()); 867 868 callback.Run(exit_code, elapsed_time, was_timeout, output); 869} 870 871void TestLauncher::OnTestIterationFinished() { 872 // When we retry tests, success is determined by having nothing more 873 // to retry (everything eventually passed), as opposed to having 874 // no failures at all. 875 if (tests_to_retry_.empty()) { 876 fprintf(stdout, "SUCCESS: all tests passed.\n"); 877 fflush(stdout); 878 } else { 879 // Signal failure, but continue to run all requested test iterations. 880 // With the summary of all iterations at the end this is a good default. 881 run_result_ = false; 882 } 883 884 results_tracker_.PrintSummaryOfCurrentIteration(); 885 886 // Kick off the next iteration. 887 MessageLoop::current()->PostTask( 888 FROM_HERE, 889 Bind(&TestLauncher::RunTestIteration, Unretained(this))); 890} 891 892void TestLauncher::OnOutputTimeout() { 893 DCHECK(thread_checker_.CalledOnValidThread()); 894 895 AutoLock lock(g_live_processes_lock.Get()); 896 897 fprintf(stdout, "Still waiting for the following processes to finish:\n"); 898 899 for (std::map<ProcessHandle, CommandLine>::iterator i = 900 g_live_processes.Get().begin(); 901 i != g_live_processes.Get().end(); 902 ++i) { 903#if defined(OS_WIN) 904 fwprintf(stdout, L"\t%s\n", i->second.GetCommandLineString().c_str()); 905#else 906 fprintf(stdout, "\t%s\n", i->second.GetCommandLineString().c_str()); 907#endif 908 } 909 910 fflush(stdout); 911 912 // Arm the timer again - otherwise it would fire only once. 913 watchdog_timer_.Reset(); 914} 915 916std::string GetTestOutputSnippet(const TestResult& result, 917 const std::string& full_output) { 918 size_t run_pos = full_output.find(std::string("[ RUN ] ") + 919 result.full_name); 920 if (run_pos == std::string::npos) 921 return std::string(); 922 923 size_t end_pos = full_output.find(std::string("[ FAILED ] ") + 924 result.full_name, 925 run_pos); 926 // Only clip the snippet to the "OK" message if the test really 927 // succeeded. It still might have e.g. crashed after printing it. 928 if (end_pos == std::string::npos && 929 result.status == TestResult::TEST_SUCCESS) { 930 end_pos = full_output.find(std::string("[ OK ] ") + 931 result.full_name, 932 run_pos); 933 } 934 if (end_pos != std::string::npos) { 935 size_t newline_pos = full_output.find("\n", end_pos); 936 if (newline_pos != std::string::npos) 937 end_pos = newline_pos + 1; 938 } 939 940 std::string snippet(full_output.substr(run_pos)); 941 if (end_pos != std::string::npos) 942 snippet = full_output.substr(run_pos, end_pos - run_pos); 943 944 return snippet; 945} 946 947int LaunchChildGTestProcess(const CommandLine& command_line, 948 const std::string& wrapper, 949 base::TimeDelta timeout, 950 bool* was_timeout) { 951 LaunchOptions options; 952 953#if defined(OS_POSIX) 954 // On POSIX, we launch the test in a new process group with pgid equal to 955 // its pid. Any child processes that the test may create will inherit the 956 // same pgid. This way, if the test is abruptly terminated, we can clean up 957 // any orphaned child processes it may have left behind. 958 options.new_process_group = true; 959#endif 960 961 return LaunchChildTestProcessWithOptions( 962 PrepareCommandLineForGTest(command_line, wrapper), 963 options, 964 timeout, 965 was_timeout); 966} 967 968CommandLine PrepareCommandLineForGTest(const CommandLine& command_line, 969 const std::string& wrapper) { 970 CommandLine new_command_line(command_line.GetProgram()); 971 CommandLine::SwitchMap switches = command_line.GetSwitches(); 972 973 // Strip out gtest_repeat flag - this is handled by the launcher process. 974 switches.erase(kGTestRepeatFlag); 975 976 // Don't try to write the final XML report in child processes. 977 switches.erase(kGTestOutputFlag); 978 979 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); 980 iter != switches.end(); ++iter) { 981 new_command_line.AppendSwitchNative((*iter).first, (*iter).second); 982 } 983 984 // Prepend wrapper after last CommandLine quasi-copy operation. CommandLine 985 // does not really support removing switches well, and trying to do that 986 // on a CommandLine with a wrapper is known to break. 987 // TODO(phajdan.jr): Give it a try to support CommandLine removing switches. 988#if defined(OS_WIN) 989 new_command_line.PrependWrapper(ASCIIToWide(wrapper)); 990#elif defined(OS_POSIX) 991 new_command_line.PrependWrapper(wrapper); 992#endif 993 994 return new_command_line; 995} 996 997int LaunchChildTestProcessWithOptions(const CommandLine& command_line, 998 const LaunchOptions& options, 999 base::TimeDelta timeout, 1000 bool* was_timeout) { 1001#if defined(OS_POSIX) 1002 // Make sure an option we rely on is present - see LaunchChildGTestProcess. 1003 DCHECK(options.new_process_group); 1004#endif 1005 1006 LaunchOptions new_options(options); 1007 1008#if defined(OS_WIN) 1009 DCHECK(!new_options.job_handle); 1010 1011 win::ScopedHandle job_handle(CreateJobObject(NULL, NULL)); 1012 if (!job_handle.IsValid()) { 1013 LOG(ERROR) << "Could not create JobObject."; 1014 return -1; 1015 } 1016 1017 // Allow break-away from job since sandbox and few other places rely on it 1018 // on Windows versions prior to Windows 8 (which supports nested jobs). 1019 // TODO(phajdan.jr): Do not allow break-away on Windows 8. 1020 if (!SetJobObjectLimitFlags(job_handle.Get(), 1021 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | 1022 JOB_OBJECT_LIMIT_BREAKAWAY_OK)) { 1023 LOG(ERROR) << "Could not SetJobObjectLimitFlags."; 1024 return -1; 1025 } 1026 1027 new_options.job_handle = job_handle.Get(); 1028#endif // defined(OS_WIN) 1029 1030#if defined(OS_LINUX) 1031 // To prevent accidental privilege sharing to an untrusted child, processes 1032 // are started with PR_SET_NO_NEW_PRIVS. Do not set that here, since this 1033 // new child will be privileged and trusted. 1034 new_options.allow_new_privs = true; 1035#endif 1036 1037 base::ProcessHandle process_handle; 1038 1039 { 1040 // Note how we grab the lock before the process possibly gets created. 1041 // This ensures that when the lock is held, ALL the processes are registered 1042 // in the set. 1043 AutoLock lock(g_live_processes_lock.Get()); 1044 1045 if (!base::LaunchProcess(command_line, new_options, &process_handle)) 1046 return -1; 1047 1048 g_live_processes.Get().insert(std::make_pair(process_handle, command_line)); 1049 } 1050 1051 int exit_code = 0; 1052 if (!base::WaitForExitCodeWithTimeout(process_handle, 1053 &exit_code, 1054 timeout)) { 1055 *was_timeout = true; 1056 exit_code = -1; // Set a non-zero exit code to signal a failure. 1057 1058 // Ensure that the process terminates. 1059 base::KillProcess(process_handle, -1, true); 1060 } 1061 1062 { 1063 // Note how we grab the log before issuing a possibly broad process kill. 1064 // Other code parts that grab the log kill processes, so avoid trying 1065 // to do that twice and trigger all kinds of log messages. 1066 AutoLock lock(g_live_processes_lock.Get()); 1067 1068#if defined(OS_POSIX) 1069 if (exit_code != 0) { 1070 // On POSIX, in case the test does not exit cleanly, either due to a crash 1071 // or due to it timing out, we need to clean up any child processes that 1072 // it might have created. On Windows, child processes are automatically 1073 // cleaned up using JobObjects. 1074 base::KillProcessGroup(process_handle); 1075 } 1076#endif 1077 1078 g_live_processes.Get().erase(process_handle); 1079 } 1080 1081 base::CloseProcessHandle(process_handle); 1082 1083 return exit_code; 1084} 1085 1086} // namespace base 1087