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