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.
5 #include "base/scoped_multi_source_observation.h"
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"
16 class TestSourceObserver {};
20 void AddObserver(TestSourceObserver* observer);
21 void RemoveObserver(TestSourceObserver* observer);
23 bool HasObserver(TestSourceObserver* observer) const;
24 size_t num_observers() const { return observers_.size(); }
27 std::vector<TestSourceObserver*> observers_;
30 void TestSource::AddObserver(TestSourceObserver* observer) {
31 observers_.push_back(observer);
34 void TestSource::RemoveObserver(TestSourceObserver* observer) {
35 auto it = base::ranges::find(observers_, observer);
36 ASSERT_TRUE(it != observers_.end());
40 bool TestSource::HasObserver(TestSourceObserver* observer) const {
41 return base::Contains(observers_, observer);
44 using TestScopedMultiSourceObservation =
45 ScopedMultiSourceObservation<TestSource, TestSourceObserver>;
47 class ScopedMultiSourceObservationTest : public testing::Test {
49 TestSource* s1() { return &s1_; }
50 TestSource* s2() { return &s2_; }
51 TestSourceObserver* o1() { return &o1_; }
56 TestSourceObserver o1_;
61 TEST_F(ScopedMultiSourceObservationTest, RemovesSourcesOnDestruction) {
63 TestScopedMultiSourceObservation obs(o1());
64 EXPECT_EQ(0u, s1()->num_observers());
65 EXPECT_FALSE(s1()->HasObserver(o1()));
67 obs.AddObservation(s1());
68 EXPECT_EQ(1u, s1()->num_observers());
69 EXPECT_TRUE(s1()->HasObserver(o1()));
71 obs.AddObservation(s2());
72 EXPECT_EQ(1u, s2()->num_observers());
73 EXPECT_TRUE(s2()->HasObserver(o1()));
76 // Test that all observations are removed when it goes out of scope.
77 EXPECT_EQ(0u, s1()->num_observers());
78 EXPECT_EQ(0u, s2()->num_observers());
81 TEST_F(ScopedMultiSourceObservationTest, RemoveObservation) {
82 TestScopedMultiSourceObservation obs(o1());
83 EXPECT_EQ(0u, s1()->num_observers());
84 EXPECT_FALSE(s1()->HasObserver(o1()));
85 EXPECT_EQ(0u, s2()->num_observers());
86 EXPECT_FALSE(s2()->HasObserver(o1()));
88 obs.AddObservation(s1());
89 EXPECT_EQ(1u, s1()->num_observers());
90 EXPECT_TRUE(s1()->HasObserver(o1()));
92 obs.AddObservation(s2());
93 EXPECT_EQ(1u, s2()->num_observers());
94 EXPECT_TRUE(s2()->HasObserver(o1()));
96 obs.RemoveObservation(s1());
97 EXPECT_EQ(0u, s1()->num_observers());
98 EXPECT_FALSE(s1()->HasObserver(o1()));
99 EXPECT_EQ(1u, s2()->num_observers());
100 EXPECT_TRUE(s2()->HasObserver(o1()));
102 obs.RemoveObservation(s2());
103 EXPECT_EQ(0u, s1()->num_observers());
104 EXPECT_FALSE(s1()->HasObserver(o1()));
105 EXPECT_EQ(0u, s2()->num_observers());
106 EXPECT_FALSE(s2()->HasObserver(o1()));
109 TEST_F(ScopedMultiSourceObservationTest, RemoveAllObservations) {
110 TestScopedMultiSourceObservation obs(o1());
111 EXPECT_EQ(0u, s1()->num_observers());
112 EXPECT_FALSE(s1()->HasObserver(o1()));
113 EXPECT_EQ(0u, s2()->num_observers());
114 EXPECT_FALSE(s2()->HasObserver(o1()));
116 obs.AddObservation(s1());
117 obs.AddObservation(s2());
118 EXPECT_EQ(1u, s1()->num_observers());
119 EXPECT_TRUE(s1()->HasObserver(o1()));
120 EXPECT_EQ(1u, s2()->num_observers());
121 EXPECT_TRUE(s2()->HasObserver(o1()));
123 obs.RemoveAllObservations();
124 EXPECT_EQ(0u, s1()->num_observers());
125 EXPECT_FALSE(s1()->HasObserver(o1()));
126 EXPECT_EQ(0u, s2()->num_observers());
127 EXPECT_FALSE(s2()->HasObserver(o1()));
130 TEST_F(ScopedMultiSourceObservationTest, IsObservingSource) {
131 TestScopedMultiSourceObservation obs(o1());
132 EXPECT_FALSE(obs.IsObservingSource(s1()));
133 EXPECT_FALSE(obs.IsObservingSource(s2()));
135 obs.AddObservation(s1());
136 EXPECT_TRUE(obs.IsObservingSource(s1()));
137 EXPECT_FALSE(obs.IsObservingSource(s2()));
139 obs.AddObservation(s2());
140 EXPECT_TRUE(obs.IsObservingSource(s1()));
141 EXPECT_TRUE(obs.IsObservingSource(s2()));
143 obs.RemoveObservation(s1());
144 EXPECT_FALSE(obs.IsObservingSource(s1()));
145 EXPECT_TRUE(obs.IsObservingSource(s2()));
148 TEST_F(ScopedMultiSourceObservationTest, IsObservingAnySource) {
149 TestScopedMultiSourceObservation obs(o1());
150 EXPECT_FALSE(obs.IsObservingAnySource());
152 obs.AddObservation(s1());
153 EXPECT_TRUE(obs.IsObservingAnySource());
155 obs.AddObservation(s2());
156 EXPECT_TRUE(obs.IsObservingAnySource());
158 obs.RemoveAllObservations();
159 EXPECT_FALSE(obs.IsObservingAnySource());
162 TEST_F(ScopedMultiSourceObservationTest, GetSourcesCount) {
163 TestScopedMultiSourceObservation obs(o1());
164 EXPECT_EQ(0u, obs.GetSourcesCount());
166 obs.AddObservation(s1());
167 EXPECT_EQ(1u, obs.GetSourcesCount());
169 obs.AddObservation(s2());
170 EXPECT_EQ(2u, obs.GetSourcesCount());
172 obs.RemoveAllObservations();
173 EXPECT_EQ(0u, obs.GetSourcesCount());
178 // A test source with oddly named Add/Remove functions.
179 class TestSourceWithNonDefaultNames {
181 void AddFoo(TestSourceObserver* observer) { impl_.AddObserver(observer); }
182 void RemoveFoo(TestSourceObserver* observer) {
183 impl_.RemoveObserver(observer);
186 const TestSource& impl() const { return impl_; }
192 using TestScopedMultiSourceObservationWithNonDefaultNames =
193 ScopedMultiSourceObservation<TestSourceWithNonDefaultNames,
199 struct ScopedObservationTraits<TestSourceWithNonDefaultNames,
200 TestSourceObserver> {
201 static void AddObserver(TestSourceWithNonDefaultNames* source,
202 TestSourceObserver* observer) {
203 source->AddFoo(observer);
205 static void RemoveObserver(TestSourceWithNonDefaultNames* source,
206 TestSourceObserver* observer) {
207 source->RemoveFoo(observer);
211 TEST_F(ScopedMultiSourceObservationTest, NonDefaultNames) {
212 TestSourceWithNonDefaultNames nds1;
214 EXPECT_EQ(0u, nds1.impl().num_observers());
216 TestScopedMultiSourceObservationWithNonDefaultNames obs(o1());
217 obs.AddObservation(&nds1);
218 EXPECT_EQ(1u, nds1.impl().num_observers());
219 EXPECT_TRUE(nds1.impl().HasObserver(o1()));
222 EXPECT_EQ(0u, nds1.impl().num_observers());