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 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 #elif defined(OS_POSIX) | 997 #elif defined(OS_POSIX) |
998 new_command_line.PrependWrapper(wrapper); | 998 new_command_line.PrependWrapper(wrapper); |
999 #endif | 999 #endif |
1000 | 1000 |
1001 return new_command_line; | 1001 return new_command_line; |
1002 } | 1002 } |
1003 | 1003 |
1004 // TODO(phajdan.jr): Move to anonymous namespace. | 1004 // TODO(phajdan.jr): Move to anonymous namespace. |
1005 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, | 1005 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, |
1006 const LaunchOptions& options, | 1006 const LaunchOptions& options, |
1007 bool use_job_objects, | 1007 int flags, |
1008 base::TimeDelta timeout, | 1008 base::TimeDelta timeout, |
1009 bool* was_timeout) { | 1009 bool* was_timeout) { |
1010 #if defined(OS_POSIX) | 1010 #if defined(OS_POSIX) |
1011 // Make sure an option we rely on is present - see LaunchChildGTestProcess. | 1011 // Make sure an option we rely on is present - see LaunchChildGTestProcess. |
1012 DCHECK(options.new_process_group); | 1012 DCHECK(options.new_process_group); |
1013 #endif | 1013 #endif |
1014 | 1014 |
1015 LaunchOptions new_options(options); | 1015 LaunchOptions new_options(options); |
1016 | 1016 |
1017 #if defined(OS_WIN) | 1017 #if defined(OS_WIN) |
1018 DCHECK(!new_options.job_handle); | 1018 DCHECK(!new_options.job_handle); |
1019 | 1019 |
1020 win::ScopedHandle job_handle; | 1020 win::ScopedHandle job_handle; |
1021 if (use_job_objects) { | 1021 if (flags & TestLauncher::USE_JOB_OBJECTS) { |
1022 job_handle.Set(CreateJobObject(NULL, NULL)); | 1022 job_handle.Set(CreateJobObject(NULL, NULL)); |
1023 if (!job_handle.IsValid()) { | 1023 if (!job_handle.IsValid()) { |
1024 LOG(ERROR) << "Could not create JobObject."; | 1024 LOG(ERROR) << "Could not create JobObject."; |
1025 return -1; | 1025 return -1; |
1026 } | 1026 } |
1027 | 1027 |
| 1028 DWORD job_flags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; |
| 1029 |
1028 // Allow break-away from job since sandbox and few other places rely on it | 1030 // Allow break-away from job since sandbox and few other places rely on it |
1029 // on Windows versions prior to Windows 8 (which supports nested jobs). | 1031 // on Windows versions prior to Windows 8 (which supports nested jobs). |
1030 // TODO(phajdan.jr): Do not allow break-away on Windows 8. | 1032 // TODO(phajdan.jr): Do not allow break-away on Windows 8. |
1031 if (!SetJobObjectLimitFlags(job_handle.Get(), | 1033 if (flags & TestLauncher::ALLOW_BREAKAWAY_FROM_JOB) |
1032 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | | 1034 job_flags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK; |
1033 JOB_OBJECT_LIMIT_BREAKAWAY_OK)) { | 1035 |
| 1036 if (!SetJobObjectLimitFlags(job_handle.Get(), job_flags)) { |
1034 LOG(ERROR) << "Could not SetJobObjectLimitFlags."; | 1037 LOG(ERROR) << "Could not SetJobObjectLimitFlags."; |
1035 return -1; | 1038 return -1; |
1036 } | 1039 } |
1037 | 1040 |
1038 new_options.job_handle = job_handle.Get(); | 1041 new_options.job_handle = job_handle.Get(); |
1039 } | 1042 } |
1040 #endif // defined(OS_WIN) | 1043 #endif // defined(OS_WIN) |
1041 | 1044 |
1042 #if defined(OS_LINUX) | 1045 #if defined(OS_LINUX) |
1043 // To prevent accidental privilege sharing to an untrusted child, processes | 1046 // To prevent accidental privilege sharing to an untrusted child, processes |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1089 | 1092 |
1090 g_live_processes.Get().erase(process_handle); | 1093 g_live_processes.Get().erase(process_handle); |
1091 } | 1094 } |
1092 | 1095 |
1093 base::CloseProcessHandle(process_handle); | 1096 base::CloseProcessHandle(process_handle); |
1094 | 1097 |
1095 return exit_code; | 1098 return exit_code; |
1096 } | 1099 } |
1097 | 1100 |
1098 } // namespace base | 1101 } // namespace base |
OLD | NEW |