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.
5 #include "base/observer_list.h"
9 #include "base/memory/raw_ptr.h"
10 #include "base/strings/string_piece.h"
11 #include "base/test/gtest_util.h"
12 #include "base/threading/simple_thread.h"
13 #include "build/build_config.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/abseil-cpp/absl/types/optional.h"
21 class CheckedBase : public CheckedObserver {
23 virtual void Observe(int x) = 0;
24 ~CheckedBase() override = default;
25 virtual int GetValue() const { return 0; }
30 virtual void Observe(int x) = 0;
31 virtual ~UncheckedBase() = default;
32 virtual int GetValue() const { return 0; }
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
39 struct PickObserverList {};
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>;
49 struct PickObserverList<UncheckedBase> {
50 template <class TypeParam,
51 bool check_empty = false,
52 bool allow_reentrancy = true>
53 using ObserverListType = typename ObserverList<TypeParam,
55 allow_reentrancy>::Unchecked;
59 class AdderT : public Foo {
61 explicit AdderT(int scaler) : total(0), scaler_(scaler) {}
62 ~AdderT() override = default;
64 void Observe(int x) override { total += x * scaler_; }
65 int GetValue() const override { return total; }
73 template <class ObserverListType,
74 class Foo = typename ObserverListType::value_type>
75 class DisrupterT : public Foo {
77 DisrupterT(ObserverListType* list, Foo* doomed, bool remove_self)
78 : list_(list), doomed_(doomed), remove_self_(remove_self) {}
79 DisrupterT(ObserverListType* list, Foo* doomed)
80 : DisrupterT(list, doomed, false) {}
81 DisrupterT(ObserverListType* list, bool remove_self)
82 : DisrupterT(list, nullptr, remove_self) {}
84 ~DisrupterT() override = default;
86 void Observe(int x) override {
88 list_->RemoveObserver(this);
90 list_->RemoveObserver(doomed_.get());
93 void SetDoomed(Foo* doomed) { doomed_ = doomed; }
96 raw_ptr<ObserverListType> list_;
101 template <class ObserverListType,
102 class Foo = typename ObserverListType::value_type>
103 class AddInObserve : public Foo {
105 explicit AddInObserve(ObserverListType* observer_list)
106 : observer_list(observer_list), to_add_() {}
108 void SetToAdd(Foo* to_add) { to_add_ = to_add; }
110 void Observe(int x) override {
112 observer_list->AddObserver(to_add_.get());
117 raw_ptr<ObserverListType> observer_list;
118 raw_ptr<Foo> to_add_;
121 template <class ObserverListType>
122 class ObserverListCreator : public DelegateSimpleThread::Delegate {
124 std::unique_ptr<ObserverListType> Create(
125 absl::optional<base::ObserverListPolicy> policy = absl::nullopt) {
127 DelegateSimpleThread thread(this, "ListCreator");
130 return std::move(observer_list_);
134 void Run() override {
136 observer_list_ = std::make_unique<ObserverListType>(*policy_);
138 observer_list_ = std::make_unique<ObserverListType>();
142 std::unique_ptr<ObserverListType> observer_list_;
143 absl::optional<base::ObserverListPolicy> policy_;
148 class ObserverListTestBase {
150 ObserverListTestBase() = default;
151 ObserverListTestBase(const ObserverListTestBase&) = delete;
152 ObserverListTestBase& operator=(const ObserverListTestBase&) = delete;
155 const decltype(T::list_.get()) list(const T& iter) {
156 return iter.list_.get();
160 typename T::value_type* GetCurrent(T* iter) {
161 return iter->GetCurrent();
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());
174 // Templatized test fixture that can pick between CheckedBase and UncheckedBase.
175 template <class ObserverType>
176 class ObserverListTest : public ObserverListTestBase, public ::testing::Test {
180 typename PickObserverList<ObserverType>::template ObserverListType<T>;
182 using iterator = typename ObserverList<ObserverType>::iterator;
183 using const_iterator = typename ObserverList<ObserverType>::const_iterator;
185 ObserverListTest() = default;
186 ObserverListTest(const ObserverListTest&) = delete;
187 ObserverListTest& operator=(const ObserverListTest&) = delete;
190 using ObserverTypes = ::testing::Types<CheckedBase, UncheckedBase>;
191 TYPED_TEST_SUITE(ObserverListTest, ObserverTypes);
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)
210 TYPED_TEST(ObserverListTest, BasicTest) {
212 ObserverListFoo observer_list;
213 const ObserverListFoo& const_observer_list = observer_list;
216 const const_iterator it1 = const_observer_list.begin();
217 EXPECT_EQ(it1, const_observer_list.end());
219 const const_iterator it2 = it1;
221 // Iterator assignment.
227 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
233 const iterator it1 = observer_list.begin();
234 EXPECT_EQ(it1, observer_list.end());
236 const iterator it2 = it1;
238 // Iterator assignment.
244 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
249 Adder a(1), b(-1), c(1), d(-1), e(-1);
250 Disrupter evil(&observer_list, &c);
252 observer_list.AddObserver(&a);
253 observer_list.AddObserver(&b);
255 EXPECT_TRUE(const_observer_list.HasObserver(&a));
256 EXPECT_FALSE(const_observer_list.HasObserver(&c));
259 const const_iterator it1 = const_observer_list.begin();
260 EXPECT_NE(it1, const_observer_list.end());
262 const const_iterator it2 = it1;
264 EXPECT_NE(it2, const_observer_list.end());
265 // Iterator assignment.
271 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
274 // Iterator post increment.
275 const_iterator it4 = it3++;
282 const iterator it1 = observer_list.begin();
283 EXPECT_NE(it1, observer_list.end());
285 const iterator it2 = it1;
287 EXPECT_NE(it2, observer_list.end());
288 // Iterator assignment.
294 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
297 // Iterator post increment.
298 iterator it4 = it3++;
304 for (auto& observer : observer_list)
305 observer.Observe(10);
307 observer_list.AddObserver(&evil);
308 observer_list.AddObserver(&c);
309 observer_list.AddObserver(&d);
311 // Removing an observer not in the list should do nothing.
312 observer_list.RemoveObserver(&e);
314 for (auto& observer : observer_list)
315 observer.Observe(10);
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);
324 TYPED_TEST(ObserverListTest, CreatedAndUsedOnDifferentThreads) {
327 ObserverListCreator<ObserverListFoo> list_creator;
329 // Check with default constructor
331 std::unique_ptr<ObserverListFoo> observer_list = list_creator.Create();
332 observer_list->AddObserver(&a);
333 for (auto& observer : *observer_list) {
336 EXPECT_EQ(1, a.GetValue());
339 // Check with constructor taking explicit policy
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) {
347 EXPECT_EQ(2, a.GetValue());
351 TYPED_TEST(ObserverListTest, CompactsWhenNoActiveIterator) {
353 using ObserverListConstFoo =
354 typename TestFixture::template ObserverList<const Foo>;
356 ObserverListConstFoo ol;
357 const ObserverListConstFoo& col = ol;
366 EXPECT_TRUE(col.HasObserver(&a));
367 EXPECT_FALSE(col.HasObserver(&c));
369 EXPECT_TRUE(!col.empty());
371 using It = typename ObserverListConstFoo::const_iterator;
375 EXPECT_NE(it, col.end());
378 EXPECT_NE(++it, col.end());
382 EXPECT_EQ(++it, col.end());
384 EXPECT_TRUE(!col.empty());
385 EXPECT_EQ(&*ita, &a);
386 EXPECT_EQ(&*itb, &b);
388 ol.RemoveObserver(&a);
389 EXPECT_TRUE(!col.empty());
390 EXPECT_FALSE(col.HasObserver(&a));
391 EXPECT_EQ(&*itb, &b);
393 ol.RemoveObserver(&b);
394 EXPECT_FALSE(!col.empty());
395 EXPECT_FALSE(col.HasObserver(&a));
396 EXPECT_FALSE(col.HasObserver(&b));
400 EXPECT_FALSE(!col.empty());
403 EXPECT_FALSE(!col.empty());
405 EXPECT_FALSE(!col.empty());
410 EXPECT_TRUE(!col.empty());
412 EXPECT_FALSE(!col.empty());
416 EXPECT_TRUE(!col.empty());
418 const It it = col.begin();
420 EXPECT_FALSE(!col.empty());
422 EXPECT_FALSE(!col.empty());
425 TYPED_TEST(ObserverListTest, DisruptSelf) {
427 ObserverListFoo observer_list;
428 Adder a(1), b(-1), c(1), d(-1);
429 Disrupter evil(&observer_list, true);
431 observer_list.AddObserver(&a);
432 observer_list.AddObserver(&b);
434 for (auto& observer : observer_list)
435 observer.Observe(10);
437 observer_list.AddObserver(&evil);
438 observer_list.AddObserver(&c);
439 observer_list.AddObserver(&d);
441 for (auto& observer : observer_list)
442 observer.Observe(10);
444 EXPECT_EQ(20, a.total);
445 EXPECT_EQ(-20, b.total);
446 EXPECT_EQ(10, c.total);
447 EXPECT_EQ(-10, d.total);
450 TYPED_TEST(ObserverListTest, DisruptBefore) {
452 ObserverListFoo observer_list;
453 Adder a(1), b(-1), c(1), d(-1);
454 Disrupter evil(&observer_list, &b);
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);
462 for (auto& observer : observer_list)
463 observer.Observe(10);
464 for (auto& observer : observer_list)
465 observer.Observe(10);
467 EXPECT_EQ(20, a.total);
468 EXPECT_EQ(-10, b.total);
469 EXPECT_EQ(20, c.total);
470 EXPECT_EQ(-20, d.total);
473 TYPED_TEST(ObserverListTest, Existing) {
475 ObserverListFoo observer_list(ObserverListPolicy::EXISTING_ONLY);
477 AddInObserve<ObserverListFoo> b(&observer_list);
481 observer_list.AddObserver(&a);
482 observer_list.AddObserver(&b);
484 for (auto& observer : observer_list)
487 EXPECT_FALSE(b.to_add_);
488 // B's adder should not have been notified because it was added during
490 EXPECT_EQ(0, c.total);
492 // Notify again to make sure b's adder is notified.
493 for (auto& observer : observer_list)
495 EXPECT_EQ(1, c.total);
498 template <class ObserverListType,
499 class Foo = typename ObserverListType::value_type>
500 class AddInClearObserve : public Foo {
502 explicit AddInClearObserve(ObserverListType* list)
503 : list_(list), added_(false), adder_(1) {}
505 void Observe(int /* x */) override {
507 list_->AddObserver(&adder_);
511 bool added() const { return added_; }
512 const AdderT<Foo>& adder() const { return adder_; }
515 const raw_ptr<ObserverListType> list_;
521 TYPED_TEST(ObserverListTest, ClearNotifyAll) {
523 ObserverListFoo observer_list;
524 AddInClearObserve<ObserverListFoo> a(&observer_list);
526 observer_list.AddObserver(&a);
528 for (auto& observer : observer_list)
530 EXPECT_TRUE(a.added());
531 EXPECT_EQ(1, a.adder().total)
532 << "Adder should observe once and have sum of 1.";
535 TYPED_TEST(ObserverListTest, ClearNotifyExistingOnly) {
537 ObserverListFoo observer_list(ObserverListPolicy::EXISTING_ONLY);
538 AddInClearObserve<ObserverListFoo> a(&observer_list);
540 observer_list.AddObserver(&a);
542 for (auto& observer : observer_list)
544 EXPECT_TRUE(a.added());
545 EXPECT_EQ(0, a.adder().total)
546 << "Adder should not observe, so sum should still be 0.";
549 template <class ObserverListType,
550 class Foo = typename ObserverListType::value_type>
551 class ListDestructor : public Foo {
553 explicit ListDestructor(ObserverListType* list) : list_(list) {}
554 ~ListDestructor() override = default;
556 void Observe(int x) override { delete list_.ExtractAsDangling(); }
559 raw_ptr<ObserverListType> list_;
562 TYPED_TEST(ObserverListTest, IteratorOutlivesList) {
564 ObserverListFoo* observer_list = new ObserverListFoo;
565 ListDestructor<ObserverListFoo> a(observer_list);
566 observer_list->AddObserver(&a);
568 for (auto& observer : *observer_list)
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.
576 TYPED_TEST(ObserverListTest, BasicStdIterator) {
578 ObserverListFoo observer_list;
580 // An optimization: begin() and end() do not involve weak pointers on
582 EXPECT_FALSE(this->list(observer_list.begin()));
583 EXPECT_FALSE(this->list(observer_list.end()));
585 // Iterate over empty list: no effect, no crash.
586 for (auto& i : observer_list)
589 Adder a(1), b(-1), c(1), d(-1);
591 observer_list.AddObserver(&a);
592 observer_list.AddObserver(&b);
593 observer_list.AddObserver(&c);
594 observer_list.AddObserver(&d);
596 for (iterator i = observer_list.begin(), e = observer_list.end(); i != e; ++i)
599 EXPECT_EQ(1, a.total);
600 EXPECT_EQ(-1, b.total);
601 EXPECT_EQ(1, c.total);
602 EXPECT_EQ(-1, d.total);
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;
608 EXPECT_EQ(1, std::abs(i->GetValue()));
611 for (const auto& o : const_list)
612 EXPECT_EQ(1, std::abs(o.GetValue()));
615 TYPED_TEST(ObserverListTest, StdIteratorRemoveItself) {
617 ObserverListFoo observer_list;
618 Adder a(1), b(-1), c(1), d(-1);
619 Disrupter disrupter(&observer_list, true);
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);
627 for (auto& o : observer_list)
630 for (auto& o : observer_list)
633 EXPECT_EQ(11, a.total);
634 EXPECT_EQ(-11, b.total);
635 EXPECT_EQ(11, c.total);
636 EXPECT_EQ(-11, d.total);
639 TYPED_TEST(ObserverListTest, StdIteratorRemoveBefore) {
641 ObserverListFoo observer_list;
642 Adder a(1), b(-1), c(1), d(-1);
643 Disrupter disrupter(&observer_list, &b);
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);
651 for (auto& o : observer_list)
654 for (auto& o : observer_list)
657 EXPECT_EQ(11, a.total);
658 EXPECT_EQ(-1, b.total);
659 EXPECT_EQ(11, c.total);
660 EXPECT_EQ(-11, d.total);
663 TYPED_TEST(ObserverListTest, StdIteratorRemoveAfter) {
665 ObserverListFoo observer_list;
666 Adder a(1), b(-1), c(1), d(-1);
667 Disrupter disrupter(&observer_list, &c);
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);
675 for (auto& o : observer_list)
678 for (auto& o : observer_list)
681 EXPECT_EQ(11, a.total);
682 EXPECT_EQ(-11, b.total);
683 EXPECT_EQ(0, c.total);
684 EXPECT_EQ(-11, d.total);
687 TYPED_TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
689 ObserverListFoo observer_list;
690 Adder a(1), b(-1), c(1), d(-1);
691 Disrupter disrupter(&observer_list, &a);
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);
699 for (auto& o : observer_list)
702 for (auto& o : observer_list)
705 EXPECT_EQ(1, a.total);
706 EXPECT_EQ(-11, b.total);
707 EXPECT_EQ(11, c.total);
708 EXPECT_EQ(-11, d.total);
711 TYPED_TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
713 ObserverListFoo observer_list;
714 Adder a(1), b(-1), c(1), d(-1);
715 Disrupter disrupter(&observer_list, &d);
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);
723 for (auto& o : observer_list)
726 for (auto& o : observer_list)
729 EXPECT_EQ(11, a.total);
730 EXPECT_EQ(-11, b.total);
731 EXPECT_EQ(11, c.total);
732 EXPECT_EQ(0, d.total);
735 TYPED_TEST(ObserverListTest, StdIteratorRemoveFront) {
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);
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);
748 bool test_disruptor = true;
749 for (iterator i = observer_list.begin(), e = observer_list.end(); i != e;
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;
759 for (auto& o : observer_list)
762 EXPECT_EQ(11, a.total);
763 EXPECT_EQ(-11, b.total);
764 EXPECT_EQ(11, c.total);
765 EXPECT_EQ(-11, d.total);
768 TYPED_TEST(ObserverListTest, StdIteratorRemoveBack) {
770 ObserverListFoo observer_list;
771 Adder a(1), b(-1), c(1), d(-1);
772 Disrupter disrupter(&observer_list, true);
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);
780 for (auto& o : observer_list)
783 for (auto& o : observer_list)
786 EXPECT_EQ(11, a.total);
787 EXPECT_EQ(-11, b.total);
788 EXPECT_EQ(11, c.total);
789 EXPECT_EQ(-11, d.total);
792 TYPED_TEST(ObserverListTest, NestedLoop) {
794 ObserverListFoo observer_list;
795 Adder a(1), b(-1), c(1), d(-1);
796 Disrupter disrupter(&observer_list, true);
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);
804 for (auto& observer : observer_list) {
805 observer.Observe(10);
807 for (auto& nested_observer : observer_list)
808 nested_observer.Observe(1);
811 EXPECT_EQ(15, a.total);
812 EXPECT_EQ(-15, b.total);
813 EXPECT_EQ(15, c.total);
814 EXPECT_EQ(-15, d.total);
817 TYPED_TEST(ObserverListTest, NonCompactList) {
819 ObserverListFoo observer_list;
822 Disrupter disrupter2(&observer_list, true); // Must outlive `disrupter1`.
823 Disrupter disrupter1(&observer_list, true);
825 // Disrupt itself and another one.
826 disrupter1.SetDoomed(&disrupter2);
828 observer_list.AddObserver(&disrupter1);
829 observer_list.AddObserver(&disrupter2);
830 observer_list.AddObserver(&a);
831 observer_list.AddObserver(&b);
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);
838 for (auto& nested_observer : observer_list)
839 nested_observer.Observe(1);
842 EXPECT_EQ(13, a.total);
843 EXPECT_EQ(-13, b.total);
846 TYPED_TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
848 ObserverListFoo observer_list;
851 Disrupter disrupter2(&observer_list, true); // Must outlive `disrupter1`.
852 Disrupter disrupter1(&observer_list, true);
854 // Disrupt itself and another one.
855 disrupter1.SetDoomed(&disrupter2);
857 observer_list.AddObserver(&disrupter1);
858 observer_list.AddObserver(&disrupter2);
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);
865 for (auto& nested_observer : observer_list)
866 nested_observer.Observe(1);
869 observer_list.AddObserver(&a);
870 observer_list.AddObserver(&b);
871 add_observers = false;
875 EXPECT_EQ(12, a.total);
876 EXPECT_EQ(-12, b.total);
879 TYPED_TEST(ObserverListTest, AddObserverInTheLastObserve) {
881 ObserverListFoo observer_list;
883 AddInObserve<ObserverListFoo> a(&observer_list);
887 observer_list.AddObserver(&a);
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.
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);
902 EXPECT_EQ(-10, b.total);
905 class MockLogAssertHandler {
909 void(const char*, int, const base::StringPiece, const base::StringPiece));
913 TYPED_TEST(ObserverListTest, NonReentrantObserverList) {
915 using NonReentrantObserverListFoo = typename PickObserverList<
916 Foo>::template ObserverListType<Foo, /*check_empty=*/false,
917 /*allow_reentrancy=*/false>;
918 NonReentrantObserverListFoo non_reentrant_observer_list;
920 non_reentrant_observer_list.AddObserver(&a);
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;
932 TYPED_TEST(ObserverListTest, ReentrantObserverList) {
934 using ReentrantObserverListFoo = typename PickObserverList<
935 Foo>::template ObserverListType<Foo, /*check_empty=*/false,
936 /*allow_reentrancy=*/true>;
937 ReentrantObserverListFoo reentrant_observer_list;
939 reentrant_observer_list.AddObserver(&a);
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;
952 class TestCheckedObserver : public CheckedObserver {
954 explicit TestCheckedObserver(int* count) : count_(count) {}
955 TestCheckedObserver(const TestCheckedObserver&) = delete;
956 TestCheckedObserver& operator=(const TestCheckedObserver&) = delete;
958 void Observe() { ++(*count_); }
964 // A second, identical observer, used to test multiple inheritance.
965 class TestCheckedObserver2 : public CheckedObserver {
967 explicit TestCheckedObserver2(int* count) : count_(count) {}
968 TestCheckedObserver2(const TestCheckedObserver2&) = delete;
969 TestCheckedObserver2& operator=(const TestCheckedObserver2&) = delete;
971 void Observe() { ++(*count_); }
977 using CheckedObserverListTest = ::testing::Test;
979 // Test Observers that CHECK() when a UAF might otherwise occur.
980 TEST_F(CheckedObserverListTest, CheckedObserver) {
981 // See comments below about why this is unique_ptr.
982 auto list = std::make_unique<ObserverList<TestCheckedObserver>>();
985 TestCheckedObserver l1(&count1);
986 list->AddObserver(&l1);
988 TestCheckedObserver l2(&count2);
989 list->AddObserver(&l2);
990 for (auto& observer : *list)
992 EXPECT_EQ(1, count1);
993 EXPECT_EQ(1, count2);
996 auto it = list->begin();
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++);
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());
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.
1014 EXPECT_EQ(2, count1);
1015 EXPECT_EQ(1, count2);
1018 class MultiObserver : public TestCheckedObserver,
1019 public TestCheckedObserver2,
1020 public AdderT<UncheckedBase> {
1022 MultiObserver(int* checked_count, int* two_count)
1023 : TestCheckedObserver(checked_count),
1024 TestCheckedObserver2(two_count),
1028 // Test that observers behave as expected when observing multiple interfaces
1029 // with different traits.
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;
1036 ObserverList<UncheckedBase>::Unchecked unsafe_list;
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());
1045 auto iterate_over = [](auto* list) {
1046 for (auto& observer : *list)
1049 iterate_over(&two_list);
1050 iterate_over(&checked_list);
1051 for (auto& observer : unsafe_list)
1052 observer.Observe(10);
1054 EXPECT_EQ(10, multi_observer->GetValue());
1055 for (const auto& count : counts)
1056 EXPECT_EQ(1, count);
1058 unsafe_list.RemoveObserver(multi_observer.get()); // Avoid a use-after-free.
1060 multi_observer.reset();
1061 EXPECT_CHECK_DEATH(iterate_over(&checked_list));
1063 for (const auto& count : counts)
1064 EXPECT_EQ(1, count);