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

Side by Side Diff: services/preferences/persistent_pref_store_impl_unittest.cc

Issue 2743563003: Pref service: add persistent pref store frontend and backend. (Closed)
Patch Set: rebase 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/persistent_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/in_memory_pref_store.h"
15 #include "mojo/public/cpp/bindings/binding_set.h"
16 #include "services/preferences/public/cpp/persistent_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 succeeded));
31 };
32
33 class PersistentPrefStoreMock : public InMemoryPrefStore {
34 public:
35 MOCK_METHOD0(CommitPendingWrite, void());
36 MOCK_METHOD0(SchedulePendingLossyWrites, void());
37 MOCK_METHOD0(ClearMutableValues, void());
38
39 private:
40 ~PersistentPrefStoreMock() override = default;
41 };
42
43 class PrefStoreConnectorMock : public mojom::PrefStoreConnector {
44 public:
45 MOCK_METHOD1(Connect, void(const ConnectCallback&));
46 };
47
48 class InitializationMockPersistentPrefStore : public InMemoryPrefStore {
49 public:
50 bool IsInitializationComplete() const override { return initialized_; }
51
52 void AddObserver(PrefStore::Observer* observer) override {
53 observers_.AddObserver(observer);
54 }
55
56 void RemoveObserver(PrefStore::Observer* observer) override {
57 observers_.RemoveObserver(observer);
58 }
59
60 void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override {
61 DCHECK(!error_delegate);
62 }
63
64 PersistentPrefStore::PrefReadError GetReadError() const override {
65 return read_error_;
66 }
67 bool ReadOnly() const override { return read_only_; }
68
69 void Initialize(bool success,
70 PersistentPrefStore::PrefReadError error,
71 bool read_only) {
72 initialized_ = success;
73 read_error_ = error;
74 read_only_ = read_only;
75 for (auto& observer : observers_) {
76 observer.OnInitializationCompleted(initialized_);
77 }
78 }
79
80 private:
81 ~InitializationMockPersistentPrefStore() override = default;
82
83 PersistentPrefStore::PrefReadError read_error_;
84 bool read_only_ = false;
85 bool initialized_ = false;
86 base::ObserverList<PrefStore::Observer, true> observers_;
87 };
88
89 class PersistentPrefStoreImplTest : public testing::Test {
90 public:
91 PersistentPrefStoreImplTest() = default;
92
93 // testing::Test:
94 void TearDown() override {
95 pref_store_ = nullptr;
96 base::RunLoop().RunUntilIdle();
97 bindings_.CloseAllBindings();
98 backing_pref_store_.reset();
99 base::RunLoop().RunUntilIdle();
100 }
101
102 void CreateImpl(scoped_refptr<PersistentPrefStore> backing_pref_store) {
103 backing_pref_store_ = base::MakeUnique<PersistentPrefStoreImpl>(
104 std::move(backing_pref_store), nullptr);
105 mojo::Binding<mojom::PersistentPrefStoreConnector> binding(
106 backing_pref_store_.get());
107 pref_store_ = CreateConnection();
108 }
109
110 mojom::PersistentPrefStoreConnectorPtr CreateConnector() {
111 return bindings_.CreateInterfacePtrAndBind(backing_pref_store_.get());
112 }
113
114 scoped_refptr<PersistentPrefStore> CreateConnection() {
115 return make_scoped_refptr(new PersistentPrefStoreClient(
116 bindings_.CreateInterfacePtrAndBind(backing_pref_store_.get())));
117 }
118
119 PersistentPrefStore* pref_store() { return pref_store_.get(); }
120
121 private:
122 base::MessageLoop message_loop_;
123
124 std::unique_ptr<PersistentPrefStoreImpl> backing_pref_store_;
125 mojo::BindingSet<mojom::PersistentPrefStoreConnector> bindings_;
126
127 scoped_refptr<PersistentPrefStore> pref_store_;
128
129 DISALLOW_COPY_AND_ASSIGN(PersistentPrefStoreImplTest);
130 };
131
132 TEST_F(PersistentPrefStoreImplTest, InitializationSuccess) {
133 auto backing_pref_store =
134 make_scoped_refptr(new InitializationMockPersistentPrefStore);
135 CreateImpl(backing_pref_store);
136 backing_pref_store->Initialize(
137 true, PersistentPrefStore::PREF_READ_ERROR_NONE, false);
138 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
139 pref_store()->ReadPrefs());
140 EXPECT_TRUE(pref_store()->IsInitializationComplete());
141 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
142 pref_store()->GetReadError());
143 EXPECT_FALSE(pref_store()->ReadOnly());
144 }
145
146 TEST_F(PersistentPrefStoreImplTest, InitializationFailure) {
147 auto backing_pref_store =
148 make_scoped_refptr(new InitializationMockPersistentPrefStore);
149 CreateImpl(backing_pref_store);
150 backing_pref_store->Initialize(
151 false, PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE, true);
152 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
153 pref_store()->ReadPrefs());
154 EXPECT_FALSE(pref_store()->IsInitializationComplete());
155 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_PARSE,
156 pref_store()->GetReadError());
157 EXPECT_TRUE(pref_store()->ReadOnly());
158 }
159
160 class TestReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
161 public:
162 TestReadErrorDelegate(PersistentPrefStore::PrefReadError* storage,
163 const base::Closure& quit)
164 : storage_(storage), quit_(quit) {
165 DCHECK(storage_);
166 DCHECK(quit_);
167 }
168
169 void OnError(PersistentPrefStore::PrefReadError error) override {
170 *storage_ = error;
171 quit_.Run();
172 }
173
174 private:
175 PersistentPrefStore::PrefReadError* const storage_;
176 const base::Closure quit_;
177 };
178
179 TEST_F(PersistentPrefStoreImplTest, InitializationFailure_AsyncRead) {
180 auto backing_pref_store =
181 make_scoped_refptr(new InitializationMockPersistentPrefStore);
182 CreateImpl(backing_pref_store);
183 backing_pref_store->Initialize(
184 false, PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE, true);
185 PersistentPrefStore::PrefReadError read_error =
186 PersistentPrefStore::PREF_READ_ERROR_NONE;
187 base::RunLoop run_loop;
188 pref_store()->ReadPrefsAsync(
189 new TestReadErrorDelegate(&read_error, run_loop.QuitClosure()));
190 run_loop.Run();
191 EXPECT_FALSE(pref_store()->IsInitializationComplete());
192 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE, read_error);
193 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE,
194 pref_store()->GetReadError());
195 EXPECT_TRUE(pref_store()->ReadOnly());
196 }
197
198 TEST_F(PersistentPrefStoreImplTest, DelayedInitializationSuccess) {
199 auto backing_pref_store =
200 make_scoped_refptr(new InitializationMockPersistentPrefStore);
201
202 CreateImpl(backing_pref_store);
203 auto connector = CreateConnector();
204 base::RunLoop run_loop;
205 connector->Connect(base::Bind(
206 [](const base::Closure& quit,
207 PersistentPrefStore::PrefReadError read_error, bool read_only,
208 std::unique_ptr<base::DictionaryValue> local_prefs,
209 mojom::PersistentPrefStorePtr pref_store,
210 mojom::PrefStoreObserverRequest observer_request) {
211 quit.Run();
212 EXPECT_FALSE(read_only);
213 EXPECT_TRUE(local_prefs);
214 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, read_error);
215 },
216 run_loop.QuitClosure()));
217 connector.FlushForTesting();
218 backing_pref_store->Initialize(
219 true, PersistentPrefStore::PREF_READ_ERROR_NONE, false);
220 run_loop.Run();
221 }
222
223 TEST_F(PersistentPrefStoreImplTest, DelayedInitializationFailure) {
224 auto backing_pref_store =
225 make_scoped_refptr(new InitializationMockPersistentPrefStore);
226
227 CreateImpl(backing_pref_store);
228 auto connector = CreateConnector();
229 base::RunLoop run_loop;
230 connector->Connect(base::Bind(
231 [](const base::Closure& quit,
232 PersistentPrefStore::PrefReadError read_error, bool read_only,
233 std::unique_ptr<base::DictionaryValue> local_prefs,
234 mojom::PersistentPrefStorePtr pref_store,
235 mojom::PrefStoreObserverRequest observer_request) {
236 quit.Run();
237 EXPECT_TRUE(read_only);
238 EXPECT_FALSE(local_prefs);
239 EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
240 read_error);
241 },
242 run_loop.QuitClosure()));
243 connector.FlushForTesting();
244 backing_pref_store->Initialize(
245 false, PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED, true);
246 run_loop.Run();
247 }
248
249 constexpr char kKey[] = "path.to.key";
250
251 TEST_F(PersistentPrefStoreImplTest, InitialValue) {
252 auto backing_pref_store = make_scoped_refptr(new InMemoryPrefStore());
253 const base::Value value("value");
254 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
255 CreateImpl(backing_pref_store);
256 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
257 pref_store()->ReadPrefs());
258 EXPECT_TRUE(pref_store()->IsInitializationComplete());
259 const base::Value* output = nullptr;
260 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
261 EXPECT_TRUE(value.Equals(output));
262 }
263
264 TEST_F(PersistentPrefStoreImplTest, InitialValueWithoutPathExpansion) {
265 auto backing_pref_store = make_scoped_refptr(new InMemoryPrefStore());
266 base::DictionaryValue dict;
267 dict.SetStringWithoutPathExpansion(kKey, "value");
268 backing_pref_store->SetValue(kKey, dict.CreateDeepCopy(), 0);
269 CreateImpl(backing_pref_store);
270 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
271 pref_store()->ReadPrefs());
272 EXPECT_TRUE(pref_store()->IsInitializationComplete());
273 const base::Value* output = nullptr;
274 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
275 EXPECT_TRUE(dict.Equals(output));
276 }
277
278 TEST_F(PersistentPrefStoreImplTest, WriteObservedByOtherClient) {
279 auto backing_pref_store = make_scoped_refptr(new InMemoryPrefStore());
280 CreateImpl(backing_pref_store);
281 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
282 pref_store()->ReadPrefs());
283 EXPECT_TRUE(pref_store()->IsInitializationComplete());
284
285 auto other_pref_store = CreateConnection();
286 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
287 other_pref_store->ReadPrefs());
288 EXPECT_TRUE(other_pref_store->IsInitializationComplete());
289
290 const base::Value value("value");
291 pref_store()->SetValueSilently(kKey, value.CreateDeepCopy(), 0);
292
293 PrefStoreObserverMock observer;
294 other_pref_store->AddObserver(&observer);
295 base::RunLoop run_loop;
296 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
297 .Times(1)
298 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
299 run_loop.Run();
300 other_pref_store->RemoveObserver(&observer);
301
302 const base::Value* output = nullptr;
303 ASSERT_TRUE(other_pref_store->GetValue(kKey, &output));
304 EXPECT_TRUE(value.Equals(output));
305 }
306
307 TEST_F(PersistentPrefStoreImplTest,
308 WriteWithoutPathExpansionObservedByOtherClient) {
309 auto backing_pref_store = make_scoped_refptr(new InMemoryPrefStore());
310 CreateImpl(backing_pref_store);
311 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
312 pref_store()->ReadPrefs());
313 EXPECT_TRUE(pref_store()->IsInitializationComplete());
314
315 auto other_pref_store = CreateConnection();
316 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
317 other_pref_store->ReadPrefs());
318 EXPECT_TRUE(other_pref_store->IsInitializationComplete());
319
320 base::DictionaryValue dict;
321 dict.SetStringWithoutPathExpansion(kKey, "value");
322 pref_store()->SetValue(kKey, dict.CreateDeepCopy(), 0);
323
324 PrefStoreObserverMock observer;
325 other_pref_store->AddObserver(&observer);
326 base::RunLoop run_loop;
327 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
328 .Times(1)
329 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
330 run_loop.Run();
331 other_pref_store->RemoveObserver(&observer);
332
333 const base::Value* output = nullptr;
334 ASSERT_TRUE(other_pref_store->GetValue(kKey, &output));
335 EXPECT_TRUE(dict.Equals(output));
336 }
337
338 TEST_F(PersistentPrefStoreImplTest, RemoveObservedByOtherClient) {
339 auto backing_pref_store = make_scoped_refptr(new InMemoryPrefStore());
340 const base::Value value("value");
341 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
342 CreateImpl(backing_pref_store);
343 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
344 pref_store()->ReadPrefs());
345 EXPECT_TRUE(pref_store()->IsInitializationComplete());
346
347 auto other_pref_store = CreateConnection();
348 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
349 other_pref_store->ReadPrefs());
350 EXPECT_TRUE(other_pref_store->IsInitializationComplete());
351
352 const base::Value* output = nullptr;
353 ASSERT_TRUE(other_pref_store->GetValue(kKey, &output));
354 EXPECT_TRUE(value.Equals(output));
355 pref_store()->RemoveValue(kKey, 0);
356
357 // This should be a no-op and shouldn't trigger a notification for the other
358 // client.
359 pref_store()->RemoveValue(kKey, 0);
360
361 PrefStoreObserverMock observer;
362 other_pref_store->AddObserver(&observer);
363 base::RunLoop run_loop;
364 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
365 .Times(1)
366 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
367 run_loop.Run();
368 base::RunLoop().RunUntilIdle();
369 other_pref_store->RemoveObserver(&observer);
370
371 EXPECT_FALSE(other_pref_store->GetValue(kKey, &output));
372 }
373
374 TEST_F(PersistentPrefStoreImplTest,
375 RemoveWithoutPathExpansionObservedByOtherClient) {
376 auto backing_pref_store = make_scoped_refptr(new InMemoryPrefStore());
377 base::DictionaryValue dict;
378 dict.SetStringWithoutPathExpansion(kKey, "value");
379 backing_pref_store->SetValue(kKey, dict.CreateDeepCopy(), 0);
380 CreateImpl(backing_pref_store);
381 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
382 pref_store()->ReadPrefs());
383 EXPECT_TRUE(pref_store()->IsInitializationComplete());
384
385 auto other_pref_store = CreateConnection();
386 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
387 other_pref_store->ReadPrefs());
388 EXPECT_TRUE(other_pref_store->IsInitializationComplete());
389
390 const base::Value* output = nullptr;
391 ASSERT_TRUE(other_pref_store->GetValue(kKey, &output));
392 EXPECT_TRUE(dict.Equals(output));
393
394 base::Value* mutable_value = nullptr;
395 dict.SetStringWithoutPathExpansion(kKey, "value");
396 ASSERT_TRUE(pref_store()->GetMutableValue(kKey, &mutable_value));
397 base::DictionaryValue* mutable_dict = nullptr;
398 ASSERT_TRUE(mutable_value->GetAsDictionary(&mutable_dict));
399 mutable_dict->RemoveWithoutPathExpansion(kKey, nullptr);
400 pref_store()->ReportValueChanged(kKey, 0);
401
402 PrefStoreObserverMock observer;
403 other_pref_store->AddObserver(&observer);
404 base::RunLoop run_loop;
405 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
406 .Times(1)
407 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
408 run_loop.Run();
409 other_pref_store->RemoveObserver(&observer);
410
411 ASSERT_TRUE(other_pref_store->GetValue(kKey, &output));
412 const base::DictionaryValue* dict_value = nullptr;
413 ASSERT_TRUE(output->GetAsDictionary(&dict_value));
414 EXPECT_TRUE(dict_value->empty());
415 }
416
417 TEST_F(PersistentPrefStoreImplTest, CommitPendingWrite) {
418 auto backing_store = make_scoped_refptr(new PersistentPrefStoreMock);
419 CreateImpl(backing_store);
420 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
421 pref_store()->ReadPrefs());
422 base::RunLoop run_loop;
423 EXPECT_CALL(*backing_store, CommitPendingWrite())
424 .Times(2)
425 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
426 pref_store()->CommitPendingWrite();
427 run_loop.Run();
428 }
429
430 TEST_F(PersistentPrefStoreImplTest, SchedulePendingLossyWrites) {
431 auto backing_store = make_scoped_refptr(new PersistentPrefStoreMock);
432 CreateImpl(backing_store);
433 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
434 pref_store()->ReadPrefs());
435 base::RunLoop run_loop;
436 EXPECT_CALL(*backing_store, SchedulePendingLossyWrites())
437 .Times(1)
438 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
439 EXPECT_CALL(*backing_store, CommitPendingWrite()).Times(1);
440 pref_store()->SchedulePendingLossyWrites();
441 run_loop.Run();
442 }
443
444 TEST_F(PersistentPrefStoreImplTest, ClearMutableValues) {
445 auto backing_store = make_scoped_refptr(new PersistentPrefStoreMock);
446 CreateImpl(backing_store);
447 ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
448 pref_store()->ReadPrefs());
449 base::RunLoop run_loop;
450 EXPECT_CALL(*backing_store, ClearMutableValues())
451 .Times(1)
452 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
453 EXPECT_CALL(*backing_store, CommitPendingWrite()).Times(1);
454 pref_store()->ClearMutableValues();
455 run_loop.Run();
456 }
457
458 } // namespace
459 } // namespace prefs
OLDNEW
« no previous file with comments | « services/preferences/persistent_pref_store_impl.cc ('k') | services/preferences/public/cpp/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698