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

Side by Side Diff: chrome/browser/prefs/pref_notifier_unittest.cc

Issue 5441002: Clean up pref change notification handling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix extension prefs breakage Created 10 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 "chrome/browser/prefs/in_memory_pref_store.h"
6 #include "chrome/browser/prefs/pref_notifier.h"
7 #include "chrome/browser/prefs/pref_service.h"
8 #include "chrome/browser/prefs/pref_value_store.h"
9 #include "chrome/common/notification_observer.h"
10 #include "chrome/common/notification_type.h"
11 #include "chrome/common/notification_service.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15
16 namespace {
17
18 const char kChangedPref[] = "changed_pref";
19 const char kUnchangedPref[] = "unchanged_pref";
20
21 bool DetailsAreChangedPref(const Details<std::string>& details) {
22 std::string* string_in = Details<std::string>(details).ptr();
23 return strcmp(string_in->c_str(), kChangedPref) == 0;
24 }
25
26 // Test PrefNotifier that allows tracking of observers and notifications.
27 class MockPrefNotifier : public PrefNotifier {
28 public:
29 MockPrefNotifier(PrefService* prefs, PrefValueStore* value_store)
30 : PrefNotifier(prefs, value_store) {}
31
32 virtual ~MockPrefNotifier() {}
33
34 MOCK_METHOD1(FireObservers, void(const char* path));
35
36 void RealFireObservers(const char* path) {
37 PrefNotifier::FireObservers(path);
38 }
39
40 size_t CountObserver(const char* path, NotificationObserver* obs) {
41 PrefObserverMap::const_iterator observer_iterator =
42 pref_observers()->find(path);
43 if (observer_iterator == pref_observers()->end())
44 return false;
45
46 NotificationObserverList* observer_list = observer_iterator->second;
47 NotificationObserverList::Iterator it(*observer_list);
48 NotificationObserver* existing_obs;
49 size_t count = 0;
50 while ((existing_obs = it.GetNext()) != NULL) {
51 if (existing_obs == obs)
52 count++;
53 }
54
55 return count;
56 }
57 };
58
59 // Mock PrefValueStore that has no unnecessary PrefStores and injects a simpler
60 // PrefHasChanged().
61 class MockPrefValueStore : public PrefValueStore {
62 public:
63 MockPrefValueStore()
64 : PrefValueStore(NULL, NULL, NULL, NULL, NULL, NULL,
65 new InMemoryPrefStore(), NULL) {}
66
67 virtual ~MockPrefValueStore() {}
68
69 // This mock version returns true if the pref path starts with "changed".
70 virtual bool PrefHasChanged(const char* path,
71 PrefNotifier::PrefStoreType new_store) {
72 std::string path_str(path);
73 if (path_str.compare(0, 7, "changed") == 0)
74 return true;
75 return false;
76 }
77 };
78
79 // Mock PrefService that allows the PrefNotifier to be injected.
80 class MockPrefService : public PrefService {
81 public:
82 explicit MockPrefService(PrefValueStore* pref_value_store)
83 : PrefService(pref_value_store) {}
84
85 void SetPrefNotifier(PrefNotifier* notifier) {
86 pref_notifier_.reset(notifier);
87 }
88 };
89
90 // Mock PrefObserver that verifies notifications.
91 class MockPrefObserver : public NotificationObserver {
92 public:
93 virtual ~MockPrefObserver() {}
94
95 MOCK_METHOD3(Observe, void(NotificationType type,
96 const NotificationSource& source,
97 const NotificationDetails& details));
98 };
99
100 // Test fixture class.
101 class PrefNotifierTest : public testing::Test {
102 protected:
103 virtual void SetUp() {
104 value_store_ = new MockPrefValueStore;
105 pref_service_.reset(new MockPrefService(value_store_));
106 notifier_ = new MockPrefNotifier(pref_service_.get(), value_store_);
107 pref_service_->SetPrefNotifier(notifier_);
108
109 pref_service_->RegisterBooleanPref(kChangedPref, true);
110 pref_service_->RegisterBooleanPref(kUnchangedPref, true);
111 }
112
113 // The PrefService takes ownership of the PrefValueStore and PrefNotifier.
114 PrefValueStore* value_store_;
115 MockPrefNotifier* notifier_;
116 scoped_ptr<MockPrefService> pref_service_;
117
118 MockPrefObserver obs1_;
119 MockPrefObserver obs2_;
120 };
121
122 TEST_F(PrefNotifierTest, OnPreferenceSet) {
123 EXPECT_CALL(*notifier_, FireObservers(kChangedPref))
124 .Times(PrefNotifier::PREF_STORE_TYPE_MAX + 1);
125 EXPECT_CALL(*notifier_, FireObservers(kUnchangedPref)).Times(0);
126
127 for (size_t i = 0; i <= PrefNotifier::PREF_STORE_TYPE_MAX; ++i) {
128 notifier_->OnPreferenceSet(kChangedPref,
129 static_cast<PrefNotifier::PrefStoreType>(i));
130 notifier_->OnPreferenceSet(kUnchangedPref,
131 static_cast<PrefNotifier::PrefStoreType>(i));
132 }
133 }
134
135 TEST_F(PrefNotifierTest, OnUserPreferenceSet) {
136 EXPECT_CALL(*notifier_, FireObservers(kChangedPref));
137 EXPECT_CALL(*notifier_, FireObservers(kUnchangedPref)).Times(0);
138 notifier_->OnUserPreferenceSet(kChangedPref);
139 notifier_->OnUserPreferenceSet(kUnchangedPref);
140 }
141
142 TEST_F(PrefNotifierTest, AddAndRemovePrefObservers) {
143 const char pref_name[] = "homepage";
144 const char pref_name2[] = "proxy";
145
146 notifier_->AddPrefObserver(pref_name, &obs1_);
147 ASSERT_EQ(1u, notifier_->CountObserver(pref_name, &obs1_));
148 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs1_));
149 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs2_));
150 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs2_));
151
152 // Re-adding the same observer for the same pref doesn't change anything.
153 // Skip this in debug mode, since it hits a DCHECK and death tests aren't
154 // thread-safe.
155 #if defined(NDEBUG)
156 notifier_->AddPrefObserver(pref_name, &obs1_);
157 ASSERT_EQ(1u, notifier_->CountObserver(pref_name, &obs1_));
158 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs1_));
159 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs2_));
160 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs2_));
161 #endif // NDEBUG
162
163 // Ensure that we can add the same observer to a different pref.
164 notifier_->AddPrefObserver(pref_name2, &obs1_);
165 ASSERT_EQ(1u, notifier_->CountObserver(pref_name, &obs1_));
166 ASSERT_EQ(1u, notifier_->CountObserver(pref_name2, &obs1_));
167 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs2_));
168 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs2_));
169
170 // Ensure that we can add another observer to the same pref.
171 notifier_->AddPrefObserver(pref_name, &obs2_);
172 ASSERT_EQ(1u, notifier_->CountObserver(pref_name, &obs1_));
173 ASSERT_EQ(1u, notifier_->CountObserver(pref_name2, &obs1_));
174 ASSERT_EQ(1u, notifier_->CountObserver(pref_name, &obs2_));
175 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs2_));
176
177 // Ensure that we can remove all observers, and that removing a non-existent
178 // observer is harmless.
179 notifier_->RemovePrefObserver(pref_name, &obs1_);
180 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs1_));
181 ASSERT_EQ(1u, notifier_->CountObserver(pref_name2, &obs1_));
182 ASSERT_EQ(1u, notifier_->CountObserver(pref_name, &obs2_));
183 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs2_));
184
185 notifier_->RemovePrefObserver(pref_name, &obs2_);
186 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs1_));
187 ASSERT_EQ(1u, notifier_->CountObserver(pref_name2, &obs1_));
188 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs2_));
189 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs2_));
190
191 notifier_->RemovePrefObserver(pref_name, &obs1_);
192 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs1_));
193 ASSERT_EQ(1u, notifier_->CountObserver(pref_name2, &obs1_));
194 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs2_));
195 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs2_));
196
197 notifier_->RemovePrefObserver(pref_name2, &obs1_);
198 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs1_));
199 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs1_));
200 ASSERT_EQ(0u, notifier_->CountObserver(pref_name, &obs2_));
201 ASSERT_EQ(0u, notifier_->CountObserver(pref_name2, &obs2_));
202 }
203
204 TEST_F(PrefNotifierTest, FireObservers) {
205 using testing::_;
206 using testing::Field;
207 using testing::Invoke;
208 using testing::Mock;
209 using testing::Truly;
210
211 // Tell googlemock to pass calls to the mock's "back door" too.
212 ON_CALL(*notifier_, FireObservers(_))
213 .WillByDefault(Invoke(notifier_, &MockPrefNotifier::RealFireObservers));
214 EXPECT_CALL(*notifier_, FireObservers(kChangedPref)).Times(4);
215 EXPECT_CALL(*notifier_, FireObservers(kUnchangedPref)).Times(0);
216
217 notifier_->AddPrefObserver(kChangedPref, &obs1_);
218 notifier_->AddPrefObserver(kUnchangedPref, &obs1_);
219
220 EXPECT_CALL(obs1_, Observe(
221 Field(&NotificationType::value, NotificationType::PREF_CHANGED),
222 Source<PrefService>(pref_service_.get()),
223 Truly(DetailsAreChangedPref)));
224 EXPECT_CALL(obs2_, Observe(_, _, _)).Times(0);
225 notifier_->OnUserPreferenceSet(kChangedPref);
226 Mock::VerifyAndClearExpectations(&obs1_);
227 Mock::VerifyAndClearExpectations(&obs2_);
228
229 EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
230 EXPECT_CALL(obs2_, Observe(_, _, _)).Times(0);
231 notifier_->OnUserPreferenceSet(kUnchangedPref);
232 Mock::VerifyAndClearExpectations(&obs1_);
233 Mock::VerifyAndClearExpectations(&obs2_);
234
235 notifier_->AddPrefObserver(kChangedPref, &obs2_);
236 notifier_->AddPrefObserver(kUnchangedPref, &obs2_);
237
238 EXPECT_CALL(obs1_, Observe(
239 Field(&NotificationType::value, NotificationType::PREF_CHANGED),
240 Source<PrefService>(pref_service_.get()),
241 Truly(DetailsAreChangedPref)));
242 EXPECT_CALL(obs2_, Observe(
243 Field(&NotificationType::value, NotificationType::PREF_CHANGED),
244 Source<PrefService>(pref_service_.get()),
245 Truly(DetailsAreChangedPref)));
246 notifier_->OnUserPreferenceSet(kChangedPref);
247 Mock::VerifyAndClearExpectations(&obs1_);
248 Mock::VerifyAndClearExpectations(&obs2_);
249
250 EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
251 EXPECT_CALL(obs2_, Observe(_, _, _)).Times(0);
252 notifier_->OnUserPreferenceSet(kUnchangedPref);
253 Mock::VerifyAndClearExpectations(&obs1_);
254 Mock::VerifyAndClearExpectations(&obs2_);
255
256 // Make sure removing an observer from one pref doesn't affect anything else.
257 notifier_->RemovePrefObserver(kChangedPref, &obs1_);
258
259 EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
260 EXPECT_CALL(obs2_, Observe(
261 Field(&NotificationType::value, NotificationType::PREF_CHANGED),
262 Source<PrefService>(pref_service_.get()),
263 Truly(DetailsAreChangedPref)));
264 notifier_->OnUserPreferenceSet(kChangedPref);
265 Mock::VerifyAndClearExpectations(&obs1_);
266 Mock::VerifyAndClearExpectations(&obs2_);
267
268 EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
269 EXPECT_CALL(obs2_, Observe(_, _, _)).Times(0);
270 notifier_->OnUserPreferenceSet(kUnchangedPref);
271 Mock::VerifyAndClearExpectations(&obs1_);
272 Mock::VerifyAndClearExpectations(&obs2_);
273
274 // Make sure removing an observer entirely doesn't affect anything else.
275 notifier_->RemovePrefObserver(kUnchangedPref, &obs1_);
276
277 EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
278 EXPECT_CALL(obs2_, Observe(
279 Field(&NotificationType::value, NotificationType::PREF_CHANGED),
280 Source<PrefService>(pref_service_.get()),
281 Truly(DetailsAreChangedPref)));
282 notifier_->OnUserPreferenceSet(kChangedPref);
283 Mock::VerifyAndClearExpectations(&obs1_);
284 Mock::VerifyAndClearExpectations(&obs2_);
285
286 EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
287 EXPECT_CALL(obs2_, Observe(_, _, _)).Times(0);
288 notifier_->OnUserPreferenceSet(kUnchangedPref);
289
290 notifier_->RemovePrefObserver(kChangedPref, &obs2_);
291 notifier_->RemovePrefObserver(kUnchangedPref, &obs2_);
292 }
293
294 } // namespace
OLDNEW
« no previous file with comments | « chrome/browser/prefs/pref_notifier_impl_unittest.cc ('k') | chrome/browser/prefs/pref_observer_mock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698