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