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