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