1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/process_info_snapshot.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <sys/types.h> // For |uid_t| (and |pid_t|). 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <unistd.h> // For |getpid()|, |getuid()|, etc. 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/command_line.h" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/eintr_wrapper.h" 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/file_path.h" 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/logging.h" 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/process_util.h" 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef testing::Test ProcessInfoSnapshotMacTest; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ProcessInfoSnapshotMacTest, FindPidOneTest) { 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sample process with PID 1, which should exist and presumably belong to 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // root. 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<base::ProcessId> pid_list; 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pid_list.push_back(1); 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessInfoSnapshot snapshot; 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(snapshot.Sample(pid_list)); 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessInfoSnapshot::ProcInfoEntry proc_info; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(snapshot.GetProcInfo(1, &proc_info)); 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(1, static_cast<int64>(proc_info.pid)); 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, static_cast<int64>(proc_info.ppid)); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, static_cast<int64>(proc_info.uid)); 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(0, static_cast<int64>(proc_info.euid)); 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_GE(proc_info.rss, 0u); 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_GT(proc_info.vsize, 0u); 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Try out the |Get...OfPID()|, but don't examine the results, since they 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // depend on how we map |ProcInfoEntry| to |...KBytes|. 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::CommittedKBytes usage; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(snapshot.GetCommittedKBytesOfPID(1, &usage)); 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::WorkingSetKBytes ws_usage; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(snapshot.GetWorkingSetKBytesOfPID(1, &ws_usage)); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure it hasn't picked up some other PID (say, 2). 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(snapshot.GetProcInfo(2, &proc_info)); 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure PID 2 still isn't there (in case I mess up my use of std::map). 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(snapshot.GetProcInfo(2, &proc_info)); 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Test |Reset()|. 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch snapshot.Reset(); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_FALSE(snapshot.GetProcInfo(1, &proc_info)); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ProcessInfoSnapshotMacTest, FindPidSelfTest) { 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sample this process and its parent. 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::ProcessId pid = static_cast<base::ProcessId>(getpid()); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::ProcessId ppid = static_cast<base::ProcessId>(getppid()); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uid_t uid = getuid(); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uid_t euid = geteuid(); 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_NE(static_cast<int64>(ppid), 0); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<base::ProcessId> pid_list; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pid_list.push_back(pid); 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pid_list.push_back(ppid); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessInfoSnapshot snapshot; 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(snapshot.Sample(pid_list)); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find our process. 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessInfoSnapshot::ProcInfoEntry proc_info; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(snapshot.GetProcInfo(pid, &proc_info)); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(pid, proc_info.pid); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(ppid, proc_info.ppid); 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(uid, proc_info.uid); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(euid, proc_info.euid); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_GE(proc_info.rss, 100u); // Sanity check: we're running, so we 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should occupy at least 100 kilobytes. 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_GE(proc_info.vsize, 1024u); // Sanity check: our |vsize| is presumably 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // at least a megabyte. 8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXPECT_GE(proc_info.rshrd, 1024u); // Shared memory should also > 1 MB. 8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXPECT_GE(proc_info.rprvt, 1024u); // Same with private memory. 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find our parent. 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(snapshot.GetProcInfo(ppid, &proc_info)); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(ppid, proc_info.pid); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_NE(static_cast<int64>(proc_info.ppid), 0); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(uid, proc_info.uid); // This (and the following) should be true 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(euid, proc_info.euid); // under reasonable circumstances. 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Can't say anything definite about its |rss|. 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_GT(proc_info.vsize, 0u); // Its |vsize| should be nonzero though. 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// To verify that ProcessInfoSnapshot is getting the actual uid and effective 9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// uid, this test runs top. top should have a uid of the caller and effective 9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// uid of 0 (root). 9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenTEST_F(ProcessInfoSnapshotMacTest, EffectiveVsRealUserIDTest) { 9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Create a pipe to be able to read top's output. 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int fds[2]; 10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCHECK(pipe(fds) == 0); 10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::file_handle_mapping_vector fds_to_remap; 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen fds_to_remap.push_back(std::make_pair(fds[1], 1)); 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Hook up top's stderr to the test process' stderr. 10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen fds_to_remap.push_back(std::make_pair(fileno(stderr), 2)); 10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::vector<std::string> argv; 10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen argv.push_back("/usr/bin/top"); 11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen argv.push_back("-l"); 11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen argv.push_back("0"); 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::ProcessHandle process_handle; 11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ASSERT_TRUE(base::LaunchApp(argv, fds_to_remap, false, &process_handle)); 11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCHECK(HANDLE_EINTR(close(fds[1])) == 0); 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Wait until there's some output form top. This is an easy way to tell that 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the exec() call is done and top is actually running. 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char buf[1]; 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCHECK(HANDLE_EINTR(read(fds[0], buf, 1)) == 1); 12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::vector<base::ProcessId> pid_list; 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen pid_list.push_back(process_handle); 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ProcessInfoSnapshot snapshot; 12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ASSERT_TRUE(snapshot.Sample(pid_list)); 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ProcessInfoSnapshot::ProcInfoEntry proc_info; 12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ASSERT_TRUE(snapshot.GetProcInfo(process_handle, &proc_info)); 12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Effective user ID should be 0 (root). 13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen EXPECT_EQ(proc_info.euid, 0u); 13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Real user ID should match the calling process's user id. 13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen EXPECT_EQ(proc_info.uid, geteuid()); 13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ASSERT_TRUE(base::KillProcess(process_handle, 0, true)); 13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCHECK(HANDLE_EINTR(close(fds[0])) == 0); 13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 137