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