1 //
2 // Copyright (C) 2014 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 "update_engine/common/fake_prefs.h"
18 
19 #include <algorithm>
20 
21 #include <gtest/gtest.h>
22 
23 using std::string;
24 using std::vector;
25 
26 using chromeos_update_engine::FakePrefs;
27 
28 namespace {
29 
CheckNotNull(const string & key,void * ptr)30 void CheckNotNull(const string& key, void* ptr) {
31   EXPECT_NE(nullptr, ptr) << "Called Get*() for key \"" << key
32                           << "\" with a null parameter.";
33 }
34 
35 }  // namespace
36 
37 namespace chromeos_update_engine {
38 
~FakePrefs()39 FakePrefs::~FakePrefs() {
40   EXPECT_TRUE(observers_.empty());
41 }
42 
43 // Compile-time type-dependent constants definitions.
44 template <>
45 FakePrefs::PrefType const FakePrefs::PrefConsts<string>::type =
46     FakePrefs::PrefType::kString;
47 template <>
48 string FakePrefs::PrefValue::*const  // NOLINT(runtime/string), not static str.
49     FakePrefs::PrefConsts<string>::member = &FakePrefs::PrefValue::as_str;
50 
51 template <>
52 FakePrefs::PrefType const FakePrefs::PrefConsts<int64_t>::type =
53     FakePrefs::PrefType::kInt64;
54 template <>
55 int64_t FakePrefs::PrefValue::*const FakePrefs::PrefConsts<int64_t>::member =
56     &FakePrefs::PrefValue::as_int64;
57 
58 template <>
59 FakePrefs::PrefType const FakePrefs::PrefConsts<bool>::type =
60     FakePrefs::PrefType::kBool;
61 template <>
62 bool FakePrefs::PrefValue::*const FakePrefs::PrefConsts<bool>::member =
63     &FakePrefs::PrefValue::as_bool;
64 
GetString(const string & key,string * value) const65 bool FakePrefs::GetString(const string& key, string* value) const {
66   return GetValue(key, value);
67 }
68 
SetString(const string & key,const string & value)69 bool FakePrefs::SetString(const string& key, const string& value) {
70   SetValue(key, value);
71   return true;
72 }
73 
GetInt64(const string & key,int64_t * value) const74 bool FakePrefs::GetInt64(const string& key, int64_t* value) const {
75   return GetValue(key, value);
76 }
77 
SetInt64(const string & key,const int64_t value)78 bool FakePrefs::SetInt64(const string& key, const int64_t value) {
79   SetValue(key, value);
80   return true;
81 }
82 
GetBoolean(const string & key,bool * value) const83 bool FakePrefs::GetBoolean(const string& key, bool* value) const {
84   return GetValue(key, value);
85 }
86 
SetBoolean(const string & key,const bool value)87 bool FakePrefs::SetBoolean(const string& key, const bool value) {
88   SetValue(key, value);
89   return true;
90 }
91 
Exists(const string & key) const92 bool FakePrefs::Exists(const string& key) const {
93   return values_.find(key) != values_.end();
94 }
95 
Delete(const string & key)96 bool FakePrefs::Delete(const string& key) {
97   if (values_.find(key) == values_.end())
98     return false;
99   values_.erase(key);
100   const auto observers_for_key = observers_.find(key);
101   if (observers_for_key != observers_.end()) {
102     std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
103     for (ObserverInterface* observer : copy_observers)
104       observer->OnPrefDeleted(key);
105   }
106   return true;
107 }
108 
GetSubKeys(const string & ns,vector<string> * keys) const109 bool FakePrefs::GetSubKeys(const string& ns, vector<string>* keys) const {
110   for (const auto& pr : values_)
111     if (pr.first.compare(0, ns.length(), ns) == 0)
112       keys->push_back(pr.first);
113   return true;
114 }
115 
GetTypeName(PrefType type)116 string FakePrefs::GetTypeName(PrefType type) {
117   switch (type) {
118     case PrefType::kString:
119       return "string";
120     case PrefType::kInt64:
121       return "int64_t";
122     case PrefType::kBool:
123       return "bool";
124   }
125   return "Unknown";
126 }
127 
CheckKeyType(const string & key,PrefType type) const128 void FakePrefs::CheckKeyType(const string& key, PrefType type) const {
129   auto it = values_.find(key);
130   EXPECT_TRUE(it == values_.end() || it->second.type == type)
131       << "Key \"" << key << "\" if defined as " << GetTypeName(it->second.type)
132       << " but is accessed as a " << GetTypeName(type);
133 }
134 
135 template <typename T>
SetValue(const string & key,const T & value)136 void FakePrefs::SetValue(const string& key, const T& value) {
137   CheckKeyType(key, PrefConsts<T>::type);
138   values_[key].type = PrefConsts<T>::type;
139   values_[key].value.*(PrefConsts<T>::member) = value;
140   const auto observers_for_key = observers_.find(key);
141   if (observers_for_key != observers_.end()) {
142     std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
143     for (ObserverInterface* observer : copy_observers)
144       observer->OnPrefSet(key);
145   }
146 }
147 
148 template <typename T>
GetValue(const string & key,T * value) const149 bool FakePrefs::GetValue(const string& key, T* value) const {
150   CheckKeyType(key, PrefConsts<T>::type);
151   auto it = values_.find(key);
152   if (it == values_.end())
153     return false;
154   CheckNotNull(key, value);
155   *value = it->second.value.*(PrefConsts<T>::member);
156   return true;
157 }
158 
AddObserver(const string & key,ObserverInterface * observer)159 void FakePrefs::AddObserver(const string& key, ObserverInterface* observer) {
160   observers_[key].push_back(observer);
161 }
162 
RemoveObserver(const string & key,ObserverInterface * observer)163 void FakePrefs::RemoveObserver(const string& key, ObserverInterface* observer) {
164   std::vector<ObserverInterface*>& observers_for_key = observers_[key];
165   auto observer_it =
166       std::find(observers_for_key.begin(), observers_for_key.end(), observer);
167   EXPECT_NE(observer_it, observers_for_key.end())
168       << "Trying to remove an observer instance not watching the key " << key;
169   if (observer_it != observers_for_key.end())
170     observers_for_key.erase(observer_it);
171   if (observers_for_key.empty())
172     observers_.erase(key);
173 }
174 
175 }  // namespace chromeos_update_engine
176