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