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.
5 #include "chrome/browser/process_info_snapshot.h"
7 #include <sys/types.h> // For |uid_t| (and |pid_t|).
8 #include <unistd.h> // For |getpid()|, |getuid()|, etc.
12 #include "base/command_line.h"
13 #include "base/files/file_path.h"
14 #include "base/logging.h"
15 #include "base/mac/mac_util.h"
16 #include "base/posix/eintr_wrapper.h"
17 #include "base/process/kill.h"
18 #include "base/process/launch.h"
19 #include "base/process/process_handle.h"
20 #include "base/process/process_metrics.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 typedef testing::Test ProcessInfoSnapshotMacTest
;
25 TEST_F(ProcessInfoSnapshotMacTest
, FindPidOneTest
) {
26 // Sample process with PID 1, which should exist and presumably belong to
28 std::vector
<base::ProcessId
> pid_list
;
29 pid_list
.push_back(1);
30 ProcessInfoSnapshot snapshot
;
31 ASSERT_TRUE(snapshot
.Sample(pid_list
));
33 ProcessInfoSnapshot::ProcInfoEntry proc_info
;
34 ASSERT_TRUE(snapshot
.GetProcInfo(1, &proc_info
));
35 EXPECT_EQ(1, static_cast<int64
>(proc_info
.pid
));
36 EXPECT_EQ(0, static_cast<int64
>(proc_info
.ppid
));
37 EXPECT_EQ(0, static_cast<int64
>(proc_info
.uid
));
38 EXPECT_EQ(0, static_cast<int64
>(proc_info
.euid
));
39 EXPECT_GE(proc_info
.rss
, 0u);
40 EXPECT_GT(proc_info
.vsize
, 0u);
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
));
49 // Make sure it hasn't picked up some other PID (say, 2).
50 EXPECT_FALSE(snapshot
.GetProcInfo(2, &proc_info
));
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
));
57 EXPECT_FALSE(snapshot
.GetProcInfo(1, &proc_info
));
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());
65 uid_t euid
= geteuid();
66 EXPECT_NE(static_cast<int64
>(ppid
), 0);
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
));
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);
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);
96 ASSERT_TRUE(snapshot
.GetProcInfo(ppid
, &proc_info
));
97 EXPECT_EQ(ppid
, proc_info
.pid
);
98 EXPECT_NE(static_cast<int64
>(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.
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
108 TEST_F(ProcessInfoSnapshotMacTest
, EffectiveVsRealUserIDTest
) {
109 // Create a pipe to be able to read top's output.
111 PCHECK(pipe(fds
) == 0);
112 base::FileHandleMappingVector fds_to_remap
;
113 fds_to_remap
.push_back(std::make_pair(fds
[1], 1));
115 // Hook up top's stderr to the test process' stderr.
116 fds_to_remap
.push_back(std::make_pair(fileno(stderr
), 2));
118 std::vector
<std::string
> argv
;
119 argv
.push_back("/usr/bin/top");
120 argv
.push_back("-l");
123 base::ProcessHandle process_handle
;
124 base::LaunchOptions options
;
125 options
.fds_to_remap
= &fds_to_remap
;
126 ASSERT_TRUE(base::LaunchProcess(argv
, options
, &process_handle
));
127 PCHECK(IGNORE_EINTR(close(fds
[1])) == 0);
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.
132 PCHECK(HANDLE_EINTR(read(fds
[0], buf
, 1)) == 1);
134 std::vector
<base::ProcessId
> pid_list
;
135 pid_list
.push_back(process_handle
);
136 ProcessInfoSnapshot snapshot
;
137 ASSERT_TRUE(snapshot
.Sample(pid_list
));
139 ProcessInfoSnapshot::ProcInfoEntry proc_info
;
140 ASSERT_TRUE(snapshot
.GetProcInfo(process_handle
, &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());
146 ASSERT_TRUE(base::KillProcess(process_handle
, 0, true));
147 PCHECK(IGNORE_EINTR(close(fds
[0])) == 0);