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 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); | 221 for (CommandLine::SwitchMap::const_iterator iter = switches.begin(); |
222 iter != switches.end(); ++iter) { | 222 iter != switches.end(); ++iter) { |
223 new_command_line.AppendSwitchNative((*iter).first, (*iter).second); | 223 new_command_line.AppendSwitchNative((*iter).first, (*iter).second); |
224 } | 224 } |
225 | 225 |
226 // Prepend wrapper after last CommandLine quasi-copy operation. CommandLine | 226 // Prepend wrapper after last CommandLine quasi-copy operation. CommandLine |
227 // does not really support removing switches well, and trying to do that | 227 // does not really support removing switches well, and trying to do that |
228 // on a CommandLine with a wrapper is known to break. | 228 // on a CommandLine with a wrapper is known to break. |
229 // TODO(phajdan.jr): Give it a try to support CommandLine removing switches. | 229 // TODO(phajdan.jr): Give it a try to support CommandLine removing switches. |
230 #if defined(OS_WIN) | 230 #if defined(OS_WIN) |
231 new_command_line.PrependWrapper(ASCIIToWide(wrapper)); | 231 new_command_line.PrependWrapper(ASCIIToUTF16(wrapper)); |
232 #elif defined(OS_POSIX) | 232 #elif defined(OS_POSIX) |
233 new_command_line.PrependWrapper(wrapper); | 233 new_command_line.PrependWrapper(wrapper); |
234 #endif | 234 #endif |
235 | 235 |
236 return new_command_line; | 236 return new_command_line; |
237 } | 237 } |
238 | 238 |
239 // Launches a child process using |command_line|. If the child process is still | 239 // Launches a child process using |command_line|. If the child process is still |
240 // running after |timeout|, it is terminated and |*was_timeout| is set to true. | 240 // running after |timeout|, it is terminated and |*was_timeout| is set to true. |
241 // Returns exit code of the process. | 241 // Returns exit code of the process. |
242 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, | 242 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, |
243 const LaunchOptions& options, | 243 const LaunchOptions& options, |
244 int flags, | 244 int flags, |
245 base::TimeDelta timeout, | 245 TimeDelta timeout, |
246 bool* was_timeout) { | 246 bool* was_timeout) { |
247 #if defined(OS_POSIX) | 247 #if defined(OS_POSIX) |
248 // Make sure an option we rely on is present - see LaunchChildGTestProcess. | 248 // Make sure an option we rely on is present - see LaunchChildGTestProcess. |
249 DCHECK(options.new_process_group); | 249 DCHECK(options.new_process_group); |
250 #endif | 250 #endif |
251 | 251 |
252 LaunchOptions new_options(options); | 252 LaunchOptions new_options(options); |
253 | 253 |
254 #if defined(OS_WIN) | 254 #if defined(OS_WIN) |
255 DCHECK(!new_options.job_handle); | 255 DCHECK(!new_options.job_handle); |
(...skipping 24 matching lines...) Expand all Loading... |
280 } | 280 } |
281 #endif // defined(OS_WIN) | 281 #endif // defined(OS_WIN) |
282 | 282 |
283 #if defined(OS_LINUX) | 283 #if defined(OS_LINUX) |
284 // To prevent accidental privilege sharing to an untrusted child, processes | 284 // To prevent accidental privilege sharing to an untrusted child, processes |
285 // are started with PR_SET_NO_NEW_PRIVS. Do not set that here, since this | 285 // are started with PR_SET_NO_NEW_PRIVS. Do not set that here, since this |
286 // new child will be privileged and trusted. | 286 // new child will be privileged and trusted. |
287 new_options.allow_new_privs = true; | 287 new_options.allow_new_privs = true; |
288 #endif | 288 #endif |
289 | 289 |
290 base::ProcessHandle process_handle; | 290 ProcessHandle process_handle; |
291 | 291 |
292 { | 292 { |
293 // Note how we grab the lock before the process possibly gets created. | 293 // Note how we grab the lock before the process possibly gets created. |
294 // This ensures that when the lock is held, ALL the processes are registered | 294 // This ensures that when the lock is held, ALL the processes are registered |
295 // in the set. | 295 // in the set. |
296 AutoLock lock(g_live_processes_lock.Get()); | 296 AutoLock lock(g_live_processes_lock.Get()); |
297 | 297 |
298 if (!base::LaunchProcess(command_line, new_options, &process_handle)) | 298 if (!LaunchProcess(command_line, new_options, &process_handle)) |
299 return -1; | 299 return -1; |
300 | 300 |
301 g_live_processes.Get().insert(std::make_pair(process_handle, command_line)); | 301 g_live_processes.Get().insert(std::make_pair(process_handle, command_line)); |
302 } | 302 } |
303 | 303 |
304 int exit_code = 0; | 304 int exit_code = 0; |
305 if (!base::WaitForExitCodeWithTimeout(process_handle, | 305 if (!WaitForExitCodeWithTimeout(process_handle, &exit_code, timeout)) { |
306 &exit_code, | |
307 timeout)) { | |
308 *was_timeout = true; | 306 *was_timeout = true; |
309 exit_code = -1; // Set a non-zero exit code to signal a failure. | 307 exit_code = -1; // Set a non-zero exit code to signal a failure. |
310 | 308 |
311 // Ensure that the process terminates. | 309 // Ensure that the process terminates. |
312 base::KillProcess(process_handle, -1, true); | 310 KillProcess(process_handle, -1, true); |
313 } | 311 } |
314 | 312 |
315 { | 313 { |
316 // Note how we grab the log before issuing a possibly broad process kill. | 314 // Note how we grab the log before issuing a possibly broad process kill. |
317 // Other code parts that grab the log kill processes, so avoid trying | 315 // Other code parts that grab the log kill processes, so avoid trying |
318 // to do that twice and trigger all kinds of log messages. | 316 // to do that twice and trigger all kinds of log messages. |
319 AutoLock lock(g_live_processes_lock.Get()); | 317 AutoLock lock(g_live_processes_lock.Get()); |
320 | 318 |
321 #if defined(OS_POSIX) | 319 #if defined(OS_POSIX) |
322 if (exit_code != 0) { | 320 if (exit_code != 0) { |
323 // On POSIX, in case the test does not exit cleanly, either due to a crash | 321 // On POSIX, in case the test does not exit cleanly, either due to a crash |
324 // or due to it timing out, we need to clean up any child processes that | 322 // or due to it timing out, we need to clean up any child processes that |
325 // it might have created. On Windows, child processes are automatically | 323 // it might have created. On Windows, child processes are automatically |
326 // cleaned up using JobObjects. | 324 // cleaned up using JobObjects. |
327 base::KillProcessGroup(process_handle); | 325 KillProcessGroup(process_handle); |
328 } | 326 } |
329 #endif | 327 #endif |
330 | 328 |
331 g_live_processes.Get().erase(process_handle); | 329 g_live_processes.Get().erase(process_handle); |
332 } | 330 } |
333 | 331 |
334 base::CloseProcessHandle(process_handle); | 332 CloseProcessHandle(process_handle); |
335 | 333 |
336 return exit_code; | 334 return exit_code; |
337 } | 335 } |
338 | 336 |
339 void RunCallback( | 337 void RunCallback( |
340 const TestLauncher::LaunchChildGTestProcessCallback& callback, | 338 const TestLauncher::LaunchChildGTestProcessCallback& callback, |
341 int exit_code, | 339 int exit_code, |
342 const TimeDelta& elapsed_time, | 340 const TimeDelta& elapsed_time, |
343 bool was_timeout, | 341 bool was_timeout, |
344 const std::string& output) { | 342 const std::string& output) { |
345 callback.Run(exit_code, elapsed_time, was_timeout, output); | 343 callback.Run(exit_code, elapsed_time, was_timeout, output); |
346 } | 344 } |
347 | 345 |
348 void DoLaunchChildTestProcess( | 346 void DoLaunchChildTestProcess( |
349 const CommandLine& command_line, | 347 const CommandLine& command_line, |
350 base::TimeDelta timeout, | 348 TimeDelta timeout, |
351 int flags, | 349 int flags, |
352 bool redirect_stdio, | 350 bool redirect_stdio, |
353 scoped_refptr<MessageLoopProxy> message_loop_proxy, | 351 scoped_refptr<MessageLoopProxy> message_loop_proxy, |
354 const TestLauncher::LaunchChildGTestProcessCallback& callback) { | 352 const TestLauncher::LaunchChildGTestProcessCallback& callback) { |
355 TimeTicks start_time = TimeTicks::Now(); | 353 TimeTicks start_time = TimeTicks::Now(); |
356 | 354 |
357 // Redirect child process output to a file. | 355 // Redirect child process output to a file. |
358 base::FilePath output_file; | 356 FilePath output_file; |
359 CHECK(base::CreateTemporaryFile(&output_file)); | 357 CHECK(CreateTemporaryFile(&output_file)); |
360 | 358 |
361 LaunchOptions options; | 359 LaunchOptions options; |
362 #if defined(OS_WIN) | 360 #if defined(OS_WIN) |
363 win::ScopedHandle handle; | 361 win::ScopedHandle handle; |
364 | 362 |
365 if (redirect_stdio) { | 363 if (redirect_stdio) { |
366 // Make the file handle inheritable by the child. | 364 // Make the file handle inheritable by the child. |
367 SECURITY_ATTRIBUTES sa_attr; | 365 SECURITY_ATTRIBUTES sa_attr; |
368 sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES); | 366 sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES); |
369 sa_attr.lpSecurityDescriptor = NULL; | 367 sa_attr.lpSecurityDescriptor = NULL; |
370 sa_attr.bInheritHandle = TRUE; | 368 sa_attr.bInheritHandle = TRUE; |
371 | 369 |
372 handle.Set(CreateFile(output_file.value().c_str(), | 370 handle.Set(CreateFile(output_file.value().c_str(), |
373 GENERIC_WRITE, | 371 GENERIC_WRITE, |
374 FILE_SHARE_READ | FILE_SHARE_DELETE, | 372 FILE_SHARE_READ | FILE_SHARE_DELETE, |
375 &sa_attr, | 373 &sa_attr, |
376 OPEN_EXISTING, | 374 OPEN_EXISTING, |
377 FILE_ATTRIBUTE_TEMPORARY, | 375 FILE_ATTRIBUTE_TEMPORARY, |
378 NULL)); | 376 NULL)); |
379 CHECK(handle.IsValid()); | 377 CHECK(handle.IsValid()); |
380 options.inherit_handles = true; | 378 options.inherit_handles = true; |
381 options.stdin_handle = INVALID_HANDLE_VALUE; | 379 options.stdin_handle = INVALID_HANDLE_VALUE; |
382 options.stdout_handle = handle.Get(); | 380 options.stdout_handle = handle.Get(); |
383 options.stderr_handle = handle.Get(); | 381 options.stderr_handle = handle.Get(); |
384 } | 382 } |
385 #elif defined(OS_POSIX) | 383 #elif defined(OS_POSIX) |
386 options.new_process_group = true; | 384 options.new_process_group = true; |
387 | 385 |
388 base::FileHandleMappingVector fds_mapping; | 386 FileHandleMappingVector fds_mapping; |
389 base::ScopedFD output_file_fd; | 387 ScopedFD output_file_fd; |
390 | 388 |
391 if (redirect_stdio) { | 389 if (redirect_stdio) { |
392 output_file_fd.reset(open(output_file.value().c_str(), O_RDWR)); | 390 output_file_fd.reset(open(output_file.value().c_str(), O_RDWR)); |
393 CHECK(output_file_fd.is_valid()); | 391 CHECK(output_file_fd.is_valid()); |
394 | 392 |
395 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDOUT_FILENO)); | 393 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDOUT_FILENO)); |
396 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDERR_FILENO)); | 394 fds_mapping.push_back(std::make_pair(output_file_fd.get(), STDERR_FILENO)); |
397 options.fds_to_remap = &fds_mapping; | 395 options.fds_to_remap = &fds_mapping; |
398 } | 396 } |
399 #endif | 397 #endif |
400 | 398 |
401 bool was_timeout = false; | 399 bool was_timeout = false; |
402 int exit_code = LaunchChildTestProcessWithOptions( | 400 int exit_code = LaunchChildTestProcessWithOptions( |
403 command_line, options, flags, timeout, &was_timeout); | 401 command_line, options, flags, timeout, &was_timeout); |
404 | 402 |
405 if (redirect_stdio) { | 403 if (redirect_stdio) { |
406 #if defined(OS_WIN) | 404 #if defined(OS_WIN) |
407 FlushFileBuffers(handle.Get()); | 405 FlushFileBuffers(handle.Get()); |
408 handle.Close(); | 406 handle.Close(); |
409 #elif defined(OS_POSIX) | 407 #elif defined(OS_POSIX) |
410 output_file_fd.reset(); | 408 output_file_fd.reset(); |
411 #endif | 409 #endif |
412 } | 410 } |
413 | 411 |
414 std::string output_file_contents; | 412 std::string output_file_contents; |
415 CHECK(base::ReadFileToString(output_file, &output_file_contents)); | 413 CHECK(ReadFileToString(output_file, &output_file_contents)); |
416 | 414 |
417 if (!base::DeleteFile(output_file, false)) { | 415 if (!DeleteFile(output_file, false)) { |
418 // This needs to be non-fatal at least for Windows. | 416 // This needs to be non-fatal at least for Windows. |
419 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe(); | 417 LOG(WARNING) << "Failed to delete " << output_file.AsUTF8Unsafe(); |
420 } | 418 } |
421 | 419 |
422 // Run target callback on the thread it was originating from, not on | 420 // Run target callback on the thread it was originating from, not on |
423 // a worker pool thread. | 421 // a worker pool thread. |
424 message_loop_proxy->PostTask( | 422 message_loop_proxy->PostTask( |
425 FROM_HERE, | 423 FROM_HERE, |
426 Bind(&RunCallback, | 424 Bind(&RunCallback, |
427 callback, | 425 callback, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 results_tracker_.PrintSummaryOfAllIterations(); | 510 results_tracker_.PrintSummaryOfAllIterations(); |
513 | 511 |
514 MaybeSaveSummaryAsJSON(); | 512 MaybeSaveSummaryAsJSON(); |
515 | 513 |
516 return run_result_; | 514 return run_result_; |
517 } | 515 } |
518 | 516 |
519 void TestLauncher::LaunchChildGTestProcess( | 517 void TestLauncher::LaunchChildGTestProcess( |
520 const CommandLine& command_line, | 518 const CommandLine& command_line, |
521 const std::string& wrapper, | 519 const std::string& wrapper, |
522 base::TimeDelta timeout, | 520 TimeDelta timeout, |
523 int flags, | 521 int flags, |
524 const LaunchChildGTestProcessCallback& callback) { | 522 const LaunchChildGTestProcessCallback& callback) { |
525 DCHECK(thread_checker_.CalledOnValidThread()); | 523 DCHECK(thread_checker_.CalledOnValidThread()); |
526 | 524 |
527 // Record the exact command line used to launch the child. | 525 // Record the exact command line used to launch the child. |
528 CommandLine new_command_line( | 526 CommandLine new_command_line( |
529 PrepareCommandLineForGTest(command_line, wrapper)); | 527 PrepareCommandLineForGTest(command_line, wrapper)); |
530 | 528 |
531 // When running in parallel mode we need to redirect stdio to avoid mixed-up | 529 // When running in parallel mode we need to redirect stdio to avoid mixed-up |
532 // output. We also always redirect on the bots to get the test output into | 530 // output. We also always redirect on the bots to get the test output into |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 bool excluded = false; | 936 bool excluded = false; |
939 for (size_t k = 0; k < negative_test_filter_.size(); ++k) { | 937 for (size_t k = 0; k < negative_test_filter_.size(); ++k) { |
940 if (MatchPattern(test_name, negative_test_filter_[k])) { | 938 if (MatchPattern(test_name, negative_test_filter_[k])) { |
941 excluded = true; | 939 excluded = true; |
942 break; | 940 break; |
943 } | 941 } |
944 } | 942 } |
945 if (excluded) | 943 if (excluded) |
946 continue; | 944 continue; |
947 | 945 |
948 if (base::Hash(test_name) % total_shards_ != | 946 if (Hash(test_name) % total_shards_ != static_cast<uint32>(shard_index_)) |
949 static_cast<uint32>(shard_index_)) { | |
950 continue; | 947 continue; |
951 } | |
952 | 948 |
953 test_names.push_back(test_name); | 949 test_names.push_back(test_name); |
954 } | 950 } |
955 | 951 |
956 test_started_count_ = launcher_delegate_->RunTests(this, test_names); | 952 test_started_count_ = launcher_delegate_->RunTests(this, test_names); |
957 | 953 |
958 if (test_started_count_ == 0) { | 954 if (test_started_count_ == 0) { |
959 fprintf(stdout, "0 tests run\n"); | 955 fprintf(stdout, "0 tests run\n"); |
960 fflush(stdout); | 956 fflush(stdout); |
961 | 957 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1084 } | 1080 } |
1085 | 1081 |
1086 std::string snippet(full_output.substr(run_pos)); | 1082 std::string snippet(full_output.substr(run_pos)); |
1087 if (end_pos != std::string::npos) | 1083 if (end_pos != std::string::npos) |
1088 snippet = full_output.substr(run_pos, end_pos - run_pos); | 1084 snippet = full_output.substr(run_pos, end_pos - run_pos); |
1089 | 1085 |
1090 return snippet; | 1086 return snippet; |
1091 } | 1087 } |
1092 | 1088 |
1093 } // namespace base | 1089 } // namespace base |
OLD | NEW |