Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: base/test/launcher/test_launcher.cc

Issue 786123002: Update from https://crrev.com/307330 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/strings/safe_sprintf_unittest.cc ('k') | base/test/test_reg_util_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « base/strings/safe_sprintf_unittest.cc ('k') | base/test/test_reg_util_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698