1 // Copyright (c) 2011 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.
6 #include "base/callback.h"
7 #include "base/prefs/mock_pref_change_callback.h"
8 #include "base/prefs/pref_notifier_impl.h"
9 #include "base/prefs/pref_observer.h"
10 #include "base/prefs/pref_registry_simple.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/prefs/pref_value_store.h"
13 #include "base/prefs/testing_pref_service.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
19 using testing::Invoke
;
25 const char kChangedPref
[] = "changed_pref";
26 const char kUnchangedPref
[] = "unchanged_pref";
28 class MockPrefInitObserver
{
30 MOCK_METHOD1(OnInitializationCompleted
, void(bool));
33 // This is an unmodified PrefNotifierImpl, except we make
34 // OnPreferenceChanged public for tests.
35 class TestingPrefNotifierImpl
: public PrefNotifierImpl
{
37 explicit TestingPrefNotifierImpl(PrefService
* service
)
38 : PrefNotifierImpl(service
) {
41 // Make public for tests.
42 using PrefNotifierImpl::OnPreferenceChanged
;
45 // Mock PrefNotifier that allows tracking of observers and notifications.
46 class MockPrefNotifier
: public PrefNotifierImpl
{
48 explicit MockPrefNotifier(PrefService
* pref_service
)
49 : PrefNotifierImpl(pref_service
) {}
50 virtual ~MockPrefNotifier() {}
52 MOCK_METHOD1(FireObservers
, void(const std::string
& path
));
54 size_t CountObserver(const char* path
, PrefObserver
* obs
) {
55 PrefObserverMap::const_iterator observer_iterator
=
56 pref_observers()->find(path
);
57 if (observer_iterator
== pref_observers()->end())
60 PrefObserverList
* observer_list
= observer_iterator
->second
;
61 PrefObserverList::Iterator
it(*observer_list
);
62 PrefObserver
* existing_obs
;
64 while ((existing_obs
= it
.GetNext()) != NULL
) {
65 if (existing_obs
== obs
)
72 // Make public for tests below.
73 using PrefNotifierImpl::OnPreferenceChanged
;
74 using PrefNotifierImpl::OnInitializationCompleted
;
77 class PrefObserverMock
: public PrefObserver
{
80 virtual ~PrefObserverMock() {}
82 MOCK_METHOD2(OnPreferenceChanged
, void(PrefService
*, const std::string
&));
84 void Expect(PrefService
* prefs
,
85 const std::string
& pref_name
,
87 EXPECT_CALL(*this, OnPreferenceChanged(prefs
, pref_name
))
88 .With(PrefValueMatches(prefs
, pref_name
, value
));
92 // Test fixture class.
93 class PrefNotifierTest
: public testing::Test
{
95 virtual void SetUp() {
96 pref_service_
.registry()->RegisterBooleanPref(kChangedPref
, true);
97 pref_service_
.registry()->RegisterBooleanPref(kUnchangedPref
, true);
100 TestingPrefServiceSimple pref_service_
;
102 PrefObserverMock obs1_
;
103 PrefObserverMock obs2_
;
106 TEST_F(PrefNotifierTest
, OnPreferenceChanged
) {
107 MockPrefNotifier
notifier(&pref_service_
);
108 EXPECT_CALL(notifier
, FireObservers(kChangedPref
)).Times(1);
109 notifier
.OnPreferenceChanged(kChangedPref
);
112 TEST_F(PrefNotifierTest
, OnInitializationCompleted
) {
113 MockPrefNotifier
notifier(&pref_service_
);
114 MockPrefInitObserver observer
;
115 notifier
.AddInitObserver(
116 base::Bind(&MockPrefInitObserver::OnInitializationCompleted
,
117 base::Unretained(&observer
)));
118 EXPECT_CALL(observer
, OnInitializationCompleted(true));
119 notifier
.OnInitializationCompleted(true);
122 TEST_F(PrefNotifierTest
, AddAndRemovePrefObservers
) {
123 const char pref_name
[] = "homepage";
124 const char pref_name2
[] = "proxy";
126 MockPrefNotifier
notifier(&pref_service_
);
127 notifier
.AddPrefObserver(pref_name
, &obs1_
);
128 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs1_
));
129 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs1_
));
130 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
131 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
133 // Re-adding the same observer for the same pref doesn't change anything.
134 // Skip this in debug mode, since it hits a DCHECK and death tests aren't
136 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
137 notifier
.AddPrefObserver(pref_name
, &obs1_
);
138 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs1_
));
139 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs1_
));
140 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
141 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
144 // Ensure that we can add the same observer to a different pref.
145 notifier
.AddPrefObserver(pref_name2
, &obs1_
);
146 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs1_
));
147 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
148 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
149 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
151 // Ensure that we can add another observer to the same pref.
152 notifier
.AddPrefObserver(pref_name
, &obs2_
);
153 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs1_
));
154 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
155 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs2_
));
156 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
158 // Ensure that we can remove all observers, and that removing a non-existent
159 // observer is harmless.
160 notifier
.RemovePrefObserver(pref_name
, &obs1_
);
161 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs1_
));
162 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
163 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs2_
));
164 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
166 notifier
.RemovePrefObserver(pref_name
, &obs2_
);
167 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs1_
));
168 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
169 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
170 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
172 notifier
.RemovePrefObserver(pref_name
, &obs1_
);
173 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs1_
));
174 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
175 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
176 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
178 notifier
.RemovePrefObserver(pref_name2
, &obs1_
);
179 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs1_
));
180 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs1_
));
181 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
182 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
185 TEST_F(PrefNotifierTest
, FireObservers
) {
186 TestingPrefNotifierImpl
notifier(&pref_service_
);
187 notifier
.AddPrefObserver(kChangedPref
, &obs1_
);
188 notifier
.AddPrefObserver(kUnchangedPref
, &obs1_
);
190 EXPECT_CALL(obs1_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
191 EXPECT_CALL(obs2_
, OnPreferenceChanged(_
, _
)).Times(0);
192 notifier
.OnPreferenceChanged(kChangedPref
);
193 Mock::VerifyAndClearExpectations(&obs1_
);
194 Mock::VerifyAndClearExpectations(&obs2_
);
196 notifier
.AddPrefObserver(kChangedPref
, &obs2_
);
197 notifier
.AddPrefObserver(kUnchangedPref
, &obs2_
);
199 EXPECT_CALL(obs1_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
200 EXPECT_CALL(obs2_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
201 notifier
.OnPreferenceChanged(kChangedPref
);
202 Mock::VerifyAndClearExpectations(&obs1_
);
203 Mock::VerifyAndClearExpectations(&obs2_
);
205 // Make sure removing an observer from one pref doesn't affect anything else.
206 notifier
.RemovePrefObserver(kChangedPref
, &obs1_
);
208 EXPECT_CALL(obs1_
, OnPreferenceChanged(_
, _
)).Times(0);
209 EXPECT_CALL(obs2_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
210 notifier
.OnPreferenceChanged(kChangedPref
);
211 Mock::VerifyAndClearExpectations(&obs1_
);
212 Mock::VerifyAndClearExpectations(&obs2_
);
214 // Make sure removing an observer entirely doesn't affect anything else.
215 notifier
.RemovePrefObserver(kUnchangedPref
, &obs1_
);
217 EXPECT_CALL(obs1_
, OnPreferenceChanged(_
, _
)).Times(0);
218 EXPECT_CALL(obs2_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
219 notifier
.OnPreferenceChanged(kChangedPref
);
220 Mock::VerifyAndClearExpectations(&obs1_
);
221 Mock::VerifyAndClearExpectations(&obs2_
);
223 notifier
.RemovePrefObserver(kChangedPref
, &obs2_
);
224 notifier
.RemovePrefObserver(kUnchangedPref
, &obs2_
);