1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2014 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker
17*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/fake_prefs.h"
18*5a923131SAndroid Build Coastguard Worker
19*5a923131SAndroid Build Coastguard Worker #include <algorithm>
20*5a923131SAndroid Build Coastguard Worker #include <utility>
21*5a923131SAndroid Build Coastguard Worker
22*5a923131SAndroid Build Coastguard Worker #include <gtest/gtest.h>
23*5a923131SAndroid Build Coastguard Worker
24*5a923131SAndroid Build Coastguard Worker using std::string;
25*5a923131SAndroid Build Coastguard Worker using std::vector;
26*5a923131SAndroid Build Coastguard Worker
27*5a923131SAndroid Build Coastguard Worker using chromeos_update_engine::FakePrefs;
28*5a923131SAndroid Build Coastguard Worker
29*5a923131SAndroid Build Coastguard Worker namespace {
30*5a923131SAndroid Build Coastguard Worker
CheckNotNull(std::string_view key,void * ptr)31*5a923131SAndroid Build Coastguard Worker void CheckNotNull(std::string_view key, void* ptr) {
32*5a923131SAndroid Build Coastguard Worker EXPECT_NE(nullptr, ptr) << "Called Get*() for key \"" << key
33*5a923131SAndroid Build Coastguard Worker << "\" with a null parameter.";
34*5a923131SAndroid Build Coastguard Worker }
35*5a923131SAndroid Build Coastguard Worker
36*5a923131SAndroid Build Coastguard Worker } // namespace
37*5a923131SAndroid Build Coastguard Worker
38*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
39*5a923131SAndroid Build Coastguard Worker
~FakePrefs()40*5a923131SAndroid Build Coastguard Worker FakePrefs::~FakePrefs() {
41*5a923131SAndroid Build Coastguard Worker EXPECT_TRUE(observers_.empty());
42*5a923131SAndroid Build Coastguard Worker }
43*5a923131SAndroid Build Coastguard Worker
44*5a923131SAndroid Build Coastguard Worker // Compile-time type-dependent constants definitions.
45*5a923131SAndroid Build Coastguard Worker template <>
46*5a923131SAndroid Build Coastguard Worker FakePrefs::PrefType const FakePrefs::PrefConsts<string>::type =
47*5a923131SAndroid Build Coastguard Worker FakePrefs::PrefType::kString;
48*5a923131SAndroid Build Coastguard Worker template <>
49*5a923131SAndroid Build Coastguard Worker string FakePrefs::PrefValue::*const // NOLINT(runtime/string), not static str.
50*5a923131SAndroid Build Coastguard Worker FakePrefs::PrefConsts<string>::member = &FakePrefs::PrefValue::as_str;
51*5a923131SAndroid Build Coastguard Worker
52*5a923131SAndroid Build Coastguard Worker template <>
53*5a923131SAndroid Build Coastguard Worker FakePrefs::PrefType const FakePrefs::PrefConsts<int64_t>::type =
54*5a923131SAndroid Build Coastguard Worker FakePrefs::PrefType::kInt64;
55*5a923131SAndroid Build Coastguard Worker template <>
56*5a923131SAndroid Build Coastguard Worker int64_t FakePrefs::PrefValue::*const FakePrefs::PrefConsts<int64_t>::member =
57*5a923131SAndroid Build Coastguard Worker &FakePrefs::PrefValue::as_int64;
58*5a923131SAndroid Build Coastguard Worker
59*5a923131SAndroid Build Coastguard Worker template <>
60*5a923131SAndroid Build Coastguard Worker FakePrefs::PrefType const FakePrefs::PrefConsts<bool>::type =
61*5a923131SAndroid Build Coastguard Worker FakePrefs::PrefType::kBool;
62*5a923131SAndroid Build Coastguard Worker template <>
63*5a923131SAndroid Build Coastguard Worker bool FakePrefs::PrefValue::*const FakePrefs::PrefConsts<bool>::member =
64*5a923131SAndroid Build Coastguard Worker &FakePrefs::PrefValue::as_bool;
65*5a923131SAndroid Build Coastguard Worker
GetString(std::string_view key,string * value) const66*5a923131SAndroid Build Coastguard Worker bool FakePrefs::GetString(std::string_view key, string* value) const {
67*5a923131SAndroid Build Coastguard Worker return GetValue(key, value);
68*5a923131SAndroid Build Coastguard Worker }
69*5a923131SAndroid Build Coastguard Worker
SetString(std::string_view key,std::string_view value)70*5a923131SAndroid Build Coastguard Worker bool FakePrefs::SetString(std::string_view key, std::string_view value) {
71*5a923131SAndroid Build Coastguard Worker SetValue(key, std::string(value));
72*5a923131SAndroid Build Coastguard Worker return true;
73*5a923131SAndroid Build Coastguard Worker }
74*5a923131SAndroid Build Coastguard Worker
GetInt64(std::string_view key,int64_t * value) const75*5a923131SAndroid Build Coastguard Worker bool FakePrefs::GetInt64(std::string_view key, int64_t* value) const {
76*5a923131SAndroid Build Coastguard Worker return GetValue(key, value);
77*5a923131SAndroid Build Coastguard Worker }
78*5a923131SAndroid Build Coastguard Worker
SetInt64(std::string_view key,const int64_t value)79*5a923131SAndroid Build Coastguard Worker bool FakePrefs::SetInt64(std::string_view key, const int64_t value) {
80*5a923131SAndroid Build Coastguard Worker SetValue(key, value);
81*5a923131SAndroid Build Coastguard Worker return true;
82*5a923131SAndroid Build Coastguard Worker }
83*5a923131SAndroid Build Coastguard Worker
GetBoolean(std::string_view key,bool * value) const84*5a923131SAndroid Build Coastguard Worker bool FakePrefs::GetBoolean(std::string_view key, bool* value) const {
85*5a923131SAndroid Build Coastguard Worker return GetValue(key, value);
86*5a923131SAndroid Build Coastguard Worker }
87*5a923131SAndroid Build Coastguard Worker
SetBoolean(std::string_view key,const bool value)88*5a923131SAndroid Build Coastguard Worker bool FakePrefs::SetBoolean(std::string_view key, const bool value) {
89*5a923131SAndroid Build Coastguard Worker SetValue(key, value);
90*5a923131SAndroid Build Coastguard Worker return true;
91*5a923131SAndroid Build Coastguard Worker }
92*5a923131SAndroid Build Coastguard Worker
Exists(std::string_view key) const93*5a923131SAndroid Build Coastguard Worker bool FakePrefs::Exists(std::string_view key) const {
94*5a923131SAndroid Build Coastguard Worker return values_.find(key) != values_.end();
95*5a923131SAndroid Build Coastguard Worker }
96*5a923131SAndroid Build Coastguard Worker
Delete(std::string_view key)97*5a923131SAndroid Build Coastguard Worker bool FakePrefs::Delete(std::string_view key) {
98*5a923131SAndroid Build Coastguard Worker if (values_.find(key) == values_.end())
99*5a923131SAndroid Build Coastguard Worker return false;
100*5a923131SAndroid Build Coastguard Worker values_.erase(std::string{key});
101*5a923131SAndroid Build Coastguard Worker const auto observers_for_key = observers_.find(key);
102*5a923131SAndroid Build Coastguard Worker if (observers_for_key != observers_.end()) {
103*5a923131SAndroid Build Coastguard Worker std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
104*5a923131SAndroid Build Coastguard Worker for (ObserverInterface* observer : copy_observers)
105*5a923131SAndroid Build Coastguard Worker observer->OnPrefDeleted(key);
106*5a923131SAndroid Build Coastguard Worker }
107*5a923131SAndroid Build Coastguard Worker return true;
108*5a923131SAndroid Build Coastguard Worker }
109*5a923131SAndroid Build Coastguard Worker
Delete(std::string_view key,const vector<string> & nss)110*5a923131SAndroid Build Coastguard Worker bool FakePrefs::Delete(std::string_view key, const vector<string>& nss) {
111*5a923131SAndroid Build Coastguard Worker bool success = Delete(key);
112*5a923131SAndroid Build Coastguard Worker for (const auto& ns : nss) {
113*5a923131SAndroid Build Coastguard Worker vector<string> ns_keys;
114*5a923131SAndroid Build Coastguard Worker success = GetSubKeys(ns, &ns_keys) && success;
115*5a923131SAndroid Build Coastguard Worker for (const auto& sub_key : ns_keys) {
116*5a923131SAndroid Build Coastguard Worker auto last_key_seperator = sub_key.find_last_of(kKeySeparator);
117*5a923131SAndroid Build Coastguard Worker if (last_key_seperator != string::npos &&
118*5a923131SAndroid Build Coastguard Worker key == sub_key.substr(last_key_seperator + 1)) {
119*5a923131SAndroid Build Coastguard Worker success = Delete(sub_key) && success;
120*5a923131SAndroid Build Coastguard Worker }
121*5a923131SAndroid Build Coastguard Worker }
122*5a923131SAndroid Build Coastguard Worker }
123*5a923131SAndroid Build Coastguard Worker return success;
124*5a923131SAndroid Build Coastguard Worker }
125*5a923131SAndroid Build Coastguard Worker
GetSubKeys(std::string_view ns,vector<string> * keys) const126*5a923131SAndroid Build Coastguard Worker bool FakePrefs::GetSubKeys(std::string_view ns, vector<string>* keys) const {
127*5a923131SAndroid Build Coastguard Worker for (const auto& pr : values_)
128*5a923131SAndroid Build Coastguard Worker if (pr.first.compare(0, ns.length(), ns) == 0)
129*5a923131SAndroid Build Coastguard Worker keys->push_back(pr.first);
130*5a923131SAndroid Build Coastguard Worker return true;
131*5a923131SAndroid Build Coastguard Worker }
132*5a923131SAndroid Build Coastguard Worker
GetTypeName(PrefType type)133*5a923131SAndroid Build Coastguard Worker string FakePrefs::GetTypeName(PrefType type) {
134*5a923131SAndroid Build Coastguard Worker switch (type) {
135*5a923131SAndroid Build Coastguard Worker case PrefType::kString:
136*5a923131SAndroid Build Coastguard Worker return "string";
137*5a923131SAndroid Build Coastguard Worker case PrefType::kInt64:
138*5a923131SAndroid Build Coastguard Worker return "int64_t";
139*5a923131SAndroid Build Coastguard Worker case PrefType::kBool:
140*5a923131SAndroid Build Coastguard Worker return "bool";
141*5a923131SAndroid Build Coastguard Worker }
142*5a923131SAndroid Build Coastguard Worker return "Unknown";
143*5a923131SAndroid Build Coastguard Worker }
144*5a923131SAndroid Build Coastguard Worker
CheckKeyType(std::string_view key,PrefType type) const145*5a923131SAndroid Build Coastguard Worker void FakePrefs::CheckKeyType(std::string_view key, PrefType type) const {
146*5a923131SAndroid Build Coastguard Worker auto it = values_.find(key);
147*5a923131SAndroid Build Coastguard Worker EXPECT_TRUE(it == values_.end() || it->second.type == type)
148*5a923131SAndroid Build Coastguard Worker << "Key \"" << key << "\" if defined as " << GetTypeName(it->second.type)
149*5a923131SAndroid Build Coastguard Worker << " but is accessed as a " << GetTypeName(type);
150*5a923131SAndroid Build Coastguard Worker }
151*5a923131SAndroid Build Coastguard Worker
152*5a923131SAndroid Build Coastguard Worker template <typename T>
SetValue(std::string_view key,T value)153*5a923131SAndroid Build Coastguard Worker void FakePrefs::SetValue(std::string_view key, T value) {
154*5a923131SAndroid Build Coastguard Worker std::string str_key{key};
155*5a923131SAndroid Build Coastguard Worker CheckKeyType(key, PrefConsts<T>::type);
156*5a923131SAndroid Build Coastguard Worker values_[str_key].type = PrefConsts<T>::type;
157*5a923131SAndroid Build Coastguard Worker values_[str_key].value.*(PrefConsts<T>::member) = std::move(value);
158*5a923131SAndroid Build Coastguard Worker const auto observers_for_key = observers_.find(key);
159*5a923131SAndroid Build Coastguard Worker if (observers_for_key != observers_.end()) {
160*5a923131SAndroid Build Coastguard Worker std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
161*5a923131SAndroid Build Coastguard Worker for (ObserverInterface* observer : copy_observers)
162*5a923131SAndroid Build Coastguard Worker observer->OnPrefSet(key);
163*5a923131SAndroid Build Coastguard Worker }
164*5a923131SAndroid Build Coastguard Worker }
165*5a923131SAndroid Build Coastguard Worker
166*5a923131SAndroid Build Coastguard Worker template <typename T>
GetValue(std::string_view key,T * value) const167*5a923131SAndroid Build Coastguard Worker bool FakePrefs::GetValue(std::string_view key, T* value) const {
168*5a923131SAndroid Build Coastguard Worker CheckKeyType(key, PrefConsts<T>::type);
169*5a923131SAndroid Build Coastguard Worker auto it = values_.find(key);
170*5a923131SAndroid Build Coastguard Worker if (it == values_.end())
171*5a923131SAndroid Build Coastguard Worker return false;
172*5a923131SAndroid Build Coastguard Worker CheckNotNull(key, value);
173*5a923131SAndroid Build Coastguard Worker *value = it->second.value.*(PrefConsts<T>::member);
174*5a923131SAndroid Build Coastguard Worker return true;
175*5a923131SAndroid Build Coastguard Worker }
176*5a923131SAndroid Build Coastguard Worker
AddObserver(std::string_view key,ObserverInterface * observer)177*5a923131SAndroid Build Coastguard Worker void FakePrefs::AddObserver(std::string_view key, ObserverInterface* observer) {
178*5a923131SAndroid Build Coastguard Worker observers_[string{key}].push_back(observer);
179*5a923131SAndroid Build Coastguard Worker }
180*5a923131SAndroid Build Coastguard Worker
RemoveObserver(std::string_view key,ObserverInterface * observer)181*5a923131SAndroid Build Coastguard Worker void FakePrefs::RemoveObserver(std::string_view key,
182*5a923131SAndroid Build Coastguard Worker ObserverInterface* observer) {
183*5a923131SAndroid Build Coastguard Worker string str_key{key};
184*5a923131SAndroid Build Coastguard Worker std::vector<ObserverInterface*>& observers_for_key = observers_[str_key];
185*5a923131SAndroid Build Coastguard Worker auto observer_it =
186*5a923131SAndroid Build Coastguard Worker std::find(observers_for_key.begin(), observers_for_key.end(), observer);
187*5a923131SAndroid Build Coastguard Worker EXPECT_NE(observer_it, observers_for_key.end())
188*5a923131SAndroid Build Coastguard Worker << "Trying to remove an observer instance not watching the key " << key;
189*5a923131SAndroid Build Coastguard Worker if (observer_it != observers_for_key.end())
190*5a923131SAndroid Build Coastguard Worker observers_for_key.erase(observer_it);
191*5a923131SAndroid Build Coastguard Worker if (observers_for_key.empty())
192*5a923131SAndroid Build Coastguard Worker observers_.erase(str_key);
193*5a923131SAndroid Build Coastguard Worker }
194*5a923131SAndroid Build Coastguard Worker
195*5a923131SAndroid Build Coastguard Worker } // namespace chromeos_update_engine
196