[go: nahoru, domu]

blob: cf57c1ce06812696b5a8b1e76bf7bf840e32d8c9 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2020 The Chromium Authors
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:172// 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_multi_source_observation.h"
6
Jan Wilken Dörrieb5a41c32020-12-09 18:55:477#include "base/containers/contains.h"
Ali Hijazie63cbaf62023-12-20 19:29:358#include "base/memory/raw_ptr.h"
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:179#include "base/ranges/algorithm.h"
Andrew Rayskiy3cf073392022-11-11 00:31:4910#include "base/scoped_observation_traits.h"
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1711#include "base/test/gtest_util.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace base {
15namespace {
16
17class TestSourceObserver {};
18
19class TestSource {
20 public:
21 void AddObserver(TestSourceObserver* observer);
22 void RemoveObserver(TestSourceObserver* observer);
23
24 bool HasObserver(TestSourceObserver* observer) const;
25 size_t num_observers() const { return observers_.size(); }
26
27 private:
Ali Hijazie63cbaf62023-12-20 19:29:3528 std::vector<raw_ptr<TestSourceObserver, VectorExperimental>> observers_;
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1729};
30
31void TestSource::AddObserver(TestSourceObserver* observer) {
32 observers_.push_back(observer);
33}
34
35void TestSource::RemoveObserver(TestSourceObserver* observer) {
36 auto it = base::ranges::find(observers_, observer);
37 ASSERT_TRUE(it != observers_.end());
38 observers_.erase(it);
39}
40
41bool TestSource::HasObserver(TestSourceObserver* observer) const {
42 return base::Contains(observers_, observer);
43}
44
45using TestScopedMultiSourceObservation =
46 ScopedMultiSourceObservation<TestSource, TestSourceObserver>;
47
48class ScopedMultiSourceObservationTest : public testing::Test {
49 public:
50 TestSource* s1() { return &s1_; }
51 TestSource* s2() { return &s2_; }
52 TestSourceObserver* o1() { return &o1_; }
53
54 private:
55 TestSource s1_;
56 TestSource s2_;
57 TestSourceObserver o1_;
58};
59
60} // namespace
61
62TEST_F(ScopedMultiSourceObservationTest, RemovesSourcesOnDestruction) {
63 {
64 TestScopedMultiSourceObservation obs(o1());
65 EXPECT_EQ(0u, s1()->num_observers());
66 EXPECT_FALSE(s1()->HasObserver(o1()));
67
68 obs.AddObservation(s1());
69 EXPECT_EQ(1u, s1()->num_observers());
70 EXPECT_TRUE(s1()->HasObserver(o1()));
71
72 obs.AddObservation(s2());
73 EXPECT_EQ(1u, s2()->num_observers());
74 EXPECT_TRUE(s2()->HasObserver(o1()));
75 }
76
77 // Test that all observations are removed when it goes out of scope.
78 EXPECT_EQ(0u, s1()->num_observers());
79 EXPECT_EQ(0u, s2()->num_observers());
80}
81
82TEST_F(ScopedMultiSourceObservationTest, RemoveObservation) {
83 TestScopedMultiSourceObservation obs(o1());
84 EXPECT_EQ(0u, s1()->num_observers());
85 EXPECT_FALSE(s1()->HasObserver(o1()));
86 EXPECT_EQ(0u, s2()->num_observers());
87 EXPECT_FALSE(s2()->HasObserver(o1()));
88
89 obs.AddObservation(s1());
90 EXPECT_EQ(1u, s1()->num_observers());
91 EXPECT_TRUE(s1()->HasObserver(o1()));
92
93 obs.AddObservation(s2());
94 EXPECT_EQ(1u, s2()->num_observers());
95 EXPECT_TRUE(s2()->HasObserver(o1()));
96
97 obs.RemoveObservation(s1());
98 EXPECT_EQ(0u, s1()->num_observers());
99 EXPECT_FALSE(s1()->HasObserver(o1()));
100 EXPECT_EQ(1u, s2()->num_observers());
101 EXPECT_TRUE(s2()->HasObserver(o1()));
102
103 obs.RemoveObservation(s2());
104 EXPECT_EQ(0u, s1()->num_observers());
105 EXPECT_FALSE(s1()->HasObserver(o1()));
106 EXPECT_EQ(0u, s2()->num_observers());
107 EXPECT_FALSE(s2()->HasObserver(o1()));
108}
109
110TEST_F(ScopedMultiSourceObservationTest, RemoveAllObservations) {
111 TestScopedMultiSourceObservation obs(o1());
112 EXPECT_EQ(0u, s1()->num_observers());
113 EXPECT_FALSE(s1()->HasObserver(o1()));
114 EXPECT_EQ(0u, s2()->num_observers());
115 EXPECT_FALSE(s2()->HasObserver(o1()));
116
117 obs.AddObservation(s1());
118 obs.AddObservation(s2());
119 EXPECT_EQ(1u, s1()->num_observers());
120 EXPECT_TRUE(s1()->HasObserver(o1()));
121 EXPECT_EQ(1u, s2()->num_observers());
122 EXPECT_TRUE(s2()->HasObserver(o1()));
123
124 obs.RemoveAllObservations();
125 EXPECT_EQ(0u, s1()->num_observers());
126 EXPECT_FALSE(s1()->HasObserver(o1()));
127 EXPECT_EQ(0u, s2()->num_observers());
128 EXPECT_FALSE(s2()->HasObserver(o1()));
129}
130
131TEST_F(ScopedMultiSourceObservationTest, IsObservingSource) {
132 TestScopedMultiSourceObservation obs(o1());
133 EXPECT_FALSE(obs.IsObservingSource(s1()));
134 EXPECT_FALSE(obs.IsObservingSource(s2()));
135
136 obs.AddObservation(s1());
137 EXPECT_TRUE(obs.IsObservingSource(s1()));
138 EXPECT_FALSE(obs.IsObservingSource(s2()));
139
140 obs.AddObservation(s2());
141 EXPECT_TRUE(obs.IsObservingSource(s1()));
142 EXPECT_TRUE(obs.IsObservingSource(s2()));
143
144 obs.RemoveObservation(s1());
145 EXPECT_FALSE(obs.IsObservingSource(s1()));
146 EXPECT_TRUE(obs.IsObservingSource(s2()));
147}
148
149TEST_F(ScopedMultiSourceObservationTest, IsObservingAnySource) {
150 TestScopedMultiSourceObservation obs(o1());
151 EXPECT_FALSE(obs.IsObservingAnySource());
152
153 obs.AddObservation(s1());
154 EXPECT_TRUE(obs.IsObservingAnySource());
155
156 obs.AddObservation(s2());
157 EXPECT_TRUE(obs.IsObservingAnySource());
158
159 obs.RemoveAllObservations();
160 EXPECT_FALSE(obs.IsObservingAnySource());
161}
162
163TEST_F(ScopedMultiSourceObservationTest, GetSourcesCount) {
164 TestScopedMultiSourceObservation obs(o1());
165 EXPECT_EQ(0u, obs.GetSourcesCount());
166
167 obs.AddObservation(s1());
168 EXPECT_EQ(1u, obs.GetSourcesCount());
169
170 obs.AddObservation(s2());
171 EXPECT_EQ(2u, obs.GetSourcesCount());
172
173 obs.RemoveAllObservations();
174 EXPECT_EQ(0u, obs.GetSourcesCount());
175}
176
177namespace {
178
179// A test source with oddly named Add/Remove functions.
180class TestSourceWithNonDefaultNames {
181 public:
182 void AddFoo(TestSourceObserver* observer) { impl_.AddObserver(observer); }
183 void RemoveFoo(TestSourceObserver* observer) {
184 impl_.RemoveObserver(observer);
185 }
186
187 const TestSource& impl() const { return impl_; }
188
189 private:
190 TestSource impl_;
191};
192
193using TestScopedMultiSourceObservationWithNonDefaultNames =
194 ScopedMultiSourceObservation<TestSourceWithNonDefaultNames,
Andrew Rayskiy3cf073392022-11-11 00:31:49195 TestSourceObserver>;
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:17196
197} // namespace
198
Andrew Rayskiy3cf073392022-11-11 00:31:49199template <>
200struct ScopedObservationTraits<TestSourceWithNonDefaultNames,
201 TestSourceObserver> {
202 static void AddObserver(TestSourceWithNonDefaultNames* source,
203 TestSourceObserver* observer) {
204 source->AddFoo(observer);
205 }
206 static void RemoveObserver(TestSourceWithNonDefaultNames* source,
207 TestSourceObserver* observer) {
208 source->RemoveFoo(observer);
209 }
210};
211
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:17212TEST_F(ScopedMultiSourceObservationTest, NonDefaultNames) {
213 TestSourceWithNonDefaultNames nds1;
214
215 EXPECT_EQ(0u, nds1.impl().num_observers());
216 {
217 TestScopedMultiSourceObservationWithNonDefaultNames obs(o1());
218 obs.AddObservation(&nds1);
219 EXPECT_EQ(1u, nds1.impl().num_observers());
220 EXPECT_TRUE(nds1.impl().HasObserver(o1()));
221 }
222
223 EXPECT_EQ(0u, nds1.impl().num_observers());
224}
225
226} // namespace base