Convert VTS for VHAL from python to gtest

VTS10 won't be supported after S.
Rewrite the VTS for VHAL in gtest test suit.
Also, the test is moved from host-side to target side.

Bug: 153872561
Test: atest -c VtsHalAutomotiveVehicleV2_0TargetTest
Change-Id: I89d3983daba2ea5784ba9d95833c3f2dda3b1fac
This commit is contained in:
Kai 2021-02-23 15:56:53 -08:00
parent e0fb8a1ef3
commit 40b9fe8213
2 changed files with 268 additions and 0 deletions

View file

@ -0,0 +1,21 @@
cc_test {
name: "VtsHalAutomotiveVehicleV2_0TargetTest",
defaults: [
"VtsHalTargetTestDefaults",
],
srcs: [
"VtsHalAutomotiveVehicleV2_0TargetTest.cpp",
],
shared_libs: [
"libbase",
"libhidlbase",
"liblog",
],
static_libs: [
"android.hardware.automotive.vehicle@2.0",
],
test_suites: [
"vts",
"general-tests",
],
}

View file

@ -0,0 +1,247 @@
/*
* Copyright (C) 2020 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.
*/
#define LOG_TAG "VtsHalAutomotiveVehicle"
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
#include <utils/Log.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
using namespace android::hardware::automotive::vehicle::V2_0;
using ::android::sp;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
constexpr auto kTimeout = std::chrono::milliseconds(500);
constexpr auto kInvalidProp = 0x31600207;
class VtsVehicleCallback : public IVehicleCallback {
private:
using MutexGuard = std::lock_guard<std::mutex>;
using HidlVecOfValues = hidl_vec<VehiclePropValue>;
std::mutex mLock;
std::condition_variable mEventCond;
std::vector<HidlVecOfValues> mReceivedEvents;
public:
Return<void> onPropertyEvent(const hidl_vec<VehiclePropValue>& values) override {
{
MutexGuard guard(mLock);
mReceivedEvents.push_back(values);
}
mEventCond.notify_one();
return Return<void>();
}
Return<void> onPropertySet(const VehiclePropValue& /* value */) override {
return Return<void>();
}
Return<void> onPropertySetError(StatusCode /* errorCode */, int32_t /* propId */,
int32_t /* areaId */) override {
return Return<void>();
}
bool waitForExpectedEvents(size_t expectedEvents) {
std::unique_lock<std::mutex> g(mLock);
if (expectedEvents == 0 && mReceivedEvents.size() == 0) {
return mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout;
}
while (expectedEvents != mReceivedEvents.size()) {
if (mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout) {
return false;
}
}
return true;
}
void reset() { mReceivedEvents.clear(); }
};
class VehicleHalHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
mVehicle = IVehicle::getService(GetParam());
ASSERT_NE(mVehicle.get(), nullptr);
}
virtual void TearDown() override {}
sp<IVehicle> mVehicle;
bool isBooleanGlobalProp(int32_t property) {
return (property & (int)VehiclePropertyType::MASK) == (int)VehiclePropertyType::BOOLEAN &&
(property & (int)VehicleArea::MASK) == (int)VehicleArea::GLOBAL;
}
void invokeGet(int32_t property, int32_t areaId) {
VehiclePropValue requestedValue{};
requestedValue.prop = property;
requestedValue.areaId = areaId;
invokeGet(requestedValue);
}
void invokeGet(const VehiclePropValue& requestedPropValue) {
mActualValue = VehiclePropValue{}; // reset previous values
StatusCode refStatus;
VehiclePropValue refValue;
bool isCalled = false;
mVehicle->get(requestedPropValue,
[&refStatus, &refValue, &isCalled](StatusCode status,
const VehiclePropValue& value) {
refStatus = status;
refValue = value;
isCalled = true;
});
ASSERT_TRUE(isCalled) << "callback wasn't called for property: " << requestedPropValue.prop;
mActualValue = refValue;
mActualStatusCode = refStatus;
}
VehiclePropValue mActualValue;
StatusCode mActualStatusCode;
};
// Test getAllPropConfig() returns at least 4 property configs.
TEST_P(VehicleHalHidlTest, getAllPropConfigs) {
ALOGD("VehicleHalHidlTest::getAllPropConfigs");
bool isCalled = false;
hidl_vec<VehiclePropConfig> propConfigs;
mVehicle->getAllPropConfigs([&isCalled, &propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) {
propConfigs = cfgs;
isCalled = true;
});
ASSERT_TRUE(isCalled);
ASSERT_GE(propConfigs.size(), 4);
}
// Test getPropConfig() can query all properties listed in CDD.
TEST_P(VehicleHalHidlTest, getPropConfigs) {
ALOGD("VehicleHalHidlTest::getPropConfigs");
// Check the properties listed in CDD
hidl_vec<int32_t> properties = {
(int)VehicleProperty::GEAR_SELECTION, (int)VehicleProperty::NIGHT_MODE,
(int)VehicleProperty::PARKING_BRAKE_ON, (int)VehicleProperty::PERF_VEHICLE_SPEED};
bool isCalled = false;
mVehicle->getPropConfigs(
properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
ASSERT_EQ(StatusCode::OK, status);
ASSERT_EQ(4u, cfgs.size());
isCalled = true;
});
ASSERT_TRUE(isCalled);
}
// Test getPropConfig() with an invalid propertyId returns an error code.
TEST_P(VehicleHalHidlTest, getPropConfigsWithInvalidProp) {
ALOGD("VehicleHalHidlTest::getPropConfigsWithInvalidProp");
hidl_vec<int32_t> properties = {kInvalidProp};
bool isCalled = false;
mVehicle->getPropConfigs(
properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
ASSERT_NE(StatusCode::OK, status);
ASSERT_EQ(0, cfgs.size());
isCalled = true;
});
ASSERT_TRUE(isCalled);
}
// Test get() return current value for properties.
TEST_P(VehicleHalHidlTest, get) {
ALOGD("VehicleHalHidlTest::get");
invokeGet((int)VehicleProperty::PERF_VEHICLE_SPEED, 0);
ASSERT_EQ(StatusCode::OK, mActualStatusCode);
}
// Test get() with an invalid propertyId return an error codes.
TEST_P(VehicleHalHidlTest, getInvalidProp) {
ALOGD("VehicleHalHidlTest::getInvalidProp");
invokeGet(kInvalidProp, 0);
ASSERT_NE(StatusCode::OK, mActualStatusCode);
}
// Test set() on read_write properties.
TEST_P(VehicleHalHidlTest, setProp) {
ALOGD("VehicleHalHidlTest::setProp");
hidl_vec<VehiclePropConfig> propConfigs;
mVehicle->getAllPropConfigs(
[&propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) { propConfigs = cfgs; });
for (const VehiclePropConfig& cfg : propConfigs) {
// test on boolean and writable property
if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop)) {
invokeGet(cfg.prop, 0);
int setValue = mActualValue.value.int32Values[0] == 1 ? 0 : 1;
VehiclePropValue propToSet = mActualValue;
propToSet.value.int32Values[0] = setValue;
ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet));
// check set success
invokeGet(cfg.prop, 0);
ASSERT_EQ(StatusCode::OK, mActualStatusCode);
ASSERT_EQ(setValue, mActualValue.value.int32Values[0]);
}
}
}
// Test set() on an read_only property.
TEST_P(VehicleHalHidlTest, setNotWritableProp) {
ALOGD("VehicleHalHidlTest::setNotWritableProp");
invokeGet(static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED), 0);
ASSERT_EQ(StatusCode::OK, mActualStatusCode);
VehiclePropValue vehicleSpeed = mActualValue;
ASSERT_EQ(StatusCode::ACCESS_DENIED, mVehicle->set(vehicleSpeed));
}
// Test subscribe() and unsubscribe().
TEST_P(VehicleHalHidlTest, subscribeAndUnsubscribe) {
ALOGD("VehicleHalHidlTest::subscribeAndUnsubscribe");
const auto prop = static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED);
sp<VtsVehicleCallback> cb = new VtsVehicleCallback();
hidl_vec<SubscribeOptions> options = {
SubscribeOptions{.propId = prop, 100.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
ASSERT_EQ(StatusCode::OK, mVehicle->subscribe(cb, options));
ASSERT_TRUE(cb->waitForExpectedEvents(10));
ASSERT_EQ(StatusCode::OK, mVehicle->unsubscribe(cb, prop));
cb->reset();
ASSERT_FALSE(cb->waitForExpectedEvents(10));
}
// Test subscribe() with an invalid property.
TEST_P(VehicleHalHidlTest, subscribeInvalidProp) {
ALOGD("VehicleHalHidlTest::subscribeInvalidProp");
sp<VtsVehicleCallback> cb = new VtsVehicleCallback();
hidl_vec<SubscribeOptions> options = {SubscribeOptions{
.propId = kInvalidProp, 10.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
ASSERT_NE(StatusCode::OK, mVehicle->subscribe(cb, options));
}
INSTANTIATE_TEST_SUITE_P(
PerInstance, VehicleHalHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVehicle::descriptor)),
android::hardware::PrintInstanceNameToString);