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