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

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

Issue 2812863002: Pref service: Add a ScopedDictionaryPrefUpdate to track value changes. (Closed)
Patch Set: rebase Created 3 years, 8 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/persistent_pref_store_client.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/pref_notifier_impl.h"
15 #include "components/prefs/pref_registry_simple.h"
16 #include "components/prefs/pref_service.h"
17 #include "mojo/public/cpp/bindings/binding_set.h"
18 #include "services/preferences/public/cpp/scoped_pref_update.h"
19 #include "services/preferences/public/interfaces/preferences.mojom.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace prefs {
23 namespace {
24
25 constexpr char kDictionaryKey[] = "path.to.key";
26 constexpr char kUninitializedDictionaryKey[] = "path.to.an.uninitialized.dict";
27
28 void DoNothingWithReadError(::PersistentPrefStore::PrefReadError read_error) {}
29
30 class PersistentPrefStoreClientTest : public testing::Test,
31 public mojom::PersistentPrefStore {
32 public:
33 PersistentPrefStoreClientTest() : binding_(this) {}
34
35 // testing::Test:
36 void SetUp() override {
37 auto persistent_pref_store_client = make_scoped_refptr(
38 new PersistentPrefStoreClient(mojom::PersistentPrefStoreConnection::New(
39 mojom::PrefStoreConnection::New(
40 mojom::PrefStoreObserverRequest(),
41 base::MakeUnique<base::DictionaryValue>(), true),
42 binding_.CreateInterfacePtrAndBind(),
43 ::PersistentPrefStore::PREF_READ_ERROR_NONE, false)));
44 auto pref_registry = make_scoped_refptr(new PrefRegistrySimple());
45 pref_registry->RegisterDictionaryPref(kDictionaryKey);
46 pref_registry->RegisterDictionaryPref(kUninitializedDictionaryKey);
47 PrefNotifierImpl* pref_notifier = new PrefNotifierImpl;
48 pref_service_ = base::MakeUnique<PrefService>(
49 pref_notifier,
50 new PrefValueStore(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
51 nullptr, pref_notifier),
52 persistent_pref_store_client.get(), pref_registry.get(),
53 base::Bind(&DoNothingWithReadError), false);
54 { ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey); }
55 auto update = WaitForUpdate();
56 ASSERT_TRUE(update->is_atomic_update());
57 EXPECT_EQ(base::DictionaryValue(), *update->get_atomic_update());
58 }
59
60 void TearDown() override {
61 pref_service_ = nullptr;
62 base::RunLoop().RunUntilIdle();
63 binding_.Close();
64 base::RunLoop().RunUntilIdle();
65 }
66
67 PrefService* pref_service() { return pref_service_.get(); }
68
69 mojom::PrefUpdateValuePtr WaitForUpdate() {
70 base::RunLoop run_loop;
71 on_update_ = run_loop.QuitClosure();
72 run_loop.Run();
73 EXPECT_EQ(1u, last_updates_.size());
74 auto result = std::move(last_updates_[0]->value);
75 last_updates_.clear();
76 return result;
77 }
78
79 void ExpectNoUpdate() {
80 binding_.FlushForTesting();
81 EXPECT_TRUE(last_updates_.empty());
82 }
83
84 private:
85 void SetValues(std::vector<mojom::PrefUpdatePtr> updates) override {
86 last_updates_ = std::move(updates);
87 if (on_update_)
88 std::move(on_update_).Run();
89 }
90
91 void CommitPendingWrite() override {}
92 void SchedulePendingLossyWrites() override {}
93 void ClearMutableValues() override {}
94
95 base::MessageLoop message_loop_;
96
97 std::unique_ptr<PrefService> pref_service_;
98
99 mojo::Binding<mojom::PersistentPrefStore> binding_;
100
101 std::vector<mojom::PrefUpdatePtr> last_updates_;
102 base::OnceClosure on_update_;
103
104 DISALLOW_COPY_AND_ASSIGN(PersistentPrefStoreClientTest);
105 };
106
107 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_Basic) {
108 {
109 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
110 update->SetInteger("path.to.integer", 1);
111 }
112 auto update = WaitForUpdate();
113 ASSERT_TRUE(update->is_split_updates());
114 auto& split_updates = update->get_split_updates();
115 ASSERT_EQ(1u, split_updates.size());
116 EXPECT_EQ(base::Value(1), *split_updates[0]->value);
117 EXPECT_EQ((std::vector<std::string>{"path", "to", "integer"}),
118 split_updates[0]->path);
119 }
120
121 TEST_F(PersistentPrefStoreClientTest,
122 SubPrefUpdates_BasicWithoutPathExpansion) {
123 {
124 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
125 update->SetIntegerWithoutPathExpansion("key.for.integer", 1);
126 }
127 auto update = WaitForUpdate();
128 ASSERT_TRUE(update->is_split_updates());
129 auto& split_updates = update->get_split_updates();
130 EXPECT_EQ(1u, split_updates.size());
131 EXPECT_EQ(base::Value(1), *split_updates[0]->value);
132 EXPECT_EQ((std::vector<std::string>{"key.for.integer"}),
133 split_updates[0]->path);
134 }
135
136 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_Remove) {
137 {
138 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
139 update->SetInteger("path.to.another_integer", 1);
140 update->SetInteger("path.to.integer", 1);
141 }
142 WaitForUpdate();
143 {
144 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
145 update->Remove("path.to.integer", nullptr);
146 }
147 auto update = WaitForUpdate();
148 ASSERT_TRUE(update->is_split_updates());
149 auto& split_updates = update->get_split_updates();
150 ASSERT_EQ(1u, split_updates.size());
151 EXPECT_FALSE(split_updates[0]->value);
152 EXPECT_EQ((std::vector<std::string>{"path", "to", "integer"}),
153 split_updates[0]->path);
154 }
155
156 TEST_F(PersistentPrefStoreClientTest,
157 SubPrefUpdates_RemoveWithoutPathExpansion) {
158 {
159 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
160 update->SetIntegerWithoutPathExpansion("path.to.another_integer", 1);
161 update->SetIntegerWithoutPathExpansion("path.to.integer", 1);
162 }
163 WaitForUpdate();
164 {
165 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
166 update->RemoveWithoutPathExpansion("path.to.integer", nullptr);
167 }
168 auto update = WaitForUpdate();
169 ASSERT_TRUE(update->is_split_updates());
170 auto& split_updates = update->get_split_updates();
171 ASSERT_EQ(1u, split_updates.size());
172 EXPECT_FALSE(split_updates[0]->value);
173 EXPECT_EQ((std::vector<std::string>{"path.to.integer"}),
174 split_updates[0]->path);
175 }
176
177 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_MultipleUpdates) {
178 {
179 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
180 update->SetDoubleWithoutPathExpansion("a.double", 1);
181 }
182 {
183 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
184 update->SetInteger("path.to.integer", 2);
185 }
186 auto update = WaitForUpdate();
187 ASSERT_TRUE(update->is_split_updates());
188 auto& split_updates = update->get_split_updates();
189 ASSERT_EQ(2u, split_updates.size());
190 EXPECT_EQ(base::Value(1.0), *split_updates[0]->value);
191 EXPECT_EQ((std::vector<std::string>{"a.double"}), split_updates[0]->path);
192 EXPECT_EQ(base::Value(2), *split_updates[1]->value);
193 EXPECT_EQ((std::vector<std::string>{"path", "to", "integer"}),
194 split_updates[1]->path);
195 }
196
197 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_NestedUpdateAfterSet) {
198 {
199 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
200 update->SetInteger("path.to.integer", 1);
201 }
202 {
203 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
204 DictionaryValueUpdate* dict;
205 ASSERT_TRUE(update->GetDictionary("path.to", &dict));
206 dict->Clear();
207 }
208 auto update = WaitForUpdate();
209 ASSERT_TRUE(update->is_split_updates());
210 auto& split_updates = update->get_split_updates();
211 ASSERT_EQ(1u, split_updates.size());
212 EXPECT_EQ(base::DictionaryValue(), *split_updates[0]->value);
213 EXPECT_EQ((std::vector<std::string>{"path", "to"}), split_updates[0]->path);
214 }
215
216 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_NestedUpdateBeforeSet) {
217 {
218 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
219 update->Set("path.to", base::MakeUnique<base::DictionaryValue>());
220 }
221 {
222 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
223 update->SetInteger("path.to.integer", 1);
224 }
225 auto update = WaitForUpdate();
226 ASSERT_TRUE(update->is_split_updates());
227 auto& split_updates = update->get_split_updates();
228 ASSERT_EQ(1u, split_updates.size());
229 base::DictionaryValue expected_value;
230 expected_value.SetInteger("integer", 1);
231 EXPECT_EQ(expected_value, *split_updates[0]->value);
232 EXPECT_EQ((std::vector<std::string>{"path", "to"}), split_updates[0]->path);
233 }
234
235 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_DoubleNestedUpdate) {
236 {
237 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
238 update->SetInteger("path.to.integer", 1);
239 }
240 {
241 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
242 DictionaryValueUpdate* dict;
243 ASSERT_TRUE(update->GetDictionary("path", &dict));
244 dict->Clear();
245 }
246 auto update = WaitForUpdate();
247 ASSERT_TRUE(update->is_split_updates());
248 auto& split_updates = update->get_split_updates();
249 ASSERT_EQ(1u, split_updates.size());
250 EXPECT_EQ(base::DictionaryValue(), *split_updates[0]->value);
251 EXPECT_EQ((std::vector<std::string>{"path"}), split_updates[0]->path);
252 }
253
254 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_ManualNesting) {
255 {
256 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
257 update->SetInteger("path.to.integer", 1);
258 }
259 WaitForUpdate();
260 {
261 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
262 DictionaryValueUpdate* dict = nullptr;
263 ASSERT_TRUE(update->GetDictionary("path.to", &dict));
264 dict->SetString("string", "string value");
265 }
266 auto update = WaitForUpdate();
267 ASSERT_TRUE(update->is_split_updates());
268 auto& split_updates = update->get_split_updates();
269 ASSERT_EQ(1u, split_updates.size());
270 EXPECT_EQ(base::Value("string value"), *split_updates[0]->value);
271 EXPECT_EQ((std::vector<std::string>{"path", "to", "string"}),
272 split_updates[0]->path);
273 }
274
275 TEST_F(PersistentPrefStoreClientTest,
276 SubPrefUpdates_ManualDictCreationAndNesting) {
277 {
278 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
279 auto* dict = update->SetDictionary(
280 "path.to", base::MakeUnique<base::DictionaryValue>());
281 dict->SetString("string", "string value");
282 }
283 auto update = WaitForUpdate();
284 ASSERT_TRUE(update->is_split_updates());
285 auto& split_updates = update->get_split_updates();
286 ASSERT_EQ(1u, split_updates.size());
287 base::DictionaryValue expected_value;
288 expected_value.SetString("string", "string value");
289 EXPECT_EQ(expected_value, *split_updates[0]->value);
290 EXPECT_EQ((std::vector<std::string>{"path", "to"}), split_updates[0]->path);
291 }
292
293 TEST_F(PersistentPrefStoreClientTest,
294 SubPrefUpdates_ManualDictCreationWithoutPathExpansionAndNesting) {
295 {
296 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
297 auto* dict = update->SetDictionaryWithoutPathExpansion(
298 "a.dictionary", base::MakeUnique<base::DictionaryValue>());
299 dict->SetStringWithoutPathExpansion("a.string", "string value");
300 }
301 auto update = WaitForUpdate();
302 ASSERT_TRUE(update->is_split_updates());
303 auto& split_updates = update->get_split_updates();
304 ASSERT_EQ(1u, split_updates.size());
305 base::DictionaryValue expected_value;
306 expected_value.SetStringWithoutPathExpansion("a.string", "string value");
307 EXPECT_EQ(expected_value, *split_updates[0]->value);
308 EXPECT_EQ((std::vector<std::string>{"a.dictionary"}), split_updates[0]->path);
309 }
310
311 TEST_F(PersistentPrefStoreClientTest,
312 SubPrefUpdates_AsDictionaryTriggersFullWrite) {
313 {
314 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
315 update->SetInteger("path.to.integer", 1);
316 update->AsDictionary();
317 }
318 auto update = WaitForUpdate();
319 ASSERT_TRUE(update->is_atomic_update());
320 base::DictionaryValue expected_value;
321 expected_value.SetInteger("path.to.integer", 1);
322 EXPECT_EQ(expected_value, *update->get_atomic_update());
323 }
324
325 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_AsConstDictionaryIsNoOp) {
326 {
327 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
328 update->SetInteger("path.to.integer", 1);
329 update->AsConstDictionary();
330 }
331 auto update = WaitForUpdate();
332 ASSERT_TRUE(update->is_split_updates());
333 auto& split_updates = update->get_split_updates();
334 ASSERT_EQ(1u, split_updates.size());
335 EXPECT_EQ(base::Value(1), *split_updates[0]->value);
336 EXPECT_EQ((std::vector<std::string>{"path", "to", "integer"}),
337 split_updates[0]->path);
338 }
339
340 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_RemovePath_Basic) {
341 {
342 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
343 update->SetInteger("path.to.integer", 1);
344 update->SetInteger("path.to.something.else", 1);
345 }
346 WaitForUpdate();
347 {
348 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
349 update->RemovePath("path.to.integer", nullptr);
350 }
351 auto update = WaitForUpdate();
352 ASSERT_TRUE(update->is_split_updates());
353 auto& split_updates = update->get_split_updates();
354 ASSERT_EQ(1u, split_updates.size());
355 EXPECT_FALSE(split_updates[0]->value);
356 EXPECT_EQ((std::vector<std::string>{"path", "to", "integer"}),
357 split_updates[0]->path);
358 }
359
360 TEST_F(PersistentPrefStoreClientTest,
361 SubPrefUpdates_RemovePath_RemoveContainingDict) {
362 {
363 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
364 update->SetInteger("path.to.integer", 1);
365 update->SetInteger("path.for.something.else", 1);
366 }
367 WaitForUpdate();
368 {
369 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
370 update->RemovePath("path.to.integer", nullptr);
371 }
372 auto update = WaitForUpdate();
373 ASSERT_TRUE(update->is_split_updates());
374 auto& split_updates = update->get_split_updates();
375 ASSERT_EQ(1u, split_updates.size());
376 EXPECT_FALSE(split_updates[0]->value);
377 EXPECT_EQ((std::vector<std::string>{"path", "to"}), split_updates[0]->path);
378 }
379
380 TEST_F(PersistentPrefStoreClientTest,
381 SubPrefUpdates_RemovePath_SinglePathComponent) {
382 {
383 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
384 update->SetInteger("integer", 1);
385 update->SetInteger("something_else", 1);
386 }
387 WaitForUpdate();
388 {
389 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
390 update->RemovePath("integer", nullptr);
391 }
392 auto update = WaitForUpdate();
393 ASSERT_TRUE(update->is_split_updates());
394 auto& split_updates = update->get_split_updates();
395 ASSERT_EQ(1u, split_updates.size());
396 EXPECT_FALSE(split_updates[0]->value);
397 EXPECT_EQ((std::vector<std::string>{"integer"}), split_updates[0]->path);
398 }
399
400 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_RemovePath_FullPref) {
401 {
402 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
403 update->SetInteger("path.to.integer", 1);
404 }
405 WaitForUpdate();
406 {
407 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
408 update->RemovePath("path.to.integer", nullptr);
409 }
410 auto update = WaitForUpdate();
411 ASSERT_TRUE(update->is_split_updates());
412 auto& split_updates = update->get_split_updates();
413 ASSERT_EQ(1u, split_updates.size());
414 EXPECT_FALSE(split_updates[0]->value);
415 EXPECT_EQ((std::vector<std::string>{"path"}), split_updates[0]->path);
416 }
417
418 TEST_F(PersistentPrefStoreClientTest,
419 SubPrefUpdates_RemovePathSinglePathComponent_FullPref) {
420 {
421 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
422 update->SetInteger("integer", 1);
423 }
424 WaitForUpdate();
425 {
426 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
427 update->RemovePath("integer", nullptr);
428 }
429 auto update = WaitForUpdate();
430 ASSERT_TRUE(update->is_split_updates());
431 auto& split_updates = update->get_split_updates();
432 ASSERT_EQ(1u, split_updates.size());
433 EXPECT_FALSE(split_updates[0]->value);
434 EXPECT_EQ((std::vector<std::string>{"integer"}), split_updates[0]->path);
435 }
436
437 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_NoChange) {
438 {
439 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
440 update->SetInteger("path.to.integer", 1);
441 }
442 WaitForUpdate();
443 { ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey); }
444 ExpectNoUpdate();
445 }
446
447 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_SetToExistingValue) {
448 {
449 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
450 update->SetInteger("path.to.integer", 1);
451 }
452 WaitForUpdate();
453 {
454 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
455 update->SetInteger("path.to.integer", 1);
456 }
457 ExpectNoUpdate();
458 }
459
460 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_ClearEmptyDictionary) {
461 {
462 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
463 update->Clear();
464 }
465 ExpectNoUpdate();
466 }
467
468 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_ReplaceDictionary) {
469 {
470 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
471 update->SetInteger("path.to.integer", 1);
472 }
473 WaitForUpdate();
474 {
475 ScopedDictionaryPrefUpdate update(pref_service(), kDictionaryKey);
476 update->SetInteger("path", 2);
477 }
478 auto update = WaitForUpdate();
479 ASSERT_TRUE(update->is_split_updates());
480 auto& split_updates = update->get_split_updates();
481 ASSERT_EQ(1u, split_updates.size());
482 EXPECT_EQ(base::Value(2), *split_updates[0]->value);
483 EXPECT_EQ((std::vector<std::string>{"path"}), split_updates[0]->path);
484 }
485
486 TEST_F(PersistentPrefStoreClientTest, SubPrefUpdates_Uninitialized) {
487 {
488 ScopedDictionaryPrefUpdate update(pref_service(),
489 kUninitializedDictionaryKey);
490 update->SetInteger("path.to.integer", 1);
491 }
492 auto update = WaitForUpdate();
493 ASSERT_TRUE(update->is_atomic_update());
494 base::DictionaryValue expected_value;
495 expected_value.SetInteger("path.to.integer", 1);
496 EXPECT_EQ(expected_value, *update->get_atomic_update());
497 }
498
499 } // namespace
500 } // namespace prefs
OLDNEW
« no previous file with comments | « services/preferences/public/cpp/tests/BUILD.gn ('k') | services/preferences/public/cpp/tests/pref_store_client_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698