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"
6 #include "base/observer_list_threadsafe.h"
12 #include "base/bind.h"
13 #include "base/compiler_specific.h"
14 #include "base/location.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/run_loop.h"
18 #include "base/sequenced_task_runner.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/synchronization/waitable_event.h"
21 #include "base/task_scheduler/post_task.h"
22 #include "base/task_scheduler/task_scheduler.h"
23 #include "base/test/gtest_util.h"
24 #include "base/test/scoped_task_environment.h"
25 #include "base/threading/platform_thread.h"
26 #include "base/threading/thread_restrictions.h"
27 #include "build/build_config.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
36 virtual void Observe(int x) = 0;
37 virtual ~Foo() = default;
38 virtual int GetValue() const { return 0; }
41 class Adder : public Foo {
43 explicit Adder(int scaler) : total(0), scaler_(scaler) {}
44 ~Adder() override = default;
46 void Observe(int x) override { total += x * scaler_; }
47 int GetValue() const override { return total; }
55 class Disrupter : public Foo {
57 Disrupter(ObserverList<Foo>* list, Foo* doomed, bool remove_self)
58 : list_(list), doomed_(doomed), remove_self_(remove_self) {}
59 Disrupter(ObserverList<Foo>* list, Foo* doomed)
60 : Disrupter(list, doomed, false) {}
61 Disrupter(ObserverList<Foo>* list, bool remove_self)
62 : Disrupter(list, nullptr, remove_self) {}
64 ~Disrupter() override = default;
66 void Observe(int x) override {
68 list_->RemoveObserver(this);
70 list_->RemoveObserver(doomed_);
73 void SetDoomed(Foo* doomed) { doomed_ = doomed; }
76 ObserverList<Foo>* list_;
81 template <typename ObserverListType>
82 class AddInObserve : public Foo {
84 explicit AddInObserve(ObserverListType* observer_list)
85 : observer_list(observer_list), to_add_() {}
87 void SetToAdd(Foo* to_add) { to_add_ = to_add; }
89 void Observe(int x) override {
91 observer_list->AddObserver(to_add_);
96 ObserverListType* observer_list;
101 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test.
103 // A thread for use in the ThreadSafeObserver test
104 // which will add and remove itself from the notification
106 class AddRemoveThread : public PlatformThread::Delegate,
109 AddRemoveThread(ObserverListThreadSafe<Foo>* list,
111 WaitableEvent* ready)
118 do_notifies_(notify),
120 weak_factory_(this) {}
122 ~AddRemoveThread() override = default;
124 void ThreadMain() override {
125 loop_ = new MessageLoop(); // Fire up a message loop.
126 loop_->task_runner()->PostTask(
128 base::BindOnce(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
130 // After ready_ is signaled, loop_ is only accessed by the main test thread
131 // (i.e. not this thread) in particular by Quit() which causes Run() to
132 // return, and we "control" loop_ again.
134 quit_loop_ = run_loop.QuitClosure();
137 loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef);
141 // This task just keeps posting to itself in an attempt
142 // to race with the notifier.
146 if ((Time::Now() - start_).InMilliseconds() > kThreadRunTime) {
152 list_->AddObserver(this);
157 list_->Notify(FROM_HERE, &Foo::Observe, 10);
160 loop_->task_runner()->PostTask(
162 base::BindOnce(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
165 // This function is only callable from the main thread.
166 void Quit() { std::move(quit_loop_).Run(); }
168 void Observe(int x) override {
171 // If we're getting called after we removed ourselves from
172 // the list, that is very bad!
175 // This callback should fire on the appropriate thread
176 EXPECT_EQ(loop_, MessageLoop::current());
178 list_->RemoveObserver(this);
183 ObserverListThreadSafe<Foo>* list_;
185 bool in_list_; // Are we currently registered for notifications.
186 // in_list_ is only used on |this| thread.
187 Time start_; // The time we started the test.
189 int count_observes_; // Number of times we observed.
190 int count_addtask_; // Number of times thread AddTask was called
191 bool do_notifies_; // Whether these threads should do notifications.
192 WaitableEvent* ready_;
194 base::OnceClosure quit_loop_;
196 base::WeakPtrFactory<AddRemoveThread> weak_factory_;
201 TEST(ObserverListTest, BasicTest) {
202 ObserverList<Foo> observer_list;
203 const ObserverList<Foo>& const_observer_list = observer_list;
206 const ObserverList<Foo>::const_iterator it1 = const_observer_list.begin();
207 EXPECT_EQ(it1, const_observer_list.end());
209 const ObserverList<Foo>::const_iterator it2 = it1;
211 // Iterator assignment.
212 ObserverList<Foo>::const_iterator it3;
217 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
223 const ObserverList<Foo>::iterator it1 = observer_list.begin();
224 EXPECT_EQ(it1, observer_list.end());
226 const ObserverList<Foo>::iterator it2 = it1;
228 // Iterator assignment.
229 ObserverList<Foo>::iterator it3;
234 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
239 Adder a(1), b(-1), c(1), d(-1), e(-1);
240 Disrupter evil(&observer_list, &c);
242 observer_list.AddObserver(&a);
243 observer_list.AddObserver(&b);
245 EXPECT_TRUE(const_observer_list.HasObserver(&a));
246 EXPECT_FALSE(const_observer_list.HasObserver(&c));
249 const ObserverList<Foo>::const_iterator it1 = const_observer_list.begin();
250 EXPECT_NE(it1, const_observer_list.end());
252 const ObserverList<Foo>::const_iterator it2 = it1;
254 EXPECT_NE(it2, const_observer_list.end());
255 // Iterator assignment.
256 ObserverList<Foo>::const_iterator it3;
261 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
264 // Iterator post increment.
265 ObserverList<Foo>::const_iterator it4 = it3++;
272 const ObserverList<Foo>::iterator it1 = observer_list.begin();
273 EXPECT_NE(it1, observer_list.end());
275 const ObserverList<Foo>::iterator it2 = it1;
277 EXPECT_NE(it2, observer_list.end());
278 // Iterator assignment.
279 ObserverList<Foo>::iterator it3;
284 it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
287 // Iterator post increment.
288 ObserverList<Foo>::iterator it4 = it3++;
294 for (auto& observer : observer_list)
295 observer.Observe(10);
297 observer_list.AddObserver(&evil);
298 observer_list.AddObserver(&c);
299 observer_list.AddObserver(&d);
301 // Removing an observer not in the list should do nothing.
302 observer_list.RemoveObserver(&e);
304 for (auto& observer : observer_list)
305 observer.Observe(10);
307 EXPECT_EQ(20, a.total);
308 EXPECT_EQ(-20, b.total);
309 EXPECT_EQ(0, c.total);
310 EXPECT_EQ(-10, d.total);
311 EXPECT_EQ(0, e.total);
314 TEST(ObserverListTest, CompactsWhenNoActiveIterator) {
315 ObserverList<const Foo> ol;
316 const ObserverList<const Foo>& col = ol;
325 EXPECT_TRUE(col.HasObserver(&a));
326 EXPECT_FALSE(col.HasObserver(&c));
328 EXPECT_TRUE(col.might_have_observers());
330 using It = ObserverList<const Foo>::const_iterator;
334 EXPECT_NE(it, col.end());
337 EXPECT_NE(++it, col.end());
341 EXPECT_EQ(++it, col.end());
343 EXPECT_TRUE(col.might_have_observers());
344 EXPECT_EQ(&*ita, &a);
345 EXPECT_EQ(&*itb, &b);
347 ol.RemoveObserver(&a);
348 EXPECT_TRUE(col.might_have_observers());
349 EXPECT_FALSE(col.HasObserver(&a));
350 EXPECT_EQ(&*itb, &b);
352 ol.RemoveObserver(&b);
353 EXPECT_TRUE(col.might_have_observers());
354 EXPECT_FALSE(col.HasObserver(&a));
355 EXPECT_FALSE(col.HasObserver(&b));
359 EXPECT_TRUE(col.might_have_observers());
362 EXPECT_TRUE(col.might_have_observers());
364 EXPECT_FALSE(col.might_have_observers());
369 EXPECT_TRUE(col.might_have_observers());
371 EXPECT_FALSE(col.might_have_observers());
375 EXPECT_TRUE(col.might_have_observers());
377 const It it = col.begin();
379 EXPECT_TRUE(col.might_have_observers());
381 EXPECT_FALSE(col.might_have_observers());
384 TEST(ObserverListTest, DisruptSelf) {
385 ObserverList<Foo> observer_list;
386 Adder a(1), b(-1), c(1), d(-1);
387 Disrupter evil(&observer_list, true);
389 observer_list.AddObserver(&a);
390 observer_list.AddObserver(&b);
392 for (auto& observer : observer_list)
393 observer.Observe(10);
395 observer_list.AddObserver(&evil);
396 observer_list.AddObserver(&c);
397 observer_list.AddObserver(&d);
399 for (auto& observer : observer_list)
400 observer.Observe(10);
402 EXPECT_EQ(20, a.total);
403 EXPECT_EQ(-20, b.total);
404 EXPECT_EQ(10, c.total);
405 EXPECT_EQ(-10, d.total);
408 TEST(ObserverListTest, DisruptBefore) {
409 ObserverList<Foo> observer_list;
410 Adder a(1), b(-1), c(1), d(-1);
411 Disrupter evil(&observer_list, &b);
413 observer_list.AddObserver(&a);
414 observer_list.AddObserver(&b);
415 observer_list.AddObserver(&evil);
416 observer_list.AddObserver(&c);
417 observer_list.AddObserver(&d);
419 for (auto& observer : observer_list)
420 observer.Observe(10);
421 for (auto& observer : observer_list)
422 observer.Observe(10);
424 EXPECT_EQ(20, a.total);
425 EXPECT_EQ(-10, b.total);
426 EXPECT_EQ(20, c.total);
427 EXPECT_EQ(-20, d.total);
430 TEST(ObserverListThreadSafeTest, BasicTest) {
433 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
434 new ObserverListThreadSafe<Foo>);
440 observer_list->AddObserver(&a);
441 observer_list->AddObserver(&b);
443 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
444 RunLoop().RunUntilIdle();
446 observer_list->AddObserver(&c);
447 observer_list->AddObserver(&d);
449 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
450 observer_list->RemoveObserver(&c);
451 RunLoop().RunUntilIdle();
453 EXPECT_EQ(20, a.total);
454 EXPECT_EQ(-20, b.total);
455 EXPECT_EQ(0, c.total);
456 EXPECT_EQ(-10, d.total);
459 TEST(ObserverListThreadSafeTest, RemoveObserver) {
462 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
463 new ObserverListThreadSafe<Foo>);
466 // A workaround for the compiler bug. See http://crbug.com/121960.
469 // Should do nothing.
470 observer_list->RemoveObserver(&a);
471 observer_list->RemoveObserver(&b);
473 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
474 RunLoop().RunUntilIdle();
476 EXPECT_EQ(0, a.total);
477 EXPECT_EQ(0, b.total);
479 observer_list->AddObserver(&a);
481 // Should also do nothing.
482 observer_list->RemoveObserver(&b);
484 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
485 RunLoop().RunUntilIdle();
487 EXPECT_EQ(10, a.total);
488 EXPECT_EQ(0, b.total);
491 TEST(ObserverListThreadSafeTest, WithoutSequence) {
492 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
493 new ObserverListThreadSafe<Foo>);
495 Adder a(1), b(1), c(1);
497 // No sequence, so these should not be added.
498 observer_list->AddObserver(&a);
499 observer_list->AddObserver(&b);
502 // Add c when there's a sequence.
504 observer_list->AddObserver(&c);
506 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
507 RunLoop().RunUntilIdle();
509 EXPECT_EQ(0, a.total);
510 EXPECT_EQ(0, b.total);
511 EXPECT_EQ(10, c.total);
513 // Now add a when there's a sequence.
514 observer_list->AddObserver(&a);
516 // Remove c when there's a sequence.
517 observer_list->RemoveObserver(&c);
520 observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
521 RunLoop().RunUntilIdle();
523 EXPECT_EQ(20, a.total);
524 EXPECT_EQ(0, b.total);
525 EXPECT_EQ(10, c.total);
528 // Removing should always succeed with or without a sequence.
529 observer_list->RemoveObserver(&a);
531 // Notifying should not fail but should also be a no-op.
533 observer_list->AddObserver(&b);
534 observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
535 RunLoop().RunUntilIdle();
537 EXPECT_EQ(20, a.total);
538 EXPECT_EQ(30, b.total);
539 EXPECT_EQ(10, c.total);
542 class FooRemover : public Foo {
544 explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {}
545 ~FooRemover() override = default;
547 void AddFooToRemove(Foo* foo) {
548 foos_.push_back(foo);
551 void Observe(int x) override {
552 std::vector<Foo*> tmp;
554 for (std::vector<Foo*>::iterator it = tmp.begin();
555 it != tmp.end(); ++it) {
556 list_->RemoveObserver(*it);
561 const scoped_refptr<ObserverListThreadSafe<Foo> > list_;
562 std::vector<Foo*> foos_;
565 TEST(ObserverListThreadSafeTest, RemoveMultipleObservers) {
567 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
568 new ObserverListThreadSafe<Foo>);
570 FooRemover a(observer_list.get());
573 observer_list->AddObserver(&a);
574 observer_list->AddObserver(&b);
576 a.AddFooToRemove(&a);
577 a.AddFooToRemove(&b);
579 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
580 RunLoop().RunUntilIdle();
583 // A test driver for a multi-threaded notification loop. Runs a number
584 // of observer threads, each of which constantly adds/removes itself
585 // from the observer list. Optionally, if cross_thread_notifies is set
586 // to true, the observer threads will also trigger notifications to
588 static void ThreadSafeObserverHarness(int num_threads,
589 bool cross_thread_notifies) {
592 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
593 new ObserverListThreadSafe<Foo>);
597 observer_list->AddObserver(&a);
598 observer_list->AddObserver(&b);
600 std::vector<AddRemoveThread*> threaded_observer;
601 std::vector<base::PlatformThreadHandle> threads(num_threads);
602 std::vector<std::unique_ptr<base::WaitableEvent>> ready;
603 threaded_observer.reserve(num_threads);
604 ready.reserve(num_threads);
605 for (int index = 0; index < num_threads; index++) {
606 ready.push_back(std::make_unique<WaitableEvent>(
607 WaitableEvent::ResetPolicy::MANUAL,
608 WaitableEvent::InitialState::NOT_SIGNALED));
609 threaded_observer.push_back(new AddRemoveThread(
610 observer_list.get(), cross_thread_notifies, ready.back().get()));
612 PlatformThread::Create(0, threaded_observer.back(), &threads[index]));
614 ASSERT_EQ(static_cast<size_t>(num_threads), threaded_observer.size());
615 ASSERT_EQ(static_cast<size_t>(num_threads), ready.size());
617 // This makes sure that threaded_observer has gotten to set loop_, so that we
618 // can call Quit() below safe-ish-ly.
619 for (int i = 0; i < num_threads; ++i)
622 Time start = Time::Now();
624 if ((Time::Now() - start).InMilliseconds() > kThreadRunTime)
627 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
629 RunLoop().RunUntilIdle();
632 for (int index = 0; index < num_threads; index++) {
633 threaded_observer[index]->Quit();
634 PlatformThread::Join(threads[index]);
638 #if defined(OS_FUCHSIA)
639 // TODO(crbug.com/738275): This is flaky on Fuchsia.
640 #define MAYBE_CrossThreadObserver DISABLED_CrossThreadObserver
642 #define MAYBE_CrossThreadObserver CrossThreadObserver
644 TEST(ObserverListThreadSafeTest, MAYBE_CrossThreadObserver) {
645 // Use 7 observer threads. Notifications only come from
647 ThreadSafeObserverHarness(7, false);
650 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) {
651 // Use 3 observer threads. Notifications will fire from
652 // the main thread and all 3 observer threads.
653 ThreadSafeObserverHarness(3, true);
656 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) {
657 MessageLoop* loop = new MessageLoop;
658 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
659 new ObserverListThreadSafe<Foo>);
662 observer_list->AddObserver(&a);
664 // Test passes if we don't crash here.
665 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
670 class SequenceVerificationObserver : public Foo {
672 explicit SequenceVerificationObserver(
673 scoped_refptr<SequencedTaskRunner> task_runner)
674 : task_runner_(std::move(task_runner)) {}
675 ~SequenceVerificationObserver() override = default;
677 void Observe(int x) override {
678 called_on_valid_sequence_ = task_runner_->RunsTasksInCurrentSequence();
681 bool called_on_valid_sequence() const { return called_on_valid_sequence_; }
684 const scoped_refptr<SequencedTaskRunner> task_runner_;
685 bool called_on_valid_sequence_ = false;
687 DISALLOW_COPY_AND_ASSIGN(SequenceVerificationObserver);
692 // Verify that observers are notified on the correct sequence.
693 TEST(ObserverListThreadSafeTest, NotificationOnValidSequence) {
694 test::ScopedTaskEnvironment scoped_task_environment;
696 auto task_runner_1 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
697 auto task_runner_2 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
699 auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
701 SequenceVerificationObserver observer_1(task_runner_1);
702 SequenceVerificationObserver observer_2(task_runner_2);
704 task_runner_1->PostTask(FROM_HERE,
705 BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
706 observer_list, Unretained(&observer_1)));
707 task_runner_2->PostTask(FROM_HERE,
708 BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
709 observer_list, Unretained(&observer_2)));
711 TaskScheduler::GetInstance()->FlushForTesting();
713 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
715 TaskScheduler::GetInstance()->FlushForTesting();
717 EXPECT_TRUE(observer_1.called_on_valid_sequence());
718 EXPECT_TRUE(observer_2.called_on_valid_sequence());
721 // Verify that when an observer is added to a NOTIFY_ALL ObserverListThreadSafe
722 // from a notification, it is itself notified.
723 TEST(ObserverListThreadSafeTest, AddObserverFromNotificationNotifyAll) {
724 test::ScopedTaskEnvironment scoped_task_environment;
725 auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
727 Adder observer_added_from_notification(1);
729 AddInObserve<ObserverListThreadSafe<Foo>> initial_observer(
730 observer_list.get());
731 initial_observer.SetToAdd(&observer_added_from_notification);
732 observer_list->AddObserver(&initial_observer);
734 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
736 base::RunLoop().RunUntilIdle();
738 EXPECT_EQ(1, observer_added_from_notification.GetValue());
743 class RemoveWhileNotificationIsRunningObserver : public Foo {
745 RemoveWhileNotificationIsRunningObserver()
746 : notification_running_(WaitableEvent::ResetPolicy::AUTOMATIC,
747 WaitableEvent::InitialState::NOT_SIGNALED),
748 barrier_(WaitableEvent::ResetPolicy::AUTOMATIC,
749 WaitableEvent::InitialState::NOT_SIGNALED) {}
750 ~RemoveWhileNotificationIsRunningObserver() override = default;
752 void Observe(int x) override {
753 notification_running_.Signal();
754 ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
758 void WaitForNotificationRunning() { notification_running_.Wait(); }
759 void Unblock() { barrier_.Signal(); }
762 WaitableEvent notification_running_;
763 WaitableEvent barrier_;
765 DISALLOW_COPY_AND_ASSIGN(RemoveWhileNotificationIsRunningObserver);
770 // Verify that there is no crash when an observer is removed while it is being
772 TEST(ObserverListThreadSafeTest, RemoveWhileNotificationIsRunning) {
773 auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
774 RemoveWhileNotificationIsRunningObserver observer;
776 WaitableEvent task_running(WaitableEvent::ResetPolicy::AUTOMATIC,
777 WaitableEvent::InitialState::NOT_SIGNALED);
778 WaitableEvent barrier(WaitableEvent::ResetPolicy::AUTOMATIC,
779 WaitableEvent::InitialState::NOT_SIGNALED);
781 // This must be after the declaration of |barrier| so that tasks posted to
782 // TaskScheduler can safely use |barrier|.
783 test::ScopedTaskEnvironment scoped_task_environment;
785 CreateSequencedTaskRunnerWithTraits({})->PostTask(
786 FROM_HERE, base::BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
787 observer_list, Unretained(&observer)));
788 TaskScheduler::GetInstance()->FlushForTesting();
790 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
791 observer.WaitForNotificationRunning();
792 observer_list->RemoveObserver(&observer);
797 TEST(ObserverListTest, Existing) {
798 ObserverList<Foo> observer_list(ObserverListPolicy::EXISTING_ONLY);
800 AddInObserve<ObserverList<Foo> > b(&observer_list);
804 observer_list.AddObserver(&a);
805 observer_list.AddObserver(&b);
807 for (auto& observer : observer_list)
810 EXPECT_FALSE(b.to_add_);
811 // B's adder should not have been notified because it was added during
813 EXPECT_EQ(0, c.total);
815 // Notify again to make sure b's adder is notified.
816 for (auto& observer : observer_list)
818 EXPECT_EQ(1, c.total);
821 // Same as above, but for ObserverListThreadSafe
822 TEST(ObserverListThreadSafeTest, Existing) {
824 scoped_refptr<ObserverListThreadSafe<Foo>> observer_list(
825 new ObserverListThreadSafe<Foo>(ObserverListPolicy::EXISTING_ONLY));
827 AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get());
831 observer_list->AddObserver(&a);
832 observer_list->AddObserver(&b);
834 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
835 RunLoop().RunUntilIdle();
837 EXPECT_FALSE(b.to_add_);
838 // B's adder should not have been notified because it was added during
840 EXPECT_EQ(0, c.total);
842 // Notify again to make sure b's adder is notified.
843 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
844 RunLoop().RunUntilIdle();
845 EXPECT_EQ(1, c.total);
848 class AddInClearObserve : public Foo {
850 explicit AddInClearObserve(ObserverList<Foo>* list)
851 : list_(list), added_(false), adder_(1) {}
853 void Observe(int /* x */) override {
855 list_->AddObserver(&adder_);
859 bool added() const { return added_; }
860 const Adder& adder() const { return adder_; }
863 ObserverList<Foo>* const list_;
869 TEST(ObserverListTest, ClearNotifyAll) {
870 ObserverList<Foo> observer_list;
871 AddInClearObserve a(&observer_list);
873 observer_list.AddObserver(&a);
875 for (auto& observer : observer_list)
877 EXPECT_TRUE(a.added());
878 EXPECT_EQ(1, a.adder().total)
879 << "Adder should observe once and have sum of 1.";
882 TEST(ObserverListTest, ClearNotifyExistingOnly) {
883 ObserverList<Foo> observer_list(ObserverListPolicy::EXISTING_ONLY);
884 AddInClearObserve a(&observer_list);
886 observer_list.AddObserver(&a);
888 for (auto& observer : observer_list)
890 EXPECT_TRUE(a.added());
891 EXPECT_EQ(0, a.adder().total)
892 << "Adder should not observe, so sum should still be 0.";
895 class ListDestructor : public Foo {
897 explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {}
898 ~ListDestructor() override = default;
900 void Observe(int x) override { delete list_; }
903 ObserverList<Foo>* list_;
907 TEST(ObserverListTest, IteratorOutlivesList) {
908 ObserverList<Foo>* observer_list = new ObserverList<Foo>;
909 ListDestructor a(observer_list);
910 observer_list->AddObserver(&a);
912 for (auto& observer : *observer_list)
915 // There are no EXPECT* statements for this test, if we catch
916 // use-after-free errors for observer_list (eg with ASan) then
917 // this test has failed. See http://crbug.com/85296.
920 TEST(ObserverListTest, BasicStdIterator) {
921 using FooList = ObserverList<Foo>;
922 FooList observer_list;
924 // An optimization: begin() and end() do not involve weak pointers on
926 EXPECT_FALSE(observer_list.begin().list_);
927 EXPECT_FALSE(observer_list.end().list_);
929 // Iterate over empty list: no effect, no crash.
930 for (auto& i : observer_list)
933 Adder a(1), b(-1), c(1), d(-1);
935 observer_list.AddObserver(&a);
936 observer_list.AddObserver(&b);
937 observer_list.AddObserver(&c);
938 observer_list.AddObserver(&d);
940 for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
944 EXPECT_EQ(1, a.total);
945 EXPECT_EQ(-1, b.total);
946 EXPECT_EQ(1, c.total);
947 EXPECT_EQ(-1, d.total);
949 // Check an iteration over a 'const view' for a given container.
950 const FooList& const_list = observer_list;
951 for (FooList::const_iterator i = const_list.begin(), e = const_list.end();
953 EXPECT_EQ(1, std::abs(i->GetValue()));
956 for (const auto& o : const_list)
957 EXPECT_EQ(1, std::abs(o.GetValue()));
960 TEST(ObserverListTest, StdIteratorRemoveItself) {
961 ObserverList<Foo> observer_list;
962 Adder a(1), b(-1), c(1), d(-1);
963 Disrupter disrupter(&observer_list, true);
965 observer_list.AddObserver(&a);
966 observer_list.AddObserver(&b);
967 observer_list.AddObserver(&disrupter);
968 observer_list.AddObserver(&c);
969 observer_list.AddObserver(&d);
971 for (auto& o : observer_list)
974 for (auto& o : observer_list)
977 EXPECT_EQ(11, a.total);
978 EXPECT_EQ(-11, b.total);
979 EXPECT_EQ(11, c.total);
980 EXPECT_EQ(-11, d.total);
983 TEST(ObserverListTest, StdIteratorRemoveBefore) {
984 ObserverList<Foo> observer_list;
985 Adder a(1), b(-1), c(1), d(-1);
986 Disrupter disrupter(&observer_list, &b);
988 observer_list.AddObserver(&a);
989 observer_list.AddObserver(&b);
990 observer_list.AddObserver(&disrupter);
991 observer_list.AddObserver(&c);
992 observer_list.AddObserver(&d);
994 for (auto& o : observer_list)
997 for (auto& o : observer_list)
1000 EXPECT_EQ(11, a.total);
1001 EXPECT_EQ(-1, b.total);
1002 EXPECT_EQ(11, c.total);
1003 EXPECT_EQ(-11, d.total);
1006 TEST(ObserverListTest, StdIteratorRemoveAfter) {
1007 ObserverList<Foo> observer_list;
1008 Adder a(1), b(-1), c(1), d(-1);
1009 Disrupter disrupter(&observer_list, &c);
1011 observer_list.AddObserver(&a);
1012 observer_list.AddObserver(&b);
1013 observer_list.AddObserver(&disrupter);
1014 observer_list.AddObserver(&c);
1015 observer_list.AddObserver(&d);
1017 for (auto& o : observer_list)
1020 for (auto& o : observer_list)
1023 EXPECT_EQ(11, a.total);
1024 EXPECT_EQ(-11, b.total);
1025 EXPECT_EQ(0, c.total);
1026 EXPECT_EQ(-11, d.total);
1029 TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
1030 ObserverList<Foo> observer_list;
1031 Adder a(1), b(-1), c(1), d(-1);
1032 Disrupter disrupter(&observer_list, &a);
1034 observer_list.AddObserver(&a);
1035 observer_list.AddObserver(&disrupter);
1036 observer_list.AddObserver(&b);
1037 observer_list.AddObserver(&c);
1038 observer_list.AddObserver(&d);
1040 for (auto& o : observer_list)
1043 for (auto& o : observer_list)
1046 EXPECT_EQ(1, a.total);
1047 EXPECT_EQ(-11, b.total);
1048 EXPECT_EQ(11, c.total);
1049 EXPECT_EQ(-11, d.total);
1052 TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
1053 ObserverList<Foo> observer_list;
1054 Adder a(1), b(-1), c(1), d(-1);
1055 Disrupter disrupter(&observer_list, &d);
1057 observer_list.AddObserver(&a);
1058 observer_list.AddObserver(&b);
1059 observer_list.AddObserver(&c);
1060 observer_list.AddObserver(&disrupter);
1061 observer_list.AddObserver(&d);
1063 for (auto& o : observer_list)
1066 for (auto& o : observer_list)
1069 EXPECT_EQ(11, a.total);
1070 EXPECT_EQ(-11, b.total);
1071 EXPECT_EQ(11, c.total);
1072 EXPECT_EQ(0, d.total);
1075 TEST(ObserverListTest, StdIteratorRemoveFront) {
1076 using FooList = ObserverList<Foo>;
1077 FooList observer_list;
1078 Adder a(1), b(-1), c(1), d(-1);
1079 Disrupter disrupter(&observer_list, true);
1081 observer_list.AddObserver(&disrupter);
1082 observer_list.AddObserver(&a);
1083 observer_list.AddObserver(&b);
1084 observer_list.AddObserver(&c);
1085 observer_list.AddObserver(&d);
1087 bool test_disruptor = true;
1088 for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
1091 // Check that second call to i->Observe() would crash here.
1092 if (test_disruptor) {
1093 EXPECT_FALSE(i.GetCurrent());
1094 test_disruptor = false;
1098 for (auto& o : observer_list)
1101 EXPECT_EQ(11, a.total);
1102 EXPECT_EQ(-11, b.total);
1103 EXPECT_EQ(11, c.total);
1104 EXPECT_EQ(-11, d.total);
1107 TEST(ObserverListTest, StdIteratorRemoveBack) {
1108 ObserverList<Foo> observer_list;
1109 Adder a(1), b(-1), c(1), d(-1);
1110 Disrupter disrupter(&observer_list, true);
1112 observer_list.AddObserver(&a);
1113 observer_list.AddObserver(&b);
1114 observer_list.AddObserver(&c);
1115 observer_list.AddObserver(&d);
1116 observer_list.AddObserver(&disrupter);
1118 for (auto& o : observer_list)
1121 for (auto& o : observer_list)
1124 EXPECT_EQ(11, a.total);
1125 EXPECT_EQ(-11, b.total);
1126 EXPECT_EQ(11, c.total);
1127 EXPECT_EQ(-11, d.total);
1130 TEST(ObserverListTest, NestedLoop) {
1131 ObserverList<Foo> observer_list;
1132 Adder a(1), b(-1), c(1), d(-1);
1133 Disrupter disrupter(&observer_list, true);
1135 observer_list.AddObserver(&disrupter);
1136 observer_list.AddObserver(&a);
1137 observer_list.AddObserver(&b);
1138 observer_list.AddObserver(&c);
1139 observer_list.AddObserver(&d);
1141 for (auto& o : observer_list) {
1144 for (auto& o : observer_list)
1148 EXPECT_EQ(15, a.total);
1149 EXPECT_EQ(-15, b.total);
1150 EXPECT_EQ(15, c.total);
1151 EXPECT_EQ(-15, d.total);
1154 TEST(ObserverListTest, NonCompactList) {
1155 ObserverList<Foo> observer_list;
1158 Disrupter disrupter1(&observer_list, true);
1159 Disrupter disrupter2(&observer_list, true);
1161 // Disrupt itself and another one.
1162 disrupter1.SetDoomed(&disrupter2);
1164 observer_list.AddObserver(&disrupter1);
1165 observer_list.AddObserver(&disrupter2);
1166 observer_list.AddObserver(&a);
1167 observer_list.AddObserver(&b);
1169 for (auto& o : observer_list) {
1170 // Get the { nullptr, nullptr, &a, &b } non-compact list
1171 // on the first inner pass.
1174 for (auto& o : observer_list)
1178 EXPECT_EQ(13, a.total);
1179 EXPECT_EQ(-13, b.total);
1182 TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
1183 ObserverList<Foo> observer_list;
1186 Disrupter disrupter1(&observer_list, true);
1187 Disrupter disrupter2(&observer_list, true);
1189 // Disrupt itself and another one.
1190 disrupter1.SetDoomed(&disrupter2);
1192 observer_list.AddObserver(&disrupter1);
1193 observer_list.AddObserver(&disrupter2);
1195 bool add_observers = true;
1196 for (auto& o : observer_list) {
1197 // Get the { nullptr, nullptr } empty list on the first inner pass.
1200 for (auto& o : observer_list)
1203 if (add_observers) {
1204 observer_list.AddObserver(&a);
1205 observer_list.AddObserver(&b);
1206 add_observers = false;
1210 EXPECT_EQ(12, a.total);
1211 EXPECT_EQ(-12, b.total);
1214 TEST(ObserverListTest, AddObserverInTheLastObserve) {
1215 using FooList = ObserverList<Foo>;
1216 FooList observer_list;
1218 AddInObserve<FooList> a(&observer_list);
1222 observer_list.AddObserver(&a);
1224 auto it = observer_list.begin();
1225 while (it != observer_list.end()) {
1226 auto& observer = *it;
1227 // Intentionally increment the iterator before calling Observe(). The
1228 // ObserverList starts with only one observer, and it == observer_list.end()
1229 // should be true after the next line.
1231 // However, the first Observe() call will add a second observer: at this
1232 // point, it != observer_list.end() should be true, and Observe() should be
1233 // called on the newly added observer on the next iteration of the loop.
1234 observer.Observe(10);
1237 EXPECT_EQ(-10, b.total);
1240 class MockLogAssertHandler {
1244 void(const char*, int, const base::StringPiece, const base::StringPiece));
1248 TEST(ObserverListTest, NonReentrantObserverList) {
1251 ObserverList<Foo, /*check_empty=*/false, /*allow_reentrancy=*/false>
1252 non_reentrant_observer_list;
1254 non_reentrant_observer_list.AddObserver(&a);
1256 EXPECT_DCHECK_DEATH({
1257 for (const Foo& a : non_reentrant_observer_list) {
1258 for (const Foo& b : non_reentrant_observer_list) {
1266 TEST(ObserverListTest, ReentrantObserverList) {
1269 ReentrantObserverList<Foo> reentrant_observer_list;
1271 reentrant_observer_list.AddObserver(&a);
1272 bool passed = false;
1273 for (const Foo& a : reentrant_observer_list) {
1274 for (const Foo& b : reentrant_observer_list) {
1280 EXPECT_TRUE(passed);