Home | History | Annotate | Download | only in browser
      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 #include "chrome/browser/process_info_snapshot.h"
      6 
      7 #include <sys/types.h>  // For |uid_t| (and |pid_t|).
      8 #include <unistd.h>  // For |getpid()|, |getuid()|, etc.
      9 
     10 #include <vector>
     11 
     12 #include "base/command_line.h"
     13 #include "base/files/file_path.h"
     14 #include "base/logging.h"
     15 #include "base/posix/eintr_wrapper.h"
     16 #include "base/process/kill.h"
     17 #include "base/process/launch.h"
     18 #include "base/process/process_handle.h"
     19 #include "base/process/process_metrics.h"
     20 #include "testing/gtest/include/gtest/gtest.h"
     21 
     22 typedef testing::Test ProcessInfoSnapshotMacTest;
     23 
     24 TEST_F(ProcessInfoSnapshotMacTest, FindPidOneTest) {
     25   // Sample process with PID 1, which should exist and presumably belong to
     26   // root.
     27   std::vector<base::ProcessId> pid_list;
     28   pid_list.push_back(1);
     29   ProcessInfoSnapshot snapshot;
     30   ASSERT_TRUE(snapshot.Sample(pid_list));
     31 
     32   ProcessInfoSnapshot::ProcInfoEntry proc_info;
     33   ASSERT_TRUE(snapshot.GetProcInfo(1, &proc_info));
     34   EXPECT_EQ(1, static_cast<int64>(proc_info.pid));
     35   EXPECT_EQ(0, static_cast<int64>(proc_info.ppid));
     36   EXPECT_EQ(0, static_cast<int64>(proc_info.uid));
     37   EXPECT_EQ(0, static_cast<int64>(proc_info.euid));
     38   EXPECT_GE(proc_info.rss, 0u);
     39   EXPECT_GT(proc_info.vsize, 0u);
     40 
     41   // Try out the |Get...OfPID()|, but don't examine the results, since they
     42   // depend on how we map |ProcInfoEntry| to |...KBytes|.
     43   base::CommittedKBytes usage;
     44   EXPECT_TRUE(snapshot.GetCommittedKBytesOfPID(1, &usage));
     45   base::WorkingSetKBytes ws_usage;
     46   EXPECT_TRUE(snapshot.GetWorkingSetKBytesOfPID(1, &ws_usage));
     47 
     48   // Make sure it hasn't picked up some other PID (say, 2).
     49   EXPECT_FALSE(snapshot.GetProcInfo(2, &proc_info));
     50 
     51   // Make sure PID 2 still isn't there (in case I mess up my use of std::map).
     52   EXPECT_FALSE(snapshot.GetProcInfo(2, &proc_info));
     53 
     54   // Test |Reset()|.
     55   snapshot.Reset();
     56   EXPECT_FALSE(snapshot.GetProcInfo(1, &proc_info));
     57 }
     58 
     59 TEST_F(ProcessInfoSnapshotMacTest, FindPidSelfTest) {
     60   // Sample this process and its parent.
     61   base::ProcessId pid = static_cast<base::ProcessId>(getpid());
     62   base::ProcessId ppid = static_cast<base::ProcessId>(getppid());
     63   uid_t uid = getuid();
     64   uid_t euid = geteuid();
     65   EXPECT_NE(static_cast<int64>(ppid), 0);
     66 
     67   std::vector<base::ProcessId> pid_list;
     68   pid_list.push_back(pid);
     69   pid_list.push_back(ppid);
     70   ProcessInfoSnapshot snapshot;
     71   ASSERT_TRUE(snapshot.Sample(pid_list));
     72 
     73   // Find our process.
     74   ProcessInfoSnapshot::ProcInfoEntry proc_info;
     75   ASSERT_TRUE(snapshot.GetProcInfo(pid, &proc_info));
     76   EXPECT_EQ(pid, proc_info.pid);
     77   EXPECT_EQ(ppid, proc_info.ppid);
     78   EXPECT_EQ(uid, proc_info.uid);
     79   EXPECT_EQ(euid, proc_info.euid);
     80   EXPECT_GE(proc_info.rss, 100u);     // Sanity check: we're running, so we
     81                                       // should occupy at least 100 kilobytes.
     82   EXPECT_GE(proc_info.vsize, 1024u);  // Sanity check: our |vsize| is presumably
     83                                       // at least a megabyte.
     84   EXPECT_GE(proc_info.rshrd, 1024u);  // Shared memory should also > 1 MB.
     85   EXPECT_GE(proc_info.rprvt, 1024u);  // Same with private memory.
     86 
     87   // Find our parent.
     88   ASSERT_TRUE(snapshot.GetProcInfo(ppid, &proc_info));
     89   EXPECT_EQ(ppid, proc_info.pid);
     90   EXPECT_NE(static_cast<int64>(proc_info.ppid), 0);
     91   EXPECT_EQ(uid, proc_info.uid);    // This (and the following) should be true
     92   EXPECT_EQ(euid, proc_info.euid);  // under reasonable circumstances.
     93   // Can't say anything definite about its |rss|.
     94   EXPECT_GT(proc_info.vsize, 0u);   // Its |vsize| should be nonzero though.
     95 }
     96 
     97 // To verify that ProcessInfoSnapshot is getting the actual uid and effective
     98 // uid, this test runs top. top should have a uid of the caller and effective
     99 // uid of 0 (root).
    100 TEST_F(ProcessInfoSnapshotMacTest, EffectiveVsRealUserIDTest) {
    101   // Create a pipe to be able to read top's output.
    102   int fds[2];
    103   PCHECK(pipe(fds) == 0);
    104   base::FileHandleMappingVector fds_to_remap;
    105   fds_to_remap.push_back(std::make_pair(fds[1], 1));
    106 
    107   // Hook up top's stderr to the test process' stderr.
    108   fds_to_remap.push_back(std::make_pair(fileno(stderr), 2));
    109 
    110   std::vector<std::string> argv;
    111   argv.push_back("/usr/bin/top");
    112   argv.push_back("-l");
    113   argv.push_back("0");
    114 
    115   base::ProcessHandle process_handle;
    116   base::LaunchOptions options;
    117   options.fds_to_remap = &fds_to_remap;
    118   ASSERT_TRUE(base::LaunchProcess(argv, options, &process_handle));
    119   PCHECK(HANDLE_EINTR(close(fds[1])) == 0);
    120 
    121   // Wait until there's some output form top. This is an easy way to tell that
    122   // the exec() call is done and top is actually running.
    123   char buf[1];
    124   PCHECK(HANDLE_EINTR(read(fds[0], buf, 1)) == 1);
    125 
    126   std::vector<base::ProcessId> pid_list;
    127   pid_list.push_back(process_handle);
    128   ProcessInfoSnapshot snapshot;
    129   ASSERT_TRUE(snapshot.Sample(pid_list));
    130 
    131   ProcessInfoSnapshot::ProcInfoEntry proc_info;
    132   ASSERT_TRUE(snapshot.GetProcInfo(process_handle, &proc_info));
    133   // Effective user ID should be 0 (root).
    134   EXPECT_EQ(proc_info.euid, 0u);
    135   // Real user ID should match the calling process's user id.
    136   EXPECT_EQ(proc_info.uid, geteuid());
    137 
    138   ASSERT_TRUE(base::KillProcess(process_handle, 0, true));
    139   PCHECK(HANDLE_EINTR(close(fds[0])) == 0);
    140 }
    141