• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "base/bind.h"
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"
16 
17 using testing::_;
18 using testing::Field;
19 using testing::Invoke;
20 using testing::Mock;
21 using testing::Truly;
22 
23 namespace {
24 
25 const char kChangedPref[] = "changed_pref";
26 const char kUnchangedPref[] = "unchanged_pref";
27 
28 class MockPrefInitObserver {
29  public:
30   MOCK_METHOD1(OnInitializationCompleted, void(bool));
31 };
32 
33 // This is an unmodified PrefNotifierImpl, except we make
34 // OnPreferenceChanged public for tests.
35 class TestingPrefNotifierImpl : public PrefNotifierImpl {
36  public:
TestingPrefNotifierImpl(PrefService * service)37   explicit TestingPrefNotifierImpl(PrefService* service)
38       : PrefNotifierImpl(service) {
39   }
40 
41   // Make public for tests.
42   using PrefNotifierImpl::OnPreferenceChanged;
43 };
44 
45 // Mock PrefNotifier that allows tracking of observers and notifications.
46 class MockPrefNotifier : public PrefNotifierImpl {
47  public:
MockPrefNotifier(PrefService * pref_service)48   explicit MockPrefNotifier(PrefService* pref_service)
49       : PrefNotifierImpl(pref_service) {}
~MockPrefNotifier()50   virtual ~MockPrefNotifier() {}
51 
52   MOCK_METHOD1(FireObservers, void(const std::string& path));
53 
CountObserver(const char * path,PrefObserver * obs)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())
58       return false;
59 
60     PrefObserverList* observer_list = observer_iterator->second;
61     PrefObserverList::Iterator it(*observer_list);
62     PrefObserver* existing_obs;
63     size_t count = 0;
64     while ((existing_obs = it.GetNext()) != NULL) {
65       if (existing_obs == obs)
66         count++;
67     }
68 
69     return count;
70   }
71 
72   // Make public for tests below.
73   using PrefNotifierImpl::OnPreferenceChanged;
74   using PrefNotifierImpl::OnInitializationCompleted;
75 };
76 
77 class PrefObserverMock : public PrefObserver {
78  public:
PrefObserverMock()79   PrefObserverMock() {}
~PrefObserverMock()80   virtual ~PrefObserverMock() {}
81 
82   MOCK_METHOD2(OnPreferenceChanged, void(PrefService*, const std::string&));
83 
Expect(PrefService * prefs,const std::string & pref_name,const base::Value * value)84   void Expect(PrefService* prefs,
85               const std::string& pref_name,
86               const base::Value* value) {
87     EXPECT_CALL(*this, OnPreferenceChanged(prefs, pref_name))
88         .With(PrefValueMatches(prefs, pref_name, value));
89   }
90 };
91 
92 // Test fixture class.
93 class PrefNotifierTest : public testing::Test {
94  protected:
SetUp()95   virtual void SetUp() {
96     pref_service_.registry()->RegisterBooleanPref(kChangedPref, true);
97     pref_service_.registry()->RegisterBooleanPref(kUnchangedPref, true);
98   }
99 
100   TestingPrefServiceSimple pref_service_;
101 
102   PrefObserverMock obs1_;
103   PrefObserverMock obs2_;
104 };
105 
TEST_F(PrefNotifierTest,OnPreferenceChanged)106 TEST_F(PrefNotifierTest, OnPreferenceChanged) {
107   MockPrefNotifier notifier(&pref_service_);
108   EXPECT_CALL(notifier, FireObservers(kChangedPref)).Times(1);
109   notifier.OnPreferenceChanged(kChangedPref);
110 }
111 
TEST_F(PrefNotifierTest,OnInitializationCompleted)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);
120 }
121 
TEST_F(PrefNotifierTest,AddAndRemovePrefObservers)122 TEST_F(PrefNotifierTest, AddAndRemovePrefObservers) {
123   const char pref_name[] = "homepage";
124   const char pref_name2[] = "proxy";
125 
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_));
132 
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
135   // thread-safe.
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_));
142 #endif
143 
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_));
150 
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_));
157 
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_));
165 
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_));
171 
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_));
177 
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_));
183 }
184 
TEST_F(PrefNotifierTest,FireObservers)185 TEST_F(PrefNotifierTest, FireObservers) {
186   TestingPrefNotifierImpl notifier(&pref_service_);
187   notifier.AddPrefObserver(kChangedPref, &obs1_);
188   notifier.AddPrefObserver(kUnchangedPref, &obs1_);
189 
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_);
195 
196   notifier.AddPrefObserver(kChangedPref, &obs2_);
197   notifier.AddPrefObserver(kUnchangedPref, &obs2_);
198 
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_);
204 
205   // Make sure removing an observer from one pref doesn't affect anything else.
206   notifier.RemovePrefObserver(kChangedPref, &obs1_);
207 
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_);
213 
214   // Make sure removing an observer entirely doesn't affect anything else.
215   notifier.RemovePrefObserver(kUnchangedPref, &obs1_);
216 
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_);
222 
223   notifier.RemovePrefObserver(kChangedPref, &obs2_);
224   notifier.RemovePrefObserver(kUnchangedPref, &obs2_);
225 }
226 
227 }  // namespace
228