Home | History | Annotate | Download | only in functional
      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 
     21 #include <VtsHalHidlTargetTestBase.h>
     22 #include <android-base/logging.h>
     23 #include <android/hardware/health/2.0/IHealth.h>
     24 #include <android/hardware/health/2.0/types.h>
     25 
     26 using ::testing::AssertionFailure;
     27 using ::testing::AssertionResult;
     28 using ::testing::AssertionSuccess;
     29 using ::testing::VtsHalHidlTargetTestBase;
     30 using ::testing::VtsHalHidlTargetTestEnvBase;
     31 
     32 namespace android {
     33 namespace hardware {
     34 namespace health {
     35 namespace V2_0 {
     36 
     37 using V1_0::BatteryStatus;
     38 
     39 // Test environment for graphics.composer
     40 class HealthHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
     41    public:
     42     // get the test environment singleton
     43     static HealthHidlEnvironment* Instance() {
     44         static HealthHidlEnvironment* instance = new HealthHidlEnvironment;
     45         return instance;
     46     }
     47 
     48     virtual void registerTestServices() override { registerTestService<IHealth>(); }
     49 
     50    private:
     51     HealthHidlEnvironment() {}
     52 
     53     GTEST_DISALLOW_COPY_AND_ASSIGN_(HealthHidlEnvironment);
     54 };
     55 
     56 class HealthHidlTest : public ::testing::VtsHalHidlTargetTestBase {
     57    public:
     58     virtual void SetUp() override {
     59         std::string serviceName = HealthHidlEnvironment::Instance()->getServiceName<IHealth>();
     60         LOG(INFO) << "get service with name:" << serviceName;
     61         ASSERT_FALSE(serviceName.empty());
     62         mHealth = ::testing::VtsHalHidlTargetTestBase::getService<IHealth>(serviceName);
     63         ASSERT_NE(mHealth, nullptr);
     64     }
     65 
     66     sp<IHealth> mHealth;
     67 };
     68 
     69 class Callback : public IHealthInfoCallback {
     70    public:
     71     Return<void> healthInfoChanged(const HealthInfo&) override {
     72         std::lock_guard<std::mutex> lock(mMutex);
     73         mInvoked = true;
     74         mInvokedNotify.notify_all();
     75         return Void();
     76     }
     77     template <typename R, typename P>
     78     bool waitInvoke(std::chrono::duration<R, P> duration) {
     79         std::unique_lock<std::mutex> lock(mMutex);
     80         bool r = mInvokedNotify.wait_for(lock, duration, [this] { return this->mInvoked; });
     81         mInvoked = false;
     82         return r;
     83     }
     84    private:
     85     std::mutex mMutex;
     86     std::condition_variable mInvokedNotify;
     87     bool mInvoked = false;
     88 };
     89 
     90 #define ASSERT_OK(r) ASSERT_TRUE(isOk(r))
     91 #define EXPECT_OK(r) EXPECT_TRUE(isOk(r))
     92 template <typename T>
     93 AssertionResult isOk(const Return<T>& r) {
     94     return r.isOk() ? AssertionSuccess() : (AssertionFailure() << r.description());
     95 }
     96 
     97 #define ASSERT_ALL_OK(r) ASSERT_TRUE(isAllOk(r))
     98 // Both isOk() and Result::SUCCESS
     99 AssertionResult isAllOk(const Return<Result>& r) {
    100     if (!r.isOk()) {
    101         return AssertionFailure() << r.description();
    102     }
    103     if (static_cast<Result>(r) != Result::SUCCESS) {
    104         return AssertionFailure() << toString(static_cast<Result>(r));
    105     }
    106     return AssertionSuccess();
    107 }
    108 
    109 /**
    110  * Test whether callbacks work. Tested functions are IHealth::registerCallback,
    111  * unregisterCallback, and update.
    112  */
    113 TEST_F(HealthHidlTest, Callbacks) {
    114     using namespace std::chrono_literals;
    115     sp<Callback> firstCallback = new Callback();
    116     sp<Callback> secondCallback = new Callback();
    117 
    118     ASSERT_ALL_OK(mHealth->registerCallback(firstCallback));
    119     ASSERT_ALL_OK(mHealth->registerCallback(secondCallback));
    120 
    121     // registerCallback may or may not invoke the callback immediately, so the test needs
    122     // to wait for the invocation. If the implementation chooses not to invoke the callback
    123     // immediately, just wait for some time.
    124     firstCallback->waitInvoke(200ms);
    125     secondCallback->waitInvoke(200ms);
    126 
    127     // assert that the first callback is invoked when update is called.
    128     ASSERT_ALL_OK(mHealth->update());
    129 
    130     ASSERT_TRUE(firstCallback->waitInvoke(1s));
    131     ASSERT_TRUE(secondCallback->waitInvoke(1s));
    132 
    133     ASSERT_ALL_OK(mHealth->unregisterCallback(firstCallback));
    134 
    135     // clear any potentially pending callbacks result from wakealarm / kernel events
    136     // If there is none, just wait for some time.
    137     firstCallback->waitInvoke(200ms);
    138     secondCallback->waitInvoke(200ms);
    139 
    140     // assert that the second callback is still invoked even though the first is unregistered.
    141     ASSERT_ALL_OK(mHealth->update());
    142 
    143     ASSERT_FALSE(firstCallback->waitInvoke(200ms));
    144     ASSERT_TRUE(secondCallback->waitInvoke(1s));
    145 
    146     ASSERT_ALL_OK(mHealth->unregisterCallback(secondCallback));
    147 }
    148 
    149 TEST_F(HealthHidlTest, UnregisterNonExistentCallback) {
    150     sp<Callback> callback = new Callback();
    151     auto ret = mHealth->unregisterCallback(callback);
    152     ASSERT_OK(ret);
    153     ASSERT_EQ(Result::NOT_FOUND, static_cast<Result>(ret)) << "Actual: " << toString(ret);
    154 }
    155 
    156 /**
    157  * Pass the test if:
    158  *  - Property is not supported (res == NOT_SUPPORTED)
    159  *  - Result is success, and predicate is true
    160  * @param res the Result value.
    161  * @param valueStr the string representation for actual value (for error message)
    162  * @param pred a predicate that test whether the value is valid
    163  */
    164 #define EXPECT_VALID_OR_UNSUPPORTED_PROP(res, valueStr, pred) \
    165     EXPECT_TRUE(isPropertyOk(res, valueStr, pred, #pred))
    166 
    167 AssertionResult isPropertyOk(Result res, const std::string& valueStr, bool pred,
    168                              const std::string& predStr) {
    169     if (res == Result::SUCCESS) {
    170         if (pred) {
    171             return AssertionSuccess();
    172         }
    173         return AssertionFailure() << "value doesn't match.\nActual: " << valueStr
    174                                   << "\nExpected: " << predStr;
    175     }
    176     if (res == Result::NOT_SUPPORTED) {
    177         return AssertionSuccess();
    178     }
    179     return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res);
    180 }
    181 
    182 bool verifyStorageInfo(const hidl_vec<struct StorageInfo>& info) {
    183     for (size_t i = 0; i < info.size(); i++) {
    184         if (!(0 <= info[i].eol && info[i].eol <= 3 && 0 <= info[i].lifetimeA &&
    185               info[i].lifetimeA <= 0x0B && 0 <= info[i].lifetimeB && info[i].lifetimeB <= 0x0B)) {
    186             return false;
    187         }
    188     }
    189 
    190     return true;
    191 }
    192 
    193 template <typename T>
    194 bool verifyEnum(T value) {
    195     for (auto it : hidl_enum_iterator<T>()) {
    196         if (it == value) {
    197             return true;
    198         }
    199     }
    200 
    201     return false;
    202 }
    203 
    204 bool verifyHealthInfo(const HealthInfo& health_info) {
    205     if (!verifyStorageInfo(health_info.storageInfos)) {
    206         return false;
    207     }
    208 
    209     using V1_0::BatteryStatus;
    210     using V1_0::BatteryHealth;
    211 
    212     if (!((health_info.legacy.batteryChargeCounter > 0) &&
    213           (health_info.legacy.batteryCurrent != INT32_MIN) &&
    214           (0 <= health_info.legacy.batteryLevel && health_info.legacy.batteryLevel <= 100) &&
    215           verifyEnum<BatteryHealth>(health_info.legacy.batteryHealth) &&
    216           (health_info.legacy.batteryStatus != BatteryStatus::UNKNOWN) &&
    217           verifyEnum<BatteryStatus>(health_info.legacy.batteryStatus))) {
    218         return false;
    219     }
    220 
    221     return true;
    222 }
    223 
    224 /*
    225  * Tests the values returned by getChargeCounter(),
    226  * getCurrentNow(), getCurrentAverage(), getCapacity(), getEnergyCounter(),
    227  * getChargeStatus(), getStorageInfo(), getDiskStats() and getHealthInfo() from
    228  * interface IHealth.
    229  */
    230 TEST_F(HealthHidlTest, Properties) {
    231     EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
    232         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
    233     }));
    234     EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) {
    235         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
    236     }));
    237     EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
    238         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
    239     }));
    240     EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
    241         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
    242     }));
    243     EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
    244         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
    245     }));
    246     EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
    247         EXPECT_VALID_OR_UNSUPPORTED_PROP(
    248             result, toString(value),
    249             value != BatteryStatus::UNKNOWN && verifyEnum<BatteryStatus>(value));
    250     }));
    251     EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
    252         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
    253     }));
    254     EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
    255         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), true);
    256     }));
    257     EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
    258         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
    259     }));
    260 }
    261 
    262 }  // namespace V2_0
    263 }  // namespace health
    264 }  // namespace hardware
    265 }  // namespace android
    266 
    267 int main(int argc, char** argv) {
    268     using ::android::hardware::health::V2_0::HealthHidlEnvironment;
    269     ::testing::AddGlobalTestEnvironment(HealthHidlEnvironment::Instance());
    270     ::testing::InitGoogleTest(&argc, argv);
    271     HealthHidlEnvironment::Instance()->init(&argc, argv);
    272     int status = RUN_ALL_TESTS();
    273     LOG(INFO) << "Test result = " << status;
    274     return status;
    275 }
    276