blob: 49891b74cdc60446f283a4c071d3cb6d54d47af7 [file] [log] [blame]
Yifan Hong69c22542017-10-03 17:40:24 -07001/*
2 * Copyright (C) 2017 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
Yifan Hongf86271d2017-11-06 12:52:20 -080017#define LOG_TAG "health_hidl_hal_test"
Yifan Hong69c22542017-10-03 17:40:24 -070018
19#include <mutex>
Yifan Hong03b2a342019-03-08 11:37:33 -080020#include <set>
21#include <string>
Yifan Hong69c22542017-10-03 17:40:24 -070022
Yifan Hong69c22542017-10-03 17:40:24 -070023#include <android-base/logging.h>
24#include <android/hardware/health/2.0/IHealth.h>
25#include <android/hardware/health/2.0/types.h>
Yifan Honge6807dd2019-03-07 13:04:33 -080026#include <gflags/gflags.h>
nelsonli4da3ca52019-12-10 17:17:09 +080027#include <gtest/gtest.h>
28#include <hidl/GtestPrinter.h>
29#include <hidl/ServiceManagement.h>
30#include <log/log.h>
Yifan Hong69c22542017-10-03 17:40:24 -070031
32using ::testing::AssertionFailure;
33using ::testing::AssertionResult;
34using ::testing::AssertionSuccess;
Yifan Hong69c22542017-10-03 17:40:24 -070035
Yifan Honge6807dd2019-03-07 13:04:33 -080036DEFINE_bool(force, false, "Force test healthd even when the default instance is present.");
37
Yifan Hong03b2a342019-03-08 11:37:33 -080038// If GTEST_SKIP is not implemented, use our own skipping mechanism
39#ifndef GTEST_SKIP
40static std::mutex gSkippedTestsMutex;
41static std::set<std::string> gSkippedTests;
42static std::string GetCurrentTestName() {
43 const auto& info = ::testing::UnitTest::GetInstance()->current_test_info();
44#ifdef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
45 std::string test_suite = info->test_suite_name();
46#else
47 std::string test_suite = info->test_case_name();
48#endif
49 return test_suite + "." + info->name();
50}
51
52#define GTEST_SKIP() \
53 do { \
54 std::unique_lock<std::mutex> lock(gSkippedTestsMutex); \
55 gSkippedTests.insert(GetCurrentTestName()); \
56 return; \
57 } while (0)
58
59#define SKIP_IF_SKIPPED() \
60 do { \
61 std::unique_lock<std::mutex> lock(gSkippedTestsMutex); \
62 if (gSkippedTests.find(GetCurrentTestName()) != gSkippedTests.end()) { \
63 std::cerr << "[ SKIPPED ] " << GetCurrentTestName() << std::endl; \
64 return; \
65 } \
66 } while (0)
67#else
68#define SKIP_IF_SKIPPED()
69#endif
70
Yifan Hong69c22542017-10-03 17:40:24 -070071namespace android {
72namespace hardware {
73namespace health {
74namespace V2_0 {
75
76using V1_0::BatteryStatus;
Yifan Hong69c22542017-10-03 17:40:24 -070077
nelsonli4da3ca52019-12-10 17:17:09 +080078class HealthHidlTest : public ::testing::TestWithParam<std::string> {
Yifan Hong69c22542017-10-03 17:40:24 -070079 public:
80 virtual void SetUp() override {
nelsonli4da3ca52019-12-10 17:17:09 +080081 std::string serviceName = GetParam();
Yifan Honge6807dd2019-03-07 13:04:33 -080082
83 if (serviceName == "backup" && !FLAGS_force &&
nelsonli4da3ca52019-12-10 17:17:09 +080084 IHealth::getService() != nullptr) {
Yifan Honge6807dd2019-03-07 13:04:33 -080085 LOG(INFO) << "Skipping tests on healthd because the default instance is present. "
86 << "Use --force if you really want to test healthd.";
87 GTEST_SKIP();
88 }
89
Yifan Hong69c22542017-10-03 17:40:24 -070090 LOG(INFO) << "get service with name:" << serviceName;
91 ASSERT_FALSE(serviceName.empty());
nelsonli4da3ca52019-12-10 17:17:09 +080092 mHealth = IHealth::getService(serviceName);
Yifan Hong69c22542017-10-03 17:40:24 -070093 ASSERT_NE(mHealth, nullptr);
94 }
95
96 sp<IHealth> mHealth;
97};
98
99class Callback : public IHealthInfoCallback {
Yifan Hong69c22542017-10-03 17:40:24 -0700100 public:
Hridya Valsarajud31932a2018-01-17 23:09:24 -0800101 Return<void> healthInfoChanged(const HealthInfo&) override {
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800102 std::lock_guard<std::mutex> lock(mMutex);
103 mInvoked = true;
104 mInvokedNotify.notify_all();
Yifan Hong69c22542017-10-03 17:40:24 -0700105 return Void();
106 }
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800107 template <typename R, typename P>
108 bool waitInvoke(std::chrono::duration<R, P> duration) {
Yifan Hong69c22542017-10-03 17:40:24 -0700109 std::unique_lock<std::mutex> lock(mMutex);
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800110 bool r = mInvokedNotify.wait_for(lock, duration, [this] { return this->mInvoked; });
111 mInvoked = false;
112 return r;
Yifan Hong69c22542017-10-03 17:40:24 -0700113 }
Yifan Hong69c22542017-10-03 17:40:24 -0700114 private:
115 std::mutex mMutex;
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800116 std::condition_variable mInvokedNotify;
117 bool mInvoked = false;
Yifan Hong69c22542017-10-03 17:40:24 -0700118};
119
120#define ASSERT_OK(r) ASSERT_TRUE(isOk(r))
121#define EXPECT_OK(r) EXPECT_TRUE(isOk(r))
122template <typename T>
123AssertionResult isOk(const Return<T>& r) {
124 return r.isOk() ? AssertionSuccess() : (AssertionFailure() << r.description());
125}
126
127#define ASSERT_ALL_OK(r) ASSERT_TRUE(isAllOk(r))
128// Both isOk() and Result::SUCCESS
129AssertionResult isAllOk(const Return<Result>& r) {
130 if (!r.isOk()) {
131 return AssertionFailure() << r.description();
132 }
133 if (static_cast<Result>(r) != Result::SUCCESS) {
134 return AssertionFailure() << toString(static_cast<Result>(r));
135 }
136 return AssertionSuccess();
137}
138
139/**
140 * Test whether callbacks work. Tested functions are IHealth::registerCallback,
141 * unregisterCallback, and update.
142 */
nelsonli4da3ca52019-12-10 17:17:09 +0800143TEST_P(HealthHidlTest, Callbacks) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800144 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700145 using namespace std::chrono_literals;
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800146 sp<Callback> firstCallback = new Callback();
147 sp<Callback> secondCallback = new Callback();
Yifan Hong69c22542017-10-03 17:40:24 -0700148
149 ASSERT_ALL_OK(mHealth->registerCallback(firstCallback));
150 ASSERT_ALL_OK(mHealth->registerCallback(secondCallback));
151
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800152 // registerCallback may or may not invoke the callback immediately, so the test needs
153 // to wait for the invocation. If the implementation chooses not to invoke the callback
154 // immediately, just wait for some time.
155 firstCallback->waitInvoke(200ms);
156 secondCallback->waitInvoke(200ms);
Yifan Hong69c22542017-10-03 17:40:24 -0700157
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800158 // assert that the first callback is invoked when update is called.
Yifan Hong69c22542017-10-03 17:40:24 -0700159 ASSERT_ALL_OK(mHealth->update());
160
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800161 ASSERT_TRUE(firstCallback->waitInvoke(1s));
162 ASSERT_TRUE(secondCallback->waitInvoke(1s));
Yifan Hong69c22542017-10-03 17:40:24 -0700163
164 ASSERT_ALL_OK(mHealth->unregisterCallback(firstCallback));
165
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800166 // clear any potentially pending callbacks result from wakealarm / kernel events
167 // If there is none, just wait for some time.
168 firstCallback->waitInvoke(200ms);
169 secondCallback->waitInvoke(200ms);
Yifan Hong69c22542017-10-03 17:40:24 -0700170
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800171 // assert that the second callback is still invoked even though the first is unregistered.
Yifan Hong69c22542017-10-03 17:40:24 -0700172 ASSERT_ALL_OK(mHealth->update());
173
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800174 ASSERT_FALSE(firstCallback->waitInvoke(200ms));
175 ASSERT_TRUE(secondCallback->waitInvoke(1s));
Yifan Hong69c22542017-10-03 17:40:24 -0700176
177 ASSERT_ALL_OK(mHealth->unregisterCallback(secondCallback));
Yifan Hong69c22542017-10-03 17:40:24 -0700178}
179
nelsonli4da3ca52019-12-10 17:17:09 +0800180TEST_P(HealthHidlTest, UnregisterNonExistentCallback) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800181 SKIP_IF_SKIPPED();
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800182 sp<Callback> callback = new Callback();
Yifan Hong69c22542017-10-03 17:40:24 -0700183 auto ret = mHealth->unregisterCallback(callback);
184 ASSERT_OK(ret);
185 ASSERT_EQ(Result::NOT_FOUND, static_cast<Result>(ret)) << "Actual: " << toString(ret);
186}
187
188/**
189 * Pass the test if:
190 * - Property is not supported (res == NOT_SUPPORTED)
191 * - Result is success, and predicate is true
192 * @param res the Result value.
193 * @param valueStr the string representation for actual value (for error message)
194 * @param pred a predicate that test whether the value is valid
195 */
196#define EXPECT_VALID_OR_UNSUPPORTED_PROP(res, valueStr, pred) \
197 EXPECT_TRUE(isPropertyOk(res, valueStr, pred, #pred))
198
199AssertionResult isPropertyOk(Result res, const std::string& valueStr, bool pred,
200 const std::string& predStr) {
201 if (res == Result::SUCCESS) {
202 if (pred) {
203 return AssertionSuccess();
204 }
205 return AssertionFailure() << "value doesn't match.\nActual: " << valueStr
206 << "\nExpected: " << predStr;
207 }
208 if (res == Result::NOT_SUPPORTED) {
209 return AssertionSuccess();
210 }
211 return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res);
212}
213
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800214bool verifyStorageInfo(const hidl_vec<struct StorageInfo>& info) {
215 for (size_t i = 0; i < info.size(); i++) {
216 if (!(0 <= info[i].eol && info[i].eol <= 3 && 0 <= info[i].lifetimeA &&
217 info[i].lifetimeA <= 0x0B && 0 <= info[i].lifetimeB && info[i].lifetimeB <= 0x0B)) {
218 return false;
219 }
220 }
221
222 return true;
223}
224
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800225template <typename T>
226bool verifyEnum(T value) {
Steven Morelandc90461c2018-05-01 16:54:09 -0700227 for (auto it : hidl_enum_range<T>()) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800228 if (it == value) {
229 return true;
230 }
231 }
232
233 return false;
234}
235
236bool verifyHealthInfo(const HealthInfo& health_info) {
Hridya Valsaraju075c1822018-04-03 11:19:08 -0700237 if (!verifyStorageInfo(health_info.storageInfos)) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800238 return false;
239 }
240
241 using V1_0::BatteryStatus;
242 using V1_0::BatteryHealth;
243
Robin Leeac5a0d32019-10-09 15:48:17 +0200244 if (!((health_info.legacy.batteryCurrent != INT32_MIN) &&
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800245 (0 <= health_info.legacy.batteryLevel && health_info.legacy.batteryLevel <= 100) &&
246 verifyEnum<BatteryHealth>(health_info.legacy.batteryHealth) &&
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800247 verifyEnum<BatteryStatus>(health_info.legacy.batteryStatus))) {
248 return false;
249 }
250
Robin Leeac5a0d32019-10-09 15:48:17 +0200251 if (health_info.legacy.batteryPresent) {
252 // If a battery is present, the battery status must be known.
253 if (!((health_info.legacy.batteryChargeCounter > 0) &&
254 (health_info.legacy.batteryStatus != BatteryStatus::UNKNOWN))) {
255 return false;
256 }
257 }
258
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800259 return true;
260}
261
262/*
Yifan Hong26c12002018-10-02 14:52:02 -0700263 * Tests the values returned by getChargeCounter() from interface IHealth.
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800264 */
nelsonli4da3ca52019-12-10 17:17:09 +0800265TEST_P(HealthHidlTest, getChargeCounter) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800266 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700267 EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
268 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
269 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700270}
271
272/*
273 * Tests the values returned by getCurrentNow() from interface IHealth.
274 */
nelsonli4da3ca52019-12-10 17:17:09 +0800275TEST_P(HealthHidlTest, getCurrentNow) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800276 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700277 EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) {
278 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
279 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700280}
281
282/*
283 * Tests the values returned by getCurrentAverage() from interface IHealth.
284 */
nelsonli4da3ca52019-12-10 17:17:09 +0800285TEST_P(HealthHidlTest, getCurrentAverage) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800286 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700287 EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
288 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
289 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700290}
291
292/*
293 * Tests the values returned by getCapacity() from interface IHealth.
294 */
nelsonli4da3ca52019-12-10 17:17:09 +0800295TEST_P(HealthHidlTest, getCapacity) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800296 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700297 EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
298 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
299 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700300}
301
302/*
303 * Tests the values returned by getEnergyCounter() from interface IHealth.
304 */
nelsonli4da3ca52019-12-10 17:17:09 +0800305TEST_P(HealthHidlTest, getEnergyCounter) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800306 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700307 EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
308 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
309 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700310}
311
312/*
313 * Tests the values returned by getChargeStatus() from interface IHealth.
314 */
nelsonli4da3ca52019-12-10 17:17:09 +0800315TEST_P(HealthHidlTest, getChargeStatus) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800316 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700317 EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
318 EXPECT_VALID_OR_UNSUPPORTED_PROP(
319 result, toString(value),
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800320 value != BatteryStatus::UNKNOWN && verifyEnum<BatteryStatus>(value));
Yifan Hong69c22542017-10-03 17:40:24 -0700321 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700322}
323
324/*
325 * Tests the values returned by getStorageInfo() from interface IHealth.
326 */
nelsonli4da3ca52019-12-10 17:17:09 +0800327TEST_P(HealthHidlTest, getStorageInfo) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800328 SKIP_IF_SKIPPED();
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800329 EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800330 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800331 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700332}
333
334/*
335 * Tests the values returned by getDiskStats() from interface IHealth.
336 */
nelsonli4da3ca52019-12-10 17:17:09 +0800337TEST_P(HealthHidlTest, getDiskStats) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800338 SKIP_IF_SKIPPED();
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800339 EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
Hridya Valsaraju075c1822018-04-03 11:19:08 -0700340 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), true);
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800341 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700342}
343
344/*
345 * Tests the values returned by getHealthInfo() from interface IHealth.
346 */
nelsonli4da3ca52019-12-10 17:17:09 +0800347TEST_P(HealthHidlTest, getHealthInfo) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800348 SKIP_IF_SKIPPED();
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800349 EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
350 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
351 }));
Yifan Hong69c22542017-10-03 17:40:24 -0700352}
353
nelsonli4da3ca52019-12-10 17:17:09 +0800354INSTANTIATE_TEST_SUITE_P(
355 PerInstance, HealthHidlTest,
356 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
357 android::hardware::PrintInstanceNameToString);
Yifan Hong69c22542017-10-03 17:40:24 -0700358} // namespace V2_0
359} // namespace health
360} // namespace hardware
361} // namespace android
362
363int main(int argc, char** argv) {
Yifan Hong69c22542017-10-03 17:40:24 -0700364 ::testing::InitGoogleTest(&argc, argv);
Yifan Honge6807dd2019-03-07 13:04:33 -0800365 gflags::ParseCommandLineFlags(&argc, &argv, true /* remove flags */);
nelsonli4da3ca52019-12-10 17:17:09 +0800366 return RUN_ALL_TESTS();
Yifan Hong69c22542017-10-03 17:40:24 -0700367}