1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2014 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
16608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/fake_prefs.h"
18608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
19d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo#include <algorithm>
20d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo
21608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo#include <gtest/gtest.h>
22608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
23608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymousing std::string;
24608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
25608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymousing chromeos_update_engine::FakePrefs;
26608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
27608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymonamespace {
28608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
29608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymovoid CheckNotNull(const string& key, void* ptr) {
30608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  EXPECT_NE(nullptr, ptr)
3188b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko      << "Called Get*() for key \"" << key << "\" with a null parameter.";
32608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
33608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
34608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}  // namespace
35608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
36608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymonamespace chromeos_update_engine {
37608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
38d6f60079258fa385b583dac9e770afd2ea3c9aebAlex DeymoFakePrefs::~FakePrefs() {
39d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  EXPECT_TRUE(observers_.empty());
40d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo}
41d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo
42608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo// Compile-time type-dependent constants definitions.
43608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymotemplate<>
44608a36586dd4a990b63b0e7a195bfef191db5c69Alex DeymoFakePrefs::PrefType const FakePrefs::PrefConsts<string>::type =
45608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    FakePrefs::PrefType::kString;
46608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymotemplate<>
47d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenkostring FakePrefs::PrefValue::* const  // NOLINT(runtime/string), not static str.
48d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko    FakePrefs::PrefConsts<string>::member = &FakePrefs::PrefValue::as_str;
49608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
50608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymotemplate<>
51608a36586dd4a990b63b0e7a195bfef191db5c69Alex DeymoFakePrefs::PrefType const FakePrefs::PrefConsts<int64_t>::type =
52608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    FakePrefs::PrefType::kInt64;
53608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymotemplate<>
54608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymoint64_t FakePrefs::PrefValue::* const FakePrefs::PrefConsts<int64_t>::member =
55608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    &FakePrefs::PrefValue::as_int64;
56608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
57608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymotemplate<>
58608a36586dd4a990b63b0e7a195bfef191db5c69Alex DeymoFakePrefs::PrefType const FakePrefs::PrefConsts<bool>::type =
59608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    FakePrefs::PrefType::kBool;
60608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymotemplate<>
61608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymobool FakePrefs::PrefValue::* const FakePrefs::PrefConsts<bool>::member =
62608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    &FakePrefs::PrefValue::as_bool;
63608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
64d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymobool FakePrefs::GetString(const string& key, string* value) const {
65608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return GetValue(key, value);
66608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
67608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
68f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool FakePrefs::SetString(const string& key, const string& value) {
69608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  SetValue(key, value);
70608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return true;
71608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
72608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
73d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymobool FakePrefs::GetInt64(const string& key, int64_t* value) const {
74608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return GetValue(key, value);
75608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
76608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
77608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymobool FakePrefs::SetInt64(const string& key, const int64_t value) {
78608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  SetValue(key, value);
79608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return true;
80608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
81608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
82d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymobool FakePrefs::GetBoolean(const string& key, bool* value) const {
83608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return GetValue(key, value);
84608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
85608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
86608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymobool FakePrefs::SetBoolean(const string& key, const bool value) {
87608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  SetValue(key, value);
88608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return true;
89608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
90608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
91d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymobool FakePrefs::Exists(const string& key) const {
92608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return values_.find(key) != values_.end();
93608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
94608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
95608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymobool FakePrefs::Delete(const string& key) {
96608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  if (values_.find(key) == values_.end())
97608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    return false;
98608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  values_.erase(key);
99d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  const auto observers_for_key = observers_.find(key);
100d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  if (observers_for_key != observers_.end()) {
101d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo    std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
102d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo    for (ObserverInterface* observer : copy_observers)
103d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo      observer->OnPrefDeleted(key);
104d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  }
105608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return true;
106608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
107608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
108608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymostring FakePrefs::GetTypeName(PrefType type) {
109608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  switch (type) {
110608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    case PrefType::kString:
111608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo      return "string";
112608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    case PrefType::kInt64:
113608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo      return "int64_t";
114608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    case PrefType::kBool:
115608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo      return "bool";
116608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  }
117608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return "Unknown";
118608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
119608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
120608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymovoid FakePrefs::CheckKeyType(const string& key, PrefType type) const {
121608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  auto it = values_.find(key);
122608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  EXPECT_TRUE(it == values_.end() || it->second.type == type)
123608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo      << "Key \"" << key << "\" if defined as " << GetTypeName(it->second.type)
124608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo      << " but is accessed as a " << GetTypeName(type);
125608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
126608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
127608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymotemplate<typename T>
128608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymovoid FakePrefs::SetValue(const string& key, const T& value) {
129608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  CheckKeyType(key, PrefConsts<T>::type);
130608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  values_[key].type = PrefConsts<T>::type;
131608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  values_[key].value.*(PrefConsts<T>::member) = value;
132d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  const auto observers_for_key = observers_.find(key);
133d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  if (observers_for_key != observers_.end()) {
134d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo    std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
135d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo    for (ObserverInterface* observer : copy_observers)
136d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo      observer->OnPrefSet(key);
137d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  }
138608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
139608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
140608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymotemplate<typename T>
141608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymobool FakePrefs::GetValue(const string& key, T* value) const {
142608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  CheckKeyType(key, PrefConsts<T>::type);
143608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  auto it = values_.find(key);
144608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  if (it == values_.end())
145608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo    return false;
146608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  CheckNotNull(key, value);
147608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  *value = it->second.value.*(PrefConsts<T>::member);
148608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo  return true;
149608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}
150608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo
151d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymovoid FakePrefs::AddObserver(const string& key, ObserverInterface* observer) {
152d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  observers_[key].push_back(observer);
153d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo}
154d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo
155d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymovoid FakePrefs::RemoveObserver(const string& key, ObserverInterface* observer) {
156d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  std::vector<ObserverInterface*>& observers_for_key = observers_[key];
157d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  auto observer_it =
158d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo      std::find(observers_for_key.begin(), observers_for_key.end(), observer);
159d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  EXPECT_NE(observer_it, observers_for_key.end())
160d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo      << "Trying to remove an observer instance not watching the key "
161d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo      << key;
162d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  if (observer_it != observers_for_key.end())
163d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo    observers_for_key.erase(observer_it);
164d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo  if (observers_for_key.empty())
165d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo    observers_.erase(key);
166d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo}
167d6f60079258fa385b583dac9e770afd2ea3c9aebAlex Deymo
168608a36586dd4a990b63b0e7a195bfef191db5c69Alex Deymo}  // namespace chromeos_update_engine
169