1 /*
2  * Copyright (C) 2017 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 "PsParser.h"
18 
19 #include "frameworks/base/core/proto/android/os/ps.pb.h"
20 
21 #include <android-base/file.h>
22 #include <android-base/test_utils.h>
23 #include <gmock/gmock.h>
24 #include <google/protobuf/message_lite.h>
25 #include <gtest/gtest.h>
26 #include <string.h>
27 #include <fcntl.h>
28 
29 using namespace android::base;
30 using namespace android::os;
31 using namespace std;
32 using ::testing::StrEq;
33 using ::testing::Test;
34 using ::testing::internal::CaptureStderr;
35 using ::testing::internal::CaptureStdout;
36 using ::testing::internal::GetCapturedStderr;
37 using ::testing::internal::GetCapturedStdout;
38 
39 class PsParserTest : public Test {
40 public:
SetUp()41     virtual void SetUp() override {
42         ASSERT_TRUE(tf.fd != -1);
43     }
44 
45 protected:
46     TemporaryFile tf;
47 
48     const string kTestPath = GetExecutableDirectory();
49     const string kTestDataPath = kTestPath + "/testdata/";
50 };
51 
TEST_F(PsParserTest,Normal)52 TEST_F(PsParserTest, Normal) {
53     const string testFile = kTestDataPath + "ps.txt";
54     PsParser parser;
55     PsProto expected;
56     PsProto got;
57 
58     PsProto::Process* record1 = expected.add_processes();
59     record1->set_label("u:r:init:s0");
60     record1->set_user("root");
61     record1->set_pid(1);
62     record1->set_tid(1);
63     record1->set_ppid(0);
64     record1->set_vsz(15816);
65     record1->set_rss(2636);
66     record1->set_wchan("SyS_epoll_wait");
67     record1->set_addr("0");
68     record1->set_s(PsProto_Process_ProcessStateCode_STATE_S);
69     record1->set_pri(19);
70     record1->set_ni(0);
71     record1->set_rtprio("-");
72     record1->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
73     record1->set_pcy(PsProto::Process::POLICY_FG);
74     record1->set_time("00:00:01");
75     record1->set_cmd("init");
76 
77     PsProto::Process* record2 = expected.add_processes();
78     record2->set_label("u:r:kernel:s0");
79     record2->set_user("root");
80     record2->set_pid(2);
81     record2->set_tid(2);
82     record2->set_ppid(0);
83     record2->set_vsz(0);
84     record2->set_rss(0);
85     record2->set_wchan("kthreadd");
86     record2->set_addr("0");
87     record2->set_s(PsProto_Process_ProcessStateCode_STATE_S);
88     record2->set_pri(19);
89     record2->set_ni(0);
90     record2->set_rtprio("-");
91     record2->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
92     record2->set_pcy(PsProto::Process::POLICY_FG);
93     record2->set_time("00:00:00");
94     record2->set_cmd("kthreadd");
95 
96     PsProto::Process* record3 = expected.add_processes();
97     record3->set_label("u:r:surfaceflinger:s0");
98     record3->set_user("system");
99     record3->set_pid(499);
100     record3->set_tid(534);
101     record3->set_ppid(1);
102     record3->set_vsz(73940);
103     record3->set_rss(22024);
104     record3->set_wchan("futex_wait_queue_me");
105     record3->set_addr("0");
106     record3->set_s(PsProto_Process_ProcessStateCode_STATE_S);
107     record3->set_pri(42);
108     record3->set_ni(-9);
109     record3->set_rtprio("2");
110     record3->set_sch(PsProto_Process_SchedulingPolicy_SCH_FIFO);
111     record3->set_pcy(PsProto::Process::POLICY_FG);
112     record3->set_time("00:00:00");
113     record3->set_cmd("EventThread");
114 
115     PsProto::Process* record4 = expected.add_processes();
116     record4->set_label("u:r:hal_gnss_default:s0");
117     record4->set_user("gps");
118     record4->set_pid(670);
119     record4->set_tid(2004);
120     record4->set_ppid(1);
121     record4->set_vsz(43064);
122     record4->set_rss(7272);
123     record4->set_wchan("poll_schedule_timeout");
124     record4->set_addr("0");
125     record4->set_s(PsProto_Process_ProcessStateCode_STATE_S);
126     record4->set_pri(19);
127     record4->set_ni(0);
128     record4->set_rtprio("-");
129     record4->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
130     record4->set_pcy(PsProto::Process::POLICY_FG);
131     record4->set_time("00:00:00");
132     record4->set_cmd("Loc_hal_worker");
133 
134     PsProto::Process* record5 = expected.add_processes();
135     record5->set_label("u:r:platform_app:s0:c512,c768");
136     record5->set_user("u0_a48");
137     record5->set_pid(1660);
138     record5->set_tid(1976);
139     record5->set_ppid(806);
140     record5->set_vsz(4468612);
141     record5->set_rss(138328);
142     record5->set_wchan("binder_thread_read");
143     record5->set_addr("0");
144     record5->set_s(PsProto_Process_ProcessStateCode_STATE_S);
145     record5->set_pri(35);
146     record5->set_ni(-16);
147     record5->set_rtprio("-");
148     record5->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
149     record5->set_pcy(PsProto::Process::POLICY_TA);
150     record5->set_time("00:00:00");
151     record5->set_cmd("HwBinder:1660_1");
152 
153     PsProto::Process* record6 = expected.add_processes();
154     record6->set_label("u:r:perfd:s0");
155     record6->set_user("root");
156     record6->set_pid(1939);
157     record6->set_tid(1946);
158     record6->set_ppid(1);
159     record6->set_vsz(18132);
160     record6->set_rss(2088);
161     record6->set_wchan("__skb_recv_datagram");
162     record6->set_addr("7b9782fd14");
163     record6->set_s(PsProto_Process_ProcessStateCode_STATE_S);
164     record6->set_pri(19);
165     record6->set_ni(0);
166     record6->set_rtprio("-");
167     record6->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
168     record6->set_pcy(PsProto::Process::POLICY_UNKNOWN);
169     record6->set_time("00:00:00");
170     record6->set_cmd("perfd");
171 
172     PsProto::Process* record7 = expected.add_processes();
173     record7->set_label("u:r:perfd:s0");
174     record7->set_user("root");
175     record7->set_pid(1939);
176     record7->set_tid(1955);
177     record7->set_ppid(1);
178     record7->set_vsz(18132);
179     record7->set_rss(2088);
180     record7->set_wchan("do_sigtimedwait");
181     record7->set_addr("7b9782ff6c");
182     record7->set_s(PsProto_Process_ProcessStateCode_STATE_S);
183     record7->set_pri(19);
184     record7->set_ni(0);
185     record7->set_rtprio("-");
186     record7->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
187     record7->set_pcy(PsProto::Process::POLICY_UNKNOWN);
188     record7->set_time("00:00:00");
189     record7->set_cmd("POSIX timer 0");
190 
191     PsProto::Process* record8 = expected.add_processes();
192     record8->set_label("u:r:shell:s0");
193     record8->set_user("shell");
194     record8->set_pid(2645);
195     record8->set_tid(2645);
196     record8->set_ppid(802);
197     record8->set_vsz(11664);
198     record8->set_rss(2972);
199     record8->set_wchan("0");
200     record8->set_addr("7f67a2f8b4");
201     record8->set_s(PsProto_Process_ProcessStateCode_STATE_R);
202     record8->set_pri(19);
203     record8->set_ni(0);
204     record8->set_rtprio("-");
205     record8->set_sch(PsProto_Process_SchedulingPolicy_SCH_NORMAL);
206     record8->set_pcy(PsProto::Process::POLICY_FG);
207     record8->set_time("00:00:00");
208     record8->set_cmd("ps");
209 
210     int fd = open(testFile.c_str(), O_RDONLY);
211     ASSERT_TRUE(fd != -1);
212 
213     CaptureStdout();
214     ASSERT_EQ(NO_ERROR, parser.Parse(fd, STDOUT_FILENO));
215     got.ParseFromString(GetCapturedStdout());
216     bool matches = true;
217 
218     if (got.processes_size() != expected.processes_size()) {
219         fprintf(stderr, "Got %d processes, want %d\n", got.processes_size(), expected.processes_size());
220         matches = false;
221     } else {
222         int n = got.processes_size();
223         for (int i = 0; i < n; i++) {
224             PsProto::Process g = got.processes(i);
225             PsProto::Process e = expected.processes(i);
226 
227             if (g.label() != e.label()) {
228                 fprintf(stderr, "prcs[%d]: Invalid label. Got %s, want %s\n", i, g.label().c_str(), e.label().c_str());
229                 matches = false;
230             }
231             if (g.user() != e.user()) {
232                 fprintf(stderr, "prcs[%d]: Invalid user. Got %s, want %s\n", i, g.user().c_str(), e.user().c_str());
233                 matches = false;
234             }
235             if (g.pid() != e.pid()) {
236                 fprintf(stderr, "prcs[%d]: Invalid pid. Got %d, want %d\n", i, g.pid(), e.pid());
237                 matches = false;
238             }
239             if (g.tid() != e.tid()) {
240                 fprintf(stderr, "prcs[%d]: Invalid tid. Got %d, want %d\n", i, g.tid(), e.tid());
241                 matches = false;
242             }
243             if (g.ppid() != e.ppid()) {
244                 fprintf(stderr, "prcs[%d]: Invalid ppid. Got %d, want %d\n", i, g.ppid(), e.ppid());
245                 matches = false;
246             }
247             if (g.vsz() != e.vsz()) {
248                 fprintf(stderr, "prcs[%d]: Invalid vsz. Got %d, want %d\n", i, g.vsz(), e.vsz());
249                 matches = false;
250             }
251             if (g.rss() != e.rss()) {
252                 fprintf(stderr, "prcs[%d]: Invalid rss. Got %d, want %d\n", i, g.rss(), e.rss());
253                 matches = false;
254             }
255             if (g.wchan() != e.wchan()) {
256                 fprintf(stderr, "prcs[%d]: Invalid wchan. Got %s, want %s\n", i, g.wchan().c_str(), e.wchan().c_str());
257                 matches = false;
258             }
259             if (g.addr() != e.addr()) {
260                 fprintf(stderr, "prcs[%d]: Invalid addr. Got %s, want %s\n", i, g.addr().c_str(), e.addr().c_str());
261                 matches = false;
262             }
263             if (g.s() != e.s()) {
264                 fprintf(stderr, "prcs[%d]: Invalid s. Got %u, want %u\n", i, g.s(), e.s());
265                 matches = false;
266             }
267             if (g.pri() != e.pri()) {
268                 fprintf(stderr, "prcs[%d]: Invalid pri. Got %d, want %d\n", i, g.pri(), e.pri());
269                 matches = false;
270             }
271             if (g.ni() != e.ni()) {
272                 fprintf(stderr, "prcs[%d]: Invalid ni. Got %d, want %d\n", i, g.ni(), e.ni());
273                 matches = false;
274             }
275             if (g.rtprio() != e.rtprio()) {
276                 fprintf(stderr, "prcs[%d]: Invalid rtprio. Got %s, want %s\n", i, g.rtprio().c_str(), e.rtprio().c_str());
277                 matches = false;
278             }
279             if (g.sch() != e.sch()) {
280                 fprintf(stderr, "prcs[%d]: Invalid sch. Got %u, want %u\n", i, g.sch(), e.sch());
281                 matches = false;
282             }
283             if (g.pcy() != e.pcy()) {
284                 fprintf(stderr, "prcs[%d]: Invalid pcy. Got %u, want %u\n", i, g.pcy(), e.pcy());
285                 matches = false;
286             }
287             if (g.time() != e.time()) {
288                 fprintf(stderr, "prcs[%d]: Invalid time. Got %s, want %s\n", i, g.time().c_str(), e.time().c_str());
289                 matches = false;
290             }
291             if (g.cmd() != e.cmd()) {
292                 fprintf(stderr, "prcs[%d]: Invalid cmd. Got %s, want %s\n", i, g.cmd().c_str(), e.cmd().c_str());
293                 matches = false;
294             }
295         }
296     }
297 
298     EXPECT_TRUE(matches);
299     close(fd);
300 }
301