1 /*
2 * Copyright (C) 2021 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 <aidl/Gtest.h>
18 #include <aidl/Vintf.h>
19 #include <android-base/chrono_utils.h>
20 #include <android-base/file.h>
21 #include <android/automotive/watchdog/BnCarWatchdogClient.h>
22 #include <android/automotive/watchdog/ICarWatchdog.h>
23 #include <android/automotive/watchdog/IResourceOveruseListener.h>
24 #include <android/automotive/watchdog/IoOveruseStats.h>
25 #include <android/automotive/watchdog/PerStateBytes.h>
26 #include <android/automotive/watchdog/ResourceOveruseStats.h>
27 #include <android/automotive/watchdog/ResourceType.h>
28 #include <binder/IBinder.h>
29 #include <binder/IServiceManager.h>
30 #include <binder/ProcessState.h>
31 #include <binder/Status.h>
32 #include <gmock/gmock.h>
33 #include <utils/Condition.h>
34 #include <utils/Mutex.h>
35 #include <utils/StrongPointer.h>
36
37 #include <unistd.h>
38
39 #include <future> // NOLINT(build/c++11)
40
41 using ::android::BBinder;
42 using ::android::Condition;
43 using ::android::IBinder;
44 using ::android::Mutex;
45 using ::android::OK;
46 using ::android::ProcessState;
47 using ::android::sp;
48 using ::android::status_t;
49 using ::android::String16;
50 using ::android::wp;
51 using ::android::automotive::watchdog::BnCarWatchdogClient;
52 using ::android::automotive::watchdog::ICarWatchdog;
53 using ::android::automotive::watchdog::IoOveruseStats;
54 using ::android::automotive::watchdog::IResourceOveruseListenerDefault;
55 using ::android::automotive::watchdog::PerStateBytes;
56 using ::android::automotive::watchdog::ResourceOveruseStats;
57 using ::android::automotive::watchdog::ResourceType;
58 using ::android::automotive::watchdog::TimeoutLength;
59 using ::android::base::WriteStringToFile;
60 using ::android::binder::Status;
61 using ::testing::_;
62 using ::testing::InitGoogleTest;
63 using ::testing::Invoke;
64 using ::testing::Return;
65 using ::testing::TestWithParam;
66 using ::testing::ValuesIn;
67
68 namespace {
69
70 constexpr std::chrono::nanoseconds kMaxWatchdogPingWaitTimeNs = 6s;
71
72 class MockCarWatchdogClient : public BnCarWatchdogClient {
73 public:
MockCarWatchdogClient()74 MockCarWatchdogClient() {}
75
76 MOCK_METHOD(Status, checkIfAlive, (int32_t, TimeoutLength), (override));
77 MOCK_METHOD(Status, prepareProcessTermination, (), (override));
78
expectCheckIfAlive()79 void expectCheckIfAlive() {
80 EXPECT_CALL(*this, checkIfAlive(_, _))
81 .WillOnce(Invoke([&](int32_t sessionId, TimeoutLength timeoutLength) -> Status {
82 Mutex::Autolock lock(mMutex);
83 mSessionId = sessionId;
84 mTimeoutLength = timeoutLength;
85 mCond.signal();
86 return Status::ok();
87 }));
88 }
89
waitCheckIfAlive(TimeoutLength expectedTimeoutLength,int32_t * actualSessionId)90 void waitCheckIfAlive(TimeoutLength expectedTimeoutLength, int32_t* actualSessionId) {
91 Mutex::Autolock lock(mMutex);
92 ASSERT_THAT(mCond.waitRelative(mMutex, kMaxWatchdogPingWaitTimeNs.count()), OK);
93 ASSERT_THAT(mTimeoutLength, expectedTimeoutLength);
94 *actualSessionId = mSessionId;
95 }
96
97 private:
98 Mutex mMutex;
99 Condition mCond GUARDED_BY(mMutex);
100 int32_t mSessionId GUARDED_BY(mMutex);
101 TimeoutLength mTimeoutLength GUARDED_BY(mMutex);
102 };
103
104 class MockBinder : public BBinder {
105 public:
106 MOCK_METHOD(status_t, linkToDeath, (const sp<DeathRecipient>&, void*, uint32_t), (override));
107 MOCK_METHOD(status_t, unlinkToDeath,
108 (const wp<DeathRecipient>&, void*, uint32_t, wp<DeathRecipient>* outRecipient),
109 (override));
110 };
111
112 class MockResourceOveruseListener : public IResourceOveruseListenerDefault {
113 public:
MockResourceOveruseListener()114 MockResourceOveruseListener() : mMockBinder(sp<MockBinder>::make()) {}
115
116 MOCK_METHOD(IBinder*, onAsBinder, (), (override));
117
expectNormalBinder()118 void expectNormalBinder() {
119 EXPECT_CALL(*mMockBinder, linkToDeath(_, nullptr, 0)).WillRepeatedly(Return(OK));
120 EXPECT_CALL(*mMockBinder, unlinkToDeath(_, nullptr, 0, nullptr)).WillRepeatedly(Return(OK));
121 EXPECT_CALL(*this, onAsBinder()).WillRepeatedly(Return(mMockBinder.get()));
122 }
123
124 private:
125 sp<MockBinder> mMockBinder;
126 };
127
128 } // namespace
129
130 class WatchdogAidlTest : public TestWithParam<std::string> {
131 public:
SetUp()132 virtual void SetUp() {
133 watchdogServer =
134 android::waitForDeclaredService<ICarWatchdog>(String16(GetParam().c_str()));
135 ASSERT_NE(watchdogServer.get(), nullptr);
136 }
137
138 sp<ICarWatchdog> watchdogServer;
139 };
140
TEST_P(WatchdogAidlTest,TestWatchdogClient)141 TEST_P(WatchdogAidlTest, TestWatchdogClient) {
142 sp<MockCarWatchdogClient> mockClient = sp<MockCarWatchdogClient>::make();
143 mockClient->expectCheckIfAlive();
144 Status status = watchdogServer->registerClient(mockClient, TimeoutLength::TIMEOUT_CRITICAL);
145 ASSERT_TRUE(status.isOk()) << "Failed to register client: " << status.toString8();
146 int32_t sessionId;
147 ASSERT_NO_FATAL_FAILURE(
148 mockClient->waitCheckIfAlive(TimeoutLength::TIMEOUT_CRITICAL, &sessionId));
149 status = watchdogServer->tellClientAlive(mockClient, sessionId);
150 ASSERT_TRUE(status.isOk()) << "Failed to tell client alive: " << status.toString8();
151 status = watchdogServer->unregisterClient(mockClient);
152 ASSERT_TRUE(status.isOk()) << "Failed to unregister client: " << status.toString8();
153 }
154
TEST_P(WatchdogAidlTest,TestFailsRegisterClientWithNullptrClient)155 TEST_P(WatchdogAidlTest, TestFailsRegisterClientWithNullptrClient) {
156 ASSERT_FALSE(watchdogServer->registerClient(nullptr, TimeoutLength::TIMEOUT_CRITICAL).isOk())
157 << "Should fail to register null client";
158 }
159
TEST_P(WatchdogAidlTest,TestFailsToTellClientAliveForNotRegisteredClient)160 TEST_P(WatchdogAidlTest, TestFailsToTellClientAliveForNotRegisteredClient) {
161 sp<MockCarWatchdogClient> mockClient = sp<MockCarWatchdogClient>::make();
162 ASSERT_FALSE(watchdogServer->tellClientAlive(mockClient, 0).isOk())
163 << "Should fail tell client alive for not registered client";
164 }
165
TEST_P(WatchdogAidlTest,TestFailsToUnRegisterNotRegisteredClient)166 TEST_P(WatchdogAidlTest, TestFailsToUnRegisterNotRegisteredClient) {
167 sp<MockCarWatchdogClient> mockClient = sp<MockCarWatchdogClient>::make();
168 ASSERT_FALSE(watchdogServer->unregisterClient(mockClient).isOk())
169 << "Should fail to unregister not registered client";
170 }
171
TEST_P(WatchdogAidlTest,TestResourceOveruseListener)172 TEST_P(WatchdogAidlTest, TestResourceOveruseListener) {
173 sp<MockResourceOveruseListener> mockListener = sp<MockResourceOveruseListener>::make();
174 mockListener->expectNormalBinder();
175 Status status = watchdogServer->addResourceOveruseListener({ResourceType::IO}, mockListener);
176 ASSERT_TRUE(status.isOk()) << "Failed to add resource overuse listener: " << status.toString8();
177 status = watchdogServer->removeResourceOveruseListener(mockListener);
178 ASSERT_TRUE(status.isOk()) << "Failed to remove resource overuse listener: "
179 << status.toString8();
180 }
181
TEST_P(WatchdogAidlTest,TestFailsAddResourceOveruseListenerWithNoResourceType)182 TEST_P(WatchdogAidlTest, TestFailsAddResourceOveruseListenerWithNoResourceType) {
183 sp<MockResourceOveruseListener> mockListener = sp<MockResourceOveruseListener>::make();
184 mockListener->expectNormalBinder();
185 ASSERT_FALSE(watchdogServer->addResourceOveruseListener({}, mockListener).isOk())
186 << "Should fail to add resource overuse listener with no resource type";
187 }
188
TEST_P(WatchdogAidlTest,TestFailsAddResourceOveruseListenerWithNullptrListener)189 TEST_P(WatchdogAidlTest, TestFailsAddResourceOveruseListenerWithNullptrListener) {
190 ASSERT_FALSE(watchdogServer->addResourceOveruseListener({ResourceType::IO}, nullptr).isOk())
191 << "Should fail to add null resource overuse listener";
192 }
193
TEST_P(WatchdogAidlTest,TestFailsToRemoveNotAddedResourceOveruseListener)194 TEST_P(WatchdogAidlTest, TestFailsToRemoveNotAddedResourceOveruseListener) {
195 sp<MockResourceOveruseListener> mockListener = sp<MockResourceOveruseListener>::make();
196 mockListener->expectNormalBinder();
197 ASSERT_FALSE(watchdogServer->removeResourceOveruseListener(mockListener).isOk())
198 << "Should fail to remote listener that is not added";
199 }
200
201 /*
202 * getResourceOveruseStats AIDL method is not tested as it requires writing to disk and waiting
203 * until the watchdog server has read I/O stats. The waiting duration depends on the watchdog
204 * server's performance data collection frequency, which varies between 20 - 60 seconds depending
205 * on the build type. The core implementation is tested in ATS with the help of custom performance
206 * data collection, which requires dumpsys access and this is not available to VTS. Thus skipping
207 * this test in VTS.
208 */
209
TEST_P(WatchdogAidlTest,TestFailsGetResourceOveruseStatsWithNoResourceTypes)210 TEST_P(WatchdogAidlTest, TestFailsGetResourceOveruseStatsWithNoResourceTypes) {
211 std::vector<ResourceOveruseStats> resourceOveruseStats;
212 ASSERT_FALSE(watchdogServer->getResourceOveruseStats({}, &resourceOveruseStats).isOk())
213 << "Should fail to fetch resource overuse stats with no resource types";
214 }
215
216 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WatchdogAidlTest);
217 INSTANTIATE_TEST_SUITE_P(CarWatchdogServer, WatchdogAidlTest,
218 ValuesIn(android::getAidlHalInstanceNames(ICarWatchdog::descriptor)),
219 android::PrintInstanceNameToString);
220
main(int argc,char ** argv)221 int main(int argc, char** argv) {
222 InitGoogleTest(&argc, argv);
223 ProcessState::self()->setThreadPoolMaxThreadCount(1);
224 ProcessState::self()->startThreadPool();
225 return RUN_ALL_TESTS();
226 }
227