process_util_unittest.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#define _CRT_SECURE_NO_WARNINGS 6 7#include <limits> 8 9#include "base/command_line.h" 10#include "base/debug/alias.h" 11#include "base/debug/stack_trace.h" 12#include "base/files/file_path.h" 13#include "base/logging.h" 14#include "base/memory/scoped_ptr.h" 15#include "base/path_service.h" 16#include "base/posix/eintr_wrapper.h" 17#include "base/process/kill.h" 18#include "base/process/launch.h" 19#include "base/process/memory.h" 20#include "base/process/process.h" 21#include "base/process/process_metrics.h" 22#include "base/strings/utf_string_conversions.h" 23#include "base/test/multiprocess_test.h" 24#include "base/test/test_timeouts.h" 25#include "base/third_party/dynamic_annotations/dynamic_annotations.h" 26#include "base/threading/platform_thread.h" 27#include "base/threading/thread.h" 28#include "testing/gtest/include/gtest/gtest.h" 29#include "testing/multiprocess_func_list.h" 30 31#if defined(OS_LINUX) 32#include <malloc.h> 33#include <sched.h> 34#endif 35#if defined(OS_POSIX) 36#include <dlfcn.h> 37#include <errno.h> 38#include <fcntl.h> 39#include <signal.h> 40#include <sys/resource.h> 41#include <sys/socket.h> 42#include <sys/wait.h> 43#endif 44#if defined(OS_WIN) 45#include <windows.h> 46#endif 47#if defined(OS_MACOSX) 48#include <mach/vm_param.h> 49#include <malloc/malloc.h> 50#endif 51 52using base::FilePath; 53 54namespace { 55 56#if defined(OS_ANDROID) 57const char kShellPath[] = "/system/bin/sh"; 58const char kPosixShell[] = "sh"; 59#else 60const char kShellPath[] = "/bin/sh"; 61const char kPosixShell[] = "bash"; 62#endif 63 64const char kSignalFileSlow[] = "SlowChildProcess.die"; 65const char kSignalFileKill[] = "KilledChildProcess.die"; 66 67#if defined(OS_WIN) 68const int kExpectedStillRunningExitCode = 0x102; 69const int kExpectedKilledExitCode = 1; 70#else 71const int kExpectedStillRunningExitCode = 0; 72#endif 73 74// Sleeps until file filename is created. 75void WaitToDie(const char* filename) { 76 FILE* fp; 77 do { 78 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); 79 fp = fopen(filename, "r"); 80 } while (!fp); 81 fclose(fp); 82} 83 84// Signals children they should die now. 85void SignalChildren(const char* filename) { 86 FILE* fp = fopen(filename, "w"); 87 fclose(fp); 88} 89 90// Using a pipe to the child to wait for an event was considered, but 91// there were cases in the past where pipes caused problems (other 92// libraries closing the fds, child deadlocking). This is a simple 93// case, so it's not worth the risk. Using wait loops is discouraged 94// in most instances. 95base::TerminationStatus WaitForChildTermination(base::ProcessHandle handle, 96 int* exit_code) { 97 // Now we wait until the result is something other than STILL_RUNNING. 98 base::TerminationStatus status = base::TERMINATION_STATUS_STILL_RUNNING; 99 const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(20); 100 base::TimeDelta waited; 101 do { 102 status = base::GetTerminationStatus(handle, exit_code); 103 base::PlatformThread::Sleep(kInterval); 104 waited += kInterval; 105 } while (status == base::TERMINATION_STATUS_STILL_RUNNING && 106// Waiting for more time for process termination on android devices. 107#if defined(OS_ANDROID) 108 waited < TestTimeouts::large_test_timeout()); 109#else 110 waited < TestTimeouts::action_max_timeout()); 111#endif 112 113 return status; 114} 115 116} // namespace 117 118class ProcessUtilTest : public base::MultiProcessTest { 119 public: 120#if defined(OS_POSIX) 121 // Spawn a child process that counts how many file descriptors are open. 122 int CountOpenFDsInChild(); 123#endif 124 // Converts the filename to a platform specific filepath. 125 // On Android files can not be created in arbitrary directories. 126 static std::string GetSignalFilePath(const char* filename); 127}; 128 129std::string ProcessUtilTest::GetSignalFilePath(const char* filename) { 130#if !defined(OS_ANDROID) 131 return filename; 132#else 133 FilePath tmp_dir; 134 PathService::Get(base::DIR_CACHE, &tmp_dir); 135 tmp_dir = tmp_dir.Append(filename); 136 return tmp_dir.value(); 137#endif 138} 139 140MULTIPROCESS_TEST_MAIN(SimpleChildProcess) { 141 return 0; 142} 143 144TEST_F(ProcessUtilTest, SpawnChild) { 145 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); 146 ASSERT_NE(base::kNullProcessHandle, handle); 147 EXPECT_TRUE(base::WaitForSingleProcess( 148 handle, TestTimeouts::action_max_timeout())); 149 base::CloseProcessHandle(handle); 150} 151 152MULTIPROCESS_TEST_MAIN(SlowChildProcess) { 153 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileSlow).c_str()); 154 return 0; 155} 156 157TEST_F(ProcessUtilTest, KillSlowChild) { 158 const std::string signal_file = 159 ProcessUtilTest::GetSignalFilePath(kSignalFileSlow); 160 remove(signal_file.c_str()); 161 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); 162 ASSERT_NE(base::kNullProcessHandle, handle); 163 SignalChildren(signal_file.c_str()); 164 EXPECT_TRUE(base::WaitForSingleProcess( 165 handle, TestTimeouts::action_max_timeout())); 166 base::CloseProcessHandle(handle); 167 remove(signal_file.c_str()); 168} 169 170// Times out on Linux and Win, flakes on other platforms, http://crbug.com/95058 171TEST_F(ProcessUtilTest, DISABLED_GetTerminationStatusExit) { 172 const std::string signal_file = 173 ProcessUtilTest::GetSignalFilePath(kSignalFileSlow); 174 remove(signal_file.c_str()); 175 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); 176 ASSERT_NE(base::kNullProcessHandle, handle); 177 178 int exit_code = 42; 179 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, 180 base::GetTerminationStatus(handle, &exit_code)); 181 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); 182 183 SignalChildren(signal_file.c_str()); 184 exit_code = 42; 185 base::TerminationStatus status = 186 WaitForChildTermination(handle, &exit_code); 187 EXPECT_EQ(base::TERMINATION_STATUS_NORMAL_TERMINATION, status); 188 EXPECT_EQ(0, exit_code); 189 base::CloseProcessHandle(handle); 190 remove(signal_file.c_str()); 191} 192 193#if defined(OS_WIN) 194// TODO(cpu): figure out how to test this in other platforms. 195TEST_F(ProcessUtilTest, GetProcId) { 196 base::ProcessId id1 = base::GetProcId(GetCurrentProcess()); 197 EXPECT_NE(0ul, id1); 198 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); 199 ASSERT_NE(base::kNullProcessHandle, handle); 200 base::ProcessId id2 = base::GetProcId(handle); 201 EXPECT_NE(0ul, id2); 202 EXPECT_NE(id1, id2); 203 base::CloseProcessHandle(handle); 204} 205#endif 206 207#if !defined(OS_MACOSX) 208// This test is disabled on Mac, since it's flaky due to ReportCrash 209// taking a variable amount of time to parse and load the debug and 210// symbol data for this unit test's executable before firing the 211// signal handler. 212// 213// TODO(gspencer): turn this test process into a very small program 214// with no symbols (instead of using the multiprocess testing 215// framework) to reduce the ReportCrash overhead. 216const char kSignalFileCrash[] = "CrashingChildProcess.die"; 217 218MULTIPROCESS_TEST_MAIN(CrashingChildProcess) { 219 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str()); 220#if defined(OS_POSIX) 221 // Have to disable to signal handler for segv so we can get a crash 222 // instead of an abnormal termination through the crash dump handler. 223 ::signal(SIGSEGV, SIG_DFL); 224#endif 225 // Make this process have a segmentation fault. 226 volatile int* oops = NULL; 227 *oops = 0xDEAD; 228 return 1; 229} 230 231// This test intentionally crashes, so we don't need to run it under 232// AddressSanitizer. 233// TODO(jschuh): crbug.com/175753 Fix this in Win64 bots. 234#if defined(ADDRESS_SANITIZER) || (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) 235#define MAYBE_GetTerminationStatusCrash DISABLED_GetTerminationStatusCrash 236#else 237#define MAYBE_GetTerminationStatusCrash GetTerminationStatusCrash 238#endif 239TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusCrash) { 240 const std::string signal_file = 241 ProcessUtilTest::GetSignalFilePath(kSignalFileCrash); 242 remove(signal_file.c_str()); 243 base::ProcessHandle handle = this->SpawnChild("CrashingChildProcess", 244 false); 245 ASSERT_NE(base::kNullProcessHandle, handle); 246 247 int exit_code = 42; 248 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, 249 base::GetTerminationStatus(handle, &exit_code)); 250 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); 251 252 SignalChildren(signal_file.c_str()); 253 exit_code = 42; 254 base::TerminationStatus status = 255 WaitForChildTermination(handle, &exit_code); 256 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_CRASHED, status); 257 258#if defined(OS_WIN) 259 EXPECT_EQ(0xc0000005, exit_code); 260#elif defined(OS_POSIX) 261 int signaled = WIFSIGNALED(exit_code); 262 EXPECT_NE(0, signaled); 263 int signal = WTERMSIG(exit_code); 264 EXPECT_EQ(SIGSEGV, signal); 265#endif 266 base::CloseProcessHandle(handle); 267 268 // Reset signal handlers back to "normal". 269 base::debug::EnableInProcessStackDumping(); 270 remove(signal_file.c_str()); 271} 272#endif // !defined(OS_MACOSX) 273 274MULTIPROCESS_TEST_MAIN(KilledChildProcess) { 275 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileKill).c_str()); 276#if defined(OS_WIN) 277 // Kill ourselves. 278 HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId()); 279 ::TerminateProcess(handle, kExpectedKilledExitCode); 280#elif defined(OS_POSIX) 281 // Send a SIGKILL to this process, just like the OOM killer would. 282 ::kill(getpid(), SIGKILL); 283#endif 284 return 1; 285} 286 287TEST_F(ProcessUtilTest, GetTerminationStatusKill) { 288 const std::string signal_file = 289 ProcessUtilTest::GetSignalFilePath(kSignalFileKill); 290 remove(signal_file.c_str()); 291 base::ProcessHandle handle = this->SpawnChild("KilledChildProcess", 292 false); 293 ASSERT_NE(base::kNullProcessHandle, handle); 294 295 int exit_code = 42; 296 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, 297 base::GetTerminationStatus(handle, &exit_code)); 298 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); 299 300 SignalChildren(signal_file.c_str()); 301 exit_code = 42; 302 base::TerminationStatus status = 303 WaitForChildTermination(handle, &exit_code); 304 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status); 305#if defined(OS_WIN) 306 EXPECT_EQ(kExpectedKilledExitCode, exit_code); 307#elif defined(OS_POSIX) 308 int signaled = WIFSIGNALED(exit_code); 309 EXPECT_NE(0, signaled); 310 int signal = WTERMSIG(exit_code); 311 EXPECT_EQ(SIGKILL, signal); 312#endif 313 base::CloseProcessHandle(handle); 314 remove(signal_file.c_str()); 315} 316 317// Ensure that the priority of a process is restored correctly after 318// backgrounding and restoring. 319// Note: a platform may not be willing or able to lower the priority of 320// a process. The calls to SetProcessBackground should be noops then. 321TEST_F(ProcessUtilTest, SetProcessBackgrounded) { 322 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); 323 base::Process process(handle); 324 int old_priority = process.GetPriority(); 325#if defined(OS_WIN) 326 EXPECT_TRUE(process.SetProcessBackgrounded(true)); 327 EXPECT_TRUE(process.IsProcessBackgrounded()); 328 EXPECT_TRUE(process.SetProcessBackgrounded(false)); 329 EXPECT_FALSE(process.IsProcessBackgrounded()); 330#else 331 process.SetProcessBackgrounded(true); 332 process.SetProcessBackgrounded(false); 333#endif 334 int new_priority = process.GetPriority(); 335 EXPECT_EQ(old_priority, new_priority); 336} 337 338// Same as SetProcessBackgrounded but to this very process. It uses 339// a different code path at least for Windows. 340TEST_F(ProcessUtilTest, SetProcessBackgroundedSelf) { 341 base::Process process(base::Process::Current().handle()); 342 int old_priority = process.GetPriority(); 343#if defined(OS_WIN) 344 EXPECT_TRUE(process.SetProcessBackgrounded(true)); 345 EXPECT_TRUE(process.IsProcessBackgrounded()); 346 EXPECT_TRUE(process.SetProcessBackgrounded(false)); 347 EXPECT_FALSE(process.IsProcessBackgrounded()); 348#else 349 process.SetProcessBackgrounded(true); 350 process.SetProcessBackgrounded(false); 351#endif 352 int new_priority = process.GetPriority(); 353 EXPECT_EQ(old_priority, new_priority); 354} 355 356#if defined(OS_WIN) 357// TODO(estade): if possible, port this test. 358TEST_F(ProcessUtilTest, GetAppOutput) { 359 // Let's create a decently long message. 360 std::string message; 361 for (int i = 0; i < 1025; i++) { // 1025 so it does not end on a kilo-byte 362 // boundary. 363 message += "Hello!"; 364 } 365 // cmd.exe's echo always adds a \r\n to its output. 366 std::string expected(message); 367 expected += "\r\n"; 368 369 FilePath cmd(L"cmd.exe"); 370 CommandLine cmd_line(cmd); 371 cmd_line.AppendArg("/c"); 372 cmd_line.AppendArg("echo " + message + ""); 373 std::string output; 374 ASSERT_TRUE(base::GetAppOutput(cmd_line, &output)); 375 EXPECT_EQ(expected, output); 376 377 // Let's make sure stderr is ignored. 378 CommandLine other_cmd_line(cmd); 379 other_cmd_line.AppendArg("/c"); 380 // http://msdn.microsoft.com/library/cc772622.aspx 381 cmd_line.AppendArg("echo " + message + " >&2"); 382 output.clear(); 383 ASSERT_TRUE(base::GetAppOutput(other_cmd_line, &output)); 384 EXPECT_EQ("", output); 385} 386 387// TODO(estade): if possible, port this test. 388TEST_F(ProcessUtilTest, LaunchAsUser) { 389 base::UserTokenHandle token; 390 ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)); 391 std::wstring cmdline = 392 this->MakeCmdLine("SimpleChildProcess", false).GetCommandLineString(); 393 base::LaunchOptions options; 394 options.as_user = token; 395 EXPECT_TRUE(base::LaunchProcess(cmdline, options, NULL)); 396} 397 398#endif // defined(OS_WIN) 399 400#if defined(OS_POSIX) 401 402namespace { 403 404// Returns the maximum number of files that a process can have open. 405// Returns 0 on error. 406int GetMaxFilesOpenInProcess() { 407 struct rlimit rlim; 408 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) { 409 return 0; 410 } 411 412 // rlim_t is a uint64 - clip to maxint. We do this since FD #s are ints 413 // which are all 32 bits on the supported platforms. 414 rlim_t max_int = static_cast<rlim_t>(std::numeric_limits<int32>::max()); 415 if (rlim.rlim_cur > max_int) { 416 return max_int; 417 } 418 419 return rlim.rlim_cur; 420} 421 422const int kChildPipe = 20; // FD # for write end of pipe in child process. 423 424} // namespace 425 426MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) { 427 // This child process counts the number of open FDs, it then writes that 428 // number out to a pipe connected to the parent. 429 int num_open_files = 0; 430 int write_pipe = kChildPipe; 431 int max_files = GetMaxFilesOpenInProcess(); 432 for (int i = STDERR_FILENO + 1; i < max_files; i++) { 433 if (i != kChildPipe) { 434 int fd; 435 if ((fd = HANDLE_EINTR(dup(i))) != -1) { 436 close(fd); 437 num_open_files += 1; 438 } 439 } 440 } 441 442 int written = HANDLE_EINTR(write(write_pipe, &num_open_files, 443 sizeof(num_open_files))); 444 DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files)); 445 int ret = IGNORE_EINTR(close(write_pipe)); 446 DPCHECK(ret == 0); 447 448 return 0; 449} 450 451int ProcessUtilTest::CountOpenFDsInChild() { 452 int fds[2]; 453 if (pipe(fds) < 0) 454 NOTREACHED(); 455 456 base::FileHandleMappingVector fd_mapping_vec; 457 fd_mapping_vec.push_back(std::pair<int, int>(fds[1], kChildPipe)); 458 base::ProcessHandle handle = this->SpawnChild( 459 "ProcessUtilsLeakFDChildProcess", fd_mapping_vec, false); 460 CHECK(handle); 461 int ret = IGNORE_EINTR(close(fds[1])); 462 DPCHECK(ret == 0); 463 464 // Read number of open files in client process from pipe; 465 int num_open_files = -1; 466 ssize_t bytes_read = 467 HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files))); 468 CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files))); 469 470#if defined(THREAD_SANITIZER) || defined(USE_HEAPCHECKER) 471 // Compiler-based ThreadSanitizer makes this test slow. 472 CHECK(base::WaitForSingleProcess(handle, base::TimeDelta::FromSeconds(3))); 473#else 474 CHECK(base::WaitForSingleProcess(handle, base::TimeDelta::FromSeconds(1))); 475#endif 476 base::CloseProcessHandle(handle); 477 ret = IGNORE_EINTR(close(fds[0])); 478 DPCHECK(ret == 0); 479 480 return num_open_files; 481} 482 483#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) 484// ProcessUtilTest.FDRemapping is flaky when ran under xvfb-run on Precise. 485// The problem is 100% reproducible with both ASan and TSan. 486// See http://crbug.com/136720. 487#define MAYBE_FDRemapping DISABLED_FDRemapping 488#else 489#define MAYBE_FDRemapping FDRemapping 490#endif 491TEST_F(ProcessUtilTest, MAYBE_FDRemapping) { 492 int fds_before = CountOpenFDsInChild(); 493 494 // open some dummy fds to make sure they don't propagate over to the 495 // child process. 496 int dev_null = open("/dev/null", O_RDONLY); 497 int sockets[2]; 498 socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); 499 500 int fds_after = CountOpenFDsInChild(); 501 502 ASSERT_EQ(fds_after, fds_before); 503 504 int ret; 505 ret = IGNORE_EINTR(close(sockets[0])); 506 DPCHECK(ret == 0); 507 ret = IGNORE_EINTR(close(sockets[1])); 508 DPCHECK(ret == 0); 509 ret = IGNORE_EINTR(close(dev_null)); 510 DPCHECK(ret == 0); 511} 512 513namespace { 514 515std::string TestLaunchProcess(const base::EnvironmentMap& env_changes, 516 const int clone_flags) { 517 std::vector<std::string> args; 518 base::FileHandleMappingVector fds_to_remap; 519 520 args.push_back(kPosixShell); 521 args.push_back("-c"); 522 args.push_back("echo $BASE_TEST"); 523 524 int fds[2]; 525 PCHECK(pipe(fds) == 0); 526 527 fds_to_remap.push_back(std::make_pair(fds[1], 1)); 528 base::LaunchOptions options; 529 options.wait = true; 530 options.environ = env_changes; 531 options.fds_to_remap = &fds_to_remap; 532#if defined(OS_LINUX) 533 options.clone_flags = clone_flags; 534#else 535 CHECK_EQ(0, clone_flags); 536#endif // OS_LINUX 537 EXPECT_TRUE(base::LaunchProcess(args, options, NULL)); 538 PCHECK(IGNORE_EINTR(close(fds[1])) == 0); 539 540 char buf[512]; 541 const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf))); 542 PCHECK(n > 0); 543 544 PCHECK(IGNORE_EINTR(close(fds[0])) == 0); 545 546 return std::string(buf, n); 547} 548 549const char kLargeString[] = 550 "0123456789012345678901234567890123456789012345678901234567890123456789" 551 "0123456789012345678901234567890123456789012345678901234567890123456789" 552 "0123456789012345678901234567890123456789012345678901234567890123456789" 553 "0123456789012345678901234567890123456789012345678901234567890123456789" 554 "0123456789012345678901234567890123456789012345678901234567890123456789" 555 "0123456789012345678901234567890123456789012345678901234567890123456789" 556 "0123456789012345678901234567890123456789012345678901234567890123456789"; 557 558} // namespace 559 560TEST_F(ProcessUtilTest, LaunchProcess) { 561 base::EnvironmentMap env_changes; 562 const int no_clone_flags = 0; 563 564 const char kBaseTest[] = "BASE_TEST"; 565 566 env_changes[kBaseTest] = "bar"; 567 EXPECT_EQ("bar\n", TestLaunchProcess(env_changes, no_clone_flags)); 568 env_changes.clear(); 569 570 EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */)); 571 EXPECT_EQ("testing\n", TestLaunchProcess(env_changes, no_clone_flags)); 572 573 env_changes[kBaseTest] = std::string(); 574 EXPECT_EQ("\n", TestLaunchProcess(env_changes, no_clone_flags)); 575 576 env_changes[kBaseTest] = "foo"; 577 EXPECT_EQ("foo\n", TestLaunchProcess(env_changes, no_clone_flags)); 578 579 env_changes.clear(); 580 EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */)); 581 EXPECT_EQ(std::string(kLargeString) + "\n", 582 TestLaunchProcess(env_changes, no_clone_flags)); 583 584 env_changes[kBaseTest] = "wibble"; 585 EXPECT_EQ("wibble\n", TestLaunchProcess(env_changes, no_clone_flags)); 586 587#if defined(OS_LINUX) 588 // Test a non-trival value for clone_flags. 589 // Don't test on Valgrind as it has limited support for clone(). 590 if (!RunningOnValgrind()) { 591 EXPECT_EQ("wibble\n", TestLaunchProcess(env_changes, CLONE_FS | SIGCHLD)); 592 } 593#endif 594} 595 596TEST_F(ProcessUtilTest, GetAppOutput) { 597 std::string output; 598 599#if defined(OS_ANDROID) 600 std::vector<std::string> argv; 601 argv.push_back("sh"); // Instead of /bin/sh, force path search to find it. 602 argv.push_back("-c"); 603 604 argv.push_back("exit 0"); 605 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 606 EXPECT_STREQ("", output.c_str()); 607 608 argv[2] = "exit 1"; 609 EXPECT_FALSE(base::GetAppOutput(CommandLine(argv), &output)); 610 EXPECT_STREQ("", output.c_str()); 611 612 argv[2] = "echo foobar42"; 613 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 614 EXPECT_STREQ("foobar42\n", output.c_str()); 615#else 616 EXPECT_TRUE(base::GetAppOutput(CommandLine(FilePath("true")), &output)); 617 EXPECT_STREQ("", output.c_str()); 618 619 EXPECT_FALSE(base::GetAppOutput(CommandLine(FilePath("false")), &output)); 620 621 std::vector<std::string> argv; 622 argv.push_back("/bin/echo"); 623 argv.push_back("-n"); 624 argv.push_back("foobar42"); 625 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 626 EXPECT_STREQ("foobar42", output.c_str()); 627#endif // defined(OS_ANDROID) 628} 629 630TEST_F(ProcessUtilTest, GetAppOutputRestricted) { 631 // Unfortunately, since we can't rely on the path, we need to know where 632 // everything is. So let's use /bin/sh, which is on every POSIX system, and 633 // its built-ins. 634 std::vector<std::string> argv; 635 argv.push_back(std::string(kShellPath)); // argv[0] 636 argv.push_back("-c"); // argv[1] 637 638 // On success, should set |output|. We use |/bin/sh -c 'exit 0'| instead of 639 // |true| since the location of the latter may be |/bin| or |/usr/bin| (and we 640 // need absolute paths). 641 argv.push_back("exit 0"); // argv[2]; equivalent to "true" 642 std::string output = "abc"; 643 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 100)); 644 EXPECT_STREQ("", output.c_str()); 645 646 argv[2] = "exit 1"; // equivalent to "false" 647 output = "before"; 648 EXPECT_FALSE(base::GetAppOutputRestricted(CommandLine(argv), 649 &output, 100)); 650 EXPECT_STREQ("", output.c_str()); 651 652 // Amount of output exactly equal to space allowed. 653 argv[2] = "echo 123456789"; // (the sh built-in doesn't take "-n") 654 output.clear(); 655 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 656 EXPECT_STREQ("123456789\n", output.c_str()); 657 658 // Amount of output greater than space allowed. 659 output.clear(); 660 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 5)); 661 EXPECT_STREQ("12345", output.c_str()); 662 663 // Amount of output less than space allowed. 664 output.clear(); 665 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 15)); 666 EXPECT_STREQ("123456789\n", output.c_str()); 667 668 // Zero space allowed. 669 output = "abc"; 670 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 0)); 671 EXPECT_STREQ("", output.c_str()); 672} 673 674#if !defined(OS_MACOSX) && !defined(OS_OPENBSD) 675// TODO(benwells): GetAppOutputRestricted should terminate applications 676// with SIGPIPE when we have enough output. http://crbug.com/88502 677TEST_F(ProcessUtilTest, GetAppOutputRestrictedSIGPIPE) { 678 std::vector<std::string> argv; 679 std::string output; 680 681 argv.push_back(std::string(kShellPath)); // argv[0] 682 argv.push_back("-c"); 683#if defined(OS_ANDROID) 684 argv.push_back("while echo 12345678901234567890; do :; done"); 685 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 686 EXPECT_STREQ("1234567890", output.c_str()); 687#else 688 argv.push_back("yes"); 689 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 690 EXPECT_STREQ("y\ny\ny\ny\ny\n", output.c_str()); 691#endif 692} 693#endif 694 695#if defined(ADDRESS_SANITIZER) && defined(OS_MACOSX) && \ 696 defined(ARCH_CPU_64_BITS) 697// Times out under AddressSanitizer on 64-bit OS X, see 698// http://crbug.com/298197. 699#define MAYBE_GetAppOutputRestrictedNoZombies \ 700 DISABLED_GetAppOutputRestrictedNoZombies 701#else 702#define MAYBE_GetAppOutputRestrictedNoZombies GetAppOutputRestrictedNoZombies 703#endif 704TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestrictedNoZombies) { 705 std::vector<std::string> argv; 706 707 argv.push_back(std::string(kShellPath)); // argv[0] 708 argv.push_back("-c"); // argv[1] 709 argv.push_back("echo 123456789012345678901234567890"); // argv[2] 710 711 // Run |GetAppOutputRestricted()| 300 (> default per-user processes on Mac OS 712 // 10.5) times with an output buffer big enough to capture all output. 713 for (int i = 0; i < 300; i++) { 714 std::string output; 715 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 100)); 716 EXPECT_STREQ("123456789012345678901234567890\n", output.c_str()); 717 } 718 719 // Ditto, but with an output buffer too small to capture all output. 720 for (int i = 0; i < 300; i++) { 721 std::string output; 722 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 723 EXPECT_STREQ("1234567890", output.c_str()); 724 } 725} 726 727TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) { 728 // Test getting output from a successful application. 729 std::vector<std::string> argv; 730 std::string output; 731 int exit_code; 732 argv.push_back(std::string(kShellPath)); // argv[0] 733 argv.push_back("-c"); // argv[1] 734 argv.push_back("echo foo"); // argv[2]; 735 EXPECT_TRUE(base::GetAppOutputWithExitCode(CommandLine(argv), &output, 736 &exit_code)); 737 EXPECT_STREQ("foo\n", output.c_str()); 738 EXPECT_EQ(exit_code, 0); 739 740 // Test getting output from an application which fails with a specific exit 741 // code. 742 output.clear(); 743 argv[2] = "echo foo; exit 2"; 744 EXPECT_TRUE(base::GetAppOutputWithExitCode(CommandLine(argv), &output, 745 &exit_code)); 746 EXPECT_STREQ("foo\n", output.c_str()); 747 EXPECT_EQ(exit_code, 2); 748} 749 750TEST_F(ProcessUtilTest, GetParentProcessId) { 751 base::ProcessId ppid = base::GetParentProcessId(base::GetCurrentProcId()); 752 EXPECT_EQ(ppid, getppid()); 753} 754 755// TODO(port): port those unit tests. 756bool IsProcessDead(base::ProcessHandle child) { 757 // waitpid() will actually reap the process which is exactly NOT what we 758 // want to test for. The good thing is that if it can't find the process 759 // we'll get a nice value for errno which we can test for. 760 const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG)); 761 return result == -1 && errno == ECHILD; 762} 763 764TEST_F(ProcessUtilTest, DelayedTermination) { 765 base::ProcessHandle child_process = 766 SpawnChild("process_util_test_never_die", false); 767 ASSERT_TRUE(child_process); 768 base::EnsureProcessTerminated(child_process); 769 base::WaitForSingleProcess(child_process, base::TimeDelta::FromSeconds(5)); 770 771 // Check that process was really killed. 772 EXPECT_TRUE(IsProcessDead(child_process)); 773 base::CloseProcessHandle(child_process); 774} 775 776MULTIPROCESS_TEST_MAIN(process_util_test_never_die) { 777 while (1) { 778 sleep(500); 779 } 780 return 0; 781} 782 783TEST_F(ProcessUtilTest, ImmediateTermination) { 784 base::ProcessHandle child_process = 785 SpawnChild("process_util_test_die_immediately", false); 786 ASSERT_TRUE(child_process); 787 // Give it time to die. 788 sleep(2); 789 base::EnsureProcessTerminated(child_process); 790 791 // Check that process was really killed. 792 EXPECT_TRUE(IsProcessDead(child_process)); 793 base::CloseProcessHandle(child_process); 794} 795 796MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) { 797 return 0; 798} 799 800#endif // defined(OS_POSIX) 801