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
&));
85 // Test fixture class.
86 class PrefNotifierTest
: public testing::Test
{
88 virtual void SetUp() {
89 pref_service_
.registry()->RegisterBooleanPref(kChangedPref
, true);
90 pref_service_
.registry()->RegisterBooleanPref(kUnchangedPref
, true);
93 TestingPrefServiceSimple pref_service_
;
95 PrefObserverMock obs1_
;
96 PrefObserverMock obs2_
;
99 TEST_F(PrefNotifierTest
, OnPreferenceChanged
) {
100 MockPrefNotifier
notifier(&pref_service_
);
101 EXPECT_CALL(notifier
, FireObservers(kChangedPref
)).Times(1);
102 notifier
.OnPreferenceChanged(kChangedPref
);
105 TEST_F(PrefNotifierTest
, OnInitializationCompleted
) {
106 MockPrefNotifier
notifier(&pref_service_
);
107 MockPrefInitObserver observer
;
108 notifier
.AddInitObserver(
109 base::Bind(&MockPrefInitObserver::OnInitializationCompleted
,
110 base::Unretained(&observer
)));
111 EXPECT_CALL(observer
, OnInitializationCompleted(true));
112 notifier
.OnInitializationCompleted(true);
115 TEST_F(PrefNotifierTest
, AddAndRemovePrefObservers
) {
116 const char pref_name
[] = "homepage";
117 const char pref_name2
[] = "proxy";
119 MockPrefNotifier
notifier(&pref_service_
);
120 notifier
.AddPrefObserver(pref_name
, &obs1_
);
121 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs1_
));
122 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs1_
));
123 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
124 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
126 // Re-adding the same observer for the same pref doesn't change anything.
127 // Skip this in debug mode, since it hits a DCHECK and death tests aren't
129 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
130 notifier
.AddPrefObserver(pref_name
, &obs1_
);
131 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs1_
));
132 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs1_
));
133 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
134 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
137 // Ensure that we can add the same observer to a different pref.
138 notifier
.AddPrefObserver(pref_name2
, &obs1_
);
139 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs1_
));
140 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
141 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
142 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
144 // Ensure that we can add another observer to the same pref.
145 notifier
.AddPrefObserver(pref_name
, &obs2_
);
146 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs1_
));
147 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
148 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs2_
));
149 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
151 // Ensure that we can remove all observers, and that removing a non-existent
152 // observer is harmless.
153 notifier
.RemovePrefObserver(pref_name
, &obs1_
);
154 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs1_
));
155 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
156 ASSERT_EQ(1u, notifier
.CountObserver(pref_name
, &obs2_
));
157 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
159 notifier
.RemovePrefObserver(pref_name
, &obs2_
);
160 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs1_
));
161 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
162 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
163 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
165 notifier
.RemovePrefObserver(pref_name
, &obs1_
);
166 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs1_
));
167 ASSERT_EQ(1u, notifier
.CountObserver(pref_name2
, &obs1_
));
168 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
169 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
171 notifier
.RemovePrefObserver(pref_name2
, &obs1_
);
172 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs1_
));
173 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs1_
));
174 ASSERT_EQ(0u, notifier
.CountObserver(pref_name
, &obs2_
));
175 ASSERT_EQ(0u, notifier
.CountObserver(pref_name2
, &obs2_
));
178 TEST_F(PrefNotifierTest
, FireObservers
) {
179 TestingPrefNotifierImpl
notifier(&pref_service_
);
180 notifier
.AddPrefObserver(kChangedPref
, &obs1_
);
181 notifier
.AddPrefObserver(kUnchangedPref
, &obs1_
);
183 EXPECT_CALL(obs1_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
184 EXPECT_CALL(obs2_
, OnPreferenceChanged(_
, _
)).Times(0);
185 notifier
.OnPreferenceChanged(kChangedPref
);
186 Mock::VerifyAndClearExpectations(&obs1_
);
187 Mock::VerifyAndClearExpectations(&obs2_
);
189 notifier
.AddPrefObserver(kChangedPref
, &obs2_
);
190 notifier
.AddPrefObserver(kUnchangedPref
, &obs2_
);
192 EXPECT_CALL(obs1_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
193 EXPECT_CALL(obs2_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
194 notifier
.OnPreferenceChanged(kChangedPref
);
195 Mock::VerifyAndClearExpectations(&obs1_
);
196 Mock::VerifyAndClearExpectations(&obs2_
);
198 // Make sure removing an observer from one pref doesn't affect anything else.
199 notifier
.RemovePrefObserver(kChangedPref
, &obs1_
);
201 EXPECT_CALL(obs1_
, OnPreferenceChanged(_
, _
)).Times(0);
202 EXPECT_CALL(obs2_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
203 notifier
.OnPreferenceChanged(kChangedPref
);
204 Mock::VerifyAndClearExpectations(&obs1_
);
205 Mock::VerifyAndClearExpectations(&obs2_
);
207 // Make sure removing an observer entirely doesn't affect anything else.
208 notifier
.RemovePrefObserver(kUnchangedPref
, &obs1_
);
210 EXPECT_CALL(obs1_
, OnPreferenceChanged(_
, _
)).Times(0);
211 EXPECT_CALL(obs2_
, OnPreferenceChanged(&pref_service_
, kChangedPref
));
212 notifier
.OnPreferenceChanged(kChangedPref
);
213 Mock::VerifyAndClearExpectations(&obs1_
);
214 Mock::VerifyAndClearExpectations(&obs2_
);
216 notifier
.RemovePrefObserver(kChangedPref
, &obs2_
);
217 notifier
.RemovePrefObserver(kUnchangedPref
, &obs2_
);