| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/test/launcher/test_launcher.h" | 5 #include "base/test/launcher/test_launcher.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/at_exit.h" | 9 #include "base/at_exit.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 // Avoids flooding the logs with amount of output that gums up | 90 // Avoids flooding the logs with amount of output that gums up |
| 91 // the infrastructure. | 91 // the infrastructure. |
| 92 const size_t kOutputSnippetLinesLimit = 5000; | 92 const size_t kOutputSnippetLinesLimit = 5000; |
| 93 | 93 |
| 94 // Limit of output snippet size. Exceeding this limit | 94 // Limit of output snippet size. Exceeding this limit |
| 95 // results in truncating the output and failing the test. | 95 // results in truncating the output and failing the test. |
| 96 const size_t kOutputSnippetBytesLimit = 300 * 1024; | 96 const size_t kOutputSnippetBytesLimit = 300 * 1024; |
| 97 | 97 |
| 98 // Set of live launch test processes with corresponding lock (it is allowed | 98 // Set of live launch test processes with corresponding lock (it is allowed |
| 99 // for callers to launch processes on different threads). | 99 // for callers to launch processes on different threads). |
| 100 LazyInstance<std::map<ProcessHandle, CommandLine>>::DestructorAtExit | 100 Lock* GetLiveProcessesLock() { |
| 101 g_live_processes = LAZY_INSTANCE_INITIALIZER; | 101 static auto* lock = new Lock; |
| 102 LazyInstance<Lock>::DestructorAtExit g_live_processes_lock = | 102 return lock; |
| 103 LAZY_INSTANCE_INITIALIZER; | 103 } |
| 104 |
| 105 std::map<ProcessHandle, CommandLine>* GetLiveProcesses() { |
| 106 static auto* map = new std::map<ProcessHandle, CommandLine>; |
| 107 return map; |
| 108 } |
| 104 | 109 |
| 105 // Performance trace generator. | 110 // Performance trace generator. |
| 106 LazyInstance<TestLauncherTracer>::DestructorAtExit g_tracer = | 111 TestLauncherTracer* GetTestLauncherTracer() { |
| 107 LAZY_INSTANCE_INITIALIZER; | 112 static auto* tracer = new TestLauncherTracer; |
| 113 return tracer; |
| 114 } |
| 108 | 115 |
| 109 #if defined(OS_POSIX) | 116 #if defined(OS_POSIX) |
| 110 // Self-pipe that makes it possible to do complex shutdown handling | 117 // Self-pipe that makes it possible to do complex shutdown handling |
| 111 // outside of the signal handler. | 118 // outside of the signal handler. |
| 112 int g_shutdown_pipe[2] = { -1, -1 }; | 119 int g_shutdown_pipe[2] = { -1, -1 }; |
| 113 | 120 |
| 114 void ShutdownPipeSignalHandler(int signal) { | 121 void ShutdownPipeSignalHandler(int signal) { |
| 115 HANDLE_EINTR(write(g_shutdown_pipe[1], "q", 1)); | 122 HANDLE_EINTR(write(g_shutdown_pipe[1], "q", 1)); |
| 116 } | 123 } |
| 117 | 124 |
| 118 void KillSpawnedTestProcesses() { | 125 void KillSpawnedTestProcesses() { |
| 119 // Keep the lock until exiting the process to prevent further processes | 126 // Keep the lock until exiting the process to prevent further processes |
| 120 // from being spawned. | 127 // from being spawned. |
| 121 AutoLock lock(g_live_processes_lock.Get()); | 128 AutoLock lock(*GetLiveProcessesLock()); |
| 122 | 129 |
| 123 fprintf(stdout, | 130 fprintf(stdout, "Sending SIGTERM to %" PRIuS " child processes... ", |
| 124 "Sending SIGTERM to %" PRIuS " child processes... ", | 131 GetLiveProcesses()->size()); |
| 125 g_live_processes.Get().size()); | |
| 126 fflush(stdout); | 132 fflush(stdout); |
| 127 | 133 |
| 128 for (std::map<ProcessHandle, CommandLine>::iterator i = | 134 for (const auto& pair : *GetLiveProcesses()) { |
| 129 g_live_processes.Get().begin(); | |
| 130 i != g_live_processes.Get().end(); | |
| 131 ++i) { | |
| 132 // Send the signal to entire process group. | 135 // Send the signal to entire process group. |
| 133 kill((-1) * (i->first), SIGTERM); | 136 kill((-1) * (pair.first), SIGTERM); |
| 134 } | 137 } |
| 135 | 138 |
| 136 fprintf(stdout, | 139 fprintf(stdout, |
| 137 "done.\nGiving processes a chance to terminate cleanly... "); | 140 "done.\nGiving processes a chance to terminate cleanly... "); |
| 138 fflush(stdout); | 141 fflush(stdout); |
| 139 | 142 |
| 140 PlatformThread::Sleep(TimeDelta::FromMilliseconds(500)); | 143 PlatformThread::Sleep(TimeDelta::FromMilliseconds(500)); |
| 141 | 144 |
| 142 fprintf(stdout, "done.\n"); | 145 fprintf(stdout, "done.\n"); |
| 143 fflush(stdout); | 146 fflush(stdout); |
| 144 | 147 |
| 145 fprintf(stdout, | 148 fprintf(stdout, "Sending SIGKILL to %" PRIuS " child processes... ", |
| 146 "Sending SIGKILL to %" PRIuS " child processes... ", | 149 GetLiveProcesses()->size()); |
| 147 g_live_processes.Get().size()); | |
| 148 fflush(stdout); | 150 fflush(stdout); |
| 149 | 151 |
| 150 for (std::map<ProcessHandle, CommandLine>::iterator i = | 152 for (const auto& pair : *GetLiveProcesses()) { |
| 151 g_live_processes.Get().begin(); | |
| 152 i != g_live_processes.Get().end(); | |
| 153 ++i) { | |
| 154 // Send the signal to entire process group. | 153 // Send the signal to entire process group. |
| 155 kill((-1) * (i->first), SIGKILL); | 154 kill((-1) * (pair.first), SIGKILL); |
| 156 } | 155 } |
| 157 | 156 |
| 158 fprintf(stdout, "done.\n"); | 157 fprintf(stdout, "done.\n"); |
| 159 fflush(stdout); | 158 fflush(stdout); |
| 160 } | 159 } |
| 161 | 160 |
| 162 // I/O watcher for the reading end of the self-pipe above. | 161 // I/O watcher for the reading end of the self-pipe above. |
| 163 // Terminates any launched child processes and exits the process. | 162 // Terminates any launched child processes and exits the process. |
| 164 void OnShutdownPipeReadable() { | 163 void OnShutdownPipeReadable() { |
| 165 fprintf(stdout, "\nCaught signal. Killing spawned test processes...\n"); | 164 fprintf(stdout, "\nCaught signal. Killing spawned test processes...\n"); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 // new child will be privileged and trusted. | 301 // new child will be privileged and trusted. |
| 303 new_options.allow_new_privs = true; | 302 new_options.allow_new_privs = true; |
| 304 #endif | 303 #endif |
| 305 | 304 |
| 306 Process process; | 305 Process process; |
| 307 | 306 |
| 308 { | 307 { |
| 309 // Note how we grab the lock before the process possibly gets created. | 308 // Note how we grab the lock before the process possibly gets created. |
| 310 // This ensures that when the lock is held, ALL the processes are registered | 309 // This ensures that when the lock is held, ALL the processes are registered |
| 311 // in the set. | 310 // in the set. |
| 312 AutoLock lock(g_live_processes_lock.Get()); | 311 AutoLock lock(*GetLiveProcessesLock()); |
| 313 | 312 |
| 314 #if defined(OS_WIN) | 313 #if defined(OS_WIN) |
| 315 // Allow the handle used to capture stdio and stdout to be inherited by the | 314 // Allow the handle used to capture stdio and stdout to be inherited by the |
| 316 // child. Note that this is done under g_live_processes_lock to ensure that | 315 // child. Note that this is done under GetLiveProcessesLock() to ensure that |
| 317 // only the desired child receives the handle. | 316 // only the desired child receives the handle. |
| 318 if (new_options.stdout_handle) { | 317 if (new_options.stdout_handle) { |
| 319 ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT, | 318 ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT, |
| 320 HANDLE_FLAG_INHERIT); | 319 HANDLE_FLAG_INHERIT); |
| 321 } | 320 } |
| 322 #endif | 321 #endif |
| 323 | 322 |
| 324 process = LaunchProcess(command_line, new_options); | 323 process = LaunchProcess(command_line, new_options); |
| 325 | 324 |
| 326 #if defined(OS_WIN) | 325 #if defined(OS_WIN) |
| 327 // Revoke inheritance so that the handle isn't leaked into other children. | 326 // Revoke inheritance so that the handle isn't leaked into other children. |
| 328 // Note that this is done under g_live_processes_lock to ensure that only | 327 // Note that this is done under GetLiveProcessesLock() to ensure that only |
| 329 // the desired child receives the handle. | 328 // the desired child receives the handle. |
| 330 if (new_options.stdout_handle) | 329 if (new_options.stdout_handle) |
| 331 ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT, 0); | 330 ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT, 0); |
| 332 #endif | 331 #endif |
| 333 | 332 |
| 334 if (!process.IsValid()) | 333 if (!process.IsValid()) |
| 335 return -1; | 334 return -1; |
| 336 | 335 |
| 337 // TODO(rvargas) crbug.com/417532: Don't store process handles. | 336 // TODO(rvargas) crbug.com/417532: Don't store process handles. |
| 338 g_live_processes.Get().insert(std::make_pair(process.Handle(), | 337 GetLiveProcesses()->insert(std::make_pair(process.Handle(), command_line)); |
| 339 command_line)); | |
| 340 } | 338 } |
| 341 | 339 |
| 342 if (!launched_callback.is_null()) | 340 if (!launched_callback.is_null()) |
| 343 launched_callback.Run(process.Handle(), process.Pid()); | 341 launched_callback.Run(process.Handle(), process.Pid()); |
| 344 | 342 |
| 345 int exit_code = 0; | 343 int exit_code = 0; |
| 346 if (!process.WaitForExitWithTimeout(timeout, &exit_code)) { | 344 if (!process.WaitForExitWithTimeout(timeout, &exit_code)) { |
| 347 *was_timeout = true; | 345 *was_timeout = true; |
| 348 exit_code = -1; // Set a non-zero exit code to signal a failure. | 346 exit_code = -1; // Set a non-zero exit code to signal a failure. |
| 349 | 347 |
| 350 // Ensure that the process terminates. | 348 // Ensure that the process terminates. |
| 351 process.Terminate(-1, true); | 349 process.Terminate(-1, true); |
| 352 } | 350 } |
| 353 | 351 |
| 354 { | 352 { |
| 355 // Note how we grab the log before issuing a possibly broad process kill. | 353 // Note how we grab the log before issuing a possibly broad process kill. |
| 356 // Other code parts that grab the log kill processes, so avoid trying | 354 // Other code parts that grab the log kill processes, so avoid trying |
| 357 // to do that twice and trigger all kinds of log messages. | 355 // to do that twice and trigger all kinds of log messages. |
| 358 AutoLock lock(g_live_processes_lock.Get()); | 356 AutoLock lock(*GetLiveProcessesLock()); |
| 359 | 357 |
| 360 #if defined(OS_POSIX) | 358 #if defined(OS_POSIX) |
| 361 if (exit_code != 0) { | 359 if (exit_code != 0) { |
| 362 // On POSIX, in case the test does not exit cleanly, either due to a crash | 360 // On POSIX, in case the test does not exit cleanly, either due to a crash |
| 363 // or due to it timing out, we need to clean up any child processes that | 361 // or due to it timing out, we need to clean up any child processes that |
| 364 // it might have created. On Windows, child processes are automatically | 362 // it might have created. On Windows, child processes are automatically |
| 365 // cleaned up using JobObjects. | 363 // cleaned up using JobObjects. |
| 366 KillProcessGroup(process.Handle()); | 364 KillProcessGroup(process.Handle()); |
| 367 } | 365 } |
| 368 #endif | 366 #endif |
| 369 | 367 |
| 370 g_live_processes.Get().erase(process.Handle()); | 368 GetLiveProcesses()->erase(process.Handle()); |
| 371 } | 369 } |
| 372 | 370 |
| 373 g_tracer.Get().RecordProcessExecution(start_time, | 371 GetTestLauncherTracer()->RecordProcessExecution( |
| 374 TimeTicks::Now() - start_time); | 372 start_time, TimeTicks::Now() - start_time); |
| 375 | 373 |
| 376 return exit_code; | 374 return exit_code; |
| 377 } | 375 } |
| 378 | 376 |
| 379 void RunCallback(const TestLauncher::GTestProcessCompletedCallback& callback, | 377 void RunCallback(const TestLauncher::GTestProcessCompletedCallback& callback, |
| 380 int exit_code, | 378 int exit_code, |
| 381 const TimeDelta& elapsed_time, | 379 const TimeDelta& elapsed_time, |
| 382 bool was_timeout, | 380 bool was_timeout, |
| 383 const std::string& output) { | 381 const std::string& output) { |
| 384 callback.Run(exit_code, elapsed_time, was_timeout, output); | 382 callback.Run(exit_code, elapsed_time, was_timeout, output); |
| (...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1107 if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) { | 1105 if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) { |
| 1108 FilePath summary_path(command_line->GetSwitchValuePath( | 1106 FilePath summary_path(command_line->GetSwitchValuePath( |
| 1109 switches::kTestLauncherSummaryOutput)); | 1107 switches::kTestLauncherSummaryOutput)); |
| 1110 if (!results_tracker_.SaveSummaryAsJSON(summary_path, additional_tags)) { | 1108 if (!results_tracker_.SaveSummaryAsJSON(summary_path, additional_tags)) { |
| 1111 LOG(ERROR) << "Failed to save test launcher output summary."; | 1109 LOG(ERROR) << "Failed to save test launcher output summary."; |
| 1112 } | 1110 } |
| 1113 } | 1111 } |
| 1114 if (command_line->HasSwitch(switches::kTestLauncherTrace)) { | 1112 if (command_line->HasSwitch(switches::kTestLauncherTrace)) { |
| 1115 FilePath trace_path( | 1113 FilePath trace_path( |
| 1116 command_line->GetSwitchValuePath(switches::kTestLauncherTrace)); | 1114 command_line->GetSwitchValuePath(switches::kTestLauncherTrace)); |
| 1117 if (!g_tracer.Get().Dump(trace_path)) { | 1115 if (!GetTestLauncherTracer()->Dump(trace_path)) { |
| 1118 LOG(ERROR) << "Failed to save test launcher trace."; | 1116 LOG(ERROR) << "Failed to save test launcher trace."; |
| 1119 } | 1117 } |
| 1120 } | 1118 } |
| 1121 } | 1119 } |
| 1122 | 1120 |
| 1123 void TestLauncher::OnLaunchTestProcessFinished( | 1121 void TestLauncher::OnLaunchTestProcessFinished( |
| 1124 const GTestProcessCompletedCallback& callback, | 1122 const GTestProcessCompletedCallback& callback, |
| 1125 int exit_code, | 1123 int exit_code, |
| 1126 const TimeDelta& elapsed_time, | 1124 const TimeDelta& elapsed_time, |
| 1127 bool was_timeout, | 1125 bool was_timeout, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1152 results_tracker_.PrintSummaryOfCurrentIteration(); | 1150 results_tracker_.PrintSummaryOfCurrentIteration(); |
| 1153 | 1151 |
| 1154 // Kick off the next iteration. | 1152 // Kick off the next iteration. |
| 1155 ThreadTaskRunnerHandle::Get()->PostTask( | 1153 ThreadTaskRunnerHandle::Get()->PostTask( |
| 1156 FROM_HERE, Bind(&TestLauncher::RunTestIteration, Unretained(this))); | 1154 FROM_HERE, Bind(&TestLauncher::RunTestIteration, Unretained(this))); |
| 1157 } | 1155 } |
| 1158 | 1156 |
| 1159 void TestLauncher::OnOutputTimeout() { | 1157 void TestLauncher::OnOutputTimeout() { |
| 1160 DCHECK(thread_checker_.CalledOnValidThread()); | 1158 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1161 | 1159 |
| 1162 AutoLock lock(g_live_processes_lock.Get()); | 1160 AutoLock lock(*GetLiveProcessesLock()); |
| 1163 | 1161 |
| 1164 fprintf(stdout, "Still waiting for the following processes to finish:\n"); | 1162 fprintf(stdout, "Still waiting for the following processes to finish:\n"); |
| 1165 | 1163 |
| 1166 for (std::map<ProcessHandle, CommandLine>::iterator i = | 1164 for (const auto& pair : *GetLiveProcesses()) { |
| 1167 g_live_processes.Get().begin(); | |
| 1168 i != g_live_processes.Get().end(); | |
| 1169 ++i) { | |
| 1170 #if defined(OS_WIN) | 1165 #if defined(OS_WIN) |
| 1171 fwprintf(stdout, L"\t%s\n", i->second.GetCommandLineString().c_str()); | 1166 fwprintf(stdout, L"\t%s\n", pair.second.GetCommandLineString().c_str()); |
| 1172 #else | 1167 #else |
| 1173 fprintf(stdout, "\t%s\n", i->second.GetCommandLineString().c_str()); | 1168 fprintf(stdout, "\t%s\n", pair.second.GetCommandLineString().c_str()); |
| 1174 #endif | 1169 #endif |
| 1175 } | 1170 } |
| 1176 | 1171 |
| 1177 fflush(stdout); | 1172 fflush(stdout); |
| 1178 | 1173 |
| 1179 // Arm the timer again - otherwise it would fire only once. | 1174 // Arm the timer again - otherwise it would fire only once. |
| 1180 watchdog_timer_.Reset(); | 1175 watchdog_timer_.Reset(); |
| 1181 } | 1176 } |
| 1182 | 1177 |
| 1183 scoped_refptr<TaskRunner> TestLauncher::GetTaskRunner() { | 1178 scoped_refptr<TaskRunner> TestLauncher::GetTaskRunner() { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1216 } | 1211 } |
| 1217 | 1212 |
| 1218 std::string snippet(full_output.substr(run_pos)); | 1213 std::string snippet(full_output.substr(run_pos)); |
| 1219 if (end_pos != std::string::npos) | 1214 if (end_pos != std::string::npos) |
| 1220 snippet = full_output.substr(run_pos, end_pos - run_pos); | 1215 snippet = full_output.substr(run_pos, end_pos - run_pos); |
| 1221 | 1216 |
| 1222 return snippet; | 1217 return snippet; |
| 1223 } | 1218 } |
| 1224 | 1219 |
| 1225 } // namespace base | 1220 } // namespace base |
| OLD | NEW |