1 /*
2 * Copyright 2021 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 "MockPackageInfoResolver.h"
18 #include "MockUidCpuStatsCollector.h"
19 #include "MockUidIoStatsCollector.h"
20 #include "MockUidProcStatsCollector.h"
21 #include "PackageInfoTestUtils.h"
22 #include "UidIoStatsCollector.h"
23 #include "UidProcStatsCollector.h"
24 #include "UidProcStatsCollectorTestUtils.h"
25 #include "UidStatsCollector.h"
26
27 #include <android-base/stringprintf.h>
28 #include <gmock/gmock.h>
29 #include <utils/RefBase.h>
30
31 #include <inttypes.h>
32
33 #include <string>
34
35 namespace android {
36 namespace automotive {
37 namespace watchdog {
38
39 using ::aidl::android::automotive::watchdog::internal::PackageInfo;
40 using ::aidl::android::automotive::watchdog::internal::UidType;
41 using ::android::base::Error;
42 using ::android::base::Result;
43 using ::android::base::StringAppendF;
44 using ::android::base::StringPrintf;
45 using ::testing::AllOf;
46 using ::testing::Eq;
47 using ::testing::ExplainMatchResult;
48 using ::testing::Field;
49 using ::testing::IsEmpty;
50 using ::testing::Matcher;
51 using ::testing::Return;
52 using ::testing::UnorderedElementsAre;
53 using ::testing::UnorderedElementsAreArray;
54
55 namespace {
56
toString(const UidStats & uidStats)57 std::string toString(const UidStats& uidStats) {
58 return StringPrintf("UidStats{packageInfo: %s, cpuTimeMillis: %" PRId64
59 ", ioStats: %s, procStats: %s}",
60 uidStats.packageInfo.toString().c_str(), uidStats.cpuTimeMillis,
61 uidStats.ioStats.toString().c_str(), uidStats.procStats.toString().c_str());
62 }
63
toString(const std::vector<UidStats> & uidStats)64 std::string toString(const std::vector<UidStats>& uidStats) {
65 std::string buffer;
66 StringAppendF(&buffer, "{");
67 for (const auto& stats : uidStats) {
68 StringAppendF(&buffer, "%s\n", toString(stats).c_str());
69 }
70 StringAppendF(&buffer, "}");
71 return buffer;
72 }
73
74 MATCHER_P(UidStatsEq, expected, "") {
75 return ExplainMatchResult(AllOf(Field("packageInfo", &UidStats::packageInfo,
76 PackageInfoEq(expected.packageInfo)),
77 Field("cpuTimeMillis", &UidStats::cpuTimeMillis,
78 Eq(expected.cpuTimeMillis)),
79 Field("ioStats", &UidStats::ioStats, Eq(expected.ioStats)),
80 Field("procStats", &UidStats::procStats,
81 UidProcStatsEq(expected.procStats))),
82 arg, result_listener);
83 }
84
UidStatsMatchers(const std::vector<UidStats> & uidStats)85 std::vector<Matcher<const UidStats&>> UidStatsMatchers(const std::vector<UidStats>& uidStats) {
86 std::vector<Matcher<const UidStats&>> matchers;
87 for (const auto& stats : uidStats) {
88 matchers.push_back(UidStatsEq(stats));
89 }
90 return matchers;
91 }
92
samplePackageInfoByUid()93 std::unordered_map<uid_t, PackageInfo> samplePackageInfoByUid() {
94 return {{1001234, constructPackageInfo("system.daemon", 1001234, UidType::NATIVE)},
95 {1005678, constructPackageInfo("kitchensink.app", 1005678, UidType::APPLICATION)}};
96 }
97
sampleUidIoStatsByUid()98 std::unordered_map<uid_t, UidIoStats> sampleUidIoStatsByUid() {
99 return {{1001234,
100 UidIoStats{/*fgRdBytes=*/3'000, /*bgRdBytes=*/0,
101 /*fgWrBytes=*/500,
102 /*bgWrBytes=*/0, /*fgFsync=*/20,
103 /*bgFsync=*/0}},
104 {1005678,
105 UidIoStats{/*fgRdBytes=*/30, /*bgRdBytes=*/100,
106 /*fgWrBytes=*/50, /*bgWrBytes=*/200,
107 /*fgFsync=*/45, /*bgFsync=*/60}}};
108 }
109
sampleUidProcStatsByUid()110 std::unordered_map<uid_t, UidProcStats> sampleUidProcStatsByUid() {
111 return {{1001234,
112 UidProcStats{.cpuTimeMillis = 10,
113 .totalMajorFaults = 220,
114 .totalTasksCount = 2,
115 .ioBlockedTasksCount = 1,
116 .processStatsByPid = {{1, {"init", 0, 10, 220, 2, 1}}}}},
117 {1005678,
118 UidProcStats{.cpuTimeMillis = 43,
119 .totalMajorFaults = 600,
120 .totalTasksCount = 2,
121 .ioBlockedTasksCount = 2,
122 .processStatsByPid = {
123 {1000, {"system_server", 13'400, 43, 600, 2, 2}}}}}};
124 }
125
sampleUidCpuStatsByUid()126 std::unordered_map<uid_t, int64_t> sampleUidCpuStatsByUid() {
127 return {{1001234, 15}, {1005678, 43}};
128 }
129
sampleUidStats()130 std::vector<UidStats> sampleUidStats() {
131 return {{.packageInfo = constructPackageInfo("system.daemon", 1001234, UidType::NATIVE),
132 .cpuTimeMillis = 15,
133 .ioStats = UidIoStats{/*fgRdBytes=*/3'000, /*bgRdBytes=*/0, /*fgWrBytes=*/500,
134 /*bgWrBytes=*/0, /*fgFsync=*/20, /*bgFsync=*/0},
135 .procStats = UidProcStats{.cpuTimeMillis = 10,
136 .totalMajorFaults = 220,
137 .totalTasksCount = 2,
138 .ioBlockedTasksCount = 1,
139 .processStatsByPid = {{1, {"init", 0, 10, 220, 2, 1}}}}},
140 {.packageInfo = constructPackageInfo("kitchensink.app", 1005678, UidType::APPLICATION),
141 .cpuTimeMillis = 43,
142 .ioStats = UidIoStats{/*fgRdBytes=*/30, /*bgRdBytes=*/100, /*fgWrBytes=*/50,
143 /*bgWrBytes=*/200,
144 /*fgFsync=*/45, /*bgFsync=*/60},
145 .procStats = UidProcStats{.cpuTimeMillis = 43,
146 .totalMajorFaults = 600,
147 .totalTasksCount = 2,
148 .ioBlockedTasksCount = 2,
149 .processStatsByPid = {
150 {1000, {"system_server", 13'400, 43, 600, 2, 2}}}}}};
151 }
152
153 } // namespace
154
155 namespace internal {
156
157 class UidStatsCollectorPeer final : public RefBase {
158 public:
UidStatsCollectorPeer(sp<UidStatsCollector> collector)159 explicit UidStatsCollectorPeer(sp<UidStatsCollector> collector) : mCollector(collector) {}
~UidStatsCollectorPeer()160 ~UidStatsCollectorPeer() { mCollector.clear(); }
161
setPackageInfoResolver(const sp<PackageInfoResolverInterface> & packageInfoResolver)162 void setPackageInfoResolver(const sp<PackageInfoResolverInterface>& packageInfoResolver) {
163 mCollector->mPackageInfoResolver = packageInfoResolver;
164 }
165
setUidIoStatsCollector(const sp<UidIoStatsCollectorInterface> & uidIoStatsCollector)166 void setUidIoStatsCollector(const sp<UidIoStatsCollectorInterface>& uidIoStatsCollector) {
167 mCollector->mUidIoStatsCollector = uidIoStatsCollector;
168 }
169
setUidProcStatsCollector(const sp<UidProcStatsCollectorInterface> & uidProcStatsCollector)170 void setUidProcStatsCollector(const sp<UidProcStatsCollectorInterface>& uidProcStatsCollector) {
171 mCollector->mUidProcStatsCollector = uidProcStatsCollector;
172 }
173
setUidCpuStatsCollector(const sp<UidCpuStatsCollectorInterface> & uidCpuStatsCollector)174 void setUidCpuStatsCollector(const sp<UidCpuStatsCollectorInterface>& uidCpuStatsCollector) {
175 mCollector->mUidCpuStatsCollector = uidCpuStatsCollector;
176 }
177
178 private:
179 sp<UidStatsCollector> mCollector;
180 };
181
182 } // namespace internal
183
184 class UidStatsCollectorTest : public ::testing::Test {
185 protected:
SetUp()186 virtual void SetUp() {
187 mUidStatsCollector = sp<UidStatsCollector>::make();
188 mUidStatsCollectorPeer = sp<internal::UidStatsCollectorPeer>::make(mUidStatsCollector);
189 mMockPackageInfoResolver = sp<MockPackageInfoResolver>::make();
190 mMockUidIoStatsCollector = sp<MockUidIoStatsCollector>::make();
191 mMockUidProcStatsCollector = sp<MockUidProcStatsCollector>::make();
192 mMockUidCpuStatsCollector = sp<MockUidCpuStatsCollector>::make();
193 mUidStatsCollectorPeer->setPackageInfoResolver(mMockPackageInfoResolver);
194 mUidStatsCollectorPeer->setUidIoStatsCollector(mMockUidIoStatsCollector);
195 mUidStatsCollectorPeer->setUidProcStatsCollector(mMockUidProcStatsCollector);
196 mUidStatsCollectorPeer->setUidCpuStatsCollector(mMockUidCpuStatsCollector);
197 }
198
TearDown()199 virtual void TearDown() {
200 mUidStatsCollector.clear();
201 mUidStatsCollectorPeer.clear();
202 mMockPackageInfoResolver.clear();
203 mMockUidIoStatsCollector.clear();
204 mMockUidProcStatsCollector.clear();
205 mMockUidCpuStatsCollector.clear();
206 }
207
208 sp<UidStatsCollector> mUidStatsCollector;
209 sp<internal::UidStatsCollectorPeer> mUidStatsCollectorPeer;
210 sp<MockPackageInfoResolver> mMockPackageInfoResolver;
211 sp<MockUidIoStatsCollector> mMockUidIoStatsCollector;
212 sp<MockUidProcStatsCollector> mMockUidProcStatsCollector;
213 sp<MockUidCpuStatsCollector> mMockUidCpuStatsCollector;
214 };
215
TEST_F(UidStatsCollectorTest,TestInit)216 TEST_F(UidStatsCollectorTest, TestInit) {
217 EXPECT_CALL(*mMockUidIoStatsCollector, init()).Times(1);
218 EXPECT_CALL(*mMockUidProcStatsCollector, init()).Times(1);
219
220 mUidStatsCollector->init();
221 }
222
TEST_F(UidStatsCollectorTest,TestCollect)223 TEST_F(UidStatsCollectorTest, TestCollect) {
224 EXPECT_CALL(*mMockUidIoStatsCollector, enabled()).WillOnce(Return(true));
225 EXPECT_CALL(*mMockUidProcStatsCollector, enabled()).WillOnce(Return(true));
226
227 EXPECT_CALL(*mMockUidIoStatsCollector, collect()).WillOnce(Return(Result<void>()));
228 EXPECT_CALL(*mMockUidProcStatsCollector, collect()).WillOnce(Return(Result<void>()));
229
230 EXPECT_CALL(*mMockUidIoStatsCollector, latestStats())
231 .WillOnce(Return(std::unordered_map<uid_t, UidIoStats>()));
232 EXPECT_CALL(*mMockUidProcStatsCollector, latestStats())
233 .WillOnce(Return(std::unordered_map<uid_t, UidProcStats>()));
234
235 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats())
236 .WillOnce(Return(std::unordered_map<uid_t, UidIoStats>()));
237 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats())
238 .WillOnce(Return(std::unordered_map<uid_t, UidProcStats>()));
239
240 ASSERT_RESULT_OK(mUidStatsCollector->collect());
241 }
242
TEST_F(UidStatsCollectorTest,TestFailsCollectOnUidIoStatsCollectorError)243 TEST_F(UidStatsCollectorTest, TestFailsCollectOnUidIoStatsCollectorError) {
244 Result<void> errorResult = Error() << "Failed to collect per-UID I/O stats";
245 EXPECT_CALL(*mMockUidIoStatsCollector, collect()).WillOnce(Return(errorResult));
246
247 ASSERT_FALSE(mUidStatsCollector->collect().ok())
248 << "Must fail to collect when per-UID I/O stats collector fails";
249 }
250
TEST_F(UidStatsCollectorTest,TestFailsCollectOnUidProcStatsCollectorError)251 TEST_F(UidStatsCollectorTest, TestFailsCollectOnUidProcStatsCollectorError) {
252 Result<void> errorResult = Error() << "Failed to collect per-UID proc stats";
253 EXPECT_CALL(*mMockUidProcStatsCollector, collect()).WillOnce(Return(errorResult));
254
255 ASSERT_FALSE(mUidStatsCollector->collect().ok())
256 << "Must fail to collect when per-UID proc stats collector fails";
257 }
258
TEST_F(UidStatsCollectorTest,TestCollectLatestStats)259 TEST_F(UidStatsCollectorTest, TestCollectLatestStats) {
260 const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
261 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
262 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
263 const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
264
265 EXPECT_CALL(*mMockPackageInfoResolver,
266 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
267 .WillOnce(Return(packageInfoByUid));
268 EXPECT_CALL(*mMockUidIoStatsCollector, latestStats()).WillOnce(Return(uidIoStatsByUid));
269 EXPECT_CALL(*mMockUidProcStatsCollector, latestStats()).WillOnce(Return(uidProcStatsByUid));
270 EXPECT_CALL(*mMockUidCpuStatsCollector, latestStats()).WillOnce(Return(uidCpuStatsByUid));
271
272 ASSERT_RESULT_OK(mUidStatsCollector->collect());
273
274 const std::vector<UidStats> expected = sampleUidStats();
275
276 auto actual = mUidStatsCollector->latestStats();
277
278 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
279 << "Latest UID stats doesn't match.\nExpected: " << toString(expected)
280 << "\nActual: " << toString(actual);
281
282 actual = mUidStatsCollector->deltaStats();
283
284 EXPECT_THAT(actual, IsEmpty()) << "Delta UID stats isn't empty.\nActual: " << toString(actual);
285 }
286
TEST_F(UidStatsCollectorTest,TestCollectDeltaStats)287 TEST_F(UidStatsCollectorTest, TestCollectDeltaStats) {
288 const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
289 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
290 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
291 const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
292
293 EXPECT_CALL(*mMockPackageInfoResolver,
294 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
295 .WillOnce(Return(packageInfoByUid));
296 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
297 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
298 EXPECT_CALL(*mMockUidCpuStatsCollector, deltaStats()).WillOnce(Return(uidCpuStatsByUid));
299
300 ASSERT_RESULT_OK(mUidStatsCollector->collect());
301
302 const std::vector<UidStats> expected = sampleUidStats();
303
304 auto actual = mUidStatsCollector->deltaStats();
305
306 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
307 << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
308 << "\nActual: " << toString(actual);
309
310 actual = mUidStatsCollector->latestStats();
311
312 EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
313 }
314
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingUidIoStats)315 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingUidIoStats) {
316 const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
317 std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
318 uidIoStatsByUid.erase(1001234);
319 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
320 const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
321
322 EXPECT_CALL(*mMockPackageInfoResolver,
323 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
324 .WillOnce(Return(packageInfoByUid));
325 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
326 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
327 EXPECT_CALL(*mMockUidCpuStatsCollector, deltaStats()).WillOnce(Return(uidCpuStatsByUid));
328
329 ASSERT_RESULT_OK(mUidStatsCollector->collect());
330
331 std::vector<UidStats> expected = sampleUidStats();
332 expected[0].ioStats = {};
333
334 auto actual = mUidStatsCollector->deltaStats();
335
336 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
337 << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
338 << "\nActual: " << toString(actual);
339
340 actual = mUidStatsCollector->latestStats();
341
342 EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
343 }
344
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingUidProcStats)345 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingUidProcStats) {
346 const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
347 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
348 std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
349 uidProcStatsByUid.erase(1001234);
350 const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
351
352 EXPECT_CALL(*mMockPackageInfoResolver,
353 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
354 .WillOnce(Return(packageInfoByUid));
355 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
356 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
357 EXPECT_CALL(*mMockUidCpuStatsCollector, deltaStats()).WillOnce(Return(uidCpuStatsByUid));
358
359 ASSERT_RESULT_OK(mUidStatsCollector->collect());
360
361 std::vector<UidStats> expected = sampleUidStats();
362 expected[0].procStats = {};
363
364 auto actual = mUidStatsCollector->deltaStats();
365
366 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
367 << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
368 << "\nActual: " << toString(actual);
369
370 actual = mUidStatsCollector->latestStats();
371
372 EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
373 }
374
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingUidCpuStats)375 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingUidCpuStats) {
376 const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
377 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
378 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
379
380 EXPECT_CALL(*mMockPackageInfoResolver,
381 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
382 .WillOnce(Return(packageInfoByUid));
383 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
384 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
385
386 ASSERT_RESULT_OK(mUidStatsCollector->collect());
387
388 std::vector<UidStats> expected = sampleUidStats();
389 // Since no Uid CPU time was recovered from the /proc/uid_cputime/show_uid_stat file, the
390 // collector will default the UID CPU time to the UidProcStats' CPU time.
391 expected[0].cpuTimeMillis = 10;
392
393 auto actual = mUidStatsCollector->deltaStats();
394
395 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
396 << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
397 << "\nActual: " << toString(actual);
398
399 actual = mUidStatsCollector->latestStats();
400
401 EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
402 }
403
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingPackageInfo)404 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingPackageInfo) {
405 std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
406 packageInfoByUid.erase(1001234);
407 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
408 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
409 const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
410
411 EXPECT_CALL(*mMockPackageInfoResolver,
412 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
413 .WillOnce(Return(packageInfoByUid));
414 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
415 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
416 EXPECT_CALL(*mMockUidCpuStatsCollector, deltaStats()).WillOnce(Return(uidCpuStatsByUid));
417
418 ASSERT_RESULT_OK(mUidStatsCollector->collect());
419
420 std::vector<UidStats> expected = sampleUidStats();
421 expected[0].packageInfo = constructPackageInfo("", 1001234);
422
423 auto actual = mUidStatsCollector->deltaStats();
424
425 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
426 << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
427 << "\nActual: " << toString(actual);
428
429 actual = mUidStatsCollector->latestStats();
430
431 EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
432 }
433
TEST_F(UidStatsCollectorTest,TestUidStatsHasPackageInfo)434 TEST_F(UidStatsCollectorTest, TestUidStatsHasPackageInfo) {
435 std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
436 packageInfoByUid.erase(1001234);
437 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
438 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
439
440 EXPECT_CALL(*mMockPackageInfoResolver,
441 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
442 .WillOnce(Return(packageInfoByUid));
443 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
444 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
445
446 ASSERT_RESULT_OK(mUidStatsCollector->collect());
447
448 const auto actual = mUidStatsCollector->deltaStats();
449
450 EXPECT_EQ(actual.size(), static_cast<size_t>(2));
451 for (const auto stats : actual) {
452 if (stats.packageInfo.packageIdentifier.uid == 1001234) {
453 EXPECT_FALSE(stats.hasPackageInfo())
454 << "Stats without package info should return false";
455 } else if (stats.packageInfo.packageIdentifier.uid == 1005678) {
456 EXPECT_TRUE(stats.hasPackageInfo()) << "Stats without package info should return true";
457 } else {
458 FAIL() << "Unexpected uid " << stats.packageInfo.packageIdentifier.uid;
459 }
460 }
461 }
462
TEST_F(UidStatsCollectorTest,TestUidStatsGenericPackageName)463 TEST_F(UidStatsCollectorTest, TestUidStatsGenericPackageName) {
464 std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
465 packageInfoByUid.erase(1001234);
466 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
467 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
468
469 EXPECT_CALL(*mMockPackageInfoResolver,
470 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
471 .WillOnce(Return(packageInfoByUid));
472 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
473 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
474
475 ASSERT_RESULT_OK(mUidStatsCollector->collect());
476
477 const auto actual = mUidStatsCollector->deltaStats();
478
479 EXPECT_EQ(actual.size(), static_cast<size_t>(2));
480 for (const auto stats : actual) {
481 if (stats.packageInfo.packageIdentifier.uid == 1001234) {
482 EXPECT_EQ(stats.genericPackageName(), "1001234")
483 << "Stats without package info should return UID as package name";
484 } else if (stats.packageInfo.packageIdentifier.uid == 1005678) {
485 EXPECT_EQ(stats.genericPackageName(), "kitchensink.app")
486 << "Stats with package info should return corresponding package name";
487 } else {
488 FAIL() << "Unexpected uid " << stats.packageInfo.packageIdentifier.uid;
489 }
490 }
491 }
492
TEST_F(UidStatsCollectorTest,TestUidStatsUid)493 TEST_F(UidStatsCollectorTest, TestUidStatsUid) {
494 std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
495 packageInfoByUid.erase(1001234);
496 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
497 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
498
499 EXPECT_CALL(*mMockPackageInfoResolver,
500 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
501 .WillOnce(Return(packageInfoByUid));
502 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
503 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
504
505 ASSERT_RESULT_OK(mUidStatsCollector->collect());
506
507 const auto actual = mUidStatsCollector->deltaStats();
508
509 for (const auto stats : actual) {
510 EXPECT_EQ(stats.uid(), static_cast<uid_t>(stats.packageInfo.packageIdentifier.uid));
511 }
512 }
513
514 } // namespace watchdog
515 } // namespace automotive
516 } // namespace android
517