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 std::shared_ptr<PackageInfoResolverInterface> & packageInfoResolver)162     void setPackageInfoResolver(const std::shared_ptr<PackageInfoResolverInterface>&
163           packageInfoResolver) {
164         mCollector->mPackageInfoResolver = packageInfoResolver;
165     }
166 
setUidIoStatsCollector(const sp<UidIoStatsCollectorInterface> & uidIoStatsCollector)167     void setUidIoStatsCollector(const sp<UidIoStatsCollectorInterface>& uidIoStatsCollector) {
168         mCollector->mUidIoStatsCollector = uidIoStatsCollector;
169     }
170 
setUidProcStatsCollector(const sp<UidProcStatsCollectorInterface> & uidProcStatsCollector)171     void setUidProcStatsCollector(const sp<UidProcStatsCollectorInterface>& uidProcStatsCollector) {
172         mCollector->mUidProcStatsCollector = uidProcStatsCollector;
173     }
174 
setUidCpuStatsCollector(const sp<UidCpuStatsCollectorInterface> & uidCpuStatsCollector)175     void setUidCpuStatsCollector(const sp<UidCpuStatsCollectorInterface>& uidCpuStatsCollector) {
176         mCollector->mUidCpuStatsCollector = uidCpuStatsCollector;
177     }
178 
179 private:
180     sp<UidStatsCollector> mCollector;
181 };
182 
183 }  // namespace internal
184 
185 class UidStatsCollectorTest : public ::testing::Test {
186 protected:
SetUp()187     virtual void SetUp() {
188         mUidStatsCollector = sp<UidStatsCollector>::make();
189         mUidStatsCollectorPeer = sp<internal::UidStatsCollectorPeer>::make(mUidStatsCollector);
190         mMockPackageInfoResolver = std::make_shared<MockPackageInfoResolver>();
191         mMockUidIoStatsCollector = sp<MockUidIoStatsCollector>::make();
192         mMockUidProcStatsCollector = sp<MockUidProcStatsCollector>::make();
193         mMockUidCpuStatsCollector = sp<MockUidCpuStatsCollector>::make();
194         mUidStatsCollectorPeer->setPackageInfoResolver(mMockPackageInfoResolver);
195         mUidStatsCollectorPeer->setUidIoStatsCollector(mMockUidIoStatsCollector);
196         mUidStatsCollectorPeer->setUidProcStatsCollector(mMockUidProcStatsCollector);
197         mUidStatsCollectorPeer->setUidCpuStatsCollector(mMockUidCpuStatsCollector);
198     }
199 
TearDown()200     virtual void TearDown() {
201         mUidStatsCollector.clear();
202         mUidStatsCollectorPeer.clear();
203         mMockPackageInfoResolver.reset();
204         mMockUidIoStatsCollector.clear();
205         mMockUidProcStatsCollector.clear();
206         mMockUidCpuStatsCollector.clear();
207     }
208 
209     sp<UidStatsCollector> mUidStatsCollector;
210     sp<internal::UidStatsCollectorPeer> mUidStatsCollectorPeer;
211     std::shared_ptr<MockPackageInfoResolver> mMockPackageInfoResolver;
212     sp<MockUidIoStatsCollector> mMockUidIoStatsCollector;
213     sp<MockUidProcStatsCollector> mMockUidProcStatsCollector;
214     sp<MockUidCpuStatsCollector> mMockUidCpuStatsCollector;
215 };
216 
TEST_F(UidStatsCollectorTest,TestInit)217 TEST_F(UidStatsCollectorTest, TestInit) {
218     EXPECT_CALL(*mMockUidIoStatsCollector, init()).Times(1);
219     EXPECT_CALL(*mMockUidProcStatsCollector, init()).Times(1);
220 
221     mUidStatsCollector->init();
222 }
223 
TEST_F(UidStatsCollectorTest,TestCollect)224 TEST_F(UidStatsCollectorTest, TestCollect) {
225     EXPECT_CALL(*mMockUidIoStatsCollector, enabled()).WillOnce(Return(true));
226     EXPECT_CALL(*mMockUidProcStatsCollector, enabled()).WillOnce(Return(true));
227 
228     EXPECT_CALL(*mMockUidIoStatsCollector, collect()).WillOnce(Return(Result<void>()));
229     EXPECT_CALL(*mMockUidProcStatsCollector, collect()).WillOnce(Return(Result<void>()));
230 
231     EXPECT_CALL(*mMockUidIoStatsCollector, latestStats())
232             .WillOnce(Return(std::unordered_map<uid_t, UidIoStats>()));
233     EXPECT_CALL(*mMockUidProcStatsCollector, latestStats())
234             .WillOnce(Return(std::unordered_map<uid_t, UidProcStats>()));
235 
236     EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats())
237             .WillOnce(Return(std::unordered_map<uid_t, UidIoStats>()));
238     EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats())
239             .WillOnce(Return(std::unordered_map<uid_t, UidProcStats>()));
240 
241     ASSERT_RESULT_OK(mUidStatsCollector->collect());
242 }
243 
TEST_F(UidStatsCollectorTest,TestFailsCollectOnUidIoStatsCollectorError)244 TEST_F(UidStatsCollectorTest, TestFailsCollectOnUidIoStatsCollectorError) {
245     Result<void> errorResult = Error() << "Failed to collect per-UID I/O stats";
246     EXPECT_CALL(*mMockUidIoStatsCollector, collect()).WillOnce(Return(errorResult));
247 
248     ASSERT_FALSE(mUidStatsCollector->collect().ok())
249             << "Must fail to collect when per-UID I/O stats collector fails";
250 }
251 
TEST_F(UidStatsCollectorTest,TestFailsCollectOnUidProcStatsCollectorError)252 TEST_F(UidStatsCollectorTest, TestFailsCollectOnUidProcStatsCollectorError) {
253     Result<void> errorResult = Error() << "Failed to collect per-UID proc stats";
254     EXPECT_CALL(*mMockUidProcStatsCollector, collect()).WillOnce(Return(errorResult));
255 
256     ASSERT_FALSE(mUidStatsCollector->collect().ok())
257             << "Must fail to collect when per-UID proc stats collector fails";
258 }
259 
TEST_F(UidStatsCollectorTest,TestCollectLatestStats)260 TEST_F(UidStatsCollectorTest, TestCollectLatestStats) {
261     const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
262     const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
263     const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
264     const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
265 
266     EXPECT_CALL(*mMockPackageInfoResolver,
267                 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
268             .WillOnce(Return(packageInfoByUid));
269     EXPECT_CALL(*mMockUidIoStatsCollector, latestStats()).WillOnce(Return(uidIoStatsByUid));
270     EXPECT_CALL(*mMockUidProcStatsCollector, latestStats()).WillOnce(Return(uidProcStatsByUid));
271     EXPECT_CALL(*mMockUidCpuStatsCollector, latestStats()).WillOnce(Return(uidCpuStatsByUid));
272 
273     ASSERT_RESULT_OK(mUidStatsCollector->collect());
274 
275     const std::vector<UidStats> expected = sampleUidStats();
276 
277     auto actual = mUidStatsCollector->latestStats();
278 
279     EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
280             << "Latest UID stats doesn't match.\nExpected: " << toString(expected)
281             << "\nActual: " << toString(actual);
282 
283     actual = mUidStatsCollector->deltaStats();
284 
285     EXPECT_THAT(actual, IsEmpty()) << "Delta UID stats isn't empty.\nActual: " << toString(actual);
286 }
287 
TEST_F(UidStatsCollectorTest,TestCollectDeltaStats)288 TEST_F(UidStatsCollectorTest, TestCollectDeltaStats) {
289     const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
290     const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
291     const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
292     const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
293 
294     EXPECT_CALL(*mMockPackageInfoResolver,
295                 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
296             .WillOnce(Return(packageInfoByUid));
297     EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
298     EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
299     EXPECT_CALL(*mMockUidCpuStatsCollector, deltaStats()).WillOnce(Return(uidCpuStatsByUid));
300 
301     ASSERT_RESULT_OK(mUidStatsCollector->collect());
302 
303     const std::vector<UidStats> expected = sampleUidStats();
304 
305     auto actual = mUidStatsCollector->deltaStats();
306 
307     EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
308             << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
309             << "\nActual: " << toString(actual);
310 
311     actual = mUidStatsCollector->latestStats();
312 
313     EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
314 }
315 
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingUidIoStats)316 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingUidIoStats) {
317     const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
318     std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
319     uidIoStatsByUid.erase(1001234);
320     const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
321     const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
322 
323     EXPECT_CALL(*mMockPackageInfoResolver,
324                 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
325             .WillOnce(Return(packageInfoByUid));
326     EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
327     EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
328     EXPECT_CALL(*mMockUidCpuStatsCollector, deltaStats()).WillOnce(Return(uidCpuStatsByUid));
329 
330     ASSERT_RESULT_OK(mUidStatsCollector->collect());
331 
332     std::vector<UidStats> expected = sampleUidStats();
333     expected[0].ioStats = {};
334 
335     auto actual = mUidStatsCollector->deltaStats();
336 
337     EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
338             << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
339             << "\nActual: " << toString(actual);
340 
341     actual = mUidStatsCollector->latestStats();
342 
343     EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
344 }
345 
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingUidProcStats)346 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingUidProcStats) {
347     const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
348     const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
349     std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
350     uidProcStatsByUid.erase(1001234);
351     const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
352 
353     EXPECT_CALL(*mMockPackageInfoResolver,
354                 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
355             .WillOnce(Return(packageInfoByUid));
356     EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
357     EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
358     EXPECT_CALL(*mMockUidCpuStatsCollector, deltaStats()).WillOnce(Return(uidCpuStatsByUid));
359 
360     ASSERT_RESULT_OK(mUidStatsCollector->collect());
361 
362     std::vector<UidStats> expected = sampleUidStats();
363     expected[0].procStats = {};
364 
365     auto actual = mUidStatsCollector->deltaStats();
366 
367     EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
368             << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
369             << "\nActual: " << toString(actual);
370 
371     actual = mUidStatsCollector->latestStats();
372 
373     EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
374 }
375 
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingUidCpuStats)376 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingUidCpuStats) {
377     const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
378     const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
379     const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
380 
381     EXPECT_CALL(*mMockPackageInfoResolver,
382                 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
383             .WillOnce(Return(packageInfoByUid));
384     EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
385     EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
386 
387     ASSERT_RESULT_OK(mUidStatsCollector->collect());
388 
389     std::vector<UidStats> expected = sampleUidStats();
390     // Since no Uid CPU time was recovered from the /proc/uid_cputime/show_uid_stat file, the
391     // collector will default the UID CPU time to the UidProcStats' CPU time.
392     expected[0].cpuTimeMillis = 10;
393 
394     auto actual = mUidStatsCollector->deltaStats();
395 
396     EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
397             << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
398             << "\nActual: " << toString(actual);
399 
400     actual = mUidStatsCollector->latestStats();
401 
402     EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
403 }
404 
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingPackageInfo)405 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingPackageInfo) {
406     std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
407     packageInfoByUid.erase(1001234);
408     const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
409     const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
410     const std::unordered_map<uid_t, int64_t> uidCpuStatsByUid = sampleUidCpuStatsByUid();
411 
412     EXPECT_CALL(*mMockPackageInfoResolver,
413                 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
414             .WillOnce(Return(packageInfoByUid));
415     EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
416     EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
417     EXPECT_CALL(*mMockUidCpuStatsCollector, deltaStats()).WillOnce(Return(uidCpuStatsByUid));
418 
419     ASSERT_RESULT_OK(mUidStatsCollector->collect());
420 
421     std::vector<UidStats> expected = sampleUidStats();
422     expected[0].packageInfo = constructPackageInfo("", 1001234);
423 
424     auto actual = mUidStatsCollector->deltaStats();
425 
426     EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
427             << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
428             << "\nActual: " << toString(actual);
429 
430     actual = mUidStatsCollector->latestStats();
431 
432     EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
433 }
434 
TEST_F(UidStatsCollectorTest,TestUidStatsHasPackageInfo)435 TEST_F(UidStatsCollectorTest, TestUidStatsHasPackageInfo) {
436     std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
437     packageInfoByUid.erase(1001234);
438     const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
439     const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
440 
441     EXPECT_CALL(*mMockPackageInfoResolver,
442                 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
443             .WillOnce(Return(packageInfoByUid));
444     EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
445     EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
446 
447     ASSERT_RESULT_OK(mUidStatsCollector->collect());
448 
449     const auto actual = mUidStatsCollector->deltaStats();
450 
451     EXPECT_EQ(actual.size(), static_cast<size_t>(2));
452     for (const auto stats : actual) {
453         if (stats.packageInfo.packageIdentifier.uid == 1001234) {
454             EXPECT_FALSE(stats.hasPackageInfo())
455                     << "Stats without package info should return false";
456         } else if (stats.packageInfo.packageIdentifier.uid == 1005678) {
457             EXPECT_TRUE(stats.hasPackageInfo()) << "Stats without package info should return true";
458         } else {
459             FAIL() << "Unexpected uid " << stats.packageInfo.packageIdentifier.uid;
460         }
461     }
462 }
463 
TEST_F(UidStatsCollectorTest,TestUidStatsGenericPackageName)464 TEST_F(UidStatsCollectorTest, TestUidStatsGenericPackageName) {
465     std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
466     packageInfoByUid.erase(1001234);
467     const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
468     const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
469 
470     EXPECT_CALL(*mMockPackageInfoResolver,
471                 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
472             .WillOnce(Return(packageInfoByUid));
473     EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
474     EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
475 
476     ASSERT_RESULT_OK(mUidStatsCollector->collect());
477 
478     const auto actual = mUidStatsCollector->deltaStats();
479 
480     EXPECT_EQ(actual.size(), static_cast<size_t>(2));
481     for (const auto stats : actual) {
482         if (stats.packageInfo.packageIdentifier.uid == 1001234) {
483             EXPECT_EQ(stats.genericPackageName(), "1001234")
484                     << "Stats without package info should return UID as package name";
485         } else if (stats.packageInfo.packageIdentifier.uid == 1005678) {
486             EXPECT_EQ(stats.genericPackageName(), "kitchensink.app")
487                     << "Stats with package info should return corresponding package name";
488         } else {
489             FAIL() << "Unexpected uid " << stats.packageInfo.packageIdentifier.uid;
490         }
491     }
492 }
493 
TEST_F(UidStatsCollectorTest,TestUidStatsUid)494 TEST_F(UidStatsCollectorTest, TestUidStatsUid) {
495     std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
496     packageInfoByUid.erase(1001234);
497     const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
498     const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
499 
500     EXPECT_CALL(*mMockPackageInfoResolver,
501                 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
502             .WillOnce(Return(packageInfoByUid));
503     EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
504     EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
505 
506     ASSERT_RESULT_OK(mUidStatsCollector->collect());
507 
508     const auto actual = mUidStatsCollector->deltaStats();
509 
510     for (const auto stats : actual) {
511         EXPECT_EQ(stats.uid(), static_cast<uid_t>(stats.packageInfo.packageIdentifier.uid));
512     }
513 }
514 
515 }  // namespace watchdog
516 }  // namespace automotive
517 }  // namespace android
518