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