blob: be00a1799684bec6f8f77747d8b8940b30e5d6eb [file] [log] [blame]
Josh Gao788a35d2016-10-28 15:23:25 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <procinfo/process.h>
18
19#include <fcntl.h>
20#include <stdlib.h>
21#include <sys/types.h>
22#include <unistd.h>
23
Josh Gao8a1b53c2017-06-27 14:06:19 -070024#include <chrono>
Josh Gao788a35d2016-10-28 15:23:25 -070025#include <set>
26#include <thread>
27#include <vector>
28
29#include <gtest/gtest.h>
30
Josh Gao67887fe2021-03-01 23:02:54 -080031#include <android-base/logging.h>
Josh Gao788a35d2016-10-28 15:23:25 -070032#include <android-base/stringprintf.h>
33
Josh Gao8a1b53c2017-06-27 14:06:19 -070034using namespace std::chrono_literals;
35
Josh Gao788a35d2016-10-28 15:23:25 -070036#if !defined(__BIONIC__)
37#include <syscall.h>
38static pid_t gettid() {
39 return syscall(__NR_gettid);
40}
41#endif
42
43TEST(process_info, process_info_smoke) {
44 android::procinfo::ProcessInfo self;
45 ASSERT_TRUE(android::procinfo::GetProcessInfo(gettid(), &self));
46 ASSERT_EQ(gettid(), self.tid);
47 ASSERT_EQ(getpid(), self.pid);
48 ASSERT_EQ(getppid(), self.ppid);
49 ASSERT_EQ(getuid(), self.uid);
50 ASSERT_EQ(getgid(), self.gid);
51}
52
53TEST(process_info, process_info_proc_pid_fd_smoke) {
54 android::procinfo::ProcessInfo self;
55 int fd = open(android::base::StringPrintf("/proc/%d", gettid()).c_str(), O_DIRECTORY | O_RDONLY);
56 ASSERT_NE(-1, fd);
57 ASSERT_TRUE(android::procinfo::GetProcessInfoFromProcPidFd(fd, &self));
58
59 // Process name is capped at 15 bytes.
60 ASSERT_EQ("libprocinfo_tes", self.name);
61 ASSERT_EQ(gettid(), self.tid);
62 ASSERT_EQ(getpid(), self.pid);
63 ASSERT_EQ(getppid(), self.ppid);
64 ASSERT_EQ(getuid(), self.uid);
65 ASSERT_EQ(getgid(), self.gid);
66 close(fd);
67}
68
69TEST(process_info, process_tids_smoke) {
70 pid_t main_tid = gettid();
71 std::thread([main_tid]() {
72 pid_t thread_tid = gettid();
73
74 {
75 std::vector<pid_t> vec;
76 ASSERT_TRUE(android::procinfo::GetProcessTids(getpid(), &vec));
77 ASSERT_EQ(1, std::count(vec.begin(), vec.end(), main_tid));
78 ASSERT_EQ(1, std::count(vec.begin(), vec.end(), thread_tid));
79 }
80
81 {
82 std::set<pid_t> set;
83 ASSERT_TRUE(android::procinfo::GetProcessTids(getpid(), &set));
84 ASSERT_EQ(1, std::count(set.begin(), set.end(), main_tid));
85 ASSERT_EQ(1, std::count(set.begin(), set.end(), thread_tid));
86 }
87 }).join();
88}
Josh Gao8a1b53c2017-06-27 14:06:19 -070089
90TEST(process_info, process_state) {
91 int pipefd[2];
92 ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
93 pid_t forkpid = fork();
94
95 ASSERT_NE(-1, forkpid);
96 if (forkpid == 0) {
97 close(pipefd[1]);
98 char buf;
99 TEMP_FAILURE_RETRY(read(pipefd[0], &buf, 1));
100 _exit(0);
101 }
102
103 // Give the child some time to get to the read.
104 std::this_thread::sleep_for(100ms);
105
106 android::procinfo::ProcessInfo procinfo;
107 ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
108 ASSERT_EQ(android::procinfo::kProcessStateSleeping, procinfo.state);
109
110 ASSERT_EQ(0, kill(forkpid, SIGKILL));
111
112 // Give the kernel some time to kill the child.
113 std::this_thread::sleep_for(100ms);
114
115 ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
116 ASSERT_EQ(android::procinfo::kProcessStateZombie, procinfo.state);
117
118 ASSERT_EQ(forkpid, waitpid(forkpid, nullptr, 0));
119}
Josh Gao67887fe2021-03-01 23:02:54 -0800120
121static uint64_t read_uptime_secs() {
122 std::string uptime;
123 if (!android::base::ReadFileToString("/proc/uptime", &uptime)) {
124 PLOG(FATAL) << "failed to read /proc/uptime";
125 }
126 return strtoll(uptime.c_str(), nullptr, 10);
127}
128
129TEST(process_info, process_start_time) {
130 uint64_t start = read_uptime_secs();
131 int pipefd[2];
132 ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
133
134 std::this_thread::sleep_for(1000ms);
135
136 pid_t forkpid = fork();
137
138 ASSERT_NE(-1, forkpid);
139 if (forkpid == 0) {
140 close(pipefd[1]);
141 char buf;
142 TEMP_FAILURE_RETRY(read(pipefd[0], &buf, 1));
143 _exit(0);
144 }
145
146 std::this_thread::sleep_for(1000ms);
147
148 uint64_t end = read_uptime_secs();
149
150 android::procinfo::ProcessInfo procinfo;
151 ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo));
152
153 // starttime is measured in clock ticks: uptime is in seconds:
154 uint64_t process_start = procinfo.starttime / sysconf(_SC_CLK_TCK);
155 ASSERT_LE(start, process_start);
156 ASSERT_LE(process_start, end);
157
158 ASSERT_EQ(0, kill(forkpid, SIGKILL));
159 ASSERT_EQ(forkpid, waitpid(forkpid, nullptr, 0));
160}