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