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 "MockWatchdogPerfService.h"
20 #include "MockWatchdogProcessService.h"
21 #include "MockWatchdogServiceHelper.h"
22 #include "WatchdogBinderMediator.h"
23
24 #include <android-base/stringprintf.h>
25 #include <binder/IBinder.h>
26 #include <gmock/gmock.h>
27 #include <gtest/gtest.h>
28 #include <utils/String16.h>
29
30 #include <errno.h>
31
32 namespace android {
33 namespace automotive {
34 namespace watchdog {
35
36 using ::android::sp;
37 using ::android::String16;
38 using ::android::base::Result;
39 using ::android::base::StringAppendF;
40 using ::android::binder::Status;
41 using ::testing::_;
42 using ::testing::DoAll;
43 using ::testing::Return;
44 using ::testing::SaveArg;
45 using ::testing::SetArgPointee;
46 using ::testing::UnorderedElementsAreArray;
47
48 namespace {
49
50 const std::function<android::base::Result<void>(const char*, const android::sp<android::IBinder>&)>
51 kAddServiceFunctionStub =
__anon6dfd99110202(const char*, const android::sp<android::IBinder>&) 52 [](const char*, const android::sp<android::IBinder>&) -> Result<void> {
53 return Result<void>{};
54 };
55
56 class MockICarWatchdogClient : public ICarWatchdogClient {
57 public:
58 MOCK_METHOD(Status, checkIfAlive, (int32_t sessionId, TimeoutLength timeout), (override));
59 MOCK_METHOD(Status, prepareProcessTermination, (), (override));
60 MOCK_METHOD(IBinder*, onAsBinder, (), (override));
61 MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
62 MOCK_METHOD(std::string, getInterfaceHash, (), (override));
63 };
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 {
78 public:
WatchdogBinderMediatorPeer(const sp<WatchdogBinderMediator> & mediator)79 explicit WatchdogBinderMediatorPeer(const sp<WatchdogBinderMediator>& mediator) :
80 mMediator(mediator) {}
~WatchdogBinderMediatorPeer()81 ~WatchdogBinderMediatorPeer() { mMediator.clear(); }
82
init(const sp<IIoOveruseMonitor> & ioOveruseMonitor)83 Result<void> init(const sp<IIoOveruseMonitor>& ioOveruseMonitor) {
84 mMediator->mIoOveruseMonitor = ioOveruseMonitor;
85 return mMediator->init();
86 }
87
88 private:
89 sp<WatchdogBinderMediator> mMediator;
90 };
91
92 } // namespace internal
93
94 class WatchdogBinderMediatorTest : public ::testing::Test {
95 protected:
SetUp()96 virtual void SetUp() {
97 mMockWatchdogProcessService = sp<MockWatchdogProcessService>::make();
98 mMockWatchdogPerfService = sp<MockWatchdogPerfService>::make();
99 mWatchdogBinderMediator =
100 sp<WatchdogBinderMediator>::make(mMockWatchdogProcessService,
101 mMockWatchdogPerfService,
102 sp<MockWatchdogServiceHelper>::make(),
103 kAddServiceFunctionStub);
104 internal::WatchdogBinderMediatorPeer mediatorPeer(mWatchdogBinderMediator);
105 mMockIoOveruseMonitor = sp<MockIoOveruseMonitor>::make();
106 ASSERT_RESULT_OK(mediatorPeer.init(mMockIoOveruseMonitor));
107 }
TearDown()108 virtual void TearDown() {
109 mMockWatchdogProcessService.clear();
110 mMockWatchdogPerfService.clear();
111 mMockIoOveruseMonitor.clear();
112 mWatchdogBinderMediator.clear();
113 }
114
115 sp<MockWatchdogProcessService> mMockWatchdogProcessService;
116 sp<MockWatchdogPerfService> mMockWatchdogPerfService;
117 sp<MockIoOveruseMonitor> mMockIoOveruseMonitor;
118 sp<WatchdogBinderMediator> mWatchdogBinderMediator;
119 };
120
TEST_F(WatchdogBinderMediatorTest,TestInit)121 TEST_F(WatchdogBinderMediatorTest, TestInit) {
122 sp<WatchdogBinderMediator> mediator =
123 sp<WatchdogBinderMediator>::make(sp<MockWatchdogProcessService>::make(),
124 sp<MockWatchdogPerfService>::make(),
125 sp<MockWatchdogServiceHelper>::make(),
126 kAddServiceFunctionStub);
127
128 ASSERT_RESULT_OK(mediator->init());
129
130 ASSERT_NE(mediator->mWatchdogProcessService, nullptr);
131 ASSERT_NE(mediator->mWatchdogPerfService, nullptr);
132 ASSERT_NE(mediator->mIoOveruseMonitor, nullptr);
133 ASSERT_NE(mediator->mWatchdogInternalHandler, nullptr);
134 }
135
TEST_F(WatchdogBinderMediatorTest,TestErrorOnInitWithNullServiceInstances)136 TEST_F(WatchdogBinderMediatorTest, TestErrorOnInitWithNullServiceInstances) {
137 auto mockWatchdogProcessService = sp<MockWatchdogProcessService>::make();
138 auto mockWatchdogPerfservice = sp<MockWatchdogPerfService>::make();
139 auto mockWatchdogServiceHelper = sp<MockWatchdogServiceHelper>::make();
140 sp<WatchdogBinderMediator> mediator =
141 sp<WatchdogBinderMediator>::make(nullptr, mockWatchdogPerfservice,
142 mockWatchdogServiceHelper, kAddServiceFunctionStub);
143
144 EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr watchdog process service";
145 mediator.clear();
146
147 mediator = sp<WatchdogBinderMediator>::make(mockWatchdogProcessService, nullptr,
148 mockWatchdogServiceHelper, kAddServiceFunctionStub);
149
150 EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr watchdog perf service";
151 mediator.clear();
152
153 mediator = sp<WatchdogBinderMediator>::make(mockWatchdogProcessService, mockWatchdogPerfservice,
154 nullptr, kAddServiceFunctionStub);
155
156 EXPECT_FALSE(mediator->init().ok()) << "No error returned on nullptr watchdog service helper";
157 mediator.clear();
158
159 mediator = sp<WatchdogBinderMediator>::make(nullptr, nullptr, nullptr, kAddServiceFunctionStub);
160
161 EXPECT_FALSE(mediator->init().ok()) << "No error returned on null services";
162 mediator.clear();
163 }
164
TEST_F(WatchdogBinderMediatorTest,TestTerminate)165 TEST_F(WatchdogBinderMediatorTest, TestTerminate) {
166 EXPECT_NE(mWatchdogBinderMediator->mWatchdogProcessService, nullptr);
167 EXPECT_NE(mWatchdogBinderMediator->mWatchdogPerfService, nullptr);
168 EXPECT_NE(mWatchdogBinderMediator->mIoOveruseMonitor, nullptr);
169 EXPECT_NE(mWatchdogBinderMediator->mWatchdogInternalHandler, nullptr);
170
171 mWatchdogBinderMediator->terminate();
172
173 EXPECT_EQ(mWatchdogBinderMediator->mWatchdogProcessService, nullptr);
174 EXPECT_EQ(mWatchdogBinderMediator->mWatchdogPerfService, nullptr);
175 EXPECT_EQ(mWatchdogBinderMediator->mIoOveruseMonitor, nullptr);
176 EXPECT_EQ(mWatchdogBinderMediator->mWatchdogInternalHandler, nullptr);
177 }
178
TEST_F(WatchdogBinderMediatorTest,TestDumpWithEmptyArgs)179 TEST_F(WatchdogBinderMediatorTest, TestDumpWithEmptyArgs) {
180 EXPECT_CALL(*mMockWatchdogProcessService, dump(-1, _)).WillOnce(Return(Result<void>()));
181 EXPECT_CALL(*mMockWatchdogPerfService, onDump(-1)).WillOnce(Return(Result<void>()));
182 mWatchdogBinderMediator->dump(-1, Vector<String16>());
183 }
184
TEST_F(WatchdogBinderMediatorTest,TestDumpWithStartCustomPerfCollection)185 TEST_F(WatchdogBinderMediatorTest, TestDumpWithStartCustomPerfCollection) {
186 EXPECT_CALL(*mMockWatchdogPerfService, onCustomCollection(-1, _))
187 .WillOnce(Return(Result<void>()));
188
189 Vector<String16> args;
190 args.push_back(String16(kStartCustomCollectionFlag));
191 ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args), OK);
192 }
193
TEST_F(WatchdogBinderMediatorTest,TestDumpWithStopCustomPerfCollection)194 TEST_F(WatchdogBinderMediatorTest, TestDumpWithStopCustomPerfCollection) {
195 EXPECT_CALL(*mMockWatchdogPerfService, onCustomCollection(-1, _))
196 .WillOnce(Return(Result<void>()));
197
198 Vector<String16> args;
199 args.push_back(String16(kEndCustomCollectionFlag));
200 ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args), OK);
201 }
202
TEST_F(WatchdogBinderMediatorTest,TestDumpWithResetResourceOveruseStats)203 TEST_F(WatchdogBinderMediatorTest, TestDumpWithResetResourceOveruseStats) {
204 std::vector<std::string> actualPackages;
205 EXPECT_CALL(*mMockIoOveruseMonitor, resetIoOveruseStats(_))
206 .WillOnce(DoAll(SaveArg<0>(&actualPackages), Return(Result<void>())));
207
208 Vector<String16> args;
209 args.push_back(String16(kResetResourceOveruseStatsFlag));
210 args.push_back(String16("packageA,packageB"));
211 ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args), OK);
212 ASSERT_EQ(actualPackages, std::vector<std::string>({"packageA", "packageB"}));
213 }
214
TEST_F(WatchdogBinderMediatorTest,TestFailsDumpWithInvalidResetResourceOveruseStatsArg)215 TEST_F(WatchdogBinderMediatorTest, TestFailsDumpWithInvalidResetResourceOveruseStatsArg) {
216 EXPECT_CALL(*mMockIoOveruseMonitor, resetIoOveruseStats(_)).Times(0);
217
218 Vector<String16> args;
219 args.push_back(String16(kResetResourceOveruseStatsFlag));
220 args.push_back(String16(""));
221 ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args), BAD_VALUE);
222 }
223
TEST_F(WatchdogBinderMediatorTest,TestDumpWithInvalidDumpArgs)224 TEST_F(WatchdogBinderMediatorTest, TestDumpWithInvalidDumpArgs) {
225 Vector<String16> args;
226 args.push_back(String16("--invalid_option"));
227 int nullFd = open("/dev/null", O_RDONLY);
228 EXPECT_CALL(*mMockWatchdogProcessService, dump(nullFd, _)).WillOnce(Return(Result<void>()));
229 EXPECT_CALL(*mMockWatchdogPerfService, onDump(nullFd)).WillOnce(Return(Result<void>()));
230
231 EXPECT_EQ(mWatchdogBinderMediator->dump(nullFd, args), OK) << "Error returned on invalid args";
232 close(nullFd);
233 }
234
TEST_F(WatchdogBinderMediatorTest,TestRegisterClient)235 TEST_F(WatchdogBinderMediatorTest, TestRegisterClient) {
236 sp<ICarWatchdogClient> client = sp<MockICarWatchdogClient>::make();
237 TimeoutLength timeout = TimeoutLength::TIMEOUT_MODERATE;
238 EXPECT_CALL(*mMockWatchdogProcessService, registerClient(client, timeout))
239 .WillOnce(Return(Status::ok()));
240 Status status = mWatchdogBinderMediator->registerClient(client, timeout);
241 ASSERT_TRUE(status.isOk()) << status;
242 }
243
TEST_F(WatchdogBinderMediatorTest,TestUnregisterClient)244 TEST_F(WatchdogBinderMediatorTest, TestUnregisterClient) {
245 sp<ICarWatchdogClient> client = sp<MockICarWatchdogClient>::make();
246 EXPECT_CALL(*mMockWatchdogProcessService, unregisterClient(client))
247 .WillOnce(Return(Status::ok()));
248 Status status = mWatchdogBinderMediator->unregisterClient(client);
249 ASSERT_TRUE(status.isOk()) << status;
250 }
251
TEST_F(WatchdogBinderMediatorTest,TestTellClientAlive)252 TEST_F(WatchdogBinderMediatorTest, TestTellClientAlive) {
253 sp<ICarWatchdogClient> client = sp<MockICarWatchdogClient>::make();
254 EXPECT_CALL(*mMockWatchdogProcessService, tellClientAlive(client, 456))
255 .WillOnce(Return(Status::ok()));
256 Status status = mWatchdogBinderMediator->tellClientAlive(client, 456);
257 ASSERT_TRUE(status.isOk()) << status;
258 }
259
TEST_F(WatchdogBinderMediatorTest,TestAddResourceOveruseListener)260 TEST_F(WatchdogBinderMediatorTest, TestAddResourceOveruseListener) {
261 sp<IResourceOveruseListener> listener = sp<MockResourceOveruseListener>::make();
262 EXPECT_CALL(*mMockIoOveruseMonitor, addIoOveruseListener(listener))
263 .WillOnce(Return(Result<void>{}));
264
265 Status status =
266 mWatchdogBinderMediator->addResourceOveruseListener({ResourceType::IO}, listener);
267 ASSERT_TRUE(status.isOk()) << status;
268 }
269
TEST_F(WatchdogBinderMediatorTest,TestErrorsAddResourceOveruseListenerOnInvalidArgs)270 TEST_F(WatchdogBinderMediatorTest, TestErrorsAddResourceOveruseListenerOnInvalidArgs) {
271 sp<IResourceOveruseListener> listener = sp<MockResourceOveruseListener>::make();
272 EXPECT_CALL(*mMockIoOveruseMonitor, addIoOveruseListener(listener)).Times(0);
273
274 ASSERT_FALSE(mWatchdogBinderMediator->addResourceOveruseListener({}, listener).isOk())
275 << "Should fail on empty resource types";
276
277 ASSERT_FALSE(
278 mWatchdogBinderMediator->addResourceOveruseListener({ResourceType::IO}, nullptr).isOk())
279 << "Should fail on null listener";
280 }
281
TEST_F(WatchdogBinderMediatorTest,TestRemoveResourceOveruseListener)282 TEST_F(WatchdogBinderMediatorTest, TestRemoveResourceOveruseListener) {
283 sp<IResourceOveruseListener> listener = sp<MockResourceOveruseListener>::make();
284 EXPECT_CALL(*mMockIoOveruseMonitor, removeIoOveruseListener(listener))
285 .WillOnce(Return(Result<void>{}));
286
287 Status status = mWatchdogBinderMediator->removeResourceOveruseListener(listener);
288 ASSERT_TRUE(status.isOk()) << status;
289 }
290
TEST_F(WatchdogBinderMediatorTest,TestGetResourceOveruseStats)291 TEST_F(WatchdogBinderMediatorTest, TestGetResourceOveruseStats) {
292 IoOveruseStats ioOveruseStats;
293 ioOveruseStats.killableOnOveruse = true;
294 ioOveruseStats.startTime = 99898;
295 ioOveruseStats.durationInSeconds = 12345;
296 ioOveruseStats.totalOveruses = 3;
297 std::vector<ResourceOveruseStats> expected;
298 ResourceOveruseStats stats;
299 stats.set<ResourceOveruseStats::ioOveruseStats>(ioOveruseStats);
300 expected.emplace_back(std::move(stats));
301
302 EXPECT_CALL(*mMockIoOveruseMonitor, getIoOveruseStats(_))
303 .WillOnce(DoAll(SetArgPointee<0>(ioOveruseStats), Return(Result<void>{})));
304
305 std::vector<ResourceOveruseStats> actual;
306 Status status = mWatchdogBinderMediator->getResourceOveruseStats({ResourceType::IO}, &actual);
307 ASSERT_TRUE(status.isOk()) << status;
308 EXPECT_THAT(actual, UnorderedElementsAreArray(expected))
309 << "Expected: " << toString(expected) << "\nActual: " << toString(actual);
310 }
311
TEST_F(WatchdogBinderMediatorTest,TestErrorsGetResourceOveruseStatsOnInvalidArgs)312 TEST_F(WatchdogBinderMediatorTest, TestErrorsGetResourceOveruseStatsOnInvalidArgs) {
313 sp<IResourceOveruseListener> listener = sp<MockResourceOveruseListener>::make();
314 EXPECT_CALL(*mMockIoOveruseMonitor, getIoOveruseStats(_)).Times(0);
315
316 std::vector<ResourceOveruseStats> actual;
317 ASSERT_FALSE(mWatchdogBinderMediator->getResourceOveruseStats({}, &actual).isOk())
318 << "Should fail on empty resource types";
319
320 ASSERT_FALSE(
321 mWatchdogBinderMediator->getResourceOveruseStats({ResourceType::IO}, nullptr).isOk())
322 << "Should fail on null listener";
323 }
324
TEST_F(WatchdogBinderMediatorTest,TestRegisterMediator)325 TEST_F(WatchdogBinderMediatorTest, TestRegisterMediator) {
326 Status status = mWatchdogBinderMediator->registerMediator(nullptr);
327 ASSERT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
328 }
329
TEST_F(WatchdogBinderMediatorTest,TestUnregisterMediator)330 TEST_F(WatchdogBinderMediatorTest, TestUnregisterMediator) {
331 Status status = mWatchdogBinderMediator->unregisterMediator(nullptr);
332 ASSERT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
333 }
334
TEST_F(WatchdogBinderMediatorTest,TestRegisterMonitor)335 TEST_F(WatchdogBinderMediatorTest, TestRegisterMonitor) {
336 Status status = mWatchdogBinderMediator->registerMonitor(nullptr);
337 ASSERT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
338 }
339
TEST_F(WatchdogBinderMediatorTest,TestUnregisterMonitor)340 TEST_F(WatchdogBinderMediatorTest, TestUnregisterMonitor) {
341 Status status = mWatchdogBinderMediator->unregisterMonitor(nullptr);
342 ASSERT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
343 }
344
TEST_F(WatchdogBinderMediatorTest,TestTellMediatorAlive)345 TEST_F(WatchdogBinderMediatorTest, TestTellMediatorAlive) {
346 Status status = mWatchdogBinderMediator->tellMediatorAlive(nullptr, {}, 0);
347 ASSERT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
348 }
349
TEST_F(WatchdogBinderMediatorTest,TestTellDumpFinished)350 TEST_F(WatchdogBinderMediatorTest, TestTellDumpFinished) {
351 Status status = mWatchdogBinderMediator->tellDumpFinished(nullptr, 0);
352 ASSERT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
353 }
354
TEST_F(WatchdogBinderMediatorTest,TestNotifySystemStateChange)355 TEST_F(WatchdogBinderMediatorTest, TestNotifySystemStateChange) {
356 Status status = mWatchdogBinderMediator->notifySystemStateChange(StateType::POWER_CYCLE, 0, 0);
357 ASSERT_EQ(status.exceptionCode(), Status::EX_UNSUPPORTED_OPERATION);
358 }
359
360 } // namespace watchdog
361 } // namespace automotive
362 } // namespace android
363