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