• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "base/observer_list.h"
6 #include "base/observer_list_threadsafe.h"
7 
8 #include <memory>
9 #include <utility>
10 #include <vector>
11 
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/strings/string_piece.h"
21 #include "base/synchronization/waitable_event.h"
22 // TaskScheduler not supported in libchrome
23 // #include "base/task_scheduler/post_task.h"
24 // #include "base/task_scheduler/task_scheduler.h"
25 #include "base/test/gtest_util.h"
26 #include "base/test/scoped_task_environment.h"
27 #include "base/threading/platform_thread.h"
28 #include "base/threading/thread_restrictions.h"
29 #include "build/build_config.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 
33 namespace base {
34 namespace {
35 
36 class Foo {
37  public:
38   virtual void Observe(int x) = 0;
39   virtual ~Foo() = default;
GetValue() const40   virtual int GetValue() const { return 0; }
41 };
42 
43 class Adder : public Foo {
44  public:
Adder(int scaler)45   explicit Adder(int scaler) : total(0), scaler_(scaler) {}
46   ~Adder() override = default;
47 
Observe(int x)48   void Observe(int x) override { total += x * scaler_; }
GetValue() const49   int GetValue() const override { return total; }
50 
51   int total;
52 
53  private:
54   int scaler_;
55 };
56 
57 class Disrupter : public Foo {
58  public:
Disrupter(ObserverList<Foo> * list,Foo * doomed,bool remove_self)59   Disrupter(ObserverList<Foo>* list, Foo* doomed, bool remove_self)
60       : list_(list), doomed_(doomed), remove_self_(remove_self) {}
Disrupter(ObserverList<Foo> * list,Foo * doomed)61   Disrupter(ObserverList<Foo>* list, Foo* doomed)
62       : Disrupter(list, doomed, false) {}
Disrupter(ObserverList<Foo> * list,bool remove_self)63   Disrupter(ObserverList<Foo>* list, bool remove_self)
64       : Disrupter(list, nullptr, remove_self) {}
65 
66   ~Disrupter() override = default;
67 
Observe(int x)68   void Observe(int x) override {
69     if (remove_self_)
70       list_->RemoveObserver(this);
71     if (doomed_)
72       list_->RemoveObserver(doomed_);
73   }
74 
SetDoomed(Foo * doomed)75   void SetDoomed(Foo* doomed) { doomed_ = doomed; }
76 
77  private:
78   ObserverList<Foo>* list_;
79   Foo* doomed_;
80   bool remove_self_;
81 };
82 
83 template <typename ObserverListType>
84 class AddInObserve : public Foo {
85  public:
AddInObserve(ObserverListType * observer_list)86   explicit AddInObserve(ObserverListType* observer_list)
87       : observer_list(observer_list), to_add_() {}
88 
SetToAdd(Foo * to_add)89   void SetToAdd(Foo* to_add) { to_add_ = to_add; }
90 
Observe(int x)91   void Observe(int x) override {
92     if (to_add_) {
93       observer_list->AddObserver(to_add_);
94       to_add_ = nullptr;
95     }
96   }
97 
98   ObserverListType* observer_list;
99   Foo* to_add_;
100 };
101 
102 
103 static const int kThreadRunTime = 2000;  // ms to run the multi-threaded test.
104 
105 // A thread for use in the ThreadSafeObserver test
106 // which will add and remove itself from the notification
107 // list repeatedly.
108 class AddRemoveThread : public PlatformThread::Delegate,
109                         public Foo {
110  public:
AddRemoveThread(ObserverListThreadSafe<Foo> * list,bool notify,WaitableEvent * ready)111   AddRemoveThread(ObserverListThreadSafe<Foo>* list,
112                   bool notify,
113                   WaitableEvent* ready)
114       : list_(list),
115         loop_(nullptr),
116         in_list_(false),
117         start_(Time::Now()),
118         count_observes_(0),
119         count_addtask_(0),
120         do_notifies_(notify),
121         ready_(ready),
122         weak_factory_(this) {}
123 
124   ~AddRemoveThread() override = default;
125 
ThreadMain()126   void ThreadMain() override {
127     loop_ = new MessageLoop();  // Fire up a message loop.
128     loop_->task_runner()->PostTask(
129         FROM_HERE,
130         base::BindOnce(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
131     ready_->Signal();
132     // After ready_ is signaled, loop_ is only accessed by the main test thread
133     // (i.e. not this thread) in particular by Quit() which causes Run() to
134     // return, and we "control" loop_ again.
135     RunLoop run_loop;
136     quit_loop_ = run_loop.QuitClosure();
137     run_loop.Run();
138     delete loop_;
139     loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef);
140     delete this;
141   }
142 
143   // This task just keeps posting to itself in an attempt
144   // to race with the notifier.
AddTask()145   void AddTask() {
146     count_addtask_++;
147 
148     if ((Time::Now() - start_).InMilliseconds() > kThreadRunTime) {
149       VLOG(1) << "DONE!";
150       return;
151     }
152 
153     if (!in_list_) {
154       list_->AddObserver(this);
155       in_list_ = true;
156     }
157 
158     if (do_notifies_) {
159       list_->Notify(FROM_HERE, &Foo::Observe, 10);
160     }
161 
162     loop_->task_runner()->PostTask(
163         FROM_HERE,
164         base::BindOnce(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
165   }
166 
167   // This function is only callable from the main thread.
Quit()168   void Quit() { std::move(quit_loop_).Run(); }
169 
Observe(int x)170   void Observe(int x) override {
171     count_observes_++;
172 
173     // If we're getting called after we removed ourselves from
174     // the list, that is very bad!
175     DCHECK(in_list_);
176 
177     // This callback should fire on the appropriate thread
178     EXPECT_EQ(loop_, MessageLoop::current());
179 
180     list_->RemoveObserver(this);
181     in_list_ = false;
182   }
183 
184  private:
185   ObserverListThreadSafe<Foo>* list_;
186   MessageLoop* loop_;
187   bool in_list_;        // Are we currently registered for notifications.
188                         // in_list_ is only used on |this| thread.
189   Time start_;          // The time we started the test.
190 
191   int count_observes_;  // Number of times we observed.
192   int count_addtask_;   // Number of times thread AddTask was called
193   bool do_notifies_;    // Whether these threads should do notifications.
194   WaitableEvent* ready_;
195 
196   base::OnceClosure quit_loop_;
197 
198   base::WeakPtrFactory<AddRemoveThread> weak_factory_;
199 };
200 
201 }  // namespace
202 
TEST(ObserverListTest,BasicTest)203 TEST(ObserverListTest, BasicTest) {
204   ObserverList<Foo> observer_list;
205   const ObserverList<Foo>& const_observer_list = observer_list;
206 
207   {
208     const ObserverList<Foo>::const_iterator it1 = const_observer_list.begin();
209     EXPECT_EQ(it1, const_observer_list.end());
210     // Iterator copy.
211     const ObserverList<Foo>::const_iterator it2 = it1;
212     EXPECT_EQ(it2, it1);
213     // Iterator assignment.
214     ObserverList<Foo>::const_iterator it3;
215     it3 = it2;
216     EXPECT_EQ(it3, it1);
217     EXPECT_EQ(it3, it2);
218     // Self assignment.
219     it3 = *&it3;  // The *& defeats Clang's -Wself-assign warning.
220     EXPECT_EQ(it3, it1);
221     EXPECT_EQ(it3, it2);
222   }
223 
224   {
225     const ObserverList<Foo>::iterator it1 = observer_list.begin();
226     EXPECT_EQ(it1, observer_list.end());
227     // Iterator copy.
228     const ObserverList<Foo>::iterator it2 = it1;
229     EXPECT_EQ(it2, it1);
230     // Iterator assignment.
231     ObserverList<Foo>::iterator it3;
232     it3 = it2;
233     EXPECT_EQ(it3, it1);
234     EXPECT_EQ(it3, it2);
235     // Self assignment.
236     it3 = *&it3;  // The *& defeats Clang's -Wself-assign warning.
237     EXPECT_EQ(it3, it1);
238     EXPECT_EQ(it3, it2);
239   }
240 
241   Adder a(1), b(-1), c(1), d(-1), e(-1);
242   Disrupter evil(&observer_list, &c);
243 
244   observer_list.AddObserver(&a);
245   observer_list.AddObserver(&b);
246 
247   EXPECT_TRUE(const_observer_list.HasObserver(&a));
248   EXPECT_FALSE(const_observer_list.HasObserver(&c));
249 
250   {
251     const ObserverList<Foo>::const_iterator it1 = const_observer_list.begin();
252     EXPECT_NE(it1, const_observer_list.end());
253     // Iterator copy.
254     const ObserverList<Foo>::const_iterator it2 = it1;
255     EXPECT_EQ(it2, it1);
256     EXPECT_NE(it2, const_observer_list.end());
257     // Iterator assignment.
258     ObserverList<Foo>::const_iterator it3;
259     it3 = it2;
260     EXPECT_EQ(it3, it1);
261     EXPECT_EQ(it3, it2);
262     // Self assignment.
263     it3 = *&it3;  // The *& defeats Clang's -Wself-assign warning.
264     EXPECT_EQ(it3, it1);
265     EXPECT_EQ(it3, it2);
266     // Iterator post increment.
267     ObserverList<Foo>::const_iterator it4 = it3++;
268     EXPECT_EQ(it4, it1);
269     EXPECT_EQ(it4, it2);
270     EXPECT_NE(it4, it3);
271   }
272 
273   {
274     const ObserverList<Foo>::iterator it1 = observer_list.begin();
275     EXPECT_NE(it1, observer_list.end());
276     // Iterator copy.
277     const ObserverList<Foo>::iterator it2 = it1;
278     EXPECT_EQ(it2, it1);
279     EXPECT_NE(it2, observer_list.end());
280     // Iterator assignment.
281     ObserverList<Foo>::iterator it3;
282     it3 = it2;
283     EXPECT_EQ(it3, it1);
284     EXPECT_EQ(it3, it2);
285     // Self assignment.
286     it3 = *&it3;  // The *& defeats Clang's -Wself-assign warning.
287     EXPECT_EQ(it3, it1);
288     EXPECT_EQ(it3, it2);
289     // Iterator post increment.
290     ObserverList<Foo>::iterator it4 = it3++;
291     EXPECT_EQ(it4, it1);
292     EXPECT_EQ(it4, it2);
293     EXPECT_NE(it4, it3);
294   }
295 
296   for (auto& observer : observer_list)
297     observer.Observe(10);
298 
299   observer_list.AddObserver(&evil);
300   observer_list.AddObserver(&c);
301   observer_list.AddObserver(&d);
302 
303   // Removing an observer not in the list should do nothing.
304   observer_list.RemoveObserver(&e);
305 
306   for (auto& observer : observer_list)
307     observer.Observe(10);
308 
309   EXPECT_EQ(20, a.total);
310   EXPECT_EQ(-20, b.total);
311   EXPECT_EQ(0, c.total);
312   EXPECT_EQ(-10, d.total);
313   EXPECT_EQ(0, e.total);
314 }
315 
TEST(ObserverListTest,CompactsWhenNoActiveIterator)316 TEST(ObserverListTest, CompactsWhenNoActiveIterator) {
317   ObserverList<const Foo> ol;
318   const ObserverList<const Foo>& col = ol;
319 
320   const Adder a(1);
321   const Adder b(2);
322   const Adder c(3);
323 
324   ol.AddObserver(&a);
325   ol.AddObserver(&b);
326 
327   EXPECT_TRUE(col.HasObserver(&a));
328   EXPECT_FALSE(col.HasObserver(&c));
329 
330   EXPECT_TRUE(col.might_have_observers());
331 
332   using It = ObserverList<const Foo>::const_iterator;
333 
334   {
335     It it = col.begin();
336     EXPECT_NE(it, col.end());
337     It ita = it;
338     EXPECT_EQ(ita, it);
339     EXPECT_NE(++it, col.end());
340     EXPECT_NE(ita, it);
341     It itb = it;
342     EXPECT_EQ(itb, it);
343     EXPECT_EQ(++it, col.end());
344 
345     EXPECT_TRUE(col.might_have_observers());
346     EXPECT_EQ(&*ita, &a);
347     EXPECT_EQ(&*itb, &b);
348 
349     ol.RemoveObserver(&a);
350     EXPECT_TRUE(col.might_have_observers());
351     EXPECT_FALSE(col.HasObserver(&a));
352     EXPECT_EQ(&*itb, &b);
353 
354     ol.RemoveObserver(&b);
355     EXPECT_TRUE(col.might_have_observers());
356     EXPECT_FALSE(col.HasObserver(&a));
357     EXPECT_FALSE(col.HasObserver(&b));
358 
359     it = It();
360     ita = It();
361     EXPECT_TRUE(col.might_have_observers());
362     ita = itb;
363     itb = It();
364     EXPECT_TRUE(col.might_have_observers());
365     ita = It();
366     EXPECT_FALSE(col.might_have_observers());
367   }
368 
369   ol.AddObserver(&a);
370   ol.AddObserver(&b);
371   EXPECT_TRUE(col.might_have_observers());
372   ol.Clear();
373   EXPECT_FALSE(col.might_have_observers());
374 
375   ol.AddObserver(&a);
376   ol.AddObserver(&b);
377   EXPECT_TRUE(col.might_have_observers());
378   {
379     const It it = col.begin();
380     ol.Clear();
381     EXPECT_TRUE(col.might_have_observers());
382   }
383   EXPECT_FALSE(col.might_have_observers());
384 }
385 
TEST(ObserverListTest,DisruptSelf)386 TEST(ObserverListTest, DisruptSelf) {
387   ObserverList<Foo> observer_list;
388   Adder a(1), b(-1), c(1), d(-1);
389   Disrupter evil(&observer_list, true);
390 
391   observer_list.AddObserver(&a);
392   observer_list.AddObserver(&b);
393 
394   for (auto& observer : observer_list)
395     observer.Observe(10);
396 
397   observer_list.AddObserver(&evil);
398   observer_list.AddObserver(&c);
399   observer_list.AddObserver(&d);
400 
401   for (auto& observer : observer_list)
402     observer.Observe(10);
403 
404   EXPECT_EQ(20, a.total);
405   EXPECT_EQ(-20, b.total);
406   EXPECT_EQ(10, c.total);
407   EXPECT_EQ(-10, d.total);
408 }
409 
TEST(ObserverListTest,DisruptBefore)410 TEST(ObserverListTest, DisruptBefore) {
411   ObserverList<Foo> observer_list;
412   Adder a(1), b(-1), c(1), d(-1);
413   Disrupter evil(&observer_list, &b);
414 
415   observer_list.AddObserver(&a);
416   observer_list.AddObserver(&b);
417   observer_list.AddObserver(&evil);
418   observer_list.AddObserver(&c);
419   observer_list.AddObserver(&d);
420 
421   for (auto& observer : observer_list)
422     observer.Observe(10);
423   for (auto& observer : observer_list)
424     observer.Observe(10);
425 
426   EXPECT_EQ(20, a.total);
427   EXPECT_EQ(-10, b.total);
428   EXPECT_EQ(20, c.total);
429   EXPECT_EQ(-20, d.total);
430 }
431 
TEST(ObserverListThreadSafeTest,BasicTest)432 TEST(ObserverListThreadSafeTest, BasicTest) {
433   MessageLoop loop;
434 
435   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
436       new ObserverListThreadSafe<Foo>);
437   Adder a(1);
438   Adder b(-1);
439   Adder c(1);
440   Adder d(-1);
441 
442   observer_list->AddObserver(&a);
443   observer_list->AddObserver(&b);
444 
445   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
446   RunLoop().RunUntilIdle();
447 
448   observer_list->AddObserver(&c);
449   observer_list->AddObserver(&d);
450 
451   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
452   observer_list->RemoveObserver(&c);
453   RunLoop().RunUntilIdle();
454 
455   EXPECT_EQ(20, a.total);
456   EXPECT_EQ(-20, b.total);
457   EXPECT_EQ(0, c.total);
458   EXPECT_EQ(-10, d.total);
459 }
460 
TEST(ObserverListThreadSafeTest,RemoveObserver)461 TEST(ObserverListThreadSafeTest, RemoveObserver) {
462   MessageLoop loop;
463 
464   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
465       new ObserverListThreadSafe<Foo>);
466   Adder a(1), b(1);
467 
468   // A workaround for the compiler bug. See http://crbug.com/121960.
469   EXPECT_NE(&a, &b);
470 
471   // Should do nothing.
472   observer_list->RemoveObserver(&a);
473   observer_list->RemoveObserver(&b);
474 
475   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
476   RunLoop().RunUntilIdle();
477 
478   EXPECT_EQ(0, a.total);
479   EXPECT_EQ(0, b.total);
480 
481   observer_list->AddObserver(&a);
482 
483   // Should also do nothing.
484   observer_list->RemoveObserver(&b);
485 
486   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
487   RunLoop().RunUntilIdle();
488 
489   EXPECT_EQ(10, a.total);
490   EXPECT_EQ(0, b.total);
491 }
492 
TEST(ObserverListThreadSafeTest,WithoutSequence)493 TEST(ObserverListThreadSafeTest, WithoutSequence) {
494   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
495       new ObserverListThreadSafe<Foo>);
496 
497   Adder a(1), b(1), c(1);
498 
499   // No sequence, so these should not be added.
500   observer_list->AddObserver(&a);
501   observer_list->AddObserver(&b);
502 
503   {
504     // Add c when there's a sequence.
505     MessageLoop loop;
506     observer_list->AddObserver(&c);
507 
508     observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
509     RunLoop().RunUntilIdle();
510 
511     EXPECT_EQ(0, a.total);
512     EXPECT_EQ(0, b.total);
513     EXPECT_EQ(10, c.total);
514 
515     // Now add a when there's a sequence.
516     observer_list->AddObserver(&a);
517 
518     // Remove c when there's a sequence.
519     observer_list->RemoveObserver(&c);
520 
521     // Notify again.
522     observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
523     RunLoop().RunUntilIdle();
524 
525     EXPECT_EQ(20, a.total);
526     EXPECT_EQ(0, b.total);
527     EXPECT_EQ(10, c.total);
528   }
529 
530   // Removing should always succeed with or without a sequence.
531   observer_list->RemoveObserver(&a);
532 
533   // Notifying should not fail but should also be a no-op.
534   MessageLoop loop;
535   observer_list->AddObserver(&b);
536   observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
537   RunLoop().RunUntilIdle();
538 
539   EXPECT_EQ(20, a.total);
540   EXPECT_EQ(30, b.total);
541   EXPECT_EQ(10, c.total);
542 }
543 
544 class FooRemover : public Foo {
545  public:
FooRemover(ObserverListThreadSafe<Foo> * list)546   explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {}
547   ~FooRemover() override = default;
548 
AddFooToRemove(Foo * foo)549   void AddFooToRemove(Foo* foo) {
550     foos_.push_back(foo);
551   }
552 
Observe(int x)553   void Observe(int x) override {
554     std::vector<Foo*> tmp;
555     tmp.swap(foos_);
556     for (std::vector<Foo*>::iterator it = tmp.begin();
557          it != tmp.end(); ++it) {
558       list_->RemoveObserver(*it);
559     }
560   }
561 
562  private:
563   const scoped_refptr<ObserverListThreadSafe<Foo> > list_;
564   std::vector<Foo*> foos_;
565 };
566 
TEST(ObserverListThreadSafeTest,RemoveMultipleObservers)567 TEST(ObserverListThreadSafeTest, RemoveMultipleObservers) {
568   MessageLoop loop;
569   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
570       new ObserverListThreadSafe<Foo>);
571 
572   FooRemover a(observer_list.get());
573   Adder b(1);
574 
575   observer_list->AddObserver(&a);
576   observer_list->AddObserver(&b);
577 
578   a.AddFooToRemove(&a);
579   a.AddFooToRemove(&b);
580 
581   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
582   RunLoop().RunUntilIdle();
583 }
584 
585 // A test driver for a multi-threaded notification loop.  Runs a number
586 // of observer threads, each of which constantly adds/removes itself
587 // from the observer list.  Optionally, if cross_thread_notifies is set
588 // to true, the observer threads will also trigger notifications to
589 // all observers.
ThreadSafeObserverHarness(int num_threads,bool cross_thread_notifies)590 static void ThreadSafeObserverHarness(int num_threads,
591                                       bool cross_thread_notifies) {
592   MessageLoop loop;
593 
594   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
595       new ObserverListThreadSafe<Foo>);
596   Adder a(1);
597   Adder b(-1);
598 
599   observer_list->AddObserver(&a);
600   observer_list->AddObserver(&b);
601 
602   std::vector<AddRemoveThread*> threaded_observer;
603   std::vector<base::PlatformThreadHandle> threads(num_threads);
604   std::vector<std::unique_ptr<base::WaitableEvent>> ready;
605   threaded_observer.reserve(num_threads);
606   ready.reserve(num_threads);
607   for (int index = 0; index < num_threads; index++) {
608     ready.push_back(std::make_unique<WaitableEvent>(
609         WaitableEvent::ResetPolicy::MANUAL,
610         WaitableEvent::InitialState::NOT_SIGNALED));
611     threaded_observer.push_back(new AddRemoveThread(
612         observer_list.get(), cross_thread_notifies, ready.back().get()));
613     EXPECT_TRUE(
614         PlatformThread::Create(0, threaded_observer.back(), &threads[index]));
615   }
616   ASSERT_EQ(static_cast<size_t>(num_threads), threaded_observer.size());
617   ASSERT_EQ(static_cast<size_t>(num_threads), ready.size());
618 
619   // This makes sure that threaded_observer has gotten to set loop_, so that we
620   // can call Quit() below safe-ish-ly.
621   for (int i = 0; i < num_threads; ++i)
622     ready[i]->Wait();
623 
624   Time start = Time::Now();
625   while (true) {
626     if ((Time::Now() - start).InMilliseconds() > kThreadRunTime)
627       break;
628 
629     observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
630 
631     RunLoop().RunUntilIdle();
632   }
633 
634   for (int index = 0; index < num_threads; index++) {
635     threaded_observer[index]->Quit();
636     PlatformThread::Join(threads[index]);
637   }
638 }
639 
640 #if defined(OS_FUCHSIA)
641 // TODO(crbug.com/738275): This is flaky on Fuchsia.
642 #define MAYBE_CrossThreadObserver DISABLED_CrossThreadObserver
643 #else
644 #define MAYBE_CrossThreadObserver CrossThreadObserver
645 #endif
TEST(ObserverListThreadSafeTest,MAYBE_CrossThreadObserver)646 TEST(ObserverListThreadSafeTest, MAYBE_CrossThreadObserver) {
647   // Use 7 observer threads.  Notifications only come from
648   // the main thread.
649   ThreadSafeObserverHarness(7, false);
650 }
651 
TEST(ObserverListThreadSafeTest,CrossThreadNotifications)652 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) {
653   // Use 3 observer threads.  Notifications will fire from
654   // the main thread and all 3 observer threads.
655   ThreadSafeObserverHarness(3, true);
656 }
657 
TEST(ObserverListThreadSafeTest,OutlivesMessageLoop)658 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) {
659   MessageLoop* loop = new MessageLoop;
660   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
661       new ObserverListThreadSafe<Foo>);
662 
663   Adder a(1);
664   observer_list->AddObserver(&a);
665   delete loop;
666   // Test passes if we don't crash here.
667   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
668 }
669 
670 namespace {
671 
672 class SequenceVerificationObserver : public Foo {
673  public:
SequenceVerificationObserver(scoped_refptr<SequencedTaskRunner> task_runner)674   explicit SequenceVerificationObserver(
675       scoped_refptr<SequencedTaskRunner> task_runner)
676       : task_runner_(std::move(task_runner)) {}
677   ~SequenceVerificationObserver() override = default;
678 
Observe(int x)679   void Observe(int x) override {
680     called_on_valid_sequence_ = task_runner_->RunsTasksInCurrentSequence();
681   }
682 
called_on_valid_sequence() const683   bool called_on_valid_sequence() const { return called_on_valid_sequence_; }
684 
685  private:
686   const scoped_refptr<SequencedTaskRunner> task_runner_;
687   bool called_on_valid_sequence_ = false;
688 
689   DISALLOW_COPY_AND_ASSIGN(SequenceVerificationObserver);
690 };
691 
692 }  // namespace
693 
694 // Verify that observers are notified on the correct sequence.
695 // TaskScheduler not supported in libchrome
696 #if 0
697 TEST(ObserverListThreadSafeTest, NotificationOnValidSequence) {
698   test::ScopedTaskEnvironment scoped_task_environment;
699 
700   auto task_runner_1 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
701   auto task_runner_2 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
702 
703   auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
704 
705   SequenceVerificationObserver observer_1(task_runner_1);
706   SequenceVerificationObserver observer_2(task_runner_2);
707 
708   task_runner_1->PostTask(FROM_HERE,
709                           BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
710                                    observer_list, Unretained(&observer_1)));
711   task_runner_2->PostTask(FROM_HERE,
712                           BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
713                                    observer_list, Unretained(&observer_2)));
714 
715   TaskScheduler::GetInstance()->FlushForTesting();
716 
717   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
718 
719   TaskScheduler::GetInstance()->FlushForTesting();
720 
721   EXPECT_TRUE(observer_1.called_on_valid_sequence());
722   EXPECT_TRUE(observer_2.called_on_valid_sequence());
723 }
724 #endif
725 
726 // Verify that when an observer is added to a NOTIFY_ALL ObserverListThreadSafe
727 // from a notification, it is itself notified.
728 // TaskScheduler not supported in libchrome
729 #if 0
730 TEST(ObserverListThreadSafeTest, AddObserverFromNotificationNotifyAll) {
731   test::ScopedTaskEnvironment scoped_task_environment;
732   auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
733 
734   Adder observer_added_from_notification(1);
735 
736   AddInObserve<ObserverListThreadSafe<Foo>> initial_observer(
737       observer_list.get());
738   initial_observer.SetToAdd(&observer_added_from_notification);
739   observer_list->AddObserver(&initial_observer);
740 
741   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
742 
743   base::RunLoop().RunUntilIdle();
744 
745   EXPECT_EQ(1, observer_added_from_notification.GetValue());
746 }
747 #endif
748 
749 namespace {
750 
751 class RemoveWhileNotificationIsRunningObserver : public Foo {
752  public:
RemoveWhileNotificationIsRunningObserver()753   RemoveWhileNotificationIsRunningObserver()
754       : notification_running_(WaitableEvent::ResetPolicy::AUTOMATIC,
755                               WaitableEvent::InitialState::NOT_SIGNALED),
756         barrier_(WaitableEvent::ResetPolicy::AUTOMATIC,
757                  WaitableEvent::InitialState::NOT_SIGNALED) {}
758   ~RemoveWhileNotificationIsRunningObserver() override = default;
759 
Observe(int x)760   void Observe(int x) override {
761     notification_running_.Signal();
762     ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
763     barrier_.Wait();
764   }
765 
WaitForNotificationRunning()766   void WaitForNotificationRunning() { notification_running_.Wait(); }
Unblock()767   void Unblock() { barrier_.Signal(); }
768 
769  private:
770   WaitableEvent notification_running_;
771   WaitableEvent barrier_;
772 
773   DISALLOW_COPY_AND_ASSIGN(RemoveWhileNotificationIsRunningObserver);
774 };
775 
776 }  // namespace
777 
778 // Verify that there is no crash when an observer is removed while it is being
779 // notified.
780 // TaskScheduler not supported in libchrome
781 #if 0
782 TEST(ObserverListThreadSafeTest, RemoveWhileNotificationIsRunning) {
783   auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
784   RemoveWhileNotificationIsRunningObserver observer;
785 
786   WaitableEvent task_running(WaitableEvent::ResetPolicy::AUTOMATIC,
787                              WaitableEvent::InitialState::NOT_SIGNALED);
788   WaitableEvent barrier(WaitableEvent::ResetPolicy::AUTOMATIC,
789                         WaitableEvent::InitialState::NOT_SIGNALED);
790 
791   // This must be after the declaration of |barrier| so that tasks posted to
792   // TaskScheduler can safely use |barrier|.
793   test::ScopedTaskEnvironment scoped_task_environment;
794 
795   CreateSequencedTaskRunnerWithTraits({})->PostTask(
796       FROM_HERE, base::BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
797                                 observer_list, Unretained(&observer)));
798   TaskScheduler::GetInstance()->FlushForTesting();
799 
800   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
801   observer.WaitForNotificationRunning();
802   observer_list->RemoveObserver(&observer);
803 
804   observer.Unblock();
805 }
806 #endif
807 
TEST(ObserverListTest,Existing)808 TEST(ObserverListTest, Existing) {
809   ObserverList<Foo> observer_list(ObserverListPolicy::EXISTING_ONLY);
810   Adder a(1);
811   AddInObserve<ObserverList<Foo> > b(&observer_list);
812   Adder c(1);
813   b.SetToAdd(&c);
814 
815   observer_list.AddObserver(&a);
816   observer_list.AddObserver(&b);
817 
818   for (auto& observer : observer_list)
819     observer.Observe(1);
820 
821   EXPECT_FALSE(b.to_add_);
822   // B's adder should not have been notified because it was added during
823   // notification.
824   EXPECT_EQ(0, c.total);
825 
826   // Notify again to make sure b's adder is notified.
827   for (auto& observer : observer_list)
828     observer.Observe(1);
829   EXPECT_EQ(1, c.total);
830 }
831 
832 // Same as above, but for ObserverListThreadSafe
TEST(ObserverListThreadSafeTest,Existing)833 TEST(ObserverListThreadSafeTest, Existing) {
834   MessageLoop loop;
835   scoped_refptr<ObserverListThreadSafe<Foo>> observer_list(
836       new ObserverListThreadSafe<Foo>(ObserverListPolicy::EXISTING_ONLY));
837   Adder a(1);
838   AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get());
839   Adder c(1);
840   b.SetToAdd(&c);
841 
842   observer_list->AddObserver(&a);
843   observer_list->AddObserver(&b);
844 
845   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
846   RunLoop().RunUntilIdle();
847 
848   EXPECT_FALSE(b.to_add_);
849   // B's adder should not have been notified because it was added during
850   // notification.
851   EXPECT_EQ(0, c.total);
852 
853   // Notify again to make sure b's adder is notified.
854   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
855   RunLoop().RunUntilIdle();
856   EXPECT_EQ(1, c.total);
857 }
858 
859 class AddInClearObserve : public Foo {
860  public:
AddInClearObserve(ObserverList<Foo> * list)861   explicit AddInClearObserve(ObserverList<Foo>* list)
862       : list_(list), added_(false), adder_(1) {}
863 
Observe(int)864   void Observe(int /* x */) override {
865     list_->Clear();
866     list_->AddObserver(&adder_);
867     added_ = true;
868   }
869 
added() const870   bool added() const { return added_; }
adder() const871   const Adder& adder() const { return adder_; }
872 
873  private:
874   ObserverList<Foo>* const list_;
875 
876   bool added_;
877   Adder adder_;
878 };
879 
TEST(ObserverListTest,ClearNotifyAll)880 TEST(ObserverListTest, ClearNotifyAll) {
881   ObserverList<Foo> observer_list;
882   AddInClearObserve a(&observer_list);
883 
884   observer_list.AddObserver(&a);
885 
886   for (auto& observer : observer_list)
887     observer.Observe(1);
888   EXPECT_TRUE(a.added());
889   EXPECT_EQ(1, a.adder().total)
890       << "Adder should observe once and have sum of 1.";
891 }
892 
TEST(ObserverListTest,ClearNotifyExistingOnly)893 TEST(ObserverListTest, ClearNotifyExistingOnly) {
894   ObserverList<Foo> observer_list(ObserverListPolicy::EXISTING_ONLY);
895   AddInClearObserve a(&observer_list);
896 
897   observer_list.AddObserver(&a);
898 
899   for (auto& observer : observer_list)
900     observer.Observe(1);
901   EXPECT_TRUE(a.added());
902   EXPECT_EQ(0, a.adder().total)
903       << "Adder should not observe, so sum should still be 0.";
904 }
905 
906 class ListDestructor : public Foo {
907  public:
ListDestructor(ObserverList<Foo> * list)908   explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {}
909   ~ListDestructor() override = default;
910 
Observe(int x)911   void Observe(int x) override { delete list_; }
912 
913  private:
914   ObserverList<Foo>* list_;
915 };
916 
917 
TEST(ObserverListTest,IteratorOutlivesList)918 TEST(ObserverListTest, IteratorOutlivesList) {
919   ObserverList<Foo>* observer_list = new ObserverList<Foo>;
920   ListDestructor a(observer_list);
921   observer_list->AddObserver(&a);
922 
923   for (auto& observer : *observer_list)
924     observer.Observe(0);
925 
926   // There are no EXPECT* statements for this test, if we catch
927   // use-after-free errors for observer_list (eg with ASan) then
928   // this test has failed.  See http://crbug.com/85296.
929 }
930 
TEST(ObserverListTest,BasicStdIterator)931 TEST(ObserverListTest, BasicStdIterator) {
932   using FooList = ObserverList<Foo>;
933   FooList observer_list;
934 
935   // An optimization: begin() and end() do not involve weak pointers on
936   // empty list.
937   EXPECT_FALSE(observer_list.begin().list_);
938   EXPECT_FALSE(observer_list.end().list_);
939 
940   // Iterate over empty list: no effect, no crash.
941   for (auto& i : observer_list)
942     i.Observe(10);
943 
944   Adder a(1), b(-1), c(1), d(-1);
945 
946   observer_list.AddObserver(&a);
947   observer_list.AddObserver(&b);
948   observer_list.AddObserver(&c);
949   observer_list.AddObserver(&d);
950 
951   for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
952        i != e; ++i)
953     i->Observe(1);
954 
955   EXPECT_EQ(1, a.total);
956   EXPECT_EQ(-1, b.total);
957   EXPECT_EQ(1, c.total);
958   EXPECT_EQ(-1, d.total);
959 
960   // Check an iteration over a 'const view' for a given container.
961   const FooList& const_list = observer_list;
962   for (FooList::const_iterator i = const_list.begin(), e = const_list.end();
963        i != e; ++i) {
964     EXPECT_EQ(1, std::abs(i->GetValue()));
965   }
966 
967   for (const auto& o : const_list)
968     EXPECT_EQ(1, std::abs(o.GetValue()));
969 }
970 
TEST(ObserverListTest,StdIteratorRemoveItself)971 TEST(ObserverListTest, StdIteratorRemoveItself) {
972   ObserverList<Foo> observer_list;
973   Adder a(1), b(-1), c(1), d(-1);
974   Disrupter disrupter(&observer_list, true);
975 
976   observer_list.AddObserver(&a);
977   observer_list.AddObserver(&b);
978   observer_list.AddObserver(&disrupter);
979   observer_list.AddObserver(&c);
980   observer_list.AddObserver(&d);
981 
982   for (auto& o : observer_list)
983     o.Observe(1);
984 
985   for (auto& o : observer_list)
986     o.Observe(10);
987 
988   EXPECT_EQ(11, a.total);
989   EXPECT_EQ(-11, b.total);
990   EXPECT_EQ(11, c.total);
991   EXPECT_EQ(-11, d.total);
992 }
993 
TEST(ObserverListTest,StdIteratorRemoveBefore)994 TEST(ObserverListTest, StdIteratorRemoveBefore) {
995   ObserverList<Foo> observer_list;
996   Adder a(1), b(-1), c(1), d(-1);
997   Disrupter disrupter(&observer_list, &b);
998 
999   observer_list.AddObserver(&a);
1000   observer_list.AddObserver(&b);
1001   observer_list.AddObserver(&disrupter);
1002   observer_list.AddObserver(&c);
1003   observer_list.AddObserver(&d);
1004 
1005   for (auto& o : observer_list)
1006     o.Observe(1);
1007 
1008   for (auto& o : observer_list)
1009     o.Observe(10);
1010 
1011   EXPECT_EQ(11, a.total);
1012   EXPECT_EQ(-1, b.total);
1013   EXPECT_EQ(11, c.total);
1014   EXPECT_EQ(-11, d.total);
1015 }
1016 
TEST(ObserverListTest,StdIteratorRemoveAfter)1017 TEST(ObserverListTest, StdIteratorRemoveAfter) {
1018   ObserverList<Foo> observer_list;
1019   Adder a(1), b(-1), c(1), d(-1);
1020   Disrupter disrupter(&observer_list, &c);
1021 
1022   observer_list.AddObserver(&a);
1023   observer_list.AddObserver(&b);
1024   observer_list.AddObserver(&disrupter);
1025   observer_list.AddObserver(&c);
1026   observer_list.AddObserver(&d);
1027 
1028   for (auto& o : observer_list)
1029     o.Observe(1);
1030 
1031   for (auto& o : observer_list)
1032     o.Observe(10);
1033 
1034   EXPECT_EQ(11, a.total);
1035   EXPECT_EQ(-11, b.total);
1036   EXPECT_EQ(0, c.total);
1037   EXPECT_EQ(-11, d.total);
1038 }
1039 
TEST(ObserverListTest,StdIteratorRemoveAfterFront)1040 TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
1041   ObserverList<Foo> observer_list;
1042   Adder a(1), b(-1), c(1), d(-1);
1043   Disrupter disrupter(&observer_list, &a);
1044 
1045   observer_list.AddObserver(&a);
1046   observer_list.AddObserver(&disrupter);
1047   observer_list.AddObserver(&b);
1048   observer_list.AddObserver(&c);
1049   observer_list.AddObserver(&d);
1050 
1051   for (auto& o : observer_list)
1052     o.Observe(1);
1053 
1054   for (auto& o : observer_list)
1055     o.Observe(10);
1056 
1057   EXPECT_EQ(1, a.total);
1058   EXPECT_EQ(-11, b.total);
1059   EXPECT_EQ(11, c.total);
1060   EXPECT_EQ(-11, d.total);
1061 }
1062 
TEST(ObserverListTest,StdIteratorRemoveBeforeBack)1063 TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
1064   ObserverList<Foo> observer_list;
1065   Adder a(1), b(-1), c(1), d(-1);
1066   Disrupter disrupter(&observer_list, &d);
1067 
1068   observer_list.AddObserver(&a);
1069   observer_list.AddObserver(&b);
1070   observer_list.AddObserver(&c);
1071   observer_list.AddObserver(&disrupter);
1072   observer_list.AddObserver(&d);
1073 
1074   for (auto& o : observer_list)
1075     o.Observe(1);
1076 
1077   for (auto& o : observer_list)
1078     o.Observe(10);
1079 
1080   EXPECT_EQ(11, a.total);
1081   EXPECT_EQ(-11, b.total);
1082   EXPECT_EQ(11, c.total);
1083   EXPECT_EQ(0, d.total);
1084 }
1085 
TEST(ObserverListTest,StdIteratorRemoveFront)1086 TEST(ObserverListTest, StdIteratorRemoveFront) {
1087   using FooList = ObserverList<Foo>;
1088   FooList observer_list;
1089   Adder a(1), b(-1), c(1), d(-1);
1090   Disrupter disrupter(&observer_list, true);
1091 
1092   observer_list.AddObserver(&disrupter);
1093   observer_list.AddObserver(&a);
1094   observer_list.AddObserver(&b);
1095   observer_list.AddObserver(&c);
1096   observer_list.AddObserver(&d);
1097 
1098   bool test_disruptor = true;
1099   for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
1100        i != e; ++i) {
1101     i->Observe(1);
1102     // Check that second call to i->Observe() would crash here.
1103     if (test_disruptor) {
1104       EXPECT_FALSE(i.GetCurrent());
1105       test_disruptor = false;
1106     }
1107   }
1108 
1109   for (auto& o : observer_list)
1110     o.Observe(10);
1111 
1112   EXPECT_EQ(11, a.total);
1113   EXPECT_EQ(-11, b.total);
1114   EXPECT_EQ(11, c.total);
1115   EXPECT_EQ(-11, d.total);
1116 }
1117 
TEST(ObserverListTest,StdIteratorRemoveBack)1118 TEST(ObserverListTest, StdIteratorRemoveBack) {
1119   ObserverList<Foo> observer_list;
1120   Adder a(1), b(-1), c(1), d(-1);
1121   Disrupter disrupter(&observer_list, true);
1122 
1123   observer_list.AddObserver(&a);
1124   observer_list.AddObserver(&b);
1125   observer_list.AddObserver(&c);
1126   observer_list.AddObserver(&d);
1127   observer_list.AddObserver(&disrupter);
1128 
1129   for (auto& o : observer_list)
1130     o.Observe(1);
1131 
1132   for (auto& o : observer_list)
1133     o.Observe(10);
1134 
1135   EXPECT_EQ(11, a.total);
1136   EXPECT_EQ(-11, b.total);
1137   EXPECT_EQ(11, c.total);
1138   EXPECT_EQ(-11, d.total);
1139 }
1140 
TEST(ObserverListTest,NestedLoop)1141 TEST(ObserverListTest, NestedLoop) {
1142   ObserverList<Foo> observer_list;
1143   Adder a(1), b(-1), c(1), d(-1);
1144   Disrupter disrupter(&observer_list, true);
1145 
1146   observer_list.AddObserver(&disrupter);
1147   observer_list.AddObserver(&a);
1148   observer_list.AddObserver(&b);
1149   observer_list.AddObserver(&c);
1150   observer_list.AddObserver(&d);
1151 
1152   for (auto& o : observer_list) {
1153     o.Observe(10);
1154 
1155     for (auto& o : observer_list)
1156       o.Observe(1);
1157   }
1158 
1159   EXPECT_EQ(15, a.total);
1160   EXPECT_EQ(-15, b.total);
1161   EXPECT_EQ(15, c.total);
1162   EXPECT_EQ(-15, d.total);
1163 }
1164 
TEST(ObserverListTest,NonCompactList)1165 TEST(ObserverListTest, NonCompactList) {
1166   ObserverList<Foo> observer_list;
1167   Adder a(1), b(-1);
1168 
1169   Disrupter disrupter1(&observer_list, true);
1170   Disrupter disrupter2(&observer_list, true);
1171 
1172   // Disrupt itself and another one.
1173   disrupter1.SetDoomed(&disrupter2);
1174 
1175   observer_list.AddObserver(&disrupter1);
1176   observer_list.AddObserver(&disrupter2);
1177   observer_list.AddObserver(&a);
1178   observer_list.AddObserver(&b);
1179 
1180   for (auto& o : observer_list) {
1181     // Get the { nullptr, nullptr, &a, &b } non-compact list
1182     // on the first inner pass.
1183     o.Observe(10);
1184 
1185     for (auto& o : observer_list)
1186       o.Observe(1);
1187   }
1188 
1189   EXPECT_EQ(13, a.total);
1190   EXPECT_EQ(-13, b.total);
1191 }
1192 
TEST(ObserverListTest,BecomesEmptyThanNonEmpty)1193 TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
1194   ObserverList<Foo> observer_list;
1195   Adder a(1), b(-1);
1196 
1197   Disrupter disrupter1(&observer_list, true);
1198   Disrupter disrupter2(&observer_list, true);
1199 
1200   // Disrupt itself and another one.
1201   disrupter1.SetDoomed(&disrupter2);
1202 
1203   observer_list.AddObserver(&disrupter1);
1204   observer_list.AddObserver(&disrupter2);
1205 
1206   bool add_observers = true;
1207   for (auto& o : observer_list) {
1208     // Get the { nullptr, nullptr } empty list on the first inner pass.
1209     o.Observe(10);
1210 
1211     for (auto& o : observer_list)
1212       o.Observe(1);
1213 
1214     if (add_observers) {
1215       observer_list.AddObserver(&a);
1216       observer_list.AddObserver(&b);
1217       add_observers = false;
1218     }
1219   }
1220 
1221   EXPECT_EQ(12, a.total);
1222   EXPECT_EQ(-12, b.total);
1223 }
1224 
TEST(ObserverListTest,AddObserverInTheLastObserve)1225 TEST(ObserverListTest, AddObserverInTheLastObserve) {
1226   using FooList = ObserverList<Foo>;
1227   FooList observer_list;
1228 
1229   AddInObserve<FooList> a(&observer_list);
1230   Adder b(-1);
1231 
1232   a.SetToAdd(&b);
1233   observer_list.AddObserver(&a);
1234 
1235   auto it = observer_list.begin();
1236   while (it != observer_list.end()) {
1237     auto& observer = *it;
1238     // Intentionally increment the iterator before calling Observe(). The
1239     // ObserverList starts with only one observer, and it == observer_list.end()
1240     // should be true after the next line.
1241     ++it;
1242     // However, the first Observe() call will add a second observer: at this
1243     // point, it != observer_list.end() should be true, and Observe() should be
1244     // called on the newly added observer on the next iteration of the loop.
1245     observer.Observe(10);
1246   }
1247 
1248   EXPECT_EQ(-10, b.total);
1249 }
1250 
1251 class MockLogAssertHandler {
1252  public:
1253   MOCK_METHOD4(
1254       HandleLogAssert,
1255       void(const char*, int, const base::StringPiece, const base::StringPiece));
1256 };
1257 
1258 #if DCHECK_IS_ON()
TEST(ObserverListTest,NonReentrantObserverList)1259 TEST(ObserverListTest, NonReentrantObserverList) {
1260   using ::testing::_;
1261 
1262   ObserverList<Foo, /*check_empty=*/false, /*allow_reentrancy=*/false>
1263       non_reentrant_observer_list;
1264   Adder a(1);
1265   non_reentrant_observer_list.AddObserver(&a);
1266 
1267   EXPECT_DCHECK_DEATH({
1268     for (const Foo& a : non_reentrant_observer_list) {
1269       for (const Foo& b : non_reentrant_observer_list) {
1270         std::ignore = a;
1271         std::ignore = b;
1272       }
1273     }
1274   });
1275 }
1276 
TEST(ObserverListTest,ReentrantObserverList)1277 TEST(ObserverListTest, ReentrantObserverList) {
1278   using ::testing::_;
1279 
1280   ReentrantObserverList<Foo> reentrant_observer_list;
1281   Adder a(1);
1282   reentrant_observer_list.AddObserver(&a);
1283   bool passed = false;
1284   for (const Foo& a : reentrant_observer_list) {
1285     for (const Foo& b : reentrant_observer_list) {
1286       std::ignore = a;
1287       std::ignore = b;
1288       passed = true;
1289     }
1290   }
1291   EXPECT_TRUE(passed);
1292 }
1293 #endif
1294 
1295 }  // namespace base
1296