1// Copyright (c) 2011 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/eintr_wrapper.h" 11#include "base/file_path.h" 12#include "base/logging.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/path_service.h" 15#include "base/process_util.h" 16#include "base/test/multiprocess_test.h" 17#include "base/test/test_timeouts.h" 18#include "base/threading/platform_thread.h" 19#include "base/utf_string_conversions.h" 20#include "testing/gtest/include/gtest/gtest.h" 21#include "testing/multiprocess_func_list.h" 22 23#if defined(OS_LINUX) 24#include <errno.h> 25#include <malloc.h> 26#include <glib.h> 27#endif 28#if defined(OS_POSIX) 29#include <dlfcn.h> 30#include <fcntl.h> 31#include <signal.h> 32#include <sys/resource.h> 33#include <sys/socket.h> 34#endif 35#if defined(OS_WIN) 36#include <windows.h> 37#endif 38#if defined(OS_MACOSX) 39#include <malloc/malloc.h> 40#include "base/process_util_unittest_mac.h" 41#endif 42 43namespace { 44 45#if defined(OS_WIN) 46const wchar_t kProcessName[] = L"base_unittests.exe"; 47#else 48const wchar_t kProcessName[] = L"base_unittests"; 49#endif // defined(OS_WIN) 50 51const char kSignalFileSlow[] = "SlowChildProcess.die"; 52const char kSignalFileCrash[] = "CrashingChildProcess.die"; 53const char kSignalFileKill[] = "KilledChildProcess.die"; 54 55#if defined(OS_WIN) 56const int kExpectedStillRunningExitCode = 0x102; 57const int kExpectedKilledExitCode = 1; 58#else 59const int kExpectedStillRunningExitCode = 0; 60#endif 61 62// The longest we'll wait for a process, in milliseconds. 63const int kMaxWaitTimeMs = TestTimeouts::action_max_timeout_ms(); 64 65// Sleeps until file filename is created. 66void WaitToDie(const char* filename) { 67 FILE *fp; 68 do { 69 base::PlatformThread::Sleep(10); 70 fp = fopen(filename, "r"); 71 } while (!fp); 72 fclose(fp); 73} 74 75// Signals children they should die now. 76void SignalChildren(const char* filename) { 77 FILE *fp = fopen(filename, "w"); 78 fclose(fp); 79} 80 81// Using a pipe to the child to wait for an event was considered, but 82// there were cases in the past where pipes caused problems (other 83// libraries closing the fds, child deadlocking). This is a simple 84// case, so it's not worth the risk. Using wait loops is discouraged 85// in most instances. 86base::TerminationStatus WaitForChildTermination(base::ProcessHandle handle, 87 int* exit_code) { 88 // Now we wait until the result is something other than STILL_RUNNING. 89 base::TerminationStatus status = base::TERMINATION_STATUS_STILL_RUNNING; 90 const int kIntervalMs = 20; 91 int waited = 0; 92 do { 93 status = base::GetTerminationStatus(handle, exit_code); 94 base::PlatformThread::Sleep(kIntervalMs); 95 waited += kIntervalMs; 96 } while (status == base::TERMINATION_STATUS_STILL_RUNNING && 97 waited < kMaxWaitTimeMs); 98 99 return status; 100} 101 102} // namespace 103 104class ProcessUtilTest : public base::MultiProcessTest { 105#if defined(OS_POSIX) 106 public: 107 // Spawn a child process that counts how many file descriptors are open. 108 int CountOpenFDsInChild(); 109#endif 110}; 111 112MULTIPROCESS_TEST_MAIN(SimpleChildProcess) { 113 return 0; 114} 115 116TEST_F(ProcessUtilTest, SpawnChild) { 117 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); 118 ASSERT_NE(base::kNullProcessHandle, handle); 119 EXPECT_TRUE(base::WaitForSingleProcess(handle, kMaxWaitTimeMs)); 120 base::CloseProcessHandle(handle); 121} 122 123MULTIPROCESS_TEST_MAIN(SlowChildProcess) { 124 WaitToDie(kSignalFileSlow); 125 return 0; 126} 127 128TEST_F(ProcessUtilTest, KillSlowChild) { 129 remove(kSignalFileSlow); 130 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); 131 ASSERT_NE(base::kNullProcessHandle, handle); 132 SignalChildren(kSignalFileSlow); 133 EXPECT_TRUE(base::WaitForSingleProcess(handle, kMaxWaitTimeMs)); 134 base::CloseProcessHandle(handle); 135 remove(kSignalFileSlow); 136} 137 138TEST_F(ProcessUtilTest, GetTerminationStatusExit) { 139 remove(kSignalFileSlow); 140 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); 141 ASSERT_NE(base::kNullProcessHandle, handle); 142 143 int exit_code = 42; 144 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, 145 base::GetTerminationStatus(handle, &exit_code)); 146 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); 147 148 SignalChildren(kSignalFileSlow); 149 exit_code = 42; 150 base::TerminationStatus status = 151 WaitForChildTermination(handle, &exit_code); 152 EXPECT_EQ(base::TERMINATION_STATUS_NORMAL_TERMINATION, status); 153 EXPECT_EQ(0, exit_code); 154 base::CloseProcessHandle(handle); 155 remove(kSignalFileSlow); 156} 157 158#if !defined(OS_MACOSX) 159// This test is disabled on Mac, since it's flaky due to ReportCrash 160// taking a variable amount of time to parse and load the debug and 161// symbol data for this unit test's executable before firing the 162// signal handler. 163// 164// TODO(gspencer): turn this test process into a very small program 165// with no symbols (instead of using the multiprocess testing 166// framework) to reduce the ReportCrash overhead. 167 168MULTIPROCESS_TEST_MAIN(CrashingChildProcess) { 169 WaitToDie(kSignalFileCrash); 170#if defined(OS_POSIX) 171 // Have to disable to signal handler for segv so we can get a crash 172 // instead of an abnormal termination through the crash dump handler. 173 ::signal(SIGSEGV, SIG_DFL); 174#endif 175 // Make this process have a segmentation fault. 176 int* oops = NULL; 177 *oops = 0xDEAD; 178 return 1; 179} 180 181TEST_F(ProcessUtilTest, GetTerminationStatusCrash) { 182 remove(kSignalFileCrash); 183 base::ProcessHandle handle = this->SpawnChild("CrashingChildProcess", 184 false); 185 ASSERT_NE(base::kNullProcessHandle, handle); 186 187 int exit_code = 42; 188 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, 189 base::GetTerminationStatus(handle, &exit_code)); 190 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); 191 192 SignalChildren(kSignalFileCrash); 193 exit_code = 42; 194 base::TerminationStatus status = 195 WaitForChildTermination(handle, &exit_code); 196 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_CRASHED, status); 197 198#if defined(OS_WIN) 199 EXPECT_EQ(0xc0000005, exit_code); 200#elif defined(OS_POSIX) 201 int signaled = WIFSIGNALED(exit_code); 202 EXPECT_NE(0, signaled); 203 int signal = WTERMSIG(exit_code); 204 EXPECT_EQ(SIGSEGV, signal); 205#endif 206 base::CloseProcessHandle(handle); 207 208 // Reset signal handlers back to "normal". 209 base::EnableInProcessStackDumping(); 210 remove(kSignalFileCrash); 211} 212#endif // !defined(OS_MACOSX) 213 214MULTIPROCESS_TEST_MAIN(KilledChildProcess) { 215 WaitToDie(kSignalFileKill); 216#if defined(OS_WIN) 217 // Kill ourselves. 218 HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId()); 219 ::TerminateProcess(handle, kExpectedKilledExitCode); 220#elif defined(OS_POSIX) 221 // Send a SIGKILL to this process, just like the OOM killer would. 222 ::kill(getpid(), SIGKILL); 223#endif 224 return 1; 225} 226 227TEST_F(ProcessUtilTest, GetTerminationStatusKill) { 228 remove(kSignalFileKill); 229 base::ProcessHandle handle = this->SpawnChild("KilledChildProcess", 230 false); 231 ASSERT_NE(base::kNullProcessHandle, handle); 232 233 int exit_code = 42; 234 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, 235 base::GetTerminationStatus(handle, &exit_code)); 236 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); 237 238 SignalChildren(kSignalFileKill); 239 exit_code = 42; 240 base::TerminationStatus status = 241 WaitForChildTermination(handle, &exit_code); 242 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status); 243#if defined(OS_WIN) 244 EXPECT_EQ(kExpectedKilledExitCode, exit_code); 245#elif defined(OS_POSIX) 246 int signaled = WIFSIGNALED(exit_code); 247 EXPECT_NE(0, signaled); 248 int signal = WTERMSIG(exit_code); 249 EXPECT_EQ(SIGKILL, signal); 250#endif 251 base::CloseProcessHandle(handle); 252 remove(kSignalFileKill); 253} 254 255// Ensure that the priority of a process is restored correctly after 256// backgrounding and restoring. 257// Note: a platform may not be willing or able to lower the priority of 258// a process. The calls to SetProcessBackground should be noops then. 259TEST_F(ProcessUtilTest, SetProcessBackgrounded) { 260 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); 261 base::Process process(handle); 262 int old_priority = process.GetPriority(); 263 process.SetProcessBackgrounded(true); 264 process.SetProcessBackgrounded(false); 265 int new_priority = process.GetPriority(); 266 EXPECT_EQ(old_priority, new_priority); 267} 268 269// TODO(estade): if possible, port these 2 tests. 270#if defined(OS_WIN) 271TEST_F(ProcessUtilTest, EnableLFH) { 272 ASSERT_TRUE(base::EnableLowFragmentationHeap()); 273 if (IsDebuggerPresent()) { 274 // Under these conditions, LFH can't be enabled. There's no point to test 275 // anything. 276 const char* no_debug_env = getenv("_NO_DEBUG_HEAP"); 277 if (!no_debug_env || strcmp(no_debug_env, "1")) 278 return; 279 } 280 HANDLE heaps[1024] = { 0 }; 281 unsigned number_heaps = GetProcessHeaps(1024, heaps); 282 EXPECT_GT(number_heaps, 0u); 283 for (unsigned i = 0; i < number_heaps; ++i) { 284 ULONG flag = 0; 285 SIZE_T length; 286 ASSERT_NE(0, HeapQueryInformation(heaps[i], 287 HeapCompatibilityInformation, 288 &flag, 289 sizeof(flag), 290 &length)); 291 // If flag is 0, the heap is a standard heap that does not support 292 // look-asides. If flag is 1, the heap supports look-asides. If flag is 2, 293 // the heap is a low-fragmentation heap (LFH). Note that look-asides are not 294 // supported on the LFH. 295 296 // We don't have any documented way of querying the HEAP_NO_SERIALIZE flag. 297 EXPECT_LE(flag, 2u); 298 EXPECT_NE(flag, 1u); 299 } 300} 301 302TEST_F(ProcessUtilTest, CalcFreeMemory) { 303 scoped_ptr<base::ProcessMetrics> metrics( 304 base::ProcessMetrics::CreateProcessMetrics(::GetCurrentProcess())); 305 ASSERT_TRUE(NULL != metrics.get()); 306 307 // Typical values here is ~1900 for total and ~1000 for largest. Obviously 308 // it depends in what other tests have done to this process. 309 base::FreeMBytes free_mem1 = {0}; 310 EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem1)); 311 EXPECT_LT(10u, free_mem1.total); 312 EXPECT_LT(10u, free_mem1.largest); 313 EXPECT_GT(2048u, free_mem1.total); 314 EXPECT_GT(2048u, free_mem1.largest); 315 EXPECT_GE(free_mem1.total, free_mem1.largest); 316 EXPECT_TRUE(NULL != free_mem1.largest_ptr); 317 318 // Allocate 20M and check again. It should have gone down. 319 const int kAllocMB = 20; 320 scoped_array<char> alloc(new char[kAllocMB * 1024 * 1024]); 321 size_t expected_total = free_mem1.total - kAllocMB; 322 size_t expected_largest = free_mem1.largest; 323 324 base::FreeMBytes free_mem2 = {0}; 325 EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem2)); 326 EXPECT_GE(free_mem2.total, free_mem2.largest); 327 EXPECT_GE(expected_total, free_mem2.total); 328 EXPECT_GE(expected_largest, free_mem2.largest); 329 EXPECT_TRUE(NULL != free_mem2.largest_ptr); 330} 331 332TEST_F(ProcessUtilTest, GetAppOutput) { 333 // Let's create a decently long message. 334 std::string message; 335 for (int i = 0; i < 1025; i++) { // 1025 so it does not end on a kilo-byte 336 // boundary. 337 message += "Hello!"; 338 } 339 340 FilePath python_runtime; 341 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &python_runtime)); 342 python_runtime = python_runtime.Append(FILE_PATH_LITERAL("third_party")) 343 .Append(FILE_PATH_LITERAL("python_26")) 344 .Append(FILE_PATH_LITERAL("python.exe")); 345 346 CommandLine cmd_line(python_runtime); 347 cmd_line.AppendArg("-c"); 348 cmd_line.AppendArg("import sys; sys.stdout.write('" + message + "');"); 349 std::string output; 350 ASSERT_TRUE(base::GetAppOutput(cmd_line, &output)); 351 EXPECT_EQ(message, output); 352 353 // Let's make sure stderr is ignored. 354 CommandLine other_cmd_line(python_runtime); 355 other_cmd_line.AppendArg("-c"); 356 other_cmd_line.AppendArg("import sys; sys.stderr.write('Hello!');"); 357 output.clear(); 358 ASSERT_TRUE(base::GetAppOutput(other_cmd_line, &output)); 359 EXPECT_EQ("", output); 360} 361 362TEST_F(ProcessUtilTest, LaunchAsUser) { 363 base::UserTokenHandle token; 364 ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)); 365 std::wstring cmdline = 366 this->MakeCmdLine("SimpleChildProcess", false).command_line_string(); 367 EXPECT_TRUE(base::LaunchAppAsUser(token, cmdline, false, NULL)); 368} 369 370#endif // defined(OS_WIN) 371 372#if defined(OS_POSIX) 373 374namespace { 375 376// Returns the maximum number of files that a process can have open. 377// Returns 0 on error. 378int GetMaxFilesOpenInProcess() { 379 struct rlimit rlim; 380 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) { 381 return 0; 382 } 383 384 // rlim_t is a uint64 - clip to maxint. We do this since FD #s are ints 385 // which are all 32 bits on the supported platforms. 386 rlim_t max_int = static_cast<rlim_t>(std::numeric_limits<int32>::max()); 387 if (rlim.rlim_cur > max_int) { 388 return max_int; 389 } 390 391 return rlim.rlim_cur; 392} 393 394const int kChildPipe = 20; // FD # for write end of pipe in child process. 395 396} // namespace 397 398MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) { 399 // This child process counts the number of open FDs, it then writes that 400 // number out to a pipe connected to the parent. 401 int num_open_files = 0; 402 int write_pipe = kChildPipe; 403 int max_files = GetMaxFilesOpenInProcess(); 404 for (int i = STDERR_FILENO + 1; i < max_files; i++) { 405 if (i != kChildPipe) { 406 int fd; 407 if ((fd = HANDLE_EINTR(dup(i))) != -1) { 408 close(fd); 409 num_open_files += 1; 410 } 411 } 412 } 413 414 int written = HANDLE_EINTR(write(write_pipe, &num_open_files, 415 sizeof(num_open_files))); 416 DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files)); 417 int ret = HANDLE_EINTR(close(write_pipe)); 418 DPCHECK(ret == 0); 419 420 return 0; 421} 422 423int ProcessUtilTest::CountOpenFDsInChild() { 424 int fds[2]; 425 if (pipe(fds) < 0) 426 NOTREACHED(); 427 428 base::file_handle_mapping_vector fd_mapping_vec; 429 fd_mapping_vec.push_back(std::pair<int, int>(fds[1], kChildPipe)); 430 base::ProcessHandle handle = this->SpawnChild( 431 "ProcessUtilsLeakFDChildProcess", fd_mapping_vec, false); 432 CHECK(handle); 433 int ret = HANDLE_EINTR(close(fds[1])); 434 DPCHECK(ret == 0); 435 436 // Read number of open files in client process from pipe; 437 int num_open_files = -1; 438 ssize_t bytes_read = 439 HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files))); 440 CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files))); 441 442 CHECK(base::WaitForSingleProcess(handle, 1000)); 443 base::CloseProcessHandle(handle); 444 ret = HANDLE_EINTR(close(fds[0])); 445 DPCHECK(ret == 0); 446 447 return num_open_files; 448} 449 450TEST_F(ProcessUtilTest, FDRemapping) { 451 int fds_before = CountOpenFDsInChild(); 452 453 // open some dummy fds to make sure they don't propagate over to the 454 // child process. 455 int dev_null = open("/dev/null", O_RDONLY); 456 int sockets[2]; 457 socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); 458 459 int fds_after = CountOpenFDsInChild(); 460 461 ASSERT_EQ(fds_after, fds_before); 462 463 int ret; 464 ret = HANDLE_EINTR(close(sockets[0])); 465 DPCHECK(ret == 0); 466 ret = HANDLE_EINTR(close(sockets[1])); 467 DPCHECK(ret == 0); 468 ret = HANDLE_EINTR(close(dev_null)); 469 DPCHECK(ret == 0); 470} 471 472namespace { 473 474std::string TestLaunchApp(const base::environment_vector& env_changes) { 475 std::vector<std::string> args; 476 base::file_handle_mapping_vector fds_to_remap; 477 base::ProcessHandle handle; 478 479 args.push_back("bash"); 480 args.push_back("-c"); 481 args.push_back("echo $BASE_TEST"); 482 483 int fds[2]; 484 PCHECK(pipe(fds) == 0); 485 486 fds_to_remap.push_back(std::make_pair(fds[1], 1)); 487 EXPECT_TRUE(base::LaunchApp(args, env_changes, fds_to_remap, 488 true /* wait for exit */, &handle)); 489 PCHECK(HANDLE_EINTR(close(fds[1])) == 0); 490 491 char buf[512]; 492 const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf))); 493 PCHECK(n > 0); 494 495 PCHECK(HANDLE_EINTR(close(fds[0])) == 0); 496 497 return std::string(buf, n); 498} 499 500const char kLargeString[] = 501 "0123456789012345678901234567890123456789012345678901234567890123456789" 502 "0123456789012345678901234567890123456789012345678901234567890123456789" 503 "0123456789012345678901234567890123456789012345678901234567890123456789" 504 "0123456789012345678901234567890123456789012345678901234567890123456789" 505 "0123456789012345678901234567890123456789012345678901234567890123456789" 506 "0123456789012345678901234567890123456789012345678901234567890123456789" 507 "0123456789012345678901234567890123456789012345678901234567890123456789"; 508 509} // namespace 510 511TEST_F(ProcessUtilTest, LaunchApp) { 512 base::environment_vector env_changes; 513 514 env_changes.push_back(std::make_pair(std::string("BASE_TEST"), 515 std::string("bar"))); 516 EXPECT_EQ("bar\n", TestLaunchApp(env_changes)); 517 env_changes.clear(); 518 519 EXPECT_EQ(0, setenv("BASE_TEST", "testing", 1 /* override */)); 520 EXPECT_EQ("testing\n", TestLaunchApp(env_changes)); 521 522 env_changes.push_back(std::make_pair(std::string("BASE_TEST"), 523 std::string(""))); 524 EXPECT_EQ("\n", TestLaunchApp(env_changes)); 525 526 env_changes[0].second = "foo"; 527 EXPECT_EQ("foo\n", TestLaunchApp(env_changes)); 528 529 env_changes.clear(); 530 EXPECT_EQ(0, setenv("BASE_TEST", kLargeString, 1 /* override */)); 531 EXPECT_EQ(std::string(kLargeString) + "\n", TestLaunchApp(env_changes)); 532 533 env_changes.push_back(std::make_pair(std::string("BASE_TEST"), 534 std::string("wibble"))); 535 EXPECT_EQ("wibble\n", TestLaunchApp(env_changes)); 536} 537 538TEST_F(ProcessUtilTest, AlterEnvironment) { 539 const char* const empty[] = { NULL }; 540 const char* const a2[] = { "A=2", NULL }; 541 base::environment_vector changes; 542 char** e; 543 544 e = base::AlterEnvironment(changes, empty); 545 EXPECT_TRUE(e[0] == NULL); 546 delete[] e; 547 548 changes.push_back(std::make_pair(std::string("A"), std::string("1"))); 549 e = base::AlterEnvironment(changes, empty); 550 EXPECT_EQ(std::string("A=1"), e[0]); 551 EXPECT_TRUE(e[1] == NULL); 552 delete[] e; 553 554 changes.clear(); 555 changes.push_back(std::make_pair(std::string("A"), std::string(""))); 556 e = base::AlterEnvironment(changes, empty); 557 EXPECT_TRUE(e[0] == NULL); 558 delete[] e; 559 560 changes.clear(); 561 e = base::AlterEnvironment(changes, a2); 562 EXPECT_EQ(std::string("A=2"), e[0]); 563 EXPECT_TRUE(e[1] == NULL); 564 delete[] e; 565 566 changes.clear(); 567 changes.push_back(std::make_pair(std::string("A"), std::string("1"))); 568 e = base::AlterEnvironment(changes, a2); 569 EXPECT_EQ(std::string("A=1"), e[0]); 570 EXPECT_TRUE(e[1] == NULL); 571 delete[] e; 572 573 changes.clear(); 574 changes.push_back(std::make_pair(std::string("A"), std::string(""))); 575 e = base::AlterEnvironment(changes, a2); 576 EXPECT_TRUE(e[0] == NULL); 577 delete[] e; 578} 579 580TEST_F(ProcessUtilTest, GetAppOutput) { 581 std::string output; 582 EXPECT_TRUE(base::GetAppOutput(CommandLine(FilePath("true")), &output)); 583 EXPECT_STREQ("", output.c_str()); 584 585 EXPECT_FALSE(base::GetAppOutput(CommandLine(FilePath("false")), &output)); 586 587 std::vector<std::string> argv; 588 argv.push_back("/bin/echo"); 589 argv.push_back("-n"); 590 argv.push_back("foobar42"); 591 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 592 EXPECT_STREQ("foobar42", output.c_str()); 593} 594 595TEST_F(ProcessUtilTest, GetAppOutputRestricted) { 596 // Unfortunately, since we can't rely on the path, we need to know where 597 // everything is. So let's use /bin/sh, which is on every POSIX system, and 598 // its built-ins. 599 std::vector<std::string> argv; 600 argv.push_back("/bin/sh"); // argv[0] 601 argv.push_back("-c"); // argv[1] 602 603 // On success, should set |output|. We use |/bin/sh -c 'exit 0'| instead of 604 // |true| since the location of the latter may be |/bin| or |/usr/bin| (and we 605 // need absolute paths). 606 argv.push_back("exit 0"); // argv[2]; equivalent to "true" 607 std::string output = "abc"; 608 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 100)); 609 EXPECT_STREQ("", output.c_str()); 610 611 argv[2] = "exit 1"; // equivalent to "false" 612 output = "before"; 613 EXPECT_FALSE(base::GetAppOutputRestricted(CommandLine(argv), 614 &output, 100)); 615 EXPECT_STREQ("", output.c_str()); 616 617 // Amount of output exactly equal to space allowed. 618 argv[2] = "echo 123456789"; // (the sh built-in doesn't take "-n") 619 output.clear(); 620 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 621 EXPECT_STREQ("123456789\n", output.c_str()); 622 623 // Amount of output greater than space allowed. 624 output.clear(); 625 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 5)); 626 EXPECT_STREQ("12345", output.c_str()); 627 628 // Amount of output less than space allowed. 629 output.clear(); 630 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 15)); 631 EXPECT_STREQ("123456789\n", output.c_str()); 632 633 // Zero space allowed. 634 output = "abc"; 635 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 0)); 636 EXPECT_STREQ("", output.c_str()); 637} 638 639TEST_F(ProcessUtilTest, GetAppOutputRestrictedNoZombies) { 640 std::vector<std::string> argv; 641 argv.push_back("/bin/sh"); // argv[0] 642 argv.push_back("-c"); // argv[1] 643 argv.push_back("echo 123456789012345678901234567890"); // argv[2] 644 645 // Run |GetAppOutputRestricted()| 300 (> default per-user processes on Mac OS 646 // 10.5) times with an output buffer big enough to capture all output. 647 for (int i = 0; i < 300; i++) { 648 std::string output; 649 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 100)); 650 EXPECT_STREQ("123456789012345678901234567890\n", output.c_str()); 651 } 652 653 // Ditto, but with an output buffer too small to capture all output. 654 for (int i = 0; i < 300; i++) { 655 std::string output; 656 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 657 EXPECT_STREQ("1234567890", output.c_str()); 658 } 659} 660 661TEST_F(ProcessUtilTest, GetParentProcessId) { 662 base::ProcessId ppid = base::GetParentProcessId(base::GetCurrentProcId()); 663 EXPECT_EQ(ppid, getppid()); 664} 665 666#if defined(OS_LINUX) 667TEST_F(ProcessUtilTest, ParseProcStatCPU) { 668 // /proc/self/stat for a process running "top". 669 const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 " 670 "4202496 471 0 0 0 " 671 "12 16 0 0 " // <- These are the goods. 672 "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 " 673 "4246868 140733983044336 18446744073709551615 140244213071219 " 674 "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0"; 675 EXPECT_EQ(12 + 16, base::ParseProcStatCPU(kTopStat)); 676 677 // cat /proc/self/stat on a random other machine I have. 678 const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 " 679 "0 142 0 0 0 " 680 "0 0 0 0 " // <- No CPU, apparently. 681 "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 " 682 "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0"; 683 684 EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat)); 685} 686#endif // defined(OS_LINUX) 687 688#endif // defined(OS_POSIX) 689 690// TODO(vandebo) make this work on Windows too. 691#if !defined(OS_WIN) 692 693#if defined(USE_TCMALLOC) 694extern "C" { 695int tc_set_new_mode(int mode); 696} 697#endif // defined(USE_TCMALLOC) 698 699class OutOfMemoryDeathTest : public testing::Test { 700 public: 701 OutOfMemoryDeathTest() 702 : value_(NULL), 703 // Make test size as large as possible minus a few pages so 704 // that alignment or other rounding doesn't make it wrap. 705 test_size_(std::numeric_limits<std::size_t>::max() - 12 * 1024), 706 signed_test_size_(std::numeric_limits<ssize_t>::max()) { 707 } 708 709 virtual void SetUp() { 710#if defined(USE_TCMALLOC) 711 tc_set_new_mode(1); 712 } 713 714 virtual void TearDown() { 715 tc_set_new_mode(0); 716#endif // defined(USE_TCMALLOC) 717 } 718 719 void SetUpInDeathAssert() { 720 // Must call EnableTerminationOnOutOfMemory() because that is called from 721 // chrome's main function and therefore hasn't been called yet. 722 // Since this call may result in another thread being created and death 723 // tests shouldn't be started in a multithread environment, this call 724 // should be done inside of the ASSERT_DEATH. 725 base::EnableTerminationOnOutOfMemory(); 726 } 727 728 void* value_; 729 size_t test_size_; 730 ssize_t signed_test_size_; 731}; 732 733TEST_F(OutOfMemoryDeathTest, New) { 734 ASSERT_DEATH({ 735 SetUpInDeathAssert(); 736 value_ = operator new(test_size_); 737 }, ""); 738} 739 740TEST_F(OutOfMemoryDeathTest, NewArray) { 741 ASSERT_DEATH({ 742 SetUpInDeathAssert(); 743 value_ = new char[test_size_]; 744 }, ""); 745} 746 747TEST_F(OutOfMemoryDeathTest, Malloc) { 748 ASSERT_DEATH({ 749 SetUpInDeathAssert(); 750 value_ = malloc(test_size_); 751 }, ""); 752} 753 754TEST_F(OutOfMemoryDeathTest, Realloc) { 755 ASSERT_DEATH({ 756 SetUpInDeathAssert(); 757 value_ = realloc(NULL, test_size_); 758 }, ""); 759} 760 761TEST_F(OutOfMemoryDeathTest, Calloc) { 762 ASSERT_DEATH({ 763 SetUpInDeathAssert(); 764 value_ = calloc(1024, test_size_ / 1024L); 765 }, ""); 766} 767 768TEST_F(OutOfMemoryDeathTest, Valloc) { 769 ASSERT_DEATH({ 770 SetUpInDeathAssert(); 771 value_ = valloc(test_size_); 772 }, ""); 773} 774 775#if defined(OS_LINUX) 776TEST_F(OutOfMemoryDeathTest, Pvalloc) { 777 ASSERT_DEATH({ 778 SetUpInDeathAssert(); 779 value_ = pvalloc(test_size_); 780 }, ""); 781} 782 783TEST_F(OutOfMemoryDeathTest, Memalign) { 784 ASSERT_DEATH({ 785 SetUpInDeathAssert(); 786 value_ = memalign(4, test_size_); 787 }, ""); 788} 789 790TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) { 791 // g_try_malloc is documented to return NULL on failure. (g_malloc is the 792 // 'safe' default that crashes if allocation fails). However, since we have 793 // hopefully overridden malloc, even g_try_malloc should fail. This tests 794 // that the run-time symbol resolution is overriding malloc for shared 795 // libraries as well as for our code. 796 ASSERT_DEATH({ 797 SetUpInDeathAssert(); 798 value_ = g_try_malloc(test_size_); 799 }, ""); 800} 801#endif // OS_LINUX 802 803#if defined(OS_POSIX) 804TEST_F(OutOfMemoryDeathTest, Posix_memalign) { 805 typedef int (*memalign_t)(void **, size_t, size_t); 806#if defined(OS_MACOSX) 807 // posix_memalign only exists on >= 10.6. Use dlsym to grab it at runtime 808 // because it may not be present in the SDK used for compilation. 809 memalign_t memalign = 810 reinterpret_cast<memalign_t>(dlsym(RTLD_DEFAULT, "posix_memalign")); 811#else 812 memalign_t memalign = posix_memalign; 813#endif // OS_* 814 if (memalign) { 815 // Grab the return value of posix_memalign to silence a compiler warning 816 // about unused return values. We don't actually care about the return 817 // value, since we're asserting death. 818 ASSERT_DEATH({ 819 SetUpInDeathAssert(); 820 EXPECT_EQ(ENOMEM, memalign(&value_, 8, test_size_)); 821 }, ""); 822 } 823} 824#endif // OS_POSIX 825 826#if defined(OS_MACOSX) 827 828// Purgeable zone tests (if it exists) 829 830TEST_F(OutOfMemoryDeathTest, MallocPurgeable) { 831 malloc_zone_t* zone = base::GetPurgeableZone(); 832 if (zone) 833 ASSERT_DEATH({ 834 SetUpInDeathAssert(); 835 value_ = malloc_zone_malloc(zone, test_size_); 836 }, ""); 837} 838 839TEST_F(OutOfMemoryDeathTest, ReallocPurgeable) { 840 malloc_zone_t* zone = base::GetPurgeableZone(); 841 if (zone) 842 ASSERT_DEATH({ 843 SetUpInDeathAssert(); 844 value_ = malloc_zone_realloc(zone, NULL, test_size_); 845 }, ""); 846} 847 848TEST_F(OutOfMemoryDeathTest, CallocPurgeable) { 849 malloc_zone_t* zone = base::GetPurgeableZone(); 850 if (zone) 851 ASSERT_DEATH({ 852 SetUpInDeathAssert(); 853 value_ = malloc_zone_calloc(zone, 1024, test_size_ / 1024L); 854 }, ""); 855} 856 857TEST_F(OutOfMemoryDeathTest, VallocPurgeable) { 858 malloc_zone_t* zone = base::GetPurgeableZone(); 859 if (zone) 860 ASSERT_DEATH({ 861 SetUpInDeathAssert(); 862 value_ = malloc_zone_valloc(zone, test_size_); 863 }, ""); 864} 865 866TEST_F(OutOfMemoryDeathTest, PosixMemalignPurgeable) { 867 malloc_zone_t* zone = base::GetPurgeableZone(); 868 869 typedef void* (*zone_memalign_t)(malloc_zone_t*, size_t, size_t); 870 // malloc_zone_memalign only exists on >= 10.6. Use dlsym to grab it at 871 // runtime because it may not be present in the SDK used for compilation. 872 zone_memalign_t zone_memalign = 873 reinterpret_cast<zone_memalign_t>( 874 dlsym(RTLD_DEFAULT, "malloc_zone_memalign")); 875 876 if (zone && zone_memalign) { 877 ASSERT_DEATH({ 878 SetUpInDeathAssert(); 879 value_ = zone_memalign(zone, 8, test_size_); 880 }, ""); 881 } 882} 883 884// Since these allocation functions take a signed size, it's possible that 885// calling them just once won't be enough to exhaust memory. In the 32-bit 886// environment, it's likely that these allocation attempts will fail because 887// not enough contiguous address space is availble. In the 64-bit environment, 888// it's likely that they'll fail because they would require a preposterous 889// amount of (virtual) memory. 890 891TEST_F(OutOfMemoryDeathTest, CFAllocatorSystemDefault) { 892 ASSERT_DEATH({ 893 SetUpInDeathAssert(); 894 while ((value_ = 895 base::AllocateViaCFAllocatorSystemDefault(signed_test_size_))) {} 896 }, ""); 897} 898 899TEST_F(OutOfMemoryDeathTest, CFAllocatorMalloc) { 900 ASSERT_DEATH({ 901 SetUpInDeathAssert(); 902 while ((value_ = 903 base::AllocateViaCFAllocatorMalloc(signed_test_size_))) {} 904 }, ""); 905} 906 907TEST_F(OutOfMemoryDeathTest, CFAllocatorMallocZone) { 908 ASSERT_DEATH({ 909 SetUpInDeathAssert(); 910 while ((value_ = 911 base::AllocateViaCFAllocatorMallocZone(signed_test_size_))) {} 912 }, ""); 913} 914 915#if !defined(ARCH_CPU_64_BITS) 916 917// See process_util_unittest_mac.mm for an explanation of why this test isn't 918// run in the 64-bit environment. 919 920TEST_F(OutOfMemoryDeathTest, PsychoticallyBigObjCObject) { 921 ASSERT_DEATH({ 922 SetUpInDeathAssert(); 923 while ((value_ = base::AllocatePsychoticallyBigObjCObject())) {} 924 }, ""); 925} 926 927#endif // !ARCH_CPU_64_BITS 928#endif // OS_MACOSX 929 930#endif // !defined(OS_WIN) 931