Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(713)

Side by Side Diff: base/observer_list_unittest.cc

Issue 2340583005: Base ObserverList: Add basic support for standard C++ iterators. (Closed)
Patch Set: Remove excessive mutable. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/observer_list.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/observer_list.h" 5 #include "base/observer_list.h"
6 #include "base/observer_list_threadsafe.h" 6 #include "base/observer_list_threadsafe.h"
7 7
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/memory/weak_ptr.h" 12 #include "base/memory/weak_ptr.h"
13 #include "base/run_loop.h" 13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
15 #include "base/threading/platform_thread.h" 15 #include "base/threading/platform_thread.h"
16 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
17 17
18 namespace base { 18 namespace base {
19 namespace { 19 namespace {
20 20
21 class Foo { 21 class Foo {
22 public: 22 public:
23 virtual void Observe(int x) = 0; 23 virtual void Observe(int x) = 0;
24 virtual ~Foo() {} 24 virtual ~Foo() {}
25 virtual int GetValue() const { return 0; }
25 }; 26 };
26 27
27 class Adder : public Foo { 28 class Adder : public Foo {
28 public: 29 public:
29 explicit Adder(int scaler) : total(0), scaler_(scaler) {} 30 explicit Adder(int scaler) : total(0), scaler_(scaler) {}
31 ~Adder() override {}
32
30 void Observe(int x) override { total += x * scaler_; } 33 void Observe(int x) override { total += x * scaler_; }
31 ~Adder() override {} 34 int GetValue() const override { return total; }
35
32 int total; 36 int total;
33 37
34 private: 38 private:
35 int scaler_; 39 int scaler_;
36 }; 40 };
37 41
38 class Disrupter : public Foo { 42 class Disrupter : public Foo {
39 public: 43 public:
44 Disrupter(ObserverList<Foo>* list, Foo* doomed, bool remove_self)
45 : list_(list), doomed_(doomed), remove_self_(remove_self) {}
40 Disrupter(ObserverList<Foo>* list, Foo* doomed) 46 Disrupter(ObserverList<Foo>* list, Foo* doomed)
41 : list_(list), 47 : Disrupter(list, doomed, false) {}
42 doomed_(doomed) { 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_);
43 } 58 }
44 ~Disrupter() override {} 59
45 void Observe(int x) override { list_->RemoveObserver(doomed_); } 60 void SetDoomed(Foo* doomed) { doomed_ = doomed; }
46 61
47 private: 62 private:
48 ObserverList<Foo>* list_; 63 ObserverList<Foo>* list_;
49 Foo* doomed_; 64 Foo* doomed_;
65 bool remove_self_;
50 }; 66 };
51 67
52 class ThreadSafeDisrupter : public Foo { 68 class ThreadSafeDisrupter : public Foo {
53 public: 69 public:
54 ThreadSafeDisrupter(ObserverListThreadSafe<Foo>* list, Foo* doomed) 70 ThreadSafeDisrupter(ObserverListThreadSafe<Foo>* list, Foo* doomed)
55 : list_(list), 71 : list_(list),
56 doomed_(doomed) { 72 doomed_(doomed) {
57 } 73 }
58 ~ThreadSafeDisrupter() override {} 74 ~ThreadSafeDisrupter() override {}
59 void Observe(int x) override { list_->RemoveObserver(doomed_); } 75 void Observe(int x) override { list_->RemoveObserver(doomed_); }
60 76
61 private: 77 private:
62 ObserverListThreadSafe<Foo>* list_; 78 ObserverListThreadSafe<Foo>* list_;
63 Foo* doomed_; 79 Foo* doomed_;
64 }; 80 };
65 81
66 template <typename ObserverListType> 82 template <typename ObserverListType>
67 class AddInObserve : public Foo { 83 class AddInObserve : public Foo {
68 public: 84 public:
69 explicit AddInObserve(ObserverListType* observer_list) 85 explicit AddInObserve(ObserverListType* observer_list)
70 : added(false), 86 : observer_list(observer_list), to_add_() {}
71 observer_list(observer_list), 87
72 adder(1) { 88 void SetToAdd(Foo* to_add) { to_add_ = to_add; }
73 }
74 89
75 void Observe(int x) override { 90 void Observe(int x) override {
76 if (!added) { 91 if (to_add_) {
77 added = true; 92 observer_list->AddObserver(to_add_);
78 observer_list->AddObserver(&adder); 93 to_add_ = nullptr;
79 } 94 }
80 } 95 }
81 96
82 bool added;
83 ObserverListType* observer_list; 97 ObserverListType* observer_list;
84 Adder adder; 98 Foo* to_add_;
85 }; 99 };
86 100
87 101
88 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test. 102 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test.
89 103
90 // A thread for use in the ThreadSafeObserver test 104 // A thread for use in the ThreadSafeObserver test
91 // which will add and remove itself from the notification 105 // which will add and remove itself from the notification
92 // list repeatedly. 106 // list repeatedly.
93 class AddRemoveThread : public PlatformThread::Delegate, 107 class AddRemoveThread : public PlatformThread::Delegate,
94 public Foo { 108 public Foo {
(...skipping 10 matching lines...) Expand all
105 } 119 }
106 120
107 ~AddRemoveThread() override {} 121 ~AddRemoveThread() override {}
108 122
109 void ThreadMain() override { 123 void ThreadMain() override {
110 loop_ = new MessageLoop(); // Fire up a message loop. 124 loop_ = new MessageLoop(); // Fire up a message loop.
111 loop_->task_runner()->PostTask( 125 loop_->task_runner()->PostTask(
112 FROM_HERE, 126 FROM_HERE,
113 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr())); 127 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
114 RunLoop().Run(); 128 RunLoop().Run();
115 //LOG(ERROR) << "Loop 0x" << std::hex << loop_ << " done. " <<
116 // count_observes_ << ", " << count_addtask_;
117 delete loop_; 129 delete loop_;
118 loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef); 130 loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef);
119 delete this; 131 delete this;
120 } 132 }
121 133
122 // This task just keeps posting to itself in an attempt 134 // This task just keeps posting to itself in an attempt
123 // to race with the notifier. 135 // to race with the notifier.
124 void AddTask() { 136 void AddTask() {
125 count_addtask_++; 137 count_addtask_++;
126 138
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 // in_list_ is only used on |this| thread. 181 // in_list_ is only used on |this| thread.
170 Time start_; // The time we started the test. 182 Time start_; // The time we started the test.
171 183
172 int count_observes_; // Number of times we observed. 184 int count_observes_; // Number of times we observed.
173 int count_addtask_; // Number of times thread AddTask was called 185 int count_addtask_; // Number of times thread AddTask was called
174 bool do_notifies_; // Whether these threads should do notifications. 186 bool do_notifies_; // Whether these threads should do notifications.
175 187
176 base::WeakPtrFactory<AddRemoveThread> weak_factory_; 188 base::WeakPtrFactory<AddRemoveThread> weak_factory_;
177 }; 189 };
178 190
191 } // namespace
192
179 TEST(ObserverListTest, BasicTest) { 193 TEST(ObserverListTest, BasicTest) {
180 ObserverList<Foo> observer_list; 194 ObserverList<Foo> observer_list;
181 Adder a(1), b(-1), c(1), d(-1), e(-1); 195 Adder a(1), b(-1), c(1), d(-1), e(-1);
182 Disrupter evil(&observer_list, &c); 196 Disrupter evil(&observer_list, &c);
183 197
184 observer_list.AddObserver(&a); 198 observer_list.AddObserver(&a);
185 observer_list.AddObserver(&b); 199 observer_list.AddObserver(&b);
186 200
187 EXPECT_TRUE(observer_list.HasObserver(&a)); 201 EXPECT_TRUE(observer_list.HasObserver(&a));
188 EXPECT_FALSE(observer_list.HasObserver(&c)); 202 EXPECT_FALSE(observer_list.HasObserver(&c));
189 203
190 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10)); 204 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
191 205
192 observer_list.AddObserver(&evil); 206 observer_list.AddObserver(&evil);
193 observer_list.AddObserver(&c); 207 observer_list.AddObserver(&c);
194 observer_list.AddObserver(&d); 208 observer_list.AddObserver(&d);
195 209
196 // Removing an observer not in the list should do nothing. 210 // Removing an observer not in the list should do nothing.
197 observer_list.RemoveObserver(&e); 211 observer_list.RemoveObserver(&e);
198 212
199 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10)); 213 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
200 214
201 EXPECT_EQ(20, a.total); 215 EXPECT_EQ(20, a.total);
202 EXPECT_EQ(-20, b.total); 216 EXPECT_EQ(-20, b.total);
203 EXPECT_EQ(0, c.total); 217 EXPECT_EQ(0, c.total);
204 EXPECT_EQ(-10, d.total); 218 EXPECT_EQ(-10, d.total);
205 EXPECT_EQ(0, e.total); 219 EXPECT_EQ(0, e.total);
206 } 220 }
207 221
222 TEST(ObserverListTest, DisruptSelf) {
223 ObserverList<Foo> observer_list;
224 Adder a(1), b(-1), c(1), d(-1);
225 Disrupter evil(&observer_list, true);
226
227 observer_list.AddObserver(&a);
228 observer_list.AddObserver(&b);
229
230 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
231
232 observer_list.AddObserver(&evil);
233 observer_list.AddObserver(&c);
234 observer_list.AddObserver(&d);
235
236 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
237
238 EXPECT_EQ(20, a.total);
239 EXPECT_EQ(-20, b.total);
240 EXPECT_EQ(10, c.total);
241 EXPECT_EQ(-10, d.total);
242 }
243
244 TEST(ObserverListTest, DisruptBefore) {
245 ObserverList<Foo> observer_list;
246 Adder a(1), b(-1), c(1), d(-1);
247 Disrupter evil(&observer_list, &b);
248
249 observer_list.AddObserver(&a);
250 observer_list.AddObserver(&b);
251 observer_list.AddObserver(&evil);
252 observer_list.AddObserver(&c);
253 observer_list.AddObserver(&d);
254
255 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
256 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
257
258 EXPECT_EQ(20, a.total);
259 EXPECT_EQ(-10, b.total);
260 EXPECT_EQ(20, c.total);
261 EXPECT_EQ(-20, d.total);
262 }
263
208 TEST(ObserverListThreadSafeTest, BasicTest) { 264 TEST(ObserverListThreadSafeTest, BasicTest) {
209 MessageLoop loop; 265 MessageLoop loop;
210 266
211 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 267 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
212 new ObserverListThreadSafe<Foo>); 268 new ObserverListThreadSafe<Foo>);
213 Adder a(1); 269 Adder a(1);
214 Adder b(-1); 270 Adder b(-1);
215 Adder c(1); 271 Adder c(1);
216 Adder d(-1); 272 Adder d(-1);
217 ThreadSafeDisrupter evil(observer_list.get(), &c); 273 ThreadSafeDisrupter evil(observer_list.get(), &c);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 observer_list->AddObserver(&a); 482 observer_list->AddObserver(&a);
427 delete loop; 483 delete loop;
428 // Test passes if we don't crash here. 484 // Test passes if we don't crash here.
429 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 485 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
430 } 486 }
431 487
432 TEST(ObserverListTest, Existing) { 488 TEST(ObserverListTest, Existing) {
433 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); 489 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY);
434 Adder a(1); 490 Adder a(1);
435 AddInObserve<ObserverList<Foo> > b(&observer_list); 491 AddInObserve<ObserverList<Foo> > b(&observer_list);
492 Adder c(1);
493 b.SetToAdd(&c);
436 494
437 observer_list.AddObserver(&a); 495 observer_list.AddObserver(&a);
438 observer_list.AddObserver(&b); 496 observer_list.AddObserver(&b);
439 497
440 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); 498 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
441 499
442 EXPECT_TRUE(b.added); 500 EXPECT_FALSE(b.to_add_);
443 // B's adder should not have been notified because it was added during 501 // B's adder should not have been notified because it was added during
444 // notification. 502 // notification.
445 EXPECT_EQ(0, b.adder.total); 503 EXPECT_EQ(0, c.total);
446 504
447 // Notify again to make sure b's adder is notified. 505 // Notify again to make sure b's adder is notified.
448 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); 506 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1));
449 EXPECT_EQ(1, b.adder.total); 507 EXPECT_EQ(1, c.total);
450 } 508 }
451 509
452 // Same as above, but for ObserverListThreadSafe 510 // Same as above, but for ObserverListThreadSafe
453 TEST(ObserverListThreadSafeTest, Existing) { 511 TEST(ObserverListThreadSafeTest, Existing) {
454 MessageLoop loop; 512 MessageLoop loop;
455 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 513 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
456 new ObserverListThreadSafe<Foo>(ObserverList<Foo>::NOTIFY_EXISTING_ONLY)); 514 new ObserverListThreadSafe<Foo>(ObserverList<Foo>::NOTIFY_EXISTING_ONLY));
457 Adder a(1); 515 Adder a(1);
458 AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get()); 516 AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get());
517 Adder c(1);
518 b.SetToAdd(&c);
459 519
460 observer_list->AddObserver(&a); 520 observer_list->AddObserver(&a);
461 observer_list->AddObserver(&b); 521 observer_list->AddObserver(&b);
462 522
463 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 523 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
464 RunLoop().RunUntilIdle(); 524 RunLoop().RunUntilIdle();
465 525
466 EXPECT_TRUE(b.added); 526 EXPECT_FALSE(b.to_add_);
467 // B's adder should not have been notified because it was added during 527 // B's adder should not have been notified because it was added during
468 // notification. 528 // notification.
469 EXPECT_EQ(0, b.adder.total); 529 EXPECT_EQ(0, c.total);
470 530
471 // Notify again to make sure b's adder is notified. 531 // Notify again to make sure b's adder is notified.
472 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 532 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
473 RunLoop().RunUntilIdle(); 533 RunLoop().RunUntilIdle();
474 EXPECT_EQ(1, b.adder.total); 534 EXPECT_EQ(1, c.total);
475 } 535 }
476 536
477 class AddInClearObserve : public Foo { 537 class AddInClearObserve : public Foo {
478 public: 538 public:
479 explicit AddInClearObserve(ObserverList<Foo>* list) 539 explicit AddInClearObserve(ObserverList<Foo>* list)
480 : list_(list), added_(false), adder_(1) {} 540 : list_(list), added_(false), adder_(1) {}
481 541
482 void Observe(int /* x */) override { 542 void Observe(int /* x */) override {
483 list_->Clear(); 543 list_->Clear();
484 list_->AddObserver(&adder_); 544 list_->AddObserver(&adder_);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 TEST(ObserverListTest, IteratorOutlivesList) { 594 TEST(ObserverListTest, IteratorOutlivesList) {
535 ObserverList<Foo>* observer_list = new ObserverList<Foo>; 595 ObserverList<Foo>* observer_list = new ObserverList<Foo>;
536 ListDestructor a(observer_list); 596 ListDestructor a(observer_list);
537 observer_list->AddObserver(&a); 597 observer_list->AddObserver(&a);
538 598
539 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0)); 599 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0));
540 // If this test fails, there'll be Valgrind errors when this function goes out 600 // If this test fails, there'll be Valgrind errors when this function goes out
541 // of scope. 601 // of scope.
542 } 602 }
543 603
544 } // namespace 604 TEST(ObserverListTest, BasicStdIterator) {
605 using FooList = ObserverList<Foo>;
606 FooList observer_list;
607
608 // An optimization: begin() and end() do not involve weak pointers on
609 // empty list.
610 EXPECT_FALSE(observer_list.begin().list_);
611 EXPECT_FALSE(observer_list.end().list_);
612
613 // Iterate over empty list: no effect, no crash.
614 for (auto& i : observer_list)
615 i.Observe(10);
616
617 Adder a(1), b(-1), c(1), d(-1);
618
619 observer_list.AddObserver(&a);
620 observer_list.AddObserver(&b);
621 observer_list.AddObserver(&c);
622 observer_list.AddObserver(&d);
623
624 for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
625 i != e; ++i)
626 i->Observe(1);
627
628 EXPECT_EQ(1, a.total);
629 EXPECT_EQ(-1, b.total);
630 EXPECT_EQ(1, c.total);
631 EXPECT_EQ(-1, d.total);
632
633 // Check an iteration over a 'const view' for a given container.
634 const FooList& const_list = observer_list;
635 for (FooList::const_iterator i = const_list.begin(), e = const_list.end();
636 i != e; ++i) {
637 EXPECT_EQ(1, std::abs(i->GetValue()));
638 }
639
640 for (const auto& o : const_list)
641 EXPECT_EQ(1, std::abs(o.GetValue()));
642 }
643
644 TEST(ObserverListTest, StdIteratorRemoveItself) {
645 ObserverList<Foo> observer_list;
646 Adder a(1), b(-1), c(1), d(-1);
647 Disrupter disrupter(&observer_list, true);
648
649 observer_list.AddObserver(&a);
650 observer_list.AddObserver(&b);
651 observer_list.AddObserver(&disrupter);
652 observer_list.AddObserver(&c);
653 observer_list.AddObserver(&d);
654
655 for (auto& o : observer_list)
656 o.Observe(1);
657
658 for (auto& o : observer_list)
659 o.Observe(10);
660
661 EXPECT_EQ(11, a.total);
662 EXPECT_EQ(-11, b.total);
663 EXPECT_EQ(11, c.total);
664 EXPECT_EQ(-11, d.total);
665 }
666
667 TEST(ObserverListTest, StdIteratorRemoveBefore) {
668 ObserverList<Foo> observer_list;
669 Adder a(1), b(-1), c(1), d(-1);
670 Disrupter disrupter(&observer_list, &b);
671
672 observer_list.AddObserver(&a);
673 observer_list.AddObserver(&b);
674 observer_list.AddObserver(&disrupter);
675 observer_list.AddObserver(&c);
676 observer_list.AddObserver(&d);
677
678 for (auto& o : observer_list)
679 o.Observe(1);
680
681 for (auto& o : observer_list)
682 o.Observe(10);
683
684 EXPECT_EQ(11, a.total);
685 EXPECT_EQ(-1, b.total);
686 EXPECT_EQ(11, c.total);
687 EXPECT_EQ(-11, d.total);
688 }
689
690 TEST(ObserverListTest, StdIteratorRemoveAfter) {
691 ObserverList<Foo> observer_list;
692 Adder a(1), b(-1), c(1), d(-1);
693 Disrupter disrupter(&observer_list, &c);
694
695 observer_list.AddObserver(&a);
696 observer_list.AddObserver(&b);
697 observer_list.AddObserver(&disrupter);
698 observer_list.AddObserver(&c);
699 observer_list.AddObserver(&d);
700
701 for (auto& o : observer_list)
702 o.Observe(1);
703
704 for (auto& o : observer_list)
705 o.Observe(10);
706
707 EXPECT_EQ(11, a.total);
708 EXPECT_EQ(-11, b.total);
709 EXPECT_EQ(0, c.total);
710 EXPECT_EQ(-11, d.total);
711 }
712
713 TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
714 ObserverList<Foo> observer_list;
715 Adder a(1), b(-1), c(1), d(-1);
716 Disrupter disrupter(&observer_list, &a);
717
718 observer_list.AddObserver(&a);
719 observer_list.AddObserver(&disrupter);
720 observer_list.AddObserver(&b);
721 observer_list.AddObserver(&c);
722 observer_list.AddObserver(&d);
723
724 for (auto& o : observer_list)
725 o.Observe(1);
726
727 for (auto& o : observer_list)
728 o.Observe(10);
729
730 EXPECT_EQ(1, a.total);
731 EXPECT_EQ(-11, b.total);
732 EXPECT_EQ(11, c.total);
733 EXPECT_EQ(-11, d.total);
734 }
735
736 TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
737 ObserverList<Foo> observer_list;
738 Adder a(1), b(-1), c(1), d(-1);
739 Disrupter disrupter(&observer_list, &d);
740
741 observer_list.AddObserver(&a);
742 observer_list.AddObserver(&b);
743 observer_list.AddObserver(&c);
744 observer_list.AddObserver(&disrupter);
745 observer_list.AddObserver(&d);
746
747 for (auto& o : observer_list)
748 o.Observe(1);
749
750 for (auto& o : observer_list)
751 o.Observe(10);
752
753 EXPECT_EQ(11, a.total);
754 EXPECT_EQ(-11, b.total);
755 EXPECT_EQ(11, c.total);
756 EXPECT_EQ(0, d.total);
757 }
758
759 TEST(ObserverListTest, StdIteratorRemoveFront) {
760 using FooList = ObserverList<Foo>;
761 FooList observer_list;
762 Adder a(1), b(-1), c(1), d(-1);
763 Disrupter disrupter(&observer_list, true);
764
765 observer_list.AddObserver(&disrupter);
766 observer_list.AddObserver(&a);
767 observer_list.AddObserver(&b);
768 observer_list.AddObserver(&c);
769 observer_list.AddObserver(&d);
770
771 bool test_disruptor = true;
772 for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
773 i != e; ++i) {
774 i->Observe(1);
775 // Check that second call to i->Observe() would crash here.
776 if (test_disruptor) {
777 EXPECT_FALSE(i.GetCurrent());
778 test_disruptor = false;
779 }
780 }
781
782 for (auto& o : observer_list)
783 o.Observe(10);
784
785 EXPECT_EQ(11, a.total);
786 EXPECT_EQ(-11, b.total);
787 EXPECT_EQ(11, c.total);
788 EXPECT_EQ(-11, d.total);
789 }
790
791 TEST(ObserverListTest, StdIteratorRemoveBack) {
792 ObserverList<Foo> observer_list;
793 Adder a(1), b(-1), c(1), d(-1);
794 Disrupter disrupter(&observer_list, true);
795
796 observer_list.AddObserver(&a);
797 observer_list.AddObserver(&b);
798 observer_list.AddObserver(&c);
799 observer_list.AddObserver(&d);
800 observer_list.AddObserver(&disrupter);
801
802 for (auto& o : observer_list)
803 o.Observe(1);
804
805 for (auto& o : observer_list)
806 o.Observe(10);
807
808 EXPECT_EQ(11, a.total);
809 EXPECT_EQ(-11, b.total);
810 EXPECT_EQ(11, c.total);
811 EXPECT_EQ(-11, d.total);
812 }
813
814 TEST(ObserverListTest, NestedLoop) {
815 ObserverList<Foo> observer_list;
816 Adder a(1), b(-1), c(1), d(-1);
817 Disrupter disrupter(&observer_list, true);
818
819 observer_list.AddObserver(&disrupter);
820 observer_list.AddObserver(&a);
821 observer_list.AddObserver(&b);
822 observer_list.AddObserver(&c);
823 observer_list.AddObserver(&d);
824
825 for (auto& o : observer_list) {
826 o.Observe(10);
827
828 for (auto& o : observer_list)
829 o.Observe(1);
830 }
831
832 EXPECT_EQ(15, a.total);
833 EXPECT_EQ(-15, b.total);
834 EXPECT_EQ(15, c.total);
835 EXPECT_EQ(-15, d.total);
836 }
837
838 TEST(ObserverListTest, NonCompactList) {
839 ObserverList<Foo> observer_list;
840 Adder a(1), b(-1);
841
842 Disrupter disrupter1(&observer_list, true);
843 Disrupter disrupter2(&observer_list, true);
844
845 // Disrupt itself and another guy.
846 disrupter1.SetDoomed(&disrupter2);
847
848 observer_list.AddObserver(&disrupter1);
849 observer_list.AddObserver(&disrupter2);
850 observer_list.AddObserver(&a);
851 observer_list.AddObserver(&b);
852
853 for (auto& o : observer_list) {
854 // Get the { nullptr, nullptr, &a, &b } non-compact list
855 // on the first inner pass.
856 o.Observe(10);
857
858 for (auto& o : observer_list)
859 o.Observe(1);
860 }
861
862 EXPECT_EQ(13, a.total);
863 EXPECT_EQ(-13, b.total);
864 }
865
866 TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
867 ObserverList<Foo> observer_list;
868 Adder a(1), b(-1);
869
870 Disrupter disrupter1(&observer_list, true);
871 Disrupter disrupter2(&observer_list, true);
872
873 // Disrupt itself and another guy.
874 disrupter1.SetDoomed(&disrupter2);
875
876 observer_list.AddObserver(&disrupter1);
877 observer_list.AddObserver(&disrupter2);
878
879 bool add_observers = true;
880 for (auto& o : observer_list) {
881 // Get the { nullptr, nullptr } empty list on the first inner pass.
882 o.Observe(10);
883
884 for (auto& o : observer_list)
885 o.Observe(1);
886
887 if (add_observers) {
888 observer_list.AddObserver(&a);
889 observer_list.AddObserver(&b);
890 add_observers = false;
891 }
892 }
893
894 EXPECT_EQ(12, a.total);
895 EXPECT_EQ(-12, b.total);
896 }
897
898 TEST(ObserverListTest, AddObserverInTheLastObserve) {
899 using FooList = ObserverList<Foo>;
900 FooList observer_list;
901
902 AddInObserve<FooList> a(&observer_list);
903 Adder b(-1);
904
905 a.SetToAdd(&b);
906 observer_list.AddObserver(&a);
907
908 FooList::Iterator it(&observer_list);
909 Foo* foo;
910 while ((foo = it.GetNext()) != nullptr)
911 foo->Observe(10);
912
913 EXPECT_EQ(-10, b.total);
914 }
915
545 } // namespace base 916 } // namespace base
OLDNEW
« no previous file with comments | « base/observer_list.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698