OLD | NEW |
(Empty) | |
| 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 <stddef.h> |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/callback.h" |
| 9 #include "base/prefs/mock_pref_change_callback.h" |
| 10 #include "base/prefs/pref_notifier_impl.h" |
| 11 #include "base/prefs/pref_observer.h" |
| 12 #include "base/prefs/pref_registry_simple.h" |
| 13 #include "base/prefs/pref_service.h" |
| 14 #include "base/prefs/pref_value_store.h" |
| 15 #include "base/prefs/testing_pref_service.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 using testing::_; |
| 20 using testing::Field; |
| 21 using testing::Invoke; |
| 22 using testing::Mock; |
| 23 using testing::Truly; |
| 24 |
| 25 namespace { |
| 26 |
| 27 const char kChangedPref[] = "changed_pref"; |
| 28 const char kUnchangedPref[] = "unchanged_pref"; |
| 29 |
| 30 class MockPrefInitObserver { |
| 31 public: |
| 32 MOCK_METHOD1(OnInitializationCompleted, void(bool)); |
| 33 }; |
| 34 |
| 35 // This is an unmodified PrefNotifierImpl, except we make |
| 36 // OnPreferenceChanged public for tests. |
| 37 class TestingPrefNotifierImpl : public PrefNotifierImpl { |
| 38 public: |
| 39 explicit TestingPrefNotifierImpl(PrefService* service) |
| 40 : PrefNotifierImpl(service) { |
| 41 } |
| 42 |
| 43 // Make public for tests. |
| 44 using PrefNotifierImpl::OnPreferenceChanged; |
| 45 }; |
| 46 |
| 47 // Mock PrefNotifier that allows tracking of observers and notifications. |
| 48 class MockPrefNotifier : public PrefNotifierImpl { |
| 49 public: |
| 50 explicit MockPrefNotifier(PrefService* pref_service) |
| 51 : PrefNotifierImpl(pref_service) {} |
| 52 virtual ~MockPrefNotifier() {} |
| 53 |
| 54 MOCK_METHOD1(FireObservers, void(const std::string& path)); |
| 55 |
| 56 size_t CountObserver(const std::string& path, PrefObserver* obs) { |
| 57 PrefObserverMap::const_iterator observer_iterator = |
| 58 pref_observers()->find(path); |
| 59 if (observer_iterator == pref_observers()->end()) |
| 60 return false; |
| 61 |
| 62 PrefObserverList* observer_list = observer_iterator->second; |
| 63 PrefObserverList::Iterator it(observer_list); |
| 64 PrefObserver* existing_obs; |
| 65 size_t count = 0; |
| 66 while ((existing_obs = it.GetNext()) != NULL) { |
| 67 if (existing_obs == obs) |
| 68 count++; |
| 69 } |
| 70 |
| 71 return count; |
| 72 } |
| 73 |
| 74 // Make public for tests below. |
| 75 using PrefNotifierImpl::OnPreferenceChanged; |
| 76 using PrefNotifierImpl::OnInitializationCompleted; |
| 77 }; |
| 78 |
| 79 class PrefObserverMock : public PrefObserver { |
| 80 public: |
| 81 PrefObserverMock() {} |
| 82 virtual ~PrefObserverMock() {} |
| 83 |
| 84 MOCK_METHOD2(OnPreferenceChanged, void(PrefService*, const std::string&)); |
| 85 }; |
| 86 |
| 87 // Test fixture class. |
| 88 class PrefNotifierTest : public testing::Test { |
| 89 protected: |
| 90 void SetUp() override { |
| 91 pref_service_.registry()->RegisterBooleanPref(kChangedPref, true); |
| 92 pref_service_.registry()->RegisterBooleanPref(kUnchangedPref, true); |
| 93 } |
| 94 |
| 95 TestingPrefServiceSimple pref_service_; |
| 96 |
| 97 PrefObserverMock obs1_; |
| 98 PrefObserverMock obs2_; |
| 99 }; |
| 100 |
| 101 TEST_F(PrefNotifierTest, OnPreferenceChanged) { |
| 102 MockPrefNotifier notifier(&pref_service_); |
| 103 EXPECT_CALL(notifier, FireObservers(kChangedPref)).Times(1); |
| 104 notifier.OnPreferenceChanged(kChangedPref); |
| 105 } |
| 106 |
| 107 TEST_F(PrefNotifierTest, OnInitializationCompleted) { |
| 108 MockPrefNotifier notifier(&pref_service_); |
| 109 MockPrefInitObserver observer; |
| 110 notifier.AddInitObserver( |
| 111 base::Bind(&MockPrefInitObserver::OnInitializationCompleted, |
| 112 base::Unretained(&observer))); |
| 113 EXPECT_CALL(observer, OnInitializationCompleted(true)); |
| 114 notifier.OnInitializationCompleted(true); |
| 115 } |
| 116 |
| 117 TEST_F(PrefNotifierTest, AddAndRemovePrefObservers) { |
| 118 const char pref_name[] = "homepage"; |
| 119 const char pref_name2[] = "proxy"; |
| 120 |
| 121 MockPrefNotifier notifier(&pref_service_); |
| 122 notifier.AddPrefObserver(pref_name, &obs1_); |
| 123 ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_)); |
| 124 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_)); |
| 125 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_)); |
| 126 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_)); |
| 127 |
| 128 // Re-adding the same observer for the same pref doesn't change anything. |
| 129 // Skip this in debug mode, since it hits a DCHECK and death tests aren't |
| 130 // thread-safe. |
| 131 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) |
| 132 notifier.AddPrefObserver(pref_name, &obs1_); |
| 133 ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_)); |
| 134 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_)); |
| 135 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_)); |
| 136 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_)); |
| 137 #endif |
| 138 |
| 139 // Ensure that we can add the same observer to a different pref. |
| 140 notifier.AddPrefObserver(pref_name2, &obs1_); |
| 141 ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_)); |
| 142 ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_)); |
| 143 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_)); |
| 144 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_)); |
| 145 |
| 146 // Ensure that we can add another observer to the same pref. |
| 147 notifier.AddPrefObserver(pref_name, &obs2_); |
| 148 ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_)); |
| 149 ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_)); |
| 150 ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_)); |
| 151 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_)); |
| 152 |
| 153 // Ensure that we can remove all observers, and that removing a non-existent |
| 154 // observer is harmless. |
| 155 notifier.RemovePrefObserver(pref_name, &obs1_); |
| 156 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_)); |
| 157 ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_)); |
| 158 ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_)); |
| 159 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_)); |
| 160 |
| 161 notifier.RemovePrefObserver(pref_name, &obs2_); |
| 162 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_)); |
| 163 ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_)); |
| 164 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_)); |
| 165 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_)); |
| 166 |
| 167 notifier.RemovePrefObserver(pref_name, &obs1_); |
| 168 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_)); |
| 169 ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_)); |
| 170 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_)); |
| 171 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_)); |
| 172 |
| 173 notifier.RemovePrefObserver(pref_name2, &obs1_); |
| 174 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_)); |
| 175 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_)); |
| 176 ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_)); |
| 177 ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_)); |
| 178 } |
| 179 |
| 180 TEST_F(PrefNotifierTest, FireObservers) { |
| 181 TestingPrefNotifierImpl notifier(&pref_service_); |
| 182 notifier.AddPrefObserver(kChangedPref, &obs1_); |
| 183 notifier.AddPrefObserver(kUnchangedPref, &obs1_); |
| 184 |
| 185 EXPECT_CALL(obs1_, OnPreferenceChanged(&pref_service_, kChangedPref)); |
| 186 EXPECT_CALL(obs2_, OnPreferenceChanged(_, _)).Times(0); |
| 187 notifier.OnPreferenceChanged(kChangedPref); |
| 188 Mock::VerifyAndClearExpectations(&obs1_); |
| 189 Mock::VerifyAndClearExpectations(&obs2_); |
| 190 |
| 191 notifier.AddPrefObserver(kChangedPref, &obs2_); |
| 192 notifier.AddPrefObserver(kUnchangedPref, &obs2_); |
| 193 |
| 194 EXPECT_CALL(obs1_, OnPreferenceChanged(&pref_service_, kChangedPref)); |
| 195 EXPECT_CALL(obs2_, OnPreferenceChanged(&pref_service_, kChangedPref)); |
| 196 notifier.OnPreferenceChanged(kChangedPref); |
| 197 Mock::VerifyAndClearExpectations(&obs1_); |
| 198 Mock::VerifyAndClearExpectations(&obs2_); |
| 199 |
| 200 // Make sure removing an observer from one pref doesn't affect anything else. |
| 201 notifier.RemovePrefObserver(kChangedPref, &obs1_); |
| 202 |
| 203 EXPECT_CALL(obs1_, OnPreferenceChanged(_, _)).Times(0); |
| 204 EXPECT_CALL(obs2_, OnPreferenceChanged(&pref_service_, kChangedPref)); |
| 205 notifier.OnPreferenceChanged(kChangedPref); |
| 206 Mock::VerifyAndClearExpectations(&obs1_); |
| 207 Mock::VerifyAndClearExpectations(&obs2_); |
| 208 |
| 209 // Make sure removing an observer entirely doesn't affect anything else. |
| 210 notifier.RemovePrefObserver(kUnchangedPref, &obs1_); |
| 211 |
| 212 EXPECT_CALL(obs1_, OnPreferenceChanged(_, _)).Times(0); |
| 213 EXPECT_CALL(obs2_, OnPreferenceChanged(&pref_service_, kChangedPref)); |
| 214 notifier.OnPreferenceChanged(kChangedPref); |
| 215 Mock::VerifyAndClearExpectations(&obs1_); |
| 216 Mock::VerifyAndClearExpectations(&obs2_); |
| 217 |
| 218 notifier.RemovePrefObserver(kChangedPref, &obs2_); |
| 219 notifier.RemovePrefObserver(kUnchangedPref, &obs2_); |
| 220 } |
| 221 |
| 222 } // namespace |
OLD | NEW |