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; 21 virtual ~Foo() {} 22 }; 23 24 class Adder : public Foo { 25 public: 26 explicit Adder(int scaler) : total(0), scaler_(scaler) {} 27 void Observe(int x) override { total += x * scaler_; } 28 ~Adder() override {} 29 int total; 30 31 private: 32 int scaler_; 33 }; 34 35 class Disrupter : public Foo { 36 public: 37 Disrupter(ObserverList<Foo>* list, Foo* doomed) 38 : list_(list), 39 doomed_(doomed) { 40 } 41 ~Disrupter() override {} 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: 52 explicit AddInObserve(ObserverListType* observer_list) 53 : added(false), 54 observer_list(observer_list), 55 adder(1) { 56 } 57 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 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 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: 122 explicit AddInClearObserve(ObserverList<Foo>* list) 123 : list_(list), added_(false), adder_(1) {} 124 125 void Observe(int /* x */) override { 126 list_->Clear(); 127 list_->AddObserver(&adder_); 128 added_ = true; 129 } 130 131 bool added() const { return added_; } 132 const Adder& adder() const { return adder_; } 133 134 private: 135 ObserverList<Foo>* const list_; 136 137 bool added_; 138 Adder adder_; 139 }; 140 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 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: 167 explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {} 168 ~ListDestructor() override {} 169 170 void Observe(int x) override { delete list_; } 171 172 private: 173 ObserverList<Foo>* list_; 174 }; 175 176 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