1 /*
2  * Copyright 2024 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 "MockPressureChangeCallback.h"
18 #include "PressureMonitor.h"
19 
20 #include <android-base/file.h>
21 #include <android-base/stringprintf.h>
22 #include <gmock/gmock.h>
23 #include <log/log.h>
24 
25 #include <sys/epoll.h>
26 
27 #include <condition_variable>  // NOLINT(build/c++11)
28 #include <mutex>               // NOLINT(build/c++11)
29 #include <queue>
30 
31 namespace android {
32 namespace automotive {
33 namespace watchdog {
34 
35 namespace {
36 
37 using ::android::sp;
38 using ::android::base::StringAppendF;
39 using ::android::base::StringPrintf;
40 using ::android::base::WriteStringToFile;
41 using ::testing::_;
42 using ::testing::AllOf;
43 using ::testing::AnyNumber;
44 using ::testing::AtLeast;
45 using ::testing::Eq;
46 using ::testing::Field;
47 using ::testing::InSequence;
48 using ::testing::Matcher;
49 using ::testing::MockFunction;
50 using ::testing::NotNull;
51 using ::testing::Return;
52 using ::testing::Test;
53 using ::testing::UnorderedElementsAreArray;
54 
55 constexpr const char kSamplePsiData[] = "some avg10=0.00 avg60=0.00 avg300=0.00 total=51013728\n"
56                                         "full avg10=0.00 avg60=0.00 avg300=0.00 total=25154435";
57 constexpr std::chrono::milliseconds kTestPollingIntervalMillis = 100ms;
58 constexpr std::chrono::milliseconds kMaxWaitForResponsesConsumed = 5s;
59 
60 enum PsiMonitorState {
61     INITIALIZED = 0,
62     REGISTERED,
63     UNREGISTERED,
64     DESTROYED,
65     STATE_COUNT,
66 };
67 
68 struct PsiMonitorInfo {
69     const psi_stall_type kStallType;
70     const int kThresholdUs;
71     const int kWindowUs;
72     epoll_data_t epollData;
73     PsiMonitorState state;
74 
toStringandroid::automotive::watchdog::__anone4d6e1d10111::PsiMonitorInfo75     std::string toString() const {
76         std::string buffer;
77         StringAppendF(&buffer,
78                       "PsiMonitorInfo{kStallType = %d, kThresholdUs = %d, kWindowUs = %d, "
79                       "epollData = %d, state = %d}",
80                       kStallType, kThresholdUs, kWindowUs, epollData.u32, state);
81         return buffer;
82     }
83 };
84 
toString(const std::vector<PsiMonitorInfo> & psiMonitorInfos)85 std::string toString(const std::vector<PsiMonitorInfo>& psiMonitorInfos) {
86     std::string buffer;
87     for (const PsiMonitorInfo& info : psiMonitorInfos) {
88         StringAppendF(&buffer, "%s\n", info.toString().c_str());
89     }
90     return buffer;
91 }
92 
93 MATCHER_P(EpollDataEq, expected, "") {
94     return ExplainMatchResult(Field("u32", &epoll_data::u32, Eq(expected.u32)), arg,
95                               result_listener);
96 }
97 
98 MATCHER_P(PsiMonitorInfoEq, expected, "") {
99     return ExplainMatchResult(AllOf(Field("kStallType", &PsiMonitorInfo::kStallType,
100                                           Eq(expected.kStallType)),
101                                     Field("kThresholdUs", &PsiMonitorInfo::kThresholdUs,
102                                           Eq(expected.kThresholdUs)),
103                                     Field("kWindowUs", &PsiMonitorInfo::kWindowUs,
104                                           Eq(expected.kWindowUs)),
105                                     Field("epollData.u32", &PsiMonitorInfo::epollData,
106                                           EpollDataEq(expected.epollData)),
107                                     Field("state", &PsiMonitorInfo::state, Eq(expected.state))),
108                               arg, result_listener);
109 }
110 
111 // TODO(b/335508921): Once stats are read from system properties, mock the system property APIs to
112 //   pass this value.
113 const std::vector<PsiMonitorInfo> kDefaultPsiMonitorInfos =
114         {PsiMonitorInfo{
115                  .kStallType = kLowPsiStallLevel,
116                  .kThresholdUs = kLowThresholdUs.count(),
117                  .kWindowUs = kPsiWindowSizeUs.count(),
118                  .epollData.u32 = PressureMonitor::PRESSURE_LEVEL_LOW,
119                  .state = REGISTERED,
120          },
121          PsiMonitorInfo{
122                  .kStallType = kMediumPsiStallLevel,
123                  .kThresholdUs = kMediumThresholdUs.count(),
124                  .kWindowUs = kPsiWindowSizeUs.count(),
125                  .epollData.u32 = PressureMonitor::PRESSURE_LEVEL_MEDIUM,
126                  .state = REGISTERED,
127          },
128          PsiMonitorInfo{
129                  .kStallType = kHighPsiStallLevel,
130                  .kThresholdUs = kHighThresholdUs.count(),
131                  .kWindowUs = kPsiWindowSizeUs.count(),
132                  .epollData.u32 = PressureMonitor::PRESSURE_LEVEL_HIGH,
133                  .state = REGISTERED,
134          }};
135 
getPsiMonitorInfoMatchers(const std::vector<PsiMonitorInfo> & psiMonitorInfos)136 std::vector<Matcher<const PsiMonitorInfo&>> getPsiMonitorInfoMatchers(
137         const std::vector<PsiMonitorInfo>& psiMonitorInfos) {
138     std::vector<Matcher<const PsiMonitorInfo&>> psiMonitorInfoMatchers;
139     for (const auto& psiMonitorInfo : psiMonitorInfos) {
140         psiMonitorInfoMatchers.push_back(PsiMonitorInfoEq(psiMonitorInfo));
141     }
142     return psiMonitorInfoMatchers;
143 }
144 
145 }  // namespace
146 
147 class PressureMonitorTest : public Test {
148 protected:
149     enum EpollResponse {
150         EVENT_TRIGGERED = 0,
151         TIMEOUT,
152         EPOLL_ERROR,
153         EPOLL_HUP,
154     };
155 
156     struct EpollResponseInfo {
157         EpollResponse response = EVENT_TRIGGERED;
158         PressureMonitorInterface::PressureLevel highestPressureLevel =
159                 PressureMonitor::PRESSURE_LEVEL_NONE;
160     };
161 
SetUp()162     void SetUp() override {
163         mTempProcPressureDir = std::make_unique<TemporaryDir>();
164         createPressureFiles();
165         mInitPsiMonitorMockFunc = std::make_unique<
166                 MockFunction<int(enum psi_stall_type, int, int, enum psi_resource)>>();
167         mRegisterPsiMonitorMockFunc = std::make_unique<MockFunction<int(int, int, void*)>>();
168         mUnregisterPsiMonitorMockFunc = std::make_unique<MockFunction<int(int, int)>>();
169         mDestroyPsiMonitorMockFunc = std::make_unique<MockFunction<void(int)>>();
170         mEpollWaitMockFunc = std::make_unique<MockFunction<int(int, epoll_event*, int, int)>>();
171         mMockPressureChangeCallback = sp<MockPressureChangeCallback>::make();
172         mPressureMonitor =
173                 sp<PressureMonitor>::make(mTempProcPressureDir->path, kTestPollingIntervalMillis,
174                                           mInitPsiMonitorMockFunc->AsStdFunction(),
175                                           mRegisterPsiMonitorMockFunc->AsStdFunction(),
176                                           mUnregisterPsiMonitorMockFunc->AsStdFunction(),
177                                           mDestroyPsiMonitorMockFunc->AsStdFunction(),
178                                           mEpollWaitMockFunc->AsStdFunction());
179         ASSERT_TRUE(
180                 mPressureMonitor->registerPressureChangeCallback(mMockPressureChangeCallback).ok())
181                 << "Failed to register pressure change callback";
182         MockPsiApis();
183     }
184 
TearDown()185     void TearDown() override {
186         mPressureMonitor->unregisterPressureChangeCallback(mMockPressureChangeCallback);
187         mPressureMonitor->terminate();
188         mTempProcPressureDir.reset();
189         mInitPsiMonitorMockFunc.reset();
190         mRegisterPsiMonitorMockFunc.reset();
191         mUnregisterPsiMonitorMockFunc.reset();
192         mDestroyPsiMonitorMockFunc.reset();
193         mMockPressureChangeCallback.clear();
194         mPressureMonitor.clear();
195         mCachedPsiMonitorInfos.clear();
196     }
197 
createPressureFiles()198     void createPressureFiles() {
199         std::string path = StringPrintf("%s/%s", mTempProcPressureDir->path, kMemoryFile);
200         ASSERT_TRUE(WriteStringToFile(kSamplePsiData, path))
201                 << "Failed to write memory psi data to file '" << path << "'";
202     }
203 
MockPsiApis()204     void MockPsiApis() {
205         // Note: For failure case, mock individual calls and return error.
206         ON_CALL(*mInitPsiMonitorMockFunc, Call(_, _, _, PSI_MEMORY))
207                 .WillByDefault([this](enum psi_stall_type stallType, int thresholdUs, int windowUs,
208                                       [[maybe_unused]] enum psi_resource _) -> int {
209                     mCachedPsiMonitorInfos.push_back(PsiMonitorInfo{
210                             .kStallType = stallType,
211                             .kThresholdUs = thresholdUs,
212                             .kWindowUs = windowUs,
213                             .state = INITIALIZED,
214                     });
215                     // Return the index in mCachedPsiMonitorInfos as the FD.
216                     return mCachedPsiMonitorInfos.size() - 1;
217                 });
218 
219         ON_CALL(*mRegisterPsiMonitorMockFunc, Call(_, _, NotNull()))
220                 .WillByDefault([this](int epollFd, int fd, void* pressureLevel) -> int {
221                     // mInitPsiMonitorMockFunc returns an index in mCachedPsiMonitorInfos as the
222                     // FD.
223                     if (fd < 0 || fd >= static_cast<int>(mCachedPsiMonitorInfos.size())) {
224                         ALOGE("Failing register_psi_monitor call: FD is out of bounds");
225                         return -1;
226                     }
227                     mCachedPsiMonitorInfos[fd].epollData.ptr = pressureLevel;
228                     mCachedPsiMonitorInfos[fd].state = REGISTERED;
229                     mEpollFds.insert(epollFd);
230                     return 0;
231                 });
232 
233         ON_CALL(*mUnregisterPsiMonitorMockFunc, Call(_, _))
234                 .WillByDefault([this](int epollFd, int fd) -> int {
235                     if (mEpollFds.empty() || mCachedPsiMonitorInfos.empty()) {
236                         ALOGE("Failing unregister_psi_monitor call: No monitors are registered");
237                         return -1;
238                     }
239                     // mInitPsiMonitorMockFunc returns an index in mCachedPsiMonitorInfos as the
240                     // FD.
241                     if (fd < 0 || fd >= static_cast<int>(mCachedPsiMonitorInfos.size())) {
242                         ALOGE("Failing unregister_psi_monitor call: FD is out of bounds");
243                         return -1;
244                     }
245                     // mEpollFds should contain only one unique FD.
246                     if (mEpollFds.find(epollFd) == mEpollFds.end()) {
247                         ALOGE("Failing unregister_psi_monitor call: Received epoll FD %d doesn't "
248                               "match %d",
249                               epollFd, *mEpollFds.begin());
250                         return -1;
251                     }
252                     if (mCachedPsiMonitorInfos[fd].state != REGISTERED) {
253                         ALOGE("Failing unregister_psi_monitor call: FD is not in registered state");
254                         return -1;
255                     }
256                     mCachedPsiMonitorInfos[fd].epollData.ptr = nullptr;
257                     mCachedPsiMonitorInfos[fd].state = UNREGISTERED;
258                     return 0;
259                 });
260 
261         ON_CALL(*mDestroyPsiMonitorMockFunc, Call(_)).WillByDefault([this](int fd) -> void {
262             // mInitPsiMonitorMockFunc returns an index in mCachedPsiMonitorInfos as the FD.
263             if (fd < 0 || fd >= static_cast<int>(mCachedPsiMonitorInfos.size())) {
264                 ALOGE("Failing destroy_psi_monitor call: FD is out of bounds");
265                 return;
266             }
267             if (mCachedPsiMonitorInfos[fd].epollData.ptr != nullptr) {
268                 ALOGE("Failing destroy_psi_monitor call: epoll data is not null");
269                 return;
270             }
271             mCachedPsiMonitorInfos[fd].state = DESTROYED;
272             // Do not erase the entry from mCachedPsiMonitorInfos. Otherwise, indexing based on fd
273             // won't work for following entries.
274         });
275 
276         ON_CALL(*mEpollWaitMockFunc, Call(_, _, _, _))
277                 .WillByDefault([this](int epollFd, epoll_event* events, int maxEvents,
278                                       int timeout) -> int {
279                     if (mEpollFds.find(epollFd) == mEpollFds.end()) {
280                         ALOGE("Failing epoll_wait: Invalid epoll fd received");
281                         return -1;
282                     }
283                     if (events == nullptr ||
284                         maxEvents != static_cast<int>(mCachedPsiMonitorInfos.size())) {
285                         ALOGE("Failing epoll_wait: Null events or incorrect maxEvents received");
286                         return -1;
287                     }
288                     if (mEpollResponses.empty()) {
289                         return 0;
290                     }
291                     EpollResponseInfo responseInfo = mEpollResponses.front();
292                     mEpollResponses.pop();
293 
294                     if (responseInfo.response == EPOLL_ERROR ||
295                         responseInfo.response == EPOLL_HUP) {
296                         events[0].events =
297                                 responseInfo.response == EPOLL_ERROR ? EPOLLERR : EPOLLHUP;
298                         std::unique_lock lock(mMutex);
299                         mPollCondition.notify_all();
300                         return 1;
301                     }
302 
303                     if (responseInfo.response == TIMEOUT) {
304                         if (timeout == -1) {
305                             ALOGE("Failing epoll_wait: Cannot timeout on indefinite wait");
306                             std::unique_lock lock(mMutex);
307                             mPollCondition.notify_all();
308                             return -1;
309                         }
310                         std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
311                     }
312                     int totalEvents = 0;
313                     for (const auto& info : mCachedPsiMonitorInfos) {
314                         if (info.epollData.u32 <= responseInfo.highestPressureLevel) {
315                             events[totalEvents].events = 0;
316                             events[totalEvents++].data.u32 = info.epollData.u32;
317                         }
318                     }
319                     std::unique_lock lock(mMutex);
320                     mPollCondition.notify_all();
321                     return totalEvents;
322                 });
323     }
324 
queueResponses(const std::vector<EpollResponseInfo> & responses)325     void queueResponses(const std::vector<EpollResponseInfo>& responses) {
326         std::unique_lock lock(mMutex);
327         for (const auto& response : responses) {
328             mEpollResponses.push(response);
329         }
330     }
331 
waitUntilResponsesConsumed()332     void waitUntilResponsesConsumed() {
333         std::unique_lock lock(mMutex);
334         mPollCondition.wait_for(lock, kMaxWaitForResponsesConsumed,
335                                 [this]() { return mEpollResponses.empty(); });
336         // Wait for additional polling interval duration before returning to ensure that any
337         // notification message posted at the end of the lopper queue is processed before the test
338         // ends.
339         std::this_thread::sleep_for(std::chrono::milliseconds(kTestPollingIntervalMillis));
340     }
341 
342 protected:
343     std::unique_ptr<TemporaryDir> mTempProcPressureDir;
344     std::unique_ptr<MockFunction<int(enum psi_stall_type, int, int, enum psi_resource)>>
345             mInitPsiMonitorMockFunc;
346     std::unique_ptr<MockFunction<int(int, int, void*)>> mRegisterPsiMonitorMockFunc;
347     std::unique_ptr<MockFunction<int(int, int)>> mUnregisterPsiMonitorMockFunc;
348     std::unique_ptr<MockFunction<void(int)>> mDestroyPsiMonitorMockFunc;
349     std::unique_ptr<MockFunction<int(int, epoll_event*, int, int)>> mEpollWaitMockFunc;
350     sp<MockPressureChangeCallback> mMockPressureChangeCallback;
351 
352     sp<PressureMonitor> mPressureMonitor;
353     std::unordered_set<int> mEpollFds;
354 
355     std::vector<PsiMonitorInfo> mCachedPsiMonitorInfos;
356 
357 private:
358     mutable std::mutex mMutex;
359     std::condition_variable mPollCondition GUARDED_BY(mMutex);
360     std::queue<EpollResponseInfo> mEpollResponses GUARDED_BY(mMutex);
361 };
362 
TEST_F(PressureMonitorTest,TestInitializeAndTerminate)363 TEST_F(PressureMonitorTest, TestInitializeAndTerminate) {
364     auto result = mPressureMonitor->init();
365     ASSERT_TRUE(result.ok()) << "Initialize pressure monitor. Result: " << result.error();
366 
367     std::vector<PsiMonitorInfo> expectedPsiMonitorInfos = kDefaultPsiMonitorInfos;
368     EXPECT_THAT(mCachedPsiMonitorInfos,
369                 UnorderedElementsAreArray(getPsiMonitorInfoMatchers(expectedPsiMonitorInfos)))
370             << "PSI monitors after initialization.\nExpected:\n"
371             << toString(expectedPsiMonitorInfos) << "Actual:\n"
372             << toString(mCachedPsiMonitorInfos);
373 
374     mPressureMonitor->terminate();
375 
376     for (auto& info : expectedPsiMonitorInfos) {
377         info.epollData.ptr = nullptr;
378         info.state = DESTROYED;
379     }
380 
381     EXPECT_THAT(mCachedPsiMonitorInfos,
382                 UnorderedElementsAreArray(getPsiMonitorInfoMatchers(expectedPsiMonitorInfos)))
383             << "PSI monitors after termination.\nExpected:\n"
384             << toString(expectedPsiMonitorInfos) << "Actual:\n"
385             << toString(mCachedPsiMonitorInfos);
386 }
387 
TEST_F(PressureMonitorTest,TestFailInitPsiMonitor)388 TEST_F(PressureMonitorTest, TestFailInitPsiMonitor) {
389     ON_CALL(*mInitPsiMonitorMockFunc,
390             Call(kHighPsiStallLevel, kHighThresholdUs.count(), kPsiWindowSizeUs.count(),
391                  PSI_MEMORY))
392             .WillByDefault(Return(-1));
393 
394     auto result = mPressureMonitor->init();
395     ASSERT_FALSE(result.ok()) << "Initialization should fail on error";
396 
397     std::vector<PsiMonitorInfo> expectedPsiMonitorInfos{kDefaultPsiMonitorInfos[0],
398                                                         kDefaultPsiMonitorInfos[1]};
399 
400     for (auto& info : expectedPsiMonitorInfos) {
401         info.epollData.ptr = nullptr;
402         info.state = DESTROYED;
403     }
404 
405     EXPECT_THAT(mCachedPsiMonitorInfos,
406                 UnorderedElementsAreArray(getPsiMonitorInfoMatchers(expectedPsiMonitorInfos)))
407             << "PSI monitors after initialization failure.\nExpected:\n"
408             << toString(expectedPsiMonitorInfos) << "Actual:\n"
409             << toString(mCachedPsiMonitorInfos);
410 
411     ASSERT_FALSE(mPressureMonitor->start().ok())
412             << "Should fail to start pressure monitor when the initialization has failed";
413 
414     ASSERT_FALSE(mPressureMonitor->isMonitorActive())
415             << "Pressure monitor should be inactive when the initialization has failed";
416 }
417 
TEST_F(PressureMonitorTest,TestFailRegisterPsiMonitor)418 TEST_F(PressureMonitorTest, TestFailRegisterPsiMonitor) {
419     ON_CALL(*mRegisterPsiMonitorMockFunc,
420             Call(_, _, reinterpret_cast<void*>(PressureMonitor::PRESSURE_LEVEL_HIGH)))
421             .WillByDefault(Return(-1));
422 
423     auto result = mPressureMonitor->init();
424     ASSERT_FALSE(result.ok()) << "Initialization should fail on error";
425 
426     std::vector<PsiMonitorInfo> expectedPsiMonitorInfos = kDefaultPsiMonitorInfos;
427     for (auto& info : expectedPsiMonitorInfos) {
428         info.epollData.ptr = nullptr;
429         info.state = DESTROYED;
430     }
431 
432     EXPECT_THAT(mCachedPsiMonitorInfos,
433                 UnorderedElementsAreArray(getPsiMonitorInfoMatchers(expectedPsiMonitorInfos)))
434             << "PSI monitors after registration failure.\nExpected:\n"
435             << toString(expectedPsiMonitorInfos) << "Actual:\n"
436             << toString(mCachedPsiMonitorInfos);
437 
438     ASSERT_FALSE(mPressureMonitor->start().ok())
439             << "Should fail to start pressure monitor when the initialization has failed";
440 
441     ASSERT_FALSE(mPressureMonitor->isMonitorActive())
442             << "Pressure monitor should be inactive when the initialization has failed";
443 }
444 
TEST_F(PressureMonitorTest,TestFailToStartMonitorTwice)445 TEST_F(PressureMonitorTest, TestFailToStartMonitorTwice) {
446     auto result = mPressureMonitor->init();
447     ASSERT_TRUE(result.ok()) << "Initialize pressure monitor. Result: " << result.error();
448 
449     result = mPressureMonitor->start();
450     ASSERT_TRUE(result.ok()) << "Failed to start pressure monitor thread. Result: "
451                              << result.error();
452 
453     ASSERT_TRUE(mPressureMonitor->isMonitorActive());
454 
455     result = mPressureMonitor->start();
456     ASSERT_FALSE(result.ok()) << "Shouldn't start pressure monitor more than once. Result: "
457                               << result.error();
458 }
459 
TEST_F(PressureMonitorTest,TestPressureEvents)460 TEST_F(PressureMonitorTest, TestPressureEvents) {
461     auto result = mPressureMonitor->init();
462     ASSERT_TRUE(result.ok()) << "Initialize pressure monitor. Result: " << result.error();
463 
464     {
465         InSequence sequence;
466         EXPECT_CALL(*mMockPressureChangeCallback,
467                     onPressureChanged(PressureMonitor::PRESSURE_LEVEL_MEDIUM))
468                 .Times(1);
469         EXPECT_CALL(*mMockPressureChangeCallback,
470                     onPressureChanged(PressureMonitor::PRESSURE_LEVEL_LOW))
471                 .Times(1);
472         EXPECT_CALL(*mMockPressureChangeCallback,
473                     onPressureChanged(PressureMonitor::PRESSURE_LEVEL_HIGH))
474                 .Times(1);
475     }
476     EXPECT_CALL(*mMockPressureChangeCallback,
477                 onPressureChanged(PressureMonitor::PRESSURE_LEVEL_NONE))
478             .Times(AnyNumber());
479 
480     queueResponses(
481             {EpollResponseInfo{.response = EVENT_TRIGGERED,
482                                .highestPressureLevel = PressureMonitor::PRESSURE_LEVEL_MEDIUM},
483              EpollResponseInfo{.response = TIMEOUT,
484                                .highestPressureLevel = PressureMonitor::PRESSURE_LEVEL_LOW},
485              EpollResponseInfo{.response = EVENT_TRIGGERED,
486                                .highestPressureLevel = PressureMonitor::PRESSURE_LEVEL_HIGH}});
487 
488     result = mPressureMonitor->start();
489     ASSERT_TRUE(result.ok()) << "Failed to start pressure monitor thread. Result: "
490                              << result.error();
491 
492     waitUntilResponsesConsumed();
493 
494     ASSERT_TRUE(mPressureMonitor->isMonitorActive());
495 }
496 
TEST_F(PressureMonitorTest,TestHighPressureEvents)497 TEST_F(PressureMonitorTest, TestHighPressureEvents) {
498     auto result = mPressureMonitor->init();
499     ASSERT_TRUE(result.ok()) << "Initialize pressure monitor. Result: " << result.error();
500 
501     EXPECT_CALL(*mMockPressureChangeCallback,
502                 onPressureChanged(PressureMonitor::PRESSURE_LEVEL_HIGH))
503             .Times(2);
504 
505     EXPECT_CALL(*mMockPressureChangeCallback,
506                 onPressureChanged(PressureMonitor::PRESSURE_LEVEL_NONE))
507             .Times(AtLeast(1));
508 
509     queueResponses(
510             {EpollResponseInfo{.response = EVENT_TRIGGERED,
511                                .highestPressureLevel = PressureMonitor::PRESSURE_LEVEL_HIGH},
512 
513              EpollResponseInfo{.response = TIMEOUT,
514                                .highestPressureLevel = PressureMonitor::PRESSURE_LEVEL_NONE},
515 
516              EpollResponseInfo{.response = EVENT_TRIGGERED,
517                                .highestPressureLevel = PressureMonitor::PRESSURE_LEVEL_HIGH}});
518 
519     result = mPressureMonitor->start();
520     ASSERT_TRUE(result.ok()) << "Failed to start pressure monitor thread. Result: "
521                              << result.error();
522 
523     waitUntilResponsesConsumed();
524 
525     ASSERT_TRUE(mPressureMonitor->isMonitorActive());
526 }
527 
TEST_F(PressureMonitorTest,TestFailEpollError)528 TEST_F(PressureMonitorTest, TestFailEpollError) {
529     auto result = mPressureMonitor->init();
530     ASSERT_TRUE(result.ok()) << "Initialize pressure monitor. Result: " << result.error();
531 
532     EXPECT_CALL(*mMockPressureChangeCallback, onPressureChanged(_)).Times(0);
533 
534     queueResponses({EpollResponseInfo{.response = EPOLL_ERROR}});
535 
536     result = mPressureMonitor->start();
537     ASSERT_TRUE(result.ok()) << "Failed to start pressure monitor thread. Result: "
538                              << result.error();
539 
540     waitUntilResponsesConsumed();
541 
542     ASSERT_FALSE(mPressureMonitor->isMonitorActive()) << "Monitor should stop on epoll error";
543 }
544 
TEST_F(PressureMonitorTest,TestFailEpollHup)545 TEST_F(PressureMonitorTest, TestFailEpollHup) {
546     auto result = mPressureMonitor->init();
547     ASSERT_TRUE(result.ok()) << "Initialize pressure monitor. Result: " << result.error();
548 
549     EXPECT_CALL(*mMockPressureChangeCallback, onPressureChanged(_)).Times(0);
550 
551     queueResponses({EpollResponseInfo{.response = EPOLL_HUP}});
552 
553     result = mPressureMonitor->start();
554     ASSERT_TRUE(result.ok()) << "Failed to start pressure monitor thread. Result: "
555                              << result.error();
556 
557     waitUntilResponsesConsumed();
558 
559     ASSERT_FALSE(mPressureMonitor->isMonitorActive()) << "Monitor should stop on epoll hang up";
560 }
561 
562 }  // namespace watchdog
563 }  // namespace automotive
564 }  // namespace android
565