1 // Copyright (c) 2012 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/observer_list.h"
6
7 #include <vector>
8
9 #include <gtest/gtest.h>
10
11 #include "base/compiler_specific.h"
12 #include "base/location.h"
13 #include "base/memory/weak_ptr.h"
14
15 namespace base {
16 namespace {
17
18 class Foo {
19 public:
20 virtual void Observe(int x) = 0;
~Foo()21 virtual ~Foo() {}
22 };
23
24 class Adder : public Foo {
25 public:
Adder(int scaler)26 explicit Adder(int scaler) : total(0), scaler_(scaler) {}
Observe(int x)27 void Observe(int x) override { total += x * scaler_; }
~Adder()28 ~Adder() override {}
29 int total;
30
31 private:
32 int scaler_;
33 };
34
35 class Disrupter : public Foo {
36 public:
Disrupter(ObserverList<Foo> * list,Foo * doomed)37 Disrupter(ObserverList<Foo>* list, Foo* doomed)
38 : list_(list),
39 doomed_(doomed) {
40 }
~Disrupter()41 ~Disrupter() override {}
Observe(int x)42 void Observe(int x) override { list_->RemoveObserver(doomed_); }
43
44 private:
45 ObserverList<Foo>* list_;
46 Foo* doomed_;
47 };
48
49 template <typename ObserverListType>
50 class AddInObserve : public Foo {
51 public:
AddInObserve(ObserverListType * observer_list)52 explicit AddInObserve(ObserverListType* observer_list)
53 : added(false),
54 observer_list(observer_list),
55 adder(1) {
56 }
57
Observe(int x)58 void Observe(int x) override {
59 if (!added) {
60 added = true;
61 observer_list->AddObserver(&adder);
62 }
63 }
64
65 bool added;
66 ObserverListType* observer_list;
67 Adder adder;
68 };
69
70
TEST(ObserverListTest,BasicTest)71 TEST(ObserverListTest, BasicTest) {
72 ObserverList<Foo> observer_list;
73 Adder a(1), b(-1), c(1), d(-1), e(-1);
74 Disrupter evil(&observer_list, &c);
75
76 observer_list.AddObserver(&a);
77 observer_list.AddObserver(&b);
78
79 EXPECT_TRUE(observer_list.HasObserver(&a));
80 EXPECT_FALSE(observer_list.HasObserver(&c));
81
82 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
83
84 observer_list.AddObserver(&evil);
85 observer_list.AddObserver(&c);
86 observer_list.AddObserver(&d);
87
88 // Removing an observer not in the list should do nothing.
89 observer_list.RemoveObserver(&e);
90
91 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
92
93 EXPECT_EQ(20, a.total);
94 EXPECT_EQ(-20, b.total);
95 EXPECT_EQ(0, c.total);
96 EXPECT_EQ(-10, d.total);
97 EXPECT_EQ(0, e.total);
98 }
99
TEST(ObserverListTest,Existing)100 TEST(ObserverListTest, Existing) {
101 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY);
102 Adder a(1);
103 AddInObserve<ObserverList<Foo> > b(&observer_list);
104
105 observer_list.AddObserver(&a);
106 observer_list.AddObserver(&b);
107
108 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
109
110 EXPECT_TRUE(b.added);
111 // B's adder should not have been notified because it was added during
112 // notification.
113 EXPECT_EQ(0, b.adder.total);
114
115 // Notify again to make sure b's adder is notified.
116 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
117 EXPECT_EQ(1, b.adder.total);
118 }
119
120 class AddInClearObserve : public Foo {
121 public:
AddInClearObserve(ObserverList<Foo> * list)122 explicit AddInClearObserve(ObserverList<Foo>* list)
123 : list_(list), added_(false), adder_(1) {}
124
Observe(int)125 void Observe(int /* x */) override {
126 list_->Clear();
127 list_->AddObserver(&adder_);
128 added_ = true;
129 }
130
added() const131 bool added() const { return added_; }
adder() const132 const Adder& adder() const { return adder_; }
133
134 private:
135 ObserverList<Foo>* const list_;
136
137 bool added_;
138 Adder adder_;
139 };
140
TEST(ObserverListTest,ClearNotifyAll)141 TEST(ObserverListTest, ClearNotifyAll) {
142 ObserverList<Foo> observer_list;
143 AddInClearObserve a(&observer_list);
144
145 observer_list.AddObserver(&a);
146
147 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
148 EXPECT_TRUE(a.added());
149 EXPECT_EQ(1, a.adder().total)
150 << "Adder should observe once and have sum of 1.";
151 }
152
TEST(ObserverListTest,ClearNotifyExistingOnly)153 TEST(ObserverListTest, ClearNotifyExistingOnly) {
154 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY);
155 AddInClearObserve a(&observer_list);
156
157 observer_list.AddObserver(&a);
158
159 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
160 EXPECT_TRUE(a.added());
161 EXPECT_EQ(0, a.adder().total)
162 << "Adder should not observe, so sum should still be 0.";
163 }
164
165 class ListDestructor : public Foo {
166 public:
ListDestructor(ObserverList<Foo> * list)167 explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {}
~ListDestructor()168 ~ListDestructor() override {}
169
Observe(int x)170 void Observe(int x) override { delete list_; }
171
172 private:
173 ObserverList<Foo>* list_;
174 };
175
176
TEST(ObserverListTest,IteratorOutlivesList)177 TEST(ObserverListTest, IteratorOutlivesList) {
178 ObserverList<Foo>* observer_list = new ObserverList<Foo>;
179 ListDestructor a(observer_list);
180 observer_list->AddObserver(&a);
181
182 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0));
183 // If this test fails, there'll be Valgrind errors when this function goes out
184 // of scope.
185 }
186
187 } // namespace
188 } // namespace base
189