mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Migrate VehiclePropertyStore.
Test: atest VehicleHalVehicleUtilsTest Bug: 199337732 Change-Id: Ia18699a0115fdb004c57c0e6fb02b043ddb138b5
This commit is contained in:
@@ -32,5 +32,6 @@ cc_defaults {
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
"-Wthread-safety",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_
|
||||
#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <VehicleHalTypes.h>
|
||||
#include <android-base/result.h>
|
||||
#include <android-base/thread_annotations.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
|
||||
// Encapsulates work related to storing and accessing configuration, storing and modifying
|
||||
// vehicle property values.
|
||||
//
|
||||
// VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g.
|
||||
// to get value for all areas for particular property.
|
||||
//
|
||||
// This class is thread-safe, however it uses blocking synchronization across all methods.
|
||||
class VehiclePropertyStore {
|
||||
public:
|
||||
// Function that used to calculate unique token for given VehiclePropValue.
|
||||
using TokenFunction = ::std::function<int64_t(
|
||||
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value)>;
|
||||
|
||||
// Register the given property according to the config. A property has to be registered first
|
||||
// before write/read. If tokenFunc is not nullptr, it would be used to generate a unique
|
||||
// property token to act as the key the property store. Otherwise, {propertyID, areaID} would be
|
||||
// used as the key.
|
||||
void registerProperty(
|
||||
const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config,
|
||||
TokenFunction tokenFunc = nullptr);
|
||||
|
||||
// Stores provided value. Returns true if value was written returns false if config wasn't
|
||||
// registered.
|
||||
::android::base::Result<void> writeValue(
|
||||
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
|
||||
|
||||
// Remove a given property value from the property store. The 'propValue' would be used to
|
||||
// generate the key for the value to remove.
|
||||
void removeValue(
|
||||
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
|
||||
|
||||
// Remove all the values for the property.
|
||||
void removeValuesForProperty(int32_t propId);
|
||||
|
||||
// Read all the stored values.
|
||||
std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> readAllValues()
|
||||
const;
|
||||
|
||||
// Read all the values for the property.
|
||||
::android::base::Result<
|
||||
std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
|
||||
readValuesForProperty(int32_t propId) const;
|
||||
|
||||
// Read the value for the requested property.
|
||||
::android::base::Result<
|
||||
std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
|
||||
readValue(
|
||||
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request) const;
|
||||
|
||||
// Read the value for the requested property.
|
||||
::android::base::Result<
|
||||
std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
|
||||
readValue(int32_t prop, int32_t area = 0, int64_t token = 0) const;
|
||||
|
||||
// Get all property configs.
|
||||
std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig> getAllConfigs()
|
||||
const;
|
||||
|
||||
// Get the property config for the requested property.
|
||||
::android::base::Result<
|
||||
const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig*>
|
||||
getConfig(int32_t propId) const;
|
||||
|
||||
private:
|
||||
struct RecordId {
|
||||
int32_t area;
|
||||
int64_t token;
|
||||
|
||||
bool operator==(const RecordId& other) const;
|
||||
bool operator<(const RecordId& other) const;
|
||||
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
struct Record {
|
||||
::aidl::android::hardware::automotive::vehicle::VehiclePropConfig propConfig;
|
||||
TokenFunction tokenFunction;
|
||||
std::map<RecordId, ::aidl::android::hardware::automotive::vehicle::VehiclePropValue> values;
|
||||
};
|
||||
|
||||
mutable std::mutex mLock;
|
||||
std::unordered_map<int32_t, Record> mRecordsByPropId GUARDED_BY(mLock);
|
||||
|
||||
const Record* getRecordLocked(int32_t propId) const;
|
||||
|
||||
Record* getRecordLocked(int32_t propId);
|
||||
|
||||
RecordId getRecordIdLocked(
|
||||
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue,
|
||||
const Record& record) const;
|
||||
|
||||
::android::base::Result<
|
||||
std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
|
||||
readValueLocked(const RecordId& recId, const Record& record) const;
|
||||
};
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "VehiclePropertyStore"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "VehiclePropertyStore.h"
|
||||
|
||||
#include <VehicleUtils.h>
|
||||
#include <android-base/format.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
|
||||
using ::android::base::Result;
|
||||
|
||||
bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const {
|
||||
return area == other.area && token == other.token;
|
||||
}
|
||||
|
||||
bool VehiclePropertyStore::RecordId::operator<(const VehiclePropertyStore::RecordId& other) const {
|
||||
return area < other.area || (area == other.area && token < other.token);
|
||||
}
|
||||
|
||||
std::string VehiclePropertyStore::RecordId::toString() const {
|
||||
return ::fmt::format("RecordID{{.areaId={:d}, .token={:d}}}", area, token);
|
||||
}
|
||||
|
||||
const VehiclePropertyStore::Record* VehiclePropertyStore::getRecordLocked(int32_t propId) const
|
||||
REQUIRES(mLock) {
|
||||
auto RecordIt = mRecordsByPropId.find(propId);
|
||||
return RecordIt == mRecordsByPropId.end() ? nullptr : &RecordIt->second;
|
||||
}
|
||||
|
||||
VehiclePropertyStore::Record* VehiclePropertyStore::getRecordLocked(int32_t propId)
|
||||
REQUIRES(mLock) {
|
||||
auto RecordIt = mRecordsByPropId.find(propId);
|
||||
return RecordIt == mRecordsByPropId.end() ? nullptr : &RecordIt->second;
|
||||
}
|
||||
|
||||
VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
|
||||
const VehiclePropValue& propValue, const VehiclePropertyStore::Record& record) const
|
||||
REQUIRES(mLock) {
|
||||
VehiclePropertyStore::RecordId recId{
|
||||
.area = isGlobalProp(propValue.prop) ? 0 : propValue.areaId, .token = 0};
|
||||
|
||||
if (record.tokenFunction != nullptr) {
|
||||
recId.token = record.tokenFunction(propValue);
|
||||
}
|
||||
return recId;
|
||||
}
|
||||
|
||||
Result<std::unique_ptr<VehiclePropValue>> VehiclePropertyStore::readValueLocked(
|
||||
const RecordId& recId, const Record& record) const REQUIRES(mLock) {
|
||||
auto it = record.values.find(recId);
|
||||
if (it == record.values.end()) {
|
||||
return Errorf("Record ID: {} is not found", recId.toString());
|
||||
}
|
||||
return std::make_unique<VehiclePropValue>(it->second);
|
||||
}
|
||||
|
||||
void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
|
||||
VehiclePropertyStore::TokenFunction tokenFunc) {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
mRecordsByPropId[config.prop] = Record{
|
||||
.propConfig = config,
|
||||
.tokenFunction = tokenFunc,
|
||||
};
|
||||
}
|
||||
|
||||
Result<void> VehiclePropertyStore::writeValue(const VehiclePropValue& propValue) {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
VehiclePropertyStore::Record* record = getRecordLocked(propValue.prop);
|
||||
if (record == nullptr) {
|
||||
return Errorf("property: {:d} not registered", propValue.prop);
|
||||
}
|
||||
|
||||
if (!isGlobalProp(propValue.prop) && getAreaConfig(propValue, record->propConfig) == nullptr) {
|
||||
return Errorf("no config for property: {:d} area: {:d}", propValue.prop, propValue.areaId);
|
||||
}
|
||||
|
||||
VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record);
|
||||
auto it = record->values.find(recId);
|
||||
if (it == record->values.end()) {
|
||||
record->values[recId] = propValue;
|
||||
return {};
|
||||
}
|
||||
VehiclePropValue* valueToUpdate = &(it->second);
|
||||
|
||||
// propValue is outdated and drops it.
|
||||
if (valueToUpdate->timestamp > propValue.timestamp) {
|
||||
return Errorf("outdated timestamp: {:d}", propValue.timestamp);
|
||||
}
|
||||
// Update the propertyValue.
|
||||
// The timestamp in propertyStore should only be updated by the server side. It indicates
|
||||
// the time when the event is generated by the server.
|
||||
valueToUpdate->timestamp = propValue.timestamp;
|
||||
valueToUpdate->value = propValue.value;
|
||||
valueToUpdate->status = propValue.status;
|
||||
return {};
|
||||
}
|
||||
|
||||
void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
VehiclePropertyStore::Record* record = getRecordLocked(propValue.prop);
|
||||
if (record == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record);
|
||||
if (auto it = record->values.find(recId); it != record->values.end()) {
|
||||
record->values.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
VehiclePropertyStore::Record* record = getRecordLocked(propId);
|
||||
if (record == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
record->values.clear();
|
||||
}
|
||||
|
||||
std::vector<VehiclePropValue> VehiclePropertyStore::readAllValues() const {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
std::vector<VehiclePropValue> allValues;
|
||||
|
||||
for (auto const& [_, record] : mRecordsByPropId) {
|
||||
for (auto const& [_, value] : record.values) {
|
||||
allValues.push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
return allValues;
|
||||
}
|
||||
|
||||
Result<std::vector<VehiclePropValue>> VehiclePropertyStore::readValuesForProperty(
|
||||
int32_t propId) const {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
std::vector<VehiclePropValue> values;
|
||||
|
||||
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
|
||||
if (record == nullptr) {
|
||||
return Errorf("property: {:d} not registered", propId);
|
||||
}
|
||||
|
||||
for (auto const& [_, value] : record->values) {
|
||||
values.push_back(value);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
Result<std::unique_ptr<VehiclePropValue>> VehiclePropertyStore::readValue(
|
||||
const VehiclePropValue& propValue) const {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
const VehiclePropertyStore::Record* record = getRecordLocked(propValue.prop);
|
||||
if (record == nullptr) {
|
||||
return Errorf("property: {:d} not registered", propValue.prop);
|
||||
}
|
||||
|
||||
VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record);
|
||||
return readValueLocked(recId, *record);
|
||||
}
|
||||
|
||||
Result<std::unique_ptr<VehiclePropValue>> VehiclePropertyStore::readValue(int32_t propId,
|
||||
int32_t areaId,
|
||||
int64_t token) const {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
|
||||
if (record == nullptr) {
|
||||
return Errorf("property: {:d} not registered", propId);
|
||||
}
|
||||
|
||||
VehiclePropertyStore::RecordId recId{.area = isGlobalProp(propId) ? 0 : areaId, .token = token};
|
||||
return readValueLocked(recId, *record);
|
||||
}
|
||||
|
||||
std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
std::vector<VehiclePropConfig> configs;
|
||||
configs.reserve(mRecordsByPropId.size());
|
||||
for (auto& [_, config] : mRecordsByPropId) {
|
||||
configs.push_back(config.propConfig);
|
||||
}
|
||||
return configs;
|
||||
}
|
||||
|
||||
Result<const VehiclePropConfig*> VehiclePropertyStore::getConfig(int32_t propId) const {
|
||||
std::lock_guard<std::mutex> g(mLock);
|
||||
|
||||
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
|
||||
if (record == nullptr) {
|
||||
return Errorf("property: {:d} not registered", propId);
|
||||
}
|
||||
|
||||
return &record->propConfig;
|
||||
}
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -22,7 +22,11 @@ cc_test {
|
||||
name: "VehicleHalVehicleUtilsTest",
|
||||
srcs: ["*.cpp"],
|
||||
vendor: true,
|
||||
static_libs: ["VehicleHalUtils"],
|
||||
static_libs: [
|
||||
"VehicleHalUtils",
|
||||
"libgtest",
|
||||
"libgmock",
|
||||
],
|
||||
defaults: ["VehicleHalDefaults"],
|
||||
test_suites: ["general-tests"],
|
||||
}
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <PropertyUtils.h>
|
||||
#include <VehiclePropertyStore.h>
|
||||
#include <VehicleUtils.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace automotive {
|
||||
namespace vehicle {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
|
||||
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
|
||||
using ::android::base::Result;
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::Eq;
|
||||
using ::testing::WhenSortedBy;
|
||||
|
||||
constexpr int INVALID_PROP_ID = 0;
|
||||
|
||||
struct PropValueCmp {
|
||||
bool operator()(const VehiclePropValue& a, const VehiclePropValue& b) const {
|
||||
return (a.prop < b.prop) || ((a.prop == b.prop) && (a.value < b.value)) ||
|
||||
((a.prop == b.prop) && (a.value == b.value) && (a.areaId < b.areaId));
|
||||
}
|
||||
} propValueCmp;
|
||||
|
||||
int64_t timestampToken(const VehiclePropValue& value) {
|
||||
return value.timestamp;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class VehiclePropertyStoreTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
mConfigFuelCapacity = {
|
||||
.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
|
||||
.access = VehiclePropertyAccess::READ,
|
||||
.changeMode = VehiclePropertyChangeMode::STATIC,
|
||||
};
|
||||
VehiclePropConfig configTirePressure = {
|
||||
.prop = toInt(VehicleProperty::TIRE_PRESSURE),
|
||||
.access = VehiclePropertyAccess::READ,
|
||||
.changeMode = VehiclePropertyChangeMode::CONTINUOUS,
|
||||
.areaConfigs = {VehicleAreaConfig{.areaId = WHEEL_FRONT_LEFT},
|
||||
VehicleAreaConfig{.areaId = WHEEL_FRONT_RIGHT},
|
||||
VehicleAreaConfig{.areaId = WHEEL_REAR_LEFT},
|
||||
VehicleAreaConfig{.areaId = WHEEL_REAR_RIGHT}},
|
||||
};
|
||||
mStore.registerProperty(mConfigFuelCapacity);
|
||||
mStore.registerProperty(configTirePressure);
|
||||
}
|
||||
|
||||
VehiclePropertyStore mStore;
|
||||
VehiclePropConfig mConfigFuelCapacity;
|
||||
};
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testGetAllConfigs) {
|
||||
std::vector<VehiclePropConfig> configs = mStore.getAllConfigs();
|
||||
|
||||
ASSERT_EQ(configs.size(), static_cast<size_t>(2));
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testGetConfig) {
|
||||
Result<const VehiclePropConfig*> result =
|
||||
mStore.getConfig(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
|
||||
|
||||
ASSERT_RESULT_OK(result);
|
||||
ASSERT_EQ(*(result.value()), mConfigFuelCapacity);
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testGetConfigWithInvalidPropId) {
|
||||
Result<const VehiclePropConfig*> result = mStore.getConfig(INVALID_PROP_ID);
|
||||
|
||||
ASSERT_FALSE(result.ok()) << "expect error when getting a config for an invalid property ID";
|
||||
}
|
||||
|
||||
std::vector<VehiclePropValue> getTestPropValues() {
|
||||
VehiclePropValue fuelCapacity = {
|
||||
.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
|
||||
.value = {.floatValues = {1.0}},
|
||||
};
|
||||
|
||||
VehiclePropValue leftTirePressure = {
|
||||
.prop = toInt(VehicleProperty::TIRE_PRESSURE),
|
||||
.value = {.floatValues = {170.0}},
|
||||
.areaId = WHEEL_FRONT_LEFT,
|
||||
};
|
||||
|
||||
VehiclePropValue rightTirePressure = {
|
||||
.prop = toInt(VehicleProperty::TIRE_PRESSURE),
|
||||
.value = {.floatValues = {180.0}},
|
||||
.areaId = WHEEL_FRONT_RIGHT,
|
||||
};
|
||||
|
||||
return {fuelCapacity, leftTirePressure, rightTirePressure};
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testWriteValueOk) {
|
||||
auto values = getTestPropValues();
|
||||
|
||||
ASSERT_RESULT_OK(mStore.writeValue(values[0]));
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testReadAllValues) {
|
||||
auto values = getTestPropValues();
|
||||
for (const auto& value : values) {
|
||||
ASSERT_RESULT_OK(mStore.writeValue(value));
|
||||
}
|
||||
|
||||
auto gotValues = mStore.readAllValues();
|
||||
|
||||
ASSERT_THAT(gotValues, WhenSortedBy(propValueCmp, Eq(values)));
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyOneValue) {
|
||||
auto values = getTestPropValues();
|
||||
for (const auto& value : values) {
|
||||
ASSERT_RESULT_OK(mStore.writeValue(value));
|
||||
}
|
||||
|
||||
auto result = mStore.readValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
|
||||
|
||||
ASSERT_RESULT_OK(result);
|
||||
ASSERT_THAT(result.value(), ElementsAre(values[0]));
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyMultipleValues) {
|
||||
auto values = getTestPropValues();
|
||||
for (const auto& value : values) {
|
||||
ASSERT_RESULT_OK(mStore.writeValue(value));
|
||||
}
|
||||
|
||||
auto result = mStore.readValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE));
|
||||
|
||||
ASSERT_RESULT_OK(result);
|
||||
ASSERT_THAT(result.value(), WhenSortedBy(propValueCmp, ElementsAre(values[1], values[2])));
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyError) {
|
||||
auto result = mStore.readValuesForProperty(INVALID_PROP_ID);
|
||||
|
||||
ASSERT_FALSE(result.ok()) << "expect error when reading values for an invalid property";
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testReadValueOk) {
|
||||
auto values = getTestPropValues();
|
||||
for (const auto& value : values) {
|
||||
ASSERT_RESULT_OK(mStore.writeValue(value));
|
||||
}
|
||||
|
||||
VehiclePropValue requestValue = {
|
||||
.prop = toInt(VehicleProperty::TIRE_PRESSURE),
|
||||
.areaId = WHEEL_FRONT_LEFT,
|
||||
};
|
||||
|
||||
auto result = mStore.readValue(requestValue);
|
||||
|
||||
ASSERT_RESULT_OK(result);
|
||||
ASSERT_EQ(*(result.value()), values[1]);
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testReadValueByPropIdOk) {
|
||||
auto values = getTestPropValues();
|
||||
for (const auto& value : values) {
|
||||
ASSERT_RESULT_OK(mStore.writeValue(value));
|
||||
}
|
||||
|
||||
auto result = mStore.readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_FRONT_RIGHT);
|
||||
|
||||
ASSERT_EQ(*(result.value()), values[2]);
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testReadValueError) {
|
||||
auto values = getTestPropValues();
|
||||
for (const auto& value : values) {
|
||||
ASSERT_RESULT_OK(mStore.writeValue(value));
|
||||
}
|
||||
|
||||
auto result = mStore.readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_REAR_LEFT);
|
||||
|
||||
ASSERT_FALSE(result.ok()) << "expect error when reading a value that has not been written";
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testWriteValueError) {
|
||||
ASSERT_FALSE(mStore.writeValue({
|
||||
.prop = INVALID_PROP_ID,
|
||||
.value = {.floatValues = {1.0}},
|
||||
})
|
||||
.ok())
|
||||
<< "expect error when writing value for an invalid property ID";
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testWriteValueNoAreaConfig) {
|
||||
ASSERT_FALSE(mStore.writeValue({
|
||||
.prop = toInt(VehicleProperty::TIRE_PRESSURE),
|
||||
.value = {.floatValues = {180.0}},
|
||||
// There is no config for ALL_WHEELS.
|
||||
.areaId = ALL_WHEELS,
|
||||
})
|
||||
.ok())
|
||||
<< "expect error when writing value for an area without config";
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testWriteOutdatedValue) {
|
||||
ASSERT_RESULT_OK(mStore.writeValue({
|
||||
.timestamp = 1,
|
||||
.prop = toInt(VehicleProperty::TIRE_PRESSURE),
|
||||
.value = {.floatValues = {180.0}},
|
||||
.areaId = WHEEL_FRONT_LEFT,
|
||||
}));
|
||||
|
||||
// Write an older value.
|
||||
ASSERT_FALSE(mStore.writeValue({
|
||||
.timestamp = 0,
|
||||
.prop = toInt(VehicleProperty::TIRE_PRESSURE),
|
||||
.value = {.floatValues = {180.0}},
|
||||
.areaId = WHEEL_FRONT_LEFT,
|
||||
})
|
||||
.ok())
|
||||
<< "expect error when writing an outdated value";
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testToken) {
|
||||
int propId = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
|
||||
VehiclePropConfig config = {
|
||||
.prop = propId,
|
||||
};
|
||||
|
||||
// Replace existing config.
|
||||
mStore.registerProperty(config, timestampToken);
|
||||
|
||||
VehiclePropValue fuelCapacityValueToken1 = {
|
||||
.timestamp = 1,
|
||||
.prop = propId,
|
||||
.value = {.floatValues = {1.0}},
|
||||
};
|
||||
|
||||
VehiclePropValue fuelCapacityValueToken2 = {
|
||||
.timestamp = 2,
|
||||
.prop = propId,
|
||||
.value = {.floatValues = {2.0}},
|
||||
};
|
||||
|
||||
ASSERT_RESULT_OK(mStore.writeValue(fuelCapacityValueToken1));
|
||||
ASSERT_RESULT_OK(mStore.writeValue(fuelCapacityValueToken2));
|
||||
|
||||
auto result = mStore.readValuesForProperty(propId);
|
||||
|
||||
ASSERT_RESULT_OK(result);
|
||||
ASSERT_EQ(result.value().size(), static_cast<size_t>(2));
|
||||
|
||||
auto tokenResult = mStore.readValue(propId, /*areaId=*/0, /*token=*/2);
|
||||
|
||||
ASSERT_RESULT_OK(tokenResult);
|
||||
ASSERT_EQ(*(tokenResult.value()), fuelCapacityValueToken2);
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testRemoveValue) {
|
||||
auto values = getTestPropValues();
|
||||
for (const auto& value : values) {
|
||||
ASSERT_RESULT_OK(mStore.writeValue(value));
|
||||
}
|
||||
|
||||
mStore.removeValue(values[0]);
|
||||
|
||||
ASSERT_FALSE(mStore.readValue(values[0]).ok()) << "expect error when reading a removed value";
|
||||
|
||||
auto leftTirePressureResult = mStore.readValue(values[1]);
|
||||
|
||||
ASSERT_RESULT_OK(leftTirePressureResult);
|
||||
ASSERT_EQ(*(leftTirePressureResult.value()), values[1]);
|
||||
}
|
||||
|
||||
TEST_F(VehiclePropertyStoreTest, testRemoveValuesForProperty) {
|
||||
auto values = getTestPropValues();
|
||||
for (const auto& value : values) {
|
||||
ASSERT_RESULT_OK(mStore.writeValue(value));
|
||||
}
|
||||
|
||||
mStore.removeValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
|
||||
mStore.removeValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE));
|
||||
|
||||
auto gotValues = mStore.readAllValues();
|
||||
ASSERT_TRUE(gotValues.empty());
|
||||
}
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
Reference in New Issue
Block a user