835 lines
29 KiB
C++
835 lines
29 KiB
C++
//
|
|
// Copyright (C) 2012 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 "shill/property_store.h"
|
|
|
|
#include "shill/property_store_unittest.h"
|
|
|
|
#include <map>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <base/macros.h>
|
|
#if defined(__ANDROID__)
|
|
#include <dbus/service_constants.h>
|
|
#else
|
|
#include <chromeos/dbus/service_constants.h>
|
|
#endif // __ANDROID__
|
|
#include <gtest/gtest.h>
|
|
#include <gmock/gmock.h>
|
|
|
|
#include "shill/error.h"
|
|
#include "shill/event_dispatcher.h"
|
|
#include "shill/manager.h"
|
|
#include "shill/mock_control.h"
|
|
#include "shill/property_accessor.h"
|
|
|
|
using base::Bind;
|
|
using base::Unretained;
|
|
using std::map;
|
|
using std::string;
|
|
using std::vector;
|
|
using ::testing::_;
|
|
using ::testing::Return;
|
|
using ::testing::Values;
|
|
|
|
namespace shill {
|
|
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kBoolV = brillo::Any(false);
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kByteV =
|
|
brillo::Any(uint8_t(0));
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kInt16V = brillo::Any(int16_t(0));
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kInt32V = brillo::Any(int32_t(0));
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kKeyValueStoreV =
|
|
brillo::Any(brillo::VariantDictionary());
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kStringV = brillo::Any(string());
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kStringmapV = brillo::Any(Stringmap());
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kStringmapsV =
|
|
brillo::Any(Stringmaps());
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kStringsV = brillo::Any(Strings());
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kUint16V = brillo::Any(uint16_t(0));
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kUint16sV = brillo::Any(Uint16s());
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kUint32V = brillo::Any(uint32_t(0));
|
|
// static
|
|
const brillo::Any PropertyStoreTest::kUint64V = brillo::Any(uint64_t(0));
|
|
|
|
PropertyStoreTest::PropertyStoreTest()
|
|
: internal_error_(kErrorResultInternalError),
|
|
invalid_args_(kErrorResultInvalidArguments),
|
|
invalid_prop_(kErrorResultInvalidProperty),
|
|
path_(dir_.CreateUniqueTempDir() ? dir_.path().value() : ""),
|
|
metrics_(dispatcher()),
|
|
default_technology_order_{Technology::kVPN,
|
|
Technology::kEthernet,
|
|
Technology::kWifi,
|
|
Technology::kWiMax,
|
|
Technology::kCellular},
|
|
manager_(control_interface(),
|
|
dispatcher(),
|
|
metrics(),
|
|
run_path(),
|
|
storage_path(),
|
|
string()) {
|
|
}
|
|
|
|
PropertyStoreTest::~PropertyStoreTest() {}
|
|
|
|
void PropertyStoreTest::SetUp() {
|
|
ASSERT_FALSE(run_path().empty());
|
|
ASSERT_FALSE(storage_path().empty());
|
|
}
|
|
|
|
TEST_P(PropertyStoreTest, SetPropertyNonexistent) {
|
|
// Ensure that an attempt to write unknown properties returns
|
|
// InvalidProperty, and does not yield a PropertyChange callback.
|
|
PropertyStore store(Bind(&PropertyStoreTest::TestCallback,
|
|
Unretained(this)));
|
|
Error error;
|
|
EXPECT_CALL(*this, TestCallback(_)).Times(0);
|
|
EXPECT_FALSE(store.SetAnyProperty("", GetParam(), &error));
|
|
EXPECT_EQ(Error::kInvalidProperty, error.type());
|
|
}
|
|
|
|
INSTANTIATE_TEST_CASE_P(
|
|
PropertyStoreTestInstance,
|
|
PropertyStoreTest,
|
|
Values(PropertyStoreTest::kBoolV,
|
|
PropertyStoreTest::kByteV,
|
|
PropertyStoreTest::kInt16V,
|
|
PropertyStoreTest::kInt32V,
|
|
PropertyStoreTest::kStringV,
|
|
PropertyStoreTest::kStringmapV,
|
|
PropertyStoreTest::kStringsV,
|
|
PropertyStoreTest::kUint16V,
|
|
PropertyStoreTest::kUint16sV,
|
|
PropertyStoreTest::kUint32V,
|
|
PropertyStoreTest::kUint64V));
|
|
|
|
template <typename T>
|
|
class PropertyStoreTypedTest : public PropertyStoreTest {
|
|
protected:
|
|
bool SetProperty(
|
|
PropertyStore* store, const string& name, Error* error);
|
|
};
|
|
|
|
TYPED_TEST_CASE(PropertyStoreTypedTest, PropertyStoreTest::PropertyTypes);
|
|
|
|
TYPED_TEST(PropertyStoreTypedTest, RegisterProperty) {
|
|
PropertyStore store(Bind(&PropertyStoreTest::TestCallback,
|
|
Unretained(this)));
|
|
Error error;
|
|
TypeParam property;
|
|
PropertyStoreTest::RegisterProperty(&store, "some property", &property);
|
|
EXPECT_TRUE(store.Contains("some property"));
|
|
}
|
|
|
|
TYPED_TEST(PropertyStoreTypedTest, GetProperty) {
|
|
PropertyStore store(Bind(&PropertyStoreTest::TestCallback,
|
|
Unretained(this)));
|
|
Error error;
|
|
TypeParam property{}; // value-initialize primitives
|
|
PropertyStoreTest::RegisterProperty(&store, "some property", &property);
|
|
|
|
TypeParam read_value;
|
|
EXPECT_CALL(*this, TestCallback(_)).Times(0);
|
|
EXPECT_TRUE(PropertyStoreTest::GetProperty(
|
|
store, "some property", &read_value, &error));
|
|
EXPECT_EQ(property, read_value);
|
|
}
|
|
|
|
TYPED_TEST(PropertyStoreTypedTest, ClearProperty) {
|
|
PropertyStore store(Bind(&PropertyStoreTest::TestCallback,
|
|
Unretained(this)));
|
|
Error error;
|
|
TypeParam property;
|
|
PropertyStoreTest::RegisterProperty(&store, "some property", &property);
|
|
EXPECT_CALL(*this, TestCallback(_));
|
|
EXPECT_TRUE(store.ClearProperty("some property", &error));
|
|
}
|
|
|
|
TYPED_TEST(PropertyStoreTypedTest, SetProperty) {
|
|
PropertyStore store(Bind(&PropertyStoreTest::TestCallback,
|
|
Unretained(this)));
|
|
Error error;
|
|
TypeParam property{}; // value-initialize primitives
|
|
PropertyStoreTest::RegisterProperty(&store, "some property", &property);
|
|
|
|
// Change the value from the default (initialized above). Should
|
|
// generate a change callback. The second SetProperty, however,
|
|
// should not. Hence, we should get exactly one callback.
|
|
EXPECT_CALL(*this, TestCallback(_)).Times(1);
|
|
EXPECT_TRUE(this->SetProperty(&store, "some property", &error));
|
|
EXPECT_FALSE(this->SetProperty(&store, "some property", &error));
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<bool>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
bool new_value = true;
|
|
return store->SetBoolProperty(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<int16_t>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
int16_t new_value = 1;
|
|
return store->SetInt16Property(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<int32_t>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
int32_t new_value = 1;
|
|
return store->SetInt32Property(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<string>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
string new_value = "new value";
|
|
return store->SetStringProperty(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<Stringmap>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
Stringmap new_value;
|
|
new_value["new key"] = "new value";
|
|
return store->SetStringmapProperty(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<Stringmaps>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
Stringmaps new_value(1);
|
|
new_value[0]["new key"] = "new value";
|
|
return store->SetStringmapsProperty(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<Strings>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
Strings new_value(1);
|
|
new_value[0] = "new value";
|
|
return store->SetStringsProperty(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<uint8_t>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
uint8_t new_value = 1;
|
|
return store->SetUint8Property(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<uint16_t>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
uint16_t new_value = 1;
|
|
return store->SetUint16Property(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<Uint16s>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
Uint16s new_value{1};
|
|
return store->SetUint16sProperty(name, new_value, error);
|
|
}
|
|
|
|
template<> bool PropertyStoreTypedTest<uint32_t>::SetProperty(
|
|
PropertyStore* store, const string& name, Error* error) {
|
|
uint32_t new_value = 1;
|
|
return store->SetUint32Property(name, new_value, error);
|
|
}
|
|
|
|
TEST_F(PropertyStoreTest, ClearBoolProperty) {
|
|
// We exercise both possibilities for the default value here,
|
|
// to ensure that Clear actually resets the property based on
|
|
// the property's initial value (rather than the language's
|
|
// default value for the type).
|
|
static const bool kDefaults[] = {true, false};
|
|
for (size_t i = 0; i < arraysize(kDefaults); ++i) {
|
|
PropertyStore store;
|
|
Error error;
|
|
|
|
const bool default_value = kDefaults[i];
|
|
bool flag = default_value;
|
|
store.RegisterBool("some bool", &flag);
|
|
|
|
EXPECT_TRUE(store.ClearProperty("some bool", &error));
|
|
EXPECT_EQ(default_value, flag);
|
|
}
|
|
}
|
|
|
|
TEST_F(PropertyStoreTest, ClearPropertyNonexistent) {
|
|
PropertyStore store(Bind(&PropertyStoreTest::TestCallback,
|
|
Unretained(this)));
|
|
Error error;
|
|
|
|
EXPECT_CALL(*this, TestCallback(_)).Times(0);
|
|
EXPECT_FALSE(store.ClearProperty("", &error));
|
|
EXPECT_EQ(Error::kInvalidProperty, error.type());
|
|
}
|
|
|
|
// Separate from SetPropertyNonexistent, because
|
|
// SetAnyProperty doesn't support Stringmaps.
|
|
TEST_F(PropertyStoreTest, SetStringmapsProperty) {
|
|
PropertyStore store(Bind(&PropertyStoreTest::TestCallback,
|
|
Unretained(this)));
|
|
|
|
Error error;
|
|
EXPECT_CALL(*this, TestCallback(_)).Times(0);
|
|
EXPECT_FALSE(store.SetAnyProperty(
|
|
"", PropertyStoreTest::kStringmapsV, &error));
|
|
EXPECT_EQ(Error::kInternalError, error.type());
|
|
}
|
|
|
|
// KeyValueStoreProperty is only defined for derived types so handle
|
|
// this case manually here.
|
|
TEST_F(PropertyStoreTest, KeyValueStorePropertyNonExistent) {
|
|
PropertyStore store(Bind(&PropertyStoreTest::TestCallback,
|
|
Unretained(this)));
|
|
Error error;
|
|
EXPECT_CALL(*this, TestCallback(_)).Times(0);
|
|
EXPECT_FALSE(store.SetAnyProperty(
|
|
"", PropertyStoreTest::kKeyValueStoreV, &error));
|
|
EXPECT_EQ(Error::kInvalidProperty, error.type());
|
|
}
|
|
|
|
TEST_F(PropertyStoreTest, KeyValueStoreProperty) {
|
|
PropertyStore store(Bind(&PropertyStoreTest::TestCallback,
|
|
Unretained(this)));
|
|
const char kKey[] = "key";
|
|
EXPECT_CALL(*this, GetKeyValueStoreCallback(_))
|
|
.WillOnce(Return(KeyValueStore()));
|
|
store.RegisterDerivedKeyValueStore(
|
|
kKey,
|
|
KeyValueStoreAccessor(
|
|
new CustomAccessor<PropertyStoreTest, KeyValueStore>(
|
|
this, &PropertyStoreTest::GetKeyValueStoreCallback,
|
|
&PropertyStoreTest::SetKeyValueStoreCallback)));
|
|
EXPECT_CALL(*this, TestCallback(_));
|
|
EXPECT_CALL(*this, SetKeyValueStoreCallback(_, _)).WillOnce(Return(true));
|
|
Error error;
|
|
EXPECT_TRUE(store.SetAnyProperty(kKey, kKeyValueStoreV, &error));
|
|
}
|
|
|
|
TEST_F(PropertyStoreTest, WriteOnlyProperties) {
|
|
// Test that properties registered as write-only are not returned
|
|
// when using Get*PropertiesIter().
|
|
PropertyStore store;
|
|
{
|
|
const string keys[] = {"boolp1", "boolp2"};
|
|
bool values[] = {true, true};
|
|
store.RegisterWriteOnlyBool(keys[0], &values[0]);
|
|
store.RegisterBool(keys[1], &values[1]);
|
|
|
|
ReadablePropertyConstIterator<bool> it = store.GetBoolPropertiesIter();
|
|
EXPECT_FALSE(it.AtEnd());
|
|
EXPECT_EQ(keys[1], it.Key());
|
|
EXPECT_TRUE(values[1] == it.value());
|
|
it.Advance();
|
|
EXPECT_TRUE(it.AtEnd());
|
|
|
|
Error errors[2];
|
|
EXPECT_FALSE(store.GetBoolProperty(keys[0], nullptr, &errors[0]));
|
|
EXPECT_EQ(Error::kPermissionDenied, errors[0].type());
|
|
bool test_value;
|
|
EXPECT_TRUE(store.GetBoolProperty(keys[1], &test_value, &errors[1]));
|
|
EXPECT_TRUE(errors[1].IsSuccess());
|
|
EXPECT_EQ(values[1], test_value);
|
|
}
|
|
{
|
|
const string keys[] = {"int16p1", "int16p2"};
|
|
int16_t values[] = {127, 128};
|
|
store.RegisterWriteOnlyInt16(keys[0], &values[0]);
|
|
store.RegisterInt16(keys[1], &values[1]);
|
|
|
|
ReadablePropertyConstIterator<int16_t> it = store.GetInt16PropertiesIter();
|
|
EXPECT_FALSE(it.AtEnd());
|
|
EXPECT_EQ(keys[1], it.Key());
|
|
EXPECT_EQ(values[1], it.value());
|
|
it.Advance();
|
|
EXPECT_TRUE(it.AtEnd());
|
|
|
|
Error errors[2];
|
|
EXPECT_FALSE(store.GetInt16Property(keys[0], nullptr, &errors[0]));
|
|
EXPECT_EQ(Error::kPermissionDenied, errors[0].type());
|
|
int16_t test_value;
|
|
EXPECT_TRUE(store.GetInt16Property(keys[1], &test_value, &errors[1]));
|
|
EXPECT_TRUE(errors[1].IsSuccess());
|
|
EXPECT_EQ(values[1], test_value);
|
|
}
|
|
{
|
|
const string keys[] = {"int32p1", "int32p2"};
|
|
int32_t values[] = {127, 128};
|
|
store.RegisterWriteOnlyInt32(keys[0], &values[0]);
|
|
store.RegisterInt32(keys[1], &values[1]);
|
|
|
|
ReadablePropertyConstIterator<int32_t> it = store.GetInt32PropertiesIter();
|
|
EXPECT_FALSE(it.AtEnd());
|
|
EXPECT_EQ(keys[1], it.Key());
|
|
EXPECT_EQ(values[1], it.value());
|
|
it.Advance();
|
|
EXPECT_TRUE(it.AtEnd());
|
|
|
|
Error errors[2];
|
|
EXPECT_FALSE(store.GetInt32Property(keys[0], nullptr, &errors[0]));
|
|
EXPECT_EQ(Error::kPermissionDenied, errors[0].type());
|
|
int32_t test_value;
|
|
EXPECT_TRUE(store.GetInt32Property(keys[1], &test_value, &errors[1]));
|
|
EXPECT_TRUE(errors[1].IsSuccess());
|
|
EXPECT_EQ(values[1], test_value);
|
|
}
|
|
{
|
|
const string keys[] = {"stringp1", "stringp2"};
|
|
string values[] = {"noooo", "yesss"};
|
|
store.RegisterWriteOnlyString(keys[0], &values[0]);
|
|
store.RegisterString(keys[1], &values[1]);
|
|
|
|
ReadablePropertyConstIterator<string> it = store.GetStringPropertiesIter();
|
|
EXPECT_FALSE(it.AtEnd());
|
|
EXPECT_EQ(keys[1], it.Key());
|
|
EXPECT_EQ(values[1], it.value());
|
|
it.Advance();
|
|
EXPECT_TRUE(it.AtEnd());
|
|
|
|
Error errors[2];
|
|
EXPECT_FALSE(store.GetStringProperty(keys[0], nullptr, &errors[0]));
|
|
EXPECT_EQ(Error::kPermissionDenied, errors[0].type());
|
|
string test_value;
|
|
EXPECT_TRUE(store.GetStringProperty(keys[1], &test_value, &errors[1]));
|
|
EXPECT_TRUE(errors[1].IsSuccess());
|
|
EXPECT_EQ(values[1], test_value);
|
|
}
|
|
{
|
|
const string keys[] = {"stringmapp1", "stringmapp2"};
|
|
Stringmap values[2];
|
|
values[0]["noooo"] = "yesss";
|
|
values[1]["yesss"] = "noooo";
|
|
store.RegisterWriteOnlyStringmap(keys[0], &values[0]);
|
|
store.RegisterStringmap(keys[1], &values[1]);
|
|
|
|
ReadablePropertyConstIterator<Stringmap> it =
|
|
store.GetStringmapPropertiesIter();
|
|
EXPECT_FALSE(it.AtEnd());
|
|
EXPECT_EQ(keys[1], it.Key());
|
|
EXPECT_TRUE(values[1] == it.value());
|
|
it.Advance();
|
|
EXPECT_TRUE(it.AtEnd());
|
|
|
|
Error errors[2];
|
|
EXPECT_FALSE(store.GetStringmapProperty(keys[0], nullptr, &errors[0]));
|
|
EXPECT_EQ(Error::kPermissionDenied, errors[0].type());
|
|
Stringmap test_value;
|
|
EXPECT_TRUE(store.GetStringmapProperty(keys[1], &test_value, &errors[1]));
|
|
EXPECT_TRUE(errors[1].IsSuccess());
|
|
EXPECT_TRUE(values[1] == test_value);
|
|
}
|
|
{
|
|
const string keys[] = {"stringmapsp1", "stringmapsp2"};
|
|
Stringmaps values[2];
|
|
Stringmap element;
|
|
element["noooo"] = "yesss";
|
|
values[0].push_back(element);
|
|
element["yesss"] = "noooo";
|
|
values[1].push_back(element);
|
|
|
|
store.RegisterWriteOnlyStringmaps(keys[0], &values[0]);
|
|
store.RegisterStringmaps(keys[1], &values[1]);
|
|
|
|
ReadablePropertyConstIterator<Stringmaps> it =
|
|
store.GetStringmapsPropertiesIter();
|
|
EXPECT_FALSE(it.AtEnd());
|
|
EXPECT_EQ(keys[1], it.Key());
|
|
EXPECT_TRUE(values[1] == it.value());
|
|
it.Advance();
|
|
EXPECT_TRUE(it.AtEnd());
|
|
|
|
Error errors[2];
|
|
EXPECT_FALSE(store.GetStringmapsProperty(keys[0], nullptr, &errors[0]));
|
|
EXPECT_EQ(Error::kPermissionDenied, errors[0].type());
|
|
Stringmaps test_value;
|
|
EXPECT_TRUE(store.GetStringmapsProperty(keys[1], &test_value, &errors[1]));
|
|
EXPECT_TRUE(errors[1].IsSuccess());
|
|
EXPECT_TRUE(values[1] == test_value);
|
|
}
|
|
{
|
|
const string keys[] = {"stringsp1", "stringsp2"};
|
|
Strings values[2];
|
|
string element;
|
|
element = "noooo";
|
|
values[0].push_back(element);
|
|
element = "yesss";
|
|
values[1].push_back(element);
|
|
store.RegisterWriteOnlyStrings(keys[0], &values[0]);
|
|
store.RegisterStrings(keys[1], &values[1]);
|
|
|
|
ReadablePropertyConstIterator<Strings> it =
|
|
store.GetStringsPropertiesIter();
|
|
EXPECT_FALSE(it.AtEnd());
|
|
EXPECT_EQ(keys[1], it.Key());
|
|
EXPECT_TRUE(values[1] == it.value());
|
|
it.Advance();
|
|
EXPECT_TRUE(it.AtEnd());
|
|
|
|
Error errors[2];
|
|
EXPECT_FALSE(store.GetStringsProperty(keys[0], nullptr, &errors[0]));
|
|
EXPECT_EQ(Error::kPermissionDenied, errors[0].type());
|
|
Strings test_value;
|
|
EXPECT_TRUE(store.GetStringsProperty(keys[1], &test_value, &errors[1]));
|
|
EXPECT_TRUE(errors[1].IsSuccess());
|
|
EXPECT_TRUE(values[1] == test_value);
|
|
}
|
|
{
|
|
const string keys[] = {"uint8p1", "uint8p2"};
|
|
uint8_t values[] = {127, 128};
|
|
store.RegisterWriteOnlyUint8(keys[0], &values[0]);
|
|
store.RegisterUint8(keys[1], &values[1]);
|
|
|
|
ReadablePropertyConstIterator<uint8_t> it = store.GetUint8PropertiesIter();
|
|
EXPECT_FALSE(it.AtEnd());
|
|
EXPECT_EQ(keys[1], it.Key());
|
|
EXPECT_EQ(values[1], it.value());
|
|
it.Advance();
|
|
EXPECT_TRUE(it.AtEnd());
|
|
|
|
Error errors[2];
|
|
EXPECT_FALSE(store.GetUint8Property(keys[0], nullptr, &errors[0]));
|
|
EXPECT_EQ(Error::kPermissionDenied, errors[0].type());
|
|
uint8_t test_value;
|
|
EXPECT_TRUE(store.GetUint8Property(keys[1], &test_value, &errors[1]));
|
|
EXPECT_TRUE(errors[1].IsSuccess());
|
|
EXPECT_EQ(values[1], test_value);
|
|
}
|
|
{
|
|
const string keys[] = {"uint16p", "uint16p1"};
|
|
uint16_t values[] = {127, 128};
|
|
store.RegisterWriteOnlyUint16(keys[0], &values[0]);
|
|
store.RegisterUint16(keys[1], &values[1]);
|
|
|
|
ReadablePropertyConstIterator<uint16_t> it =
|
|
store.GetUint16PropertiesIter();
|
|
EXPECT_FALSE(it.AtEnd());
|
|
EXPECT_EQ(keys[1], it.Key());
|
|
EXPECT_EQ(values[1], it.value());
|
|
it.Advance();
|
|
EXPECT_TRUE(it.AtEnd());
|
|
|
|
Error errors[2];
|
|
EXPECT_FALSE(store.GetUint16Property(keys[0], nullptr, &errors[0]));
|
|
EXPECT_EQ(Error::kPermissionDenied, errors[0].type());
|
|
uint16_t test_value;
|
|
EXPECT_TRUE(store.GetUint16Property(keys[1], &test_value, &errors[1]));
|
|
EXPECT_TRUE(errors[1].IsSuccess());
|
|
EXPECT_EQ(values[1], test_value);
|
|
}
|
|
}
|
|
|
|
TEST_F(PropertyStoreTest, SetAnyProperty) {
|
|
// Test that registered properties can be set using brillo::Any variant
|
|
// type.
|
|
PropertyStore store;
|
|
{
|
|
// Register property value.
|
|
const string key = "boolp";
|
|
bool value = true;
|
|
store.RegisterBool(key, &value);
|
|
|
|
// Verify property value.
|
|
bool test_value;
|
|
Error error;
|
|
EXPECT_TRUE(store.GetBoolProperty(key, &test_value, &error));
|
|
EXPECT_EQ(value, test_value);
|
|
|
|
// Set property using brillo::Any variant type.
|
|
bool new_value = false;
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(new_value), &error));
|
|
EXPECT_TRUE(store.GetBoolProperty(key, &test_value, &error));
|
|
EXPECT_EQ(new_value, test_value);
|
|
}
|
|
{
|
|
// Register property value.
|
|
const string key = "int16p";
|
|
int16_t value = 127;
|
|
store.RegisterInt16(key, &value);
|
|
|
|
// Verify property value.
|
|
int16_t test_value;
|
|
Error error;
|
|
EXPECT_TRUE(store.GetInt16Property(key, &test_value, &error));
|
|
EXPECT_EQ(value, test_value);
|
|
|
|
// Set property using brillo::Any variant type.
|
|
int16_t new_value = 128;
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(new_value), &error));
|
|
EXPECT_TRUE(store.GetInt16Property(key, &test_value, &error));
|
|
EXPECT_EQ(new_value, test_value);
|
|
}
|
|
{
|
|
// Register property value.
|
|
const string key = "int32p";
|
|
int32_t value = 127;
|
|
store.RegisterInt32(key, &value);
|
|
|
|
// Verify property value.
|
|
int32_t test_value;
|
|
Error error;
|
|
EXPECT_TRUE(store.GetInt32Property(key, &test_value, &error));
|
|
EXPECT_EQ(value, test_value);
|
|
|
|
// Set property using brillo::Any variant type.
|
|
int32_t new_value = 128;
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(new_value), &error));
|
|
EXPECT_TRUE(store.GetInt32Property(key, &test_value, &error));
|
|
EXPECT_EQ(new_value, test_value);
|
|
}
|
|
{
|
|
// Register property value.
|
|
const string key = "stringp";
|
|
string value = "noooo";
|
|
store.RegisterString(key, &value);
|
|
|
|
// Verify property value.
|
|
string test_value;
|
|
Error error;
|
|
EXPECT_TRUE(store.GetStringProperty(key, &test_value, &error));
|
|
EXPECT_EQ(value, test_value);
|
|
|
|
// Set property using brillo::Any variant type.
|
|
string new_value = "yesss";
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(new_value), &error));
|
|
EXPECT_TRUE(store.GetStringProperty(key, &test_value, &error));
|
|
EXPECT_EQ(new_value, test_value);
|
|
}
|
|
{
|
|
// Register property value.
|
|
const string key = "stringmapp";
|
|
Stringmap value;
|
|
value["noooo"] = "yesss";
|
|
store.RegisterStringmap(key, &value);
|
|
|
|
// Verify property value.
|
|
Stringmap test_value;
|
|
Error error;
|
|
EXPECT_TRUE(store.GetStringmapProperty(key, &test_value, &error));
|
|
EXPECT_TRUE(value == test_value);
|
|
|
|
// Set property using brillo::Any variant type.
|
|
Stringmap new_value;
|
|
new_value["yesss"] = "noooo";
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(new_value), &error));
|
|
EXPECT_TRUE(store.GetStringmapProperty(key, &test_value, &error));
|
|
EXPECT_TRUE(new_value == test_value);
|
|
}
|
|
{
|
|
// Register property value.
|
|
const string key = "stringsp";
|
|
Strings value;
|
|
string element;
|
|
element = "noooo";
|
|
value.push_back(element);
|
|
store.RegisterStrings(key, &value);
|
|
|
|
// Verify property value.
|
|
Strings test_value;
|
|
Error error;
|
|
EXPECT_TRUE(store.GetStringsProperty(key, &test_value, &error));
|
|
EXPECT_TRUE(value == test_value);
|
|
|
|
// Set property using brillo::Any variant type.
|
|
Strings new_value;
|
|
string new_element;
|
|
new_element = "yesss";
|
|
new_value.push_back(new_element);
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(new_value), &error));
|
|
EXPECT_TRUE(store.GetStringsProperty(key, &test_value, &error));
|
|
EXPECT_TRUE(new_value == test_value);
|
|
}
|
|
{
|
|
// Register property value.
|
|
const string key = "uint8p";
|
|
uint8_t value = 127;
|
|
store.RegisterUint8(key, &value);
|
|
|
|
// Verify property value.
|
|
uint8_t test_value;
|
|
Error error;
|
|
EXPECT_TRUE(store.GetUint8Property(key, &test_value, &error));
|
|
EXPECT_EQ(value, test_value);
|
|
|
|
// Set property using brillo::Any variant type.
|
|
uint8_t new_value = 128;
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(new_value), &error));
|
|
EXPECT_TRUE(store.GetUint8Property(key, &test_value, &error));
|
|
EXPECT_EQ(new_value, test_value);
|
|
}
|
|
{
|
|
// Register property value.
|
|
const string key = "uint16p";
|
|
uint16_t value = 127;
|
|
store.RegisterUint16(key, &value);
|
|
|
|
// Verify property value.
|
|
uint16_t test_value;
|
|
Error error;
|
|
EXPECT_TRUE(store.GetUint16Property(key, &test_value, &error));
|
|
EXPECT_EQ(value, test_value);
|
|
|
|
// Set property using brillo::Any variant type.
|
|
uint16_t new_value = 128;
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(new_value), &error));
|
|
EXPECT_TRUE(store.GetUint16Property(key, &test_value, &error));
|
|
EXPECT_EQ(new_value, test_value);
|
|
}
|
|
{
|
|
// Register property value.
|
|
const string key = "uint32p";
|
|
uint32_t value = 127;
|
|
store.RegisterUint32(key, &value);
|
|
|
|
// Verify property value.
|
|
uint32_t test_value;
|
|
Error error;
|
|
EXPECT_TRUE(store.GetUint32Property(key, &test_value, &error));
|
|
EXPECT_EQ(value, test_value);
|
|
|
|
// Set property using brillo::Any variant type.
|
|
uint32_t new_value = 128;
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(new_value), &error));
|
|
EXPECT_TRUE(store.GetUint32Property(key, &test_value, &error));
|
|
EXPECT_EQ(new_value, test_value);
|
|
}
|
|
{
|
|
// KeyValueStoreProperty is only defined for derived types so handle
|
|
// this case manually here.
|
|
const string key = "keyvaluestorep";
|
|
EXPECT_CALL(*this, GetKeyValueStoreCallback(_))
|
|
.WillOnce(Return(KeyValueStore()));
|
|
store.RegisterDerivedKeyValueStore(
|
|
key,
|
|
KeyValueStoreAccessor(
|
|
new CustomAccessor<PropertyStoreTest, KeyValueStore>(
|
|
this, &PropertyStoreTest::GetKeyValueStoreCallback,
|
|
&PropertyStoreTest::SetKeyValueStoreCallback)));
|
|
|
|
brillo::VariantDictionary value;
|
|
EXPECT_CALL(*this, SetKeyValueStoreCallback(_, _)).WillOnce(Return(true));
|
|
Error error;
|
|
EXPECT_TRUE(store.SetAnyProperty(key, brillo::Any(value), &error));
|
|
}
|
|
}
|
|
|
|
TEST_F(PropertyStoreTest, SetAndGetProperties) {
|
|
PropertyStore store;
|
|
|
|
// Register properties.
|
|
const string kBoolKey = "boolp";
|
|
const string kKeyValueStoreKey = "keyvaluestorep";
|
|
const string kInt16Key = "int16p";
|
|
const string kInt32Key = "int32p";
|
|
const string kStringKey = "stringp";
|
|
const string kStringsKey = "stringsp";
|
|
const string kStringmapKey = "stringmapp";
|
|
const string kUint8Key = "uint8p";
|
|
const string kUint16Key = "uint16p";
|
|
const string kUint32Key = "uint32p";
|
|
bool bool_value = true;
|
|
int16_t int16_value = 16;
|
|
int32_t int32_value = 32;
|
|
string string_value = "string";
|
|
Stringmap stringmap_value;
|
|
stringmap_value["noooo"] = "yesss";
|
|
Strings strings_value;
|
|
strings_value.push_back("yesss");
|
|
uint8_t uint8_value = 8;
|
|
uint16_t uint16_value = 16;
|
|
uint32_t uint32_value = 32;
|
|
|
|
store.RegisterBool(kBoolKey, &bool_value);
|
|
store.RegisterInt16(kInt16Key, &int16_value);
|
|
store.RegisterInt32(kInt32Key, &int32_value);
|
|
store.RegisterString(kStringKey, &string_value);
|
|
store.RegisterStrings(kStringsKey, &strings_value);
|
|
store.RegisterStringmap(kStringmapKey, &stringmap_value);
|
|
store.RegisterUint8(kUint8Key, &uint8_value);
|
|
store.RegisterUint16(kUint16Key, &uint16_value);
|
|
store.RegisterUint32(kUint32Key, &uint32_value);
|
|
|
|
// Special handling for KeyValueStore property.
|
|
EXPECT_CALL(*this, GetKeyValueStoreCallback(_))
|
|
.WillOnce(Return(KeyValueStore()));
|
|
store.RegisterDerivedKeyValueStore(
|
|
kKeyValueStoreKey,
|
|
KeyValueStoreAccessor(
|
|
new CustomAccessor<PropertyStoreTest, KeyValueStore>(
|
|
this, &PropertyStoreTest::GetKeyValueStoreCallback,
|
|
&PropertyStoreTest::SetKeyValueStoreCallback)));
|
|
|
|
// Update properties.
|
|
bool new_bool_value = false;
|
|
brillo::VariantDictionary new_key_value_store_value;
|
|
int16_t new_int16_value = 17;
|
|
int32_t new_int32_value = 33;
|
|
string new_string_value = "strings";
|
|
Stringmap new_stringmap_value;
|
|
new_stringmap_value["yesss"] = "noooo";
|
|
Strings new_strings_value;
|
|
new_strings_value.push_back("noooo");
|
|
uint8_t new_uint8_value = 9;
|
|
uint16_t new_uint16_value = 17;
|
|
uint32_t new_uint32_value = 33;
|
|
|
|
brillo::VariantDictionary dict;
|
|
dict.insert(std::make_pair(kBoolKey, brillo::Any(new_bool_value)));
|
|
dict.insert(std::make_pair(kKeyValueStoreKey,
|
|
brillo::Any(new_key_value_store_value)));
|
|
dict.insert(std::make_pair(kInt16Key, brillo::Any(new_int16_value)));
|
|
dict.insert(std::make_pair(kInt32Key, brillo::Any(new_int32_value)));
|
|
dict.insert(std::make_pair(kStringKey, brillo::Any(new_string_value)));
|
|
dict.insert(std::make_pair(kStringmapKey,
|
|
brillo::Any(new_stringmap_value)));
|
|
dict.insert(std::make_pair(kStringsKey, brillo::Any(new_strings_value)));
|
|
dict.insert(std::make_pair(kUint8Key, brillo::Any(new_uint8_value)));
|
|
dict.insert(std::make_pair(kUint16Key, brillo::Any(new_uint16_value)));
|
|
dict.insert(std::make_pair(kUint32Key, brillo::Any(new_uint32_value)));
|
|
|
|
EXPECT_CALL(*this, SetKeyValueStoreCallback(_, _)).WillOnce(Return(true));
|
|
Error error;
|
|
EXPECT_TRUE(store.SetProperties(dict, &error));
|
|
|
|
// Retrieve properties.
|
|
EXPECT_CALL(*this, GetKeyValueStoreCallback(_))
|
|
.WillOnce(Return(KeyValueStore()));
|
|
brillo::VariantDictionary result_dict;
|
|
EXPECT_TRUE(store.GetProperties(&result_dict, &error));
|
|
|
|
// Verify property values.
|
|
EXPECT_EQ(new_bool_value, result_dict[kBoolKey].Get<bool>());
|
|
EXPECT_EQ(new_int16_value, result_dict[kInt16Key].Get<int16_t>());
|
|
EXPECT_EQ(new_int32_value, result_dict[kInt32Key].Get<int32_t>());
|
|
EXPECT_EQ(new_string_value, result_dict[kStringKey].Get<string>());
|
|
EXPECT_TRUE(
|
|
new_stringmap_value == result_dict[kStringmapKey].Get<Stringmap>());
|
|
EXPECT_TRUE(new_strings_value == result_dict[kStringsKey].Get<Strings>());
|
|
EXPECT_EQ(new_uint8_value, result_dict[kUint8Key].Get<uint8_t>());
|
|
EXPECT_EQ(new_uint16_value, result_dict[kUint16Key].Get<uint16_t>());
|
|
EXPECT_EQ(new_uint32_value, result_dict[kUint32Key].Get<uint32_t>());
|
|
}
|
|
|
|
} // namespace shill
|