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