1 // Copyright 2012 The Chromium Authors
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 <memory>
8 #include <optional>
9
10 #include "base/memory/raw_ptr.h"
11 #include "base/strings/string_piece.h"
12 #include "base/test/gtest_util.h"
13 #include "base/threading/simple_thread.h"
14 #include "build/build_config.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19 namespace {
20
21 class CheckedBase : public CheckedObserver {
22 public:
23 virtual void Observe(int x) = 0;
24 ~CheckedBase() override = default;
GetValue() const25 virtual int GetValue() const { return 0; }
26 };
27
28 class UncheckedBase {
29 public:
30 virtual void Observe(int x) = 0;
31 virtual ~UncheckedBase() = default;
GetValue() const32 virtual int GetValue() const { return 0; }
33 };
34
35 // Helper for TYPED_TEST_SUITE machinery to pick the ObserverList under test.
36 // Keyed off the observer type since ObserverList has too many template args and
37 // it gets ugly.
38 template <class Foo>
39 struct PickObserverList {};
40 template <>
41 struct 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 };
48 template <>
49 struct 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
58 template <class Foo>
59 class AdderT : public Foo {
60 public:
AdderT(int scaler)61 explicit AdderT(int scaler) : total(0), scaler_(scaler) {}
62 ~AdderT() override = default;
63
Observe(int x)64 void Observe(int x) override { total += x * scaler_; }
GetValue() const65 int GetValue() const override { return total; }
66
67 int total;
68
69 private:
70 int scaler_;
71 };
72
73 template <class ObserverListType,
74 class Foo = typename ObserverListType::value_type>
75 class DisrupterT : public Foo {
76 public:
DisrupterT(ObserverListType * list,Foo * doomed,bool remove_self)77 DisrupterT(ObserverListType* list, Foo* doomed, bool remove_self)
78 : list_(list), doomed_(doomed), remove_self_(remove_self) {}
DisrupterT(ObserverListType * list,Foo * doomed)79 DisrupterT(ObserverListType* list, Foo* doomed)
80 : DisrupterT(list, doomed, false) {}
DisrupterT(ObserverListType * list,bool remove_self)81 DisrupterT(ObserverListType* list, bool remove_self)
82 : DisrupterT(list, nullptr, remove_self) {}
83
84 ~DisrupterT() override = default;
85
Observe(int x)86 void Observe(int x) override {
87 if (remove_self_)
88 list_->RemoveObserver(this);
89 if (doomed_)
90 list_->RemoveObserver(doomed_.get());
91 }
92
SetDoomed(Foo * doomed)93 void SetDoomed(Foo* doomed) { doomed_ = doomed; }
94
95 private:
96 raw_ptr<ObserverListType> list_;
97 raw_ptr<Foo> doomed_;
98 bool remove_self_;
99 };
100
101 template <class ObserverListType,
102 class Foo = typename ObserverListType::value_type>
103 class AddInObserve : public Foo {
104 public:
AddInObserve(ObserverListType * observer_list)105 explicit AddInObserve(ObserverListType* observer_list)
106 : observer_list(observer_list), to_add_() {}
107
SetToAdd(Foo * to_add)108 void SetToAdd(Foo* to_add) { to_add_ = to_add; }
109
Observe(int x)110 void Observe(int x) override {
111 if (to_add_) {
112 observer_list->AddObserver(to_add_.get());
113 to_add_ = nullptr;
114 }
115 }
116
117 raw_ptr<ObserverListType> observer_list;
118 raw_ptr<Foo> to_add_;
119 };
120
121 template <class ObserverListType>
122 class ObserverListCreator : public DelegateSimpleThread::Delegate {
123 public:
Create(std::optional<base::ObserverListPolicy> policy=std::nullopt)124 std::unique_ptr<ObserverListType> Create(
125 std::optional<base::ObserverListPolicy> policy = std::nullopt) {
126 policy_ = policy;
127 DelegateSimpleThread thread(this, "ListCreator");
128 thread.Start();
129 thread.Join();
130 return std::move(observer_list_);
131 }
132
133 private:
Run()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_;
143 std::optional<base::ObserverListPolicy> policy_;
144 };
145
146 } // namespace
147
148 class ObserverListTestBase {
149 public:
150 ObserverListTestBase() = default;
151 ObserverListTestBase(const ObserverListTestBase&) = delete;
152 ObserverListTestBase& operator=(const ObserverListTestBase&) = delete;
153
154 template <class T>
list(const T & iter)155 const decltype(T::list_.get()) list(const T& iter) {
156 return iter.list_.get();
157 }
158
159 template <class T>
GetCurrent(T * iter)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().
GetCurrent(ObserverList<CheckedBase>::iterator * iter)168 CheckedBase* GetCurrent(ObserverList<CheckedBase>::iterator* iter) {
169 EXPECT_DCHECK_DEATH(return iter->GetCurrent());
170 return nullptr;
171 }
172 };
173
174 // Templatized test fixture that can pick between CheckedBase and UncheckedBase.
175 template <class ObserverType>
176 class 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
185 ObserverListTest() = default;
186 ObserverListTest(const ObserverListTest&) = delete;
187 ObserverListTest& operator=(const ObserverListTest&) = delete;
188 };
189
190 using ObserverTypes = ::testing::Types<CheckedBase, UncheckedBase>;
191 TYPED_TEST_SUITE(ObserverListTest, ObserverTypes);
192
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; \
205 (void)reinterpret_cast<Disrupter*>(0); \
206 (void)reinterpret_cast<Adder*>(0); \
207 (void)reinterpret_cast<const_iterator*>(0); \
208 (void)reinterpret_cast<iterator*>(0)
209
TYPED_TEST(ObserverListTest,BasicTest)210 TYPED_TEST(ObserverListTest, BasicTest) {
211 DECLARE_TYPES;
212 ObserverListFoo observer_list;
213 const ObserverListFoo& const_observer_list = observer_list;
214
215 {
216 const const_iterator it1 = const_observer_list.begin();
217 EXPECT_EQ(it1, const_observer_list.end());
218 // Iterator copy.
219 const const_iterator it2 = it1;
220 EXPECT_EQ(it2, it1);
221 // Iterator assignment.
222 const_iterator it3;
223 it3 = it2;
224 EXPECT_EQ(it3, it1);
225 EXPECT_EQ(it3, it2);
226 // Self assignment.
227 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
228 EXPECT_EQ(it3, it1);
229 EXPECT_EQ(it3, it2);
230 }
231
232 {
233 const iterator it1 = observer_list.begin();
234 EXPECT_EQ(it1, observer_list.end());
235 // Iterator copy.
236 const iterator it2 = it1;
237 EXPECT_EQ(it2, it1);
238 // Iterator assignment.
239 iterator it3;
240 it3 = it2;
241 EXPECT_EQ(it3, it1);
242 EXPECT_EQ(it3, it2);
243 // Self assignment.
244 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
245 EXPECT_EQ(it3, it1);
246 EXPECT_EQ(it3, it2);
247 }
248
249 Adder a(1), b(-1), c(1), d(-1), e(-1);
250 Disrupter evil(&observer_list, &c);
251
252 observer_list.AddObserver(&a);
253 observer_list.AddObserver(&b);
254
255 EXPECT_TRUE(const_observer_list.HasObserver(&a));
256 EXPECT_FALSE(const_observer_list.HasObserver(&c));
257
258 {
259 const const_iterator it1 = const_observer_list.begin();
260 EXPECT_NE(it1, const_observer_list.end());
261 // Iterator copy.
262 const const_iterator it2 = it1;
263 EXPECT_EQ(it2, it1);
264 EXPECT_NE(it2, const_observer_list.end());
265 // Iterator assignment.
266 const_iterator it3;
267 it3 = it2;
268 EXPECT_EQ(it3, it1);
269 EXPECT_EQ(it3, it2);
270 // Self assignment.
271 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
272 EXPECT_EQ(it3, it1);
273 EXPECT_EQ(it3, it2);
274 // Iterator post increment.
275 const_iterator it4 = it3++;
276 EXPECT_EQ(it4, it1);
277 EXPECT_EQ(it4, it2);
278 EXPECT_NE(it4, it3);
279 }
280
281 {
282 const iterator it1 = observer_list.begin();
283 EXPECT_NE(it1, observer_list.end());
284 // Iterator copy.
285 const iterator it2 = it1;
286 EXPECT_EQ(it2, it1);
287 EXPECT_NE(it2, observer_list.end());
288 // Iterator assignment.
289 iterator it3;
290 it3 = it2;
291 EXPECT_EQ(it3, it1);
292 EXPECT_EQ(it3, it2);
293 // Self assignment.
294 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
295 EXPECT_EQ(it3, it1);
296 EXPECT_EQ(it3, it2);
297 // Iterator post increment.
298 iterator it4 = it3++;
299 EXPECT_EQ(it4, it1);
300 EXPECT_EQ(it4, it2);
301 EXPECT_NE(it4, it3);
302 }
303
304 for (auto& observer : observer_list)
305 observer.Observe(10);
306
307 observer_list.AddObserver(&evil);
308 observer_list.AddObserver(&c);
309 observer_list.AddObserver(&d);
310
311 // Removing an observer not in the list should do nothing.
312 observer_list.RemoveObserver(&e);
313
314 for (auto& observer : observer_list)
315 observer.Observe(10);
316
317 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);
322 }
323
TYPED_TEST(ObserverListTest,CreatedAndUsedOnDifferentThreads)324 TYPED_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
TYPED_TEST(ObserverListTest,CompactsWhenNoActiveIterator)351 TYPED_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;
358
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
369 EXPECT_TRUE(!col.empty());
370
371 using It = typename ObserverListConstFoo::const_iterator;
372
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
384 EXPECT_TRUE(!col.empty());
385 EXPECT_EQ(&*ita, &a);
386 EXPECT_EQ(&*itb, &b);
387
388 ol.RemoveObserver(&a);
389 EXPECT_TRUE(!col.empty());
390 EXPECT_FALSE(col.HasObserver(&a));
391 EXPECT_EQ(&*itb, &b);
392
393 ol.RemoveObserver(&b);
394 EXPECT_FALSE(!col.empty());
395 EXPECT_FALSE(col.HasObserver(&a));
396 EXPECT_FALSE(col.HasObserver(&b));
397
398 it = It();
399 ita = It();
400 EXPECT_FALSE(!col.empty());
401 ita = itb;
402 itb = It();
403 EXPECT_FALSE(!col.empty());
404 ita = It();
405 EXPECT_FALSE(!col.empty());
406 }
407
408 ol.AddObserver(&a);
409 ol.AddObserver(&b);
410 EXPECT_TRUE(!col.empty());
411 ol.Clear();
412 EXPECT_FALSE(!col.empty());
413
414 ol.AddObserver(&a);
415 ol.AddObserver(&b);
416 EXPECT_TRUE(!col.empty());
417 {
418 const It it = col.begin();
419 ol.Clear();
420 EXPECT_FALSE(!col.empty());
421 }
422 EXPECT_FALSE(!col.empty());
423 }
424
TYPED_TEST(ObserverListTest,DisruptSelf)425 TYPED_TEST(ObserverListTest, DisruptSelf) {
426 DECLARE_TYPES;
427 ObserverListFoo observer_list;
428 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
434 for (auto& observer : observer_list)
435 observer.Observe(10);
436
437 observer_list.AddObserver(&evil);
438 observer_list.AddObserver(&c);
439 observer_list.AddObserver(&d);
440
441 for (auto& observer : observer_list)
442 observer.Observe(10);
443
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
TYPED_TEST(ObserverListTest,DisruptBefore)450 TYPED_TEST(ObserverListTest, DisruptBefore) {
451 DECLARE_TYPES;
452 ObserverListFoo observer_list;
453 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
462 for (auto& observer : observer_list)
463 observer.Observe(10);
464 for (auto& observer : observer_list)
465 observer.Observe(10);
466
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
TYPED_TEST(ObserverListTest,Existing)473 TYPED_TEST(ObserverListTest, Existing) {
474 DECLARE_TYPES;
475 ObserverListFoo observer_list(ObserverListPolicy::EXISTING_ONLY);
476 Adder a(1);
477 AddInObserve<ObserverListFoo> b(&observer_list);
478 Adder c(1);
479 b.SetToAdd(&c);
480
481 observer_list.AddObserver(&a);
482 observer_list.AddObserver(&b);
483
484 for (auto& observer : observer_list)
485 observer.Observe(1);
486
487 EXPECT_FALSE(b.to_add_);
488 // B's adder should not have been notified because it was added during
489 // notification.
490 EXPECT_EQ(0, c.total);
491
492 // Notify again to make sure b's adder is notified.
493 for (auto& observer : observer_list)
494 observer.Observe(1);
495 EXPECT_EQ(1, c.total);
496 }
497
498 template <class ObserverListType,
499 class Foo = typename ObserverListType::value_type>
500 class AddInClearObserve : public Foo {
501 public:
AddInClearObserve(ObserverListType * list)502 explicit AddInClearObserve(ObserverListType* list)
503 : list_(list), added_(false), adder_(1) {}
504
Observe(int)505 void Observe(int /* x */) override {
506 list_->Clear();
507 list_->AddObserver(&adder_);
508 added_ = true;
509 }
510
added() const511 bool added() const { return added_; }
adder() const512 const AdderT<Foo>& adder() const { return adder_; }
513
514 private:
515 const raw_ptr<ObserverListType> list_;
516
517 bool added_;
518 AdderT<Foo> adder_;
519 };
520
TYPED_TEST(ObserverListTest,ClearNotifyAll)521 TYPED_TEST(ObserverListTest, ClearNotifyAll) {
522 DECLARE_TYPES;
523 ObserverListFoo observer_list;
524 AddInClearObserve<ObserverListFoo> a(&observer_list);
525
526 observer_list.AddObserver(&a);
527
528 for (auto& observer : observer_list)
529 observer.Observe(1);
530 EXPECT_TRUE(a.added());
531 EXPECT_EQ(1, a.adder().total)
532 << "Adder should observe once and have sum of 1.";
533 }
534
TYPED_TEST(ObserverListTest,ClearNotifyExistingOnly)535 TYPED_TEST(ObserverListTest, ClearNotifyExistingOnly) {
536 DECLARE_TYPES;
537 ObserverListFoo observer_list(ObserverListPolicy::EXISTING_ONLY);
538 AddInClearObserve<ObserverListFoo> a(&observer_list);
539
540 observer_list.AddObserver(&a);
541
542 for (auto& observer : observer_list)
543 observer.Observe(1);
544 EXPECT_TRUE(a.added());
545 EXPECT_EQ(0, a.adder().total)
546 << "Adder should not observe, so sum should still be 0.";
547 }
548
549 template <class ObserverListType,
550 class Foo = typename ObserverListType::value_type>
551 class ListDestructor : public Foo {
552 public:
ListDestructor(ObserverListType * list)553 explicit ListDestructor(ObserverListType* list) : list_(list) {}
554 ~ListDestructor() override = default;
555
Observe(int x)556 void Observe(int x) override { delete list_.ExtractAsDangling(); }
557
558 private:
559 raw_ptr<ObserverListType> list_;
560 };
561
TYPED_TEST(ObserverListTest,IteratorOutlivesList)562 TYPED_TEST(ObserverListTest, IteratorOutlivesList) {
563 DECLARE_TYPES;
564 ObserverListFoo* observer_list = new ObserverListFoo;
565 ListDestructor<ObserverListFoo> a(observer_list);
566 observer_list->AddObserver(&a);
567
568 for (auto& observer : *observer_list)
569 observer.Observe(0);
570
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.
574 }
575
TYPED_TEST(ObserverListTest,BasicStdIterator)576 TYPED_TEST(ObserverListTest, BasicStdIterator) {
577 DECLARE_TYPES;
578 ObserverListFoo observer_list;
579
580 // An optimization: begin() and end() do not involve weak pointers on
581 // empty list.
582 EXPECT_FALSE(this->list(observer_list.begin()));
583 EXPECT_FALSE(this->list(observer_list.end()));
584
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
596 for (iterator i = observer_list.begin(), e = observer_list.end(); i != e; ++i)
597 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.
605 const ObserverListFoo& const_list = observer_list;
606 for (const_iterator i = const_list.begin(), e = const_list.end(); i != e;
607 ++i) {
608 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
TYPED_TEST(ObserverListTest,StdIteratorRemoveItself)615 TYPED_TEST(ObserverListTest, StdIteratorRemoveItself) {
616 DECLARE_TYPES;
617 ObserverListFoo observer_list;
618 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
TYPED_TEST(ObserverListTest,StdIteratorRemoveBefore)639 TYPED_TEST(ObserverListTest, StdIteratorRemoveBefore) {
640 DECLARE_TYPES;
641 ObserverListFoo observer_list;
642 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
TYPED_TEST(ObserverListTest,StdIteratorRemoveAfter)663 TYPED_TEST(ObserverListTest, StdIteratorRemoveAfter) {
664 DECLARE_TYPES;
665 ObserverListFoo observer_list;
666 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
TYPED_TEST(ObserverListTest,StdIteratorRemoveAfterFront)687 TYPED_TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
688 DECLARE_TYPES;
689 ObserverListFoo observer_list;
690 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
TYPED_TEST(ObserverListTest,StdIteratorRemoveBeforeBack)711 TYPED_TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
712 DECLARE_TYPES;
713 ObserverListFoo observer_list;
714 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
TYPED_TEST(ObserverListTest,StdIteratorRemoveFront)735 TYPED_TEST(ObserverListTest, StdIteratorRemoveFront) {
736 DECLARE_TYPES;
737 using iterator = typename TestFixture::iterator;
738 ObserverListFoo observer_list;
739 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;
749 for (iterator i = observer_list.begin(), e = observer_list.end(); i != e;
750 ++i) {
751 i->Observe(1);
752 // Check that second call to i->Observe() would crash here.
753 if (test_disruptor) {
754 EXPECT_FALSE(this->GetCurrent(&i));
755 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
TYPED_TEST(ObserverListTest,StdIteratorRemoveBack)768 TYPED_TEST(ObserverListTest, StdIteratorRemoveBack) {
769 DECLARE_TYPES;
770 ObserverListFoo observer_list;
771 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
TYPED_TEST(ObserverListTest,NestedLoop)792 TYPED_TEST(ObserverListTest, NestedLoop) {
793 DECLARE_TYPES;
794 ObserverListFoo observer_list;
795 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
804 for (auto& observer : observer_list) {
805 observer.Observe(10);
806
807 for (auto& nested_observer : observer_list)
808 nested_observer.Observe(1);
809 }
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
TYPED_TEST(ObserverListTest,NonCompactList)817 TYPED_TEST(ObserverListTest, NonCompactList) {
818 DECLARE_TYPES;
819 ObserverListFoo observer_list;
820 Adder a(1), b(-1);
821
822 Disrupter disrupter2(&observer_list, true); // Must outlive `disrupter1`.
823 Disrupter disrupter1(&observer_list, true);
824
825 // Disrupt itself and another one.
826 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
833 for (auto& observer : observer_list) {
834 // Get the { nullptr, nullptr, &a, &b } non-compact list
835 // on the first inner pass.
836 observer.Observe(10);
837
838 for (auto& nested_observer : observer_list)
839 nested_observer.Observe(1);
840 }
841
842 EXPECT_EQ(13, a.total);
843 EXPECT_EQ(-13, b.total);
844 }
845
TYPED_TEST(ObserverListTest,BecomesEmptyThanNonEmpty)846 TYPED_TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
847 DECLARE_TYPES;
848 ObserverListFoo observer_list;
849 Adder a(1), b(-1);
850
851 Disrupter disrupter2(&observer_list, true); // Must outlive `disrupter1`.
852 Disrupter disrupter1(&observer_list, true);
853
854 // Disrupt itself and another one.
855 disrupter1.SetDoomed(&disrupter2);
856
857 observer_list.AddObserver(&disrupter1);
858 observer_list.AddObserver(&disrupter2);
859
860 bool add_observers = true;
861 for (auto& observer : observer_list) {
862 // Get the { nullptr, nullptr } empty list on the first inner pass.
863 observer.Observe(10);
864
865 for (auto& nested_observer : observer_list)
866 nested_observer.Observe(1);
867
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
TYPED_TEST(ObserverListTest,AddObserverInTheLastObserve)879 TYPED_TEST(ObserverListTest, AddObserverInTheLastObserve) {
880 DECLARE_TYPES;
881 ObserverListFoo observer_list;
882
883 AddInObserve<ObserverListFoo> a(&observer_list);
884 Adder b(-1);
885
886 a.SetToAdd(&b);
887 observer_list.AddObserver(&a);
888
889 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 }
901
902 EXPECT_EQ(-10, b.total);
903 }
904
905 class 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()
TYPED_TEST(ObserverListTest,NonReentrantObserverList)913 TYPED_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;
919 Adder a(1);
920 non_reentrant_observer_list.AddObserver(&a);
921
922 EXPECT_DCHECK_DEATH({
923 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;
927 }
928 }
929 });
930 }
931
TYPED_TEST(ObserverListTest,ReentrantObserverList)932 TYPED_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;
938 Adder a(1);
939 reentrant_observer_list.AddObserver(&a);
940 bool passed = false;
941 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;
945 passed = true;
946 }
947 }
948 EXPECT_TRUE(passed);
949 }
950 #endif
951
952 class TestCheckedObserver : public CheckedObserver {
953 public:
TestCheckedObserver(int * count)954 explicit TestCheckedObserver(int* count) : count_(count) {}
955 TestCheckedObserver(const TestCheckedObserver&) = delete;
956 TestCheckedObserver& operator=(const TestCheckedObserver&) = delete;
957
Observe()958 void Observe() { ++(*count_); }
959
960 private:
961 raw_ptr<int> count_;
962 };
963
964 // A second, identical observer, used to test multiple inheritance.
965 class TestCheckedObserver2 : public CheckedObserver {
966 public:
TestCheckedObserver2(int * count)967 explicit TestCheckedObserver2(int* count) : count_(count) {}
968 TestCheckedObserver2(const TestCheckedObserver2&) = delete;
969 TestCheckedObserver2& operator=(const TestCheckedObserver2&) = delete;
970
Observe()971 void Observe() { ++(*count_); }
972
973 private:
974 raw_ptr<int> count_;
975 };
976
977 using CheckedObserverListTest = ::testing::Test;
978
979 // Test Observers that CHECK() when a UAF might otherwise occur.
TEST_F(CheckedObserverListTest,CheckedObserver)980 TEST_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);
1006 EXPECT_TRUE(!list->empty());
1007
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
1018 class MultiObserver : public TestCheckedObserver,
1019 public TestCheckedObserver2,
1020 public AdderT<UncheckedBase> {
1021 public:
MultiObserver(int * checked_count,int * two_count)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.
TEST_F(CheckedObserverListTest,MultiObserver)1030 TEST_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
1040 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());
1044
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
1054 EXPECT_EQ(10, multi_observer->GetValue());
1055 for (const auto& count : counts)
1056 EXPECT_EQ(1, count);
1057
1058 unsafe_list.RemoveObserver(multi_observer.get()); // Avoid a use-after-free.
1059
1060 multi_observer.reset();
1061 EXPECT_CHECK_DEATH(iterate_over(&checked_list));
1062
1063 for (const auto& count : counts)
1064 EXPECT_EQ(1, count);
1065 }
1066
1067 } // namespace base
1068