• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #define LOG_TAG "health_hidl_hal_test"
18 
19 #include <mutex>
20 #include <set>
21 #include <string>
22 
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>
27 #include <gflags/gflags.h>
28 
29 using ::testing::AssertionFailure;
30 using ::testing::AssertionResult;
31 using ::testing::AssertionSuccess;
32 using ::testing::VtsHalHidlTargetTestBase;
33 using ::testing::VtsHalHidlTargetTestEnvBase;
34 
35 DEFINE_bool(force, false, "Force test healthd even when the default instance is present.");
36 
37 // If GTEST_SKIP is not implemented, use our own skipping mechanism
38 #ifndef GTEST_SKIP
39 static std::mutex gSkippedTestsMutex;
40 static std::set<std::string> gSkippedTests;
GetCurrentTestName()41 static 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 
70 namespace android {
71 namespace hardware {
72 namespace health {
73 namespace V2_0 {
74 
75 using V1_0::BatteryStatus;
76 
77 // Test environment for graphics.composer
78 class HealthHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
79    public:
80     // get the test environment singleton
Instance()81     static HealthHidlEnvironment* Instance() {
82         static HealthHidlEnvironment* instance = new HealthHidlEnvironment;
83         return instance;
84     }
85 
registerTestServices()86     virtual void registerTestServices() override { registerTestService<IHealth>(); }
87 
88    private:
HealthHidlEnvironment()89     HealthHidlEnvironment() {}
90 
91     GTEST_DISALLOW_COPY_AND_ASSIGN_(HealthHidlEnvironment);
92 };
93 
94 class HealthHidlTest : public ::testing::VtsHalHidlTargetTestBase {
95    public:
SetUp()96     virtual void SetUp() override {
97         std::string serviceName = HealthHidlEnvironment::Instance()->getServiceName<IHealth>();
98 
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 
106         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 
115 class Callback : public IHealthInfoCallback {
116    public:
healthInfoChanged(const HealthInfo &)117     Return<void> healthInfoChanged(const HealthInfo&) override {
118         std::lock_guard<std::mutex> lock(mMutex);
119         mInvoked = true;
120         mInvokedNotify.notify_all();
121         return Void();
122     }
123     template <typename R, typename P>
waitInvoke(std::chrono::duration<R,P> duration)124     bool waitInvoke(std::chrono::duration<R, P> duration) {
125         std::unique_lock<std::mutex> lock(mMutex);
126         bool r = mInvokedNotify.wait_for(lock, duration, [this] { return this->mInvoked; });
127         mInvoked = false;
128         return r;
129     }
130    private:
131     std::mutex mMutex;
132     std::condition_variable mInvokedNotify;
133     bool mInvoked = false;
134 };
135 
136 #define ASSERT_OK(r) ASSERT_TRUE(isOk(r))
137 #define EXPECT_OK(r) EXPECT_TRUE(isOk(r))
138 template <typename T>
isOk(const Return<T> & r)139 AssertionResult 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
isAllOk(const Return<Result> & r)145 AssertionResult 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  */
TEST_F(HealthHidlTest,Callbacks)159 TEST_F(HealthHidlTest, Callbacks) {
160     SKIP_IF_SKIPPED();
161     using namespace std::chrono_literals;
162     sp<Callback> firstCallback = new Callback();
163     sp<Callback> secondCallback = new Callback();
164 
165     ASSERT_ALL_OK(mHealth->registerCallback(firstCallback));
166     ASSERT_ALL_OK(mHealth->registerCallback(secondCallback));
167 
168     // 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);
173 
174     // assert that the first callback is invoked when update is called.
175     ASSERT_ALL_OK(mHealth->update());
176 
177     ASSERT_TRUE(firstCallback->waitInvoke(1s));
178     ASSERT_TRUE(secondCallback->waitInvoke(1s));
179 
180     ASSERT_ALL_OK(mHealth->unregisterCallback(firstCallback));
181 
182     // 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);
186 
187     // assert that the second callback is still invoked even though the first is unregistered.
188     ASSERT_ALL_OK(mHealth->update());
189 
190     ASSERT_FALSE(firstCallback->waitInvoke(200ms));
191     ASSERT_TRUE(secondCallback->waitInvoke(1s));
192 
193     ASSERT_ALL_OK(mHealth->unregisterCallback(secondCallback));
194 }
195 
TEST_F(HealthHidlTest,UnregisterNonExistentCallback)196 TEST_F(HealthHidlTest, UnregisterNonExistentCallback) {
197     SKIP_IF_SKIPPED();
198     sp<Callback> callback = new Callback();
199     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 
isPropertyOk(Result res,const std::string & valueStr,bool pred,const std::string & predStr)215 AssertionResult 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 
verifyStorageInfo(const hidl_vec<struct StorageInfo> & info)230 bool 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 
241 template <typename T>
verifyEnum(T value)242 bool verifyEnum(T value) {
243     for (auto it : hidl_enum_range<T>()) {
244         if (it == value) {
245             return true;
246         }
247     }
248 
249     return false;
250 }
251 
verifyHealthInfo(const HealthInfo & health_info)252 bool verifyHealthInfo(const HealthInfo& health_info) {
253     if (!verifyStorageInfo(health_info.storageInfos)) {
254         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 /*
273  * Tests the values returned by getChargeCounter() from interface IHealth.
274  */
TEST_F(HealthHidlTest,getChargeCounter)275 TEST_F(HealthHidlTest, getChargeCounter) {
276     SKIP_IF_SKIPPED();
277     EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
278         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
279     }));
280 }
281 
282 /*
283  * Tests the values returned by getCurrentNow() from interface IHealth.
284  */
TEST_F(HealthHidlTest,getCurrentNow)285 TEST_F(HealthHidlTest, getCurrentNow) {
286     SKIP_IF_SKIPPED();
287     EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) {
288         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
289     }));
290 }
291 
292 /*
293  * Tests the values returned by getCurrentAverage() from interface IHealth.
294  */
TEST_F(HealthHidlTest,getCurrentAverage)295 TEST_F(HealthHidlTest, getCurrentAverage) {
296     SKIP_IF_SKIPPED();
297     EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
298         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
299     }));
300 }
301 
302 /*
303  * Tests the values returned by getCapacity() from interface IHealth.
304  */
TEST_F(HealthHidlTest,getCapacity)305 TEST_F(HealthHidlTest, getCapacity) {
306     SKIP_IF_SKIPPED();
307     EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
308         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
309     }));
310 }
311 
312 /*
313  * Tests the values returned by getEnergyCounter() from interface IHealth.
314  */
TEST_F(HealthHidlTest,getEnergyCounter)315 TEST_F(HealthHidlTest, getEnergyCounter) {
316     SKIP_IF_SKIPPED();
317     EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
318         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
319     }));
320 }
321 
322 /*
323  * Tests the values returned by getChargeStatus() from interface IHealth.
324  */
TEST_F(HealthHidlTest,getChargeStatus)325 TEST_F(HealthHidlTest, getChargeStatus) {
326     SKIP_IF_SKIPPED();
327     EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
328         EXPECT_VALID_OR_UNSUPPORTED_PROP(
329             result, toString(value),
330             value != BatteryStatus::UNKNOWN && verifyEnum<BatteryStatus>(value));
331     }));
332 }
333 
334 /*
335  * Tests the values returned by getStorageInfo() from interface IHealth.
336  */
TEST_F(HealthHidlTest,getStorageInfo)337 TEST_F(HealthHidlTest, getStorageInfo) {
338     SKIP_IF_SKIPPED();
339     EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
340         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
341     }));
342 }
343 
344 /*
345  * Tests the values returned by getDiskStats() from interface IHealth.
346  */
TEST_F(HealthHidlTest,getDiskStats)347 TEST_F(HealthHidlTest, getDiskStats) {
348     SKIP_IF_SKIPPED();
349     EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
350         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), true);
351     }));
352 }
353 
354 /*
355  * Tests the values returned by getHealthInfo() from interface IHealth.
356  */
TEST_F(HealthHidlTest,getHealthInfo)357 TEST_F(HealthHidlTest, getHealthInfo) {
358     SKIP_IF_SKIPPED();
359     EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
360         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
361     }));
362 }
363 
364 }  // namespace V2_0
365 }  // namespace health
366 }  // namespace hardware
367 }  // namespace android
368 
main(int argc,char ** argv)369 int 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);
374     gflags::ParseCommandLineFlags(&argc, &argv, true /* remove flags */);
375     int status = RUN_ALL_TESTS();
376     LOG(INFO) << "Test result = " << status;
377     return status;
378 }
379