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

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, 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/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 succeeded));
tibell 2017/03/27 03:37:56 Can drop |succeeded| here for consistency with the
Sam McNally 2017/03/27 06:44:40 Done.
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 private:
59 ~MockPrefStore() override = default;
60
61 bool initialized_ = false;
62 bool success_ = false;
63 base::ObserverList<PrefStore::Observer, true> observers_;
64 };
65
66 constexpr char kKey[] = "path.to.key";
67 constexpr char kOtherKey[] = "path.to.other_key";
68
69 class PrefStoreImplTest : public testing::Test {
70 public:
71 PrefStoreImplTest() = default;
72
73 // testing::Test:
74 void TearDown() override {
75 pref_store_ = nullptr;
76 base::RunLoop().RunUntilIdle();
77 pref_store_ptr_.reset();
78 base::RunLoop().RunUntilIdle();
79 impl_.reset();
80 base::RunLoop().RunUntilIdle();
81 }
82
83 void CreateImpl(scoped_refptr<PrefStore> backing_pref_store,
tibell 2017/03/27 03:37:56 Could this just return the PrefStore instead? Less
Sam McNally 2017/03/27 06:44:40 Different tests use different PrefStores.
84 std::vector<std::string> observed_prefs = {}) {
85 impl_ = base::MakeUnique<PrefStoreImpl>(
86 std::move(backing_pref_store), mojo::MakeRequest(&pref_store_ptr_));
87
88 if (observed_prefs.empty())
89 observed_prefs.insert(observed_prefs.end(), {kKey, kOtherKey});
90 pref_store_ = CreateConnection(std::move(observed_prefs));
91 }
92
93 scoped_refptr<PrefStore> CreateConnection(
94 std::vector<std::string> observed_prefs) {
95 base::RunLoop run_loop;
96 mojom::PrefStoreConnectionPtr connection;
97 pref_store_ptr_->AddObserver(
98 observed_prefs,
99 base::Bind(
100 [](mojom::PrefStoreConnectionPtr* output, base::OnceClosure quit,
101 mojom::PrefStoreConnectionPtr connection) {
102 std::move(quit).Run();
103 *output = std::move(connection);
104 },
105 &connection, run_loop.QuitClosure()));
106 run_loop.Run();
107 return make_scoped_refptr(new PrefStoreClient(std::move(connection)));
108 }
109
110 PrefStore* pref_store() { return pref_store_.get(); }
111
112 private:
113 base::MessageLoop message_loop_;
114
115 std::unique_ptr<PrefStoreImpl> impl_;
116 mojom::PrefStorePtr pref_store_ptr_;
117
118 scoped_refptr<PrefStore> pref_store_;
119
120 DISALLOW_COPY_AND_ASSIGN(PrefStoreImplTest);
121 };
122
123 TEST_F(PrefStoreImplTest, InitializationSuccess) {
124 auto backing_pref_store = make_scoped_refptr(new MockPrefStore());
125 CreateImpl(backing_pref_store);
126 EXPECT_FALSE(pref_store()->IsInitializationComplete());
127
128 backing_pref_store->CompleteInitialization(true);
129 PrefStoreObserverMock observer;
130 pref_store()->AddObserver(&observer);
131 base::RunLoop run_loop;
132 EXPECT_CALL(observer, OnInitializationCompleted(true))
133 .Times(1)
tibell 2017/03/27 03:37:56 Times(1) is the default so you can remove.
Sam McNally 2017/03/27 06:44:40 Done.
134 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
135 run_loop.Run();
136 pref_store()->RemoveObserver(&observer);
137 EXPECT_TRUE(pref_store()->IsInitializationComplete());
138 }
139
140 TEST_F(PrefStoreImplTest, InitializationFailure) {
141 auto backing_pref_store = make_scoped_refptr(new MockPrefStore());
142 CreateImpl(backing_pref_store);
143 EXPECT_FALSE(pref_store()->IsInitializationComplete());
144
145 backing_pref_store->CompleteInitialization(false);
146 PrefStoreObserverMock observer;
147 pref_store()->AddObserver(&observer);
148 base::RunLoop run_loop;
149 EXPECT_CALL(observer, OnInitializationCompleted(false))
150 .Times(1)
tibell 2017/03/27 03:37:56 ditto
Sam McNally 2017/03/27 06:44:41 Done.
151 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
152 run_loop.Run();
153 pref_store()->RemoveObserver(&observer);
154
155 // TODO(sammc): Should IsInitializationComplete() return false?
156 EXPECT_TRUE(pref_store()->IsInitializationComplete());
157 }
158
159 TEST_F(PrefStoreImplTest, InitialValue) {
160 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
161 const base::Value value("value");
162 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
163 CreateImpl(backing_pref_store);
164 ASSERT_TRUE(pref_store()->IsInitializationComplete());
tibell 2017/03/27 03:37:56 Maybe add a TODO here too to check what the backin
Sam McNally 2017/03/27 06:44:41 As discussed, this isn't testing that the presence
165 const base::Value* output = nullptr;
166 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
167 EXPECT_TRUE(value.Equals(output));
168 }
169
170 TEST_F(PrefStoreImplTest, InitialValueWithoutPathExpansion) {
171 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
172 base::DictionaryValue dict;
173 dict.SetStringWithoutPathExpansion(kKey, "value");
174 backing_pref_store->SetValue(kKey, dict.CreateDeepCopy(), 0);
175 CreateImpl(backing_pref_store);
176 ASSERT_TRUE(pref_store()->IsInitializationComplete());
177 const base::Value* output = nullptr;
178 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
179 EXPECT_TRUE(dict.Equals(output));
180 }
181
182 TEST_F(PrefStoreImplTest, WriteObservedByClient) {
183 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
184 CreateImpl(backing_pref_store);
185 ASSERT_TRUE(pref_store()->IsInitializationComplete());
186
187 const base::Value value("value");
188 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
189
190 PrefStoreObserverMock observer;
191 pref_store()->AddObserver(&observer);
192 base::RunLoop run_loop;
193 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
tibell 2017/03/27 03:37:56 Could this be lifted out into a ExpectPrefChange(
Sam McNally 2017/03/27 06:44:40 Done.
194 .Times(1)
tibell 2017/03/27 03:37:56 Remove
Sam McNally 2017/03/27 06:44:40 Done.
195 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
196 run_loop.Run();
197 pref_store()->RemoveObserver(&observer);
198
199 const base::Value* output = nullptr;
200 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
201 EXPECT_TRUE(value.Equals(output));
202 }
203
204 TEST_F(PrefStoreImplTest, WriteToUnregisteredPrefNotObservedByClient) {
205 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
206 CreateImpl(backing_pref_store, {kKey});
207 ASSERT_TRUE(pref_store()->IsInitializationComplete());
208
209 backing_pref_store->SetValue(kOtherKey, base::MakeUnique<base::Value>(123),
210 0);
211 backing_pref_store->SetValue(kKey, base::MakeUnique<base::Value>("value"), 0);
212
213 PrefStoreObserverMock observer;
214 pref_store()->AddObserver(&observer);
215 base::RunLoop run_loop;
216 EXPECT_CALL(observer, OnPrefValueChanged(kOtherKey)).Times(0);
217 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
218 .Times(1)
tibell 2017/03/27 03:37:56 Remove
Sam McNally 2017/03/27 06:44:41 Done.
219 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
220 run_loop.Run();
221 pref_store()->RemoveObserver(&observer);
222
223 EXPECT_FALSE(pref_store()->GetValue(kOtherKey, nullptr));
224 }
225
226 TEST_F(PrefStoreImplTest, WriteWithoutPathExpansionObservedByClient) {
227 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
228 CreateImpl(backing_pref_store);
229 ASSERT_TRUE(pref_store()->IsInitializationComplete());
230
231 base::DictionaryValue dict;
232 dict.SetStringWithoutPathExpansion(kKey, "value");
233 backing_pref_store->SetValue(kKey, dict.CreateDeepCopy(), 0);
234
235 PrefStoreObserverMock observer;
236 pref_store()->AddObserver(&observer);
237 base::RunLoop run_loop;
238 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
239 .Times(1)
tibell 2017/03/27 03:37:56 Remove
Sam McNally 2017/03/27 06:44:40 Done.
240 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
241 run_loop.Run();
242 pref_store()->RemoveObserver(&observer);
243
244 const base::Value* output = nullptr;
245 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
246 EXPECT_TRUE(dict.Equals(output));
247 }
248
249 TEST_F(PrefStoreImplTest, RemoveObservedByClient) {
250 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
251 const base::Value value("value");
252 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
253 CreateImpl(backing_pref_store);
254 ASSERT_TRUE(pref_store()->IsInitializationComplete());
255
256 const base::Value* output = nullptr;
257 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
258 EXPECT_TRUE(value.Equals(output));
259 backing_pref_store->RemoveValue(kKey, 0);
260
261 // This should be a no-op and shouldn't trigger a notification for the other
262 // client.
263 backing_pref_store->RemoveValue(kKey, 0);
264
265 PrefStoreObserverMock observer;
266 pref_store()->AddObserver(&observer);
267 base::RunLoop run_loop;
268 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
269 .Times(1)
tibell 2017/03/27 03:37:56 Remove
Sam McNally 2017/03/27 06:44:41 Done.
270 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
271 run_loop.Run();
272 base::RunLoop().RunUntilIdle();
273 pref_store()->RemoveObserver(&observer);
274
275 EXPECT_FALSE(pref_store()->GetValue(kKey, &output));
276 }
277
278 TEST_F(PrefStoreImplTest, RemoveOfUnregisteredPrefNotObservedByClient) {
279 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
280 const base::Value value("value");
281 backing_pref_store->SetValue(kKey, value.CreateDeepCopy(), 0);
282 backing_pref_store->SetValue(kOtherKey, value.CreateDeepCopy(), 0);
283 CreateImpl(backing_pref_store, {kKey});
284 ASSERT_TRUE(pref_store()->IsInitializationComplete());
285
286 backing_pref_store->RemoveValue(kOtherKey, 0);
287 backing_pref_store->RemoveValue(kKey, 0);
288
289 PrefStoreObserverMock observer;
290 pref_store()->AddObserver(&observer);
291 base::RunLoop run_loop;
292 EXPECT_CALL(observer, OnPrefValueChanged(kOtherKey)).Times(0);
293 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
294 .Times(1)
tibell 2017/03/27 03:37:56 Remove
Sam McNally 2017/03/27 06:44:40 Done.
295 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
296 run_loop.Run();
297 pref_store()->RemoveObserver(&observer);
298 }
299
300 TEST_F(PrefStoreImplTest, RemoveWithoutPathExpansionObservedByOtherClient) {
301 auto backing_pref_store = make_scoped_refptr(new ValueMapPrefStore());
302 base::DictionaryValue dict;
303 dict.SetStringWithoutPathExpansion(kKey, "value");
304 backing_pref_store->SetValue(kKey, dict.CreateDeepCopy(), 0);
305 CreateImpl(backing_pref_store);
306 ASSERT_TRUE(pref_store()->IsInitializationComplete());
307
308 const base::Value* output = nullptr;
309 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
310 EXPECT_TRUE(dict.Equals(output));
311
312 base::Value* mutable_value = nullptr;
313 dict.SetStringWithoutPathExpansion(kKey, "value");
314 ASSERT_TRUE(backing_pref_store->GetMutableValue(kKey, &mutable_value));
315 base::DictionaryValue* mutable_dict = nullptr;
316 ASSERT_TRUE(mutable_value->GetAsDictionary(&mutable_dict));
317 mutable_dict->RemoveWithoutPathExpansion(kKey, nullptr);
318 backing_pref_store->ReportValueChanged(kKey, 0);
319
320 PrefStoreObserverMock observer;
321 pref_store()->AddObserver(&observer);
322 base::RunLoop run_loop;
323 EXPECT_CALL(observer, OnPrefValueChanged(kKey))
324 .Times(1)
tibell 2017/03/27 03:37:56 Remove
Sam McNally 2017/03/27 06:44:40 Done.
325 .WillOnce(WithoutArgs(Invoke([&run_loop]() { run_loop.Quit(); })));
326 run_loop.Run();
327 pref_store()->RemoveObserver(&observer);
328
329 ASSERT_TRUE(pref_store()->GetValue(kKey, &output));
330 const base::DictionaryValue* dict_value = nullptr;
331 ASSERT_TRUE(output->GetAsDictionary(&dict_value));
332 EXPECT_TRUE(dict_value->empty());
333 }
334
335 } // namespace
336 } // namespace prefs
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698