blob: 90d03a580ced76e30d6cf7ef35f5c9a4230cfa75 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
5#include "base/observer_list.h"
[email protected]3c0d45e2010-09-17 19:33:066
David Bienvenu5f4d4f02020-09-27 16:55:037#include <memory>
8
Hans Wennborged2126e2022-08-02 14:44:589#include "base/memory/raw_ptr.h"
Trent Apted4d207362018-08-15 23:48:1510#include "base/strings/string_piece.h"
Wez0c9c93c2018-04-26 16:23:2411#include "base/test/gtest_util.h"
Oskar Sundbomc92fda62018-10-24 11:38:0212#include "base/threading/simple_thread.h"
Fabrice de Gans-Riberi62c715552018-06-18 19:36:3513#include "build/build_config.h"
Mitsuru Oshima538b1db2018-02-28 04:05:2314#include "testing/gmock/include/gmock/gmock.h"
initial.commitd7cae122008-07-26 21:49:3815#include "testing/gtest/include/gtest/gtest.h"
Anton Bikineev7dd58ad2021-05-18 01:01:3916#include "third_party/abseil-cpp/absl/types/optional.h"
initial.commitd7cae122008-07-26 21:49:3817
[email protected]7ff48ca2013-02-06 16:56:1918namespace base {
initial.commitd7cae122008-07-26 21:49:3819namespace {
20
Trent Apted30f97fd2018-08-21 09:03:4721class CheckedBase : public CheckedObserver {
initial.commitd7cae122008-07-26 21:49:3822 public:
23 virtual void Observe(int x) = 0;
Trent Apted30f97fd2018-08-21 09:03:4724 ~CheckedBase() override = default;
loyso29025b62016-10-11 06:51:3325 virtual int GetValue() const { return 0; }
initial.commitd7cae122008-07-26 21:49:3826};
27
Trent Apted30f97fd2018-08-21 09:03:4728class UncheckedBase {
initial.commitd7cae122008-07-26 21:49:3829 public:
Trent Apted30f97fd2018-08-21 09:03:4730 virtual void Observe(int x) = 0;
31 virtual ~UncheckedBase() = default;
32 virtual int GetValue() const { return 0; }
33};
34
Victor Costanebc52732019-02-15 02:39:4735// Helper for TYPED_TEST_SUITE machinery to pick the ObserverList under test.
Trent Apted30f97fd2018-08-21 09:03:4736// Keyed off the observer type since ObserverList has too many template args and
37// it gets ugly.
38template <class Foo>
39struct PickObserverList {};
40template <>
41struct PickObserverList<CheckedBase> {
42 template <class TypeParam,
43 bool check_empty = false,
44 bool allow_reentrancy = true>
45 using ObserverListType =
46 ObserverList<TypeParam, check_empty, allow_reentrancy>;
47};
48template <>
49struct PickObserverList<UncheckedBase> {
50 template <class TypeParam,
51 bool check_empty = false,
52 bool allow_reentrancy = true>
53 using ObserverListType = typename ObserverList<TypeParam,
54 check_empty,
55 allow_reentrancy>::Unchecked;
56};
57
58template <class Foo>
59class AdderT : public Foo {
60 public:
61 explicit AdderT(int scaler) : total(0), scaler_(scaler) {}
62 ~AdderT() override = default;
loyso29025b62016-10-11 06:51:3363
64 void Observe(int x) override { total += x * scaler_; }
65 int GetValue() const override { return total; }
66
initial.commitd7cae122008-07-26 21:49:3867 int total;
[email protected]44106182012-04-06 03:53:0268
initial.commitd7cae122008-07-26 21:49:3869 private:
70 int scaler_;
71};
72
Trent Apted30f97fd2018-08-21 09:03:4773template <class ObserverListType,
74 class Foo = typename ObserverListType::value_type>
75class DisrupterT : public Foo {
initial.commitd7cae122008-07-26 21:49:3876 public:
Trent Apted30f97fd2018-08-21 09:03:4777 DisrupterT(ObserverListType* list, Foo* doomed, bool remove_self)
loyso29025b62016-10-11 06:51:3378 : list_(list), doomed_(doomed), remove_self_(remove_self) {}
Trent Apted30f97fd2018-08-21 09:03:4779 DisrupterT(ObserverListType* list, Foo* doomed)
80 : DisrupterT(list, doomed, false) {}
81 DisrupterT(ObserverListType* list, bool remove_self)
82 : DisrupterT(list, nullptr, remove_self) {}
loyso29025b62016-10-11 06:51:3383
Trent Apted30f97fd2018-08-21 09:03:4784 ~DisrupterT() override = default;
loyso29025b62016-10-11 06:51:3385
86 void Observe(int x) override {
87 if (remove_self_)
88 list_->RemoveObserver(this);
89 if (doomed_)
Keishi Hattori0e45c022021-11-27 09:25:5290 list_->RemoveObserver(doomed_.get());
loyso29025b62016-10-11 06:51:3391 }
92
93 void SetDoomed(Foo* doomed) { doomed_ = doomed; }
[email protected]44106182012-04-06 03:53:0294
initial.commitd7cae122008-07-26 21:49:3895 private:
Keishi Hattori0e45c022021-11-27 09:25:5296 raw_ptr<ObserverListType> list_;
97 raw_ptr<Foo> doomed_;
loyso29025b62016-10-11 06:51:3398 bool remove_self_;
initial.commitd7cae122008-07-26 21:49:3899};
100
Trent Apted30f97fd2018-08-21 09:03:47101template <class ObserverListType,
102 class Foo = typename ObserverListType::value_type>
[email protected]b3e2fad02008-10-31 03:32:06103class AddInObserve : public Foo {
104 public:
Trent Apted30f97fd2018-08-21 09:03:47105 explicit AddInObserve(ObserverListType* observer_list)
loyso29025b62016-10-11 06:51:33106 : observer_list(observer_list), to_add_() {}
107
108 void SetToAdd(Foo* to_add) { to_add_ = to_add; }
[email protected]44106182012-04-06 03:53:02109
nickc0b001062015-04-22 23:17:20110 void Observe(int x) override {
loyso29025b62016-10-11 06:51:33111 if (to_add_) {
Keishi Hattori0e45c022021-11-27 09:25:52112 observer_list->AddObserver(to_add_.get());
loyso29025b62016-10-11 06:51:33113 to_add_ = nullptr;
[email protected]b3e2fad02008-10-31 03:32:06114 }
115 }
116
Keishi Hattori0e45c022021-11-27 09:25:52117 raw_ptr<ObserverListType> observer_list;
118 raw_ptr<Foo> to_add_;
[email protected]b3e2fad02008-10-31 03:32:06119};
120
Oskar Sundbomc92fda62018-10-24 11:38:02121template <class ObserverListType>
122class ObserverListCreator : public DelegateSimpleThread::Delegate {
123 public:
124 std::unique_ptr<ObserverListType> Create(
Anton Bikineev7dd58ad2021-05-18 01:01:39125 absl::optional<base::ObserverListPolicy> policy = absl::nullopt) {
Oskar Sundbomc92fda62018-10-24 11:38:02126 policy_ = policy;
127 DelegateSimpleThread thread(this, "ListCreator");
128 thread.Start();
129 thread.Join();
130 return std::move(observer_list_);
131 }
132
133 private:
134 void Run() override {
135 if (policy_) {
136 observer_list_ = std::make_unique<ObserverListType>(*policy_);
137 } else {
138 observer_list_ = std::make_unique<ObserverListType>();
139 }
140 }
141
142 std::unique_ptr<ObserverListType> observer_list_;
Anton Bikineev7dd58ad2021-05-18 01:01:39143 absl::optional<base::ObserverListPolicy> policy_;
Oskar Sundbomc92fda62018-10-24 11:38:02144};
145
loyso29025b62016-10-11 06:51:33146} // namespace
147
Trent Apted30f97fd2018-08-21 09:03:47148class ObserverListTestBase {
149 public:
David Bienvenu5f4d4f02020-09-27 16:55:03150 ObserverListTestBase() = default;
151 ObserverListTestBase(const ObserverListTestBase&) = delete;
152 ObserverListTestBase& operator=(const ObserverListTestBase&) = delete;
Trent Apted30f97fd2018-08-21 09:03:47153
154 template <class T>
Trent Aptedf59cdf0d32018-10-04 03:42:22155 const decltype(T::list_.get()) list(const T& iter) {
156 return iter.list_.get();
Trent Apted30f97fd2018-08-21 09:03:47157 }
158
159 template <class T>
160 typename T::value_type* GetCurrent(T* iter) {
161 return iter->GetCurrent();
162 }
163
164 // Override GetCurrent() for CheckedObserver. When StdIteratorRemoveFront
165 // tries to simulate a sequence to see if it "would" crash, CheckedObservers
166 // do, actually, crash with a DCHECK(). Note this check is different to the
167 // check during an observer _iteration_. Hence, DCHECK(), not CHECK().
168 CheckedBase* GetCurrent(ObserverList<CheckedBase>::iterator* iter) {
169 EXPECT_DCHECK_DEATH(return iter->GetCurrent());
170 return nullptr;
171 }
Trent Apted30f97fd2018-08-21 09:03:47172};
173
174// Templatized test fixture that can pick between CheckedBase and UncheckedBase.
175template <class ObserverType>
176class ObserverListTest : public ObserverListTestBase, public ::testing::Test {
177 public:
178 template <class T>
179 using ObserverList =
180 typename PickObserverList<ObserverType>::template ObserverListType<T>;
181
182 using iterator = typename ObserverList<ObserverType>::iterator;
183 using const_iterator = typename ObserverList<ObserverType>::const_iterator;
184
David Bienvenu5f4d4f02020-09-27 16:55:03185 ObserverListTest() = default;
186 ObserverListTest(const ObserverListTest&) = delete;
187 ObserverListTest& operator=(const ObserverListTest&) = delete;
Trent Apted30f97fd2018-08-21 09:03:47188};
189
190using ObserverTypes = ::testing::Types<CheckedBase, UncheckedBase>;
Victor Costanebc52732019-02-15 02:39:47191TYPED_TEST_SUITE(ObserverListTest, ObserverTypes);
Trent Apted30f97fd2018-08-21 09:03:47192
193// TYPED_TEST causes the test parent class to be a template parameter, which
194// makes the syntax for referring to the types awkward. Create aliases in local
195// scope with clearer names. Unfortunately, we also need some trailing cruft to
196// avoid "unused local type alias" warnings.
197#define DECLARE_TYPES \
198 using Foo = TypeParam; \
199 using ObserverListFoo = \
200 typename PickObserverList<TypeParam>::template ObserverListType<Foo>; \
201 using Adder = AdderT<Foo>; \
202 using Disrupter = DisrupterT<ObserverListFoo>; \
203 using const_iterator = typename TestFixture::const_iterator; \
204 using iterator = typename TestFixture::iterator; \
David Bienvenu5f4d4f02020-09-27 16:55:03205 (void)reinterpret_cast<Disrupter*>(0); \
206 (void)reinterpret_cast<Adder*>(0); \
207 (void)reinterpret_cast<const_iterator*>(0); \
208 (void)reinterpret_cast<iterator*>(0)
Trent Apted30f97fd2018-08-21 09:03:47209
210TYPED_TEST(ObserverListTest, BasicTest) {
211 DECLARE_TYPES;
212 ObserverListFoo observer_list;
213 const ObserverListFoo& const_observer_list = observer_list;
François Degros0659d69332017-11-15 09:31:44214
215 {
Trent Apted30f97fd2018-08-21 09:03:47216 const const_iterator it1 = const_observer_list.begin();
François Degros0659d69332017-11-15 09:31:44217 EXPECT_EQ(it1, const_observer_list.end());
218 // Iterator copy.
Trent Apted30f97fd2018-08-21 09:03:47219 const const_iterator it2 = it1;
François Degros0659d69332017-11-15 09:31:44220 EXPECT_EQ(it2, it1);
221 // Iterator assignment.
Trent Apted30f97fd2018-08-21 09:03:47222 const_iterator it3;
François Degros0659d69332017-11-15 09:31:44223 it3 = it2;
224 EXPECT_EQ(it3, it1);
225 EXPECT_EQ(it3, it2);
226 // Self assignment.
Hans Wennborg792903f2018-04-09 11:20:06227 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
François Degros0659d69332017-11-15 09:31:44228 EXPECT_EQ(it3, it1);
229 EXPECT_EQ(it3, it2);
230 }
231
232 {
Trent Apted30f97fd2018-08-21 09:03:47233 const iterator it1 = observer_list.begin();
François Degros0659d69332017-11-15 09:31:44234 EXPECT_EQ(it1, observer_list.end());
235 // Iterator copy.
Trent Apted30f97fd2018-08-21 09:03:47236 const iterator it2 = it1;
François Degros0659d69332017-11-15 09:31:44237 EXPECT_EQ(it2, it1);
238 // Iterator assignment.
Trent Apted30f97fd2018-08-21 09:03:47239 iterator it3;
François Degros0659d69332017-11-15 09:31:44240 it3 = it2;
241 EXPECT_EQ(it3, it1);
242 EXPECT_EQ(it3, it2);
243 // Self assignment.
Hans Wennborg792903f2018-04-09 11:20:06244 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
François Degros0659d69332017-11-15 09:31:44245 EXPECT_EQ(it3, it1);
246 EXPECT_EQ(it3, it2);
247 }
248
[email protected]631739f2011-06-05 07:07:12249 Adder a(1), b(-1), c(1), d(-1), e(-1);
[email protected]503631c2008-10-22 23:09:21250 Disrupter evil(&observer_list, &c);
initial.commitd7cae122008-07-26 21:49:38251
252 observer_list.AddObserver(&a);
253 observer_list.AddObserver(&b);
254
François Degros0659d69332017-11-15 09:31:44255 EXPECT_TRUE(const_observer_list.HasObserver(&a));
256 EXPECT_FALSE(const_observer_list.HasObserver(&c));
257
258 {
Trent Apted30f97fd2018-08-21 09:03:47259 const const_iterator it1 = const_observer_list.begin();
François Degros0659d69332017-11-15 09:31:44260 EXPECT_NE(it1, const_observer_list.end());
261 // Iterator copy.
Trent Apted30f97fd2018-08-21 09:03:47262 const const_iterator it2 = it1;
François Degros0659d69332017-11-15 09:31:44263 EXPECT_EQ(it2, it1);
264 EXPECT_NE(it2, const_observer_list.end());
265 // Iterator assignment.
Trent Apted30f97fd2018-08-21 09:03:47266 const_iterator it3;
François Degros0659d69332017-11-15 09:31:44267 it3 = it2;
268 EXPECT_EQ(it3, it1);
269 EXPECT_EQ(it3, it2);
270 // Self assignment.
Hans Wennborg792903f2018-04-09 11:20:06271 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
François Degros0659d69332017-11-15 09:31:44272 EXPECT_EQ(it3, it1);
273 EXPECT_EQ(it3, it2);
jdoerrie977dc3f2017-12-12 09:23:34274 // Iterator post increment.
Trent Apted30f97fd2018-08-21 09:03:47275 const_iterator it4 = it3++;
jdoerrie977dc3f2017-12-12 09:23:34276 EXPECT_EQ(it4, it1);
277 EXPECT_EQ(it4, it2);
278 EXPECT_NE(it4, it3);
François Degros0659d69332017-11-15 09:31:44279 }
280
281 {
Trent Apted30f97fd2018-08-21 09:03:47282 const iterator it1 = observer_list.begin();
François Degros0659d69332017-11-15 09:31:44283 EXPECT_NE(it1, observer_list.end());
284 // Iterator copy.
Trent Apted30f97fd2018-08-21 09:03:47285 const iterator it2 = it1;
François Degros0659d69332017-11-15 09:31:44286 EXPECT_EQ(it2, it1);
287 EXPECT_NE(it2, observer_list.end());
288 // Iterator assignment.
Trent Apted30f97fd2018-08-21 09:03:47289 iterator it3;
François Degros0659d69332017-11-15 09:31:44290 it3 = it2;
291 EXPECT_EQ(it3, it1);
292 EXPECT_EQ(it3, it2);
293 // Self assignment.
Hans Wennborg792903f2018-04-09 11:20:06294 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
François Degros0659d69332017-11-15 09:31:44295 EXPECT_EQ(it3, it1);
296 EXPECT_EQ(it3, it2);
jdoerrie977dc3f2017-12-12 09:23:34297 // Iterator post increment.
Trent Apted30f97fd2018-08-21 09:03:47298 iterator it4 = it3++;
jdoerrie977dc3f2017-12-12 09:23:34299 EXPECT_EQ(it4, it1);
300 EXPECT_EQ(it4, it2);
301 EXPECT_NE(it4, it3);
François Degros0659d69332017-11-15 09:31:44302 }
mgiuca64ccf2362014-11-10 06:44:23303
ericwilligersa60549cd2016-10-16 00:09:05304 for (auto& observer : observer_list)
305 observer.Observe(10);
initial.commitd7cae122008-07-26 21:49:38306
307 observer_list.AddObserver(&evil);
308 observer_list.AddObserver(&c);
309 observer_list.AddObserver(&d);
310
[email protected]631739f2011-06-05 07:07:12311 // Removing an observer not in the list should do nothing.
312 observer_list.RemoveObserver(&e);
313
ericwilligersa60549cd2016-10-16 00:09:05314 for (auto& observer : observer_list)
315 observer.Observe(10);
initial.commitd7cae122008-07-26 21:49:38316
[email protected]14cf9102012-08-23 09:59:19317 EXPECT_EQ(20, a.total);
318 EXPECT_EQ(-20, b.total);
319 EXPECT_EQ(0, c.total);
320 EXPECT_EQ(-10, d.total);
321 EXPECT_EQ(0, e.total);
initial.commitd7cae122008-07-26 21:49:38322}
license.botbf09a502008-08-24 00:55:55323
Oskar Sundbomc92fda62018-10-24 11:38:02324TYPED_TEST(ObserverListTest, CreatedAndUsedOnDifferentThreads) {
325 DECLARE_TYPES;
326
327 ObserverListCreator<ObserverListFoo> list_creator;
328 Adder a(1);
329 // Check with default constructor
330 {
331 std::unique_ptr<ObserverListFoo> observer_list = list_creator.Create();
332 observer_list->AddObserver(&a);
333 for (auto& observer : *observer_list) {
334 observer.Observe(1);
335 }
336 EXPECT_EQ(1, a.GetValue());
337 }
338
339 // Check with constructor taking explicit policy
340 {
341 std::unique_ptr<ObserverListFoo> observer_list =
342 list_creator.Create(base::ObserverListPolicy::EXISTING_ONLY);
343 observer_list->AddObserver(&a);
344 for (auto& observer : *observer_list) {
345 observer.Observe(1);
346 }
347 EXPECT_EQ(2, a.GetValue());
348 }
349}
350
Trent Apted30f97fd2018-08-21 09:03:47351TYPED_TEST(ObserverListTest, CompactsWhenNoActiveIterator) {
352 DECLARE_TYPES;
353 using ObserverListConstFoo =
354 typename TestFixture::template ObserverList<const Foo>;
355
356 ObserverListConstFoo ol;
357 const ObserverListConstFoo& col = ol;
François Degros0659d69332017-11-15 09:31:44358
359 const Adder a(1);
360 const Adder b(2);
361 const Adder c(3);
362
363 ol.AddObserver(&a);
364 ol.AddObserver(&b);
365
366 EXPECT_TRUE(col.HasObserver(&a));
367 EXPECT_FALSE(col.HasObserver(&c));
368
Mitsuru Oshimade680cf2021-01-13 19:22:18369 EXPECT_TRUE(!col.empty());
François Degros0659d69332017-11-15 09:31:44370
Trent Apted30f97fd2018-08-21 09:03:47371 using It = typename ObserverListConstFoo::const_iterator;
François Degros0659d69332017-11-15 09:31:44372
373 {
374 It it = col.begin();
375 EXPECT_NE(it, col.end());
376 It ita = it;
377 EXPECT_EQ(ita, it);
378 EXPECT_NE(++it, col.end());
379 EXPECT_NE(ita, it);
380 It itb = it;
381 EXPECT_EQ(itb, it);
382 EXPECT_EQ(++it, col.end());
383
Mitsuru Oshimade680cf2021-01-13 19:22:18384 EXPECT_TRUE(!col.empty());
François Degros0659d69332017-11-15 09:31:44385 EXPECT_EQ(&*ita, &a);
386 EXPECT_EQ(&*itb, &b);
387
388 ol.RemoveObserver(&a);
Mitsuru Oshimade680cf2021-01-13 19:22:18389 EXPECT_TRUE(!col.empty());
François Degros0659d69332017-11-15 09:31:44390 EXPECT_FALSE(col.HasObserver(&a));
391 EXPECT_EQ(&*itb, &b);
392
393 ol.RemoveObserver(&b);
Mitsuru Oshimade680cf2021-01-13 19:22:18394 EXPECT_FALSE(!col.empty());
François Degros0659d69332017-11-15 09:31:44395 EXPECT_FALSE(col.HasObserver(&a));
396 EXPECT_FALSE(col.HasObserver(&b));
397
398 it = It();
399 ita = It();
Mitsuru Oshimade680cf2021-01-13 19:22:18400 EXPECT_FALSE(!col.empty());
François Degros0659d69332017-11-15 09:31:44401 ita = itb;
402 itb = It();
Mitsuru Oshimade680cf2021-01-13 19:22:18403 EXPECT_FALSE(!col.empty());
François Degros0659d69332017-11-15 09:31:44404 ita = It();
Mitsuru Oshimade680cf2021-01-13 19:22:18405 EXPECT_FALSE(!col.empty());
François Degros0659d69332017-11-15 09:31:44406 }
407
408 ol.AddObserver(&a);
409 ol.AddObserver(&b);
Mitsuru Oshimade680cf2021-01-13 19:22:18410 EXPECT_TRUE(!col.empty());
François Degros0659d69332017-11-15 09:31:44411 ol.Clear();
Mitsuru Oshimade680cf2021-01-13 19:22:18412 EXPECT_FALSE(!col.empty());
François Degros0659d69332017-11-15 09:31:44413
414 ol.AddObserver(&a);
415 ol.AddObserver(&b);
Mitsuru Oshimade680cf2021-01-13 19:22:18416 EXPECT_TRUE(!col.empty());
François Degros0659d69332017-11-15 09:31:44417 {
418 const It it = col.begin();
419 ol.Clear();
Mitsuru Oshimade680cf2021-01-13 19:22:18420 EXPECT_FALSE(!col.empty());
François Degros0659d69332017-11-15 09:31:44421 }
Mitsuru Oshimade680cf2021-01-13 19:22:18422 EXPECT_FALSE(!col.empty());
François Degros0659d69332017-11-15 09:31:44423}
424
Trent Apted30f97fd2018-08-21 09:03:47425TYPED_TEST(ObserverListTest, DisruptSelf) {
426 DECLARE_TYPES;
427 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33428 Adder a(1), b(-1), c(1), d(-1);
429 Disrupter evil(&observer_list, true);
430
431 observer_list.AddObserver(&a);
432 observer_list.AddObserver(&b);
433
ericwilligersa60549cd2016-10-16 00:09:05434 for (auto& observer : observer_list)
435 observer.Observe(10);
loyso29025b62016-10-11 06:51:33436
437 observer_list.AddObserver(&evil);
438 observer_list.AddObserver(&c);
439 observer_list.AddObserver(&d);
440
ericwilligersa60549cd2016-10-16 00:09:05441 for (auto& observer : observer_list)
442 observer.Observe(10);
loyso29025b62016-10-11 06:51:33443
444 EXPECT_EQ(20, a.total);
445 EXPECT_EQ(-20, b.total);
446 EXPECT_EQ(10, c.total);
447 EXPECT_EQ(-10, d.total);
448}
449
Trent Apted30f97fd2018-08-21 09:03:47450TYPED_TEST(ObserverListTest, DisruptBefore) {
451 DECLARE_TYPES;
452 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33453 Adder a(1), b(-1), c(1), d(-1);
454 Disrupter evil(&observer_list, &b);
455
456 observer_list.AddObserver(&a);
457 observer_list.AddObserver(&b);
458 observer_list.AddObserver(&evil);
459 observer_list.AddObserver(&c);
460 observer_list.AddObserver(&d);
461
ericwilligersa60549cd2016-10-16 00:09:05462 for (auto& observer : observer_list)
463 observer.Observe(10);
464 for (auto& observer : observer_list)
465 observer.Observe(10);
loyso29025b62016-10-11 06:51:33466
467 EXPECT_EQ(20, a.total);
468 EXPECT_EQ(-10, b.total);
469 EXPECT_EQ(20, c.total);
470 EXPECT_EQ(-20, d.total);
471}
472
Trent Apted30f97fd2018-08-21 09:03:47473TYPED_TEST(ObserverListTest, Existing) {
474 DECLARE_TYPES;
475 ObserverListFoo observer_list(ObserverListPolicy::EXISTING_ONLY);
[email protected]b3e2fad02008-10-31 03:32:06476 Adder a(1);
Trent Apted30f97fd2018-08-21 09:03:47477 AddInObserve<ObserverListFoo> b(&observer_list);
loyso29025b62016-10-11 06:51:33478 Adder c(1);
479 b.SetToAdd(&c);
[email protected]b3e2fad02008-10-31 03:32:06480
481 observer_list.AddObserver(&a);
482 observer_list.AddObserver(&b);
483
ericwilligersa60549cd2016-10-16 00:09:05484 for (auto& observer : observer_list)
485 observer.Observe(1);
[email protected]b3e2fad02008-10-31 03:32:06486
loyso29025b62016-10-11 06:51:33487 EXPECT_FALSE(b.to_add_);
[email protected]b3e2fad02008-10-31 03:32:06488 // B's adder should not have been notified because it was added during
[email protected]6be50d72014-05-08 23:49:40489 // notification.
loyso29025b62016-10-11 06:51:33490 EXPECT_EQ(0, c.total);
[email protected]b3e2fad02008-10-31 03:32:06491
492 // Notify again to make sure b's adder is notified.
ericwilligersa60549cd2016-10-16 00:09:05493 for (auto& observer : observer_list)
494 observer.Observe(1);
loyso29025b62016-10-11 06:51:33495 EXPECT_EQ(1, c.total);
[email protected]b3e2fad02008-10-31 03:32:06496}
[email protected]84aebed2010-02-25 03:09:41497
Trent Apted30f97fd2018-08-21 09:03:47498template <class ObserverListType,
499 class Foo = typename ObserverListType::value_type>
[email protected]84aebed2010-02-25 03:09:41500class AddInClearObserve : public Foo {
501 public:
Trent Apted30f97fd2018-08-21 09:03:47502 explicit AddInClearObserve(ObserverListType* list)
[email protected]84aebed2010-02-25 03:09:41503 : list_(list), added_(false), adder_(1) {}
504
dcheng56488182014-10-21 10:54:51505 void Observe(int /* x */) override {
[email protected]84aebed2010-02-25 03:09:41506 list_->Clear();
507 list_->AddObserver(&adder_);
508 added_ = true;
509 }
510
511 bool added() const { return added_; }
Trent Apted30f97fd2018-08-21 09:03:47512 const AdderT<Foo>& adder() const { return adder_; }
[email protected]84aebed2010-02-25 03:09:41513
514 private:
Keishi Hattori0e45c022021-11-27 09:25:52515 const raw_ptr<ObserverListType> list_;
[email protected]84aebed2010-02-25 03:09:41516
517 bool added_;
Trent Apted30f97fd2018-08-21 09:03:47518 AdderT<Foo> adder_;
[email protected]84aebed2010-02-25 03:09:41519};
520
Trent Apted30f97fd2018-08-21 09:03:47521TYPED_TEST(ObserverListTest, ClearNotifyAll) {
522 DECLARE_TYPES;
523 ObserverListFoo observer_list;
524 AddInClearObserve<ObserverListFoo> a(&observer_list);
[email protected]84aebed2010-02-25 03:09:41525
526 observer_list.AddObserver(&a);
527
ericwilligersa60549cd2016-10-16 00:09:05528 for (auto& observer : observer_list)
529 observer.Observe(1);
[email protected]84aebed2010-02-25 03:09:41530 EXPECT_TRUE(a.added());
531 EXPECT_EQ(1, a.adder().total)
532 << "Adder should observe once and have sum of 1.";
533}
534
Trent Apted30f97fd2018-08-21 09:03:47535TYPED_TEST(ObserverListTest, ClearNotifyExistingOnly) {
536 DECLARE_TYPES;
537 ObserverListFoo observer_list(ObserverListPolicy::EXISTING_ONLY);
538 AddInClearObserve<ObserverListFoo> a(&observer_list);
[email protected]84aebed2010-02-25 03:09:41539
540 observer_list.AddObserver(&a);
541
ericwilligersa60549cd2016-10-16 00:09:05542 for (auto& observer : observer_list)
543 observer.Observe(1);
[email protected]84aebed2010-02-25 03:09:41544 EXPECT_TRUE(a.added());
545 EXPECT_EQ(0, a.adder().total)
546 << "Adder should not observe, so sum should still be 0.";
547}
548
Trent Apted30f97fd2018-08-21 09:03:47549template <class ObserverListType,
550 class Foo = typename ObserverListType::value_type>
[email protected]671b74d2011-06-09 03:41:18551class ListDestructor : public Foo {
552 public:
Trent Apted30f97fd2018-08-21 09:03:47553 explicit ListDestructor(ObserverListType* list) : list_(list) {}
Chris Watkinsbb7211c2017-11-29 07:16:38554 ~ListDestructor() override = default;
[email protected]44106182012-04-06 03:53:02555
dcheng56488182014-10-21 10:54:51556 void Observe(int x) override { delete list_; }
[email protected]2e58cbd2012-08-06 01:03:05557
[email protected]671b74d2011-06-09 03:41:18558 private:
Keishi Hattori0e45c022021-11-27 09:25:52559 raw_ptr<ObserverListType> list_;
[email protected]671b74d2011-06-09 03:41:18560};
561
Trent Apted30f97fd2018-08-21 09:03:47562TYPED_TEST(ObserverListTest, IteratorOutlivesList) {
563 DECLARE_TYPES;
564 ObserverListFoo* observer_list = new ObserverListFoo;
565 ListDestructor<ObserverListFoo> a(observer_list);
[email protected]671b74d2011-06-09 03:41:18566 observer_list->AddObserver(&a);
567
loyso802c2132016-10-26 07:13:06568 for (auto& observer : *observer_list)
569 observer.Observe(0);
Mostyn Bramley-Moored0ecd6a2017-12-06 19:13:21570
571 // There are no EXPECT* statements for this test, if we catch
572 // use-after-free errors for observer_list (eg with ASan) then
573 // this test has failed. See http://crbug.com/85296.
[email protected]671b74d2011-06-09 03:41:18574}
575
Trent Apted30f97fd2018-08-21 09:03:47576TYPED_TEST(ObserverListTest, BasicStdIterator) {
577 DECLARE_TYPES;
578 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33579
580 // An optimization: begin() and end() do not involve weak pointers on
581 // empty list.
Trent Apted30f97fd2018-08-21 09:03:47582 EXPECT_FALSE(this->list(observer_list.begin()));
583 EXPECT_FALSE(this->list(observer_list.end()));
loyso29025b62016-10-11 06:51:33584
585 // Iterate over empty list: no effect, no crash.
586 for (auto& i : observer_list)
587 i.Observe(10);
588
589 Adder a(1), b(-1), c(1), d(-1);
590
591 observer_list.AddObserver(&a);
592 observer_list.AddObserver(&b);
593 observer_list.AddObserver(&c);
594 observer_list.AddObserver(&d);
595
Trent Apted30f97fd2018-08-21 09:03:47596 for (iterator i = observer_list.begin(), e = observer_list.end(); i != e; ++i)
loyso29025b62016-10-11 06:51:33597 i->Observe(1);
598
599 EXPECT_EQ(1, a.total);
600 EXPECT_EQ(-1, b.total);
601 EXPECT_EQ(1, c.total);
602 EXPECT_EQ(-1, d.total);
603
604 // Check an iteration over a 'const view' for a given container.
Trent Apted30f97fd2018-08-21 09:03:47605 const ObserverListFoo& const_list = observer_list;
606 for (const_iterator i = const_list.begin(), e = const_list.end(); i != e;
607 ++i) {
loyso29025b62016-10-11 06:51:33608 EXPECT_EQ(1, std::abs(i->GetValue()));
609 }
610
611 for (const auto& o : const_list)
612 EXPECT_EQ(1, std::abs(o.GetValue()));
613}
614
Trent Apted30f97fd2018-08-21 09:03:47615TYPED_TEST(ObserverListTest, StdIteratorRemoveItself) {
616 DECLARE_TYPES;
617 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33618 Adder a(1), b(-1), c(1), d(-1);
619 Disrupter disrupter(&observer_list, true);
620
621 observer_list.AddObserver(&a);
622 observer_list.AddObserver(&b);
623 observer_list.AddObserver(&disrupter);
624 observer_list.AddObserver(&c);
625 observer_list.AddObserver(&d);
626
627 for (auto& o : observer_list)
628 o.Observe(1);
629
630 for (auto& o : observer_list)
631 o.Observe(10);
632
633 EXPECT_EQ(11, a.total);
634 EXPECT_EQ(-11, b.total);
635 EXPECT_EQ(11, c.total);
636 EXPECT_EQ(-11, d.total);
637}
638
Trent Apted30f97fd2018-08-21 09:03:47639TYPED_TEST(ObserverListTest, StdIteratorRemoveBefore) {
640 DECLARE_TYPES;
641 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33642 Adder a(1), b(-1), c(1), d(-1);
643 Disrupter disrupter(&observer_list, &b);
644
645 observer_list.AddObserver(&a);
646 observer_list.AddObserver(&b);
647 observer_list.AddObserver(&disrupter);
648 observer_list.AddObserver(&c);
649 observer_list.AddObserver(&d);
650
651 for (auto& o : observer_list)
652 o.Observe(1);
653
654 for (auto& o : observer_list)
655 o.Observe(10);
656
657 EXPECT_EQ(11, a.total);
658 EXPECT_EQ(-1, b.total);
659 EXPECT_EQ(11, c.total);
660 EXPECT_EQ(-11, d.total);
661}
662
Trent Apted30f97fd2018-08-21 09:03:47663TYPED_TEST(ObserverListTest, StdIteratorRemoveAfter) {
664 DECLARE_TYPES;
665 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33666 Adder a(1), b(-1), c(1), d(-1);
667 Disrupter disrupter(&observer_list, &c);
668
669 observer_list.AddObserver(&a);
670 observer_list.AddObserver(&b);
671 observer_list.AddObserver(&disrupter);
672 observer_list.AddObserver(&c);
673 observer_list.AddObserver(&d);
674
675 for (auto& o : observer_list)
676 o.Observe(1);
677
678 for (auto& o : observer_list)
679 o.Observe(10);
680
681 EXPECT_EQ(11, a.total);
682 EXPECT_EQ(-11, b.total);
683 EXPECT_EQ(0, c.total);
684 EXPECT_EQ(-11, d.total);
685}
686
Trent Apted30f97fd2018-08-21 09:03:47687TYPED_TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
688 DECLARE_TYPES;
689 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33690 Adder a(1), b(-1), c(1), d(-1);
691 Disrupter disrupter(&observer_list, &a);
692
693 observer_list.AddObserver(&a);
694 observer_list.AddObserver(&disrupter);
695 observer_list.AddObserver(&b);
696 observer_list.AddObserver(&c);
697 observer_list.AddObserver(&d);
698
699 for (auto& o : observer_list)
700 o.Observe(1);
701
702 for (auto& o : observer_list)
703 o.Observe(10);
704
705 EXPECT_EQ(1, a.total);
706 EXPECT_EQ(-11, b.total);
707 EXPECT_EQ(11, c.total);
708 EXPECT_EQ(-11, d.total);
709}
710
Trent Apted30f97fd2018-08-21 09:03:47711TYPED_TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
712 DECLARE_TYPES;
713 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33714 Adder a(1), b(-1), c(1), d(-1);
715 Disrupter disrupter(&observer_list, &d);
716
717 observer_list.AddObserver(&a);
718 observer_list.AddObserver(&b);
719 observer_list.AddObserver(&c);
720 observer_list.AddObserver(&disrupter);
721 observer_list.AddObserver(&d);
722
723 for (auto& o : observer_list)
724 o.Observe(1);
725
726 for (auto& o : observer_list)
727 o.Observe(10);
728
729 EXPECT_EQ(11, a.total);
730 EXPECT_EQ(-11, b.total);
731 EXPECT_EQ(11, c.total);
732 EXPECT_EQ(0, d.total);
733}
734
Trent Apted30f97fd2018-08-21 09:03:47735TYPED_TEST(ObserverListTest, StdIteratorRemoveFront) {
736 DECLARE_TYPES;
737 using iterator = typename TestFixture::iterator;
738 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33739 Adder a(1), b(-1), c(1), d(-1);
740 Disrupter disrupter(&observer_list, true);
741
742 observer_list.AddObserver(&disrupter);
743 observer_list.AddObserver(&a);
744 observer_list.AddObserver(&b);
745 observer_list.AddObserver(&c);
746 observer_list.AddObserver(&d);
747
748 bool test_disruptor = true;
Trent Apted30f97fd2018-08-21 09:03:47749 for (iterator i = observer_list.begin(), e = observer_list.end(); i != e;
750 ++i) {
loyso29025b62016-10-11 06:51:33751 i->Observe(1);
752 // Check that second call to i->Observe() would crash here.
753 if (test_disruptor) {
Trent Apted30f97fd2018-08-21 09:03:47754 EXPECT_FALSE(this->GetCurrent(&i));
loyso29025b62016-10-11 06:51:33755 test_disruptor = false;
756 }
757 }
758
759 for (auto& o : observer_list)
760 o.Observe(10);
761
762 EXPECT_EQ(11, a.total);
763 EXPECT_EQ(-11, b.total);
764 EXPECT_EQ(11, c.total);
765 EXPECT_EQ(-11, d.total);
766}
767
Trent Apted30f97fd2018-08-21 09:03:47768TYPED_TEST(ObserverListTest, StdIteratorRemoveBack) {
769 DECLARE_TYPES;
770 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33771 Adder a(1), b(-1), c(1), d(-1);
772 Disrupter disrupter(&observer_list, true);
773
774 observer_list.AddObserver(&a);
775 observer_list.AddObserver(&b);
776 observer_list.AddObserver(&c);
777 observer_list.AddObserver(&d);
778 observer_list.AddObserver(&disrupter);
779
780 for (auto& o : observer_list)
781 o.Observe(1);
782
783 for (auto& o : observer_list)
784 o.Observe(10);
785
786 EXPECT_EQ(11, a.total);
787 EXPECT_EQ(-11, b.total);
788 EXPECT_EQ(11, c.total);
789 EXPECT_EQ(-11, d.total);
790}
791
Trent Apted30f97fd2018-08-21 09:03:47792TYPED_TEST(ObserverListTest, NestedLoop) {
793 DECLARE_TYPES;
794 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33795 Adder a(1), b(-1), c(1), d(-1);
796 Disrupter disrupter(&observer_list, true);
797
798 observer_list.AddObserver(&disrupter);
799 observer_list.AddObserver(&a);
800 observer_list.AddObserver(&b);
801 observer_list.AddObserver(&c);
802 observer_list.AddObserver(&d);
803
Dave Tapuska0b98e5c2019-09-04 13:05:46804 for (auto& observer : observer_list) {
805 observer.Observe(10);
loyso29025b62016-10-11 06:51:33806
Dave Tapuska0b98e5c2019-09-04 13:05:46807 for (auto& nested_observer : observer_list)
808 nested_observer.Observe(1);
loyso29025b62016-10-11 06:51:33809 }
810
811 EXPECT_EQ(15, a.total);
812 EXPECT_EQ(-15, b.total);
813 EXPECT_EQ(15, c.total);
814 EXPECT_EQ(-15, d.total);
815}
816
Trent Apted30f97fd2018-08-21 09:03:47817TYPED_TEST(ObserverListTest, NonCompactList) {
818 DECLARE_TYPES;
819 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33820 Adder a(1), b(-1);
821
822 Disrupter disrupter1(&observer_list, true);
823 Disrupter disrupter2(&observer_list, true);
824
benwells2cbda2f2016-10-24 20:18:52825 // Disrupt itself and another one.
loyso29025b62016-10-11 06:51:33826 disrupter1.SetDoomed(&disrupter2);
827
828 observer_list.AddObserver(&disrupter1);
829 observer_list.AddObserver(&disrupter2);
830 observer_list.AddObserver(&a);
831 observer_list.AddObserver(&b);
832
Dave Tapuska0b98e5c2019-09-04 13:05:46833 for (auto& observer : observer_list) {
loyso29025b62016-10-11 06:51:33834 // Get the { nullptr, nullptr, &a, &b } non-compact list
835 // on the first inner pass.
Dave Tapuska0b98e5c2019-09-04 13:05:46836 observer.Observe(10);
loyso29025b62016-10-11 06:51:33837
Dave Tapuska0b98e5c2019-09-04 13:05:46838 for (auto& nested_observer : observer_list)
839 nested_observer.Observe(1);
loyso29025b62016-10-11 06:51:33840 }
841
842 EXPECT_EQ(13, a.total);
843 EXPECT_EQ(-13, b.total);
844}
845
Trent Apted30f97fd2018-08-21 09:03:47846TYPED_TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
847 DECLARE_TYPES;
848 ObserverListFoo observer_list;
loyso29025b62016-10-11 06:51:33849 Adder a(1), b(-1);
850
851 Disrupter disrupter1(&observer_list, true);
852 Disrupter disrupter2(&observer_list, true);
853
benwells2cbda2f2016-10-24 20:18:52854 // Disrupt itself and another one.
loyso29025b62016-10-11 06:51:33855 disrupter1.SetDoomed(&disrupter2);
856
857 observer_list.AddObserver(&disrupter1);
858 observer_list.AddObserver(&disrupter2);
859
860 bool add_observers = true;
Dave Tapuska0b98e5c2019-09-04 13:05:46861 for (auto& observer : observer_list) {
loyso29025b62016-10-11 06:51:33862 // Get the { nullptr, nullptr } empty list on the first inner pass.
Dave Tapuska0b98e5c2019-09-04 13:05:46863 observer.Observe(10);
loyso29025b62016-10-11 06:51:33864
Dave Tapuska0b98e5c2019-09-04 13:05:46865 for (auto& nested_observer : observer_list)
866 nested_observer.Observe(1);
loyso29025b62016-10-11 06:51:33867
868 if (add_observers) {
869 observer_list.AddObserver(&a);
870 observer_list.AddObserver(&b);
871 add_observers = false;
872 }
873 }
874
875 EXPECT_EQ(12, a.total);
876 EXPECT_EQ(-12, b.total);
877}
878
Trent Apted30f97fd2018-08-21 09:03:47879TYPED_TEST(ObserverListTest, AddObserverInTheLastObserve) {
880 DECLARE_TYPES;
881 ObserverListFoo observer_list;
882
883 AddInObserve<ObserverListFoo> a(&observer_list);
loyso29025b62016-10-11 06:51:33884 Adder b(-1);
885
886 a.SetToAdd(&b);
887 observer_list.AddObserver(&a);
888
dchengc9dd0142016-10-15 05:43:19889 auto it = observer_list.begin();
890 while (it != observer_list.end()) {
891 auto& observer = *it;
892 // Intentionally increment the iterator before calling Observe(). The
893 // ObserverList starts with only one observer, and it == observer_list.end()
894 // should be true after the next line.
895 ++it;
896 // However, the first Observe() call will add a second observer: at this
897 // point, it != observer_list.end() should be true, and Observe() should be
898 // called on the newly added observer on the next iteration of the loop.
899 observer.Observe(10);
900 }
loyso29025b62016-10-11 06:51:33901
902 EXPECT_EQ(-10, b.total);
903}
904
Mitsuru Oshima538b1db2018-02-28 04:05:23905class MockLogAssertHandler {
906 public:
907 MOCK_METHOD4(
908 HandleLogAssert,
909 void(const char*, int, const base::StringPiece, const base::StringPiece));
910};
911
912#if DCHECK_IS_ON()
Trent Apted30f97fd2018-08-21 09:03:47913TYPED_TEST(ObserverListTest, NonReentrantObserverList) {
914 DECLARE_TYPES;
915 using NonReentrantObserverListFoo = typename PickObserverList<
916 Foo>::template ObserverListType<Foo, /*check_empty=*/false,
917 /*allow_reentrancy=*/false>;
918 NonReentrantObserverListFoo non_reentrant_observer_list;
Mitsuru Oshima538b1db2018-02-28 04:05:23919 Adder a(1);
920 non_reentrant_observer_list.AddObserver(&a);
921
Wez0c9c93c2018-04-26 16:23:24922 EXPECT_DCHECK_DEATH({
Dave Tapuska0b98e5c2019-09-04 13:05:46923 for (const Foo& observer : non_reentrant_observer_list) {
924 for (const Foo& nested_observer : non_reentrant_observer_list) {
925 std::ignore = observer;
926 std::ignore = nested_observer;
Mitsuru Oshima538b1db2018-02-28 04:05:23927 }
928 }
Wez0c9c93c2018-04-26 16:23:24929 });
Mitsuru Oshima538b1db2018-02-28 04:05:23930}
931
Trent Apted30f97fd2018-08-21 09:03:47932TYPED_TEST(ObserverListTest, ReentrantObserverList) {
933 DECLARE_TYPES;
934 using ReentrantObserverListFoo = typename PickObserverList<
935 Foo>::template ObserverListType<Foo, /*check_empty=*/false,
936 /*allow_reentrancy=*/true>;
937 ReentrantObserverListFoo reentrant_observer_list;
Mitsuru Oshima538b1db2018-02-28 04:05:23938 Adder a(1);
939 reentrant_observer_list.AddObserver(&a);
940 bool passed = false;
Dave Tapuska0b98e5c2019-09-04 13:05:46941 for (const Foo& observer : reentrant_observer_list) {
942 for (const Foo& nested_observer : reentrant_observer_list) {
943 std::ignore = observer;
944 std::ignore = nested_observer;
Mitsuru Oshima538b1db2018-02-28 04:05:23945 passed = true;
946 }
947 }
948 EXPECT_TRUE(passed);
949}
950#endif
951
Trent Apted30f97fd2018-08-21 09:03:47952class TestCheckedObserver : public CheckedObserver {
953 public:
954 explicit TestCheckedObserver(int* count) : count_(count) {}
David Bienvenu5f4d4f02020-09-27 16:55:03955 TestCheckedObserver(const TestCheckedObserver&) = delete;
956 TestCheckedObserver& operator=(const TestCheckedObserver&) = delete;
Trent Apted30f97fd2018-08-21 09:03:47957
958 void Observe() { ++(*count_); }
959
960 private:
Keishi Hattori0e45c022021-11-27 09:25:52961 raw_ptr<int> count_;
Trent Apted30f97fd2018-08-21 09:03:47962};
963
964// A second, identical observer, used to test multiple inheritance.
965class TestCheckedObserver2 : public CheckedObserver {
966 public:
967 explicit TestCheckedObserver2(int* count) : count_(count) {}
David Bienvenu5f4d4f02020-09-27 16:55:03968 TestCheckedObserver2(const TestCheckedObserver2&) = delete;
969 TestCheckedObserver2& operator=(const TestCheckedObserver2&) = delete;
Trent Apted30f97fd2018-08-21 09:03:47970
971 void Observe() { ++(*count_); }
972
973 private:
Keishi Hattori0e45c022021-11-27 09:25:52974 raw_ptr<int> count_;
Trent Apted30f97fd2018-08-21 09:03:47975};
976
977using CheckedObserverListTest = ::testing::Test;
978
979// Test Observers that CHECK() when a UAF might otherwise occur.
980TEST_F(CheckedObserverListTest, CheckedObserver) {
981 // See comments below about why this is unique_ptr.
982 auto list = std::make_unique<ObserverList<TestCheckedObserver>>();
983 int count1 = 0;
984 int count2 = 0;
985 TestCheckedObserver l1(&count1);
986 list->AddObserver(&l1);
987 {
988 TestCheckedObserver l2(&count2);
989 list->AddObserver(&l2);
990 for (auto& observer : *list)
991 observer.Observe();
992 EXPECT_EQ(1, count1);
993 EXPECT_EQ(1, count2);
994 }
995 {
996 auto it = list->begin();
997 it->Observe();
998 // For CheckedObservers, a CHECK() occurs when advancing the iterator. (On
999 // calling the observer method would be too late since the pointer would
1000 // already be null by then).
1001 EXPECT_CHECK_DEATH(it++);
1002
1003 // On the non-death fork, no UAF occurs since the deleted observer is never
1004 // notified, but also the observer list still has |l2| in it. Check that.
1005 list->RemoveObserver(&l1);
Mitsuru Oshimade680cf2021-01-13 19:22:181006 EXPECT_TRUE(!list->empty());
Trent Apted30f97fd2018-08-21 09:03:471007
1008 // Now (in the non-death fork()) there's a problem. To delete |it|, we need
1009 // to compact the list, but that needs to iterate, which would CHECK again.
1010 // We can't remove |l2| (it's null). But we can delete |list|, which makes
1011 // the weak pointer in the iterator itself null.
1012 list.reset();
1013 }
1014 EXPECT_EQ(2, count1);
1015 EXPECT_EQ(1, count2);
1016}
1017
1018class MultiObserver : public TestCheckedObserver,
1019 public TestCheckedObserver2,
1020 public AdderT<UncheckedBase> {
1021 public:
1022 MultiObserver(int* checked_count, int* two_count)
1023 : TestCheckedObserver(checked_count),
1024 TestCheckedObserver2(two_count),
1025 AdderT(1) {}
1026};
1027
1028// Test that observers behave as expected when observing multiple interfaces
1029// with different traits.
1030TEST_F(CheckedObserverListTest, MultiObserver) {
1031 // Observe two checked observer lists. This is to ensure the WeakPtrFactory
1032 // in CheckedObserver can correctly service multiple ObserverLists.
1033 ObserverList<TestCheckedObserver> checked_list;
1034 ObserverList<TestCheckedObserver2> two_list;
1035
1036 ObserverList<UncheckedBase>::Unchecked unsafe_list;
1037
1038 int counts[2] = {};
1039
Dave Tapuska0b98e5c2019-09-04 13:05:461040 auto multi_observer = std::make_unique<MultiObserver>(&counts[0], &counts[1]);
1041 two_list.AddObserver(multi_observer.get());
1042 checked_list.AddObserver(multi_observer.get());
1043 unsafe_list.AddObserver(multi_observer.get());
Trent Apted30f97fd2018-08-21 09:03:471044
1045 auto iterate_over = [](auto* list) {
1046 for (auto& observer : *list)
1047 observer.Observe();
1048 };
1049 iterate_over(&two_list);
1050 iterate_over(&checked_list);
1051 for (auto& observer : unsafe_list)
1052 observer.Observe(10);
1053
Dave Tapuska0b98e5c2019-09-04 13:05:461054 EXPECT_EQ(10, multi_observer->GetValue());
Trent Apted30f97fd2018-08-21 09:03:471055 for (const auto& count : counts)
1056 EXPECT_EQ(1, count);
1057
Dave Tapuska0b98e5c2019-09-04 13:05:461058 unsafe_list.RemoveObserver(multi_observer.get()); // Avoid a use-after-free.
Trent Apted30f97fd2018-08-21 09:03:471059
Dave Tapuska0b98e5c2019-09-04 13:05:461060 multi_observer.reset();
Trent Apted30f97fd2018-08-21 09:03:471061 EXPECT_CHECK_DEATH(iterate_over(&checked_list));
1062
1063 for (const auto& count : counts)
1064 EXPECT_EQ(1, count);
1065}
1066
[email protected]7ff48ca2013-02-06 16:56:191067} // namespace base