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