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

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

Issue 55473002: GTTF: Unify parallel test launching. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: reupload Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « base/test/launcher/test_launcher.h ('k') | base/test/launcher/unit_test_launcher.cc » ('j') | 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/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/file_util.h" 15 #include "base/file_util.h"
16 #include "base/files/file_path.h" 16 #include "base/files/file_path.h"
17 #include "base/format_macros.h" 17 #include "base/format_macros.h"
18 #include "base/lazy_instance.h" 18 #include "base/lazy_instance.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h" 20 #include "base/memory/scoped_ptr.h"
21 #include "base/message_loop/message_loop.h" 21 #include "base/message_loop/message_loop.h"
22 #include "base/process/kill.h" 22 #include "base/process/kill.h"
23 #include "base/process/launch.h" 23 #include "base/process/launch.h"
24 #include "base/strings/string_number_conversions.h" 24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/stringprintf.h" 25 #include "base/strings/stringprintf.h"
26 #include "base/strings/utf_string_conversions.h" 26 #include "base/strings/utf_string_conversions.h"
27 #include "base/test/launcher/test_results_tracker.h" 27 #include "base/test/launcher/test_results_tracker.h"
28 #include "base/test/sequenced_worker_pool_owner.h"
28 #include "base/test/test_switches.h" 29 #include "base/test/test_switches.h"
29 #include "base/test/test_timeouts.h" 30 #include "base/test/test_timeouts.h"
30 #include "base/threading/thread_checker.h" 31 #include "base/threading/thread_checker.h"
31 #include "base/time/time.h" 32 #include "base/time/time.h"
32 #include "testing/gtest/include/gtest/gtest.h" 33 #include "testing/gtest/include/gtest/gtest.h"
33 34
34 #if defined(OS_MACOSX) 35 #if defined(OS_MACOSX)
35 #include "base/mac/scoped_nsautorelease_pool.h" 36 #include "base/mac/scoped_nsautorelease_pool.h"
36 #endif 37 #endif
37 38
38 namespace base { 39 namespace base {
39 40
40 // See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/u T3FaE_sgkAJ . 41 // See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/u T3FaE_sgkAJ .
41 using ::operator<<; 42 using ::operator<<;
42 43
43 // The environment variable name for the total number of test shards. 44 // The environment variable name for the total number of test shards.
44 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; 45 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
45 // The environment variable name for the test shard index. 46 // The environment variable name for the test shard index.
46 const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; 47 const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
47 48
48 namespace { 49 namespace {
49 50
51 // Maximum time of no output after which we print list of processes still
52 // running. This deliberately doesn't use TestTimeouts (which is otherwise
53 // a recommended solution), because they can be increased. This would defeat
54 // the purpose of this timeout, which is 1) to avoid buildbot "no output for
55 // X seconds" timeout killing the process 2) help communicate status of
56 // the test launcher to people looking at the output (no output for a long
57 // time is mysterious and gives no info about what is happening) 3) help
58 // debugging in case the process hangs anyway.
59 const int kOutputTimeoutSeconds = 15;
60
50 // Set of live launch test processes with corresponding lock (it is allowed 61 // Set of live launch test processes with corresponding lock (it is allowed
51 // for callers to launch processes on different threads). 62 // for callers to launch processes on different threads).
52 LazyInstance<std::set<ProcessHandle> > g_live_process_handles 63 LazyInstance<std::map<ProcessHandle, CommandLine> > g_live_processes
53 = LAZY_INSTANCE_INITIALIZER; 64 = LAZY_INSTANCE_INITIALIZER;
54 LazyInstance<Lock> g_live_process_handles_lock = LAZY_INSTANCE_INITIALIZER; 65 LazyInstance<Lock> g_live_processes_lock = LAZY_INSTANCE_INITIALIZER;
55 66
56 #if defined(OS_POSIX) 67 #if defined(OS_POSIX)
57 // Self-pipe that makes it possible to do complex shutdown handling 68 // Self-pipe that makes it possible to do complex shutdown handling
58 // outside of the signal handler. 69 // outside of the signal handler.
59 int g_shutdown_pipe[2] = { -1, -1 }; 70 int g_shutdown_pipe[2] = { -1, -1 };
60 71
61 void ShutdownPipeSignalHandler(int signal) { 72 void ShutdownPipeSignalHandler(int signal) {
62 HANDLE_EINTR(write(g_shutdown_pipe[1], "q", 1)); 73 HANDLE_EINTR(write(g_shutdown_pipe[1], "q", 1));
63 } 74 }
64 75
65 void KillSpawnedTestProcesses() { 76 void KillSpawnedTestProcesses() {
66 // Keep the lock until exiting the process to prevent further processes 77 // Keep the lock until exiting the process to prevent further processes
67 // from being spawned. 78 // from being spawned.
68 AutoLock lock(g_live_process_handles_lock.Get()); 79 AutoLock lock(g_live_processes_lock.Get());
69 80
70 fprintf(stdout, 81 fprintf(stdout,
71 "Sending SIGTERM to %" PRIuS " child processes... ", 82 "Sending SIGTERM to %" PRIuS " child processes... ",
72 g_live_process_handles.Get().size()); 83 g_live_processes.Get().size());
73 fflush(stdout); 84 fflush(stdout);
74 85
75 for (std::set<ProcessHandle>::iterator i = 86 for (std::map<ProcessHandle, CommandLine>::iterator i =
76 g_live_process_handles.Get().begin(); 87 g_live_processes.Get().begin();
77 i != g_live_process_handles.Get().end(); 88 i != g_live_processes.Get().end();
78 ++i) { 89 ++i) {
79 kill((-1) * (*i), SIGTERM); // Send the signal to entire process group. 90 // Send the signal to entire process group.
91 kill((-1) * (i->first), SIGTERM);
80 } 92 }
81 93
82 fprintf(stdout, 94 fprintf(stdout,
83 "done.\nGiving processes a chance to terminate cleanly... "); 95 "done.\nGiving processes a chance to terminate cleanly... ");
84 fflush(stdout); 96 fflush(stdout);
85 97
86 PlatformThread::Sleep(TimeDelta::FromMilliseconds(500)); 98 PlatformThread::Sleep(TimeDelta::FromMilliseconds(500));
87 99
88 fprintf(stdout, "done.\n"); 100 fprintf(stdout, "done.\n");
89 fflush(stdout); 101 fflush(stdout);
90 102
91 fprintf(stdout, 103 fprintf(stdout,
92 "Sending SIGKILL to %" PRIuS " child processes... ", 104 "Sending SIGKILL to %" PRIuS " child processes... ",
93 g_live_process_handles.Get().size()); 105 g_live_processes.Get().size());
94 fflush(stdout); 106 fflush(stdout);
95 107
96 for (std::set<ProcessHandle>::iterator i = 108 for (std::map<ProcessHandle, CommandLine>::iterator i =
97 g_live_process_handles.Get().begin(); 109 g_live_processes.Get().begin();
98 i != g_live_process_handles.Get().end(); 110 i != g_live_processes.Get().end();
99 ++i) { 111 ++i) {
100 kill((-1) * (*i), SIGKILL); // Send the signal to entire process group. 112 // Send the signal to entire process group.
113 kill((-1) * (i->first), SIGKILL);
101 } 114 }
102 115
103 fprintf(stdout, "done.\n"); 116 fprintf(stdout, "done.\n");
104 fflush(stdout); 117 fflush(stdout);
105 } 118 }
106 119
107 // I/O watcher for the reading end of the self-pipe above. 120 // I/O watcher for the reading end of the self-pipe above.
108 // Terminates any launched child processes and exits the process. 121 // Terminates any launched child processes and exits the process.
109 class SignalFDWatcher : public MessageLoopForIO::Watcher { 122 class SignalFDWatcher : public MessageLoopForIO::Watcher {
110 public: 123 public:
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 // Returns if no more pattern can be found. 200 // Returns if no more pattern can be found.
188 if (cur_pattern == NULL) { 201 if (cur_pattern == NULL) {
189 return false; 202 return false;
190 } 203 }
191 204
192 // Skips the pattern separater (the ':' character). 205 // Skips the pattern separater (the ':' character).
193 cur_pattern++; 206 cur_pattern++;
194 } 207 }
195 } 208 }
196 209
210 void RunCallback(
211 const TestLauncher::LaunchChildGTestProcessCallback& callback,
212 int exit_code,
213 const TimeDelta& elapsed_time,
214 bool was_timeout,
215 const std::string& output) {
216 callback.Run(exit_code, elapsed_time, was_timeout, output);
217 }
218
219 void DoLaunchChildTestProcess(
220 const CommandLine& command_line,
221 base::TimeDelta timeout,
222 scoped_refptr<MessageLoopProxy> message_loop_proxy,
223 const TestLauncher::LaunchChildGTestProcessCallback& callback) {
224 TimeTicks start_time = TimeTicks::Now();
225
226 // Redirect child process output to a file.
227 base::FilePath output_file;
228 CHECK(file_util::CreateTemporaryFile(&output_file));
229
230 LaunchOptions options;
231 #if defined(OS_WIN)
232 // Make the file handle inheritable by the child.
233 SECURITY_ATTRIBUTES sa_attr;
234 sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
235 sa_attr.lpSecurityDescriptor = NULL;
236 sa_attr.bInheritHandle = TRUE;
237
238 win::ScopedHandle handle(CreateFile(output_file.value().c_str(),
239 GENERIC_WRITE,
240 FILE_SHARE_READ | FILE_SHARE_DELETE,
241 &sa_attr,
242 OPEN_EXISTING,
243 FILE_ATTRIBUTE_TEMPORARY,
244 NULL));
245 CHECK(handle.IsValid());
246 options.inherit_handles = true;
247 options.stdin_handle = INVALID_HANDLE_VALUE;
248 options.stdout_handle = handle.Get();
249 options.stderr_handle = handle.Get();
250 #elif defined(OS_POSIX)
251 options.new_process_group = true;
252
253 int output_file_fd = open(output_file.value().c_str(), O_RDWR);
254 CHECK_GE(output_file_fd, 0);
255
256 file_util::ScopedFD output_file_fd_closer(&output_file_fd);
257
258 base::FileHandleMappingVector fds_mapping;
259 fds_mapping.push_back(std::make_pair(output_file_fd, STDOUT_FILENO));
260 fds_mapping.push_back(std::make_pair(output_file_fd, STDERR_FILENO));
261 options.fds_to_remap = &fds_mapping;
262 #endif
263
264 bool was_timeout = false;
265 int exit_code = LaunchChildTestProcessWithOptions(
266 command_line, options, timeout, &was_timeout);
267
268 #if defined(OS_WIN)
269 FlushFileBuffers(handle.Get());
270 handle.Close();
271 #elif defined(OS_POSIX)
272 output_file_fd_closer.reset();
273 #endif
274
275 std::string output_file_contents;
276 CHECK(base::ReadFileToString(output_file, &output_file_contents));
277
278 if (!base::DeleteFile(output_file, false)) {
279 // This needs to be non-fatal at least for Windows.
280 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe();
281 }
282
283 // Run target callback on the thread it was originating from, not on
284 // a worker pool thread.
285 message_loop_proxy->PostTask(
286 FROM_HERE,
287 Bind(&RunCallback,
288 callback,
289 exit_code,
290 TimeTicks::Now() - start_time,
291 was_timeout,
292 output_file_contents));
293 }
294
197 } // namespace 295 } // namespace
198 296
199 const char kGTestFilterFlag[] = "gtest_filter"; 297 const char kGTestFilterFlag[] = "gtest_filter";
200 const char kGTestHelpFlag[] = "gtest_help"; 298 const char kGTestHelpFlag[] = "gtest_help";
201 const char kGTestListTestsFlag[] = "gtest_list_tests"; 299 const char kGTestListTestsFlag[] = "gtest_list_tests";
202 const char kGTestRepeatFlag[] = "gtest_repeat"; 300 const char kGTestRepeatFlag[] = "gtest_repeat";
203 const char kGTestRunDisabledTestsFlag[] = "gtest_also_run_disabled_tests"; 301 const char kGTestRunDisabledTestsFlag[] = "gtest_also_run_disabled_tests";
204 const char kGTestOutputFlag[] = "gtest_output"; 302 const char kGTestOutputFlag[] = "gtest_output";
205 303
206 TestLauncherDelegate::~TestLauncherDelegate() { 304 TestLauncherDelegate::~TestLauncherDelegate() {
207 } 305 }
208 306
209 TestLauncher::TestLauncher(TestLauncherDelegate* launcher_delegate) 307 TestLauncher::TestLauncher(TestLauncherDelegate* launcher_delegate,
308 size_t parallel_jobs)
210 : launcher_delegate_(launcher_delegate), 309 : launcher_delegate_(launcher_delegate),
211 total_shards_(1), 310 total_shards_(1),
212 shard_index_(0), 311 shard_index_(0),
213 cycles_(1), 312 cycles_(1),
214 test_started_count_(0), 313 test_started_count_(0),
215 test_finished_count_(0), 314 test_finished_count_(0),
216 test_success_count_(0), 315 test_success_count_(0),
217 test_broken_count_(0), 316 test_broken_count_(0),
218 retry_count_(0), 317 retry_count_(0),
219 retry_limit_(3), // TODO(phajdan.jr): Make a flag control this. 318 retry_limit_(3), // TODO(phajdan.jr): Make a flag control this.
220 run_result_(true) { 319 run_result_(true),
320 watchdog_timer_(FROM_HERE,
321 TimeDelta::FromSeconds(kOutputTimeoutSeconds),
322 this,
323 &TestLauncher::OnOutputTimeout),
324 worker_pool_owner_(
325 new SequencedWorkerPoolOwner(parallel_jobs, "test_launcher")) {
221 } 326 }
222 327
223 TestLauncher::~TestLauncher() { 328 TestLauncher::~TestLauncher() {
329 worker_pool_owner_->pool()->Shutdown();
224 } 330 }
225 331
226 bool TestLauncher::Run(int argc, char** argv) { 332 bool TestLauncher::Run(int argc, char** argv) {
227 if (!Init()) 333 if (!Init())
228 return false; 334 return false;
229 335
230 #if defined(OS_POSIX) 336 #if defined(OS_POSIX)
231 CHECK_EQ(0, pipe(g_shutdown_pipe)); 337 CHECK_EQ(0, pipe(g_shutdown_pipe));
232 338
233 struct sigaction action; 339 struct sigaction action;
234 memset(&action, 0, sizeof(action)); 340 memset(&action, 0, sizeof(action));
235 sigemptyset(&action.sa_mask); 341 sigemptyset(&action.sa_mask);
236 action.sa_handler = &ShutdownPipeSignalHandler; 342 action.sa_handler = &ShutdownPipeSignalHandler;
237 343
238 CHECK_EQ(0, sigaction(SIGINT, &action, NULL)); 344 CHECK_EQ(0, sigaction(SIGINT, &action, NULL));
239 CHECK_EQ(0, sigaction(SIGQUIT, &action, NULL)); 345 CHECK_EQ(0, sigaction(SIGQUIT, &action, NULL));
240 CHECK_EQ(0, sigaction(SIGTERM, &action, NULL)); 346 CHECK_EQ(0, sigaction(SIGTERM, &action, NULL));
241 347
242 MessageLoopForIO::FileDescriptorWatcher controller; 348 MessageLoopForIO::FileDescriptorWatcher controller;
243 SignalFDWatcher watcher; 349 SignalFDWatcher watcher;
244 350
245 CHECK(MessageLoopForIO::current()->WatchFileDescriptor( 351 CHECK(MessageLoopForIO::current()->WatchFileDescriptor(
246 g_shutdown_pipe[0], 352 g_shutdown_pipe[0],
247 true, 353 true,
248 MessageLoopForIO::WATCH_READ, 354 MessageLoopForIO::WATCH_READ,
249 &controller, 355 &controller,
250 &watcher)); 356 &watcher));
251 #endif // defined(OS_POSIX) 357 #endif // defined(OS_POSIX)
252 358
359 // Start the watchdog timer.
360 watchdog_timer_.Reset();
361
253 MessageLoop::current()->PostTask( 362 MessageLoop::current()->PostTask(
254 FROM_HERE, 363 FROM_HERE,
255 Bind(&TestLauncher::RunTestIteration, Unretained(this))); 364 Bind(&TestLauncher::RunTestIteration, Unretained(this)));
256 365
257 MessageLoop::current()->Run(); 366 MessageLoop::current()->Run();
258 367
259 if (cycles_ != 1) 368 if (cycles_ != 1)
260 results_tracker_.PrintSummaryOfAllIterations(); 369 results_tracker_.PrintSummaryOfAllIterations();
261 370
262 MaybeSaveSummaryAsJSON(); 371 MaybeSaveSummaryAsJSON();
263 372
264 return run_result_; 373 return run_result_;
265 } 374 }
266 375
376 void TestLauncher::LaunchChildGTestProcess(
377 const CommandLine& command_line,
378 const std::string& wrapper,
379 base::TimeDelta timeout,
380 const LaunchChildGTestProcessCallback& callback) {
381 DCHECK(thread_checker_.CalledOnValidThread());
382
383 // Record the exact command line used to launch the child.
384 CommandLine new_command_line(
385 PrepareCommandLineForGTest(command_line, wrapper));
386
387 worker_pool_owner_->pool()->PostWorkerTask(
388 FROM_HERE,
389 Bind(&DoLaunchChildTestProcess,
390 new_command_line,
391 timeout,
392 MessageLoopProxy::current(),
393 Bind(&TestLauncher::OnLaunchTestProcessFinished,
394 Unretained(this),
395 callback)));
396 }
397
267 void TestLauncher::OnTestFinished(const TestResult& result) { 398 void TestLauncher::OnTestFinished(const TestResult& result) {
268 ++test_finished_count_; 399 ++test_finished_count_;
269 400
270 bool print_snippet = false; 401 bool print_snippet = false;
271 std::string print_test_stdio("auto"); 402 std::string print_test_stdio("auto");
272 if (CommandLine::ForCurrentProcess()->HasSwitch( 403 if (CommandLine::ForCurrentProcess()->HasSwitch(
273 switches::kTestLauncherPrintTestStdio)) { 404 switches::kTestLauncherPrintTestStdio)) {
274 print_test_stdio = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 405 print_test_stdio = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
275 switches::kTestLauncherPrintTestStdio); 406 switches::kTestLauncherPrintTestStdio);
276 } 407 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 status_line.append("(SKIPPED)"); 445 status_line.append("(SKIPPED)");
315 } else if (result.status == TestResult::TEST_UNKNOWN) { 446 } else if (result.status == TestResult::TEST_UNKNOWN) {
316 status_line.append("(UNKNOWN)"); 447 status_line.append("(UNKNOWN)");
317 } else { 448 } else {
318 // Fail very loudly so it's not ignored. 449 // Fail very loudly so it's not ignored.
319 CHECK(false) << "Unhandled test result status: " << result.status; 450 CHECK(false) << "Unhandled test result status: " << result.status;
320 } 451 }
321 fprintf(stdout, "%s\n", status_line.c_str()); 452 fprintf(stdout, "%s\n", status_line.c_str());
322 fflush(stdout); 453 fflush(stdout);
323 454
455 // We just printed a status line, reset the watchdog timer.
456 watchdog_timer_.Reset();
457
324 if (test_finished_count_ == test_started_count_) { 458 if (test_finished_count_ == test_started_count_) {
325 if (!tests_to_retry_.empty() && retry_count_ < retry_limit_) { 459 if (!tests_to_retry_.empty() && retry_count_ < retry_limit_) {
326 retry_count_++; 460 retry_count_++;
327 461
328 std::vector<std::string> test_names(tests_to_retry_.begin(), 462 std::vector<std::string> test_names(tests_to_retry_.begin(),
329 tests_to_retry_.end()); 463 tests_to_retry_.end());
330 464
331 tests_to_retry_.clear(); 465 tests_to_retry_.clear();
332 466
333 size_t retry_started_count = 467 size_t retry_started_count =
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 test_broken_count_ = 0; 664 test_broken_count_ = 0;
531 retry_count_ = 0; 665 retry_count_ = 0;
532 tests_to_retry_.clear(); 666 tests_to_retry_.clear();
533 results_tracker_.OnTestIterationStarting(); 667 results_tracker_.OnTestIterationStarting();
534 launcher_delegate_->OnTestIterationStarting(); 668 launcher_delegate_->OnTestIterationStarting();
535 669
536 MessageLoop::current()->PostTask( 670 MessageLoop::current()->PostTask(
537 FROM_HERE, Bind(&TestLauncher::RunTests, Unretained(this))); 671 FROM_HERE, Bind(&TestLauncher::RunTests, Unretained(this)));
538 } 672 }
539 673
540 void TestLauncher::OnAllTestsStarted() {
541 }
542
543 void TestLauncher::MaybeSaveSummaryAsJSON() { 674 void TestLauncher::MaybeSaveSummaryAsJSON() {
544 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 675 const CommandLine* command_line = CommandLine::ForCurrentProcess();
545 if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) { 676 if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) {
546 FilePath summary_path(command_line->GetSwitchValuePath( 677 FilePath summary_path(command_line->GetSwitchValuePath(
547 switches::kTestLauncherSummaryOutput)); 678 switches::kTestLauncherSummaryOutput));
548 if (!results_tracker_.SaveSummaryAsJSON(summary_path)) { 679 if (!results_tracker_.SaveSummaryAsJSON(summary_path)) {
549 LOG(ERROR) << "Failed to save test launcher output summary."; 680 LOG(ERROR) << "Failed to save test launcher output summary.";
550 } 681 }
551 } 682 }
552 } 683 }
553 684
685 void TestLauncher::OnLaunchTestProcessFinished(
686 const LaunchChildGTestProcessCallback& callback,
687 int exit_code,
688 const TimeDelta& elapsed_time,
689 bool was_timeout,
690 const std::string& output) {
691 DCHECK(thread_checker_.CalledOnValidThread());
692
693 callback.Run(exit_code, elapsed_time, was_timeout, output);
694 }
695
696 void TestLauncher::OnOutputTimeout() {
697 DCHECK(thread_checker_.CalledOnValidThread());
698
699 AutoLock lock(g_live_processes_lock.Get());
700
701 fprintf(stdout, "Still waiting for the following processes to finish:\n");
702
703 for (std::map<ProcessHandle, CommandLine>::iterator i =
704 g_live_processes.Get().begin();
705 i != g_live_processes.Get().end();
706 ++i) {
707 #if defined(OS_WIN)
708 fwprintf(stdout, L"\t%s\n", i->second.GetCommandLineString().c_str());
709 #else
710 fprintf(stdout, "\t%s\n", i->second.GetCommandLineString().c_str());
711 #endif
712 }
713
714 fflush(stdout);
715
716 // Arm the timer again - otherwise it would fire only once.
717 watchdog_timer_.Reset();
718 }
719
554 std::string GetTestOutputSnippet(const TestResult& result, 720 std::string GetTestOutputSnippet(const TestResult& result,
555 const std::string& full_output) { 721 const std::string& full_output) {
556 size_t run_pos = full_output.find(std::string("[ RUN ] ") + 722 size_t run_pos = full_output.find(std::string("[ RUN ] ") +
557 result.full_name); 723 result.full_name);
558 if (run_pos == std::string::npos) 724 if (run_pos == std::string::npos)
559 return std::string(); 725 return std::string();
560 726
561 size_t end_pos = full_output.find(std::string("[ FAILED ] ") + 727 size_t end_pos = full_output.find(std::string("[ FAILED ] ") +
562 result.full_name, 728 result.full_name,
563 run_pos); 729 run_pos);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 824
659 new_options.job_handle = job_handle.Get(); 825 new_options.job_handle = job_handle.Get();
660 #endif // defined(OS_WIN) 826 #endif // defined(OS_WIN)
661 827
662 base::ProcessHandle process_handle; 828 base::ProcessHandle process_handle;
663 829
664 { 830 {
665 // Note how we grab the lock before the process possibly gets created. 831 // Note how we grab the lock before the process possibly gets created.
666 // This ensures that when the lock is held, ALL the processes are registered 832 // This ensures that when the lock is held, ALL the processes are registered
667 // in the set. 833 // in the set.
668 AutoLock lock(g_live_process_handles_lock.Get()); 834 AutoLock lock(g_live_processes_lock.Get());
669 835
670 if (!base::LaunchProcess(command_line, new_options, &process_handle)) 836 if (!base::LaunchProcess(command_line, new_options, &process_handle))
671 return -1; 837 return -1;
672 838
673 g_live_process_handles.Get().insert(process_handle); 839 g_live_processes.Get().insert(std::make_pair(process_handle, command_line));
674 } 840 }
675 841
676 int exit_code = 0; 842 int exit_code = 0;
677 if (!base::WaitForExitCodeWithTimeout(process_handle, 843 if (!base::WaitForExitCodeWithTimeout(process_handle,
678 &exit_code, 844 &exit_code,
679 timeout)) { 845 timeout)) {
680 *was_timeout = true; 846 *was_timeout = true;
681 exit_code = -1; // Set a non-zero exit code to signal a failure. 847 exit_code = -1; // Set a non-zero exit code to signal a failure.
682 848
683 // Ensure that the process terminates. 849 // Ensure that the process terminates.
684 base::KillProcess(process_handle, -1, true); 850 base::KillProcess(process_handle, -1, true);
685 } 851 }
686 852
687 { 853 {
688 // Note how we grab the log before issuing a possibly broad process kill. 854 // Note how we grab the log before issuing a possibly broad process kill.
689 // Other code parts that grab the log kill processes, so avoid trying 855 // Other code parts that grab the log kill processes, so avoid trying
690 // to do that twice and trigger all kinds of log messages. 856 // to do that twice and trigger all kinds of log messages.
691 AutoLock lock(g_live_process_handles_lock.Get()); 857 AutoLock lock(g_live_processes_lock.Get());
692 858
693 #if defined(OS_POSIX) 859 #if defined(OS_POSIX)
694 if (exit_code != 0) { 860 if (exit_code != 0) {
695 // On POSIX, in case the test does not exit cleanly, either due to a crash 861 // On POSIX, in case the test does not exit cleanly, either due to a crash
696 // or due to it timing out, we need to clean up any child processes that 862 // or due to it timing out, we need to clean up any child processes that
697 // it might have created. On Windows, child processes are automatically 863 // it might have created. On Windows, child processes are automatically
698 // cleaned up using JobObjects. 864 // cleaned up using JobObjects.
699 base::KillProcessGroup(process_handle); 865 base::KillProcessGroup(process_handle);
700 } 866 }
701 #endif 867 #endif
702 868
703 g_live_process_handles.Get().erase(process_handle); 869 g_live_processes.Get().erase(process_handle);
704 } 870 }
705 871
706 base::CloseProcessHandle(process_handle); 872 base::CloseProcessHandle(process_handle);
707 873
708 return exit_code; 874 return exit_code;
709 } 875 }
710 876
711 } // namespace base 877 } // namespace base
OLDNEW
« no previous file with comments | « base/test/launcher/test_launcher.h ('k') | base/test/launcher/unit_test_launcher.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698