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

Side by Side Diff: base/observer_list_unittest.cc

Issue 2340583005: Base ObserverList: Add basic support for standard C++ iterators. (Closed)
Patch Set: Fix bugs. Add new tests. 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
« base/observer_list.h ('K') | « 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_); }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 } 121 }
106 122
107 ~AddRemoveThread() override {} 123 ~AddRemoveThread() override {}
108 124
109 void ThreadMain() override { 125 void ThreadMain() override {
110 loop_ = new MessageLoop(); // Fire up a message loop. 126 loop_ = new MessageLoop(); // Fire up a message loop.
111 loop_->task_runner()->PostTask( 127 loop_->task_runner()->PostTask(
112 FROM_HERE, 128 FROM_HERE,
113 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr())); 129 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
114 RunLoop().Run(); 130 RunLoop().Run();
115 //LOG(ERROR) << "Loop 0x" << std::hex << loop_ << " done. " <<
116 // count_observes_ << ", " << count_addtask_;
117 delete loop_; 131 delete loop_;
118 loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef); 132 loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef);
119 delete this; 133 delete this;
120 } 134 }
121 135
122 // This task just keeps posting to itself in an attempt 136 // This task just keeps posting to itself in an attempt
123 // to race with the notifier. 137 // to race with the notifier.
124 void AddTask() { 138 void AddTask() {
125 count_addtask_++; 139 count_addtask_++;
126 140
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 // in_list_ is only used on |this| thread. 183 // in_list_ is only used on |this| thread.
170 Time start_; // The time we started the test. 184 Time start_; // The time we started the test.
171 185
172 int count_observes_; // Number of times we observed. 186 int count_observes_; // Number of times we observed.
173 int count_addtask_; // Number of times thread AddTask was called 187 int count_addtask_; // Number of times thread AddTask was called
174 bool do_notifies_; // Whether these threads should do notifications. 188 bool do_notifies_; // Whether these threads should do notifications.
175 189
176 base::WeakPtrFactory<AddRemoveThread> weak_factory_; 190 base::WeakPtrFactory<AddRemoveThread> weak_factory_;
177 }; 191 };
178 192
193 } // namespace
194
179 TEST(ObserverListTest, BasicTest) { 195 TEST(ObserverListTest, BasicTest) {
180 ObserverList<Foo> observer_list; 196 ObserverList<Foo> observer_list;
181 Adder a(1), b(-1), c(1), d(-1), e(-1); 197 Adder a(1), b(-1), c(1), d(-1), e(-1);
182 Disrupter evil(&observer_list, &c); 198 Disrupter evil(&observer_list, &c);
183 199
184 observer_list.AddObserver(&a); 200 observer_list.AddObserver(&a);
185 observer_list.AddObserver(&b); 201 observer_list.AddObserver(&b);
186 202
187 EXPECT_TRUE(observer_list.HasObserver(&a)); 203 EXPECT_TRUE(observer_list.HasObserver(&a));
188 EXPECT_FALSE(observer_list.HasObserver(&c)); 204 EXPECT_FALSE(observer_list.HasObserver(&c));
189 205
190 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10)); 206 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
191 207
192 observer_list.AddObserver(&evil); 208 observer_list.AddObserver(&evil);
193 observer_list.AddObserver(&c); 209 observer_list.AddObserver(&c);
194 observer_list.AddObserver(&d); 210 observer_list.AddObserver(&d);
195 211
196 // Removing an observer not in the list should do nothing. 212 // Removing an observer not in the list should do nothing.
197 observer_list.RemoveObserver(&e); 213 observer_list.RemoveObserver(&e);
198 214
199 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10)); 215 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
200 216
201 EXPECT_EQ(20, a.total); 217 EXPECT_EQ(20, a.total);
202 EXPECT_EQ(-20, b.total); 218 EXPECT_EQ(-20, b.total);
203 EXPECT_EQ(0, c.total); 219 EXPECT_EQ(0, c.total);
204 EXPECT_EQ(-10, d.total); 220 EXPECT_EQ(-10, d.total);
205 EXPECT_EQ(0, e.total); 221 EXPECT_EQ(0, e.total);
206 } 222 }
207 223
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_EACH_OBSERVER(Foo, observer_list, Observe(10));
233
234 observer_list.AddObserver(&evil);
235 observer_list.AddObserver(&c);
236 observer_list.AddObserver(&d);
237
238 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
239
240 EXPECT_EQ(20, a.total);
241 EXPECT_EQ(-20, b.total);
242 EXPECT_EQ(10, c.total);
243 EXPECT_EQ(-10, d.total);
244 }
245
246 TEST(ObserverListTest, DisruptBefore) {
247 ObserverList<Foo> observer_list;
248 Adder a(1), b(-1), c(1), d(-1);
249 Disrupter evil(&observer_list, &b);
250
251 observer_list.AddObserver(&a);
252 observer_list.AddObserver(&b);
253 observer_list.AddObserver(&evil);
254 observer_list.AddObserver(&c);
255 observer_list.AddObserver(&d);
256
257 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
258 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10));
259
260 EXPECT_EQ(20, a.total);
261 EXPECT_EQ(-10, b.total);
262 EXPECT_EQ(20, c.total);
263 EXPECT_EQ(-20, d.total);
264 }
265
208 TEST(ObserverListThreadSafeTest, BasicTest) { 266 TEST(ObserverListThreadSafeTest, BasicTest) {
209 MessageLoop loop; 267 MessageLoop loop;
210 268
211 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 269 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
212 new ObserverListThreadSafe<Foo>); 270 new ObserverListThreadSafe<Foo>);
213 Adder a(1); 271 Adder a(1);
214 Adder b(-1); 272 Adder b(-1);
215 Adder c(1); 273 Adder c(1);
216 Adder d(-1); 274 Adder d(-1);
217 ThreadSafeDisrupter evil(observer_list.get(), &c); 275 ThreadSafeDisrupter evil(observer_list.get(), &c);
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 TEST(ObserverListTest, IteratorOutlivesList) { 592 TEST(ObserverListTest, IteratorOutlivesList) {
535 ObserverList<Foo>* observer_list = new ObserverList<Foo>; 593 ObserverList<Foo>* observer_list = new ObserverList<Foo>;
536 ListDestructor a(observer_list); 594 ListDestructor a(observer_list);
537 observer_list->AddObserver(&a); 595 observer_list->AddObserver(&a);
538 596
539 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0)); 597 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0));
540 // If this test fails, there'll be Valgrind errors when this function goes out 598 // If this test fails, there'll be Valgrind errors when this function goes out
541 // of scope. 599 // of scope.
542 } 600 }
543 601
544 } // namespace 602 TEST(ObserverListTest, BasicStdIterator) {
603 using FooList = ObserverList<Foo>;
604 FooList observer_list;
605
606 // An optimization: begin() and end() do not involve weak pointers on
607 // empty list.
608 EXPECT_FALSE(observer_list.begin().list_);
609 EXPECT_FALSE(observer_list.end().list_);
610
611 // Iterate over empty list: no effect, no crash.
612 for (auto& i : observer_list)
613 i.Observe(10);
614
615 Adder a(1), b(-1), c(1), d(-1);
616
617 observer_list.AddObserver(&a);
618 observer_list.AddObserver(&b);
619 observer_list.AddObserver(&c);
620 observer_list.AddObserver(&d);
621
622 for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
623 i != e; ++i)
624 i->Observe(1);
625
626 EXPECT_EQ(1, a.total);
627 EXPECT_EQ(-1, b.total);
628 EXPECT_EQ(1, c.total);
629 EXPECT_EQ(-1, d.total);
630
631 // Check an iteration over a 'const view' for a given container.
632 const FooList& const_list = observer_list;
633 for (FooList::const_iterator i = const_list.begin(), e = const_list.end();
634 i != e; ++i) {
635 EXPECT_EQ(1, std::abs(i->GetValue()));
636 }
637
638 for (const auto& o : const_list)
639 EXPECT_EQ(1, std::abs(o.GetValue()));
640 }
641
642 TEST(ObserverListTest, StdIteratorRemoveItself) {
643 ObserverList<Foo> observer_list;
644 Adder a(1), b(-1), c(1), d(-1);
645 Disrupter disrupter(&observer_list, true);
646
647 observer_list.AddObserver(&a);
648 observer_list.AddObserver(&b);
649 observer_list.AddObserver(&disrupter);
650 observer_list.AddObserver(&c);
651 observer_list.AddObserver(&d);
652
653 for (auto& o : observer_list)
654 o.Observe(1);
655
656 for (auto& o : observer_list)
657 o.Observe(10);
658
659 EXPECT_EQ(11, a.total);
660 EXPECT_EQ(-11, b.total);
661 EXPECT_EQ(11, c.total);
662 EXPECT_EQ(-11, d.total);
663 }
664
665 TEST(ObserverListTest, StdIteratorRemoveBefore) {
666 ObserverList<Foo> observer_list;
667 Adder a(1), b(-1), c(1), d(-1);
668 Disrupter disrupter(&observer_list, &b);
669
670 observer_list.AddObserver(&a);
671 observer_list.AddObserver(&b);
672 observer_list.AddObserver(&disrupter);
673 observer_list.AddObserver(&c);
674 observer_list.AddObserver(&d);
675
676 for (auto& o : observer_list)
677 o.Observe(1);
678
679 for (auto& o : observer_list)
680 o.Observe(10);
681
682 EXPECT_EQ(11, a.total);
683 EXPECT_EQ(-1, b.total);
684 EXPECT_EQ(11, c.total);
685 EXPECT_EQ(-11, d.total);
686 }
687
688 TEST(ObserverListTest, StdIteratorRemoveAfter) {
689 ObserverList<Foo> observer_list;
690 Adder a(1), b(-1), c(1), d(-1);
691 Disrupter disrupter(&observer_list, &c);
692
693 observer_list.AddObserver(&a);
694 observer_list.AddObserver(&b);
695 observer_list.AddObserver(&disrupter);
696 observer_list.AddObserver(&c);
697 observer_list.AddObserver(&d);
698
699 for (auto& o : observer_list)
700 o.Observe(1);
701
702 for (auto& o : observer_list)
703 o.Observe(10);
704
705 EXPECT_EQ(11, a.total);
706 EXPECT_EQ(-11, b.total);
707 EXPECT_EQ(0, c.total);
708 EXPECT_EQ(-11, d.total);
709 }
710
711 TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
712 ObserverList<Foo> observer_list;
713 Adder a(1), b(-1), c(1), d(-1);
714 Disrupter disrupter(&observer_list, &a);
715
716 observer_list.AddObserver(&a);
717 observer_list.AddObserver(&disrupter);
718 observer_list.AddObserver(&b);
719 observer_list.AddObserver(&c);
720 observer_list.AddObserver(&d);
721
722 for (auto& o : observer_list)
723 o.Observe(1);
724
725 for (auto& o : observer_list)
726 o.Observe(10);
727
728 EXPECT_EQ(1, a.total);
729 EXPECT_EQ(-11, b.total);
730 EXPECT_EQ(11, c.total);
731 EXPECT_EQ(-11, d.total);
732 }
733
734 TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
735 ObserverList<Foo> observer_list;
736 Adder a(1), b(-1), c(1), d(-1);
737 Disrupter disrupter(&observer_list, &d);
738
739 observer_list.AddObserver(&a);
740 observer_list.AddObserver(&b);
741 observer_list.AddObserver(&c);
742 observer_list.AddObserver(&disrupter);
743 observer_list.AddObserver(&d);
744
745 for (auto& o : observer_list)
746 o.Observe(1);
747
748 for (auto& o : observer_list)
749 o.Observe(10);
750
751 EXPECT_EQ(11, a.total);
752 EXPECT_EQ(-11, b.total);
753 EXPECT_EQ(11, c.total);
754 EXPECT_EQ(0, d.total);
755 }
756
757 TEST(ObserverListTest, StdIteratorRemoveFront) {
758 using FooList = ObserverList<Foo>;
759 FooList observer_list;
760 Adder a(1), b(-1), c(1), d(-1);
761 Disrupter disrupter(&observer_list, true);
762
763 observer_list.AddObserver(&disrupter);
764 observer_list.AddObserver(&a);
765 observer_list.AddObserver(&b);
766 observer_list.AddObserver(&c);
767 observer_list.AddObserver(&d);
768
769 bool test_disruptor = true;
770 for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
771 i != e; ++i) {
772 i->Observe(1);
773 // Check that second call to i->Observe() would crash here.
774 if (test_disruptor) {
775 EXPECT_FALSE(i.GetCurrent());
776 test_disruptor = false;
777 }
778 }
779
780 for (auto& o : observer_list)
781 o.Observe(10);
782
783 EXPECT_EQ(11, a.total);
784 EXPECT_EQ(-11, b.total);
785 EXPECT_EQ(11, c.total);
786 EXPECT_EQ(-11, d.total);
787 }
788
789 TEST(ObserverListTest, StdIteratorRemoveBack) {
790 ObserverList<Foo> observer_list;
791 Adder a(1), b(-1), c(1), d(-1);
792 Disrupter disrupter(&observer_list, true);
793
794 observer_list.AddObserver(&a);
795 observer_list.AddObserver(&b);
796 observer_list.AddObserver(&c);
797 observer_list.AddObserver(&d);
798 observer_list.AddObserver(&disrupter);
799
800 for (auto& o : observer_list)
801 o.Observe(1);
802
803 for (auto& o : observer_list)
804 o.Observe(10);
805
806 EXPECT_EQ(11, a.total);
807 EXPECT_EQ(-11, b.total);
808 EXPECT_EQ(11, c.total);
809 EXPECT_EQ(-11, d.total);
810 }
811
812 TEST(ObserverListTest, Multipass) {
813 ObserverList<Foo> observer_list;
814 Adder a(1), b(-1), c(1), d(-1);
815 Disrupter disrupter(&observer_list, true);
816
817 observer_list.AddObserver(&disrupter);
818 observer_list.AddObserver(&a);
819 observer_list.AddObserver(&b);
820 observer_list.AddObserver(&c);
821 observer_list.AddObserver(&d);
822
823 for (auto& o : observer_list) {
824 o.Observe(10);
825
826 for (auto& o : observer_list)
827 o.Observe(1);
828 }
829
830 EXPECT_EQ(15, a.total);
831 EXPECT_EQ(-15, b.total);
832 EXPECT_EQ(15, c.total);
833 EXPECT_EQ(-15, d.total);
834 }
835
836 TEST(ObserverListTest, NonCompactList) {
837 ObserverList<Foo> observer_list;
838 Adder a(1), b(-1);
839
840 Disrupter disrupter1(&observer_list, true);
841 Disrupter disrupter2(&observer_list, true);
842
843 // Disrupt itself and another guy.
844 disrupter1.SetDoomed(&disrupter2);
845
846 observer_list.AddObserver(&disrupter1);
847 observer_list.AddObserver(&disrupter2);
848 observer_list.AddObserver(&a);
849 observer_list.AddObserver(&b);
850
851 for (auto& o : observer_list) {
852 // Get the { nullptr, nullptr, &a, &b } non-compact list
853 // on the first inner pass.
854 o.Observe(10);
855
856 for (auto& o : observer_list)
857 o.Observe(1);
858 }
859
860 EXPECT_EQ(13, a.total);
861 EXPECT_EQ(-13, b.total);
862 }
863
545 } // namespace base 864 } // namespace base
OLDNEW
« base/observer_list.h ('K') | « base/observer_list.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698