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 27 matching lines...) Expand all Loading... |
38 #include "base/test/test_timeouts.h" | 38 #include "base/test/test_timeouts.h" |
39 #include "base/thread_task_runner_handle.h" | 39 #include "base/thread_task_runner_handle.h" |
40 #include "base/threading/thread_checker.h" | 40 #include "base/threading/thread_checker.h" |
41 #include "base/time/time.h" | 41 #include "base/time/time.h" |
42 #include "testing/gtest/include/gtest/gtest.h" | 42 #include "testing/gtest/include/gtest/gtest.h" |
43 | 43 |
44 #if defined(OS_MACOSX) | 44 #if defined(OS_MACOSX) |
45 #include "base/mac/scoped_nsautorelease_pool.h" | 45 #include "base/mac/scoped_nsautorelease_pool.h" |
46 #endif | 46 #endif |
47 | 47 |
48 #if defined(OS_WIN) | |
49 #include "base/win/windows_version.h" | |
50 #endif | |
51 | |
52 namespace base { | 48 namespace base { |
53 | 49 |
54 // See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/u
T3FaE_sgkAJ . | 50 // See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/u
T3FaE_sgkAJ . |
55 using ::operator<<; | 51 using ::operator<<; |
56 | 52 |
57 // The environment variable name for the total number of test shards. | 53 // The environment variable name for the total number of test shards. |
58 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; | 54 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; |
59 // The environment variable name for the test shard index. | 55 // The environment variable name for the test shard index. |
60 const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; | 56 const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; |
61 | 57 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 | 219 |
224 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); | 220 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); |
225 iter != switches.end(); ++iter) { | 221 iter != switches.end(); ++iter) { |
226 new_command_line.AppendSwitchNative((*iter).first, (*iter).second); | 222 new_command_line.AppendSwitchNative((*iter).first, (*iter).second); |
227 } | 223 } |
228 | 224 |
229 // Prepend wrapper after last CommandLine quasi-copy operation. CommandLine | 225 // Prepend wrapper after last CommandLine quasi-copy operation. CommandLine |
230 // does not really support removing switches well, and trying to do that | 226 // does not really support removing switches well, and trying to do that |
231 // on a CommandLine with a wrapper is known to break. | 227 // on a CommandLine with a wrapper is known to break. |
232 // TODO(phajdan.jr): Give it a try to support CommandLine removing switches. | 228 // TODO(phajdan.jr): Give it a try to support CommandLine removing switches. |
233 #if defined(OS_WIN) | 229 #if defined(OS_POSIX) |
234 new_command_line.PrependWrapper(ASCIIToUTF16(wrapper)); | |
235 #elif defined(OS_POSIX) | |
236 new_command_line.PrependWrapper(wrapper); | 230 new_command_line.PrependWrapper(wrapper); |
237 #endif | 231 #endif |
238 | 232 |
239 return new_command_line; | 233 return new_command_line; |
240 } | 234 } |
241 | 235 |
242 // Launches a child process using |command_line|. If the child process is still | 236 // 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. | 237 // running after |timeout|, it is terminated and |*was_timeout| is set to true. |
244 // Returns exit code of the process. | 238 // Returns exit code of the process. |
245 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, | 239 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, |
246 const LaunchOptions& options, | 240 const LaunchOptions& options, |
247 int flags, | 241 int flags, |
248 TimeDelta timeout, | 242 TimeDelta timeout, |
249 bool* was_timeout) { | 243 bool* was_timeout) { |
250 #if defined(OS_POSIX) | 244 #if defined(OS_POSIX) |
251 // Make sure an option we rely on is present - see LaunchChildGTestProcess. | 245 // Make sure an option we rely on is present - see LaunchChildGTestProcess. |
252 DCHECK(options.new_process_group); | 246 DCHECK(options.new_process_group); |
253 #endif | 247 #endif |
254 | 248 |
255 LaunchOptions new_options(options); | 249 LaunchOptions new_options(options); |
256 | 250 |
257 #if defined(OS_WIN) | |
258 DCHECK(!new_options.job_handle); | |
259 | |
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; | |
266 } | |
267 | |
268 DWORD job_flags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; | |
269 | |
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; | |
275 } | |
276 | |
277 if (!SetJobObjectLimitFlags(job_handle.Get(), job_flags)) { | |
278 LOG(ERROR) << "Could not SetJobObjectLimitFlags."; | |
279 return -1; | |
280 } | |
281 | |
282 new_options.job_handle = job_handle.Get(); | |
283 } | |
284 #endif // defined(OS_WIN) | |
285 | 251 |
286 #if defined(OS_LINUX) | 252 #if defined(OS_LINUX) |
287 // To prevent accidental privilege sharing to an untrusted child, processes | 253 // 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 | 254 // are started with PR_SET_NO_NEW_PRIVS. Do not set that here, since this |
289 // new child will be privileged and trusted. | 255 // new child will be privileged and trusted. |
290 new_options.allow_new_privs = true; | 256 new_options.allow_new_privs = true; |
291 #endif | 257 #endif |
292 | 258 |
293 Process process; | 259 Process process; |
294 | 260 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 bool redirect_stdio, | 320 bool redirect_stdio, |
355 SingleThreadTaskRunner* task_runner, | 321 SingleThreadTaskRunner* task_runner, |
356 const TestLauncher::LaunchChildGTestProcessCallback& callback) { | 322 const TestLauncher::LaunchChildGTestProcessCallback& callback) { |
357 TimeTicks start_time = TimeTicks::Now(); | 323 TimeTicks start_time = TimeTicks::Now(); |
358 | 324 |
359 // Redirect child process output to a file. | 325 // Redirect child process output to a file. |
360 FilePath output_file; | 326 FilePath output_file; |
361 CHECK(CreateTemporaryFile(&output_file)); | 327 CHECK(CreateTemporaryFile(&output_file)); |
362 | 328 |
363 LaunchOptions options; | 329 LaunchOptions options; |
364 #if defined(OS_WIN) | 330 #if defined(OS_POSIX) |
365 win::ScopedHandle handle; | |
366 | |
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; | |
373 | |
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(); | |
386 } | |
387 #elif defined(OS_POSIX) | |
388 options.new_process_group = true; | 331 options.new_process_group = true; |
389 #if defined(OS_LINUX) | 332 #if defined(OS_LINUX) |
390 options.kill_on_parent_death = true; | 333 options.kill_on_parent_death = true; |
391 #endif // defined(OS_LINUX) | 334 #endif // defined(OS_LINUX) |
392 | 335 |
393 FileHandleMappingVector fds_mapping; | 336 FileHandleMappingVector fds_mapping; |
394 ScopedFD output_file_fd; | 337 ScopedFD output_file_fd; |
395 | 338 |
396 if (redirect_stdio) { | 339 if (redirect_stdio) { |
397 output_file_fd.reset(open(output_file.value().c_str(), O_RDWR)); | 340 output_file_fd.reset(open(output_file.value().c_str(), O_RDWR)); |
398 CHECK(output_file_fd.is_valid()); | 341 CHECK(output_file_fd.is_valid()); |
399 | 342 |
400 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDOUT_FILENO)); | 343 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)); | 344 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDERR_FILENO)); |
402 options.fds_to_remap = &fds_mapping; | 345 options.fds_to_remap = &fds_mapping; |
403 } | 346 } |
404 #endif | 347 #endif |
405 | 348 |
406 bool was_timeout = false; | 349 bool was_timeout = false; |
407 int exit_code = LaunchChildTestProcessWithOptions( | 350 int exit_code = LaunchChildTestProcessWithOptions( |
408 command_line, options, flags, timeout, &was_timeout); | 351 command_line, options, flags, timeout, &was_timeout); |
409 | 352 |
410 if (redirect_stdio) { | 353 if (redirect_stdio) { |
411 #if defined(OS_WIN) | 354 #if defined(OS_POSIX) |
412 FlushFileBuffers(handle.Get()); | |
413 handle.Close(); | |
414 #elif defined(OS_POSIX) | |
415 output_file_fd.reset(); | 355 output_file_fd.reset(); |
416 #endif | 356 #endif |
417 } | 357 } |
418 | 358 |
419 std::string output_file_contents; | 359 std::string output_file_contents; |
420 CHECK(ReadFileToString(output_file, &output_file_contents)); | 360 CHECK(ReadFileToString(output_file, &output_file_contents)); |
421 | 361 |
422 if (!DeleteFile(output_file, false)) { | 362 if (!DeleteFile(output_file, false)) { |
423 // This needs to be non-fatal at least for Windows. | 363 // This needs to be non-fatal at least for Windows. |
424 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe(); | 364 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe(); |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
869 #endif | 809 #endif |
870 | 810 |
871 #if defined(OS_POSIX) | 811 #if defined(OS_POSIX) |
872 results_tracker_.AddGlobalTag("OS_POSIX"); | 812 results_tracker_.AddGlobalTag("OS_POSIX"); |
873 #endif | 813 #endif |
874 | 814 |
875 #if defined(OS_SOLARIS) | 815 #if defined(OS_SOLARIS) |
876 results_tracker_.AddGlobalTag("OS_SOLARIS"); | 816 results_tracker_.AddGlobalTag("OS_SOLARIS"); |
877 #endif | 817 #endif |
878 | 818 |
879 #if defined(OS_WIN) | |
880 results_tracker_.AddGlobalTag("OS_WIN"); | |
881 #endif | |
882 | |
883 // CPU-related tags. | 819 // CPU-related tags. |
884 #if defined(ARCH_CPU_32_BITS) | 820 #if defined(ARCH_CPU_32_BITS) |
885 results_tracker_.AddGlobalTag("CPU_32_BITS"); | 821 results_tracker_.AddGlobalTag("CPU_32_BITS"); |
886 #endif | 822 #endif |
887 | 823 |
888 #if defined(ARCH_CPU_64_BITS) | 824 #if defined(ARCH_CPU_64_BITS) |
889 results_tracker_.AddGlobalTag("CPU_64_BITS"); | 825 results_tracker_.AddGlobalTag("CPU_64_BITS"); |
890 #endif | 826 #endif |
891 | 827 |
892 return true; | 828 return true; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1025 DCHECK(thread_checker_.CalledOnValidThread()); | 961 DCHECK(thread_checker_.CalledOnValidThread()); |
1026 | 962 |
1027 AutoLock lock(g_live_processes_lock.Get()); | 963 AutoLock lock(g_live_processes_lock.Get()); |
1028 | 964 |
1029 fprintf(stdout, "Still waiting for the following processes to finish:\n"); | 965 fprintf(stdout, "Still waiting for the following processes to finish:\n"); |
1030 | 966 |
1031 for (std::map<ProcessHandle, CommandLine>::iterator i = | 967 for (std::map<ProcessHandle, CommandLine>::iterator i = |
1032 g_live_processes.Get().begin(); | 968 g_live_processes.Get().begin(); |
1033 i != g_live_processes.Get().end(); | 969 i != g_live_processes.Get().end(); |
1034 ++i) { | 970 ++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()); | 971 fprintf(stdout, "\t%s\n", i->second.GetCommandLineString().c_str()); |
1039 #endif | |
1040 } | 972 } |
1041 | 973 |
1042 fflush(stdout); | 974 fflush(stdout); |
1043 | 975 |
1044 // Arm the timer again - otherwise it would fire only once. | 976 // Arm the timer again - otherwise it would fire only once. |
1045 watchdog_timer_.Reset(); | 977 watchdog_timer_.Reset(); |
1046 } | 978 } |
1047 | 979 |
1048 std::string GetTestOutputSnippet(const TestResult& result, | 980 std::string GetTestOutputSnippet(const TestResult& result, |
1049 const std::string& full_output) { | 981 const std::string& full_output) { |
(...skipping 20 matching lines...) Expand all Loading... |
1070 } | 1002 } |
1071 | 1003 |
1072 std::string snippet(full_output.substr(run_pos)); | 1004 std::string snippet(full_output.substr(run_pos)); |
1073 if (end_pos != std::string::npos) | 1005 if (end_pos != std::string::npos) |
1074 snippet = full_output.substr(run_pos, end_pos - run_pos); | 1006 snippet = full_output.substr(run_pos, end_pos - run_pos); |
1075 | 1007 |
1076 return snippet; | 1008 return snippet; |
1077 } | 1009 } |
1078 | 1010 |
1079 } // namespace base | 1011 } // namespace base |
OLD | NEW |