blob: 881e4c94a454d93053f8baa41279dc072091165d [file] [log] [blame]
Sigurdur Asgeirsson046f5c72020-11-04 16:48:431// 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_observation.h"
6
Jan Wilken Dörrieb5a41c32020-12-09 18:55:477#include "base/containers/contains.h"
Sigurdur Asgeirsson046f5c72020-11-04 16:48:438#include "base/ranges/algorithm.h"
Sigurdur Asgeirsson046f5c72020-11-04 16:48:439#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 EXPECT_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 TestScopedObservation = ScopedObservation<TestSource, TestSourceObserver>;
44
45} // namespace
46
47TEST(ScopedObservationTest, RemovesObservationOnDestruction) {
48 TestSource s1;
49
50 {
51 TestSourceObserver o1;
52 TestScopedObservation obs(&o1);
53 EXPECT_EQ(0u, s1.num_observers());
54 EXPECT_FALSE(s1.HasObserver(&o1));
55
56 obs.Observe(&s1);
57 EXPECT_EQ(1u, s1.num_observers());
58 EXPECT_TRUE(s1.HasObserver(&o1));
59 }
60
61 // Test that the observation is removed when it goes out of scope.
62 EXPECT_EQ(0u, s1.num_observers());
63}
64
Sigurdur Asgeirssonc7a6ac22020-11-23 17:59:1965TEST(ScopedObservationTest, Reset) {
66 TestSource s1;
67 TestSourceObserver o1;
68 TestScopedObservation obs(&o1);
69 EXPECT_EQ(0u, s1.num_observers());
70 obs.Reset();
71
72 obs.Observe(&s1);
73 EXPECT_EQ(1u, s1.num_observers());
74 EXPECT_TRUE(s1.HasObserver(&o1));
75
76 obs.Reset();
77 EXPECT_EQ(0u, s1.num_observers());
78
79 // Safe to call with no observation.
80 obs.Reset();
81 EXPECT_EQ(0u, s1.num_observers());
82}
83
Sigurdur Asgeirsson046f5c72020-11-04 16:48:4384TEST(ScopedObservationTest, IsObserving) {
85 TestSource s1;
86 TestSourceObserver o1;
87 TestScopedObservation obs(&o1);
88 EXPECT_FALSE(obs.IsObserving());
89
90 obs.Observe(&s1);
91 EXPECT_TRUE(obs.IsObserving());
92
Sigurdur Asgeirsson518e2082020-12-09 13:00:2793 obs.Reset();
Sigurdur Asgeirsson046f5c72020-11-04 16:48:4394 EXPECT_FALSE(obs.IsObserving());
95}
96
97TEST(ScopedObservationTest, IsObservingSource) {
98 TestSource s1;
99 TestSource s2;
100 TestSourceObserver o1;
101 TestScopedObservation obs(&o1);
102 EXPECT_FALSE(obs.IsObservingSource(&s1));
103 EXPECT_FALSE(obs.IsObservingSource(&s2));
104
105 obs.Observe(&s1);
106 EXPECT_TRUE(obs.IsObservingSource(&s1));
107 EXPECT_FALSE(obs.IsObservingSource(&s2));
108
Sigurdur Asgeirsson518e2082020-12-09 13:00:27109 obs.Reset();
Sigurdur Asgeirsson046f5c72020-11-04 16:48:43110 EXPECT_FALSE(obs.IsObservingSource(&s1));
111 EXPECT_FALSE(obs.IsObservingSource(&s2));
112}
113
114namespace {
115
116// A test source with oddly named Add/Remove functions.
117class TestSourceWithNonDefaultNames {
118 public:
119 void AddFoo(TestSourceObserver* observer) { impl_.AddObserver(observer); }
120 void RemoveFoo(TestSourceObserver* observer) {
121 impl_.RemoveObserver(observer);
122 }
123
124 const TestSource& impl() const { return impl_; }
125
126 private:
127 TestSource impl_;
128};
129
130using TestScopedObservationWithNonDefaultNames =
131 ScopedObservation<TestSourceWithNonDefaultNames,
132 TestSourceObserver,
133 &TestSourceWithNonDefaultNames::AddFoo,
134 &TestSourceWithNonDefaultNames::RemoveFoo>;
135
136} // namespace
137
138TEST(ScopedObservationTest, NonDefaultNames) {
139 TestSourceWithNonDefaultNames s1;
140 TestSourceObserver o1;
141
142 EXPECT_EQ(0u, s1.impl().num_observers());
143 {
144 TestScopedObservationWithNonDefaultNames obs(&o1);
145 obs.Observe(&s1);
146 EXPECT_EQ(1u, s1.impl().num_observers());
147 EXPECT_TRUE(s1.impl().HasObserver(&o1));
148 }
149}
150
151} // namespace base