process_util_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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_LINUX) || defined(OS_ANDROID) 357TEST_F(ProcessUtilTest, GetSystemMemoryInfo) { 358 base::SystemMemoryInfoKB info; 359 EXPECT_TRUE(base::GetSystemMemoryInfo(&info)); 360 361 // Ensure each field received a value. 362 EXPECT_GT(info.total, 0); 363 EXPECT_GT(info.free, 0); 364 EXPECT_GT(info.buffers, 0); 365 EXPECT_GT(info.cached, 0); 366 EXPECT_GT(info.active_anon, 0); 367 EXPECT_GT(info.inactive_anon, 0); 368 EXPECT_GT(info.active_file, 0); 369 EXPECT_GT(info.inactive_file, 0); 370 371 // All the values should be less than the total amount of memory. 372 EXPECT_LT(info.free, info.total); 373 EXPECT_LT(info.buffers, info.total); 374 EXPECT_LT(info.cached, info.total); 375 EXPECT_LT(info.active_anon, info.total); 376 EXPECT_LT(info.inactive_anon, info.total); 377 EXPECT_LT(info.active_file, info.total); 378 EXPECT_LT(info.inactive_file, info.total); 379 380#if defined(OS_CHROMEOS) 381 // Chrome OS exposes shmem. 382 EXPECT_GT(info.shmem, 0); 383 EXPECT_LT(info.shmem, info.total); 384 // Chrome unit tests are not run on actual Chrome OS hardware, so gem_objects 385 // and gem_size cannot be tested here. 386#endif 387} 388#endif // defined(OS_LINUX) || defined(OS_ANDROID) 389 390// TODO(estade): if possible, port these 2 tests. 391#if defined(OS_WIN) 392TEST_F(ProcessUtilTest, CalcFreeMemory) { 393 scoped_ptr<base::ProcessMetrics> metrics( 394 base::ProcessMetrics::CreateProcessMetrics(::GetCurrentProcess())); 395 ASSERT_TRUE(NULL != metrics.get()); 396 397 bool using_tcmalloc = false; 398 399 // Detect if we are using tcmalloc 400#if !defined(NO_TCMALLOC) 401 const char* chrome_allocator = getenv("CHROME_ALLOCATOR"); 402 if (!chrome_allocator || _stricmp(chrome_allocator, "tcmalloc") == 0) 403 using_tcmalloc = true; 404#endif 405 406 // Typical values here is ~1900 for total and ~1000 for largest. Obviously 407 // it depends in what other tests have done to this process. 408 base::FreeMBytes free_mem1 = {0}; 409 EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem1)); 410 EXPECT_LT(10u, free_mem1.total); 411 EXPECT_LT(10u, free_mem1.largest); 412 EXPECT_GT(2048u, free_mem1.total); 413 EXPECT_GT(2048u, free_mem1.largest); 414 EXPECT_GE(free_mem1.total, free_mem1.largest); 415 EXPECT_TRUE(NULL != free_mem1.largest_ptr); 416 417 // Allocate 20M and check again. It should have gone down. 418 const int kAllocMB = 20; 419 scoped_ptr<char[]> alloc(new char[kAllocMB * 1024 * 1024]); 420 size_t expected_total = free_mem1.total - kAllocMB; 421 size_t expected_largest = free_mem1.largest; 422 423 base::FreeMBytes free_mem2 = {0}; 424 EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem2)); 425 EXPECT_GE(free_mem2.total, free_mem2.largest); 426 // This test is flaky when using tcmalloc, because tcmalloc 427 // allocation strategy sometimes results in less than the 428 // full drop of 20Mb of free memory. 429 if (!using_tcmalloc) 430 EXPECT_GE(expected_total, free_mem2.total); 431 EXPECT_GE(expected_largest, free_mem2.largest); 432 EXPECT_TRUE(NULL != free_mem2.largest_ptr); 433} 434 435TEST_F(ProcessUtilTest, GetAppOutput) { 436 // Let's create a decently long message. 437 std::string message; 438 for (int i = 0; i < 1025; i++) { // 1025 so it does not end on a kilo-byte 439 // boundary. 440 message += "Hello!"; 441 } 442 // cmd.exe's echo always adds a \r\n to its output. 443 std::string expected(message); 444 expected += "\r\n"; 445 446 FilePath cmd(L"cmd.exe"); 447 CommandLine cmd_line(cmd); 448 cmd_line.AppendArg("/c"); 449 cmd_line.AppendArg("echo " + message + ""); 450 std::string output; 451 ASSERT_TRUE(base::GetAppOutput(cmd_line, &output)); 452 EXPECT_EQ(expected, output); 453 454 // Let's make sure stderr is ignored. 455 CommandLine other_cmd_line(cmd); 456 other_cmd_line.AppendArg("/c"); 457 // http://msdn.microsoft.com/library/cc772622.aspx 458 cmd_line.AppendArg("echo " + message + " >&2"); 459 output.clear(); 460 ASSERT_TRUE(base::GetAppOutput(other_cmd_line, &output)); 461 EXPECT_EQ("", output); 462} 463 464TEST_F(ProcessUtilTest, LaunchAsUser) { 465 base::UserTokenHandle token; 466 ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)); 467 std::wstring cmdline = 468 this->MakeCmdLine("SimpleChildProcess", false).GetCommandLineString(); 469 base::LaunchOptions options; 470 options.as_user = token; 471 EXPECT_TRUE(base::LaunchProcess(cmdline, options, NULL)); 472} 473 474#endif // defined(OS_WIN) 475 476#if defined(OS_POSIX) 477 478namespace { 479 480// Returns the maximum number of files that a process can have open. 481// Returns 0 on error. 482int GetMaxFilesOpenInProcess() { 483 struct rlimit rlim; 484 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) { 485 return 0; 486 } 487 488 // rlim_t is a uint64 - clip to maxint. We do this since FD #s are ints 489 // which are all 32 bits on the supported platforms. 490 rlim_t max_int = static_cast<rlim_t>(std::numeric_limits<int32>::max()); 491 if (rlim.rlim_cur > max_int) { 492 return max_int; 493 } 494 495 return rlim.rlim_cur; 496} 497 498const int kChildPipe = 20; // FD # for write end of pipe in child process. 499 500} // namespace 501 502MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) { 503 // This child process counts the number of open FDs, it then writes that 504 // number out to a pipe connected to the parent. 505 int num_open_files = 0; 506 int write_pipe = kChildPipe; 507 int max_files = GetMaxFilesOpenInProcess(); 508 for (int i = STDERR_FILENO + 1; i < max_files; i++) { 509 if (i != kChildPipe) { 510 int fd; 511 if ((fd = HANDLE_EINTR(dup(i))) != -1) { 512 close(fd); 513 num_open_files += 1; 514 } 515 } 516 } 517 518 int written = HANDLE_EINTR(write(write_pipe, &num_open_files, 519 sizeof(num_open_files))); 520 DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files)); 521 int ret = HANDLE_EINTR(close(write_pipe)); 522 DPCHECK(ret == 0); 523 524 return 0; 525} 526 527int ProcessUtilTest::CountOpenFDsInChild() { 528 int fds[2]; 529 if (pipe(fds) < 0) 530 NOTREACHED(); 531 532 base::FileHandleMappingVector fd_mapping_vec; 533 fd_mapping_vec.push_back(std::pair<int, int>(fds[1], kChildPipe)); 534 base::ProcessHandle handle = this->SpawnChild( 535 "ProcessUtilsLeakFDChildProcess", fd_mapping_vec, false); 536 CHECK(handle); 537 int ret = HANDLE_EINTR(close(fds[1])); 538 DPCHECK(ret == 0); 539 540 // Read number of open files in client process from pipe; 541 int num_open_files = -1; 542 ssize_t bytes_read = 543 HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files))); 544 CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files))); 545 546#if defined(THREAD_SANITIZER) || defined(USE_HEAPCHECKER) 547 // Compiler-based ThreadSanitizer makes this test slow. 548 CHECK(base::WaitForSingleProcess(handle, base::TimeDelta::FromSeconds(3))); 549#else 550 CHECK(base::WaitForSingleProcess(handle, base::TimeDelta::FromSeconds(1))); 551#endif 552 base::CloseProcessHandle(handle); 553 ret = HANDLE_EINTR(close(fds[0])); 554 DPCHECK(ret == 0); 555 556 return num_open_files; 557} 558 559#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) 560// ProcessUtilTest.FDRemapping is flaky when ran under xvfb-run on Precise. 561// The problem is 100% reproducible with both ASan and TSan. 562// See http://crbug.com/136720. 563#define MAYBE_FDRemapping DISABLED_FDRemapping 564#else 565#define MAYBE_FDRemapping FDRemapping 566#endif 567TEST_F(ProcessUtilTest, MAYBE_FDRemapping) { 568 int fds_before = CountOpenFDsInChild(); 569 570 // open some dummy fds to make sure they don't propagate over to the 571 // child process. 572 int dev_null = open("/dev/null", O_RDONLY); 573 int sockets[2]; 574 socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); 575 576 int fds_after = CountOpenFDsInChild(); 577 578 ASSERT_EQ(fds_after, fds_before); 579 580 int ret; 581 ret = HANDLE_EINTR(close(sockets[0])); 582 DPCHECK(ret == 0); 583 ret = HANDLE_EINTR(close(sockets[1])); 584 DPCHECK(ret == 0); 585 ret = HANDLE_EINTR(close(dev_null)); 586 DPCHECK(ret == 0); 587} 588 589namespace { 590 591std::string TestLaunchProcess(const base::EnvironmentMap& env_changes, 592 const int clone_flags) { 593 std::vector<std::string> args; 594 base::FileHandleMappingVector fds_to_remap; 595 596 args.push_back(kPosixShell); 597 args.push_back("-c"); 598 args.push_back("echo $BASE_TEST"); 599 600 int fds[2]; 601 PCHECK(pipe(fds) == 0); 602 603 fds_to_remap.push_back(std::make_pair(fds[1], 1)); 604 base::LaunchOptions options; 605 options.wait = true; 606 options.environ = env_changes; 607 options.fds_to_remap = &fds_to_remap; 608#if defined(OS_LINUX) 609 options.clone_flags = clone_flags; 610#else 611 CHECK_EQ(0, clone_flags); 612#endif // OS_LINUX 613 EXPECT_TRUE(base::LaunchProcess(args, options, NULL)); 614 PCHECK(HANDLE_EINTR(close(fds[1])) == 0); 615 616 char buf[512]; 617 const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf))); 618 PCHECK(n > 0); 619 620 PCHECK(HANDLE_EINTR(close(fds[0])) == 0); 621 622 return std::string(buf, n); 623} 624 625const char kLargeString[] = 626 "0123456789012345678901234567890123456789012345678901234567890123456789" 627 "0123456789012345678901234567890123456789012345678901234567890123456789" 628 "0123456789012345678901234567890123456789012345678901234567890123456789" 629 "0123456789012345678901234567890123456789012345678901234567890123456789" 630 "0123456789012345678901234567890123456789012345678901234567890123456789" 631 "0123456789012345678901234567890123456789012345678901234567890123456789" 632 "0123456789012345678901234567890123456789012345678901234567890123456789"; 633 634} // namespace 635 636TEST_F(ProcessUtilTest, LaunchProcess) { 637 base::EnvironmentMap env_changes; 638 const int no_clone_flags = 0; 639 640 const char kBaseTest[] = "BASE_TEST"; 641 642 env_changes[kBaseTest] = "bar"; 643 EXPECT_EQ("bar\n", TestLaunchProcess(env_changes, no_clone_flags)); 644 env_changes.clear(); 645 646 EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */)); 647 EXPECT_EQ("testing\n", TestLaunchProcess(env_changes, no_clone_flags)); 648 649 env_changes[kBaseTest] = std::string(); 650 EXPECT_EQ("\n", TestLaunchProcess(env_changes, no_clone_flags)); 651 652 env_changes[kBaseTest] = "foo"; 653 EXPECT_EQ("foo\n", TestLaunchProcess(env_changes, no_clone_flags)); 654 655 env_changes.clear(); 656 EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */)); 657 EXPECT_EQ(std::string(kLargeString) + "\n", 658 TestLaunchProcess(env_changes, no_clone_flags)); 659 660 env_changes[kBaseTest] = "wibble"; 661 EXPECT_EQ("wibble\n", TestLaunchProcess(env_changes, no_clone_flags)); 662 663#if defined(OS_LINUX) 664 // Test a non-trival value for clone_flags. 665 // Don't test on Valgrind as it has limited support for clone(). 666 if (!RunningOnValgrind()) { 667 EXPECT_EQ("wibble\n", TestLaunchProcess(env_changes, CLONE_FS | SIGCHLD)); 668 } 669#endif 670} 671 672TEST_F(ProcessUtilTest, GetAppOutput) { 673 std::string output; 674 675#if defined(OS_ANDROID) 676 std::vector<std::string> argv; 677 argv.push_back("sh"); // Instead of /bin/sh, force path search to find it. 678 argv.push_back("-c"); 679 680 argv.push_back("exit 0"); 681 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 682 EXPECT_STREQ("", output.c_str()); 683 684 argv[2] = "exit 1"; 685 EXPECT_FALSE(base::GetAppOutput(CommandLine(argv), &output)); 686 EXPECT_STREQ("", output.c_str()); 687 688 argv[2] = "echo foobar42"; 689 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 690 EXPECT_STREQ("foobar42\n", output.c_str()); 691#else 692 EXPECT_TRUE(base::GetAppOutput(CommandLine(FilePath("true")), &output)); 693 EXPECT_STREQ("", output.c_str()); 694 695 EXPECT_FALSE(base::GetAppOutput(CommandLine(FilePath("false")), &output)); 696 697 std::vector<std::string> argv; 698 argv.push_back("/bin/echo"); 699 argv.push_back("-n"); 700 argv.push_back("foobar42"); 701 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 702 EXPECT_STREQ("foobar42", output.c_str()); 703#endif // defined(OS_ANDROID) 704} 705 706TEST_F(ProcessUtilTest, GetAppOutputRestricted) { 707 // Unfortunately, since we can't rely on the path, we need to know where 708 // everything is. So let's use /bin/sh, which is on every POSIX system, and 709 // its built-ins. 710 std::vector<std::string> argv; 711 argv.push_back(std::string(kShellPath)); // argv[0] 712 argv.push_back("-c"); // argv[1] 713 714 // On success, should set |output|. We use |/bin/sh -c 'exit 0'| instead of 715 // |true| since the location of the latter may be |/bin| or |/usr/bin| (and we 716 // need absolute paths). 717 argv.push_back("exit 0"); // argv[2]; equivalent to "true" 718 std::string output = "abc"; 719 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 100)); 720 EXPECT_STREQ("", output.c_str()); 721 722 argv[2] = "exit 1"; // equivalent to "false" 723 output = "before"; 724 EXPECT_FALSE(base::GetAppOutputRestricted(CommandLine(argv), 725 &output, 100)); 726 EXPECT_STREQ("", output.c_str()); 727 728 // Amount of output exactly equal to space allowed. 729 argv[2] = "echo 123456789"; // (the sh built-in doesn't take "-n") 730 output.clear(); 731 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 732 EXPECT_STREQ("123456789\n", output.c_str()); 733 734 // Amount of output greater than space allowed. 735 output.clear(); 736 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 5)); 737 EXPECT_STREQ("12345", output.c_str()); 738 739 // Amount of output less than space allowed. 740 output.clear(); 741 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 15)); 742 EXPECT_STREQ("123456789\n", output.c_str()); 743 744 // Zero space allowed. 745 output = "abc"; 746 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 0)); 747 EXPECT_STREQ("", output.c_str()); 748} 749 750#if !defined(OS_MACOSX) && !defined(OS_OPENBSD) 751// TODO(benwells): GetAppOutputRestricted should terminate applications 752// with SIGPIPE when we have enough output. http://crbug.com/88502 753TEST_F(ProcessUtilTest, GetAppOutputRestrictedSIGPIPE) { 754 std::vector<std::string> argv; 755 std::string output; 756 757 argv.push_back(std::string(kShellPath)); // argv[0] 758 argv.push_back("-c"); 759#if defined(OS_ANDROID) 760 argv.push_back("while echo 12345678901234567890; do :; done"); 761 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 762 EXPECT_STREQ("1234567890", output.c_str()); 763#else 764 argv.push_back("yes"); 765 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 766 EXPECT_STREQ("y\ny\ny\ny\ny\n", output.c_str()); 767#endif 768} 769#endif 770 771#if defined(ADDRESS_SANITIZER) && defined(OS_MACOSX) && \ 772 defined(ARCH_CPU_64_BITS) 773// Times out under AddressSanitizer on 64-bit OS X, see 774// http://crbug.com/298197. 775#define MAYBE_GetAppOutputRestrictedNoZombies \ 776 DISABLED_GetAppOutputRestrictedNoZombies 777#else 778#define MAYBE_GetAppOutputRestrictedNoZombies GetAppOutputRestrictedNoZombies 779#endif 780TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestrictedNoZombies) { 781 std::vector<std::string> argv; 782 783 argv.push_back(std::string(kShellPath)); // argv[0] 784 argv.push_back("-c"); // argv[1] 785 argv.push_back("echo 123456789012345678901234567890"); // argv[2] 786 787 // Run |GetAppOutputRestricted()| 300 (> default per-user processes on Mac OS 788 // 10.5) times with an output buffer big enough to capture all output. 789 for (int i = 0; i < 300; i++) { 790 std::string output; 791 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 100)); 792 EXPECT_STREQ("123456789012345678901234567890\n", output.c_str()); 793 } 794 795 // Ditto, but with an output buffer too small to capture all output. 796 for (int i = 0; i < 300; i++) { 797 std::string output; 798 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 799 EXPECT_STREQ("1234567890", output.c_str()); 800 } 801} 802 803TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) { 804 // Test getting output from a successful application. 805 std::vector<std::string> argv; 806 std::string output; 807 int exit_code; 808 argv.push_back(std::string(kShellPath)); // argv[0] 809 argv.push_back("-c"); // argv[1] 810 argv.push_back("echo foo"); // argv[2]; 811 EXPECT_TRUE(base::GetAppOutputWithExitCode(CommandLine(argv), &output, 812 &exit_code)); 813 EXPECT_STREQ("foo\n", output.c_str()); 814 EXPECT_EQ(exit_code, 0); 815 816 // Test getting output from an application which fails with a specific exit 817 // code. 818 output.clear(); 819 argv[2] = "echo foo; exit 2"; 820 EXPECT_TRUE(base::GetAppOutputWithExitCode(CommandLine(argv), &output, 821 &exit_code)); 822 EXPECT_STREQ("foo\n", output.c_str()); 823 EXPECT_EQ(exit_code, 2); 824} 825 826TEST_F(ProcessUtilTest, GetParentProcessId) { 827 base::ProcessId ppid = base::GetParentProcessId(base::GetCurrentProcId()); 828 EXPECT_EQ(ppid, getppid()); 829} 830 831#if defined(OS_LINUX) || defined(OS_ANDROID) 832TEST_F(ProcessUtilTest, ParseProcStatCPU) { 833 // /proc/self/stat for a process running "top". 834 const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 " 835 "4202496 471 0 0 0 " 836 "12 16 0 0 " // <- These are the goods. 837 "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 " 838 "4246868 140733983044336 18446744073709551615 140244213071219 " 839 "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0"; 840 EXPECT_EQ(12 + 16, base::ParseProcStatCPU(kTopStat)); 841 842 // cat /proc/self/stat on a random other machine I have. 843 const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 " 844 "0 142 0 0 0 " 845 "0 0 0 0 " // <- No CPU, apparently. 846 "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 " 847 "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0"; 848 849 EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat)); 850} 851 852// Disable on Android because base_unittests runs inside a Dalvik VM that 853// starts and stop threads (crbug.com/175563). 854#if !defined(OS_ANDROID) 855TEST_F(ProcessUtilTest, GetNumberOfThreads) { 856 const base::ProcessHandle current = base::GetCurrentProcessHandle(); 857 const int initial_threads = base::GetNumberOfThreads(current); 858 ASSERT_GT(initial_threads, 0); 859 const int kNumAdditionalThreads = 10; 860 { 861 scoped_ptr<base::Thread> my_threads[kNumAdditionalThreads]; 862 for (int i = 0; i < kNumAdditionalThreads; ++i) { 863 my_threads[i].reset(new base::Thread("GetNumberOfThreadsTest")); 864 my_threads[i]->Start(); 865 ASSERT_EQ(base::GetNumberOfThreads(current), initial_threads + 1 + i); 866 } 867 } 868 // The Thread destructor will stop them. 869 ASSERT_EQ(initial_threads, base::GetNumberOfThreads(current)); 870} 871#endif // !defined(OS_ANDROID) 872 873#endif // defined(OS_LINUX) || defined(OS_ANDROID) 874 875// TODO(port): port those unit tests. 876bool IsProcessDead(base::ProcessHandle child) { 877 // waitpid() will actually reap the process which is exactly NOT what we 878 // want to test for. The good thing is that if it can't find the process 879 // we'll get a nice value for errno which we can test for. 880 const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG)); 881 return result == -1 && errno == ECHILD; 882} 883 884TEST_F(ProcessUtilTest, DelayedTermination) { 885 base::ProcessHandle child_process = 886 SpawnChild("process_util_test_never_die", false); 887 ASSERT_TRUE(child_process); 888 base::EnsureProcessTerminated(child_process); 889 base::WaitForSingleProcess(child_process, base::TimeDelta::FromSeconds(5)); 890 891 // Check that process was really killed. 892 EXPECT_TRUE(IsProcessDead(child_process)); 893 base::CloseProcessHandle(child_process); 894} 895 896MULTIPROCESS_TEST_MAIN(process_util_test_never_die) { 897 while (1) { 898 sleep(500); 899 } 900 return 0; 901} 902 903TEST_F(ProcessUtilTest, ImmediateTermination) { 904 base::ProcessHandle child_process = 905 SpawnChild("process_util_test_die_immediately", false); 906 ASSERT_TRUE(child_process); 907 // Give it time to die. 908 sleep(2); 909 base::EnsureProcessTerminated(child_process); 910 911 // Check that process was really killed. 912 EXPECT_TRUE(IsProcessDead(child_process)); 913 base::CloseProcessHandle(child_process); 914} 915 916MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) { 917 return 0; 918} 919 920#endif // defined(OS_POSIX) 921