OLD | NEW |
| (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 | |
OLD | NEW |