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