1 /*
2  * Copyright 2020 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 "LooperStub.h"
18 #include "MockDataProcessor.h"
19 #include "MockProcDiskStats.h"
20 #include "MockProcStat.h"
21 #include "MockUidStatsCollector.h"
22 #include "ProcStat.h"
23 #include "UidStatsCollector.h"
24 #include "WatchdogPerfService.h"
25 
26 #include <WatchdogProperties.sysprop.h>
27 #include <android-base/file.h>
28 #include <gmock/gmock.h>
29 
30 #include <future>  // NOLINT(build/c++11)
31 #include <queue>
32 #include <string>
33 #include <vector>
34 
35 namespace android {
36 namespace automotive {
37 namespace watchdog {
38 
39 using ::android::sp;
40 using ::android::String16;
41 using ::android::wp;
42 using ::android::automotive::watchdog::testing::LooperStub;
43 using ::android::base::Error;
44 using ::android::base::Result;
45 using ::testing::_;
46 using ::testing::InSequence;
47 using ::testing::Mock;
48 using ::testing::NiceMock;
49 using ::testing::Return;
50 using ::testing::StrictMock;
51 using ::testing::UnorderedElementsAreArray;
52 
53 constexpr std::chrono::seconds kTestBoottimeCollectionInterval = 1s;
54 constexpr std::chrono::seconds kTestPeriodicCollectionInterval = 5s;
55 constexpr std::chrono::seconds kTestCustomCollectionInterval = 3s;
56 constexpr std::chrono::seconds kTestCustomCollectionDuration = 11s;
57 constexpr std::chrono::seconds kTestPeriodicMonitorInterval = 2s;
58 
59 namespace internal {
60 
61 class WatchdogPerfServicePeer {
62 public:
WatchdogPerfServicePeer(sp<WatchdogPerfService> service)63     explicit WatchdogPerfServicePeer(sp<WatchdogPerfService> service) : service(service) {}
64     WatchdogPerfServicePeer() = delete;
~WatchdogPerfServicePeer()65     ~WatchdogPerfServicePeer() { service->terminate(); }
66 
injectFakes()67     void injectFakes() {
68         looperStub = sp<LooperStub>::make();
69         mockUidStatsCollector = sp<MockUidStatsCollector>::make();
70         mockProcDiskStats = sp<NiceMock<MockProcDiskStats>>::make();
71         mockProcStat = sp<NiceMock<MockProcStat>>::make();
72         mockDataProcessor = sp<StrictMock<MockDataProcessor>>::make();
73 
74         {
75             Mutex::Autolock lock(service->mMutex);
76             service->mHandlerLooper = looperStub;
77             service->mUidStatsCollector = mockUidStatsCollector;
78             service->mProcDiskStats = mockProcDiskStats;
79             service->mProcStat = mockProcStat;
80         }
81         EXPECT_CALL(*mockDataProcessor, init()).Times(1);
82         ASSERT_RESULT_OK(service->registerDataProcessor(mockDataProcessor));
83     }
84 
start()85     Result<void> start() {
86         if (auto ret = service->start(); !ret.ok()) {
87             return ret;
88         }
89         Mutex::Autolock lock(service->mMutex);
90         service->mBoottimeCollection.interval = kTestBoottimeCollectionInterval;
91         service->mPeriodicCollection.interval = kTestPeriodicCollectionInterval;
92         service->mPeriodicMonitor.interval = kTestPeriodicMonitorInterval;
93         return {};
94     }
95 
getCurrCollectionEvent()96     EventType getCurrCollectionEvent() {
97         Mutex::Autolock lock(service->mMutex);
98         return service->mCurrCollectionEvent;
99     }
100 
joinCollectionThread()101     std::future<void> joinCollectionThread() {
102         return std::async([&]() {
103             if (service->mCollectionThread.joinable()) {
104                 service->mCollectionThread.join();
105             }
106         });
107     }
108 
verifyAndClearExpectations()109     void verifyAndClearExpectations() {
110         Mock::VerifyAndClearExpectations(mockUidStatsCollector.get());
111         Mock::VerifyAndClearExpectations(mockProcStat.get());
112         Mock::VerifyAndClearExpectations(mockDataProcessor.get());
113     }
114 
115     sp<WatchdogPerfService> service;
116     // Below fields are populated only on injectFakes.
117     sp<LooperStub> looperStub;
118     sp<MockUidStatsCollector> mockUidStatsCollector;
119     sp<MockProcDiskStats> mockProcDiskStats;
120     sp<MockProcStat> mockProcStat;
121     sp<MockDataProcessor> mockDataProcessor;
122 };
123 
124 }  // namespace internal
125 
126 namespace {
127 
startPeriodicCollection(internal::WatchdogPerfServicePeer * servicePeer)128 void startPeriodicCollection(internal::WatchdogPerfServicePeer* servicePeer) {
129     ASSERT_NO_FATAL_FAILURE(servicePeer->injectFakes());
130 
131     ASSERT_RESULT_OK(servicePeer->start());
132 
133     EXPECT_CALL(*servicePeer->mockUidStatsCollector, collect()).Times(2);
134     EXPECT_CALL(*servicePeer->mockProcStat, collect()).Times(2);
135     EXPECT_CALL(*servicePeer->mockDataProcessor,
136                 onBoottimeCollection(_,
137                                      wp<UidStatsCollectorInterface>(
138                                              servicePeer->mockUidStatsCollector),
139                                      wp<ProcStat>(servicePeer->mockProcStat)))
140             .Times(2);
141 
142     // Make sure the collection event changes from EventType::INIT to
143     // EventType::BOOT_TIME_COLLECTION.
144     ASSERT_RESULT_OK(servicePeer->looperStub->pollCache());
145 
146     // Mark boot complete.
147     ASSERT_RESULT_OK(servicePeer->service->onBootFinished());
148 
149     // Process |SwitchMessage::END_BOOTTIME_COLLECTION| and switch to periodic collection.
150     ASSERT_RESULT_OK(servicePeer->looperStub->pollCache());
151 
152     ASSERT_EQ(servicePeer->getCurrCollectionEvent(), EventType::PERIODIC_COLLECTION)
153             << "Invalid collection event";
154 
155     servicePeer->verifyAndClearExpectations();
156 }
157 
skipPeriodicMonitorEvents(internal::WatchdogPerfServicePeer * servicePeer)158 void skipPeriodicMonitorEvents(internal::WatchdogPerfServicePeer* servicePeer) {
159     EXPECT_CALL(*servicePeer->mockDataProcessor, onPeriodicMonitor(_, _, _)).Times(2);
160     ASSERT_RESULT_OK(servicePeer->looperStub->pollCache());
161     ASSERT_RESULT_OK(servicePeer->looperStub->pollCache());
162 }
163 
164 }  // namespace
165 
TEST(WatchdogPerfServiceTest,TestServiceStartAndTerminate)166 TEST(WatchdogPerfServiceTest, TestServiceStartAndTerminate) {
167     sp<WatchdogPerfService> service = sp<WatchdogPerfService>::make();
168     sp<MockDataProcessor> mockDataProcessor = sp<MockDataProcessor>::make();
169 
170     EXPECT_CALL(*mockDataProcessor, init()).Times(1);
171 
172     ASSERT_RESULT_OK(service->registerDataProcessor(mockDataProcessor));
173     ASSERT_RESULT_OK(service->start());
174     ASSERT_TRUE(service->mCollectionThread.joinable()) << "Collection thread not created";
175     ASSERT_FALSE(service->start().ok())
176             << "No error returned when WatchdogPerfService was started more than once";
177     ASSERT_TRUE(sysprop::boottimeCollectionInterval().has_value());
178     ASSERT_EQ(std::chrono::duration_cast<std::chrono::seconds>(
179                       service->mBoottimeCollection.interval)
180                       .count(),
181               sysprop::boottimeCollectionInterval().value());
182     ASSERT_TRUE(sysprop::periodicCollectionInterval().has_value());
183     ASSERT_EQ(std::chrono::duration_cast<std::chrono::seconds>(
184                       service->mPeriodicCollection.interval)
185                       .count(),
186               sysprop::periodicCollectionInterval().value());
187 
188     service->terminate();
189     ASSERT_FALSE(service->mCollectionThread.joinable()) << "Collection thread did not terminate";
190 }
191 
TEST(WatchdogPerfServiceTest,TestValidCollectionSequence)192 TEST(WatchdogPerfServiceTest, TestValidCollectionSequence) {
193     sp<WatchdogPerfService> service = sp<WatchdogPerfService>::make();
194 
195     internal::WatchdogPerfServicePeer servicePeer(service);
196     ASSERT_NO_FATAL_FAILURE(servicePeer.injectFakes());
197 
198     ASSERT_RESULT_OK(servicePeer.start());
199 
200     wp<UidStatsCollectorInterface> uidStatsCollector(servicePeer.mockUidStatsCollector);
201     wp<IProcDiskStatsInterface> procDiskStats(servicePeer.mockProcDiskStats);
202     wp<ProcStat> procStat(servicePeer.mockProcStat);
203 
204     // #1 Boot-time collection
205     EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).Times(1);
206     EXPECT_CALL(*servicePeer.mockProcStat, collect()).Times(1);
207     EXPECT_CALL(*servicePeer.mockDataProcessor,
208                 onBoottimeCollection(_, uidStatsCollector, procStat))
209             .Times(1);
210 
211     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
212 
213     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), 0)
214             << "Boot-time collection didn't start immediately";
215     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::BOOT_TIME_COLLECTION)
216             << "Invalid collection event";
217     servicePeer.verifyAndClearExpectations();
218 
219     // #2 Boot-time collection
220     EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).Times(1);
221     EXPECT_CALL(*servicePeer.mockProcStat, collect()).Times(1);
222     EXPECT_CALL(*servicePeer.mockDataProcessor,
223                 onBoottimeCollection(_, uidStatsCollector, procStat))
224             .Times(1);
225 
226     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
227 
228     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), kTestBoottimeCollectionInterval.count())
229             << "Subsequent boot-time collection didn't happen at "
230             << kTestBoottimeCollectionInterval.count() << " seconds interval";
231     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::BOOT_TIME_COLLECTION)
232             << "Invalid collection event";
233     servicePeer.verifyAndClearExpectations();
234 
235     // #3 Last boot-time collection
236     EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).Times(1);
237     EXPECT_CALL(*servicePeer.mockProcStat, collect()).Times(1);
238     EXPECT_CALL(*servicePeer.mockDataProcessor,
239                 onBoottimeCollection(_, uidStatsCollector, procStat))
240             .Times(1);
241 
242     ASSERT_RESULT_OK(service->onBootFinished());
243 
244     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
245 
246     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), 0)
247             << "Last boot-time collection didn't happen immediately after receiving boot complete "
248             << "notification";
249     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::PERIODIC_COLLECTION)
250             << "Invalid collection event";
251     servicePeer.verifyAndClearExpectations();
252 
253     // #4 Periodic monitor
254     EXPECT_CALL(*servicePeer.mockProcDiskStats, collect()).Times(1);
255     EXPECT_CALL(*servicePeer.mockDataProcessor, onPeriodicMonitor(_, procDiskStats, _)).Times(1);
256 
257     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
258 
259     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), kTestPeriodicMonitorInterval.count())
260             << "First periodic monitor didn't happen at " << kTestPeriodicMonitorInterval.count()
261             << " seconds interval";
262     servicePeer.verifyAndClearExpectations();
263 
264     // #5 Periodic monitor
265     EXPECT_CALL(*servicePeer.mockProcDiskStats, collect()).Times(1);
266     EXPECT_CALL(*servicePeer.mockDataProcessor, onPeriodicMonitor(_, procDiskStats, _)).Times(1);
267 
268     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
269 
270     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), kTestPeriodicMonitorInterval.count())
271             << "Second periodic monitor didn't happen at " << kTestPeriodicMonitorInterval.count()
272             << " seconds interval";
273     servicePeer.verifyAndClearExpectations();
274 
275     // #6 Periodic collection
276     EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).Times(1);
277     EXPECT_CALL(*servicePeer.mockProcStat, collect()).Times(1);
278     EXPECT_CALL(*servicePeer.mockDataProcessor,
279                 onPeriodicCollection(_, SystemState::NORMAL_MODE, uidStatsCollector, procStat))
280             .Times(1);
281 
282     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
283 
284     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), 1)
285             << "First periodic collection didn't happen at 1 second interval";
286     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::PERIODIC_COLLECTION)
287             << "Invalid collection event";
288     servicePeer.verifyAndClearExpectations();
289 
290     // #7 Custom collection
291     Vector<String16> args;
292     args.push_back(String16(kStartCustomCollectionFlag));
293     args.push_back(String16(kIntervalFlag));
294     args.push_back(String16(std::to_string(kTestCustomCollectionInterval.count()).c_str()));
295     args.push_back(String16(kMaxDurationFlag));
296     args.push_back(String16(std::to_string(kTestCustomCollectionDuration.count()).c_str()));
297 
298     ASSERT_RESULT_OK(service->onCustomCollection(-1, args));
299 
300     EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).Times(1);
301     EXPECT_CALL(*servicePeer.mockProcStat, collect()).Times(1);
302     EXPECT_CALL(*servicePeer.mockDataProcessor,
303                 onCustomCollection(_, SystemState::NORMAL_MODE, _, uidStatsCollector, procStat))
304             .Times(1);
305 
306     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
307 
308     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), 0)
309             << "Custom collection didn't start immediately";
310     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::CUSTOM_COLLECTION)
311             << "Invalid collection event";
312     servicePeer.verifyAndClearExpectations();
313 
314     // #8 Custom collection
315     EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).Times(1);
316     EXPECT_CALL(*servicePeer.mockProcStat, collect()).Times(1);
317     EXPECT_CALL(*servicePeer.mockDataProcessor,
318                 onCustomCollection(_, SystemState::NORMAL_MODE, _, uidStatsCollector, procStat))
319             .Times(1);
320 
321     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
322 
323     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), kTestCustomCollectionInterval.count())
324             << "Subsequent custom collection didn't happen at "
325             << kTestCustomCollectionInterval.count() << " seconds interval";
326     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::CUSTOM_COLLECTION)
327             << "Invalid collection event";
328     servicePeer.verifyAndClearExpectations();
329 
330     // #9 End custom collection
331     TemporaryFile customDump;
332     {
333         InSequence s;
334         EXPECT_CALL(*servicePeer.mockDataProcessor, onCustomCollectionDump(customDump.fd)).Times(1);
335         EXPECT_CALL(*servicePeer.mockDataProcessor, onCustomCollectionDump(-1)).Times(1);
336     }
337 
338     args.clear();
339     args.push_back(String16(kEndCustomCollectionFlag));
340     ASSERT_RESULT_OK(service->onCustomCollection(customDump.fd, args));
341     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
342     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::PERIODIC_COLLECTION)
343             << "Invalid collection event";
344 
345     // #10 Switch to periodic collection
346     EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).Times(1);
347     EXPECT_CALL(*servicePeer.mockProcStat, collect()).Times(1);
348     EXPECT_CALL(*servicePeer.mockDataProcessor,
349                 onPeriodicCollection(_, SystemState::NORMAL_MODE, uidStatsCollector, procStat))
350             .Times(1);
351 
352     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
353 
354     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), 0)
355             << "Periodic collection didn't start immediately after ending custom collection";
356     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::PERIODIC_COLLECTION)
357             << "Invalid collection event";
358     servicePeer.verifyAndClearExpectations();
359 
360     // #11 Periodic monitor.
361     EXPECT_CALL(*servicePeer.mockProcDiskStats, collect()).Times(1);
362     EXPECT_CALL(*servicePeer.mockDataProcessor, onPeriodicMonitor(_, procDiskStats, _)).Times(1);
363 
364     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
365 
366     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), kTestPeriodicMonitorInterval.count());
367     servicePeer.verifyAndClearExpectations();
368 
369     EXPECT_CALL(*servicePeer.mockDataProcessor, terminate()).Times(1);
370 }
371 
TEST(WatchdogPerfServiceTest,TestCollectionTerminatesOnZeroEnabledCollectors)372 TEST(WatchdogPerfServiceTest, TestCollectionTerminatesOnZeroEnabledCollectors) {
373     sp<WatchdogPerfService> service = sp<WatchdogPerfService>::make();
374 
375     internal::WatchdogPerfServicePeer servicePeer(service);
376     ASSERT_NO_FATAL_FAILURE(servicePeer.injectFakes());
377 
378     ASSERT_RESULT_OK(servicePeer.start());
379 
380     ON_CALL(*servicePeer.mockUidStatsCollector, enabled()).WillByDefault(Return(false));
381     ON_CALL(*servicePeer.mockProcStat, enabled()).WillByDefault(Return(false));
382 
383     // Collection should terminate and call data processor's terminate method on error.
384     EXPECT_CALL(*servicePeer.mockDataProcessor, terminate()).Times(1);
385 
386     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
387 
388     ASSERT_EQ(servicePeer.joinCollectionThread().wait_for(1s), std::future_status::ready)
389             << "Collection thread didn't terminate within 1 second.";
390     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::TERMINATED);
391 }
392 
TEST(WatchdogPerfServiceTest,TestCollectionTerminatesOnDataCollectorError)393 TEST(WatchdogPerfServiceTest, TestCollectionTerminatesOnDataCollectorError) {
394     sp<WatchdogPerfService> service = sp<WatchdogPerfService>::make();
395 
396     internal::WatchdogPerfServicePeer servicePeer(service);
397     ASSERT_NO_FATAL_FAILURE(servicePeer.injectFakes());
398 
399     ASSERT_RESULT_OK(servicePeer.start());
400 
401     // Inject data collector error.
402     Result<void> errorRes = Error() << "Failed to collect data";
403     EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).WillOnce(Return(errorRes));
404 
405     // Collection should terminate and call data processor's terminate method on error.
406     EXPECT_CALL(*servicePeer.mockDataProcessor, terminate()).Times(1);
407 
408     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
409 
410     ASSERT_EQ(servicePeer.joinCollectionThread().wait_for(1s), std::future_status::ready)
411             << "Collection thread didn't terminate within 1 second.";
412     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::TERMINATED);
413 }
414 
TEST(WatchdogPerfServiceTest,TestCollectionTerminatesOnDataProcessorError)415 TEST(WatchdogPerfServiceTest, TestCollectionTerminatesOnDataProcessorError) {
416     sp<WatchdogPerfService> service = sp<WatchdogPerfService>::make();
417 
418     internal::WatchdogPerfServicePeer servicePeer(service);
419     ASSERT_NO_FATAL_FAILURE(servicePeer.injectFakes());
420 
421     EXPECT_CALL(*servicePeer.mockDataProcessor, name()).Times(1);
422 
423     ASSERT_RESULT_OK(servicePeer.start());
424 
425     // Inject data processor error.
426     Result<void> errorRes = Error() << "Failed to process data";
427     EXPECT_CALL(*servicePeer.mockDataProcessor,
428                 onBoottimeCollection(_,
429                                      wp<UidStatsCollectorInterface>(
430                                              servicePeer.mockUidStatsCollector),
431                                      wp<ProcStat>(servicePeer.mockProcStat)))
432             .WillOnce(Return(errorRes));
433 
434     // Collection should terminate and call data processor's terminate method on error.
435     EXPECT_CALL(*servicePeer.mockDataProcessor, terminate()).Times(1);
436 
437     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
438 
439     ASSERT_EQ(servicePeer.joinCollectionThread().wait_for(1s), std::future_status::ready)
440             << "Collection thread didn't terminate within 1 second.";
441     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::TERMINATED);
442 }
443 
TEST(WatchdogPerfServiceTest,TestCustomCollection)444 TEST(WatchdogPerfServiceTest, TestCustomCollection) {
445     sp<WatchdogPerfService> service = sp<WatchdogPerfService>::make();
446     internal::WatchdogPerfServicePeer servicePeer(service);
447 
448     ASSERT_NO_FATAL_FAILURE(startPeriodicCollection(&servicePeer));
449 
450     // Start custom collection with filter packages option.
451     Vector<String16> args;
452     args.push_back(String16(kStartCustomCollectionFlag));
453     args.push_back(String16(kIntervalFlag));
454     args.push_back(String16(std::to_string(kTestCustomCollectionInterval.count()).c_str()));
455     args.push_back(String16(kMaxDurationFlag));
456     args.push_back(String16(std::to_string(kTestCustomCollectionDuration.count()).c_str()));
457     args.push_back(String16(kFilterPackagesFlag));
458     args.push_back(String16("android.car.cts,system_server"));
459 
460     ASSERT_RESULT_OK(service->onCustomCollection(-1, args));
461 
462     // Poll until custom collection auto terminates.
463     int maxIterations = static_cast<int>(kTestCustomCollectionDuration.count() /
464                                          kTestCustomCollectionInterval.count());
465     for (int i = 0; i <= maxIterations; ++i) {
466         EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).Times(1);
467         EXPECT_CALL(*servicePeer.mockProcStat, collect()).Times(1);
468         EXPECT_CALL(*servicePeer.mockDataProcessor,
469                     onCustomCollection(_, SystemState::NORMAL_MODE,
470                                        UnorderedElementsAreArray(
471                                                {"android.car.cts", "system_server"}),
472                                        wp<UidStatsCollectorInterface>(
473                                                servicePeer.mockUidStatsCollector),
474                                        wp<ProcStat>(servicePeer.mockProcStat)))
475                 .Times(1);
476 
477         ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
478 
479         int secondsElapsed = (i == 0 ? 0 : kTestCustomCollectionInterval.count());
480         ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), secondsElapsed)
481                 << "Custom collection didn't happen at " << secondsElapsed
482                 << " seconds interval in iteration " << i;
483         ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::CUSTOM_COLLECTION)
484                 << "Invalid collection event";
485         servicePeer.verifyAndClearExpectations();
486     }
487 
488     EXPECT_CALL(*servicePeer.mockDataProcessor, onCustomCollectionDump(-1)).Times(1);
489 
490     // Next looper message was injected during startCustomCollection to end the custom collection
491     // after |kTestCustomCollectionDuration|. On processing this message, the custom collection
492     // should auto terminate.
493     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
494 
495     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(),
496               kTestCustomCollectionDuration.count() % kTestCustomCollectionInterval.count())
497             << "Custom collection did't end after " << kTestCustomCollectionDuration.count()
498             << " seconds";
499     ASSERT_EQ(servicePeer.getCurrCollectionEvent(), EventType::PERIODIC_COLLECTION)
500             << "Invalid collection event";
501     EXPECT_CALL(*servicePeer.mockDataProcessor, terminate()).Times(1);
502 }
503 
TEST(WatchdogPerfServiceTest,TestPeriodicMonitorRequestsCollection)504 TEST(WatchdogPerfServiceTest, TestPeriodicMonitorRequestsCollection) {
505     sp<WatchdogPerfService> service = sp<WatchdogPerfService>::make();
506     internal::WatchdogPerfServicePeer servicePeer(service);
507 
508     ASSERT_NO_FATAL_FAILURE(startPeriodicCollection(&servicePeer));
509 
510     wp<UidStatsCollectorInterface> uidStatsCollector(servicePeer.mockUidStatsCollector);
511     wp<IProcDiskStatsInterface> procDiskStats(servicePeer.mockProcDiskStats);
512     wp<ProcStat> procStat(servicePeer.mockProcStat);
513 
514     // Periodic monitor issuing an alert to start new collection.
515     EXPECT_CALL(*servicePeer.mockProcDiskStats, collect()).Times(1);
516     EXPECT_CALL(*servicePeer.mockDataProcessor, onPeriodicMonitor(_, procDiskStats, _))
517             .WillOnce([&](auto, auto, const auto& alertHandler) -> Result<void> {
518                 alertHandler();
519                 return {};
520             });
521 
522     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
523 
524     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), kTestPeriodicMonitorInterval.count())
525             << "First periodic monitor didn't happen at " << kTestPeriodicMonitorInterval.count()
526             << " seconds interval";
527     servicePeer.verifyAndClearExpectations();
528 
529     EXPECT_CALL(*servicePeer.mockUidStatsCollector, collect()).Times(1);
530     EXPECT_CALL(*servicePeer.mockProcStat, collect()).Times(1);
531     EXPECT_CALL(*servicePeer.mockDataProcessor,
532                 onPeriodicCollection(_, SystemState::NORMAL_MODE, uidStatsCollector, procStat))
533             .Times(1);
534 
535     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
536 
537     ASSERT_EQ(servicePeer.looperStub->numSecondsElapsed(), 0)
538             << "First periodic collection didn't happen immediately after the alert";
539 
540     servicePeer.verifyAndClearExpectations();
541 
542     EXPECT_CALL(*servicePeer.mockDataProcessor, terminate()).Times(1);
543 }
544 
TEST(WatchdogPerfServiceTest,TestSystemStateSwitch)545 TEST(WatchdogPerfServiceTest, TestSystemStateSwitch) {
546     sp<WatchdogPerfService> service = sp<WatchdogPerfService>::make();
547     internal::WatchdogPerfServicePeer servicePeer(service);
548 
549     ASSERT_NO_FATAL_FAILURE(startPeriodicCollection(&servicePeer));
550     ASSERT_NO_FATAL_FAILURE(skipPeriodicMonitorEvents(&servicePeer));
551 
552     EXPECT_CALL(*servicePeer.mockDataProcessor,
553                 onPeriodicCollection(_, SystemState::NORMAL_MODE, _, _))
554             .Times(1);
555 
556     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
557 
558     servicePeer.verifyAndClearExpectations();
559 
560     ASSERT_NO_FATAL_FAILURE(skipPeriodicMonitorEvents(&servicePeer));
561 
562     service->setSystemState(SystemState::GARAGE_MODE);
563 
564     EXPECT_CALL(*servicePeer.mockDataProcessor,
565                 onPeriodicCollection(_, SystemState::GARAGE_MODE, _, _))
566             .Times(1);
567 
568     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
569 
570     servicePeer.verifyAndClearExpectations();
571 
572     ASSERT_NO_FATAL_FAILURE(skipPeriodicMonitorEvents(&servicePeer));
573 
574     service->setSystemState(SystemState::NORMAL_MODE);
575 
576     EXPECT_CALL(*servicePeer.mockDataProcessor,
577                 onPeriodicCollection(_, SystemState::NORMAL_MODE, _, _))
578             .Times(1);
579 
580     ASSERT_RESULT_OK(servicePeer.looperStub->pollCache());
581 
582     servicePeer.verifyAndClearExpectations();
583 
584     EXPECT_CALL(*servicePeer.mockDataProcessor, terminate()).Times(1);
585 }
586 
TEST(WatchdogPerfServiceTest,TestHandlesInvalidDumpArguments)587 TEST(WatchdogPerfServiceTest, TestHandlesInvalidDumpArguments) {
588     sp<WatchdogPerfService> service = sp<WatchdogPerfService>::make();
589     Vector<String16> args;
590     args.push_back(String16(kStartCustomCollectionFlag));
591     args.push_back(String16("Invalid flag"));
592     args.push_back(String16("Invalid value"));
593     ASSERT_FALSE(service->onCustomCollection(-1, args).ok());
594 
595     args.clear();
596     args.push_back(String16(kStartCustomCollectionFlag));
597     args.push_back(String16(kIntervalFlag));
598     args.push_back(String16("Invalid interval"));
599     ASSERT_FALSE(service->onCustomCollection(-1, args).ok());
600 
601     args.clear();
602     args.push_back(String16(kStartCustomCollectionFlag));
603     args.push_back(String16(kMaxDurationFlag));
604     args.push_back(String16("Invalid duration"));
605     ASSERT_FALSE(service->onCustomCollection(-1, args).ok());
606 
607     args.clear();
608     args.push_back(String16(kEndCustomCollectionFlag));
609     args.push_back(String16(kMaxDurationFlag));
610     args.push_back(String16(std::to_string(kTestCustomCollectionDuration.count()).c_str()));
611     ASSERT_FALSE(service->onCustomCollection(-1, args).ok());
612 
613     args.clear();
614     args.push_back(String16("Invalid flag"));
615     ASSERT_FALSE(service->onCustomCollection(-1, args).ok());
616     service->terminate();
617 }
618 
619 }  // namespace watchdog
620 }  // namespace automotive
621 }  // namespace android
622