Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(432)

Side by Side Diff: services/preferences/public/cpp/tests/pref_store_impl_unittest.cc

Issue 2778643002: Pref service: Filter updates from read-only pref stores. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/preferences/public/cpp/pref_store_impl.h"
6
7 #include <utility>
8
9 #include "base/macros.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/values.h"
14 #include "components/prefs/value_map_pref_store.h"
15 #include "mojo/public/cpp/bindings/binding_set.h"
16 #include "services/preferences/public/cpp/pref_store_client.h"
17 #include "services/preferences/public/interfaces/preferences.mojom.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 using testing::Invoke;
22 using testing::WithoutArgs;
23
24 namespace prefs {
25 namespace {
26
27 class PrefStoreObserverMock : public PrefStore::Observer {
28 public:
29 MOCK_METHOD1(OnPrefValueChanged, void(const std::string&));
30 MOCK_METHOD1(OnInitializationCompleted, void(bool));
31 };
32
33 class MockPrefStore : public ValueMapPrefStore {
34 public:
35 bool IsInitializationComplete() const override {
36 return initialized_ && success_;
37 }
38
39 void AddObserver(PrefStore::Observer* observer) override {
40 observers_.AddObserver(observer);
41 }
42
43 void RemoveObserver(PrefStore::Observer* observer) override {
44 observers_.RemoveObserver(observer);
45 }
46
47 void CompleteInitialization(bool success) {
48 initialized_ = true;
49 success_ = success;
50 for (auto& observer : observers_) {
51 // Some pref stores report completing initialization more than once. Test
52 // that additional calls are ignored.
53 observer.OnInitializationCompleted(success);
54 observer.OnInitializationCompleted(success);
55 }
56 }
57
58 void SetValue(const std::string& key,
59 std::unique_ptr<base::Value> value,
60 uint32_t flags) override {
61 ValueMapPrefStore::SetValue(key, std::move(value), flags);
62 for (auto& observer : observers_) {
63 observer.OnPrefValueChanged(key);
64 }
65 }
66
67 private:
68 ~MockPrefStore() override = default;
69
70 bool initialized_ = false;
71 bool success_ = false;
72 base::ObserverList<PrefStore::Observer, true> observers_;
73 };
74
75 constexpr char kKey[] = "path.to.key";
76 constexpr char kOtherKey[] = "path.to.other_key";
77
78 void ExpectInitializationComplete(PrefStore* pref_store, bool success) {
79 PrefStoreObserverMock observer;
80 pref_store->AddObserver(&observer);
81 base::RunLoop run_loop;
82 EXPECT_CALL(observer, OnPrefValueChanged("")).Times(0);
83 EXPECT_CALL(observer, OnInitializationCompleted(success))
84 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
85 run_loop.Run();
86 pref_store->RemoveObserver(&observer);
87 }
88
89 void ExpectPrefChange(PrefStore* pref_store, base::StringPiece key) {
90 PrefStoreObserverMock observer;
91 pref_store->AddObserver(&observer);
92 base::RunLoop run_loop;
93 EXPECT_CALL(observer, OnPrefValueChanged(key.as_string()))
94 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
95 run_loop.Run();
96 pref_store->RemoveObserver(&observer);
97 }
98
99 class PrefStoreImplTest : public testing::Test {
100 public:
101 PrefStoreImplTest() = default;
102
103 // testing::Test:
104 void TearDown() override {
105 pref_store_ = nullptr;
106 base::RunLoop().RunUntilIdle();
107 pref_store_ptr_.reset();
108 base::RunLoop().RunUntilIdle();
109 impl_.reset();
110 base::RunLoop().RunUntilIdle();
111 }
112
113 void CreateImpl(
114 scoped_refptr<PrefStore> backing_pref_store,
115 std::vector<std::string> observed_prefs = std::vector<std::string>()) {
116 impl_ = base::MakeUnique<PrefStoreImpl>(
117 std::move(backing_pref_store), mojo::MakeRequest(&pref_store_ptr_));
118
119 if (observed_prefs.empty())
120 observed_prefs.insert(observed_prefs.end(), {kKey, kOtherKey});
121 pref_store_ = CreateConnection(std::move(observed_prefs));
122 }
123
124 scoped_refptr<PrefStore> CreateConnection(
125 std::vector<std::string> observed_prefs) {
126 base::RunLoop run_loop;
127 mojom::PrefStoreConnectionPtr connection;
128 pref_store_ptr_->AddObserver(
129 observed_prefs,
130 base::Bind(
131 [](mojom::PrefStoreConnectionPtr* output, base::OnceClosure quit,
132 mojom::PrefStoreConnectionPtr connection) {
133 std::move(quit).Run();
134 *output = std::move(connection);
135 },
136 &connection, run_loop.QuitClosure()));
137 run_loop.Run();
138 return make_scoped_refptr(new PrefStoreClient(std::move(connection)));
139 }
140
141 PrefStore* pref_store() { return pref_store_.get(); }
142
143 private:
144 base::MessageLoop message_loop_;
145
146 std::unique_ptr<PrefStoreImpl> impl_;
147 mojom::PrefStorePtr pref_store_ptr_;
148
149 scoped_refptr<PrefStore> pref_store_;
150
151 DISALLOW_COPY_AND_ASSIGN(PrefStoreImplTest);
152 };
153
154 TEST_F(PrefStoreImplTest, InitializationSuccess) {
155 auto backing_pref_store = make_scoped_refptr(new MockPrefStore());
156 backing_pref_store->SetValue(kKey, base::MakeUnique<base::Value>("value"), 0);
157 CreateImpl(backing_pref_store);
158 EXPECT_FALSE(pref_store()->IsInitializationComplete());
159
160 backing_pref_store->CompleteInitialization(true);
161 ExpectInitializationComplete(pref_store(), true);
162 EXPECT_TRUE(pref_store()->IsInitializationComplete());
163 }
164
165 TEST_F(PrefStoreImplTest, InitializationFailure) {
166 auto backing_pref_store = make_scoped_refptr(new MockPrefStore());
167 backing_pref_store->SetValue(kKey, base::MakeUnique<base::Value>("value"), 0);
168 CreateImpl(backing_pref_store);
169 EXPECT_FALSE(pref_store()->IsInitializationComplete());
170
171 backing_pref_store->CompleteInitialization(false);
172 ExpectInitializationComplete(pref_store(), false);
173
174 // TODO(sammc): Should IsInitializationComplete() return false?
175 EXPECT_TRUE(pref_store()->IsInitializationComplete());
176 }
177
178 TEST_F(PrefStoreImplTest, ValueChangesBeforeInitializationCompletes) {
179 auto backing_pref_store = make_scoped_refptr(new MockPrefStore());
180 CreateImpl(backing_pref_store);
181 EXPECT_FALSE(pref_store()->IsInitializationComplete());
182
183 const base::Value value("value");
184 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
185 backing_pref_store->CompleteInitialization(true);
186
187 // The update occurs before initialization has completed, so should not
188 // trigger notifications to client observers, but the value should be
189 // observable once initialization completes.
190 ExpectInitializationComplete(pref_store(), true);
191 EXPECT_TRUE(pref_store()->IsInitializationComplete());
192
193 const base::Value* output = nullptr;
194 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
195 EXPECT_TRUE(value.Equals(output));
196 }
197
198 TEST_F(PrefStoreImplTest, InitialValue) {
199 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
200 const base::Value value("value");
201 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
202 CreateImpl(backing_pref_store);
203 ASSERT_TRUE(pref_store()->IsInitializationComplete());
204 const base::Value* output = nullptr;
205 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
206 EXPECT_TRUE(value.Equals(output));
207 }
208
209 TEST_F(PrefStoreImplTest, InitialValueWithoutPathExpansion) {
210 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
211 base::DictionaryValue dict;
212 dict.SetStringWithoutPathExpansion(kKey, "value");
213 backing_pref_store->SetValue(kKey, dict.CreateDeepCopy(), 0);
214 CreateImpl(backing_pref_store);
215 ASSERT_TRUE(pref_store()->IsInitializationComplete());
216 const base::Value* output = nullptr;
217 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
218 EXPECT_TRUE(dict.Equals(output));
219 }
220
221 TEST_F(PrefStoreImplTest, WriteObservedByClient) {
222 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
223 CreateImpl(backing_pref_store);
224 ASSERT_TRUE(pref_store()->IsInitializationComplete());
225
226 const base::Value value("value");
227 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
228
229 ExpectPrefChange(pref_store(), kKey);
230 const base::Value* output = nullptr;
231 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
232 EXPECT_TRUE(value.Equals(output));
233 }
234
235 TEST_F(PrefStoreImplTest, WriteToUnregisteredPrefNotObservedByClient) {
236 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
237 CreateImpl(backing_pref_store, {kKey});
238 ASSERT_TRUE(pref_store()->IsInitializationComplete());
239
240 backing_pref_store->SetValue(kOtherKey, base::MakeUnique<base::Value>(123),
241 0);
242 backing_pref_store->SetValue(kKey, base::MakeUnique<base::Value>("value"), 0);
243
244 ExpectPrefChange(pref_store(), kKey);
245 EXPECT_FALSE(pref_store()->GetValue(kOtherKey, nullptr));
246 }
247
248 TEST_F(PrefStoreImplTest, WriteWithoutPathExpansionObservedByClient) {
249 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
250 CreateImpl(backing_pref_store);
251 ASSERT_TRUE(pref_store()->IsInitializationComplete());
252
253 base::DictionaryValue dict;
254 dict.SetStringWithoutPathExpansion(kKey, "value");
255 backing_pref_store->SetValue(kKey, dict.CreateDeepCopy(), 0);
256
257 ExpectPrefChange(pref_store(), kKey);
258 const base::Value* output = nullptr;
259 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
260 EXPECT_TRUE(dict.Equals(output));
261 }
262
263 TEST_F(PrefStoreImplTest, RemoveObservedByClient) {
264 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
265 const base::Value value("value");
266 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
267 CreateImpl(backing_pref_store);
268 ASSERT_TRUE(pref_store()->IsInitializationComplete());
269
270 const base::Value* output = nullptr;
271 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
272 EXPECT_TRUE(value.Equals(output));
273 backing_pref_store->RemoveValue(kKey, 0);
274
275 // This should be a no-op and shouldn't trigger a notification for the other
276 // client.
277 backing_pref_store->RemoveValue(kKey, 0);
278
279 ExpectPrefChange(pref_store(), kKey);
280 EXPECT_FALSE(pref_store()->GetValue(kKey, &output));
281 }
282
283 TEST_F(PrefStoreImplTest, RemoveOfUnregisteredPrefNotObservedByClient) {
284 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
285 const base::Value value("value");
286 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
287 backing_pref_store->SetValue(kOtherKey, value.CreateDeepCopy(), 0);
288 CreateImpl(backing_pref_store, {kKey});
289 ASSERT_TRUE(pref_store()->IsInitializationComplete());
290
291 backing_pref_store->RemoveValue(kOtherKey, 0);
292 backing_pref_store->RemoveValue(kKey, 0);
293
294 ExpectPrefChange(pref_store(), kKey);
295 }
296
297 TEST_F(PrefStoreImplTest, RemoveWithoutPathExpansionObservedByOtherClient) {
298 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
299 base::DictionaryValue dict;
300 dict.SetStringWithoutPathExpansion(kKey, "value");
301 backing_pref_store->SetValue(kKey, dict.CreateDeepCopy(), 0);
302 CreateImpl(backing_pref_store);
303 ASSERT_TRUE(pref_store()->IsInitializationComplete());
304
305 const base::Value* output = nullptr;
306 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
307 EXPECT_TRUE(dict.Equals(output));
308
309 base::Value* mutable_value = nullptr;
310 dict.SetStringWithoutPathExpansion(kKey, "value");
311 ASSERT_TRUE(backing_pref_store->GetMutableValue(kKey, &mutable_value));
312 base::DictionaryValue* mutable_dict = nullptr;
313 ASSERT_TRUE(mutable_value->GetAsDictionary(&mutable_dict));
314 mutable_dict->RemoveWithoutPathExpansion(kKey, nullptr);
315 backing_pref_store->ReportValueChanged(kKey, 0);
316
317 ExpectPrefChange(pref_store(), kKey);
318 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
319 const base::DictionaryValue* dict_value = nullptr;
320 ASSERT_TRUE(output->GetAsDictionary(&dict_value));
321 EXPECT_TRUE(dict_value->empty());
322 }
323
324 } // namespace
325 } // namespace prefs
OLDNEW
« no previous file with comments | « services/preferences/public/cpp/tests/BUILD.gn ('k') | services/preferences/public/interfaces/preferences.mojom » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698