OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/test/launcher/test_launcher.h" | 5 #include "base/test/launcher/test_launcher.h" |
6 | 6 |
7 #if defined(OS_POSIX) | 7 #if defined(OS_POSIX) |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 30 matching lines...) Expand all Loading... |
41 #include "base/mac/scoped_nsautorelease_pool.h" | 41 #include "base/mac/scoped_nsautorelease_pool.h" |
42 #endif | 42 #endif |
43 | 43 |
44 namespace base { | 44 namespace base { |
45 | 45 |
46 // Launches a child process using |command_line|. If the child process is still | 46 // Launches a child process using |command_line|. If the child process is still |
47 // running after |timeout|, it is terminated and |*was_timeout| is set to true. | 47 // running after |timeout|, it is terminated and |*was_timeout| is set to true. |
48 // Returns exit code of the process. | 48 // Returns exit code of the process. |
49 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, | 49 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, |
50 const LaunchOptions& options, | 50 const LaunchOptions& options, |
51 bool use_job_objects, | 51 int flags, |
52 base::TimeDelta timeout, | 52 base::TimeDelta timeout, |
53 bool* was_timeout); | 53 bool* was_timeout); |
54 | 54 |
55 // See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/u
T3FaE_sgkAJ . | 55 // See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/u
T3FaE_sgkAJ . |
56 using ::operator<<; | 56 using ::operator<<; |
57 | 57 |
58 // The environment variable name for the total number of test shards. | 58 // The environment variable name for the total number of test shards. |
59 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; | 59 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; |
60 // The environment variable name for the test shard index. | 60 // The environment variable name for the test shard index. |
61 const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; | 61 const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 int exit_code, | 216 int exit_code, |
217 const TimeDelta& elapsed_time, | 217 const TimeDelta& elapsed_time, |
218 bool was_timeout, | 218 bool was_timeout, |
219 const std::string& output) { | 219 const std::string& output) { |
220 callback.Run(exit_code, elapsed_time, was_timeout, output); | 220 callback.Run(exit_code, elapsed_time, was_timeout, output); |
221 } | 221 } |
222 | 222 |
223 void DoLaunchChildTestProcess( | 223 void DoLaunchChildTestProcess( |
224 const CommandLine& command_line, | 224 const CommandLine& command_line, |
225 base::TimeDelta timeout, | 225 base::TimeDelta timeout, |
226 bool use_job_objects, | 226 int flags, |
227 bool redirect_stdio, | 227 bool redirect_stdio, |
228 scoped_refptr<MessageLoopProxy> message_loop_proxy, | 228 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
229 const TestLauncher::LaunchChildGTestProcessCallback& callback) { | 229 const TestLauncher::LaunchChildGTestProcessCallback& callback) { |
230 TimeTicks start_time = TimeTicks::Now(); | 230 TimeTicks start_time = TimeTicks::Now(); |
231 | 231 |
232 // Redirect child process output to a file. | 232 // Redirect child process output to a file. |
233 base::FilePath output_file; | 233 base::FilePath output_file; |
234 CHECK(base::CreateTemporaryFile(&output_file)); | 234 CHECK(base::CreateTemporaryFile(&output_file)); |
235 | 235 |
236 LaunchOptions options; | 236 LaunchOptions options; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 CHECK(output_file_fd.is_valid()); | 268 CHECK(output_file_fd.is_valid()); |
269 | 269 |
270 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDOUT_FILENO)); | 270 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDOUT_FILENO)); |
271 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDERR_FILENO)); | 271 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDERR_FILENO)); |
272 options.fds_to_remap = &fds_mapping; | 272 options.fds_to_remap = &fds_mapping; |
273 } | 273 } |
274 #endif | 274 #endif |
275 | 275 |
276 bool was_timeout = false; | 276 bool was_timeout = false; |
277 int exit_code = LaunchChildTestProcessWithOptions( | 277 int exit_code = LaunchChildTestProcessWithOptions( |
278 command_line, options, use_job_objects, timeout, &was_timeout); | 278 command_line, options, flags, timeout, &was_timeout); |
279 | 279 |
280 if (redirect_stdio) { | 280 if (redirect_stdio) { |
281 #if defined(OS_WIN) | 281 #if defined(OS_WIN) |
282 FlushFileBuffers(handle.Get()); | 282 FlushFileBuffers(handle.Get()); |
283 handle.Close(); | 283 handle.Close(); |
284 #elif defined(OS_POSIX) | 284 #elif defined(OS_POSIX) |
285 output_file_fd.reset(); | 285 output_file_fd.reset(); |
286 #endif | 286 #endif |
287 } | 287 } |
288 | 288 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 | 402 |
403 MaybeSaveSummaryAsJSON(); | 403 MaybeSaveSummaryAsJSON(); |
404 | 404 |
405 return run_result_; | 405 return run_result_; |
406 } | 406 } |
407 | 407 |
408 void TestLauncher::LaunchChildGTestProcess( | 408 void TestLauncher::LaunchChildGTestProcess( |
409 const CommandLine& command_line, | 409 const CommandLine& command_line, |
410 const std::string& wrapper, | 410 const std::string& wrapper, |
411 base::TimeDelta timeout, | 411 base::TimeDelta timeout, |
412 bool use_job_objects, | 412 int flags, |
413 const LaunchChildGTestProcessCallback& callback) { | 413 const LaunchChildGTestProcessCallback& callback) { |
414 DCHECK(thread_checker_.CalledOnValidThread()); | 414 DCHECK(thread_checker_.CalledOnValidThread()); |
415 | 415 |
416 // Record the exact command line used to launch the child. | 416 // Record the exact command line used to launch the child. |
417 CommandLine new_command_line( | 417 CommandLine new_command_line( |
418 PrepareCommandLineForGTest(command_line, wrapper)); | 418 PrepareCommandLineForGTest(command_line, wrapper)); |
419 | 419 |
420 // When running in parallel mode we need to redirect stdio to avoid mixed-up | 420 // When running in parallel mode we need to redirect stdio to avoid mixed-up |
421 // output. We also always redirect on the bots to get the test output into | 421 // output. We also always redirect on the bots to get the test output into |
422 // JSON summary. | 422 // JSON summary. |
423 bool redirect_stdio = (parallel_jobs_ > 1) || BotModeEnabled(); | 423 bool redirect_stdio = (parallel_jobs_ > 1) || BotModeEnabled(); |
424 | 424 |
425 worker_pool_owner_->pool()->PostWorkerTask( | 425 worker_pool_owner_->pool()->PostWorkerTask( |
426 FROM_HERE, | 426 FROM_HERE, |
427 Bind(&DoLaunchChildTestProcess, | 427 Bind(&DoLaunchChildTestProcess, |
428 new_command_line, | 428 new_command_line, |
429 timeout, | 429 timeout, |
430 use_job_objects, | 430 flags, |
431 redirect_stdio, | 431 redirect_stdio, |
432 MessageLoopProxy::current(), | 432 MessageLoopProxy::current(), |
433 Bind(&TestLauncher::OnLaunchTestProcessFinished, | 433 Bind(&TestLauncher::OnLaunchTestProcessFinished, |
434 Unretained(this), | 434 Unretained(this), |
435 callback))); | 435 callback))); |
436 } | 436 } |
437 | 437 |
438 void TestLauncher::OnTestFinished(const TestResult& result) { | 438 void TestLauncher::OnTestFinished(const TestResult& result) { |
439 ++test_finished_count_; | 439 ++test_finished_count_; |
440 | 440 |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 #elif defined(OS_POSIX) | 1002 #elif defined(OS_POSIX) |
1003 new_command_line.PrependWrapper(wrapper); | 1003 new_command_line.PrependWrapper(wrapper); |
1004 #endif | 1004 #endif |
1005 | 1005 |
1006 return new_command_line; | 1006 return new_command_line; |
1007 } | 1007 } |
1008 | 1008 |
1009 // TODO(phajdan.jr): Move to anonymous namespace. | 1009 // TODO(phajdan.jr): Move to anonymous namespace. |
1010 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, | 1010 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, |
1011 const LaunchOptions& options, | 1011 const LaunchOptions& options, |
1012 bool use_job_objects, | 1012 int flags, |
1013 base::TimeDelta timeout, | 1013 base::TimeDelta timeout, |
1014 bool* was_timeout) { | 1014 bool* was_timeout) { |
1015 #if defined(OS_POSIX) | 1015 #if defined(OS_POSIX) |
1016 // Make sure an option we rely on is present - see LaunchChildGTestProcess. | 1016 // Make sure an option we rely on is present - see LaunchChildGTestProcess. |
1017 DCHECK(options.new_process_group); | 1017 DCHECK(options.new_process_group); |
1018 #endif | 1018 #endif |
1019 | 1019 |
1020 LaunchOptions new_options(options); | 1020 LaunchOptions new_options(options); |
1021 | 1021 |
1022 #if defined(OS_WIN) | 1022 #if defined(OS_WIN) |
1023 DCHECK(!new_options.job_handle); | 1023 DCHECK(!new_options.job_handle); |
1024 | 1024 |
1025 win::ScopedHandle job_handle; | 1025 win::ScopedHandle job_handle; |
1026 if (use_job_objects) { | 1026 if (flags & TestLauncher::USE_JOB_OBJECTS) { |
1027 job_handle.Set(CreateJobObject(NULL, NULL)); | 1027 job_handle.Set(CreateJobObject(NULL, NULL)); |
1028 if (!job_handle.IsValid()) { | 1028 if (!job_handle.IsValid()) { |
1029 LOG(ERROR) << "Could not create JobObject."; | 1029 LOG(ERROR) << "Could not create JobObject."; |
1030 return -1; | 1030 return -1; |
1031 } | 1031 } |
1032 | 1032 |
| 1033 DWORD job_flags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; |
| 1034 |
1033 // Allow break-away from job since sandbox and few other places rely on it | 1035 // Allow break-away from job since sandbox and few other places rely on it |
1034 // on Windows versions prior to Windows 8 (which supports nested jobs). | 1036 // on Windows versions prior to Windows 8 (which supports nested jobs). |
1035 // TODO(phajdan.jr): Do not allow break-away on Windows 8. | 1037 // TODO(phajdan.jr): Do not allow break-away on Windows 8. |
1036 if (!SetJobObjectLimitFlags(job_handle.Get(), | 1038 if (flags & TestLauncher::ALLOW_BREAKAWAY_FROM_JOB) |
1037 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | | 1039 job_flags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK; |
1038 JOB_OBJECT_LIMIT_BREAKAWAY_OK)) { | 1040 |
| 1041 if (!SetJobObjectLimitFlags(job_handle.Get(), job_flags)) { |
1039 LOG(ERROR) << "Could not SetJobObjectLimitFlags."; | 1042 LOG(ERROR) << "Could not SetJobObjectLimitFlags."; |
1040 return -1; | 1043 return -1; |
1041 } | 1044 } |
1042 | 1045 |
1043 new_options.job_handle = job_handle.Get(); | 1046 new_options.job_handle = job_handle.Get(); |
1044 } | 1047 } |
1045 #endif // defined(OS_WIN) | 1048 #endif // defined(OS_WIN) |
1046 | 1049 |
1047 #if defined(OS_LINUX) | 1050 #if defined(OS_LINUX) |
1048 // To prevent accidental privilege sharing to an untrusted child, processes | 1051 // To prevent accidental privilege sharing to an untrusted child, processes |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1094 | 1097 |
1095 g_live_processes.Get().erase(process_handle); | 1098 g_live_processes.Get().erase(process_handle); |
1096 } | 1099 } |
1097 | 1100 |
1098 base::CloseProcessHandle(process_handle); | 1101 base::CloseProcessHandle(process_handle); |
1099 | 1102 |
1100 return exit_code; | 1103 return exit_code; |
1101 } | 1104 } |
1102 | 1105 |
1103 } // namespace base | 1106 } // namespace base |
OLD | NEW |