• 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 <vector>
9 
10 #include "base/compiler_specific.h"
11 #include "base/location.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/threading/platform_thread.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace base {
19 namespace {
20 
21 class Foo {
22  public:
23   virtual void Observe(int x) = 0;
~Foo()24   virtual ~Foo() {}
GetValue() const25   virtual int GetValue() const { return 0; }
26 };
27 
28 class Adder : public Foo {
29  public:
Adder(int scaler)30   explicit Adder(int scaler) : total(0), scaler_(scaler) {}
~Adder()31   ~Adder() override {}
32 
Observe(int x)33   void Observe(int x) override { total += x * scaler_; }
GetValue() const34   int GetValue() const override { return total; }
35 
36   int total;
37 
38  private:
39   int scaler_;
40 };
41 
42 class Disrupter : public Foo {
43  public:
Disrupter(ObserverList<Foo> * list,Foo * doomed,bool remove_self)44   Disrupter(ObserverList<Foo>* list, Foo* doomed, bool remove_self)
45       : list_(list), doomed_(doomed), remove_self_(remove_self) {}
Disrupter(ObserverList<Foo> * list,Foo * doomed)46   Disrupter(ObserverList<Foo>* list, Foo* doomed)
47       : Disrupter(list, doomed, false) {}
Disrupter(ObserverList<Foo> * list,bool remove_self)48   Disrupter(ObserverList<Foo>* list, bool remove_self)
49       : Disrupter(list, nullptr, remove_self) {}
50 
~Disrupter()51   ~Disrupter() override {}
52 
Observe(int x)53   void Observe(int x) override {
54     if (remove_self_)
55       list_->RemoveObserver(this);
56     if (doomed_)
57       list_->RemoveObserver(doomed_);
58   }
59 
SetDoomed(Foo * doomed)60   void SetDoomed(Foo* doomed) { doomed_ = doomed; }
61 
62  private:
63   ObserverList<Foo>* list_;
64   Foo* doomed_;
65   bool remove_self_;
66 };
67 
68 class ThreadSafeDisrupter : public Foo {
69  public:
ThreadSafeDisrupter(ObserverListThreadSafe<Foo> * list,Foo * doomed)70   ThreadSafeDisrupter(ObserverListThreadSafe<Foo>* list, Foo* doomed)
71       : list_(list),
72         doomed_(doomed) {
73   }
~ThreadSafeDisrupter()74   ~ThreadSafeDisrupter() override {}
Observe(int x)75   void Observe(int x) override { list_->RemoveObserver(doomed_); }
76 
77  private:
78   ObserverListThreadSafe<Foo>* list_;
79   Foo* doomed_;
80 };
81 
82 template <typename ObserverListType>
83 class AddInObserve : public Foo {
84  public:
AddInObserve(ObserverListType * observer_list)85   explicit AddInObserve(ObserverListType* observer_list)
86       : observer_list(observer_list), to_add_() {}
87 
SetToAdd(Foo * to_add)88   void SetToAdd(Foo* to_add) { to_add_ = to_add; }
89 
Observe(int x)90   void Observe(int x) override {
91     if (to_add_) {
92       observer_list->AddObserver(to_add_);
93       to_add_ = nullptr;
94     }
95   }
96 
97   ObserverListType* observer_list;
98   Foo* to_add_;
99 };
100 
101 
102 static const int kThreadRunTime = 2000;  // ms to run the multi-threaded test.
103 
104 // A thread for use in the ThreadSafeObserver test
105 // which will add and remove itself from the notification
106 // list repeatedly.
107 class AddRemoveThread : public PlatformThread::Delegate,
108                         public Foo {
109  public:
AddRemoveThread(ObserverListThreadSafe<Foo> * list,bool notify)110   AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify)
111       : list_(list),
112         loop_(nullptr),
113         in_list_(false),
114         start_(Time::Now()),
115         count_observes_(0),
116         count_addtask_(0),
117         do_notifies_(notify),
118         weak_factory_(this) {
119   }
120 
~AddRemoveThread()121   ~AddRemoveThread() override {}
122 
ThreadMain()123   void ThreadMain() override {
124     loop_ = new MessageLoop();  // Fire up a message loop.
125     loop_->task_runner()->PostTask(
126         FROM_HERE,
127         base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
128     RunLoop().Run();
129     delete loop_;
130     loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef);
131     delete this;
132   }
133 
134   // This task just keeps posting to itself in an attempt
135   // to race with the notifier.
AddTask()136   void AddTask() {
137     count_addtask_++;
138 
139     if ((Time::Now() - start_).InMilliseconds() > kThreadRunTime) {
140       VLOG(1) << "DONE!";
141       return;
142     }
143 
144     if (!in_list_) {
145       list_->AddObserver(this);
146       in_list_ = true;
147     }
148 
149     if (do_notifies_) {
150       list_->Notify(FROM_HERE, &Foo::Observe, 10);
151     }
152 
153     loop_->task_runner()->PostTask(
154         FROM_HERE,
155         base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
156   }
157 
Quit()158   void Quit() {
159     loop_->task_runner()->PostTask(FROM_HERE,
160                                    MessageLoop::QuitWhenIdleClosure());
161   }
162 
Observe(int x)163   void Observe(int x) override {
164     count_observes_++;
165 
166     // If we're getting called after we removed ourselves from
167     // the list, that is very bad!
168     DCHECK(in_list_);
169 
170     // This callback should fire on the appropriate thread
171     EXPECT_EQ(loop_, MessageLoop::current());
172 
173     list_->RemoveObserver(this);
174     in_list_ = false;
175   }
176 
177  private:
178   ObserverListThreadSafe<Foo>* list_;
179   MessageLoop* loop_;
180   bool in_list_;        // Are we currently registered for notifications.
181                         // in_list_ is only used on |this| thread.
182   Time start_;          // The time we started the test.
183 
184   int count_observes_;  // Number of times we observed.
185   int count_addtask_;   // Number of times thread AddTask was called
186   bool do_notifies_;    // Whether these threads should do notifications.
187 
188   base::WeakPtrFactory<AddRemoveThread> weak_factory_;
189 };
190 
191 }  // namespace
192 
TEST(ObserverListTest,BasicTest)193 TEST(ObserverListTest, BasicTest) {
194   ObserverList<Foo> observer_list;
195   Adder a(1), b(-1), c(1), d(-1), e(-1);
196   Disrupter evil(&observer_list, &c);
197 
198   observer_list.AddObserver(&a);
199   observer_list.AddObserver(&b);
200 
201   EXPECT_TRUE(observer_list.HasObserver(&a));
202   EXPECT_FALSE(observer_list.HasObserver(&c));
203 
204   for (auto& observer : observer_list)
205     observer.Observe(10);
206 
207   observer_list.AddObserver(&evil);
208   observer_list.AddObserver(&c);
209   observer_list.AddObserver(&d);
210 
211   // Removing an observer not in the list should do nothing.
212   observer_list.RemoveObserver(&e);
213 
214   for (auto& observer : observer_list)
215     observer.Observe(10);
216 
217   EXPECT_EQ(20, a.total);
218   EXPECT_EQ(-20, b.total);
219   EXPECT_EQ(0, c.total);
220   EXPECT_EQ(-10, d.total);
221   EXPECT_EQ(0, e.total);
222 }
223 
TEST(ObserverListTest,DisruptSelf)224 TEST(ObserverListTest, DisruptSelf) {
225   ObserverList<Foo> observer_list;
226   Adder a(1), b(-1), c(1), d(-1);
227   Disrupter evil(&observer_list, true);
228 
229   observer_list.AddObserver(&a);
230   observer_list.AddObserver(&b);
231 
232   for (auto& observer : observer_list)
233     observer.Observe(10);
234 
235   observer_list.AddObserver(&evil);
236   observer_list.AddObserver(&c);
237   observer_list.AddObserver(&d);
238 
239   for (auto& observer : observer_list)
240     observer.Observe(10);
241 
242   EXPECT_EQ(20, a.total);
243   EXPECT_EQ(-20, b.total);
244   EXPECT_EQ(10, c.total);
245   EXPECT_EQ(-10, d.total);
246 }
247 
TEST(ObserverListTest,DisruptBefore)248 TEST(ObserverListTest, DisruptBefore) {
249   ObserverList<Foo> observer_list;
250   Adder a(1), b(-1), c(1), d(-1);
251   Disrupter evil(&observer_list, &b);
252 
253   observer_list.AddObserver(&a);
254   observer_list.AddObserver(&b);
255   observer_list.AddObserver(&evil);
256   observer_list.AddObserver(&c);
257   observer_list.AddObserver(&d);
258 
259   for (auto& observer : observer_list)
260     observer.Observe(10);
261   for (auto& observer : observer_list)
262     observer.Observe(10);
263 
264   EXPECT_EQ(20, a.total);
265   EXPECT_EQ(-10, b.total);
266   EXPECT_EQ(20, c.total);
267   EXPECT_EQ(-20, d.total);
268 }
269 
TEST(ObserverListThreadSafeTest,BasicTest)270 TEST(ObserverListThreadSafeTest, BasicTest) {
271   MessageLoop loop;
272 
273   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
274       new ObserverListThreadSafe<Foo>);
275   Adder a(1);
276   Adder b(-1);
277   Adder c(1);
278   Adder d(-1);
279   ThreadSafeDisrupter evil(observer_list.get(), &c);
280 
281   observer_list->AddObserver(&a);
282   observer_list->AddObserver(&b);
283 
284   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
285   RunLoop().RunUntilIdle();
286 
287   observer_list->AddObserver(&evil);
288   observer_list->AddObserver(&c);
289   observer_list->AddObserver(&d);
290 
291   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
292   RunLoop().RunUntilIdle();
293 
294   EXPECT_EQ(20, a.total);
295   EXPECT_EQ(-20, b.total);
296   EXPECT_EQ(0, c.total);
297   EXPECT_EQ(-10, d.total);
298 }
299 
TEST(ObserverListThreadSafeTest,RemoveObserver)300 TEST(ObserverListThreadSafeTest, RemoveObserver) {
301   MessageLoop loop;
302 
303   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
304       new ObserverListThreadSafe<Foo>);
305   Adder a(1), b(1);
306 
307   // A workaround for the compiler bug. See http://crbug.com/121960.
308   EXPECT_NE(&a, &b);
309 
310   // Should do nothing.
311   observer_list->RemoveObserver(&a);
312   observer_list->RemoveObserver(&b);
313 
314   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
315   RunLoop().RunUntilIdle();
316 
317   EXPECT_EQ(0, a.total);
318   EXPECT_EQ(0, b.total);
319 
320   observer_list->AddObserver(&a);
321 
322   // Should also do nothing.
323   observer_list->RemoveObserver(&b);
324 
325   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
326   RunLoop().RunUntilIdle();
327 
328   EXPECT_EQ(10, a.total);
329   EXPECT_EQ(0, b.total);
330 }
331 
TEST(ObserverListThreadSafeTest,WithoutMessageLoop)332 TEST(ObserverListThreadSafeTest, WithoutMessageLoop) {
333   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
334       new ObserverListThreadSafe<Foo>);
335 
336   Adder a(1), b(1), c(1);
337 
338   // No MessageLoop, so these should not be added.
339   observer_list->AddObserver(&a);
340   observer_list->AddObserver(&b);
341 
342   {
343     // Add c when there's a loop.
344     MessageLoop loop;
345     observer_list->AddObserver(&c);
346 
347     observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
348     RunLoop().RunUntilIdle();
349 
350     EXPECT_EQ(0, a.total);
351     EXPECT_EQ(0, b.total);
352     EXPECT_EQ(10, c.total);
353 
354     // Now add a when there's a loop.
355     observer_list->AddObserver(&a);
356 
357     // Remove c when there's a loop.
358     observer_list->RemoveObserver(&c);
359 
360     // Notify again.
361     observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
362     RunLoop().RunUntilIdle();
363 
364     EXPECT_EQ(20, a.total);
365     EXPECT_EQ(0, b.total);
366     EXPECT_EQ(10, c.total);
367   }
368 
369   // Removing should always succeed with or without a loop.
370   observer_list->RemoveObserver(&a);
371 
372   // Notifying should not fail but should also be a no-op.
373   MessageLoop loop;
374   observer_list->AddObserver(&b);
375   observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
376   RunLoop().RunUntilIdle();
377 
378   EXPECT_EQ(20, a.total);
379   EXPECT_EQ(30, b.total);
380   EXPECT_EQ(10, c.total);
381 }
382 
383 class FooRemover : public Foo {
384  public:
FooRemover(ObserverListThreadSafe<Foo> * list)385   explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {}
~FooRemover()386   ~FooRemover() override {}
387 
AddFooToRemove(Foo * foo)388   void AddFooToRemove(Foo* foo) {
389     foos_.push_back(foo);
390   }
391 
Observe(int x)392   void Observe(int x) override {
393     std::vector<Foo*> tmp;
394     tmp.swap(foos_);
395     for (std::vector<Foo*>::iterator it = tmp.begin();
396          it != tmp.end(); ++it) {
397       list_->RemoveObserver(*it);
398     }
399   }
400 
401  private:
402   const scoped_refptr<ObserverListThreadSafe<Foo> > list_;
403   std::vector<Foo*> foos_;
404 };
405 
TEST(ObserverListThreadSafeTest,RemoveMultipleObservers)406 TEST(ObserverListThreadSafeTest, RemoveMultipleObservers) {
407   MessageLoop loop;
408   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
409       new ObserverListThreadSafe<Foo>);
410 
411   FooRemover a(observer_list.get());
412   Adder b(1);
413 
414   observer_list->AddObserver(&a);
415   observer_list->AddObserver(&b);
416 
417   a.AddFooToRemove(&a);
418   a.AddFooToRemove(&b);
419 
420   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
421   RunLoop().RunUntilIdle();
422 }
423 
424 // A test driver for a multi-threaded notification loop.  Runs a number
425 // of observer threads, each of which constantly adds/removes itself
426 // from the observer list.  Optionally, if cross_thread_notifies is set
427 // to true, the observer threads will also trigger notifications to
428 // all observers.
ThreadSafeObserverHarness(int num_threads,bool cross_thread_notifies)429 static void ThreadSafeObserverHarness(int num_threads,
430                                       bool cross_thread_notifies) {
431   MessageLoop loop;
432 
433   const int kMaxThreads = 15;
434   num_threads = num_threads > kMaxThreads ? kMaxThreads : num_threads;
435 
436   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
437       new ObserverListThreadSafe<Foo>);
438   Adder a(1);
439   Adder b(-1);
440   Adder c(1);
441   Adder d(-1);
442 
443   observer_list->AddObserver(&a);
444   observer_list->AddObserver(&b);
445 
446   AddRemoveThread* threaded_observer[kMaxThreads];
447   base::PlatformThreadHandle threads[kMaxThreads];
448   for (int index = 0; index < num_threads; index++) {
449     threaded_observer[index] = new AddRemoveThread(observer_list.get(), false);
450     EXPECT_TRUE(PlatformThread::Create(0,
451                 threaded_observer[index], &threads[index]));
452   }
453 
454   Time start = Time::Now();
455   while (true) {
456     if ((Time::Now() - start).InMilliseconds() > kThreadRunTime)
457       break;
458 
459     observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
460 
461     RunLoop().RunUntilIdle();
462   }
463 
464   for (int index = 0; index < num_threads; index++) {
465     threaded_observer[index]->Quit();
466     PlatformThread::Join(threads[index]);
467   }
468 }
469 
TEST(ObserverListThreadSafeTest,CrossThreadObserver)470 TEST(ObserverListThreadSafeTest, CrossThreadObserver) {
471   // Use 7 observer threads.  Notifications only come from
472   // the main thread.
473   ThreadSafeObserverHarness(7, false);
474 }
475 
TEST(ObserverListThreadSafeTest,CrossThreadNotifications)476 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) {
477   // Use 3 observer threads.  Notifications will fire from
478   // the main thread and all 3 observer threads.
479   ThreadSafeObserverHarness(3, true);
480 }
481 
TEST(ObserverListThreadSafeTest,OutlivesMessageLoop)482 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) {
483   MessageLoop* loop = new MessageLoop;
484   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
485       new ObserverListThreadSafe<Foo>);
486 
487   Adder a(1);
488   observer_list->AddObserver(&a);
489   delete loop;
490   // Test passes if we don't crash here.
491   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
492 }
493 
TEST(ObserverListTest,Existing)494 TEST(ObserverListTest, Existing) {
495   ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY);
496   Adder a(1);
497   AddInObserve<ObserverList<Foo> > b(&observer_list);
498   Adder c(1);
499   b.SetToAdd(&c);
500 
501   observer_list.AddObserver(&a);
502   observer_list.AddObserver(&b);
503 
504   for (auto& observer : observer_list)
505     observer.Observe(1);
506 
507   EXPECT_FALSE(b.to_add_);
508   // B's adder should not have been notified because it was added during
509   // notification.
510   EXPECT_EQ(0, c.total);
511 
512   // Notify again to make sure b's adder is notified.
513   for (auto& observer : observer_list)
514     observer.Observe(1);
515   EXPECT_EQ(1, c.total);
516 }
517 
518 // Same as above, but for ObserverListThreadSafe
TEST(ObserverListThreadSafeTest,Existing)519 TEST(ObserverListThreadSafeTest, Existing) {
520   MessageLoop loop;
521   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
522       new ObserverListThreadSafe<Foo>(ObserverList<Foo>::NOTIFY_EXISTING_ONLY));
523   Adder a(1);
524   AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get());
525   Adder c(1);
526   b.SetToAdd(&c);
527 
528   observer_list->AddObserver(&a);
529   observer_list->AddObserver(&b);
530 
531   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
532   RunLoop().RunUntilIdle();
533 
534   EXPECT_FALSE(b.to_add_);
535   // B's adder should not have been notified because it was added during
536   // notification.
537   EXPECT_EQ(0, c.total);
538 
539   // Notify again to make sure b's adder is notified.
540   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
541   RunLoop().RunUntilIdle();
542   EXPECT_EQ(1, c.total);
543 }
544 
545 class AddInClearObserve : public Foo {
546  public:
AddInClearObserve(ObserverList<Foo> * list)547   explicit AddInClearObserve(ObserverList<Foo>* list)
548       : list_(list), added_(false), adder_(1) {}
549 
Observe(int)550   void Observe(int /* x */) override {
551     list_->Clear();
552     list_->AddObserver(&adder_);
553     added_ = true;
554   }
555 
added() const556   bool added() const { return added_; }
adder() const557   const Adder& adder() const { return adder_; }
558 
559  private:
560   ObserverList<Foo>* const list_;
561 
562   bool added_;
563   Adder adder_;
564 };
565 
TEST(ObserverListTest,ClearNotifyAll)566 TEST(ObserverListTest, ClearNotifyAll) {
567   ObserverList<Foo> observer_list;
568   AddInClearObserve a(&observer_list);
569 
570   observer_list.AddObserver(&a);
571 
572   for (auto& observer : observer_list)
573     observer.Observe(1);
574   EXPECT_TRUE(a.added());
575   EXPECT_EQ(1, a.adder().total)
576       << "Adder should observe once and have sum of 1.";
577 }
578 
TEST(ObserverListTest,ClearNotifyExistingOnly)579 TEST(ObserverListTest, ClearNotifyExistingOnly) {
580   ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY);
581   AddInClearObserve a(&observer_list);
582 
583   observer_list.AddObserver(&a);
584 
585   for (auto& observer : observer_list)
586     observer.Observe(1);
587   EXPECT_TRUE(a.added());
588   EXPECT_EQ(0, a.adder().total)
589       << "Adder should not observe, so sum should still be 0.";
590 }
591 
592 class ListDestructor : public Foo {
593  public:
ListDestructor(ObserverList<Foo> * list)594   explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {}
~ListDestructor()595   ~ListDestructor() override {}
596 
Observe(int x)597   void Observe(int x) override { delete list_; }
598 
599  private:
600   ObserverList<Foo>* list_;
601 };
602 
603 
TEST(ObserverListTest,IteratorOutlivesList)604 TEST(ObserverListTest, IteratorOutlivesList) {
605   ObserverList<Foo>* observer_list = new ObserverList<Foo>;
606   ListDestructor a(observer_list);
607   observer_list->AddObserver(&a);
608 
609   for (auto& observer : *observer_list)
610     observer.Observe(0);
611   // If this test fails, there'll be Valgrind errors when this function goes out
612   // of scope.
613 }
614 
TEST(ObserverListTest,BasicStdIterator)615 TEST(ObserverListTest, BasicStdIterator) {
616   using FooList = ObserverList<Foo>;
617   FooList observer_list;
618 
619   // An optimization: begin() and end() do not involve weak pointers on
620   // empty list.
621   EXPECT_FALSE(observer_list.begin().list_);
622   EXPECT_FALSE(observer_list.end().list_);
623 
624   // Iterate over empty list: no effect, no crash.
625   for (auto& i : observer_list)
626     i.Observe(10);
627 
628   Adder a(1), b(-1), c(1), d(-1);
629 
630   observer_list.AddObserver(&a);
631   observer_list.AddObserver(&b);
632   observer_list.AddObserver(&c);
633   observer_list.AddObserver(&d);
634 
635   for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
636        i != e; ++i)
637     i->Observe(1);
638 
639   EXPECT_EQ(1, a.total);
640   EXPECT_EQ(-1, b.total);
641   EXPECT_EQ(1, c.total);
642   EXPECT_EQ(-1, d.total);
643 
644   // Check an iteration over a 'const view' for a given container.
645   const FooList& const_list = observer_list;
646   for (FooList::const_iterator i = const_list.begin(), e = const_list.end();
647        i != e; ++i) {
648     EXPECT_EQ(1, std::abs(i->GetValue()));
649   }
650 
651   for (const auto& o : const_list)
652     EXPECT_EQ(1, std::abs(o.GetValue()));
653 }
654 
TEST(ObserverListTest,StdIteratorRemoveItself)655 TEST(ObserverListTest, StdIteratorRemoveItself) {
656   ObserverList<Foo> observer_list;
657   Adder a(1), b(-1), c(1), d(-1);
658   Disrupter disrupter(&observer_list, true);
659 
660   observer_list.AddObserver(&a);
661   observer_list.AddObserver(&b);
662   observer_list.AddObserver(&disrupter);
663   observer_list.AddObserver(&c);
664   observer_list.AddObserver(&d);
665 
666   for (auto& o : observer_list)
667     o.Observe(1);
668 
669   for (auto& o : observer_list)
670     o.Observe(10);
671 
672   EXPECT_EQ(11, a.total);
673   EXPECT_EQ(-11, b.total);
674   EXPECT_EQ(11, c.total);
675   EXPECT_EQ(-11, d.total);
676 }
677 
TEST(ObserverListTest,StdIteratorRemoveBefore)678 TEST(ObserverListTest, StdIteratorRemoveBefore) {
679   ObserverList<Foo> observer_list;
680   Adder a(1), b(-1), c(1), d(-1);
681   Disrupter disrupter(&observer_list, &b);
682 
683   observer_list.AddObserver(&a);
684   observer_list.AddObserver(&b);
685   observer_list.AddObserver(&disrupter);
686   observer_list.AddObserver(&c);
687   observer_list.AddObserver(&d);
688 
689   for (auto& o : observer_list)
690     o.Observe(1);
691 
692   for (auto& o : observer_list)
693     o.Observe(10);
694 
695   EXPECT_EQ(11, a.total);
696   EXPECT_EQ(-1, b.total);
697   EXPECT_EQ(11, c.total);
698   EXPECT_EQ(-11, d.total);
699 }
700 
TEST(ObserverListTest,StdIteratorRemoveAfter)701 TEST(ObserverListTest, StdIteratorRemoveAfter) {
702   ObserverList<Foo> observer_list;
703   Adder a(1), b(-1), c(1), d(-1);
704   Disrupter disrupter(&observer_list, &c);
705 
706   observer_list.AddObserver(&a);
707   observer_list.AddObserver(&b);
708   observer_list.AddObserver(&disrupter);
709   observer_list.AddObserver(&c);
710   observer_list.AddObserver(&d);
711 
712   for (auto& o : observer_list)
713     o.Observe(1);
714 
715   for (auto& o : observer_list)
716     o.Observe(10);
717 
718   EXPECT_EQ(11, a.total);
719   EXPECT_EQ(-11, b.total);
720   EXPECT_EQ(0, c.total);
721   EXPECT_EQ(-11, d.total);
722 }
723 
TEST(ObserverListTest,StdIteratorRemoveAfterFront)724 TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
725   ObserverList<Foo> observer_list;
726   Adder a(1), b(-1), c(1), d(-1);
727   Disrupter disrupter(&observer_list, &a);
728 
729   observer_list.AddObserver(&a);
730   observer_list.AddObserver(&disrupter);
731   observer_list.AddObserver(&b);
732   observer_list.AddObserver(&c);
733   observer_list.AddObserver(&d);
734 
735   for (auto& o : observer_list)
736     o.Observe(1);
737 
738   for (auto& o : observer_list)
739     o.Observe(10);
740 
741   EXPECT_EQ(1, a.total);
742   EXPECT_EQ(-11, b.total);
743   EXPECT_EQ(11, c.total);
744   EXPECT_EQ(-11, d.total);
745 }
746 
TEST(ObserverListTest,StdIteratorRemoveBeforeBack)747 TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
748   ObserverList<Foo> observer_list;
749   Adder a(1), b(-1), c(1), d(-1);
750   Disrupter disrupter(&observer_list, &d);
751 
752   observer_list.AddObserver(&a);
753   observer_list.AddObserver(&b);
754   observer_list.AddObserver(&c);
755   observer_list.AddObserver(&disrupter);
756   observer_list.AddObserver(&d);
757 
758   for (auto& o : observer_list)
759     o.Observe(1);
760 
761   for (auto& o : observer_list)
762     o.Observe(10);
763 
764   EXPECT_EQ(11, a.total);
765   EXPECT_EQ(-11, b.total);
766   EXPECT_EQ(11, c.total);
767   EXPECT_EQ(0, d.total);
768 }
769 
TEST(ObserverListTest,StdIteratorRemoveFront)770 TEST(ObserverListTest, StdIteratorRemoveFront) {
771   using FooList = ObserverList<Foo>;
772   FooList observer_list;
773   Adder a(1), b(-1), c(1), d(-1);
774   Disrupter disrupter(&observer_list, true);
775 
776   observer_list.AddObserver(&disrupter);
777   observer_list.AddObserver(&a);
778   observer_list.AddObserver(&b);
779   observer_list.AddObserver(&c);
780   observer_list.AddObserver(&d);
781 
782   bool test_disruptor = true;
783   for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
784        i != e; ++i) {
785     i->Observe(1);
786     // Check that second call to i->Observe() would crash here.
787     if (test_disruptor) {
788       EXPECT_FALSE(i.GetCurrent());
789       test_disruptor = false;
790     }
791   }
792 
793   for (auto& o : observer_list)
794     o.Observe(10);
795 
796   EXPECT_EQ(11, a.total);
797   EXPECT_EQ(-11, b.total);
798   EXPECT_EQ(11, c.total);
799   EXPECT_EQ(-11, d.total);
800 }
801 
TEST(ObserverListTest,StdIteratorRemoveBack)802 TEST(ObserverListTest, StdIteratorRemoveBack) {
803   ObserverList<Foo> observer_list;
804   Adder a(1), b(-1), c(1), d(-1);
805   Disrupter disrupter(&observer_list, true);
806 
807   observer_list.AddObserver(&a);
808   observer_list.AddObserver(&b);
809   observer_list.AddObserver(&c);
810   observer_list.AddObserver(&d);
811   observer_list.AddObserver(&disrupter);
812 
813   for (auto& o : observer_list)
814     o.Observe(1);
815 
816   for (auto& o : observer_list)
817     o.Observe(10);
818 
819   EXPECT_EQ(11, a.total);
820   EXPECT_EQ(-11, b.total);
821   EXPECT_EQ(11, c.total);
822   EXPECT_EQ(-11, d.total);
823 }
824 
TEST(ObserverListTest,NestedLoop)825 TEST(ObserverListTest, NestedLoop) {
826   ObserverList<Foo> observer_list;
827   Adder a(1), b(-1), c(1), d(-1);
828   Disrupter disrupter(&observer_list, true);
829 
830   observer_list.AddObserver(&disrupter);
831   observer_list.AddObserver(&a);
832   observer_list.AddObserver(&b);
833   observer_list.AddObserver(&c);
834   observer_list.AddObserver(&d);
835 
836   for (auto& o : observer_list) {
837     o.Observe(10);
838 
839     for (auto& o : observer_list)
840       o.Observe(1);
841   }
842 
843   EXPECT_EQ(15, a.total);
844   EXPECT_EQ(-15, b.total);
845   EXPECT_EQ(15, c.total);
846   EXPECT_EQ(-15, d.total);
847 }
848 
TEST(ObserverListTest,NonCompactList)849 TEST(ObserverListTest, NonCompactList) {
850   ObserverList<Foo> observer_list;
851   Adder a(1), b(-1);
852 
853   Disrupter disrupter1(&observer_list, true);
854   Disrupter disrupter2(&observer_list, true);
855 
856   // Disrupt itself and another one.
857   disrupter1.SetDoomed(&disrupter2);
858 
859   observer_list.AddObserver(&disrupter1);
860   observer_list.AddObserver(&disrupter2);
861   observer_list.AddObserver(&a);
862   observer_list.AddObserver(&b);
863 
864   for (auto& o : observer_list) {
865     // Get the { nullptr, nullptr, &a, &b } non-compact list
866     // on the first inner pass.
867     o.Observe(10);
868 
869     for (auto& o : observer_list)
870       o.Observe(1);
871   }
872 
873   EXPECT_EQ(13, a.total);
874   EXPECT_EQ(-13, b.total);
875 }
876 
TEST(ObserverListTest,BecomesEmptyThanNonEmpty)877 TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
878   ObserverList<Foo> observer_list;
879   Adder a(1), b(-1);
880 
881   Disrupter disrupter1(&observer_list, true);
882   Disrupter disrupter2(&observer_list, true);
883 
884   // Disrupt itself and another one.
885   disrupter1.SetDoomed(&disrupter2);
886 
887   observer_list.AddObserver(&disrupter1);
888   observer_list.AddObserver(&disrupter2);
889 
890   bool add_observers = true;
891   for (auto& o : observer_list) {
892     // Get the { nullptr, nullptr } empty list on the first inner pass.
893     o.Observe(10);
894 
895     for (auto& o : observer_list)
896       o.Observe(1);
897 
898     if (add_observers) {
899       observer_list.AddObserver(&a);
900       observer_list.AddObserver(&b);
901       add_observers = false;
902     }
903   }
904 
905   EXPECT_EQ(12, a.total);
906   EXPECT_EQ(-12, b.total);
907 }
908 
TEST(ObserverListTest,AddObserverInTheLastObserve)909 TEST(ObserverListTest, AddObserverInTheLastObserve) {
910   using FooList = ObserverList<Foo>;
911   FooList observer_list;
912 
913   AddInObserve<FooList> a(&observer_list);
914   Adder b(-1);
915 
916   a.SetToAdd(&b);
917   observer_list.AddObserver(&a);
918 
919   auto it = observer_list.begin();
920   while (it != observer_list.end()) {
921     auto& observer = *it;
922     // Intentionally increment the iterator before calling Observe(). The
923     // ObserverList starts with only one observer, and it == observer_list.end()
924     // should be true after the next line.
925     ++it;
926     // However, the first Observe() call will add a second observer: at this
927     // point, it != observer_list.end() should be true, and Observe() should be
928     // called on the newly added observer on the next iteration of the loop.
929     observer.Observe(10);
930   }
931 
932   EXPECT_EQ(-10, b.total);
933 }
934 
935 }  // namespace base
936