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 };
     26 
     27 class Adder : public Foo {
     28  public:
     29   explicit Adder(int scaler) : total(0), scaler_(scaler) {}
     30   void Observe(int x) override { total += x * scaler_; }
     31   ~Adder() override {}
     32   int total;
     33 
     34  private:
     35   int scaler_;
     36 };
     37 
     38 class Disrupter : public Foo {
     39  public:
     40   Disrupter(ObserverList<Foo>* list, Foo* doomed)
     41       : list_(list),
     42         doomed_(doomed) {
     43   }
     44   ~Disrupter() override {}
     45   void Observe(int x) override { list_->RemoveObserver(doomed_); }
     46 
     47  private:
     48   ObserverList<Foo>* list_;
     49   Foo* doomed_;
     50 };
     51 
     52 class ThreadSafeDisrupter : public Foo {
     53  public:
     54   ThreadSafeDisrupter(ObserverListThreadSafe<Foo>* list, Foo* doomed)
     55       : list_(list),
     56         doomed_(doomed) {
     57   }
     58   ~ThreadSafeDisrupter() override {}
     59   void Observe(int x) override { list_->RemoveObserver(doomed_); }
     60 
     61  private:
     62   ObserverListThreadSafe<Foo>* list_;
     63   Foo* doomed_;
     64 };
     65 
     66 template <typename ObserverListType>
     67 class AddInObserve : public Foo {
     68  public:
     69   explicit AddInObserve(ObserverListType* observer_list)
     70       : added(false),
     71         observer_list(observer_list),
     72         adder(1) {
     73   }
     74 
     75   void Observe(int x) override {
     76     if (!added) {
     77       added = true;
     78       observer_list->AddObserver(&adder);
     79     }
     80   }
     81 
     82   bool added;
     83   ObserverListType* observer_list;
     84   Adder adder;
     85 };
     86 
     87 
     88 static const int kThreadRunTime = 2000;  // ms to run the multi-threaded test.
     89 
     90 // A thread for use in the ThreadSafeObserver test
     91 // which will add and remove itself from the notification
     92 // list repeatedly.
     93 class AddRemoveThread : public PlatformThread::Delegate,
     94                         public Foo {
     95  public:
     96   AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify)
     97       : list_(list),
     98         loop_(nullptr),
     99         in_list_(false),
    100         start_(Time::Now()),
    101         count_observes_(0),
    102         count_addtask_(0),
    103         do_notifies_(notify),
    104         weak_factory_(this) {
    105   }
    106 
    107   ~AddRemoveThread() override {}
    108 
    109   void ThreadMain() override {
    110     loop_ = new MessageLoop();  // Fire up a message loop.
    111     loop_->task_runner()->PostTask(
    112         FROM_HERE,
    113         base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
    114     RunLoop().Run();
    115     //LOG(ERROR) << "Loop 0x" << std::hex << loop_ << " done. " <<
    116     //    count_observes_ << ", " << count_addtask_;
    117     delete loop_;
    118     loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef);
    119     delete this;
    120   }
    121 
    122   // This task just keeps posting to itself in an attempt
    123   // to race with the notifier.
    124   void AddTask() {
    125     count_addtask_++;
    126 
    127     if ((Time::Now() - start_).InMilliseconds() > kThreadRunTime) {
    128       VLOG(1) << "DONE!";
    129       return;
    130     }
    131 
    132     if (!in_list_) {
    133       list_->AddObserver(this);
    134       in_list_ = true;
    135     }
    136 
    137     if (do_notifies_) {
    138       list_->Notify(FROM_HERE, &Foo::Observe, 10);
    139     }
    140 
    141     loop_->task_runner()->PostTask(
    142         FROM_HERE,
    143         base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
    144   }
    145 
    146   void Quit() {
    147     loop_->task_runner()->PostTask(FROM_HERE,
    148                                    MessageLoop::QuitWhenIdleClosure());
    149   }
    150 
    151   void Observe(int x) override {
    152     count_observes_++;
    153 
    154     // If we're getting called after we removed ourselves from
    155     // the list, that is very bad!
    156     DCHECK(in_list_);
    157 
    158     // This callback should fire on the appropriate thread
    159     EXPECT_EQ(loop_, MessageLoop::current());
    160 
    161     list_->RemoveObserver(this);
    162     in_list_ = false;
    163   }
    164 
    165  private:
    166   ObserverListThreadSafe<Foo>* list_;
    167   MessageLoop* loop_;
    168   bool in_list_;        // Are we currently registered for notifications.
    169                         // in_list_ is only used on |this| thread.
    170   Time start_;          // The time we started the test.
    171 
    172   int count_observes_;  // Number of times we observed.
    173   int count_addtask_;   // Number of times thread AddTask was called
    174   bool do_notifies_;    // Whether these threads should do notifications.
    175 
    176   base::WeakPtrFactory<AddRemoveThread> weak_factory_;
    177 };
    178 
    179 TEST(ObserverListTest, BasicTest) {
    180   ObserverList<Foo> observer_list;
    181   Adder a(1), b(-1), c(1), d(-1), e(-1);
    182   Disrupter evil(&observer_list, &c);
    183 
    184   observer_list.AddObserver(&a);
    185   observer_list.AddObserver(&b);
    186 
    187   EXPECT_TRUE(observer_list.HasObserver(&a));
    188   EXPECT_FALSE(observer_list.HasObserver(&c));
    189 
    190   FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
    191 
    192   observer_list.AddObserver(&evil);
    193   observer_list.AddObserver(&c);
    194   observer_list.AddObserver(&d);
    195 
    196   // Removing an observer not in the list should do nothing.
    197   observer_list.RemoveObserver(&e);
    198 
    199   FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
    200 
    201   EXPECT_EQ(20, a.total);
    202   EXPECT_EQ(-20, b.total);
    203   EXPECT_EQ(0, c.total);
    204   EXPECT_EQ(-10, d.total);
    205   EXPECT_EQ(0, e.total);
    206 }
    207 
    208 TEST(ObserverListThreadSafeTest, BasicTest) {
    209   MessageLoop loop;
    210 
    211   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
    212       new ObserverListThreadSafe<Foo>);
    213   Adder a(1);
    214   Adder b(-1);
    215   Adder c(1);
    216   Adder d(-1);
    217   ThreadSafeDisrupter evil(observer_list.get(), &c);
    218 
    219   observer_list->AddObserver(&a);
    220   observer_list->AddObserver(&b);
    221 
    222   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
    223   RunLoop().RunUntilIdle();
    224 
    225   observer_list->AddObserver(&evil);
    226   observer_list->AddObserver(&c);
    227   observer_list->AddObserver(&d);
    228 
    229   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
    230   RunLoop().RunUntilIdle();
    231 
    232   EXPECT_EQ(20, a.total);
    233   EXPECT_EQ(-20, b.total);
    234   EXPECT_EQ(0, c.total);
    235   EXPECT_EQ(-10, d.total);
    236 }
    237 
    238 TEST(ObserverListThreadSafeTest, RemoveObserver) {
    239   MessageLoop loop;
    240 
    241   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
    242       new ObserverListThreadSafe<Foo>);
    243   Adder a(1), b(1);
    244 
    245   // A workaround for the compiler bug. See http://crbug.com/121960.
    246   EXPECT_NE(&a, &b);
    247 
    248   // Should do nothing.
    249   observer_list->RemoveObserver(&a);
    250   observer_list->RemoveObserver(&b);
    251 
    252   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
    253   RunLoop().RunUntilIdle();
    254 
    255   EXPECT_EQ(0, a.total);
    256   EXPECT_EQ(0, b.total);
    257 
    258   observer_list->AddObserver(&a);
    259 
    260   // Should also do nothing.
    261   observer_list->RemoveObserver(&b);
    262 
    263   observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
    264   RunLoop().RunUntilIdle();
    265 
    266   EXPECT_EQ(10, a.total);
    267   EXPECT_EQ(0, b.total);
    268 }
    269 
    270 TEST(ObserverListThreadSafeTest, WithoutMessageLoop) {
    271   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
    272       new ObserverListThreadSafe<Foo>);
    273 
    274   Adder a(1), b(1), c(1);
    275 
    276   // No MessageLoop, so these should not be added.
    277   observer_list->AddObserver(&a);
    278   observer_list->AddObserver(&b);
    279 
    280   {
    281     // Add c when there's a loop.
    282     MessageLoop loop;
    283     observer_list->AddObserver(&c);
    284 
    285     observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
    286     RunLoop().RunUntilIdle();
    287 
    288     EXPECT_EQ(0, a.total);
    289     EXPECT_EQ(0, b.total);
    290     EXPECT_EQ(10, c.total);
    291 
    292     // Now add a when there's a loop.
    293     observer_list->AddObserver(&a);
    294 
    295     // Remove c when there's a loop.
    296     observer_list->RemoveObserver(&c);
    297 
    298     // Notify again.
    299     observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
    300     RunLoop().RunUntilIdle();
    301 
    302     EXPECT_EQ(20, a.total);
    303     EXPECT_EQ(0, b.total);
    304     EXPECT_EQ(10, c.total);
    305   }
    306 
    307   // Removing should always succeed with or without a loop.
    308   observer_list->RemoveObserver(&a);
    309 
    310   // Notifying should not fail but should also be a no-op.
    311   MessageLoop loop;
    312   observer_list->AddObserver(&b);
    313   observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
    314   RunLoop().RunUntilIdle();
    315 
    316   EXPECT_EQ(20, a.total);
    317   EXPECT_EQ(30, b.total);
    318   EXPECT_EQ(10, c.total);
    319 }
    320 
    321 class FooRemover : public Foo {
    322  public:
    323   explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {}
    324   ~FooRemover() override {}
    325 
    326   void AddFooToRemove(Foo* foo) {
    327     foos_.push_back(foo);
    328   }
    329 
    330   void Observe(int x) override {
    331     std::vector<Foo*> tmp;
    332     tmp.swap(foos_);
    333     for (std::vector<Foo*>::iterator it = tmp.begin();
    334          it != tmp.end(); ++it) {
    335       list_->RemoveObserver(*it);
    336     }
    337   }
    338 
    339  private:
    340   const scoped_refptr<ObserverListThreadSafe<Foo> > list_;
    341   std::vector<Foo*> foos_;
    342 };
    343 
    344 TEST(ObserverListThreadSafeTest, RemoveMultipleObservers) {
    345   MessageLoop loop;
    346   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
    347       new ObserverListThreadSafe<Foo>);
    348 
    349   FooRemover a(observer_list.get());
    350   Adder b(1);
    351 
    352   observer_list->AddObserver(&a);
    353   observer_list->AddObserver(&b);
    354 
    355   a.AddFooToRemove(&a);
    356   a.AddFooToRemove(&b);
    357 
    358   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
    359   RunLoop().RunUntilIdle();
    360 }
    361 
    362 // A test driver for a multi-threaded notification loop.  Runs a number
    363 // of observer threads, each of which constantly adds/removes itself
    364 // from the observer list.  Optionally, if cross_thread_notifies is set
    365 // to true, the observer threads will also trigger notifications to
    366 // all observers.
    367 static void ThreadSafeObserverHarness(int num_threads,
    368                                       bool cross_thread_notifies) {
    369   MessageLoop loop;
    370 
    371   const int kMaxThreads = 15;
    372   num_threads = num_threads > kMaxThreads ? kMaxThreads : num_threads;
    373 
    374   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
    375       new ObserverListThreadSafe<Foo>);
    376   Adder a(1);
    377   Adder b(-1);
    378   Adder c(1);
    379   Adder d(-1);
    380 
    381   observer_list->AddObserver(&a);
    382   observer_list->AddObserver(&b);
    383 
    384   AddRemoveThread* threaded_observer[kMaxThreads];
    385   base::PlatformThreadHandle threads[kMaxThreads];
    386   for (int index = 0; index < num_threads; index++) {
    387     threaded_observer[index] = new AddRemoveThread(observer_list.get(), false);
    388     EXPECT_TRUE(PlatformThread::Create(0,
    389                 threaded_observer[index], &threads[index]));
    390   }
    391 
    392   Time start = Time::Now();
    393   while (true) {
    394     if ((Time::Now() - start).InMilliseconds() > kThreadRunTime)
    395       break;
    396 
    397     observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
    398 
    399     RunLoop().RunUntilIdle();
    400   }
    401 
    402   for (int index = 0; index < num_threads; index++) {
    403     threaded_observer[index]->Quit();
    404     PlatformThread::Join(threads[index]);
    405   }
    406 }
    407 
    408 TEST(ObserverListThreadSafeTest, CrossThreadObserver) {
    409   // Use 7 observer threads.  Notifications only come from
    410   // the main thread.
    411   ThreadSafeObserverHarness(7, false);
    412 }
    413 
    414 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) {
    415   // Use 3 observer threads.  Notifications will fire from
    416   // the main thread and all 3 observer threads.
    417   ThreadSafeObserverHarness(3, true);
    418 }
    419 
    420 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) {
    421   MessageLoop* loop = new MessageLoop;
    422   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
    423       new ObserverListThreadSafe<Foo>);
    424 
    425   Adder a(1);
    426   observer_list->AddObserver(&a);
    427   delete loop;
    428   // Test passes if we don't crash here.
    429   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
    430 }
    431 
    432 TEST(ObserverListTest, Existing) {
    433   ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY);
    434   Adder a(1);
    435   AddInObserve<ObserverList<Foo> > b(&observer_list);
    436 
    437   observer_list.AddObserver(&a);
    438   observer_list.AddObserver(&b);
    439 
    440   FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
    441 
    442   EXPECT_TRUE(b.added);
    443   // B's adder should not have been notified because it was added during
    444   // notification.
    445   EXPECT_EQ(0, b.adder.total);
    446 
    447   // Notify again to make sure b's adder is notified.
    448   FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
    449   EXPECT_EQ(1, b.adder.total);
    450 }
    451 
    452 // Same as above, but for ObserverListThreadSafe
    453 TEST(ObserverListThreadSafeTest, Existing) {
    454   MessageLoop loop;
    455   scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
    456       new ObserverListThreadSafe<Foo>(ObserverList<Foo>::NOTIFY_EXISTING_ONLY));
    457   Adder a(1);
    458   AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get());
    459 
    460   observer_list->AddObserver(&a);
    461   observer_list->AddObserver(&b);
    462 
    463   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
    464   RunLoop().RunUntilIdle();
    465 
    466   EXPECT_TRUE(b.added);
    467   // B's adder should not have been notified because it was added during
    468   // notification.
    469   EXPECT_EQ(0, b.adder.total);
    470 
    471   // Notify again to make sure b's adder is notified.
    472   observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
    473   RunLoop().RunUntilIdle();
    474   EXPECT_EQ(1, b.adder.total);
    475 }
    476 
    477 class AddInClearObserve : public Foo {
    478  public:
    479   explicit AddInClearObserve(ObserverList<Foo>* list)
    480       : list_(list), added_(false), adder_(1) {}
    481 
    482   void Observe(int /* x */) override {
    483     list_->Clear();
    484     list_->AddObserver(&adder_);
    485     added_ = true;
    486   }
    487 
    488   bool added() const { return added_; }
    489   const Adder& adder() const { return adder_; }
    490 
    491  private:
    492   ObserverList<Foo>* const list_;
    493 
    494   bool added_;
    495   Adder adder_;
    496 };
    497 
    498 TEST(ObserverListTest, ClearNotifyAll) {
    499   ObserverList<Foo> observer_list;
    500   AddInClearObserve a(&observer_list);
    501 
    502   observer_list.AddObserver(&a);
    503 
    504   FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
    505   EXPECT_TRUE(a.added());
    506   EXPECT_EQ(1, a.adder().total)
    507       << "Adder should observe once and have sum of 1.";
    508 }
    509 
    510 TEST(ObserverListTest, ClearNotifyExistingOnly) {
    511   ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY);
    512   AddInClearObserve a(&observer_list);
    513 
    514   observer_list.AddObserver(&a);
    515 
    516   FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
    517   EXPECT_TRUE(a.added());
    518   EXPECT_EQ(0, a.adder().total)
    519       << "Adder should not observe, so sum should still be 0.";
    520 }
    521 
    522 class ListDestructor : public Foo {
    523  public:
    524   explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {}
    525   ~ListDestructor() override {}
    526 
    527   void Observe(int x) override { delete list_; }
    528 
    529  private:
    530   ObserverList<Foo>* list_;
    531 };
    532 
    533 
    534 TEST(ObserverListTest, IteratorOutlivesList) {
    535   ObserverList<Foo>* observer_list = new ObserverList<Foo>;
    536   ListDestructor a(observer_list);
    537   observer_list->AddObserver(&a);
    538 
    539   FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0));
    540   // If this test fails, there'll be Valgrind errors when this function goes out
    541   // of scope.
    542 }
    543 
    544 }  // namespace
    545 }  // namespace base
    546