1 // Copyright 2012 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.
5 #include "components/prefs/overlay_user_pref_store.h"
9 #include "base/test/task_environment.h"
10 #include "base/values.h"
11 #include "components/prefs/persistent_pref_store_unittest.h"
12 #include "components/prefs/pref_store_observer_mock.h"
13 #include "components/prefs/testing_pref_store.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 using ::testing::Mock;
18 using ::testing::StrEq;
23 const char kBrowserWindowPlacement[] = "browser.window_placement";
24 const char kShowBookmarkBar[] = "bookmark_bar.show_on_all_tabs";
25 const char kSharedKey[] = "sync_promo.show_on_first_run_allowed";
27 const char* const regular_key = kBrowserWindowPlacement;
28 const char* const persistent_key = kShowBookmarkBar;
29 const char* const shared_key = kSharedKey;
33 class OverlayUserPrefStoreTest : public testing::Test {
35 OverlayUserPrefStoreTest()
36 : underlay_(new TestingPrefStore()),
37 overlay_(new OverlayUserPrefStore(underlay_.get())) {
38 overlay_->RegisterPersistentPref(persistent_key);
39 overlay_->RegisterPersistentPref(shared_key);
42 ~OverlayUserPrefStoreTest() override {}
44 base::test::TaskEnvironment task_environment_;
45 scoped_refptr<TestingPrefStore> underlay_;
46 scoped_refptr<OverlayUserPrefStore> overlay_;
49 TEST_F(OverlayUserPrefStoreTest, Observer) {
50 PrefStoreObserverMock obs;
51 overlay_->AddObserver(&obs);
53 // Check that underlay first value is reported.
54 underlay_->SetValue(regular_key, Value(42),
55 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
56 obs.VerifyAndResetChangedKey(regular_key);
58 // Check that underlay overwriting is reported.
59 underlay_->SetValue(regular_key, Value(43),
60 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
61 obs.VerifyAndResetChangedKey(regular_key);
63 // Check that overwriting change in overlay is reported.
64 overlay_->SetValue(regular_key, Value(44),
65 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
66 obs.VerifyAndResetChangedKey(regular_key);
68 // Check that hidden underlay change is not reported.
69 underlay_->SetValue(regular_key, Value(45),
70 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
71 EXPECT_TRUE(obs.changed_keys.empty());
73 // Check that overlay remove is reported.
74 overlay_->RemoveValue(regular_key,
75 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
76 obs.VerifyAndResetChangedKey(regular_key);
78 // Check that underlay remove is reported.
79 underlay_->RemoveValue(regular_key,
80 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
81 obs.VerifyAndResetChangedKey(regular_key);
83 // Check respecting of silence.
84 overlay_->SetValueSilently(regular_key, Value(46),
85 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
86 EXPECT_TRUE(obs.changed_keys.empty());
88 overlay_->RemoveObserver(&obs);
90 // Check successful unsubscription.
91 underlay_->SetValue(regular_key, Value(47),
92 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
93 overlay_->SetValue(regular_key, Value(48),
94 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
95 EXPECT_TRUE(obs.changed_keys.empty());
98 TEST_F(OverlayUserPrefStoreTest, GetAndSet) {
99 const Value* value = nullptr;
100 EXPECT_FALSE(overlay_->GetValue(regular_key, &value));
101 EXPECT_FALSE(underlay_->GetValue(regular_key, &value));
103 underlay_->SetValue(regular_key, Value(42),
104 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
106 // Value shines through:
107 EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
108 EXPECT_EQ(base::Value(42), *value);
110 EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
111 EXPECT_EQ(base::Value(42), *value);
113 overlay_->SetValue(regular_key, Value(43),
114 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
116 EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
117 EXPECT_EQ(base::Value(43), *value);
119 EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
120 EXPECT_EQ(base::Value(42), *value);
122 overlay_->RemoveValue(regular_key,
123 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
125 // Value shines through:
126 EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
127 EXPECT_EQ(base::Value(42), *value);
129 EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
130 EXPECT_EQ(base::Value(42), *value);
133 // Check that GetMutableValue does not return the dictionary of the underlay.
134 TEST_F(OverlayUserPrefStoreTest, ModifyDictionaries) {
135 underlay_->SetValue(regular_key, base::Value(base::Value::Dict()),
136 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
138 Value* modify = nullptr;
139 EXPECT_TRUE(overlay_->GetMutableValue(regular_key, &modify));
141 ASSERT_TRUE(modify->is_dict());
142 modify->GetDict().SetByDottedPath(regular_key, 42);
144 Value* original_in_underlay = nullptr;
145 EXPECT_TRUE(underlay_->GetMutableValue(regular_key, &original_in_underlay));
146 ASSERT_TRUE(original_in_underlay);
147 ASSERT_TRUE(original_in_underlay->is_dict());
148 EXPECT_TRUE(original_in_underlay->GetDict().empty());
150 Value* modified = nullptr;
151 EXPECT_TRUE(overlay_->GetMutableValue(regular_key, &modified));
152 ASSERT_TRUE(modified);
153 ASSERT_TRUE(modified->is_dict());
154 EXPECT_EQ(*modify, *modified);
157 // Here we consider a global preference that is not overlayed.
158 TEST_F(OverlayUserPrefStoreTest, GlobalPref) {
159 PrefStoreObserverMock obs;
160 overlay_->AddObserver(&obs);
162 const Value* value = nullptr;
164 // Check that underlay first value is reported.
165 underlay_->SetValue(persistent_key, Value(42),
166 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
167 obs.VerifyAndResetChangedKey(persistent_key);
169 // Check that underlay overwriting is reported.
170 underlay_->SetValue(persistent_key, Value(43),
171 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
172 obs.VerifyAndResetChangedKey(persistent_key);
174 // Check that we get this value from the overlay
175 EXPECT_TRUE(overlay_->GetValue(persistent_key, &value));
176 EXPECT_EQ(base::Value(43), *value);
178 // Check that overwriting change in overlay is reported.
179 overlay_->SetValue(persistent_key, Value(44),
180 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
181 obs.VerifyAndResetChangedKey(persistent_key);
183 // Check that we get this value from the overlay and the underlay.
184 EXPECT_TRUE(overlay_->GetValue(persistent_key, &value));
185 EXPECT_EQ(base::Value(44), *value);
186 EXPECT_TRUE(underlay_->GetValue(persistent_key, &value));
187 EXPECT_EQ(base::Value(44), *value);
189 // Check that overlay remove is reported.
190 overlay_->RemoveValue(persistent_key,
191 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
192 obs.VerifyAndResetChangedKey(persistent_key);
194 // Check that value was removed from overlay and underlay
195 EXPECT_FALSE(overlay_->GetValue(persistent_key, &value));
196 EXPECT_FALSE(underlay_->GetValue(persistent_key, &value));
198 // Check respecting of silence.
199 overlay_->SetValueSilently(persistent_key, Value(46),
200 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
201 EXPECT_TRUE(obs.changed_keys.empty());
203 overlay_->RemoveObserver(&obs);
205 // Check successful unsubscription.
206 underlay_->SetValue(persistent_key, Value(47),
207 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
208 overlay_->SetValue(persistent_key, Value(48),
209 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
210 EXPECT_TRUE(obs.changed_keys.empty());
213 TEST_F(OverlayUserPrefStoreTest, GetValues) {
214 // To check merge behavior, create underlay and overlay so each has a key the
215 // other doesn't have and they have one key in common.
216 underlay_->SetValue(persistent_key, Value(42),
217 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
218 overlay_->SetValue(regular_key, Value(43),
219 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
220 underlay_->SetValue(shared_key, Value(42),
221 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
222 overlay_->SetValue(shared_key, Value(43),
223 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
225 auto values = overlay_->GetValues();
226 // Check that an overlay preference is returned.
227 const Value* value = values.FindByDottedPath(persistent_key);
229 EXPECT_EQ(base::Value(42), *value);
231 // Check that an underlay preference is returned.
232 value = values.FindByDottedPath(regular_key);
234 EXPECT_EQ(base::Value(43), *value);
236 // Check that the overlay is preferred.
237 value = values.FindByDottedPath(shared_key);
239 EXPECT_EQ(base::Value(43), *value);
242 TEST_F(OverlayUserPrefStoreTest, CommitPendingWriteWithCallback) {
243 TestCommitPendingWriteWithCallback(overlay_.get(), &task_environment_);