638 lines
20 KiB
C++
638 lines
20 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_accessor.h"
|
|
|
|
#include <limits>
|
|
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <base/stl_util.h>
|
|
#include <gtest/gtest.h>
|
|
#include <gmock/gmock.h>
|
|
|
|
#include "shill/error.h"
|
|
|
|
using std::map;
|
|
using std::string;
|
|
using std::vector;
|
|
using ::testing::Return;
|
|
using ::testing::Test;
|
|
|
|
namespace shill {
|
|
|
|
TEST(PropertyAccessorTest, SignedIntCorrectness) {
|
|
int32_t int_store = 0;
|
|
{
|
|
Error error;
|
|
int32_t orig_value = int_store;
|
|
Int32Accessor accessor(new PropertyAccessor<int32_t>(&int_store));
|
|
EXPECT_EQ(int_store, accessor->Get(&error));
|
|
|
|
int32_t expected_int32 = 127;
|
|
EXPECT_TRUE(accessor->Set(expected_int32, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_int32, accessor->Get(&error));
|
|
// Resetting to the same value should return false, but without
|
|
// an error.
|
|
EXPECT_FALSE(accessor->Set(expected_int32, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
|
|
accessor->Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(orig_value, accessor->Get(&error));
|
|
|
|
int_store = std::numeric_limits<int32_t>::max();
|
|
EXPECT_EQ(std::numeric_limits<int32_t>::max(), accessor->Get(&error));
|
|
}
|
|
{
|
|
Error error;
|
|
Int32Accessor accessor(new ConstPropertyAccessor<int32_t>(&int_store));
|
|
EXPECT_EQ(int_store, accessor->Get(&error));
|
|
|
|
int32_t expected_int32 = 127;
|
|
accessor->Set(expected_int32, &error);
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
EXPECT_EQ(Error::kInvalidArguments, error.type());
|
|
EXPECT_EQ(int_store, accessor->Get(&error));
|
|
|
|
int_store = std::numeric_limits<int32_t>::max();
|
|
EXPECT_EQ(std::numeric_limits<int32_t>::max(), accessor->Get(&error));
|
|
}
|
|
{
|
|
Error error;
|
|
Int32Accessor accessor(new ConstPropertyAccessor<int32_t>(&int_store));
|
|
accessor->Clear(&error);
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
}
|
|
{
|
|
Error error;
|
|
Int32Accessor accessor(new WriteOnlyPropertyAccessor<int32_t>(&int_store));
|
|
accessor->Get(&error);
|
|
EXPECT_TRUE(error.IsFailure());
|
|
EXPECT_EQ(Error::kPermissionDenied, error.type());
|
|
}
|
|
{
|
|
Error error;
|
|
int32_t expected_int32 = 127;
|
|
WriteOnlyPropertyAccessor<int32_t> accessor(&int_store);
|
|
EXPECT_TRUE(accessor.Set(expected_int32, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_int32, *accessor.property_);
|
|
// Resetting to the same value should return false, but without
|
|
// an error.
|
|
EXPECT_FALSE(accessor.Set(expected_int32, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
// As a write-only, the value can't be read.
|
|
EXPECT_EQ(int32_t(), accessor.Get(&error));
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
|
|
int_store = std::numeric_limits<int32_t>::max();
|
|
EXPECT_EQ(std::numeric_limits<int32_t>::max(), *accessor.property_);
|
|
}
|
|
{
|
|
Error error;
|
|
int32_t orig_value = int_store = 0;
|
|
WriteOnlyPropertyAccessor<int32_t> accessor(&int_store);
|
|
|
|
EXPECT_TRUE(accessor.Set(127, &error));
|
|
accessor.Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(orig_value, *accessor.property_);
|
|
}
|
|
}
|
|
|
|
TEST(PropertyAccessorTest, UnsignedIntCorrectness) {
|
|
uint32_t int_store = 0;
|
|
{
|
|
Error error;
|
|
uint32_t orig_value = int_store;
|
|
Uint32Accessor accessor(new PropertyAccessor<uint32_t>(&int_store));
|
|
EXPECT_EQ(int_store, accessor->Get(&error));
|
|
|
|
uint32_t expected_uint32 = 127;
|
|
EXPECT_TRUE(accessor->Set(expected_uint32, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_uint32, accessor->Get(&error));
|
|
// Resetting to the same value should return false, but without
|
|
// an error.
|
|
EXPECT_FALSE(accessor->Set(expected_uint32, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
|
|
accessor->Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(orig_value, accessor->Get(&error));
|
|
|
|
int_store = std::numeric_limits<uint32_t>::max();
|
|
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), accessor->Get(&error));
|
|
}
|
|
{
|
|
Error error;
|
|
Uint32Accessor accessor(new ConstPropertyAccessor<uint32_t>(&int_store));
|
|
EXPECT_EQ(int_store, accessor->Get(&error));
|
|
|
|
uint32_t expected_uint32 = 127;
|
|
EXPECT_FALSE(accessor->Set(expected_uint32, &error));
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
EXPECT_EQ(Error::kInvalidArguments, error.type());
|
|
EXPECT_EQ(int_store, accessor->Get(&error));
|
|
|
|
int_store = std::numeric_limits<uint32_t>::max();
|
|
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), accessor->Get(&error));
|
|
}
|
|
{
|
|
Error error;
|
|
Uint32Accessor accessor(new ConstPropertyAccessor<uint32_t>(&int_store));
|
|
accessor->Clear(&error);
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
}
|
|
{
|
|
Error error;
|
|
Uint32Accessor accessor(
|
|
new WriteOnlyPropertyAccessor<uint32_t>(&int_store));
|
|
accessor->Get(&error);
|
|
EXPECT_TRUE(error.IsFailure());
|
|
EXPECT_EQ(Error::kPermissionDenied, error.type());
|
|
}
|
|
{
|
|
Error error;
|
|
uint32_t expected_uint32 = 127;
|
|
WriteOnlyPropertyAccessor<uint32_t> accessor(&int_store);
|
|
EXPECT_TRUE(accessor.Set(expected_uint32, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_uint32, *accessor.property_);
|
|
// Resetting to the same value should return false, but without
|
|
// an error.
|
|
EXPECT_FALSE(accessor.Set(expected_uint32, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
// As a write-only, the value can't be read.
|
|
EXPECT_EQ(uint32_t(), accessor.Get(&error));
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
|
|
int_store = std::numeric_limits<uint32_t>::max();
|
|
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), *accessor.property_);
|
|
}
|
|
{
|
|
Error error;
|
|
uint32_t orig_value = int_store = 0;
|
|
WriteOnlyPropertyAccessor<uint32_t> accessor(&int_store);
|
|
|
|
EXPECT_TRUE(accessor.Set(127, &error));
|
|
accessor.Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(orig_value, *accessor.property_);
|
|
}
|
|
}
|
|
|
|
TEST(PropertyAccessorTest, StringCorrectness) {
|
|
string storage;
|
|
{
|
|
Error error;
|
|
string orig_value = storage;
|
|
StringAccessor accessor(new PropertyAccessor<string>(&storage));
|
|
EXPECT_EQ(storage, accessor->Get(&error));
|
|
|
|
string expected_string("what");
|
|
EXPECT_TRUE(accessor->Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_string, accessor->Get(&error));
|
|
// Resetting to the same value should return false, but without
|
|
// an error.
|
|
EXPECT_FALSE(accessor->Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
|
|
accessor->Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(orig_value, accessor->Get(&error));
|
|
|
|
storage = "nooooo";
|
|
EXPECT_EQ(storage, accessor->Get(&error));
|
|
}
|
|
{
|
|
Error error;
|
|
StringAccessor accessor(new ConstPropertyAccessor<string>(&storage));
|
|
EXPECT_EQ(storage, accessor->Get(&error));
|
|
|
|
string expected_string("what");
|
|
EXPECT_FALSE(accessor->Set(expected_string, &error));
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
EXPECT_EQ(Error::kInvalidArguments, error.type());
|
|
EXPECT_EQ(storage, accessor->Get(&error));
|
|
|
|
storage = "nooooo";
|
|
EXPECT_EQ(storage, accessor->Get(&error));
|
|
}
|
|
{
|
|
Error error;
|
|
StringAccessor accessor(new ConstPropertyAccessor<string>(&storage));
|
|
accessor->Clear(&error);
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
}
|
|
{
|
|
Error error;
|
|
StringAccessor accessor(new WriteOnlyPropertyAccessor<string>(&storage));
|
|
accessor->Get(&error);
|
|
EXPECT_TRUE(error.IsFailure());
|
|
EXPECT_EQ(Error::kPermissionDenied, error.type());
|
|
}
|
|
{
|
|
Error error;
|
|
string expected_string = "what";
|
|
WriteOnlyPropertyAccessor<string> accessor(&storage);
|
|
EXPECT_TRUE(accessor.Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_string, *accessor.property_);
|
|
// Resetting to the same value should return false, but without
|
|
// an error.
|
|
EXPECT_FALSE(accessor.Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
// As a write-only, the value can't be read.
|
|
EXPECT_EQ(string(), accessor.Get(&error));
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
|
|
storage = "nooooo";
|
|
EXPECT_EQ("nooooo", *accessor.property_);
|
|
}
|
|
{
|
|
Error error;
|
|
string orig_value = storage = "original value";
|
|
WriteOnlyPropertyAccessor<string> accessor(&storage);
|
|
EXPECT_TRUE(accessor.Set("new value", &error));
|
|
accessor.Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(orig_value, *accessor.property_);
|
|
}
|
|
}
|
|
|
|
TEST(PropertyAccessorTest, ByteArrayCorrectness) {
|
|
ByteArray byteArray;
|
|
{
|
|
Error error;
|
|
ByteArray orig_byteArray = byteArray;
|
|
ByteArrayAccessor accessor(new PropertyAccessor<ByteArray>(&byteArray));
|
|
EXPECT_EQ(byteArray, accessor->Get(&error));
|
|
|
|
ByteArray expected_byteArray({ 0x01, 0x7F, 0x80, 0xFF });
|
|
EXPECT_TRUE(accessor->Set(expected_byteArray, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_byteArray, accessor->Get(&error));
|
|
|
|
// Resetting to the same value should return false, but without
|
|
// an error.
|
|
EXPECT_FALSE(accessor->Set(expected_byteArray, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
|
|
accessor->Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(orig_byteArray, accessor->Get(&error));
|
|
|
|
byteArray = ByteArray({ 0xFF, 0x7F, 0x80, 0x00 });
|
|
EXPECT_EQ(byteArray, accessor->Get(&error));
|
|
}
|
|
{
|
|
Error error;
|
|
ByteArrayAccessor accessor(new ConstPropertyAccessor<ByteArray>(&byteArray));
|
|
EXPECT_EQ(byteArray, accessor->Get(&error));
|
|
|
|
ByteArray expected_byteArray({ 0x01, 0x7F, 0x80, 0xFF });
|
|
EXPECT_FALSE(accessor->Set(expected_byteArray, &error));
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
EXPECT_EQ(Error::kInvalidArguments, error.type());
|
|
EXPECT_EQ(byteArray, accessor->Get(&error));
|
|
|
|
byteArray = ByteArray({ 0xFF, 0x7F, 0x80, 0x00 });
|
|
EXPECT_EQ(byteArray, accessor->Get(&error));
|
|
}
|
|
{
|
|
Error error;
|
|
ByteArrayAccessor accessor(new ConstPropertyAccessor<ByteArray>(&byteArray));
|
|
accessor->Clear(&error);
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
}
|
|
{
|
|
Error error;
|
|
ByteArrayAccessor accessor(new WriteOnlyPropertyAccessor<ByteArray>(&byteArray));
|
|
accessor->Get(&error);
|
|
EXPECT_TRUE(error.IsFailure());
|
|
EXPECT_EQ(Error::kPermissionDenied, error.type());
|
|
}
|
|
{
|
|
Error error;
|
|
ByteArray expected_byteArray({ 0x01, 0x7F, 0x80, 0xFF });
|
|
WriteOnlyPropertyAccessor<ByteArray> accessor(&byteArray);
|
|
|
|
EXPECT_TRUE(accessor.Set(expected_byteArray, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_byteArray, *accessor.property_);
|
|
|
|
// Resetting to the same value should return false, but without
|
|
// an error.
|
|
EXPECT_FALSE(accessor.Set(expected_byteArray, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
|
|
// As a write-only, the value can't be read.
|
|
EXPECT_EQ(ByteArray(), accessor.Get(&error));
|
|
EXPECT_FALSE(error.IsSuccess());
|
|
|
|
byteArray = ByteArray({ 0xFF, 0x7F, 0x80, 0x00 });
|
|
EXPECT_EQ(ByteArray({ 0xFF, 0x7F, 0x80, 0x00 }), *accessor.property_);
|
|
}
|
|
{
|
|
Error error;
|
|
ByteArray orig_byteArray = byteArray = ByteArray({ 0x00, 0x7F, 0x80, 0xFF });
|
|
WriteOnlyPropertyAccessor<ByteArray> accessor(&byteArray);
|
|
|
|
EXPECT_TRUE(accessor.Set(ByteArray({ 0xFF, 0x7F, 0x80, 0x00 }), &error));
|
|
accessor.Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(orig_byteArray, *accessor.property_);
|
|
}
|
|
}
|
|
|
|
class StringWrapper {
|
|
public:
|
|
string Get(Error* /*error*/) {
|
|
return value_;
|
|
}
|
|
string ConstGet(Error* /*error*/) const {
|
|
return value_;
|
|
}
|
|
bool Set(const string& value, Error* /*error*/) {
|
|
if (value_ == value) {
|
|
return false;
|
|
}
|
|
value_ = value;
|
|
return true;
|
|
}
|
|
void Clear(Error* /*error*/) {
|
|
value_.clear();
|
|
}
|
|
|
|
string value_;
|
|
};
|
|
|
|
TEST(PropertyAccessorTest, CustomAccessorCorrectness) {
|
|
StringWrapper wrapper;
|
|
{
|
|
// Custom accessor: read, write, write-same, clear, read-updated.
|
|
// Together, write and write-same verify that the CustomAccessor
|
|
// template passes through the value from the called function.
|
|
Error error;
|
|
const string orig_value = wrapper.value_ = "original value";
|
|
CustomAccessor<StringWrapper, string> accessor(&wrapper,
|
|
&StringWrapper::Get,
|
|
&StringWrapper::Set);
|
|
EXPECT_EQ(orig_value, accessor.Get(&error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
|
|
const string expected_string = "new value";
|
|
EXPECT_TRUE(accessor.Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_string, accessor.Get(&error));
|
|
// Set to same value.
|
|
EXPECT_FALSE(accessor.Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
|
|
accessor.Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(orig_value, accessor.Get(&error));
|
|
|
|
wrapper.value_ = "nooooo";
|
|
EXPECT_EQ(wrapper.value_, accessor.Get(&error));
|
|
}
|
|
{
|
|
// Custom read-only accessor: read, write, read-updated.
|
|
Error error;
|
|
CustomAccessor<StringWrapper, string> accessor(&wrapper,
|
|
&StringWrapper::Get,
|
|
nullptr);
|
|
EXPECT_EQ(wrapper.value_, accessor.Get(&error));
|
|
|
|
const string expected_string = "what";
|
|
EXPECT_FALSE(accessor.Set(expected_string, &error));
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
EXPECT_EQ(Error::kInvalidArguments, error.type());
|
|
EXPECT_EQ(wrapper.value_, accessor.Get(&error));
|
|
|
|
wrapper.value_ = "nooooo";
|
|
EXPECT_EQ(wrapper.value_, accessor.Get(&error));
|
|
}
|
|
{
|
|
// Custom read-only accessor: clear.
|
|
Error error;
|
|
CustomAccessor<StringWrapper, string> accessor(&wrapper,
|
|
&StringWrapper::Get,
|
|
nullptr);
|
|
accessor.Clear(&error);
|
|
ASSERT_FALSE(error.IsSuccess());
|
|
}
|
|
{
|
|
// Custom read-only accessor with custom clear method.
|
|
Error error;
|
|
CustomAccessor<StringWrapper, string> accessor(&wrapper,
|
|
&StringWrapper::Get,
|
|
nullptr,
|
|
&StringWrapper::Clear);
|
|
wrapper.value_ = "empty this";
|
|
accessor.Clear(&error);
|
|
ASSERT_TRUE(error.IsSuccess());
|
|
EXPECT_TRUE(wrapper.value_.empty());
|
|
}
|
|
}
|
|
|
|
TEST(PropertyAccessorTest, CustomWriteOnlyAccessorWithDefault) {
|
|
StringWrapper wrapper;
|
|
{
|
|
// Test reading.
|
|
Error error;
|
|
const string default_value = "default value";
|
|
CustomWriteOnlyAccessor<StringWrapper, string> accessor(
|
|
&wrapper, &StringWrapper::Set, nullptr, &default_value);
|
|
wrapper.value_ = "can't read this";
|
|
EXPECT_EQ(string(), accessor.Get(&error));
|
|
EXPECT_TRUE(error.IsFailure());
|
|
EXPECT_EQ(Error::kPermissionDenied, error.type());
|
|
}
|
|
{
|
|
// Test writing.
|
|
Error error;
|
|
const string default_value = "default value";
|
|
const string expected_string = "what";
|
|
CustomWriteOnlyAccessor<StringWrapper, string> accessor(
|
|
&wrapper, &StringWrapper::Set, nullptr, &default_value);
|
|
EXPECT_TRUE(accessor.Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_string, wrapper.value_);
|
|
// Set to same value. With the above, this verifies that the
|
|
// CustomWriteOnlyAccessor template passes through the return
|
|
// value.
|
|
EXPECT_FALSE(accessor.Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
}
|
|
{
|
|
// Test clearing.
|
|
Error error;
|
|
const string default_value = "default value";
|
|
CustomWriteOnlyAccessor<StringWrapper, string> accessor(
|
|
&wrapper, &StringWrapper::Set, nullptr, &default_value);
|
|
accessor.Set("new value", &error);
|
|
EXPECT_EQ("new value", wrapper.value_);
|
|
accessor.Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(default_value, wrapper.value_);
|
|
}
|
|
}
|
|
|
|
TEST(PropertyAccessorTest, CustomWriteOnlyAccessorWithClear) {
|
|
StringWrapper wrapper;
|
|
{
|
|
// Test reading.
|
|
Error error;
|
|
CustomWriteOnlyAccessor<StringWrapper, string> accessor(
|
|
&wrapper, &StringWrapper::Set, &StringWrapper::Clear, nullptr);
|
|
wrapper.value_ = "can't read this";
|
|
EXPECT_EQ(string(), accessor.Get(&error));
|
|
EXPECT_TRUE(error.IsFailure());
|
|
EXPECT_EQ(Error::kPermissionDenied, error.type());
|
|
}
|
|
{
|
|
// Test writing.
|
|
Error error;
|
|
const string expected_string = "what";
|
|
CustomWriteOnlyAccessor<StringWrapper, string> accessor(
|
|
&wrapper, &StringWrapper::Set, &StringWrapper::Clear, nullptr);
|
|
EXPECT_TRUE(accessor.Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(expected_string, wrapper.value_);
|
|
// Set to same value. With the above, this verifies that the
|
|
// CustomWriteOnlyAccessor template passes through the return
|
|
// value.
|
|
EXPECT_FALSE(accessor.Set(expected_string, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
}
|
|
{
|
|
// Test clearing.
|
|
Error error;
|
|
CustomWriteOnlyAccessor<StringWrapper, string> accessor(
|
|
&wrapper, &StringWrapper::Set, &StringWrapper::Clear, nullptr);
|
|
EXPECT_TRUE(accessor.Set("new value", &error));
|
|
EXPECT_EQ("new value", wrapper.value_);
|
|
accessor.Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ("", wrapper.value_);
|
|
}
|
|
}
|
|
|
|
TEST(PropertyAccessorTest, CustomReadOnlyAccessor) {
|
|
StringWrapper wrapper;
|
|
CustomReadOnlyAccessor<StringWrapper, string> accessor(
|
|
&wrapper, &StringWrapper::ConstGet);
|
|
const string orig_value = wrapper.value_ = "original value";
|
|
{
|
|
// Test reading.
|
|
Error error;
|
|
EXPECT_EQ(orig_value, accessor.Get(&error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
}
|
|
{
|
|
// Test writing.
|
|
Error error;
|
|
EXPECT_FALSE(accessor.Set("new value", &error));
|
|
EXPECT_EQ(Error::kInvalidArguments, error.type());
|
|
EXPECT_EQ(orig_value, accessor.Get(&error));
|
|
}
|
|
{
|
|
// Test writing original value -- this also fails.
|
|
Error error;
|
|
EXPECT_FALSE(accessor.Set(orig_value, &error));
|
|
EXPECT_EQ(Error::kInvalidArguments, error.type());
|
|
EXPECT_EQ(orig_value, accessor.Get(&error));
|
|
}
|
|
{
|
|
// Test clearing.
|
|
Error error;
|
|
accessor.Clear(&error);
|
|
EXPECT_EQ(Error::kInvalidArguments, error.type());
|
|
EXPECT_EQ(orig_value, accessor.Get(&error));
|
|
}
|
|
}
|
|
|
|
class StringMapWrapper {
|
|
public:
|
|
void Clear(const string& key, Error* /*error*/) {
|
|
value_.erase(key);
|
|
}
|
|
string Get(const string& key, Error* /*error*/) {
|
|
EXPECT_TRUE(ContainsKey(value_, key));
|
|
return value_[key];
|
|
}
|
|
bool Set(const string& key, const string& value, Error* /*error*/) {
|
|
if (value_[key] == value) {
|
|
return false;
|
|
}
|
|
value_[key] = value;
|
|
return true;
|
|
}
|
|
|
|
map<string, string> value_;
|
|
};
|
|
|
|
TEST(PropertyAccessorTest, CustomMappedAccessor) {
|
|
const string kKey = "entry_key";
|
|
const string kValue = "entry_value";
|
|
{
|
|
// Test reading.
|
|
StringMapWrapper wrapper;
|
|
CustomMappedAccessor<StringMapWrapper, string, string> accessor(
|
|
&wrapper, &StringMapWrapper::Clear, &StringMapWrapper::Get,
|
|
&StringMapWrapper::Set, kKey);
|
|
wrapper.value_[kKey] = kValue;
|
|
Error error;
|
|
EXPECT_EQ(kValue, accessor.Get(&error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
}
|
|
{
|
|
// Test writing.
|
|
StringMapWrapper wrapper;
|
|
CustomMappedAccessor<StringMapWrapper, string, string> accessor(
|
|
&wrapper, &StringMapWrapper::Clear, &StringMapWrapper::Get,
|
|
&StringMapWrapper::Set, kKey);
|
|
Error error;
|
|
EXPECT_TRUE(accessor.Set(kValue, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_EQ(kValue, wrapper.value_[kKey]);
|
|
// Set to same value. With the above, this verifies that the
|
|
// CustomMappedAccessor template passes through the return
|
|
// value.
|
|
EXPECT_FALSE(accessor.Set(kValue, &error));
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
}
|
|
{
|
|
// Test clearing.
|
|
StringMapWrapper wrapper;
|
|
CustomMappedAccessor<StringMapWrapper, string, string> accessor(
|
|
&wrapper, &StringMapWrapper::Clear, &StringMapWrapper::Get,
|
|
&StringMapWrapper::Set, kKey);
|
|
wrapper.value_[kKey] = kValue;
|
|
Error error;
|
|
accessor.Clear(&error);
|
|
EXPECT_TRUE(error.IsSuccess());
|
|
EXPECT_FALSE(ContainsKey(wrapper.value_, kKey));
|
|
}
|
|
}
|
|
|
|
} // namespace shill
|