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