blob: 74fe4fbd83012ad9206453298b2d17dd9bb32160 [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
23#include <VtsHalHidlTargetTestBase.h>
24#include <android-base/logging.h>
25#include <android/hardware/health/2.0/IHealth.h>
26#include <android/hardware/health/2.0/types.h>
Yifan Honge6807dd2019-03-07 13:04:33 -080027#include <gflags/gflags.h>
Yifan Hong69c22542017-10-03 17:40:24 -070028
29using ::testing::AssertionFailure;
30using ::testing::AssertionResult;
31using ::testing::AssertionSuccess;
32using ::testing::VtsHalHidlTargetTestBase;
33using ::testing::VtsHalHidlTargetTestEnvBase;
34
Yifan Honge6807dd2019-03-07 13:04:33 -080035DEFINE_bool(force, false, "Force test healthd even when the default instance is present.");
36
Yifan Hong03b2a342019-03-08 11:37:33 -080037// If GTEST_SKIP is not implemented, use our own skipping mechanism
38#ifndef GTEST_SKIP
39static std::mutex gSkippedTestsMutex;
40static std::set<std::string> gSkippedTests;
41static std::string GetCurrentTestName() {
42 const auto& info = ::testing::UnitTest::GetInstance()->current_test_info();
43#ifdef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
44 std::string test_suite = info->test_suite_name();
45#else
46 std::string test_suite = info->test_case_name();
47#endif
48 return test_suite + "." + info->name();
49}
50
51#define GTEST_SKIP() \
52 do { \
53 std::unique_lock<std::mutex> lock(gSkippedTestsMutex); \
54 gSkippedTests.insert(GetCurrentTestName()); \
55 return; \
56 } while (0)
57
58#define SKIP_IF_SKIPPED() \
59 do { \
60 std::unique_lock<std::mutex> lock(gSkippedTestsMutex); \
61 if (gSkippedTests.find(GetCurrentTestName()) != gSkippedTests.end()) { \
62 std::cerr << "[ SKIPPED ] " << GetCurrentTestName() << std::endl; \
63 return; \
64 } \
65 } while (0)
66#else
67#define SKIP_IF_SKIPPED()
68#endif
69
Yifan Hong69c22542017-10-03 17:40:24 -070070namespace android {
71namespace hardware {
72namespace health {
73namespace V2_0 {
74
75using V1_0::BatteryStatus;
Yifan Hong69c22542017-10-03 17:40:24 -070076
77// Test environment for graphics.composer
78class HealthHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
79 public:
80 // get the test environment singleton
81 static HealthHidlEnvironment* Instance() {
82 static HealthHidlEnvironment* instance = new HealthHidlEnvironment;
83 return instance;
84 }
85
86 virtual void registerTestServices() override { registerTestService<IHealth>(); }
87
88 private:
89 HealthHidlEnvironment() {}
90
91 GTEST_DISALLOW_COPY_AND_ASSIGN_(HealthHidlEnvironment);
92};
93
94class HealthHidlTest : public ::testing::VtsHalHidlTargetTestBase {
95 public:
96 virtual void SetUp() override {
97 std::string serviceName = HealthHidlEnvironment::Instance()->getServiceName<IHealth>();
Yifan Honge6807dd2019-03-07 13:04:33 -080098
99 if (serviceName == "backup" && !FLAGS_force &&
100 ::testing::VtsHalHidlTargetTestBase::getService<IHealth>() != nullptr) {
101 LOG(INFO) << "Skipping tests on healthd because the default instance is present. "
102 << "Use --force if you really want to test healthd.";
103 GTEST_SKIP();
104 }
105
Yifan Hong69c22542017-10-03 17:40:24 -0700106 LOG(INFO) << "get service with name:" << serviceName;
107 ASSERT_FALSE(serviceName.empty());
108 mHealth = ::testing::VtsHalHidlTargetTestBase::getService<IHealth>(serviceName);
109 ASSERT_NE(mHealth, nullptr);
110 }
111
112 sp<IHealth> mHealth;
113};
114
115class Callback : public IHealthInfoCallback {
Yifan Hong69c22542017-10-03 17:40:24 -0700116 public:
Hridya Valsarajud31932a2018-01-17 23:09:24 -0800117 Return<void> healthInfoChanged(const HealthInfo&) override {
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800118 std::lock_guard<std::mutex> lock(mMutex);
119 mInvoked = true;
120 mInvokedNotify.notify_all();
Yifan Hong69c22542017-10-03 17:40:24 -0700121 return Void();
122 }
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800123 template <typename R, typename P>
124 bool waitInvoke(std::chrono::duration<R, P> duration) {
Yifan Hong69c22542017-10-03 17:40:24 -0700125 std::unique_lock<std::mutex> lock(mMutex);
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800126 bool r = mInvokedNotify.wait_for(lock, duration, [this] { return this->mInvoked; });
127 mInvoked = false;
128 return r;
Yifan Hong69c22542017-10-03 17:40:24 -0700129 }
Yifan Hong69c22542017-10-03 17:40:24 -0700130 private:
131 std::mutex mMutex;
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800132 std::condition_variable mInvokedNotify;
133 bool mInvoked = false;
Yifan Hong69c22542017-10-03 17:40:24 -0700134};
135
136#define ASSERT_OK(r) ASSERT_TRUE(isOk(r))
137#define EXPECT_OK(r) EXPECT_TRUE(isOk(r))
138template <typename T>
139AssertionResult isOk(const Return<T>& r) {
140 return r.isOk() ? AssertionSuccess() : (AssertionFailure() << r.description());
141}
142
143#define ASSERT_ALL_OK(r) ASSERT_TRUE(isAllOk(r))
144// Both isOk() and Result::SUCCESS
145AssertionResult isAllOk(const Return<Result>& r) {
146 if (!r.isOk()) {
147 return AssertionFailure() << r.description();
148 }
149 if (static_cast<Result>(r) != Result::SUCCESS) {
150 return AssertionFailure() << toString(static_cast<Result>(r));
151 }
152 return AssertionSuccess();
153}
154
155/**
156 * Test whether callbacks work. Tested functions are IHealth::registerCallback,
157 * unregisterCallback, and update.
158 */
159TEST_F(HealthHidlTest, Callbacks) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800160 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700161 using namespace std::chrono_literals;
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800162 sp<Callback> firstCallback = new Callback();
163 sp<Callback> secondCallback = new Callback();
Yifan Hong69c22542017-10-03 17:40:24 -0700164
165 ASSERT_ALL_OK(mHealth->registerCallback(firstCallback));
166 ASSERT_ALL_OK(mHealth->registerCallback(secondCallback));
167
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800168 // registerCallback may or may not invoke the callback immediately, so the test needs
169 // to wait for the invocation. If the implementation chooses not to invoke the callback
170 // immediately, just wait for some time.
171 firstCallback->waitInvoke(200ms);
172 secondCallback->waitInvoke(200ms);
Yifan Hong69c22542017-10-03 17:40:24 -0700173
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800174 // assert that the first callback is invoked when update is called.
Yifan Hong69c22542017-10-03 17:40:24 -0700175 ASSERT_ALL_OK(mHealth->update());
176
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800177 ASSERT_TRUE(firstCallback->waitInvoke(1s));
178 ASSERT_TRUE(secondCallback->waitInvoke(1s));
Yifan Hong69c22542017-10-03 17:40:24 -0700179
180 ASSERT_ALL_OK(mHealth->unregisterCallback(firstCallback));
181
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800182 // clear any potentially pending callbacks result from wakealarm / kernel events
183 // If there is none, just wait for some time.
184 firstCallback->waitInvoke(200ms);
185 secondCallback->waitInvoke(200ms);
Yifan Hong69c22542017-10-03 17:40:24 -0700186
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800187 // assert that the second callback is still invoked even though the first is unregistered.
Yifan Hong69c22542017-10-03 17:40:24 -0700188 ASSERT_ALL_OK(mHealth->update());
189
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800190 ASSERT_FALSE(firstCallback->waitInvoke(200ms));
191 ASSERT_TRUE(secondCallback->waitInvoke(1s));
Yifan Hong69c22542017-10-03 17:40:24 -0700192
193 ASSERT_ALL_OK(mHealth->unregisterCallback(secondCallback));
Yifan Hong69c22542017-10-03 17:40:24 -0700194}
195
196TEST_F(HealthHidlTest, UnregisterNonExistentCallback) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800197 SKIP_IF_SKIPPED();
Yifan Hongd6ea57e2017-11-20 14:41:09 -0800198 sp<Callback> callback = new Callback();
Yifan Hong69c22542017-10-03 17:40:24 -0700199 auto ret = mHealth->unregisterCallback(callback);
200 ASSERT_OK(ret);
201 ASSERT_EQ(Result::NOT_FOUND, static_cast<Result>(ret)) << "Actual: " << toString(ret);
202}
203
204/**
205 * Pass the test if:
206 * - Property is not supported (res == NOT_SUPPORTED)
207 * - Result is success, and predicate is true
208 * @param res the Result value.
209 * @param valueStr the string representation for actual value (for error message)
210 * @param pred a predicate that test whether the value is valid
211 */
212#define EXPECT_VALID_OR_UNSUPPORTED_PROP(res, valueStr, pred) \
213 EXPECT_TRUE(isPropertyOk(res, valueStr, pred, #pred))
214
215AssertionResult isPropertyOk(Result res, const std::string& valueStr, bool pred,
216 const std::string& predStr) {
217 if (res == Result::SUCCESS) {
218 if (pred) {
219 return AssertionSuccess();
220 }
221 return AssertionFailure() << "value doesn't match.\nActual: " << valueStr
222 << "\nExpected: " << predStr;
223 }
224 if (res == Result::NOT_SUPPORTED) {
225 return AssertionSuccess();
226 }
227 return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res);
228}
229
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800230bool verifyStorageInfo(const hidl_vec<struct StorageInfo>& info) {
231 for (size_t i = 0; i < info.size(); i++) {
232 if (!(0 <= info[i].eol && info[i].eol <= 3 && 0 <= info[i].lifetimeA &&
233 info[i].lifetimeA <= 0x0B && 0 <= info[i].lifetimeB && info[i].lifetimeB <= 0x0B)) {
234 return false;
235 }
236 }
237
238 return true;
239}
240
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800241template <typename T>
242bool verifyEnum(T value) {
Steven Morelandc90461c2018-05-01 16:54:09 -0700243 for (auto it : hidl_enum_range<T>()) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800244 if (it == value) {
245 return true;
246 }
247 }
248
249 return false;
250}
251
252bool verifyHealthInfo(const HealthInfo& health_info) {
Hridya Valsaraju075c1822018-04-03 11:19:08 -0700253 if (!verifyStorageInfo(health_info.storageInfos)) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800254 return false;
255 }
256
257 using V1_0::BatteryStatus;
258 using V1_0::BatteryHealth;
259
260 if (!((health_info.legacy.batteryChargeCounter > 0) &&
261 (health_info.legacy.batteryCurrent != INT32_MIN) &&
262 (0 <= health_info.legacy.batteryLevel && health_info.legacy.batteryLevel <= 100) &&
263 verifyEnum<BatteryHealth>(health_info.legacy.batteryHealth) &&
264 (health_info.legacy.batteryStatus != BatteryStatus::UNKNOWN) &&
265 verifyEnum<BatteryStatus>(health_info.legacy.batteryStatus))) {
266 return false;
267 }
268
269 return true;
270}
271
272/*
Yifan Hong26c12002018-10-02 14:52:02 -0700273 * Tests the values returned by getChargeCounter() from interface IHealth.
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800274 */
Yifan Hong26c12002018-10-02 14:52:02 -0700275TEST_F(HealthHidlTest, getChargeCounter) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800276 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700277 EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
278 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
279 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700280}
281
282/*
283 * Tests the values returned by getCurrentNow() from interface IHealth.
284 */
285TEST_F(HealthHidlTest, getCurrentNow) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800286 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700287 EXPECT_OK(mHealth->getCurrentNow([](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 getCurrentAverage() from interface IHealth.
294 */
295TEST_F(HealthHidlTest, getCurrentAverage) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800296 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700297 EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
298 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
299 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700300}
301
302/*
303 * Tests the values returned by getCapacity() from interface IHealth.
304 */
305TEST_F(HealthHidlTest, getCapacity) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800306 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700307 EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
308 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
309 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700310}
311
312/*
313 * Tests the values returned by getEnergyCounter() from interface IHealth.
314 */
315TEST_F(HealthHidlTest, getEnergyCounter) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800316 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700317 EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
318 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
319 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700320}
321
322/*
323 * Tests the values returned by getChargeStatus() from interface IHealth.
324 */
325TEST_F(HealthHidlTest, getChargeStatus) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800326 SKIP_IF_SKIPPED();
Yifan Hong69c22542017-10-03 17:40:24 -0700327 EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
328 EXPECT_VALID_OR_UNSUPPORTED_PROP(
329 result, toString(value),
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800330 value != BatteryStatus::UNKNOWN && verifyEnum<BatteryStatus>(value));
Yifan Hong69c22542017-10-03 17:40:24 -0700331 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700332}
333
334/*
335 * Tests the values returned by getStorageInfo() from interface IHealth.
336 */
337TEST_F(HealthHidlTest, getStorageInfo) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800338 SKIP_IF_SKIPPED();
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800339 EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800340 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800341 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700342}
343
344/*
345 * Tests the values returned by getDiskStats() from interface IHealth.
346 */
347TEST_F(HealthHidlTest, getDiskStats) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800348 SKIP_IF_SKIPPED();
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800349 EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
Hridya Valsaraju075c1822018-04-03 11:19:08 -0700350 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), true);
Hridya Valsaraju2120ecc2017-12-20 13:27:52 -0800351 }));
Yifan Hong26c12002018-10-02 14:52:02 -0700352}
353
354/*
355 * Tests the values returned by getHealthInfo() from interface IHealth.
356 */
357TEST_F(HealthHidlTest, getHealthInfo) {
Yifan Hong03b2a342019-03-08 11:37:33 -0800358 SKIP_IF_SKIPPED();
Hridya Valsaraju87e29602018-01-12 17:46:22 -0800359 EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
360 EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
361 }));
Yifan Hong69c22542017-10-03 17:40:24 -0700362}
363
364} // namespace V2_0
365} // namespace health
366} // namespace hardware
367} // namespace android
368
369int main(int argc, char** argv) {
370 using ::android::hardware::health::V2_0::HealthHidlEnvironment;
371 ::testing::AddGlobalTestEnvironment(HealthHidlEnvironment::Instance());
372 ::testing::InitGoogleTest(&argc, argv);
373 HealthHidlEnvironment::Instance()->init(&argc, argv);
Yifan Honge6807dd2019-03-07 13:04:33 -0800374 gflags::ParseCommandLineFlags(&argc, &argv, true /* remove flags */);
Yifan Hong69c22542017-10-03 17:40:24 -0700375 int status = RUN_ALL_TESTS();
376 LOG(INFO) << "Test result = " << status;
377 return status;
378}