xref: /aosp_15_r20/external/cronet/components/prefs/segregated_pref_store_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2014 The Chromium Authors
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 "components/prefs/segregated_pref_store.h"
6 
7 #include <memory>
8 #include <set>
9 #include <string>
10 #include <utility>
11 
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/run_loop.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "base/test/task_environment.h"
19 #include "base/values.h"
20 #include "components/prefs/persistent_pref_store.h"
21 #include "components/prefs/pref_name_set.h"
22 #include "components/prefs/pref_store_observer_mock.h"
23 #include "components/prefs/testing_pref_store.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 
26 namespace {
27 
28 const char kSelectedPref[] = "selected_pref";
29 const char kUnselectedPref[] = "unselected_pref";
30 const char kSharedPref[] = "shared_pref";
31 
32 const char kValue1[] = "value1";
33 const char kValue2[] = "value2";
34 
35 class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
36  public:
37   struct Data {
Data__anon3b84fe4b0111::MockReadErrorDelegate::Data38     Data(bool invoked_in, PersistentPrefStore::PrefReadError read_error_in)
39         : invoked(invoked_in), read_error(read_error_in) {}
40 
41     bool invoked;
42     PersistentPrefStore::PrefReadError read_error;
43   };
44 
MockReadErrorDelegate(Data * data)45   explicit MockReadErrorDelegate(Data* data) : data_(data) {
46     DCHECK(data_);
47     EXPECT_FALSE(data_->invoked);
48   }
49 
50   // PersistentPrefStore::ReadErrorDelegate implementation
OnError(PersistentPrefStore::PrefReadError read_error)51   void OnError(PersistentPrefStore::PrefReadError read_error) override {
52     EXPECT_FALSE(data_->invoked);
53     data_->invoked = true;
54     data_->read_error = read_error;
55   }
56 
57  private:
58   raw_ptr<Data> data_;
59 };
60 
61 enum class CommitPendingWriteMode {
62   // Basic mode.
63   WITHOUT_CALLBACK,
64   // With reply callback.
65   WITH_CALLBACK,
66   // With synchronous notify callback (synchronous after the write -- shouldn't
67   // require pumping messages to observe).
68   WITH_SYNCHRONOUS_CALLBACK,
69 };
70 
71 class SegregatedPrefStoreTest
72     : public testing::TestWithParam<CommitPendingWriteMode> {
73  public:
SegregatedPrefStoreTest()74   SegregatedPrefStoreTest()
75       : read_error_delegate_data_(false,
76                                   PersistentPrefStore::PREF_READ_ERROR_NONE),
77         read_error_delegate_(
78             new MockReadErrorDelegate(&read_error_delegate_data_)) {}
79 
SetUp()80   void SetUp() override {
81     selected_store_ = new TestingPrefStore;
82     default_store_ = new TestingPrefStore;
83 
84     selected_pref_names_.insert(kSelectedPref);
85     selected_pref_names_.insert(kSharedPref);
86     segregated_store_ = new SegregatedPrefStore(default_store_, selected_store_,
87                                                 selected_pref_names_);
88     segregated_store_->AddObserver(&observer_);
89   }
90 
TearDown()91   void TearDown() override { segregated_store_->RemoveObserver(&observer_); }
92 
93  protected:
94   std::unique_ptr<PersistentPrefStore::ReadErrorDelegate>
GetReadErrorDelegate()95   GetReadErrorDelegate() {
96     EXPECT_TRUE(read_error_delegate_);
97     return std::move(read_error_delegate_);
98   }
99 
100   base::test::TaskEnvironment task_environment_;
101 
102   PrefStoreObserverMock observer_;
103 
104   scoped_refptr<TestingPrefStore> default_store_;
105   scoped_refptr<TestingPrefStore> selected_store_;
106   scoped_refptr<SegregatedPrefStore> segregated_store_;
107 
108   PrefNameSet selected_pref_names_;
109   MockReadErrorDelegate::Data read_error_delegate_data_;
110 
111  private:
112   std::unique_ptr<MockReadErrorDelegate> read_error_delegate_;
113 };
114 
115 }  // namespace
116 
TEST_P(SegregatedPrefStoreTest,StoreValues)117 TEST_P(SegregatedPrefStoreTest, StoreValues) {
118   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
119             segregated_store_->ReadPrefs());
120 
121   // Properly stores new values.
122   segregated_store_->SetValue(kSelectedPref, base::Value(kValue1),
123                               WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
124   segregated_store_->SetValue(kUnselectedPref, base::Value(kValue2),
125                               WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
126 
127   ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
128   ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
129   ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
130   ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
131 
132   ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
133   ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
134 
135   ASSERT_FALSE(selected_store_->committed());
136   ASSERT_FALSE(default_store_->committed());
137 
138   switch (GetParam()) {
139     case CommitPendingWriteMode::WITHOUT_CALLBACK: {
140       segregated_store_->CommitPendingWrite();
141       base::RunLoop().RunUntilIdle();
142       break;
143     }
144 
145     case CommitPendingWriteMode::WITH_CALLBACK: {
146       base::RunLoop run_loop;
147       segregated_store_->CommitPendingWrite(run_loop.QuitClosure());
148       run_loop.Run();
149       break;
150     }
151 
152     case CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK: {
153       base::WaitableEvent written;
154       segregated_store_->CommitPendingWrite(
155           base::OnceClosure(),
156           base::BindOnce(&base::WaitableEvent::Signal, Unretained(&written)));
157       written.Wait();
158       break;
159     }
160   }
161 
162   ASSERT_TRUE(selected_store_->committed());
163   ASSERT_TRUE(default_store_->committed());
164 }
165 
TEST_F(SegregatedPrefStoreTest,ReadValues)166 TEST_F(SegregatedPrefStoreTest, ReadValues) {
167   selected_store_->SetValue(kSelectedPref, base::Value(kValue1),
168                             WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
169   default_store_->SetValue(kUnselectedPref, base::Value(kValue2),
170                            WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
171 
172   // Works properly with values that are already there.
173   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
174             segregated_store_->ReadPrefs());
175   ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
176             segregated_store_->GetReadError());
177 
178   ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
179   ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
180   ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
181   ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
182 
183   ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
184   ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
185 }
186 
TEST_F(SegregatedPrefStoreTest,RemoveValuesByPrefix)187 TEST_F(SegregatedPrefStoreTest, RemoveValuesByPrefix) {
188   const std::string subpref_name1 = kSelectedPref;
189   const std::string subpref_name2 = std::string(kSelectedPref) + "b";
190   const std::string other_name = kUnselectedPref;
191   const std::string prefix = kSelectedPref;
192 
193   selected_store_->SetValue(subpref_name1, base::Value(kValue1),
194                             WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
195   default_store_->SetValue(subpref_name2, base::Value(kValue2),
196                            WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
197   default_store_->SetValue(other_name, base::Value(kValue2),
198                            WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
199 
200   ASSERT_TRUE(selected_store_->GetValue(subpref_name1, nullptr));
201   ASSERT_TRUE(default_store_->GetValue(subpref_name2, nullptr));
202   ASSERT_TRUE(default_store_->GetValue(other_name, nullptr));
203 
204   segregated_store_->RemoveValuesByPrefixSilently(kSelectedPref);
205 
206   ASSERT_FALSE(selected_store_->GetValue(subpref_name1, nullptr));
207   ASSERT_FALSE(default_store_->GetValue(subpref_name2, nullptr));
208   ASSERT_TRUE(default_store_->GetValue(other_name, nullptr));
209 }
210 
TEST_F(SegregatedPrefStoreTest,Observer)211 TEST_F(SegregatedPrefStoreTest, Observer) {
212   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
213             segregated_store_->ReadPrefs());
214   EXPECT_TRUE(observer_.initialized);
215   EXPECT_TRUE(observer_.initialization_success);
216   EXPECT_TRUE(observer_.changed_keys.empty());
217   segregated_store_->SetValue(kSelectedPref, base::Value(kValue1),
218                               WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
219   observer_.VerifyAndResetChangedKey(kSelectedPref);
220   segregated_store_->SetValue(kUnselectedPref, base::Value(kValue2),
221                               WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
222   observer_.VerifyAndResetChangedKey(kUnselectedPref);
223 }
224 
TEST_F(SegregatedPrefStoreTest,ObserverAfterConstructionAfterSubInitialization)225 TEST_F(SegregatedPrefStoreTest,
226        ObserverAfterConstructionAfterSubInitialization) {
227   // Ensure that underlying PrefStores are initialized first.
228   default_store_->ReadPrefs();
229   selected_store_->ReadPrefs();
230   EXPECT_TRUE(default_store_->IsInitializationComplete());
231   EXPECT_TRUE(selected_store_->IsInitializationComplete());
232 
233   // Create a new SegregatedPrefStore based on the initialized PrefStores.
234   segregated_store_->RemoveObserver(&observer_);
235   segregated_store_ = base::MakeRefCounted<SegregatedPrefStore>(
236       default_store_, selected_store_, selected_pref_names_);
237   segregated_store_->AddObserver(&observer_);
238   EXPECT_TRUE(segregated_store_->IsInitializationComplete());
239 
240   // The Observer should receive notifications from the SegregatedPrefStore.
241   EXPECT_TRUE(observer_.changed_keys.empty());
242   segregated_store_->SetValue(kSelectedPref, base::Value(kValue1),
243                               WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
244   observer_.VerifyAndResetChangedKey(kSelectedPref);
245   segregated_store_->SetValue(kUnselectedPref, base::Value(kValue2),
246                               WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
247   observer_.VerifyAndResetChangedKey(kUnselectedPref);
248 }
249 
TEST_F(SegregatedPrefStoreTest,SelectedPrefReadNoFileError)250 TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileError) {
251   // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
252   // to PREF_READ_ERROR_NONE.
253   selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
254   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
255             segregated_store_->ReadPrefs());
256   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
257             segregated_store_->GetReadError());
258 }
259 
TEST_F(SegregatedPrefStoreTest,SelectedPrefReadError)260 TEST_F(SegregatedPrefStoreTest, SelectedPrefReadError) {
261   selected_store_->set_read_error(
262       PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
263   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
264             segregated_store_->ReadPrefs());
265   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
266             segregated_store_->GetReadError());
267 }
268 
TEST_F(SegregatedPrefStoreTest,SelectedPrefReadNoFileErrorAsync)269 TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileErrorAsync) {
270   // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
271   // to PREF_READ_ERROR_NONE.
272   selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
273 
274   default_store_->SetBlockAsyncRead(true);
275 
276   EXPECT_FALSE(read_error_delegate_data_.invoked);
277 
278   segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
279 
280   EXPECT_FALSE(read_error_delegate_data_.invoked);
281 
282   default_store_->SetBlockAsyncRead(false);
283 
284   // ReadErrorDelegate is not invoked for ERROR_NONE.
285   EXPECT_FALSE(read_error_delegate_data_.invoked);
286   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
287             segregated_store_->GetReadError());
288   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
289             segregated_store_->GetReadError());
290 }
291 
TEST_F(SegregatedPrefStoreTest,UnselectedPrefReadNoFileError)292 TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadNoFileError) {
293   default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
294   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
295             segregated_store_->ReadPrefs());
296   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
297             segregated_store_->GetReadError());
298 }
299 
TEST_F(SegregatedPrefStoreTest,UnselectedPrefReadError)300 TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadError) {
301   default_store_->set_read_error(
302       PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
303   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
304             segregated_store_->ReadPrefs());
305   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
306             segregated_store_->GetReadError());
307 }
308 
TEST_F(SegregatedPrefStoreTest,BothPrefReadError)309 TEST_F(SegregatedPrefStoreTest, BothPrefReadError) {
310   default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
311   selected_store_->set_read_error(
312       PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
313   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
314             segregated_store_->ReadPrefs());
315   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
316             segregated_store_->GetReadError());
317 }
318 
TEST_F(SegregatedPrefStoreTest,BothPrefReadErrorAsync)319 TEST_F(SegregatedPrefStoreTest, BothPrefReadErrorAsync) {
320   default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
321   selected_store_->set_read_error(
322       PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
323 
324   selected_store_->SetBlockAsyncRead(true);
325 
326   EXPECT_FALSE(read_error_delegate_data_.invoked);
327 
328   segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
329 
330   EXPECT_FALSE(read_error_delegate_data_.invoked);
331 
332   selected_store_->SetBlockAsyncRead(false);
333 
334   EXPECT_TRUE(read_error_delegate_data_.invoked);
335   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
336             segregated_store_->GetReadError());
337   EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
338             segregated_store_->GetReadError());
339 }
340 
TEST_F(SegregatedPrefStoreTest,IsInitializationComplete)341 TEST_F(SegregatedPrefStoreTest, IsInitializationComplete) {
342   EXPECT_FALSE(segregated_store_->IsInitializationComplete());
343   segregated_store_->ReadPrefs();
344   EXPECT_TRUE(segregated_store_->IsInitializationComplete());
345 }
346 
TEST_F(SegregatedPrefStoreTest,IsInitializationCompleteAsync)347 TEST_F(SegregatedPrefStoreTest, IsInitializationCompleteAsync) {
348   selected_store_->SetBlockAsyncRead(true);
349   default_store_->SetBlockAsyncRead(true);
350   EXPECT_FALSE(segregated_store_->IsInitializationComplete());
351   segregated_store_->ReadPrefsAsync(NULL);
352   EXPECT_FALSE(segregated_store_->IsInitializationComplete());
353   selected_store_->SetBlockAsyncRead(false);
354   EXPECT_FALSE(segregated_store_->IsInitializationComplete());
355   default_store_->SetBlockAsyncRead(false);
356   EXPECT_TRUE(segregated_store_->IsInitializationComplete());
357 }
358 
TEST_F(SegregatedPrefStoreTest,GetValues)359 TEST_F(SegregatedPrefStoreTest, GetValues) {
360   // To check merge behavior, create selected and default stores so each has a
361   // key the other doesn't have and they have one key in common.
362   selected_store_->SetValue(kSelectedPref, base::Value(kValue1),
363                             WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
364   default_store_->SetValue(kUnselectedPref, base::Value(kValue2),
365                            WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
366   selected_store_->SetValue(kSharedPref, base::Value(kValue1),
367                             WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
368 
369   auto values = segregated_store_->GetValues();
370   // Check that a selected preference is returned.
371   const base::Value* value = values.Find(kSelectedPref);
372   ASSERT_TRUE(value);
373   EXPECT_EQ(base::Value(kValue1), *value);
374 
375   // Check that a a default preference is returned.
376   value = values.Find(kUnselectedPref);
377   ASSERT_TRUE(value);
378   EXPECT_EQ(base::Value(kValue2), *value);
379 
380   // Check that the selected preference is preferred.
381   value = values.Find(kSharedPref);
382   ASSERT_TRUE(value);
383   EXPECT_EQ(base::Value(kValue1), *value);
384 }
385 
386 INSTANTIATE_TEST_SUITE_P(
387     WithoutCallback,
388     SegregatedPrefStoreTest,
389     ::testing::Values(CommitPendingWriteMode::WITHOUT_CALLBACK));
390 INSTANTIATE_TEST_SUITE_P(
391     WithCallback,
392     SegregatedPrefStoreTest,
393     ::testing::Values(CommitPendingWriteMode::WITH_CALLBACK));
394 INSTANTIATE_TEST_SUITE_P(
395     WithSynchronousCallback,
396     SegregatedPrefStoreTest,
397     ::testing::Values(CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK));
398