Upload upstream chromium 114.0.5735.31
[platform/framework/web/chromium-efl.git] / base / scoped_observation_unittest.cc
1 // Copyright 2020 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 "base/scoped_observation.h"
6
7 #include "base/containers/contains.h"
8 #include "base/ranges/algorithm.h"
9 #include "base/scoped_observation_traits.h"
10 #include "base/test/gtest_util.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace base {
14 namespace {
15
16 class TestSourceObserver {
17  public:
18   virtual ~TestSourceObserver() = default;
19 };
20
21 class TestSource {
22  public:
23   void AddObserver(TestSourceObserver* observer);
24   void RemoveObserver(TestSourceObserver* observer);
25
26   bool HasObserver(TestSourceObserver* observer) const;
27   size_t num_observers() const { return observers_.size(); }
28
29  private:
30   std::vector<TestSourceObserver*> observers_;
31 };
32
33 void TestSource::AddObserver(TestSourceObserver* observer) {
34   observers_.push_back(observer);
35 }
36
37 void TestSource::RemoveObserver(TestSourceObserver* observer) {
38   auto it = base::ranges::find(observers_, observer);
39   EXPECT_TRUE(it != observers_.end());
40   observers_.erase(it);
41 }
42
43 bool TestSource::HasObserver(TestSourceObserver* observer) const {
44   return base::Contains(observers_, observer);
45 }
46
47 using TestScopedObservation = ScopedObservation<TestSource, TestSourceObserver>;
48
49 }  // namespace
50
51 TEST(ScopedObservationTest, RemovesObservationOnDestruction) {
52   TestSource s1;
53
54   {
55     TestSourceObserver o1;
56     TestScopedObservation obs(&o1);
57     EXPECT_EQ(0u, s1.num_observers());
58     EXPECT_FALSE(s1.HasObserver(&o1));
59
60     obs.Observe(&s1);
61     EXPECT_EQ(1u, s1.num_observers());
62     EXPECT_TRUE(s1.HasObserver(&o1));
63   }
64
65   // Test that the observation is removed when it goes out of scope.
66   EXPECT_EQ(0u, s1.num_observers());
67 }
68
69 TEST(ScopedObservationTest, Reset) {
70   TestSource s1;
71   TestSourceObserver o1;
72   TestScopedObservation obs(&o1);
73   EXPECT_EQ(0u, s1.num_observers());
74   obs.Reset();
75
76   obs.Observe(&s1);
77   EXPECT_EQ(1u, s1.num_observers());
78   EXPECT_TRUE(s1.HasObserver(&o1));
79
80   obs.Reset();
81   EXPECT_EQ(0u, s1.num_observers());
82
83   // Safe to call with no observation.
84   obs.Reset();
85   EXPECT_EQ(0u, s1.num_observers());
86 }
87
88 TEST(ScopedObservationTest, IsObserving) {
89   TestSource s1;
90   TestSourceObserver o1;
91   TestScopedObservation obs(&o1);
92   EXPECT_FALSE(obs.IsObserving());
93
94   obs.Observe(&s1);
95   EXPECT_TRUE(obs.IsObserving());
96
97   obs.Reset();
98   EXPECT_FALSE(obs.IsObserving());
99 }
100
101 TEST(ScopedObservationTest, IsObservingSource) {
102   TestSource s1;
103   TestSource s2;
104   TestSourceObserver o1;
105   TestScopedObservation obs(&o1);
106   EXPECT_FALSE(obs.IsObservingSource(&s1));
107   EXPECT_FALSE(obs.IsObservingSource(&s2));
108
109   obs.Observe(&s1);
110   EXPECT_TRUE(obs.IsObservingSource(&s1));
111   EXPECT_FALSE(obs.IsObservingSource(&s2));
112
113   obs.Reset();
114   EXPECT_FALSE(obs.IsObservingSource(&s1));
115   EXPECT_FALSE(obs.IsObservingSource(&s2));
116 }
117
118 namespace {
119
120 // A test source with oddly named Add/Remove functions.
121 class TestSourceWithNonDefaultNames {
122  public:
123   void AddFoo(TestSourceObserver* observer) { impl_.AddObserver(observer); }
124   void RemoveFoo(TestSourceObserver* observer) {
125     impl_.RemoveObserver(observer);
126   }
127
128   const TestSource& impl() const { return impl_; }
129
130  private:
131   TestSource impl_;
132 };
133
134 using TestScopedObservationWithNonDefaultNames =
135     ScopedObservation<TestSourceWithNonDefaultNames, TestSourceObserver>;
136
137 }  // namespace
138
139 template <>
140 struct ScopedObservationTraits<TestSourceWithNonDefaultNames,
141                                TestSourceObserver> {
142   static void AddObserver(TestSourceWithNonDefaultNames* source,
143                           TestSourceObserver* observer) {
144     source->AddFoo(observer);
145   }
146   static void RemoveObserver(TestSourceWithNonDefaultNames* source,
147                              TestSourceObserver* observer) {
148     source->RemoveFoo(observer);
149   }
150 };
151
152 TEST(ScopedObservationTest, NonDefaultNames) {
153   TestSourceWithNonDefaultNames s1;
154   TestSourceObserver o1;
155
156   EXPECT_EQ(0u, s1.impl().num_observers());
157   {
158     TestScopedObservationWithNonDefaultNames obs(&o1);
159     obs.Observe(&s1);
160     EXPECT_EQ(1u, s1.impl().num_observers());
161     EXPECT_TRUE(s1.impl().HasObserver(&o1));
162   }
163
164   EXPECT_EQ(0u, s1.impl().num_observers());
165 }
166
167 namespace {
168
169 // A forward-declared test source.
170
171 class TestSourceFwd;
172
173 class ObservationHolder : public TestSourceObserver {
174  public:
175   // Declared but not defined since TestSourceFwd is not yet defined.
176   explicit ObservationHolder(TestSourceFwd* source);
177
178  private:
179   // ScopedObservation<> is instantiated with a forward-declared parameter.
180   ScopedObservation<TestSourceFwd, TestSourceObserver> obs_{this};
181 };
182
183 // TestSourceFwd gets an actual definition!
184 class TestSourceFwd : public TestSource {};
185
186 // Calling ScopedObservation::Observe() requires an actual definition rather
187 // than just a forward declaration; make sure it compiles now that there is a
188 // definition.
189 ObservationHolder::ObservationHolder(TestSourceFwd* source) {
190   obs_.Observe(source);
191 }
192
193 }  // namespace
194
195 TEST(ScopedObservationTest, ForwardDeclaredSource) {
196   TestSourceFwd s;
197   ASSERT_EQ(s.num_observers(), 0U);
198   {
199     ObservationHolder o(&s);
200     ASSERT_EQ(s.num_observers(), 1U);
201   }
202   ASSERT_EQ(s.num_observers(), 0U);
203 }
204
205 namespace {
206
207 class TestSourceWithNonDefaultNamesFwd;
208
209 class ObservationWithNonDefaultNamesHolder : public TestSourceObserver {
210  public:
211   // Declared but not defined since TestSourceWithNonDefaultNamesFwd is not yet
212   // defined.
213   explicit ObservationWithNonDefaultNamesHolder(
214       TestSourceWithNonDefaultNamesFwd* source);
215
216  private:
217   // ScopedObservation<> is instantiated with a forward-declared parameter.
218   ScopedObservation<TestSourceWithNonDefaultNamesFwd, TestSourceObserver> obs_{
219       this};
220 };
221
222 // TestSourceWithNonDefaultNamesFwd gets an actual definition!
223 class TestSourceWithNonDefaultNamesFwd : public TestSourceWithNonDefaultNames {
224 };
225
226 }  // namespace
227
228 // Now we define the corresponding traits. ScopedObservationTraits
229 // specializations must be defined in base::, since that is where the primary
230 // template definition lives.
231 template <>
232 struct ScopedObservationTraits<TestSourceWithNonDefaultNamesFwd,
233                                TestSourceObserver> {
234   static void AddObserver(TestSourceWithNonDefaultNamesFwd* source,
235                           TestSourceObserver* observer) {
236     source->AddFoo(observer);
237   }
238   static void RemoveObserver(TestSourceWithNonDefaultNamesFwd* source,
239                              TestSourceObserver* observer) {
240     source->RemoveFoo(observer);
241   }
242 };
243
244 namespace {
245
246 // Calling ScopedObservation::Observe() requires an actual definition rather
247 // than just a forward declaration; make sure it compiles now that there is
248 // a definition.
249 ObservationWithNonDefaultNamesHolder::ObservationWithNonDefaultNamesHolder(
250     TestSourceWithNonDefaultNamesFwd* source) {
251   obs_.Observe(source);
252 }
253
254 }  // namespace
255
256 TEST(ScopedObservationTest, ForwardDeclaredSourceWithNonDefaultNames) {
257   TestSourceWithNonDefaultNamesFwd s;
258   ASSERT_EQ(s.impl().num_observers(), 0U);
259   {
260     ObservationWithNonDefaultNamesHolder o(&s);
261     ASSERT_EQ(s.impl().num_observers(), 1U);
262   }
263   ASSERT_EQ(s.impl().num_observers(), 0U);
264 }
265
266 }  // namespace base