xref: /aosp_15_r20/system/libprocinfo/process_test.cpp (revision e7c5e80fc9b28c04f5db9de8d2855377d05126c5)
1*e7c5e80fSMitch Phillips /*
2*e7c5e80fSMitch Phillips  * Copyright (C) 2016 The Android Open Source Project
3*e7c5e80fSMitch Phillips  *
4*e7c5e80fSMitch Phillips  * Licensed under the Apache License, Version 2.0 (the "License");
5*e7c5e80fSMitch Phillips  * you may not use this file except in compliance with the License.
6*e7c5e80fSMitch Phillips  * You may obtain a copy of the License at
7*e7c5e80fSMitch Phillips  *
8*e7c5e80fSMitch Phillips  *      http://www.apache.org/licenses/LICENSE-2.0
9*e7c5e80fSMitch Phillips  *
10*e7c5e80fSMitch Phillips  * Unless required by applicable law or agreed to in writing, software
11*e7c5e80fSMitch Phillips  * distributed under the License is distributed on an "AS IS" BASIS,
12*e7c5e80fSMitch Phillips  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7c5e80fSMitch Phillips  * See the License for the specific language governing permissions and
14*e7c5e80fSMitch Phillips  * limitations under the License.
15*e7c5e80fSMitch Phillips  */
16*e7c5e80fSMitch Phillips 
17*e7c5e80fSMitch Phillips #include <procinfo/process.h>
18*e7c5e80fSMitch Phillips 
19*e7c5e80fSMitch Phillips #include <fcntl.h>
20*e7c5e80fSMitch Phillips #include <stdlib.h>
21*e7c5e80fSMitch Phillips #include <sys/types.h>
22*e7c5e80fSMitch Phillips #include <unistd.h>
23*e7c5e80fSMitch Phillips 
24*e7c5e80fSMitch Phillips #include <algorithm>
25*e7c5e80fSMitch Phillips #include <chrono>
26*e7c5e80fSMitch Phillips #include <set>
27*e7c5e80fSMitch Phillips #include <thread>
28*e7c5e80fSMitch Phillips #include <vector>
29*e7c5e80fSMitch Phillips 
30*e7c5e80fSMitch Phillips #include <gtest/gtest.h>
31*e7c5e80fSMitch Phillips 
32*e7c5e80fSMitch Phillips #include <android-base/file.h>
33*e7c5e80fSMitch Phillips #include <android-base/logging.h>
34*e7c5e80fSMitch Phillips #include <android-base/stringprintf.h>
35*e7c5e80fSMitch Phillips #include <android-base/unique_fd.h>
36*e7c5e80fSMitch Phillips 
37*e7c5e80fSMitch Phillips using namespace std::chrono_literals;
38*e7c5e80fSMitch Phillips 
39*e7c5e80fSMitch Phillips #if defined(__GLIBC__)
40*e7c5e80fSMitch Phillips #include <syscall.h>
gettid()41*e7c5e80fSMitch Phillips static pid_t gettid() {
42*e7c5e80fSMitch Phillips   return syscall(__NR_gettid);
43*e7c5e80fSMitch Phillips }
44*e7c5e80fSMitch Phillips #endif
45*e7c5e80fSMitch Phillips 
TEST(process_info,process_info_smoke)46*e7c5e80fSMitch Phillips TEST(process_info, process_info_smoke) {
47*e7c5e80fSMitch Phillips   android::procinfo::ProcessInfo self;
48*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::procinfo::GetProcessInfo(gettid(), &self));
49*e7c5e80fSMitch Phillips   ASSERT_EQ(gettid(), self.tid);
50*e7c5e80fSMitch Phillips   ASSERT_EQ(getpid(), self.pid);
51*e7c5e80fSMitch Phillips   ASSERT_EQ(getppid(), self.ppid);
52*e7c5e80fSMitch Phillips   ASSERT_EQ(getuid(), self.uid);
53*e7c5e80fSMitch Phillips   ASSERT_EQ(getgid(), self.gid);
54*e7c5e80fSMitch Phillips }
55*e7c5e80fSMitch Phillips 
TEST(process_info,process_info_proc_pid_fd_smoke)56*e7c5e80fSMitch Phillips TEST(process_info, process_info_proc_pid_fd_smoke) {
57*e7c5e80fSMitch Phillips   android::procinfo::ProcessInfo self;
58*e7c5e80fSMitch Phillips   int fd = open(android::base::StringPrintf("/proc/%d", gettid()).c_str(), O_DIRECTORY | O_RDONLY);
59*e7c5e80fSMitch Phillips   ASSERT_NE(-1, fd);
60*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::procinfo::GetProcessInfoFromProcPidFd(fd, gettid(), &self));
61*e7c5e80fSMitch Phillips 
62*e7c5e80fSMitch Phillips   // Process name is capped at 15 bytes.
63*e7c5e80fSMitch Phillips   ASSERT_EQ("libprocinfo_tes", self.name);
64*e7c5e80fSMitch Phillips   ASSERT_EQ(gettid(), self.tid);
65*e7c5e80fSMitch Phillips   ASSERT_EQ(getpid(), self.pid);
66*e7c5e80fSMitch Phillips   ASSERT_EQ(getppid(), self.ppid);
67*e7c5e80fSMitch Phillips   ASSERT_EQ(getuid(), self.uid);
68*e7c5e80fSMitch Phillips   ASSERT_EQ(getgid(), self.gid);
69*e7c5e80fSMitch Phillips   close(fd);
70*e7c5e80fSMitch Phillips }
71*e7c5e80fSMitch Phillips 
TEST(process_info,process_tids_smoke)72*e7c5e80fSMitch Phillips TEST(process_info, process_tids_smoke) {
73*e7c5e80fSMitch Phillips   pid_t main_tid = gettid();
74*e7c5e80fSMitch Phillips   std::thread([main_tid]() {
75*e7c5e80fSMitch Phillips     pid_t thread_tid = gettid();
76*e7c5e80fSMitch Phillips 
77*e7c5e80fSMitch Phillips     {
78*e7c5e80fSMitch Phillips       std::vector<pid_t> vec;
79*e7c5e80fSMitch Phillips       ASSERT_TRUE(android::procinfo::GetProcessTids(getpid(), &vec));
80*e7c5e80fSMitch Phillips       ASSERT_EQ(1, std::count(vec.begin(), vec.end(), main_tid));
81*e7c5e80fSMitch Phillips       ASSERT_EQ(1, std::count(vec.begin(), vec.end(), thread_tid));
82*e7c5e80fSMitch Phillips     }
83*e7c5e80fSMitch Phillips 
84*e7c5e80fSMitch Phillips     {
85*e7c5e80fSMitch Phillips       std::set<pid_t> set;
86*e7c5e80fSMitch Phillips       ASSERT_TRUE(android::procinfo::GetProcessTids(getpid(), &set));
87*e7c5e80fSMitch Phillips       ASSERT_EQ(1, std::count(set.begin(), set.end(), main_tid));
88*e7c5e80fSMitch Phillips       ASSERT_EQ(1, std::count(set.begin(), set.end(), thread_tid));
89*e7c5e80fSMitch Phillips     }
90*e7c5e80fSMitch Phillips   }).join();
91*e7c5e80fSMitch Phillips }
92*e7c5e80fSMitch Phillips 
TEST(process_info,process_state)93*e7c5e80fSMitch Phillips TEST(process_info, process_state) {
94*e7c5e80fSMitch Phillips   int pipefd[2];
95*e7c5e80fSMitch Phillips   ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
96*e7c5e80fSMitch Phillips   pid_t forkpid = fork();
97*e7c5e80fSMitch Phillips 
98*e7c5e80fSMitch Phillips   ASSERT_NE(-1, forkpid);
99*e7c5e80fSMitch Phillips   if (forkpid == 0) {
100*e7c5e80fSMitch Phillips     close(pipefd[1]);
101*e7c5e80fSMitch Phillips     char buf;
102*e7c5e80fSMitch Phillips     TEMP_FAILURE_RETRY(read(pipefd[0], &buf, 1));
103*e7c5e80fSMitch Phillips     _exit(0);
104*e7c5e80fSMitch Phillips   }
105*e7c5e80fSMitch Phillips 
106*e7c5e80fSMitch Phillips 
107*e7c5e80fSMitch Phillips   // Give the child some time to get to the read.
108*e7c5e80fSMitch Phillips   android::procinfo::ProcessInfo procinfo;
109*e7c5e80fSMitch Phillips   for (int loop = 0; loop < 50 && procinfo.state != android::procinfo::kProcessStateSleeping; loop++) {
110*e7c5e80fSMitch Phillips    std::this_thread::sleep_for(100ms);
111*e7c5e80fSMitch Phillips    ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
112*e7c5e80fSMitch Phillips   }
113*e7c5e80fSMitch Phillips   ASSERT_EQ(android::procinfo::kProcessStateSleeping, procinfo.state);
114*e7c5e80fSMitch Phillips 
115*e7c5e80fSMitch Phillips   ASSERT_EQ(0, kill(forkpid, SIGKILL));
116*e7c5e80fSMitch Phillips 
117*e7c5e80fSMitch Phillips   // Give the kernel some time to kill the child.
118*e7c5e80fSMitch Phillips   for (int loop = 0; loop < 50 && procinfo.state != android::procinfo::kProcessStateZombie; loop++) {
119*e7c5e80fSMitch Phillips     std::this_thread::sleep_for(100ms);
120*e7c5e80fSMitch Phillips     ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
121*e7c5e80fSMitch Phillips   }
122*e7c5e80fSMitch Phillips   ASSERT_EQ(android::procinfo::kProcessStateZombie, procinfo.state);
123*e7c5e80fSMitch Phillips 
124*e7c5e80fSMitch Phillips   ASSERT_EQ(forkpid, waitpid(forkpid, nullptr, 0));
125*e7c5e80fSMitch Phillips }
126*e7c5e80fSMitch Phillips 
read_uptime_secs()127*e7c5e80fSMitch Phillips static uint64_t read_uptime_secs() {
128*e7c5e80fSMitch Phillips   std::string uptime;
129*e7c5e80fSMitch Phillips   if (!android::base::ReadFileToString("/proc/uptime", &uptime)) {
130*e7c5e80fSMitch Phillips     PLOG(FATAL) << "failed to read /proc/uptime";
131*e7c5e80fSMitch Phillips   }
132*e7c5e80fSMitch Phillips   return strtoll(uptime.c_str(), nullptr, 10);
133*e7c5e80fSMitch Phillips }
134*e7c5e80fSMitch Phillips 
TEST(process_info,process_start_time)135*e7c5e80fSMitch Phillips TEST(process_info, process_start_time) {
136*e7c5e80fSMitch Phillips   uint64_t start = read_uptime_secs();
137*e7c5e80fSMitch Phillips   int pipefd[2];
138*e7c5e80fSMitch Phillips   ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
139*e7c5e80fSMitch Phillips 
140*e7c5e80fSMitch Phillips   std::this_thread::sleep_for(1000ms);
141*e7c5e80fSMitch Phillips 
142*e7c5e80fSMitch Phillips   pid_t forkpid = fork();
143*e7c5e80fSMitch Phillips 
144*e7c5e80fSMitch Phillips   ASSERT_NE(-1, forkpid);
145*e7c5e80fSMitch Phillips   if (forkpid == 0) {
146*e7c5e80fSMitch Phillips     close(pipefd[1]);
147*e7c5e80fSMitch Phillips     char buf;
148*e7c5e80fSMitch Phillips     TEMP_FAILURE_RETRY(read(pipefd[0], &buf, 1));
149*e7c5e80fSMitch Phillips     _exit(0);
150*e7c5e80fSMitch Phillips   }
151*e7c5e80fSMitch Phillips 
152*e7c5e80fSMitch Phillips   std::this_thread::sleep_for(1000ms);
153*e7c5e80fSMitch Phillips 
154*e7c5e80fSMitch Phillips   uint64_t end = read_uptime_secs();
155*e7c5e80fSMitch Phillips 
156*e7c5e80fSMitch Phillips   android::procinfo::ProcessInfo procinfo;
157*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
158*e7c5e80fSMitch Phillips 
159*e7c5e80fSMitch Phillips   // starttime is measured in clock ticks: uptime is in seconds:
160*e7c5e80fSMitch Phillips   uint64_t process_start = procinfo.starttime / sysconf(_SC_CLK_TCK);
161*e7c5e80fSMitch Phillips   ASSERT_LE(start, process_start);
162*e7c5e80fSMitch Phillips   ASSERT_LE(process_start, end);
163*e7c5e80fSMitch Phillips 
164*e7c5e80fSMitch Phillips   ASSERT_EQ(0, kill(forkpid, SIGKILL));
165*e7c5e80fSMitch Phillips   ASSERT_EQ(forkpid, waitpid(forkpid, nullptr, 0));
166*e7c5e80fSMitch Phillips }
167*e7c5e80fSMitch Phillips 
TEST(process_info,GetProcessInfoFromProcPidFd_set_error)168*e7c5e80fSMitch Phillips TEST(process_info, GetProcessInfoFromProcPidFd_set_error) {
169*e7c5e80fSMitch Phillips   TemporaryDir tmp_dir;
170*e7c5e80fSMitch Phillips 
171*e7c5e80fSMitch Phillips   android::base::unique_fd dirfd(open(tmp_dir.path, O_DIRECTORY | O_RDONLY));
172*e7c5e80fSMitch Phillips   android::procinfo::ProcessInfo procinfo;
173*e7c5e80fSMitch Phillips   std::string error;
174*e7c5e80fSMitch Phillips 
175*e7c5e80fSMitch Phillips   // failed to open status file error
176*e7c5e80fSMitch Phillips   // No segfault if not given error string.
177*e7c5e80fSMitch Phillips   ASSERT_FALSE(android::procinfo::GetProcessInfoFromProcPidFd(dirfd.get(), 0, &procinfo));
178*e7c5e80fSMitch Phillips   // Set error when given error string.
179*e7c5e80fSMitch Phillips   ASSERT_FALSE(android::procinfo::GetProcessInfoFromProcPidFd(dirfd.get(), 0, &procinfo, &error));
180*e7c5e80fSMitch Phillips   ASSERT_EQ(error, "failed to open /proc/0/status in GetProcessInfoFromProcPidFd: No such file or directory");
181*e7c5e80fSMitch Phillips 
182*e7c5e80fSMitch Phillips   // failed to parse status file error
183*e7c5e80fSMitch Phillips   std::string status_file = std::string(tmp_dir.path) + "/status";
184*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::base::WriteStringToFile("invalid data", status_file));
185*e7c5e80fSMitch Phillips   ASSERT_FALSE(android::procinfo::GetProcessInfoFromProcPidFd(dirfd.get(), 0, &procinfo));
186*e7c5e80fSMitch Phillips   ASSERT_FALSE(android::procinfo::GetProcessInfoFromProcPidFd(dirfd.get(), 0, &procinfo, &error));
187*e7c5e80fSMitch Phillips   ASSERT_EQ(error, "failed to parse /proc/0/status");
188*e7c5e80fSMitch Phillips 
189*e7c5e80fSMitch Phillips   // Give the "/status" file valid contents.
190*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::base::WriteStringToFile(
191*e7c5e80fSMitch Phillips       "Name:\tsh\nTgid:\t0\nPid:\t0\nTracerPid:\t0\nUid:\t0\nGid:\t0\n", status_file));
192*e7c5e80fSMitch Phillips 
193*e7c5e80fSMitch Phillips   // failed to open stat file error
194*e7c5e80fSMitch Phillips   ASSERT_FALSE(android::procinfo::GetProcessInfoFromProcPidFd(dirfd.get(), 0, &procinfo));
195*e7c5e80fSMitch Phillips   ASSERT_FALSE(android::procinfo::GetProcessInfoFromProcPidFd(dirfd.get(), 0, &procinfo, &error));
196*e7c5e80fSMitch Phillips   ASSERT_EQ(error, "failed to open /proc/0/stat: No such file or directory");
197*e7c5e80fSMitch Phillips 
198*e7c5e80fSMitch Phillips   // failed to parse stat file error
199*e7c5e80fSMitch Phillips   std::string stat_file = std::string(tmp_dir.path) + "/stat";
200*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::base::WriteStringToFile("2027 (sh) invalid data", stat_file));
201*e7c5e80fSMitch Phillips   ASSERT_FALSE(android::procinfo::GetProcessInfoFromProcPidFd(dirfd.get(), 0, &procinfo));
202*e7c5e80fSMitch Phillips   ASSERT_FALSE(android::procinfo::GetProcessInfoFromProcPidFd(dirfd.get(), 0, &procinfo, &error));
203*e7c5e80fSMitch Phillips   ASSERT_EQ(error, "failed to parse /proc/0/stat");
204*e7c5e80fSMitch Phillips }
205