273 lines
8 KiB
C++
273 lines
8 KiB
C++
//
|
|
// Copyright (C) 2015 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/fake_store.h"
|
|
|
|
#include <typeinfo>
|
|
#include <vector>
|
|
|
|
#include "shill/logging.h"
|
|
|
|
using std::set;
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
namespace shill {
|
|
|
|
namespace Logging {
|
|
|
|
static auto kModuleLogScope = ScopeLogger::kStorage;
|
|
static string ObjectID(const FakeStore* j) {
|
|
return "(unknown)";
|
|
}
|
|
|
|
} // namespace Logging
|
|
|
|
namespace {
|
|
|
|
bool DoesGroupContainProperties(
|
|
const brillo::VariantDictionary& group,
|
|
const brillo::VariantDictionary& required_properties) {
|
|
for (const auto& required_property_name_and_value : required_properties) {
|
|
const auto& required_key = required_property_name_and_value.first;
|
|
const auto& required_value = required_property_name_and_value.second;
|
|
const auto& group_it = group.find(required_key);
|
|
if (group_it == group.end() || group_it->second != required_value) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
FakeStore::FakeStore() {}
|
|
|
|
bool FakeStore::IsNonEmpty() const {
|
|
// For now, the choice for return value is arbitrary. Revisit if we
|
|
// find tests depend on this behaving correctly. (i.e., if any tests
|
|
// require this to return true after a Close().)
|
|
return false;
|
|
}
|
|
|
|
bool FakeStore::Open() {
|
|
return true;
|
|
}
|
|
|
|
bool FakeStore::Close() {
|
|
return true;
|
|
}
|
|
|
|
bool FakeStore::Flush() {
|
|
return true;
|
|
}
|
|
|
|
bool FakeStore::MarkAsCorrupted() {
|
|
return true;
|
|
}
|
|
|
|
set<string> FakeStore::GetGroups() const {
|
|
set<string> matching_groups;
|
|
for (const auto& group_name_and_settings : group_name_to_settings_) {
|
|
matching_groups.insert(group_name_and_settings.first);
|
|
}
|
|
return matching_groups;
|
|
}
|
|
|
|
// Returns a set so that caller can easily test whether a particular group
|
|
// is contained within this collection.
|
|
set<string> FakeStore::GetGroupsWithKey(const string& key) const {
|
|
set<string> matching_groups;
|
|
// iterate over groups, find ones with matching key
|
|
for (const auto& group_name_and_settings : group_name_to_settings_) {
|
|
const auto& group_name = group_name_and_settings.first;
|
|
const auto& group_settings = group_name_and_settings.second;
|
|
if (group_settings.find(key) != group_settings.end()) {
|
|
matching_groups.insert(group_name);
|
|
}
|
|
}
|
|
return matching_groups;
|
|
}
|
|
|
|
set<string> FakeStore::GetGroupsWithProperties(const KeyValueStore& properties)
|
|
const {
|
|
set<string> matching_groups;
|
|
const brillo::VariantDictionary& properties_dict(properties.properties());
|
|
for (const auto& group_name_and_settings : group_name_to_settings_) {
|
|
const auto& group_name = group_name_and_settings.first;
|
|
const auto& group_settings = group_name_and_settings.second;
|
|
if (DoesGroupContainProperties(group_settings, properties_dict)) {
|
|
matching_groups.insert(group_name);
|
|
}
|
|
}
|
|
return matching_groups;
|
|
}
|
|
|
|
bool FakeStore::ContainsGroup(const string& group) const {
|
|
const auto& it = group_name_to_settings_.find(group);
|
|
return it != group_name_to_settings_.end();
|
|
}
|
|
|
|
bool FakeStore::DeleteKey(const string& group, const string& key) {
|
|
const auto& group_name_and_settings = group_name_to_settings_.find(group);
|
|
if (group_name_and_settings == group_name_to_settings_.end()) {
|
|
LOG(ERROR) << "Could not find group |" << group << "|.";
|
|
return false;
|
|
}
|
|
|
|
auto& group_settings = group_name_and_settings->second;
|
|
auto property_it = group_settings.find(key);
|
|
if (property_it != group_settings.end()) {
|
|
group_settings.erase(property_it);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool FakeStore::DeleteGroup(const string& group) {
|
|
auto group_name_and_settings = group_name_to_settings_.find(group);
|
|
if (group_name_and_settings != group_name_to_settings_.end()) {
|
|
group_name_to_settings_.erase(group_name_and_settings);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool FakeStore::SetHeader(const string& header) {
|
|
return true;
|
|
}
|
|
|
|
bool FakeStore::GetString(const string& group,
|
|
const string& key,
|
|
string* value) const {
|
|
return ReadSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::SetString(
|
|
const string& group, const string& key, const string& value) {
|
|
return WriteSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::GetBool(const string& group, const string& key, bool* value)
|
|
const {
|
|
return ReadSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::SetBool(const string& group, const string& key, bool value) {
|
|
return WriteSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::GetInt(
|
|
const string& group, const string& key, int* value) const {
|
|
return ReadSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::SetInt(const string& group, const string& key, int value) {
|
|
return WriteSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::GetUint64(
|
|
const string& group, const string& key, uint64_t* value) const {
|
|
return ReadSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::SetUint64(
|
|
const string& group, const string& key, uint64_t value) {
|
|
return WriteSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::GetStringList(
|
|
const string& group, const string& key, vector<string>* value) const {
|
|
return ReadSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::SetStringList(
|
|
const string& group, const string& key, const vector<string>& value) {
|
|
return WriteSetting(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::GetCryptedString(
|
|
const string& group, const string& key, string* value) {
|
|
return GetString(group, key, value);
|
|
}
|
|
|
|
bool FakeStore::SetCryptedString(
|
|
const string& group, const string& key, const string& value) {
|
|
return SetString(group, key, value);
|
|
}
|
|
|
|
// Private methods.
|
|
template<typename T>
|
|
bool FakeStore::ReadSetting(
|
|
const string& group, const string& key, T* out) const {
|
|
const auto& group_name_and_settings = group_name_to_settings_.find(group);
|
|
if (group_name_and_settings == group_name_to_settings_.end()) {
|
|
SLOG(this, 10) << "Could not find group |" << group << "|.";
|
|
return false;
|
|
}
|
|
|
|
const auto& group_settings = group_name_and_settings->second;
|
|
const auto& property_name_and_value = group_settings.find(key);
|
|
if (property_name_and_value == group_settings.end()) {
|
|
SLOG(this, 10) << "Could not find property |" << key << "|.";
|
|
return false;
|
|
}
|
|
|
|
if (!property_name_and_value->second.IsTypeCompatible<T>()) {
|
|
// We assume that the reader and the writer agree on the exact
|
|
// type. So we do not allow implicit conversion.
|
|
LOG(ERROR) << "Can not read |" << brillo::GetUndecoratedTypeName<T>()
|
|
<< "| from |"
|
|
<< property_name_and_value->second.GetUndecoratedTypeName()
|
|
<< "|.";
|
|
return false;
|
|
}
|
|
|
|
if (out) {
|
|
return property_name_and_value->second.GetValue(out);
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
bool FakeStore::WriteSetting(
|
|
const string& group, const string& key, const T& new_value) {
|
|
auto group_name_and_settings = group_name_to_settings_.find(group);
|
|
if (group_name_and_settings == group_name_to_settings_.end()) {
|
|
group_name_to_settings_[group][key] = new_value;
|
|
return true;
|
|
}
|
|
|
|
auto& group_settings = group_name_and_settings->second;
|
|
auto property_name_and_value = group_settings.find(key);
|
|
if (property_name_and_value == group_settings.end()) {
|
|
group_settings[key] = new_value;
|
|
return true;
|
|
}
|
|
|
|
if (!property_name_and_value->second.IsTypeCompatible<T>()) {
|
|
SLOG(this, 10) << "New type |" << brillo::GetUndecoratedTypeName<T>()
|
|
<< "| differs from current type |"
|
|
<< property_name_and_value->second.GetUndecoratedTypeName()
|
|
<< "|.";
|
|
return false;
|
|
} else {
|
|
property_name_and_value->second = new_value;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
} // namespace shill
|