Add unittest for HidlVhalClient.
Test: atest libvhalclient_test
Bug: 214635003
Change-Id: Ia248d7a9a108e9aae653afef2b30cbee58dc36e6
diff --git a/cpp/vhal/client/include/AidlVhalClient.h b/cpp/vhal/client/include/AidlVhalClient.h
index 196d25d..e1c28fb 100644
--- a/cpp/vhal/client/include/AidlVhalClient.h
+++ b/cpp/vhal/client/include/AidlVhalClient.h
@@ -38,11 +38,11 @@
namespace automotive {
namespace vhal {
-namespace test {
+namespace aidl_test {
class AidlVhalClientTest;
-}
+} // namespace aidl_test
class GetSetValueClient;
@@ -79,7 +79,7 @@
std::shared_ptr<ISubscriptionCallback> callback) override;
private:
- friend class test::AidlVhalClientTest;
+ friend class aidl_test::AidlVhalClientTest;
class ILinkUnlinkToDeath {
public:
diff --git a/cpp/vhal/client/include/HidlVhalClient.h b/cpp/vhal/client/include/HidlVhalClient.h
index 7354d1d..9d920d1 100644
--- a/cpp/vhal/client/include/HidlVhalClient.h
+++ b/cpp/vhal/client/include/HidlVhalClient.h
@@ -32,6 +32,12 @@
namespace automotive {
namespace vhal {
+namespace hidl_test {
+
+class HidlVhalClientTest;
+
+} // namespace hidl_test
+
class HidlVhalClient final : public IVhalClient {
public:
explicit HidlVhalClient(
@@ -63,6 +69,8 @@
std::shared_ptr<ISubscriptionCallback> callback) override;
private:
+ friend class hidl_test::HidlVhalClientTest;
+
class DeathRecipient : public ::android::hardware::hidl_death_recipient {
public:
explicit DeathRecipient(HidlVhalClient* client);
diff --git a/cpp/vhal/client/test/AidlVhalClientTest.cpp b/cpp/vhal/client/test/AidlVhalClientTest.cpp
index 3523f42..ed285fc 100644
--- a/cpp/vhal/client/test/AidlVhalClientTest.cpp
+++ b/cpp/vhal/client/test/AidlVhalClientTest.cpp
@@ -32,7 +32,7 @@
namespace frameworks {
namespace automotive {
namespace vhal {
-namespace test {
+namespace aidl_test {
using ::android::base::Result;
using ::android::hardware::automotive::vehicle::toInt;
@@ -866,7 +866,7 @@
ASSERT_FALSE(result.ok());
}
-} // namespace test
+} // namespace aidl_test
} // namespace vhal
} // namespace automotive
} // namespace frameworks
diff --git a/cpp/vhal/client/test/HidlVhalClientTest.cpp b/cpp/vhal/client/test/HidlVhalClientTest.cpp
new file mode 100644
index 0000000..c0c348d
--- /dev/null
+++ b/cpp/vhal/client/test/HidlVhalClientTest.cpp
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include "HidlHalPropValue.h"
+#include "HidlVhalClient.h"
+
+#include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
+#include <android-base/result.h>
+#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+#include <gtest/gtest.h>
+#include <utils/StrongPointer.h>
+
+#include <VehicleUtils.h>
+
+#include <vector>
+
+namespace android {
+namespace frameworks {
+namespace automotive {
+namespace vhal {
+namespace hidl_test {
+
+using ::android::sp;
+using ::android::base::Result;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::automotive::vehicle::toInt;
+using ::android::hardware::automotive::vehicle::V2_0::IVehicle;
+using ::android::hardware::automotive::vehicle::V2_0::IVehicleCallback;
+using ::android::hardware::automotive::vehicle::V2_0::StatusCode;
+using ::android::hardware::automotive::vehicle::V2_0::SubscribeFlags;
+using ::android::hardware::automotive::vehicle::V2_0::SubscribeOptions;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropConfig;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValue;
+
+class MockVhal final : public IVehicle {
+public:
+ Return<void> getAllPropConfigs(IVehicle::getAllPropConfigs_cb callback) override {
+ callback(mPropConfigs);
+ return {};
+ }
+
+ Return<void> getPropConfigs(const hidl_vec<int32_t>& props,
+ IVehicle::getPropConfigs_cb callback) override {
+ mGetPropConfigsProps = props;
+ callback(mStatus, mPropConfigs);
+ return {};
+ }
+
+ Return<void> get(const VehiclePropValue& requestPropValue, IVehicle::get_cb callback) override {
+ mRequestPropValue = requestPropValue;
+ callback(mStatus, mPropValue);
+ return {};
+ }
+
+ Return<StatusCode> set(const VehiclePropValue& value) override {
+ mRequestPropValue = value;
+ return mStatus;
+ }
+
+ Return<StatusCode> subscribe(const sp<IVehicleCallback>& callback,
+ const hidl_vec<SubscribeOptions>& options) override {
+ mSubscribedCallback = callback;
+ mSubscribeOptions = options;
+ return mStatus;
+ }
+
+ Return<StatusCode> unsubscribe([[maybe_unused]] const sp<IVehicleCallback>& callback,
+ int32_t propId) override {
+ mUnsubscribedPropId = propId;
+ return mStatus;
+ }
+
+ Return<void> debugDump([[maybe_unused]] IVehicle::debugDump_cb callback) override { return {}; }
+
+ // Test functions
+
+ void setPropConfigs(std::vector<VehiclePropConfig> configs) { mPropConfigs = configs; }
+
+ void setStatus(StatusCode status) { mStatus = status; }
+
+ void setVehiclePropValue(VehiclePropValue value) { mPropValue = value; }
+
+ std::vector<int32_t> getGetPropConfigsProps() { return mGetPropConfigsProps; }
+
+ VehiclePropValue getRequestPropValue() { return mRequestPropValue; }
+
+ std::vector<SubscribeOptions> getSubscribeOptions() { return mSubscribeOptions; }
+
+ int32_t getUnsubscribedPropId() { return mUnsubscribedPropId; }
+
+ void triggerOnPropertyEvent(const std::vector<VehiclePropValue>& values) {
+ mSubscribedCallback->onPropertyEvent(values);
+ }
+
+ void triggerSetErrorEvent(StatusCode status, int32_t propId, int32_t areaId) {
+ mSubscribedCallback->onPropertySetError(status, propId, areaId);
+ }
+
+private:
+ std::vector<VehiclePropConfig> mPropConfigs;
+ StatusCode mStatus = StatusCode::OK;
+ VehiclePropValue mPropValue;
+
+ std::vector<int32_t> mGetPropConfigsProps;
+ VehiclePropValue mRequestPropValue;
+ sp<IVehicleCallback> mSubscribedCallback;
+ std::vector<SubscribeOptions> mSubscribeOptions;
+ int32_t mUnsubscribedPropId;
+};
+
+class MockSubscriptionCallback final : public ISubscriptionCallback {
+public:
+ void onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>>& values) override {
+ for (const auto& value : values) {
+ mEventPropIds.push_back(value->getPropId());
+ }
+ }
+ void onPropertySetError(const std::vector<HalPropError>& errors) override { mErrors = errors; }
+
+ std::vector<int32_t> getEventPropIds() { return mEventPropIds; }
+
+ std::vector<HalPropError> getErrors() { return mErrors; }
+
+private:
+ std::vector<int32_t> mEventPropIds;
+ std::vector<HalPropError> mErrors;
+};
+
+class HidlVhalClientTest : public ::testing::Test {
+protected:
+ constexpr static int32_t TEST_PROP_ID = 1;
+ constexpr static int32_t TEST_AREA_ID = 2;
+ constexpr static int32_t TEST_PROP_ID_2 = 3;
+
+ const VehiclePropValue TEST_VALUE{
+ .prop = TEST_PROP_ID,
+ .areaId = TEST_AREA_ID,
+ .value.int32Values = {1},
+ };
+
+ void SetUp() override {
+ mVhal = new MockVhal();
+ mVhalClient = std::make_unique<HidlVhalClient>(mVhal);
+ }
+
+ MockVhal* getVhal() { return mVhal.get(); }
+
+ HidlVhalClient* getClient() { return mVhalClient.get(); }
+
+ void triggerBinderDied() { mVhalClient->onBinderDied(); }
+
+private:
+ sp<MockVhal> mVhal;
+ std::unique_ptr<HidlVhalClient> mVhalClient;
+};
+
+TEST_F(HidlVhalClientTest, testGetValue) {
+ Result<std::unique_ptr<IHalPropValue>> result;
+ Result<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
+ bool gotResult = false;
+ bool* gotResultPtr = &gotResult;
+ auto callback = std::make_shared<HidlVhalClient::GetValueCallbackFunc>(
+ [resultPtr, gotResultPtr](Result<std::unique_ptr<IHalPropValue>> r) {
+ *resultPtr = std::move(r);
+ *gotResultPtr = true;
+ });
+ getVhal()->setVehiclePropValue(TEST_VALUE);
+
+ getClient()->getValue(HidlHalPropValue(TEST_PROP_ID, TEST_AREA_ID), callback);
+
+ ASSERT_TRUE(gotResult);
+ ASSERT_EQ(getVhal()->getRequestPropValue().prop, TEST_PROP_ID);
+ ASSERT_EQ(getVhal()->getRequestPropValue().areaId, TEST_AREA_ID);
+ ASSERT_TRUE(result.ok());
+ auto gotValue = std::move(result.value());
+ ASSERT_EQ(gotValue->getPropId(), TEST_PROP_ID);
+ ASSERT_EQ(gotValue->getAreaId(), TEST_AREA_ID);
+ ASSERT_EQ(gotValue->getInt32Values(), std::vector<int32_t>({1}));
+}
+
+TEST_F(HidlVhalClientTest, testGetValueError) {
+ getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
+
+ Result<std::unique_ptr<IHalPropValue>> result;
+ Result<std::unique_ptr<IHalPropValue>>* resultPtr = &result;
+ bool gotResult = false;
+ bool* gotResultPtr = &gotResult;
+ auto callback = std::make_shared<HidlVhalClient::GetValueCallbackFunc>(
+ [resultPtr, gotResultPtr](Result<std::unique_ptr<IHalPropValue>> r) {
+ *resultPtr = std::move(r);
+ *gotResultPtr = true;
+ });
+
+ getClient()->getValue(HidlHalPropValue(TEST_PROP_ID, TEST_AREA_ID), callback);
+
+ ASSERT_TRUE(gotResult);
+ ASSERT_FALSE(result.ok());
+}
+
+TEST_F(HidlVhalClientTest, testSetValue) {
+ Result<void> result;
+ Result<void>* resultPtr = &result;
+ bool gotResult = false;
+ bool* gotResultPtr = &gotResult;
+ auto callback = std::make_shared<HidlVhalClient::SetValueCallbackFunc>(
+ [resultPtr, gotResultPtr](Result<void> r) {
+ *resultPtr = std::move(r);
+ *gotResultPtr = true;
+ });
+
+ getClient()->setValue(HidlHalPropValue(TEST_PROP_ID, TEST_AREA_ID), callback);
+
+ ASSERT_TRUE(gotResult);
+ ASSERT_EQ(getVhal()->getRequestPropValue().prop, TEST_PROP_ID);
+ ASSERT_EQ(getVhal()->getRequestPropValue().areaId, TEST_AREA_ID);
+ ASSERT_TRUE(result.ok());
+}
+TEST_F(HidlVhalClientTest, testSetValueError) {
+ getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
+
+ Result<void> result;
+ Result<void>* resultPtr = &result;
+ bool gotResult = false;
+ bool* gotResultPtr = &gotResult;
+ auto callback = std::make_shared<HidlVhalClient::SetValueCallbackFunc>(
+ [resultPtr, gotResultPtr](Result<void> r) {
+ *resultPtr = std::move(r);
+ *gotResultPtr = true;
+ });
+
+ getClient()->setValue(HidlHalPropValue(TEST_PROP_ID, TEST_AREA_ID), callback);
+
+ ASSERT_TRUE(gotResult);
+ ASSERT_FALSE(result.ok());
+}
+
+TEST_F(HidlVhalClientTest, testAddOnBinderDiedCallback) {
+ struct Result {
+ bool callbackOneCalled = false;
+ bool callbackTwoCalled = false;
+ } result;
+
+ getClient()->addOnBinderDiedCallback(std::make_shared<HidlVhalClient::OnBinderDiedCallbackFunc>(
+ [&result] { result.callbackOneCalled = true; }));
+ getClient()->addOnBinderDiedCallback(std::make_shared<HidlVhalClient::OnBinderDiedCallbackFunc>(
+ [&result] { result.callbackTwoCalled = true; }));
+ triggerBinderDied();
+
+ ASSERT_TRUE(result.callbackOneCalled);
+ ASSERT_TRUE(result.callbackTwoCalled);
+}
+
+TEST_F(HidlVhalClientTest, testRemoveOnBinderDiedCallback) {
+ struct Result {
+ bool callbackOneCalled = false;
+ bool callbackTwoCalled = false;
+ } result;
+
+ auto callbackOne = std::make_shared<HidlVhalClient::OnBinderDiedCallbackFunc>(
+ [&result] { result.callbackOneCalled = true; });
+ auto callbackTwo = std::make_shared<HidlVhalClient::OnBinderDiedCallbackFunc>(
+ [&result] { result.callbackTwoCalled = true; });
+ getClient()->addOnBinderDiedCallback(callbackOne);
+ getClient()->addOnBinderDiedCallback(callbackTwo);
+ getClient()->removeOnBinderDiedCallback(callbackOne);
+ triggerBinderDied();
+
+ ASSERT_FALSE(result.callbackOneCalled);
+ ASSERT_TRUE(result.callbackTwoCalled);
+}
+
+TEST_F(HidlVhalClientTest, testGetAllPropConfigs) {
+ getVhal()->setPropConfigs({
+ VehiclePropConfig{
+ .prop = TEST_PROP_ID,
+ .areaConfigs = {{
+ .areaId = TEST_AREA_ID,
+ .minInt32Value = 0,
+ .maxInt32Value = 1,
+ }},
+ },
+ VehiclePropConfig{
+ .prop = TEST_PROP_ID_2,
+ },
+ });
+
+ auto result = getClient()->getAllPropConfigs();
+
+ ASSERT_TRUE(result.ok());
+ std::vector<std::unique_ptr<IHalPropConfig>> configs = std::move(result.value());
+
+ ASSERT_EQ(configs.size(), static_cast<size_t>(2));
+ ASSERT_EQ(configs[0]->getPropId(), TEST_PROP_ID);
+ ASSERT_EQ(configs[0]->getAreaConfigSize(), static_cast<size_t>(1));
+
+ const IHalAreaConfig* areaConfig = configs[0]->getAreaConfigs();
+ ASSERT_EQ(areaConfig->getAreaId(), TEST_AREA_ID);
+ ASSERT_EQ(areaConfig->getMinInt32Value(), 0);
+ ASSERT_EQ(areaConfig->getMaxInt32Value(), 1);
+
+ ASSERT_EQ(configs[1]->getPropId(), TEST_PROP_ID_2);
+ ASSERT_EQ(configs[1]->getAreaConfigSize(), static_cast<size_t>(0));
+}
+
+TEST_F(HidlVhalClientTest, testGetPropConfigs) {
+ getVhal()->setPropConfigs({
+ VehiclePropConfig{
+ .prop = TEST_PROP_ID,
+ .areaConfigs = {{
+ .areaId = TEST_AREA_ID,
+ .minInt32Value = 0,
+ .maxInt32Value = 1,
+ }},
+ },
+ VehiclePropConfig{
+ .prop = TEST_PROP_ID_2,
+ },
+ });
+
+ std::vector<int32_t> propIds = {TEST_PROP_ID, TEST_PROP_ID_2};
+ auto result = getClient()->getPropConfigs(propIds);
+
+ ASSERT_EQ(getVhal()->getGetPropConfigsProps(), propIds);
+ ASSERT_TRUE(result.ok());
+ std::vector<std::unique_ptr<IHalPropConfig>> configs = std::move(result.value());
+
+ ASSERT_EQ(configs.size(), static_cast<size_t>(2));
+ ASSERT_EQ(configs[0]->getPropId(), TEST_PROP_ID);
+ ASSERT_EQ(configs[0]->getAreaConfigSize(), static_cast<size_t>(1));
+
+ const IHalAreaConfig* areaConfig = configs[0]->getAreaConfigs();
+ ASSERT_EQ(areaConfig->getAreaId(), TEST_AREA_ID);
+ ASSERT_EQ(areaConfig->getMinInt32Value(), 0);
+ ASSERT_EQ(areaConfig->getMaxInt32Value(), 1);
+
+ ASSERT_EQ(configs[1]->getPropId(), TEST_PROP_ID_2);
+ ASSERT_EQ(configs[1]->getAreaConfigSize(), static_cast<size_t>(0));
+}
+
+TEST_F(HidlVhalClientTest, testGetPropConfigsError) {
+ getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
+
+ std::vector<int32_t> propIds = {TEST_PROP_ID, TEST_PROP_ID_2};
+ auto result = getClient()->getPropConfigs(propIds);
+
+ ASSERT_FALSE(result.ok());
+}
+
+TEST_F(HidlVhalClientTest, testSubscribe) {
+ std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions> options = {
+ {
+ .propId = TEST_PROP_ID,
+ .areaIds = {TEST_AREA_ID},
+ .sampleRate = 1.0,
+ },
+ {
+ .propId = TEST_PROP_ID_2,
+ .sampleRate = 2.0,
+ },
+ };
+ std::vector<SubscribeOptions> hidlOptions = {
+ {
+ .propId = TEST_PROP_ID,
+ .flags = SubscribeFlags::UNDEFINED,
+ .sampleRate = 1.0,
+ },
+ {
+ .propId = TEST_PROP_ID_2,
+ .flags = SubscribeFlags::UNDEFINED,
+ .sampleRate = 2.0,
+ },
+ };
+
+ auto callback = std::make_shared<MockSubscriptionCallback>();
+ auto subscriptionClient = getClient()->getSubscriptionClient(callback);
+ auto result = subscriptionClient->subscribe(options);
+
+ ASSERT_TRUE(result.ok());
+ ASSERT_EQ(getVhal()->getSubscribeOptions(), hidlOptions);
+
+ getVhal()->triggerOnPropertyEvent(std::vector<VehiclePropValue>{
+ {
+ .prop = TEST_PROP_ID,
+ .areaId = TEST_AREA_ID,
+ .value.int32Values = {1},
+ },
+ });
+
+ ASSERT_EQ(callback->getEventPropIds(), std::vector<int32_t>({TEST_PROP_ID}));
+
+ getVhal()->triggerSetErrorEvent(StatusCode::INTERNAL_ERROR, TEST_PROP_ID, TEST_AREA_ID);
+
+ auto errors = callback->getErrors();
+ ASSERT_EQ(errors.size(), static_cast<size_t>(1));
+ ASSERT_EQ(errors[0].propId, TEST_PROP_ID);
+ ASSERT_EQ(errors[0].areaId, TEST_AREA_ID);
+ ASSERT_EQ(errors[0].status,
+ ::aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR);
+}
+
+TEST_F(HidlVhalClientTest, testSubscribeError) {
+ std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions> options = {
+ {
+ .propId = TEST_PROP_ID,
+ .areaIds = {TEST_AREA_ID},
+ .sampleRate = 1.0,
+ },
+ {
+ .propId = TEST_PROP_ID_2,
+ .sampleRate = 2.0,
+ },
+ };
+
+ getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
+ auto callback = std::make_shared<MockSubscriptionCallback>();
+ auto subscriptionClient = getClient()->getSubscriptionClient(callback);
+ auto result = subscriptionClient->subscribe(options);
+
+ ASSERT_FALSE(result.ok());
+}
+
+TEST_F(HidlVhalClientTest, testUnubscribe) {
+ auto callback = std::make_shared<MockSubscriptionCallback>();
+ auto subscriptionClient = getClient()->getSubscriptionClient(callback);
+ auto result = subscriptionClient->unsubscribe({TEST_PROP_ID});
+
+ ASSERT_TRUE(result.ok());
+ ASSERT_EQ(getVhal()->getUnsubscribedPropId(), TEST_PROP_ID);
+}
+
+TEST_F(HidlVhalClientTest, testUnubscribeError) {
+ getVhal()->setStatus(StatusCode::INTERNAL_ERROR);
+ auto callback = std::make_shared<MockSubscriptionCallback>();
+ auto subscriptionClient = getClient()->getSubscriptionClient(callback);
+ auto result = subscriptionClient->unsubscribe({TEST_PROP_ID});
+
+ ASSERT_FALSE(result.ok());
+}
+
+} // namespace hidl_test
+} // namespace vhal
+} // namespace automotive
+} // namespace frameworks
+} // namespace android