1 //
2 // Copyright (C) 2015 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "shill/fake_store.h"
18
19 #include <typeinfo>
20 #include <vector>
21
22 #include "shill/logging.h"
23
24 using std::set;
25 using std::string;
26 using std::vector;
27
28 namespace shill {
29
30 namespace Logging {
31
32 static auto kModuleLogScope = ScopeLogger::kStorage;
ObjectID(const FakeStore * j)33 static string ObjectID(const FakeStore* j) {
34 return "(unknown)";
35 }
36
37 } // namespace Logging
38
39 namespace {
40
DoesGroupContainProperties(const brillo::VariantDictionary & group,const brillo::VariantDictionary & required_properties)41 bool DoesGroupContainProperties(
42 const brillo::VariantDictionary& group,
43 const brillo::VariantDictionary& required_properties) {
44 for (const auto& required_property_name_and_value : required_properties) {
45 const auto& required_key = required_property_name_and_value.first;
46 const auto& required_value = required_property_name_and_value.second;
47 const auto& group_it = group.find(required_key);
48 if (group_it == group.end() || group_it->second != required_value) {
49 return false;
50 }
51 }
52 return true;
53 }
54
55 } // namespace
56
FakeStore()57 FakeStore::FakeStore() {}
58
IsNonEmpty() const59 bool FakeStore::IsNonEmpty() const {
60 // For now, the choice for return value is arbitrary. Revisit if we
61 // find tests depend on this behaving correctly. (i.e., if any tests
62 // require this to return true after a Close().)
63 return false;
64 }
65
Open()66 bool FakeStore::Open() {
67 return true;
68 }
69
Close()70 bool FakeStore::Close() {
71 return true;
72 }
73
Flush()74 bool FakeStore::Flush() {
75 return true;
76 }
77
MarkAsCorrupted()78 bool FakeStore::MarkAsCorrupted() {
79 return true;
80 }
81
GetGroups() const82 set<string> FakeStore::GetGroups() const {
83 set<string> matching_groups;
84 for (const auto& group_name_and_settings : group_name_to_settings_) {
85 matching_groups.insert(group_name_and_settings.first);
86 }
87 return matching_groups;
88 }
89
90 // Returns a set so that caller can easily test whether a particular group
91 // is contained within this collection.
GetGroupsWithKey(const string & key) const92 set<string> FakeStore::GetGroupsWithKey(const string& key) const {
93 set<string> matching_groups;
94 // iterate over groups, find ones with matching key
95 for (const auto& group_name_and_settings : group_name_to_settings_) {
96 const auto& group_name = group_name_and_settings.first;
97 const auto& group_settings = group_name_and_settings.second;
98 if (group_settings.find(key) != group_settings.end()) {
99 matching_groups.insert(group_name);
100 }
101 }
102 return matching_groups;
103 }
104
GetGroupsWithProperties(const KeyValueStore & properties) const105 set<string> FakeStore::GetGroupsWithProperties(const KeyValueStore& properties)
106 const {
107 set<string> matching_groups;
108 const brillo::VariantDictionary& properties_dict(properties.properties());
109 for (const auto& group_name_and_settings : group_name_to_settings_) {
110 const auto& group_name = group_name_and_settings.first;
111 const auto& group_settings = group_name_and_settings.second;
112 if (DoesGroupContainProperties(group_settings, properties_dict)) {
113 matching_groups.insert(group_name);
114 }
115 }
116 return matching_groups;
117 }
118
ContainsGroup(const string & group) const119 bool FakeStore::ContainsGroup(const string& group) const {
120 const auto& it = group_name_to_settings_.find(group);
121 return it != group_name_to_settings_.end();
122 }
123
DeleteKey(const string & group,const string & key)124 bool FakeStore::DeleteKey(const string& group, const string& key) {
125 const auto& group_name_and_settings = group_name_to_settings_.find(group);
126 if (group_name_and_settings == group_name_to_settings_.end()) {
127 LOG(ERROR) << "Could not find group |" << group << "|.";
128 return false;
129 }
130
131 auto& group_settings = group_name_and_settings->second;
132 auto property_it = group_settings.find(key);
133 if (property_it != group_settings.end()) {
134 group_settings.erase(property_it);
135 }
136
137 return true;
138 }
139
DeleteGroup(const string & group)140 bool FakeStore::DeleteGroup(const string& group) {
141 auto group_name_and_settings = group_name_to_settings_.find(group);
142 if (group_name_and_settings != group_name_to_settings_.end()) {
143 group_name_to_settings_.erase(group_name_and_settings);
144 }
145 return true;
146 }
147
SetHeader(const string & header)148 bool FakeStore::SetHeader(const string& header) {
149 return true;
150 }
151
GetString(const string & group,const string & key,string * value) const152 bool FakeStore::GetString(const string& group,
153 const string& key,
154 string* value) const {
155 return ReadSetting(group, key, value);
156 }
157
SetString(const string & group,const string & key,const string & value)158 bool FakeStore::SetString(
159 const string& group, const string& key, const string& value) {
160 return WriteSetting(group, key, value);
161 }
162
GetBool(const string & group,const string & key,bool * value) const163 bool FakeStore::GetBool(const string& group, const string& key, bool* value)
164 const {
165 return ReadSetting(group, key, value);
166 }
167
SetBool(const string & group,const string & key,bool value)168 bool FakeStore::SetBool(const string& group, const string& key, bool value) {
169 return WriteSetting(group, key, value);
170 }
171
GetInt(const string & group,const string & key,int * value) const172 bool FakeStore::GetInt(
173 const string& group, const string& key, int* value) const {
174 return ReadSetting(group, key, value);
175 }
176
SetInt(const string & group,const string & key,int value)177 bool FakeStore::SetInt(const string& group, const string& key, int value) {
178 return WriteSetting(group, key, value);
179 }
180
GetUint64(const string & group,const string & key,uint64_t * value) const181 bool FakeStore::GetUint64(
182 const string& group, const string& key, uint64_t* value) const {
183 return ReadSetting(group, key, value);
184 }
185
SetUint64(const string & group,const string & key,uint64_t value)186 bool FakeStore::SetUint64(
187 const string& group, const string& key, uint64_t value) {
188 return WriteSetting(group, key, value);
189 }
190
GetStringList(const string & group,const string & key,vector<string> * value) const191 bool FakeStore::GetStringList(
192 const string& group, const string& key, vector<string>* value) const {
193 return ReadSetting(group, key, value);
194 }
195
SetStringList(const string & group,const string & key,const vector<string> & value)196 bool FakeStore::SetStringList(
197 const string& group, const string& key, const vector<string>& value) {
198 return WriteSetting(group, key, value);
199 }
200
GetCryptedString(const string & group,const string & key,string * value)201 bool FakeStore::GetCryptedString(
202 const string& group, const string& key, string* value) {
203 return GetString(group, key, value);
204 }
205
SetCryptedString(const string & group,const string & key,const string & value)206 bool FakeStore::SetCryptedString(
207 const string& group, const string& key, const string& value) {
208 return SetString(group, key, value);
209 }
210
211 // Private methods.
212 template<typename T>
ReadSetting(const string & group,const string & key,T * out) const213 bool FakeStore::ReadSetting(
214 const string& group, const string& key, T* out) const {
215 const auto& group_name_and_settings = group_name_to_settings_.find(group);
216 if (group_name_and_settings == group_name_to_settings_.end()) {
217 SLOG(this, 10) << "Could not find group |" << group << "|.";
218 return false;
219 }
220
221 const auto& group_settings = group_name_and_settings->second;
222 const auto& property_name_and_value = group_settings.find(key);
223 if (property_name_and_value == group_settings.end()) {
224 SLOG(this, 10) << "Could not find property |" << key << "|.";
225 return false;
226 }
227
228 if (!property_name_and_value->second.IsTypeCompatible<T>()) {
229 // We assume that the reader and the writer agree on the exact
230 // type. So we do not allow implicit conversion.
231 LOG(ERROR) << "Can not read |" << brillo::GetUndecoratedTypeName<T>()
232 << "| from |"
233 << property_name_and_value->second.GetUndecoratedTypeName()
234 << "|.";
235 return false;
236 }
237
238 if (out) {
239 return property_name_and_value->second.GetValue(out);
240 } else {
241 return true;
242 }
243 }
244
245 template<typename T>
WriteSetting(const string & group,const string & key,const T & new_value)246 bool FakeStore::WriteSetting(
247 const string& group, const string& key, const T& new_value) {
248 auto group_name_and_settings = group_name_to_settings_.find(group);
249 if (group_name_and_settings == group_name_to_settings_.end()) {
250 group_name_to_settings_[group][key] = new_value;
251 return true;
252 }
253
254 auto& group_settings = group_name_and_settings->second;
255 auto property_name_and_value = group_settings.find(key);
256 if (property_name_and_value == group_settings.end()) {
257 group_settings[key] = new_value;
258 return true;
259 }
260
261 if (!property_name_and_value->second.IsTypeCompatible<T>()) {
262 SLOG(this, 10) << "New type |" << brillo::GetUndecoratedTypeName<T>()
263 << "| differs from current type |"
264 << property_name_and_value->second.GetUndecoratedTypeName()
265 << "|.";
266 return false;
267 } else {
268 property_name_and_value->second = new_value;
269 return true;
270 }
271 }
272
273 } // namespace shill
274