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