1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/observer_list.h"
7 // observer_list.h is a widely included header and its size has significant
8 // impact on build time. Try not to raise this limit unless necessary. See
9 // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
11 #pragma clang max_tokens_here 480000
16 #include "base/strings/string_piece.h"
17 #include "base/test/gtest_util.h"
18 #include "base/threading/simple_thread.h"
19 #include "build/build_config.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "third_party/abseil-cpp/absl/types/optional.h"
27 class CheckedBase : public CheckedObserver {
29 virtual void Observe(int x) = 0;
30 ~CheckedBase() override = default;
31 virtual int GetValue() const { return 0; }
36 virtual void Observe(int x) = 0;
37 virtual ~UncheckedBase() = default;
38 virtual int GetValue() const { return 0; }
41 // Helper for TYPED_TEST_SUITE machinery to pick the ObserverList under test.
42 // Keyed off the observer type since ObserverList has too many template args and
45 struct PickObserverList {};
47 struct PickObserverList<CheckedBase> {
48 template <class TypeParam,
49 bool check_empty = false,
50 bool allow_reentrancy = true>
51 using ObserverListType =
52 ObserverList<TypeParam, check_empty, allow_reentrancy>;
55 struct PickObserverList<UncheckedBase> {
56 template <class TypeParam,
57 bool check_empty = false,
58 bool allow_reentrancy = true>
59 using ObserverListType = typename ObserverList<TypeParam,
61 allow_reentrancy>::Unchecked;
65 class AdderT : public Foo {
67 explicit AdderT(int scaler) : total(0), scaler_(scaler) {}
68 ~AdderT() override = default;
70 void Observe(int x) override { total += x * scaler_; }
71 int GetValue() const override { return total; }
79 template <class ObserverListType,
80 class Foo = typename ObserverListType::value_type>
81 class DisrupterT : public Foo {
83 DisrupterT(ObserverListType* list, Foo* doomed, bool remove_self)
84 : list_(list), doomed_(doomed), remove_self_(remove_self) {}
85 DisrupterT(ObserverListType* list, Foo* doomed)
86 : DisrupterT(list, doomed, false) {}
87 DisrupterT(ObserverListType* list, bool remove_self)
88 : DisrupterT(list, nullptr, remove_self) {}
90 ~DisrupterT() override = default;
92 void Observe(int x) override {
94 list_->RemoveObserver(this);
96 list_->RemoveObserver(doomed_);
99 void SetDoomed(Foo* doomed) { doomed_ = doomed; }
102 ObserverListType* list_;
107 template <class ObserverListType,
108 class Foo = typename ObserverListType::value_type>
109 class AddInObserve : public Foo {
111 explicit AddInObserve(ObserverListType* observer_list)
112 : observer_list(observer_list), to_add_() {}
114 void SetToAdd(Foo* to_add) { to_add_ = to_add; }
116 void Observe(int x) override {
118 observer_list->AddObserver(to_add_);
123 ObserverListType* observer_list;
127 template <class ObserverListType>
128 class ObserverListCreator : public DelegateSimpleThread::Delegate {
130 std::unique_ptr<ObserverListType> Create(
131 absl::optional<base::ObserverListPolicy> policy = absl::nullopt) {
133 DelegateSimpleThread thread(this, "ListCreator");
136 return std::move(observer_list_);
140 void Run() override {
142 observer_list_ = std::make_unique<ObserverListType>(*policy_);
144 observer_list_ = std::make_unique<ObserverListType>();
148 std::unique_ptr<ObserverListType> observer_list_;
149 absl::optional<base::ObserverListPolicy> policy_;
154 class ObserverListTestBase {
156 ObserverListTestBase() = default;
157 ObserverListTestBase(const ObserverListTestBase&) = delete;
158 ObserverListTestBase& operator=(const ObserverListTestBase&) = delete;
161 const decltype(T::list_.get()) list(const T& iter) {
162 return iter.list_.get();
166 typename T::value_type* GetCurrent(T* iter) {
167 return iter->GetCurrent();
170 // Override GetCurrent() for CheckedObserver. When StdIteratorRemoveFront
171 // tries to simulate a sequence to see if it "would" crash, CheckedObservers
172 // do, actually, crash with a DCHECK(). Note this check is different to the
173 // check during an observer _iteration_. Hence, DCHECK(), not CHECK().
174 CheckedBase* GetCurrent(ObserverList<CheckedBase>::iterator* iter) {
175 EXPECT_DCHECK_DEATH(return iter->GetCurrent());
180 // Templatized test fixture that can pick between CheckedBase and UncheckedBase.
181 template <class ObserverType>
182 class ObserverListTest : public ObserverListTestBase, public ::testing::Test {
186 typename PickObserverList<ObserverType>::template ObserverListType<T>;
188 using iterator = typename ObserverList<ObserverType>::iterator;
189 using const_iterator = typename ObserverList<ObserverType>::const_iterator;
191 ObserverListTest() = default;
192 ObserverListTest(const ObserverListTest&) = delete;
193 ObserverListTest& operator=(const ObserverListTest&) = delete;
196 using ObserverTypes = ::testing::Types<CheckedBase, UncheckedBase>;
197 TYPED_TEST_SUITE(ObserverListTest, ObserverTypes);
199 // TYPED_TEST causes the test parent class to be a template parameter, which
200 // makes the syntax for referring to the types awkward. Create aliases in local
201 // scope with clearer names. Unfortunately, we also need some trailing cruft to
202 // avoid "unused local type alias" warnings.
203 #define DECLARE_TYPES \
204 using Foo = TypeParam; \
205 using ObserverListFoo = \
206 typename PickObserverList<TypeParam>::template ObserverListType<Foo>; \
207 using Adder = AdderT<Foo>; \
208 using Disrupter = DisrupterT<ObserverListFoo>; \
209 using const_iterator = typename TestFixture::const_iterator; \
210 using iterator = typename TestFixture::iterator; \
211 (void)reinterpret_cast<Disrupter*>(0); \
212 (void)reinterpret_cast<Adder*>(0); \
213 (void)reinterpret_cast<const_iterator*>(0); \
214 (void)reinterpret_cast<iterator*>(0)
216 TYPED_TEST(ObserverListTest, BasicTest) {
218 ObserverListFoo observer_list;
219 const ObserverListFoo& const_observer_list = observer_list;
222 const const_iterator it1 = const_observer_list.begin();
223 EXPECT_EQ(it1, const_observer_list.end());
225 const const_iterator it2 = it1;
227 // Iterator assignment.
233 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
239 const iterator it1 = observer_list.begin();
240 EXPECT_EQ(it1, observer_list.end());
242 const iterator it2 = it1;
244 // Iterator assignment.
250 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
255 Adder a(1), b(-1), c(1), d(-1), e(-1);
256 Disrupter evil(&observer_list, &c);
258 observer_list.AddObserver(&a);
259 observer_list.AddObserver(&b);
261 EXPECT_TRUE(const_observer_list.HasObserver(&a));
262 EXPECT_FALSE(const_observer_list.HasObserver(&c));
265 const const_iterator it1 = const_observer_list.begin();
266 EXPECT_NE(it1, const_observer_list.end());
268 const const_iterator it2 = it1;
270 EXPECT_NE(it2, const_observer_list.end());
271 // Iterator assignment.
277 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
280 // Iterator post increment.
281 const_iterator it4 = it3++;
288 const iterator it1 = observer_list.begin();
289 EXPECT_NE(it1, observer_list.end());
291 const iterator it2 = it1;
293 EXPECT_NE(it2, observer_list.end());
294 // Iterator assignment.
300 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
303 // Iterator post increment.
304 iterator it4 = it3++;
310 for (auto& observer : observer_list)
311 observer.Observe(10);
313 observer_list.AddObserver(&evil);
314 observer_list.AddObserver(&c);
315 observer_list.AddObserver(&d);
317 // Removing an observer not in the list should do nothing.
318 observer_list.RemoveObserver(&e);
320 for (auto& observer : observer_list)
321 observer.Observe(10);
323 EXPECT_EQ(20, a.total);
324 EXPECT_EQ(-20, b.total);
325 EXPECT_EQ(0, c.total);
326 EXPECT_EQ(-10, d.total);
327 EXPECT_EQ(0, e.total);
330 TYPED_TEST(ObserverListTest, CreatedAndUsedOnDifferentThreads) {
333 ObserverListCreator<ObserverListFoo> list_creator;
335 // Check with default constructor
337 std::unique_ptr<ObserverListFoo> observer_list = list_creator.Create();
338 observer_list->AddObserver(&a);
339 for (auto& observer : *observer_list) {
342 EXPECT_EQ(1, a.GetValue());
345 // Check with constructor taking explicit policy
347 std::unique_ptr<ObserverListFoo> observer_list =
348 list_creator.Create(base::ObserverListPolicy::EXISTING_ONLY);
349 observer_list->AddObserver(&a);
350 for (auto& observer : *observer_list) {
353 EXPECT_EQ(2, a.GetValue());
357 TYPED_TEST(ObserverListTest, CompactsWhenNoActiveIterator) {
359 using ObserverListConstFoo =
360 typename TestFixture::template ObserverList<const Foo>;
362 ObserverListConstFoo ol;
363 const ObserverListConstFoo& col = ol;
372 EXPECT_TRUE(col.HasObserver(&a));
373 EXPECT_FALSE(col.HasObserver(&c));
375 EXPECT_TRUE(!col.empty());
377 using It = typename ObserverListConstFoo::const_iterator;
381 EXPECT_NE(it, col.end());
384 EXPECT_NE(++it, col.end());
388 EXPECT_EQ(++it, col.end());
390 EXPECT_TRUE(!col.empty());
391 EXPECT_EQ(&*ita, &a);
392 EXPECT_EQ(&*itb, &b);
394 ol.RemoveObserver(&a);
395 EXPECT_TRUE(!col.empty());
396 EXPECT_FALSE(col.HasObserver(&a));
397 EXPECT_EQ(&*itb, &b);
399 ol.RemoveObserver(&b);
400 EXPECT_FALSE(!col.empty());
401 EXPECT_FALSE(col.HasObserver(&a));
402 EXPECT_FALSE(col.HasObserver(&b));
406 EXPECT_FALSE(!col.empty());
409 EXPECT_FALSE(!col.empty());
411 EXPECT_FALSE(!col.empty());
416 EXPECT_TRUE(!col.empty());
418 EXPECT_FALSE(!col.empty());
422 EXPECT_TRUE(!col.empty());
424 const It it = col.begin();
426 EXPECT_FALSE(!col.empty());
428 EXPECT_FALSE(!col.empty());
431 TYPED_TEST(ObserverListTest, DisruptSelf) {
433 ObserverListFoo observer_list;
434 Adder a(1), b(-1), c(1), d(-1);
435 Disrupter evil(&observer_list, true);
437 observer_list.AddObserver(&a);
438 observer_list.AddObserver(&b);
440 for (auto& observer : observer_list)
441 observer.Observe(10);
443 observer_list.AddObserver(&evil);
444 observer_list.AddObserver(&c);
445 observer_list.AddObserver(&d);
447 for (auto& observer : observer_list)
448 observer.Observe(10);
450 EXPECT_EQ(20, a.total);
451 EXPECT_EQ(-20, b.total);
452 EXPECT_EQ(10, c.total);
453 EXPECT_EQ(-10, d.total);
456 TYPED_TEST(ObserverListTest, DisruptBefore) {
458 ObserverListFoo observer_list;
459 Adder a(1), b(-1), c(1), d(-1);
460 Disrupter evil(&observer_list, &b);
462 observer_list.AddObserver(&a);
463 observer_list.AddObserver(&b);
464 observer_list.AddObserver(&evil);
465 observer_list.AddObserver(&c);
466 observer_list.AddObserver(&d);
468 for (auto& observer : observer_list)
469 observer.Observe(10);
470 for (auto& observer : observer_list)
471 observer.Observe(10);
473 EXPECT_EQ(20, a.total);
474 EXPECT_EQ(-10, b.total);
475 EXPECT_EQ(20, c.total);
476 EXPECT_EQ(-20, d.total);
479 TYPED_TEST(ObserverListTest, Existing) {
481 ObserverListFoo observer_list(ObserverListPolicy::EXISTING_ONLY);
483 AddInObserve<ObserverListFoo> b(&observer_list);
487 observer_list.AddObserver(&a);
488 observer_list.AddObserver(&b);
490 for (auto& observer : observer_list)
493 EXPECT_FALSE(b.to_add_);
494 // B's adder should not have been notified because it was added during
496 EXPECT_EQ(0, c.total);
498 // Notify again to make sure b's adder is notified.
499 for (auto& observer : observer_list)
501 EXPECT_EQ(1, c.total);
504 template <class ObserverListType,
505 class Foo = typename ObserverListType::value_type>
506 class AddInClearObserve : public Foo {
508 explicit AddInClearObserve(ObserverListType* list)
509 : list_(list), added_(false), adder_(1) {}
511 void Observe(int /* x */) override {
513 list_->AddObserver(&adder_);
517 bool added() const { return added_; }
518 const AdderT<Foo>& adder() const { return adder_; }
521 ObserverListType* const list_;
527 TYPED_TEST(ObserverListTest, ClearNotifyAll) {
529 ObserverListFoo observer_list;
530 AddInClearObserve<ObserverListFoo> a(&observer_list);
532 observer_list.AddObserver(&a);
534 for (auto& observer : observer_list)
536 EXPECT_TRUE(a.added());
537 EXPECT_EQ(1, a.adder().total)
538 << "Adder should observe once and have sum of 1.";
541 TYPED_TEST(ObserverListTest, ClearNotifyExistingOnly) {
543 ObserverListFoo observer_list(ObserverListPolicy::EXISTING_ONLY);
544 AddInClearObserve<ObserverListFoo> a(&observer_list);
546 observer_list.AddObserver(&a);
548 for (auto& observer : observer_list)
550 EXPECT_TRUE(a.added());
551 EXPECT_EQ(0, a.adder().total)
552 << "Adder should not observe, so sum should still be 0.";
555 template <class ObserverListType,
556 class Foo = typename ObserverListType::value_type>
557 class ListDestructor : public Foo {
559 explicit ListDestructor(ObserverListType* list) : list_(list) {}
560 ~ListDestructor() override = default;
562 void Observe(int x) override { delete list_; }
565 ObserverListType* list_;
568 TYPED_TEST(ObserverListTest, IteratorOutlivesList) {
570 ObserverListFoo* observer_list = new ObserverListFoo;
571 ListDestructor<ObserverListFoo> a(observer_list);
572 observer_list->AddObserver(&a);
574 for (auto& observer : *observer_list)
577 // There are no EXPECT* statements for this test, if we catch
578 // use-after-free errors for observer_list (eg with ASan) then
579 // this test has failed. See http://crbug.com/85296.
582 TYPED_TEST(ObserverListTest, BasicStdIterator) {
584 ObserverListFoo observer_list;
586 // An optimization: begin() and end() do not involve weak pointers on
588 EXPECT_FALSE(this->list(observer_list.begin()));
589 EXPECT_FALSE(this->list(observer_list.end()));
591 // Iterate over empty list: no effect, no crash.
592 for (auto& i : observer_list)
595 Adder a(1), b(-1), c(1), d(-1);
597 observer_list.AddObserver(&a);
598 observer_list.AddObserver(&b);
599 observer_list.AddObserver(&c);
600 observer_list.AddObserver(&d);
602 for (iterator i = observer_list.begin(), e = observer_list.end(); i != e; ++i)
605 EXPECT_EQ(1, a.total);
606 EXPECT_EQ(-1, b.total);
607 EXPECT_EQ(1, c.total);
608 EXPECT_EQ(-1, d.total);
610 // Check an iteration over a 'const view' for a given container.
611 const ObserverListFoo& const_list = observer_list;
612 for (const_iterator i = const_list.begin(), e = const_list.end(); i != e;
614 EXPECT_EQ(1, std::abs(i->GetValue()));
617 for (const auto& o : const_list)
618 EXPECT_EQ(1, std::abs(o.GetValue()));
621 TYPED_TEST(ObserverListTest, StdIteratorRemoveItself) {
623 ObserverListFoo observer_list;
624 Adder a(1), b(-1), c(1), d(-1);
625 Disrupter disrupter(&observer_list, true);
627 observer_list.AddObserver(&a);
628 observer_list.AddObserver(&b);
629 observer_list.AddObserver(&disrupter);
630 observer_list.AddObserver(&c);
631 observer_list.AddObserver(&d);
633 for (auto& o : observer_list)
636 for (auto& o : observer_list)
639 EXPECT_EQ(11, a.total);
640 EXPECT_EQ(-11, b.total);
641 EXPECT_EQ(11, c.total);
642 EXPECT_EQ(-11, d.total);
645 TYPED_TEST(ObserverListTest, StdIteratorRemoveBefore) {
647 ObserverListFoo observer_list;
648 Adder a(1), b(-1), c(1), d(-1);
649 Disrupter disrupter(&observer_list, &b);
651 observer_list.AddObserver(&a);
652 observer_list.AddObserver(&b);
653 observer_list.AddObserver(&disrupter);
654 observer_list.AddObserver(&c);
655 observer_list.AddObserver(&d);
657 for (auto& o : observer_list)
660 for (auto& o : observer_list)
663 EXPECT_EQ(11, a.total);
664 EXPECT_EQ(-1, b.total);
665 EXPECT_EQ(11, c.total);
666 EXPECT_EQ(-11, d.total);
669 TYPED_TEST(ObserverListTest, StdIteratorRemoveAfter) {
671 ObserverListFoo observer_list;
672 Adder a(1), b(-1), c(1), d(-1);
673 Disrupter disrupter(&observer_list, &c);
675 observer_list.AddObserver(&a);
676 observer_list.AddObserver(&b);
677 observer_list.AddObserver(&disrupter);
678 observer_list.AddObserver(&c);
679 observer_list.AddObserver(&d);
681 for (auto& o : observer_list)
684 for (auto& o : observer_list)
687 EXPECT_EQ(11, a.total);
688 EXPECT_EQ(-11, b.total);
689 EXPECT_EQ(0, c.total);
690 EXPECT_EQ(-11, d.total);
693 TYPED_TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
695 ObserverListFoo observer_list;
696 Adder a(1), b(-1), c(1), d(-1);
697 Disrupter disrupter(&observer_list, &a);
699 observer_list.AddObserver(&a);
700 observer_list.AddObserver(&disrupter);
701 observer_list.AddObserver(&b);
702 observer_list.AddObserver(&c);
703 observer_list.AddObserver(&d);
705 for (auto& o : observer_list)
708 for (auto& o : observer_list)
711 EXPECT_EQ(1, a.total);
712 EXPECT_EQ(-11, b.total);
713 EXPECT_EQ(11, c.total);
714 EXPECT_EQ(-11, d.total);
717 TYPED_TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
719 ObserverListFoo observer_list;
720 Adder a(1), b(-1), c(1), d(-1);
721 Disrupter disrupter(&observer_list, &d);
723 observer_list.AddObserver(&a);
724 observer_list.AddObserver(&b);
725 observer_list.AddObserver(&c);
726 observer_list.AddObserver(&disrupter);
727 observer_list.AddObserver(&d);
729 for (auto& o : observer_list)
732 for (auto& o : observer_list)
735 EXPECT_EQ(11, a.total);
736 EXPECT_EQ(-11, b.total);
737 EXPECT_EQ(11, c.total);
738 EXPECT_EQ(0, d.total);
741 TYPED_TEST(ObserverListTest, StdIteratorRemoveFront) {
743 using iterator = typename TestFixture::iterator;
744 ObserverListFoo observer_list;
745 Adder a(1), b(-1), c(1), d(-1);
746 Disrupter disrupter(&observer_list, true);
748 observer_list.AddObserver(&disrupter);
749 observer_list.AddObserver(&a);
750 observer_list.AddObserver(&b);
751 observer_list.AddObserver(&c);
752 observer_list.AddObserver(&d);
754 bool test_disruptor = true;
755 for (iterator i = observer_list.begin(), e = observer_list.end(); i != e;
758 // Check that second call to i->Observe() would crash here.
759 if (test_disruptor) {
760 EXPECT_FALSE(this->GetCurrent(&i));
761 test_disruptor = false;
765 for (auto& o : observer_list)
768 EXPECT_EQ(11, a.total);
769 EXPECT_EQ(-11, b.total);
770 EXPECT_EQ(11, c.total);
771 EXPECT_EQ(-11, d.total);
774 TYPED_TEST(ObserverListTest, StdIteratorRemoveBack) {
776 ObserverListFoo observer_list;
777 Adder a(1), b(-1), c(1), d(-1);
778 Disrupter disrupter(&observer_list, true);
780 observer_list.AddObserver(&a);
781 observer_list.AddObserver(&b);
782 observer_list.AddObserver(&c);
783 observer_list.AddObserver(&d);
784 observer_list.AddObserver(&disrupter);
786 for (auto& o : observer_list)
789 for (auto& o : observer_list)
792 EXPECT_EQ(11, a.total);
793 EXPECT_EQ(-11, b.total);
794 EXPECT_EQ(11, c.total);
795 EXPECT_EQ(-11, d.total);
798 TYPED_TEST(ObserverListTest, NestedLoop) {
800 ObserverListFoo observer_list;
801 Adder a(1), b(-1), c(1), d(-1);
802 Disrupter disrupter(&observer_list, true);
804 observer_list.AddObserver(&disrupter);
805 observer_list.AddObserver(&a);
806 observer_list.AddObserver(&b);
807 observer_list.AddObserver(&c);
808 observer_list.AddObserver(&d);
810 for (auto& observer : observer_list) {
811 observer.Observe(10);
813 for (auto& nested_observer : observer_list)
814 nested_observer.Observe(1);
817 EXPECT_EQ(15, a.total);
818 EXPECT_EQ(-15, b.total);
819 EXPECT_EQ(15, c.total);
820 EXPECT_EQ(-15, d.total);
823 TYPED_TEST(ObserverListTest, NonCompactList) {
825 ObserverListFoo observer_list;
828 Disrupter disrupter1(&observer_list, true);
829 Disrupter disrupter2(&observer_list, true);
831 // Disrupt itself and another one.
832 disrupter1.SetDoomed(&disrupter2);
834 observer_list.AddObserver(&disrupter1);
835 observer_list.AddObserver(&disrupter2);
836 observer_list.AddObserver(&a);
837 observer_list.AddObserver(&b);
839 for (auto& observer : observer_list) {
840 // Get the { nullptr, nullptr, &a, &b } non-compact list
841 // on the first inner pass.
842 observer.Observe(10);
844 for (auto& nested_observer : observer_list)
845 nested_observer.Observe(1);
848 EXPECT_EQ(13, a.total);
849 EXPECT_EQ(-13, b.total);
852 TYPED_TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
854 ObserverListFoo observer_list;
857 Disrupter disrupter1(&observer_list, true);
858 Disrupter disrupter2(&observer_list, true);
860 // Disrupt itself and another one.
861 disrupter1.SetDoomed(&disrupter2);
863 observer_list.AddObserver(&disrupter1);
864 observer_list.AddObserver(&disrupter2);
866 bool add_observers = true;
867 for (auto& observer : observer_list) {
868 // Get the { nullptr, nullptr } empty list on the first inner pass.
869 observer.Observe(10);
871 for (auto& nested_observer : observer_list)
872 nested_observer.Observe(1);
875 observer_list.AddObserver(&a);
876 observer_list.AddObserver(&b);
877 add_observers = false;
881 EXPECT_EQ(12, a.total);
882 EXPECT_EQ(-12, b.total);
885 TYPED_TEST(ObserverListTest, AddObserverInTheLastObserve) {
887 ObserverListFoo observer_list;
889 AddInObserve<ObserverListFoo> a(&observer_list);
893 observer_list.AddObserver(&a);
895 auto it = observer_list.begin();
896 while (it != observer_list.end()) {
897 auto& observer = *it;
898 // Intentionally increment the iterator before calling Observe(). The
899 // ObserverList starts with only one observer, and it == observer_list.end()
900 // should be true after the next line.
902 // However, the first Observe() call will add a second observer: at this
903 // point, it != observer_list.end() should be true, and Observe() should be
904 // called on the newly added observer on the next iteration of the loop.
905 observer.Observe(10);
908 EXPECT_EQ(-10, b.total);
911 class MockLogAssertHandler {
915 void(const char*, int, const base::StringPiece, const base::StringPiece));
919 TYPED_TEST(ObserverListTest, NonReentrantObserverList) {
921 using NonReentrantObserverListFoo = typename PickObserverList<
922 Foo>::template ObserverListType<Foo, /*check_empty=*/false,
923 /*allow_reentrancy=*/false>;
924 NonReentrantObserverListFoo non_reentrant_observer_list;
926 non_reentrant_observer_list.AddObserver(&a);
928 EXPECT_DCHECK_DEATH({
929 for (const Foo& observer : non_reentrant_observer_list) {
930 for (const Foo& nested_observer : non_reentrant_observer_list) {
931 std::ignore = observer;
932 std::ignore = nested_observer;
938 TYPED_TEST(ObserverListTest, ReentrantObserverList) {
940 using ReentrantObserverListFoo = typename PickObserverList<
941 Foo>::template ObserverListType<Foo, /*check_empty=*/false,
942 /*allow_reentrancy=*/true>;
943 ReentrantObserverListFoo reentrant_observer_list;
945 reentrant_observer_list.AddObserver(&a);
947 for (const Foo& observer : reentrant_observer_list) {
948 for (const Foo& nested_observer : reentrant_observer_list) {
949 std::ignore = observer;
950 std::ignore = nested_observer;
958 class TestCheckedObserver : public CheckedObserver {
960 explicit TestCheckedObserver(int* count) : count_(count) {}
961 TestCheckedObserver(const TestCheckedObserver&) = delete;
962 TestCheckedObserver& operator=(const TestCheckedObserver&) = delete;
964 void Observe() { ++(*count_); }
970 // A second, identical observer, used to test multiple inheritance.
971 class TestCheckedObserver2 : public CheckedObserver {
973 explicit TestCheckedObserver2(int* count) : count_(count) {}
974 TestCheckedObserver2(const TestCheckedObserver2&) = delete;
975 TestCheckedObserver2& operator=(const TestCheckedObserver2&) = delete;
977 void Observe() { ++(*count_); }
983 using CheckedObserverListTest = ::testing::Test;
985 // Test Observers that CHECK() when a UAF might otherwise occur.
986 TEST_F(CheckedObserverListTest, CheckedObserver) {
987 // See comments below about why this is unique_ptr.
988 auto list = std::make_unique<ObserverList<TestCheckedObserver>>();
991 TestCheckedObserver l1(&count1);
992 list->AddObserver(&l1);
994 TestCheckedObserver l2(&count2);
995 list->AddObserver(&l2);
996 for (auto& observer : *list)
998 EXPECT_EQ(1, count1);
999 EXPECT_EQ(1, count2);
1002 auto it = list->begin();
1004 // For CheckedObservers, a CHECK() occurs when advancing the iterator. (On
1005 // calling the observer method would be too late since the pointer would
1006 // already be null by then).
1007 EXPECT_CHECK_DEATH(it++);
1009 // On the non-death fork, no UAF occurs since the deleted observer is never
1010 // notified, but also the observer list still has |l2| in it. Check that.
1011 list->RemoveObserver(&l1);
1012 EXPECT_TRUE(!list->empty());
1014 // Now (in the non-death fork()) there's a problem. To delete |it|, we need
1015 // to compact the list, but that needs to iterate, which would CHECK again.
1016 // We can't remove |l2| (it's null). But we can delete |list|, which makes
1017 // the weak pointer in the iterator itself null.
1020 EXPECT_EQ(2, count1);
1021 EXPECT_EQ(1, count2);
1024 class MultiObserver : public TestCheckedObserver,
1025 public TestCheckedObserver2,
1026 public AdderT<UncheckedBase> {
1028 MultiObserver(int* checked_count, int* two_count)
1029 : TestCheckedObserver(checked_count),
1030 TestCheckedObserver2(two_count),
1034 // Test that observers behave as expected when observing multiple interfaces
1035 // with different traits.
1036 TEST_F(CheckedObserverListTest, MultiObserver) {
1037 // Observe two checked observer lists. This is to ensure the WeakPtrFactory
1038 // in CheckedObserver can correctly service multiple ObserverLists.
1039 ObserverList<TestCheckedObserver> checked_list;
1040 ObserverList<TestCheckedObserver2> two_list;
1042 ObserverList<UncheckedBase>::Unchecked unsafe_list;
1046 auto multi_observer = std::make_unique<MultiObserver>(&counts[0], &counts[1]);
1047 two_list.AddObserver(multi_observer.get());
1048 checked_list.AddObserver(multi_observer.get());
1049 unsafe_list.AddObserver(multi_observer.get());
1051 auto iterate_over = [](auto* list) {
1052 for (auto& observer : *list)
1055 iterate_over(&two_list);
1056 iterate_over(&checked_list);
1057 for (auto& observer : unsafe_list)
1058 observer.Observe(10);
1060 EXPECT_EQ(10, multi_observer->GetValue());
1061 for (const auto& count : counts)
1062 EXPECT_EQ(1, count);
1064 unsafe_list.RemoveObserver(multi_observer.get()); // Avoid a use-after-free.
1066 multi_observer.reset();
1067 EXPECT_CHECK_DEATH(iterate_over(&checked_list));
1069 for (const auto& count : counts)
1070 EXPECT_EQ(1, count);