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