Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2200cffd authored by Yifan Hong's avatar Yifan Hong
Browse files

health AIDL: add vts tests

This is a direct translation of the health 2.0
and 2.1 VTS tests.

Some slight modifications are made (e.g. use googlemock
matchers) to make the test code more readable.

Test: run on Pixel
Bug: 203245778

Change-Id: Ifc3799a04a6a09d0d53f400b60d19fbfe004a3e3
parent 236fa890
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -32,5 +32,11 @@ cc_test {
        "android.hardware.health@1.0",
        "android.hardware.health@2.0",
    ],
    test_suites: ["general-tests", "vts"],
    header_libs: [
        "libhealthtest_headers",
    ],
    test_suites: [
        "general-tests",
        "vts",
    ],
}
+9 −117
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <android/hardware/health/2.0/types.h>
#include <gflags/gflags.h>
#include <gtest/gtest.h>
#include <health-test/TestUtils.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include <log/log.h>
@@ -51,6 +52,7 @@ namespace android {
namespace hardware {
namespace health {

using test_utils::SucceedOnce;
using V1_0::BatteryStatus;
using V1_0::toString;

@@ -356,64 +358,9 @@ static AssertionResult IsBatteryCurrentSignCorrect(HalResult<BatteryStatus> stat
                                  << toString(current.result) << ", skipping";
    }

    // For IHealth.getCurrentNow/Average, if current is not available, it is expected that
    // current.result == Result::NOT_SUPPORTED, which is checked above. Hence, zero current is
    // not treated as unknown values.
    // For IHealth.getHealthInfo, if current is not available, health_info.current_* == 0.
    // Caller of this function provides current.result == Result::SUCCESS. Hence, just skip the
    // check.
    if (current.value == 0 && acceptZeroCurrentAsUnknown) {
        return AssertionSuccess()
               << "current is 0, which indicates the value may not be available. Skipping.";
    }

    switch (status.value) {
        case BatteryStatus::UNKNOWN:
            if (current.value != 0) {
                // BatteryStatus may be UNKNOWN initially with a non-zero current value, but
                // after it is initialized, it should be known.
                return AssertionFailure()
                       << "BatteryStatus is UNKNOWN but current is not 0. Actual: "
                       << current.value;
            }
            break;
        case BatteryStatus::CHARGING:
            if (current.value <= 0) {
                return AssertionFailure()
                       << "BatteryStatus is CHARGING but current is not positive. Actual: "
                       << current.value;
            }
            break;
        case BatteryStatus::NOT_CHARGING:
            if (current.value > 0) {
                return AssertionFailure() << "BatteryStatus is " << toString(status.value)
                                          << " but current is positive. Actual: " << current.value;
            }
            break;
        case BatteryStatus::DISCHARGING:
            if (current.value >= 0) {
                return AssertionFailure()
                       << "BatteryStatus is " << toString(status.value)
                       << " but current is not negative. Actual: " << current.value;
            }
            break;
        case BatteryStatus::FULL:
            // Battery current may be positive or negative depending on the load.
            break;
        default:
            return AssertionFailure() << "Unknown BatteryStatus " << toString(status.value);
    }

    return AssertionSuccess() << "BatteryStatus is " << toString(status.value)
                              << " and current has the correct sign: " << current.value;
}

static AssertionResult IsValueSimilar(int32_t dividend, int32_t divisor, double factor) {
    auto difference = abs(dividend - divisor);
    if (difference > factor * abs(divisor)) {
        return AssertionFailure() << dividend << " and " << divisor << " are not similar.";
    }
    return AssertionSuccess() << dividend << " and " << divisor << " are similar.";
    return test_utils::IsBatteryCurrentSignCorrect(
            status.value, current.value, acceptZeroCurrentAsUnknown,
            [](BatteryStatus status) { return toString(status); });
}

static AssertionResult IsBatteryCurrentSimilar(HalResult<BatteryStatus> status,
@@ -437,31 +384,8 @@ static AssertionResult IsBatteryCurrentSimilar(HalResult<BatteryStatus> status,
                                  << currentAverage.value << ", skipping";
    }

    // Check that the two values are similar. Note that the two tests uses a different
    // divisor to ensure that they are actually pretty similar. For example,
    // IsValueSimilar(5,10,0.4) returns true, but IsValueSimlar(10,5,0.4) returns false.
    TEST_AND_RETURN(IsValueSimilar(currentNow.value, currentAverage.value, gCurrentCompareFactor)
                    << " for now vs. average. Check units.");
    TEST_AND_RETURN(IsValueSimilar(currentAverage.value, currentNow.value, gCurrentCompareFactor)
                    << " for average vs. now. Check units.");
    return AssertionSuccess() << "currentNow = " << currentNow.value
                              << " and currentAverage = " << currentAverage.value
                              << " are considered similar.";
}

// Test that f() returns AssertionSuccess() once in a given period of time.
template <typename Duration, typename Function>
static AssertionResult SucceedOnce(Duration d, Function f) {
    AssertionResult result = AssertionFailure() << "Function never evaluated.";
    auto end = std::chrono::system_clock::now() + d;
    while (std::chrono::system_clock::now() <= end) {
        result = f();
        if (result) {
            return result;
        }
        std::this_thread::sleep_for(2s);
    }
    return result;
    return test_utils::IsBatteryCurrentSimilar(currentNow.value, currentAverage.value,
                                               gCurrentCompareFactor);
}

uint64_t GetShippingApiLevel() {
@@ -603,40 +527,8 @@ AssertionResult IsBatteryStatusCorrect(HalResult<BatteryStatus> status,
    }

    const auto& batteryInfo = healthInfo.value.legacy;
    bool isConnected = batteryInfo.chargerAcOnline || batteryInfo.chargerUsbOnline ||
                       batteryInfo.chargerWirelessOnline;

    std::stringstream message;
    message << "BatteryStatus is " << toString(status.value) << " and "
            << (isConnected ? "" : "no ")
            << "power source is connected: ac=" << batteryInfo.chargerAcOnline
            << ", usb=" << batteryInfo.chargerUsbOnline
            << ", wireless=" << batteryInfo.chargerWirelessOnline;

    switch (status.value) {
        case BatteryStatus::UNKNOWN: {
            // Don't enforce anything on isConnected on unknown battery status.
            // Battery-less devices must report UNKNOWN battery status, but may report true
            // or false on isConnected.
        } break;
        case BatteryStatus::CHARGING:
        case BatteryStatus::NOT_CHARGING:
        case BatteryStatus::FULL: {
            if (!isConnected) {
                return AssertionFailure() << message.str();
            }
        } break;
        case BatteryStatus::DISCHARGING: {
            if (isConnected) {
                return AssertionFailure() << message.str();
            }
        } break;
        default: {
            return AssertionFailure() << "Unknown battery status value " << toString(status.value);
        } break;
    }

    return AssertionSuccess() << message.str();
    return test_utils::IsBatteryStatusCorrect(
            status.value, batteryInfo, [](BatteryStatus status) { return toString(status); });
}

TEST_P(BatteryTest, ConnectedAgainstStatusFromHal) {
+48 −0
Original line number Diff line number Diff line
//
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package {
    // See: http://go/android-license-faq
    // A large-scale-change added 'default_applicable_licenses' to import
    // all of the 'license_kinds' from "hardware_interfaces_license"
    // to get the below license kinds:
    //   SPDX-license-identifier-Apache-2.0
    default_applicable_licenses: ["hardware_interfaces_license"],
}

cc_test {
    name: "VtsHalHealthTargetTest",
    defaults: [
        "VtsHalTargetTestDefaults",
        "use_libaidlvintf_gtest_helper_static",
    ],
    srcs: [
        "VtsHalHealthTargetTest.cpp",
    ],
    shared_libs: [
        "libbinder_ndk",
    ],
    static_libs: [
        "android.hardware.health-V1-ndk",
        "libgmock",
    ],
    header_libs: [
        "libhealthtest_headers",
    ],
    test_suites: [
        "vts",
    ],
}
+539 −0

File added.

Preview size limit exceeded, changes collapsed.

+29 −0
Original line number Diff line number Diff line
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Utils library for VTS tests.
cc_library_headers {
    name: "libhealthtest_headers",
    static_libs: [
        "libgmock",
        "libgtest",
    ],
    export_static_lib_headers: [
        "libgmock",
        "libgtest",
    ],
    export_include_dirs: [
        "include",
    ],
}
Loading