• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/pref_notifier_impl.h"
6 #include "chrome/browser/prefs/pref_observer_mock.h"
7 #include "chrome/browser/prefs/pref_service.h"
8 #include "chrome/browser/prefs/pref_value_store.h"
9 #include "chrome/test/testing_pref_service.h"
10 #include "content/common/notification_observer_mock.h"
11 #include "content/common/notification_registrar.h"
12 #include "content/common/notification_service.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 using testing::_;
17 using testing::Field;
18 using testing::Invoke;
19 using testing::Mock;
20 using testing::Truly;
21 
22 namespace {
23 
24 const char kChangedPref[] = "changed_pref";
25 const char kUnchangedPref[] = "unchanged_pref";
26 
DetailsAreChangedPref(const Details<std::string> & details)27 bool DetailsAreChangedPref(const Details<std::string>& details) {
28   std::string* string_in = Details<std::string>(details).ptr();
29   return strcmp(string_in->c_str(), kChangedPref) == 0;
30 }
31 
32 // Test PrefNotifier that allows tracking of observers and notifications.
33 class MockPrefNotifier : public PrefNotifierImpl {
34  public:
MockPrefNotifier(PrefService * pref_service)35   explicit MockPrefNotifier(PrefService* pref_service)
36       : PrefNotifierImpl(pref_service) {}
~MockPrefNotifier()37   virtual ~MockPrefNotifier() {}
38 
39   MOCK_METHOD1(FireObservers, void(const std::string& path));
40 
CountObserver(const char * path,NotificationObserver * obs)41   size_t CountObserver(const char* path, NotificationObserver* obs) {
42     PrefObserverMap::const_iterator observer_iterator =
43         pref_observers()->find(path);
44     if (observer_iterator == pref_observers()->end())
45       return false;
46 
47     NotificationObserverList* observer_list = observer_iterator->second;
48     NotificationObserverList::Iterator it(*observer_list);
49     NotificationObserver* existing_obs;
50     size_t count = 0;
51     while ((existing_obs = it.GetNext()) != NULL) {
52       if (existing_obs == obs)
53         count++;
54     }
55 
56     return count;
57   }
58 };
59 
60 // Test fixture class.
61 class PrefNotifierTest : public testing::Test {
62  protected:
SetUp()63   virtual void SetUp() {
64     pref_service_.RegisterBooleanPref(kChangedPref, true);
65     pref_service_.RegisterBooleanPref(kUnchangedPref, true);
66   }
67 
68   TestingPrefService pref_service_;
69 
70   PrefObserverMock obs1_;
71   PrefObserverMock obs2_;
72 };
73 
TEST_F(PrefNotifierTest,OnPreferenceChanged)74 TEST_F(PrefNotifierTest, OnPreferenceChanged) {
75   MockPrefNotifier notifier(&pref_service_);
76   EXPECT_CALL(notifier, FireObservers(kChangedPref)).Times(1);
77   notifier.OnPreferenceChanged(kChangedPref);
78 }
79 
TEST_F(PrefNotifierTest,OnInitializationCompleted)80 TEST_F(PrefNotifierTest, OnInitializationCompleted) {
81   MockPrefNotifier notifier(&pref_service_);
82   NotificationObserverMock observer;
83   NotificationRegistrar registrar;
84   registrar.Add(&observer, NotificationType::PREF_INITIALIZATION_COMPLETED,
85                 Source<PrefService>(&pref_service_));
86   EXPECT_CALL(observer, Observe(
87       Field(&NotificationType::value,
88             NotificationType::PREF_INITIALIZATION_COMPLETED),
89       Source<PrefService>(&pref_service_),
90       NotificationService::NoDetails()));
91   notifier.OnInitializationCompleted();
92 }
93 
TEST_F(PrefNotifierTest,AddAndRemovePrefObservers)94 TEST_F(PrefNotifierTest, AddAndRemovePrefObservers) {
95   const char pref_name[] = "homepage";
96   const char pref_name2[] = "proxy";
97 
98   MockPrefNotifier notifier(&pref_service_);
99   notifier.AddPrefObserver(pref_name, &obs1_);
100   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
101   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
102   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
103   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
104 
105   // Re-adding the same observer for the same pref doesn't change anything.
106   // Skip this in debug mode, since it hits a DCHECK and death tests aren't
107   // thread-safe.
108 #if defined(NDEBUG)
109   notifier.AddPrefObserver(pref_name, &obs1_);
110   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
111   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
112   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
113   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
114 #endif  // NDEBUG
115 
116   // Ensure that we can add the same observer to a different pref.
117   notifier.AddPrefObserver(pref_name2, &obs1_);
118   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
119   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
120   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
121   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
122 
123   // Ensure that we can add another observer to the same pref.
124   notifier.AddPrefObserver(pref_name, &obs2_);
125   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
126   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
127   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_));
128   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
129 
130   // Ensure that we can remove all observers, and that removing a non-existent
131   // observer is harmless.
132   notifier.RemovePrefObserver(pref_name, &obs1_);
133   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
134   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
135   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_));
136   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
137 
138   notifier.RemovePrefObserver(pref_name, &obs2_);
139   ASSERT_EQ(0u, 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_));
143 
144   notifier.RemovePrefObserver(pref_name, &obs1_);
145   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
146   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
147   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
148   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
149 
150   notifier.RemovePrefObserver(pref_name2, &obs1_);
151   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
152   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
153   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
154   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
155 }
156 
TEST_F(PrefNotifierTest,FireObservers)157 TEST_F(PrefNotifierTest, FireObservers) {
158   FundamentalValue value_true(true);
159   PrefNotifierImpl notifier(&pref_service_);
160   notifier.AddPrefObserver(kChangedPref, &obs1_);
161   notifier.AddPrefObserver(kUnchangedPref, &obs1_);
162 
163   obs1_.Expect(&pref_service_, kChangedPref, &value_true);
164   EXPECT_CALL(obs2_, Observe(_, _, _)).Times(0);
165   notifier.OnPreferenceChanged(kChangedPref);
166   Mock::VerifyAndClearExpectations(&obs1_);
167   Mock::VerifyAndClearExpectations(&obs2_);
168 
169   notifier.AddPrefObserver(kChangedPref, &obs2_);
170   notifier.AddPrefObserver(kUnchangedPref, &obs2_);
171 
172   obs1_.Expect(&pref_service_, kChangedPref, &value_true);
173   obs2_.Expect(&pref_service_, kChangedPref, &value_true);
174   notifier.OnPreferenceChanged(kChangedPref);
175   Mock::VerifyAndClearExpectations(&obs1_);
176   Mock::VerifyAndClearExpectations(&obs2_);
177 
178   // Make sure removing an observer from one pref doesn't affect anything else.
179   notifier.RemovePrefObserver(kChangedPref, &obs1_);
180 
181   EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
182   obs2_.Expect(&pref_service_, kChangedPref, &value_true);
183   notifier.OnPreferenceChanged(kChangedPref);
184   Mock::VerifyAndClearExpectations(&obs1_);
185   Mock::VerifyAndClearExpectations(&obs2_);
186 
187   // Make sure removing an observer entirely doesn't affect anything else.
188   notifier.RemovePrefObserver(kUnchangedPref, &obs1_);
189 
190   EXPECT_CALL(obs1_, Observe(_, _, _)).Times(0);
191   obs2_.Expect(&pref_service_, kChangedPref, &value_true);
192   notifier.OnPreferenceChanged(kChangedPref);
193   Mock::VerifyAndClearExpectations(&obs1_);
194   Mock::VerifyAndClearExpectations(&obs2_);
195 
196   notifier.RemovePrefObserver(kChangedPref, &obs2_);
197   notifier.RemovePrefObserver(kUnchangedPref, &obs2_);
198 }
199 
200 }  // namespace
201