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