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 "MockIoOveruseMonitor.h"
18 #include "MockResourceOveruseListener.h"
19 #include "MockWatchdogInternalHandler.h"
20 #include "MockWatchdogPerfService.h"
21 #include "MockWatchdogProcessService.h"
22 #include "MockWatchdogServiceHelper.h"
23 #include "WatchdogBinderMediator.h"
24
25 #include <android-base/stringprintf.h>
26 #include <binder/IBinder.h>
27 #include <gmock/gmock.h>
28 #include <gtest/gtest.h>
29 #include <utils/String16.h>
30
31 #include <errno.h>
32
33 namespace android {
34 namespace automotive {
35 namespace watchdog {
36
37 using ::aidl::android::automotive::watchdog::ICarWatchdogClient;
38 using ::aidl::android::automotive::watchdog::ICarWatchdogClientDefault;
39 using ::aidl::android::automotive::watchdog::IoOveruseStats;
40 using ::aidl::android::automotive::watchdog::IResourceOveruseListener;
41 using ::aidl::android::automotive::watchdog::ResourceOveruseStats;
42 using ::aidl::android::automotive::watchdog::ResourceType;
43 using ::aidl::android::automotive::watchdog::StateType;
44 using ::aidl::android::automotive::watchdog::TimeoutLength;
45 using ::android::sp;
46 using ::android::String16;
47 using ::android::base::Result;
48 using ::android::base::StringAppendF;
49 using ::ndk::ICInterface;
50 using ::ndk::ScopedAStatus;
51 using ::ndk::SharedRefBase;
52 using ::testing::_;
53 using ::testing::ByMove;
54 using ::testing::DoAll;
55 using ::testing::Return;
56 using ::testing::SetArgPointee;
57 using ::testing::UnorderedElementsAreArray;
58
59 namespace {
60
61 const std::function<android::base::Result<void>(const char*, ICInterface*, bool, int)>
62 kAddServiceFunctionStub =
__anonf7a4a3ea0202(const char*, ICInterface*, bool, int) 63 [](const char*, ICInterface*, bool, int) -> Result<void> { return Result<void>{}; };
64
toString(const std::vector<ResourceOveruseStats> & resourceOveruseStats)65 std::string toString(const std::vector<ResourceOveruseStats>& resourceOveruseStats) {
66 std::string buffer;
67 for (const auto& stats : resourceOveruseStats) {
68 StringAppendF(&buffer, "%s\n", stats.toString().c_str());
69 }
70 return buffer;
71 }
72
73 } // namespace
74
75 namespace internal {
76
77 class WatchdogBinderMediatorPeer final {
78 public:
WatchdogBinderMediatorPeer(WatchdogBinderMediator * mediator)79 explicit WatchdogBinderMediatorPeer(WatchdogBinderMediator* mediator) : mMediator(mediator) {}
80
setWatchdogInternalHandler(const std::shared_ptr<WatchdogInternalHandlerInterface> & watchdogInternalHandler)81 void setWatchdogInternalHandler(
82 const std::shared_ptr<WatchdogInternalHandlerInterface>& watchdogInternalHandler) {
83 mMediator->mWatchdogInternalHandler = watchdogInternalHandler;
84 }
85
86 private:
87 WatchdogBinderMediator* mMediator;
88 };
89
90 }; // namespace internal
91
92 class WatchdogBinderMediatorTest : public ::testing::Test {
93 protected:
SetUp()94 virtual void SetUp() {
95 mMockWatchdogProcessService = sp<MockWatchdogProcessService>::make();
96 mMockWatchdogPerfService = sp<MockWatchdogPerfService>::make();
97 mMockIoOveruseMonitor = sp<MockIoOveruseMonitor>::make();
98 mWatchdogBinderMediator =
99 SharedRefBase::make<WatchdogBinderMediator>(mMockWatchdogProcessService,
100 mMockWatchdogPerfService,
101 sp<MockWatchdogServiceHelper>::make(),
102 mMockIoOveruseMonitor,
103 kAddServiceFunctionStub);
104 mMockWatchdogInternalHandler = SharedRefBase::make<MockWatchdogInternalHandler>();
105 internal::WatchdogBinderMediatorPeer peer(mWatchdogBinderMediator.get());
106 peer.setWatchdogInternalHandler(mMockWatchdogInternalHandler);
107 }
108
TearDown()109 virtual void TearDown() {
110 mMockWatchdogProcessService.clear();
111 mMockWatchdogPerfService.clear();
112 mMockIoOveruseMonitor.clear();
113 mWatchdogBinderMediator.reset();
114 }
115
116 sp<MockWatchdogProcessService> mMockWatchdogProcessService;
117 sp<MockWatchdogPerfService> mMockWatchdogPerfService;
118 sp<MockIoOveruseMonitor> mMockIoOveruseMonitor;
119 std::shared_ptr<MockWatchdogInternalHandler> mMockWatchdogInternalHandler;
120 std::shared_ptr<WatchdogBinderMediator> mWatchdogBinderMediator;
121 };
122
TEST_F(WatchdogBinderMediatorTest,TestInit)123 TEST_F(WatchdogBinderMediatorTest, TestInit) {
124 std::shared_ptr<WatchdogBinderMediator> mediator =
125 SharedRefBase::make<WatchdogBinderMediator>(sp<MockWatchdogProcessService>::make(),
126 sp<MockWatchdogPerfService>::make(),
127 sp<MockWatchdogServiceHelper>::make(),
128 sp<MockIoOveruseMonitor>::make(),
129 kAddServiceFunctionStub);
130
131 ASSERT_RESULT_OK(mediator->init());
132
133 ASSERT_NE(mediator->mWatchdogProcessService, nullptr);
134 ASSERT_NE(mediator->mWatchdogPerfService, nullptr);
135 ASSERT_NE(mediator->mIoOveruseMonitor, nullptr);
136 ASSERT_NE(mediator->mWatchdogInternalHandler, nullptr);
137 }
138
TEST_F(WatchdogBinderMediatorTest,TestErrorOnInitWithNullServiceInstances)139 TEST_F(WatchdogBinderMediatorTest, TestErrorOnInitWithNullServiceInstances) {
140 auto mockWatchdogProcessService = sp<MockWatchdogProcessService>::make();
141 auto mockWatchdogPerfservice = sp<MockWatchdogPerfService>::make();
142 auto mockWatchdogServiceHelper = sp<MockWatchdogServiceHelper>::make();
143 auto mockIoOveruseMonitor = sp<MockIoOveruseMonitor>::make();
144 std::shared_ptr<WatchdogBinderMediator> mediator =
145 SharedRefBase::make<WatchdogBinderMediator>(nullptr, mockWatchdogPerfservice,
146 mockWatchdogServiceHelper,
147 mockIoOveruseMonitor,
148 kAddServiceFunctionStub);
149
150 EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr watchdog process service";
151 mediator.reset();
152
153 mediator = SharedRefBase::make<WatchdogBinderMediator>(mockWatchdogProcessService, nullptr,
154 mockWatchdogServiceHelper,
155 mockIoOveruseMonitor,
156 kAddServiceFunctionStub);
157
158 EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr watchdog perf service";
159 mediator.reset();
160
161 mediator = SharedRefBase::make<WatchdogBinderMediator>(mockWatchdogProcessService,
162 mockWatchdogPerfservice, nullptr,
163 mockIoOveruseMonitor,
164 kAddServiceFunctionStub);
165
166 EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr watchdog service helper";
167 mediator.reset();
168
169 mediator = SharedRefBase::make<WatchdogBinderMediator>(mockWatchdogProcessService,
170 mockWatchdogPerfservice,
171 mockWatchdogServiceHelper, nullptr,
172 kAddServiceFunctionStub);
173
174 EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr I/O overuse monitor";
175 mediator.reset();
176
177 mediator = SharedRefBase::make<WatchdogBinderMediator>(nullptr, nullptr, nullptr, nullptr,
178 kAddServiceFunctionStub);
179
180 EXPECT_FALSE(mediator->init().ok()) << "No error returned on null services";
181 mediator.reset();
182 }
183
TEST_F(WatchdogBinderMediatorTest,TestDump)184 TEST_F(WatchdogBinderMediatorTest, TestDump) {
185 const char* args[] = {kStartCustomCollectionFlag, kIntervalFlag, "10", kMaxDurationFlag, "200"};
186 EXPECT_CALL(*mMockWatchdogInternalHandler, dump(-1, args, /*numArgs=*/5)).WillOnce(Return(OK));
187
188 ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args, /*numArgs=*/5), OK);
189 }
190
TEST_F(WatchdogBinderMediatorTest,TestRegisterClient)191 TEST_F(WatchdogBinderMediatorTest, TestRegisterClient) {
192 std::shared_ptr<ICarWatchdogClient> client = SharedRefBase::make<ICarWatchdogClientDefault>();
193 TimeoutLength timeout = TimeoutLength::TIMEOUT_MODERATE;
194
195 EXPECT_CALL(*mMockWatchdogProcessService, registerClient(client, timeout))
196 .WillOnce(Return(ByMove(ScopedAStatus::ok())));
197
198 auto status = mWatchdogBinderMediator->registerClient(client, timeout);
199
200 ASSERT_TRUE(status.isOk()) << status.getMessage();
201 }
202
TEST_F(WatchdogBinderMediatorTest,TestUnregisterClient)203 TEST_F(WatchdogBinderMediatorTest, TestUnregisterClient) {
204 std::shared_ptr<ICarWatchdogClient> client = SharedRefBase::make<ICarWatchdogClientDefault>();
205
206 EXPECT_CALL(*mMockWatchdogProcessService, unregisterClient(client))
207 .WillOnce(Return(ByMove(ScopedAStatus::ok())));
208
209 auto status = mWatchdogBinderMediator->unregisterClient(client);
210
211 ASSERT_TRUE(status.isOk()) << status.getMessage();
212 }
213
TEST_F(WatchdogBinderMediatorTest,TestTellClientAlive)214 TEST_F(WatchdogBinderMediatorTest, TestTellClientAlive) {
215 std::shared_ptr<ICarWatchdogClient> client = SharedRefBase::make<ICarWatchdogClientDefault>();
216
217 EXPECT_CALL(*mMockWatchdogProcessService, tellClientAlive(client, 456))
218 .WillOnce(Return(ByMove(ScopedAStatus::ok())));
219
220 auto status = mWatchdogBinderMediator->tellClientAlive(client, 456);
221
222 ASSERT_TRUE(status.isOk()) << status.getMessage();
223 }
224
TEST_F(WatchdogBinderMediatorTest,TestAddResourceOveruseListener)225 TEST_F(WatchdogBinderMediatorTest, TestAddResourceOveruseListener) {
226 std::shared_ptr<IResourceOveruseListener> listener =
227 SharedRefBase::make<MockResourceOveruseListener>();
228
229 EXPECT_CALL(*mMockIoOveruseMonitor, addIoOveruseListener(listener))
230 .WillOnce(Return(Result<void>{}));
231
232 auto status = mWatchdogBinderMediator->addResourceOveruseListener({ResourceType::IO}, listener);
233
234 ASSERT_TRUE(status.isOk()) << status.getMessage();
235 }
236
TEST_F(WatchdogBinderMediatorTest,TestErrorsAddResourceOveruseListenerOnInvalidArgs)237 TEST_F(WatchdogBinderMediatorTest, TestErrorsAddResourceOveruseListenerOnInvalidArgs) {
238 std::shared_ptr<IResourceOveruseListener> listener =
239 SharedRefBase::make<MockResourceOveruseListener>();
240 EXPECT_CALL(*mMockIoOveruseMonitor, addIoOveruseListener(listener)).Times(0);
241
242 ASSERT_FALSE(mWatchdogBinderMediator->addResourceOveruseListener({}, listener).isOk())
243 << "Should fail on empty resource types";
244
245 ASSERT_FALSE(
246 mWatchdogBinderMediator->addResourceOveruseListener({ResourceType::IO}, nullptr).isOk())
247 << "Should fail on null listener";
248 }
249
TEST_F(WatchdogBinderMediatorTest,TestRemoveResourceOveruseListener)250 TEST_F(WatchdogBinderMediatorTest, TestRemoveResourceOveruseListener) {
251 std::shared_ptr<IResourceOveruseListener> listener =
252 SharedRefBase::make<MockResourceOveruseListener>();
253
254 EXPECT_CALL(*mMockIoOveruseMonitor, removeIoOveruseListener(listener))
255 .WillOnce(Return(Result<void>{}));
256
257 auto status = mWatchdogBinderMediator->removeResourceOveruseListener(listener);
258
259 ASSERT_TRUE(status.isOk()) << status.getMessage();
260 }
261
TEST_F(WatchdogBinderMediatorTest,TestGetResourceOveruseStats)262 TEST_F(WatchdogBinderMediatorTest, TestGetResourceOveruseStats) {
263 IoOveruseStats ioOveruseStats;
264 ioOveruseStats.killableOnOveruse = true;
265 ioOveruseStats.startTime = 99898;
266 ioOveruseStats.durationInSeconds = 12345;
267 ioOveruseStats.totalOveruses = 3;
268 std::vector<ResourceOveruseStats> expected;
269 ResourceOveruseStats stats;
270 stats.set<ResourceOveruseStats::ioOveruseStats>(ioOveruseStats);
271 expected.emplace_back(std::move(stats));
272
273 EXPECT_CALL(*mMockIoOveruseMonitor, getIoOveruseStats(_))
274 .WillOnce(DoAll(SetArgPointee<0>(ioOveruseStats), Return(Result<void>{})));
275
276 std::vector<ResourceOveruseStats> actual;
277 auto status = mWatchdogBinderMediator->getResourceOveruseStats({ResourceType::IO}, &actual);
278
279 ASSERT_TRUE(status.isOk()) << status.getMessage();
280 EXPECT_THAT(actual, UnorderedElementsAreArray(expected))
281 << "Expected: " << toString(expected) << "\nActual: " << toString(actual);
282 }
283
TEST_F(WatchdogBinderMediatorTest,TestErrorsGetResourceOveruseStatsOnInvalidArgs)284 TEST_F(WatchdogBinderMediatorTest, TestErrorsGetResourceOveruseStatsOnInvalidArgs) {
285 EXPECT_CALL(*mMockIoOveruseMonitor, getIoOveruseStats(_)).Times(0);
286
287 std::vector<ResourceOveruseStats> actual;
288 ASSERT_FALSE(mWatchdogBinderMediator->getResourceOveruseStats({}, &actual).isOk())
289 << "Should fail on empty resource types";
290
291 ASSERT_FALSE(
292 mWatchdogBinderMediator->getResourceOveruseStats({ResourceType::IO}, nullptr).isOk())
293 << "Should fail on null listener";
294 }
295
TEST_F(WatchdogBinderMediatorTest,TestRegisterMediator)296 TEST_F(WatchdogBinderMediatorTest, TestRegisterMediator) {
297 auto status = mWatchdogBinderMediator->registerMediator(nullptr);
298 ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
299 }
300
TEST_F(WatchdogBinderMediatorTest,TestUnregisterMediator)301 TEST_F(WatchdogBinderMediatorTest, TestUnregisterMediator) {
302 auto status = mWatchdogBinderMediator->unregisterMediator(nullptr);
303 ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
304 }
305
TEST_F(WatchdogBinderMediatorTest,TestRegisterMonitor)306 TEST_F(WatchdogBinderMediatorTest, TestRegisterMonitor) {
307 auto status = mWatchdogBinderMediator->registerMonitor(nullptr);
308 ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
309 }
310
TEST_F(WatchdogBinderMediatorTest,TestUnregisterMonitor)311 TEST_F(WatchdogBinderMediatorTest, TestUnregisterMonitor) {
312 auto status = mWatchdogBinderMediator->unregisterMonitor(nullptr);
313 ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
314 }
315
TEST_F(WatchdogBinderMediatorTest,TestTellMediatorAlive)316 TEST_F(WatchdogBinderMediatorTest, TestTellMediatorAlive) {
317 auto status = mWatchdogBinderMediator->tellMediatorAlive(nullptr, {}, 0);
318 ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
319 }
320
TEST_F(WatchdogBinderMediatorTest,TestTellDumpFinished)321 TEST_F(WatchdogBinderMediatorTest, TestTellDumpFinished) {
322 auto status = mWatchdogBinderMediator->tellDumpFinished(nullptr, 0);
323 ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
324 }
325
TEST_F(WatchdogBinderMediatorTest,TestNotifySystemStateChange)326 TEST_F(WatchdogBinderMediatorTest, TestNotifySystemStateChange) {
327 auto status = mWatchdogBinderMediator->notifySystemStateChange(StateType::POWER_CYCLE, 0, 0);
328 ASSERT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
329 }
330
331 } // namespace watchdog
332 } // namespace automotive
333 } // namespace android
334