Home | History | Annotate | Download | only in base
      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;
     24   virtual ~Foo() {}
     25   virtual int GetValue() const { return 0; }
     26 };
     27 
     28 class Adder : public Foo {
     29  public:
     30   explicit Adder(int scaler) : total(0), scaler_(scaler) {}
     31   ~Adder() override {}
     32 
     33   void Observe(int x) override { total += x * scaler_; }
     34   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:
     44   Disrupter(ObserverList<Foo>* list, Foo* doomed, bool remove_self)
     45       : list_(list), doomed_(doomed), remove_self_(remove_self) {}
     46   Disrupter(ObserverList<Foo>* list, Foo* doomed)
     47       : Disrupter(list, doomed, false) {}
     48   Disrupter(ObserverList<Foo>* list, bool remove_self)
     49       : Disrupter(list, nullptr, remove_self) {}
     50 
     51   ~Disrupter() override {}
     52 
     53   void Observe(int x) override {
     54     if (remove_self_)
     55       list_->RemoveObserver(this);
     56     if (doomed_)
     57       list_->RemoveObserver(doomed_);
     58   }
     59 
     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:
     70   ThreadSafeDisrupter(ObserverListThreadSafe<Foo>* list, Foo* doomed)
     71       : list_(list),
     72         doomed_(doomed) {
     73   }
     74   ~ThreadSafeDisrupter() override {}
     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:
     85   explicit AddInObserve(ObserverListType* observer_list)
     86       : observer_list(observer_list), to_add_() {}
     87 
     88   void SetToAdd(Foo* to_add) { to_add_ = to_add; }
     89 
     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:
    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 
    121   ~AddRemoveThread() override {}
    122 
    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.
    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 
    158   void Quit() {
    159     loop_->task_runner()->PostTask(FROM_HERE,
    160                                    MessageLoop::QuitWhenIdleClosure());
    161   }
    162 
    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 
    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 
    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 
    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 
    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 
    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 
    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:
    385   explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {}
    386   ~FooRemover() override {}
    387 
    388   void AddFooToRemove(Foo* foo) {
    389     foos_.push_back(foo);
    390   }
    391 
    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 
    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.
    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 
    470 TEST(ObserverListThreadSafeTest, CrossThreadObserver) {
    471   // Use 7 observer threads.  Notifications only come from
    472   // the main thread.
    473   ThreadSafeObserverHarness(7, false);
    474 }
    475 
    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 
    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 
    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
    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:
    547   explicit AddInClearObserve(ObserverList<Foo>* list)
    548       : list_(list), added_(false), adder_(1) {}
    549 
    550   void Observe(int /* x */) override {
    551     list_->Clear();
    552     list_->AddObserver(&adder_);
    553     added_ = true;
    554   }
    555 
    556   bool added() const { return added_; }
    557   const Adder& adder() const { return adder_; }
    558 
    559  private:
    560   ObserverList<Foo>* const list_;
    561 
    562   bool added_;
    563   Adder adder_;
    564 };
    565 
    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 
    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:
    594   explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {}
    595   ~ListDestructor() override {}
    596 
    597   void Observe(int x) override { delete list_; }
    598 
    599  private:
    600   ObserverList<Foo>* list_;
    601 };
    602 
    603 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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