xref: /aosp_15_r20/external/cronet/components/prefs/pref_notifier_impl_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2011 The Chromium Authors
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/functional/bind.h"
8 #include "base/functional/callback.h"
9 #include "components/prefs/mock_pref_change_callback.h"
10 #include "components/prefs/pref_notifier_impl.h"
11 #include "components/prefs/pref_observer.h"
12 #include "components/prefs/pref_registry_simple.h"
13 #include "components/prefs/pref_service.h"
14 #include "components/prefs/pref_value_store.h"
15 #include "components/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:
TestingPrefNotifierImpl(PrefService * service)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:
MockPrefNotifier(PrefService * pref_service)50   explicit MockPrefNotifier(PrefService* pref_service)
51       : PrefNotifierImpl(pref_service) {}
~MockPrefNotifier()52   ~MockPrefNotifier() override {}
53 
54   MOCK_METHOD1(FireObservers, void(const std::string& path));
55 
CountObserver(const std::string & path,PrefObserver * obs)56   size_t CountObserver(const std::string& path, PrefObserver* obs) {
57     auto observer_iterator = pref_observers()->find(path);
58     if (observer_iterator == pref_observers()->end())
59       return false;
60 
61     size_t count = 0;
62     for (auto& existing_obs : *observer_iterator->second) {
63       if (&existing_obs == obs)
64         count++;
65     }
66 
67     return count;
68   }
69 
70   // Make public for tests below.
71   using PrefNotifierImpl::OnPreferenceChanged;
72   using PrefNotifierImpl::OnInitializationCompleted;
73 };
74 
75 class PrefObserverMock : public PrefObserver {
76  public:
PrefObserverMock()77   PrefObserverMock() {}
~PrefObserverMock()78   virtual ~PrefObserverMock() {}
79 
80   MOCK_METHOD2(OnPreferenceChanged, void(PrefService*, const std::string&));
81 };
82 
83 // Test fixture class.
84 class PrefNotifierTest : public testing::Test {
85  protected:
SetUp()86   void SetUp() override {
87     pref_service_.registry()->RegisterBooleanPref(kChangedPref, true);
88     pref_service_.registry()->RegisterBooleanPref(kUnchangedPref, true);
89   }
90 
91   TestingPrefServiceSimple pref_service_;
92 
93   PrefObserverMock obs1_;
94   PrefObserverMock obs2_;
95 };
96 
TEST_F(PrefNotifierTest,OnPreferenceChanged)97 TEST_F(PrefNotifierTest, OnPreferenceChanged) {
98   MockPrefNotifier notifier(&pref_service_);
99   EXPECT_CALL(notifier, FireObservers(kChangedPref)).Times(1);
100   notifier.OnPreferenceChanged(kChangedPref);
101 }
102 
TEST_F(PrefNotifierTest,OnInitializationCompleted)103 TEST_F(PrefNotifierTest, OnInitializationCompleted) {
104   MockPrefNotifier notifier(&pref_service_);
105   MockPrefInitObserver observer;
106   notifier.AddInitObserver(
107       base::BindOnce(&MockPrefInitObserver::OnInitializationCompleted,
108                      base::Unretained(&observer)));
109   EXPECT_CALL(observer, OnInitializationCompleted(true));
110   notifier.OnInitializationCompleted(true);
111 }
112 
TEST_F(PrefNotifierTest,AddAndRemovePrefObservers)113 TEST_F(PrefNotifierTest, AddAndRemovePrefObservers) {
114   const char pref_name[] = "homepage";
115   const char pref_name2[] = "proxy";
116 
117   MockPrefNotifier notifier(&pref_service_);
118   notifier.AddPrefObserver(pref_name, &obs1_);
119   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
120   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
121   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
122   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
123 
124   // Re-adding the same observer for the same pref doesn't change anything.
125   // Skip this in debug mode, since it hits a DCHECK and death tests aren't
126   // thread-safe.
127 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
128   notifier.AddPrefObserver(pref_name, &obs1_);
129   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
130   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
131   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
132   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
133 #endif
134 
135   // Ensure that we can add the same observer to a different pref.
136   notifier.AddPrefObserver(pref_name2, &obs1_);
137   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
138   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
139   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
140   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
141 
142   // Ensure that we can add another observer to the same pref.
143   notifier.AddPrefObserver(pref_name, &obs2_);
144   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs1_));
145   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
146   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_));
147   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
148 
149   // Ensure that we can remove all observers, and that removing a non-existent
150   // observer is harmless.
151   notifier.RemovePrefObserver(pref_name, &obs1_);
152   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
153   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
154   ASSERT_EQ(1u, notifier.CountObserver(pref_name, &obs2_));
155   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
156 
157   notifier.RemovePrefObserver(pref_name, &obs2_);
158   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
159   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
160   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
161   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
162 
163   notifier.RemovePrefObserver(pref_name, &obs1_);
164   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
165   ASSERT_EQ(1u, notifier.CountObserver(pref_name2, &obs1_));
166   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
167   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
168 
169   notifier.RemovePrefObserver(pref_name2, &obs1_);
170   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs1_));
171   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs1_));
172   ASSERT_EQ(0u, notifier.CountObserver(pref_name, &obs2_));
173   ASSERT_EQ(0u, notifier.CountObserver(pref_name2, &obs2_));
174 }
175 
TEST_F(PrefNotifierTest,FireObservers)176 TEST_F(PrefNotifierTest, FireObservers) {
177   TestingPrefNotifierImpl notifier(&pref_service_);
178   notifier.AddPrefObserver(kChangedPref, &obs1_);
179   notifier.AddPrefObserver(kUnchangedPref, &obs1_);
180 
181   EXPECT_CALL(obs1_, OnPreferenceChanged(&pref_service_, kChangedPref));
182   EXPECT_CALL(obs2_, OnPreferenceChanged(_, _)).Times(0);
183   notifier.OnPreferenceChanged(kChangedPref);
184   Mock::VerifyAndClearExpectations(&obs1_);
185   Mock::VerifyAndClearExpectations(&obs2_);
186 
187   notifier.AddPrefObserver(kChangedPref, &obs2_);
188   notifier.AddPrefObserver(kUnchangedPref, &obs2_);
189 
190   EXPECT_CALL(obs1_, OnPreferenceChanged(&pref_service_, kChangedPref));
191   EXPECT_CALL(obs2_, OnPreferenceChanged(&pref_service_, kChangedPref));
192   notifier.OnPreferenceChanged(kChangedPref);
193   Mock::VerifyAndClearExpectations(&obs1_);
194   Mock::VerifyAndClearExpectations(&obs2_);
195 
196   // Make sure removing an observer from one pref doesn't affect anything else.
197   notifier.RemovePrefObserver(kChangedPref, &obs1_);
198 
199   EXPECT_CALL(obs1_, OnPreferenceChanged(_, _)).Times(0);
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 entirely doesn't affect anything else.
206   notifier.RemovePrefObserver(kUnchangedPref, &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   notifier.RemovePrefObserver(kChangedPref, &obs2_);
215   notifier.RemovePrefObserver(kUnchangedPref, &obs2_);
216 }
217 
218 }  // namespace
219