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

Side by Side Diff: base/observer_list_unittest.cc

Issue 2340583005: Base ObserverList: Add basic support for standard C++ iterators. (Closed)
Patch Set: Some usages expect macro to be an expression, not a statement. 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:
40 Disrupter(ObserverList<Foo>* list, Foo* doomed) 44 Disrupter(ObserverList<Foo>* list, Foo* doomed)
41 : list_(list), 45 : list_(list),
42 doomed_(doomed) { 46 doomed_(doomed) {
43 } 47 }
44 ~Disrupter() override {} 48 ~Disrupter() override {}
45 void Observe(int x) override { list_->RemoveObserver(doomed_); } 49 void Observe(int x) override { list_->RemoveObserver(doomed_); }
46 50
47 private: 51 private:
48 ObserverList<Foo>* list_; 52 ObserverList<Foo>* list_;
49 Foo* doomed_; 53 Foo* doomed_;
50 }; 54 };
51 55
56 class DisrupterSelf : public Foo {
57 public:
58 DisrupterSelf(ObserverList<Foo>* list) : list_(list) {}
59 ~DisrupterSelf() override {}
60 void Observe(int x) override { list_->RemoveObserver(this); }
61
62 private:
63 ObserverList<Foo>* list_;
64 };
65
52 class ThreadSafeDisrupter : public Foo { 66 class ThreadSafeDisrupter : public Foo {
53 public: 67 public:
54 ThreadSafeDisrupter(ObserverListThreadSafe<Foo>* list, Foo* doomed) 68 ThreadSafeDisrupter(ObserverListThreadSafe<Foo>* list, Foo* doomed)
55 : list_(list), 69 : list_(list),
56 doomed_(doomed) { 70 doomed_(doomed) {
57 } 71 }
58 ~ThreadSafeDisrupter() override {} 72 ~ThreadSafeDisrupter() override {}
59 void Observe(int x) override { list_->RemoveObserver(doomed_); } 73 void Observe(int x) override { list_->RemoveObserver(doomed_); }
60 74
61 private: 75 private:
(...skipping 107 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, DesruptSelf) {
dcheng 2016/10/05 07:08:24 Nit: Desrupt -> Disrupt
loyso (OOO) 2016/10/07 03:45:08 Done.
225 ObserverList<Foo> observer_list;
226 Adder a(1), b(-1), c(1), d(-1);
227 DisrupterSelf evil(&observer_list);
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, DesruptBefore) {
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 DisrupterSelf disrupter(&observer_list);
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 DisrupterSelf disrupter(&observer_list);
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 for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
770 i != e; ++i) {
771 const bool has_disruptor = observer_list.HasObserver(&disrupter);
772 i->Observe(1);
773 // Check that second call to i->Observe() would crash here.
774 if (has_disruptor)
775 EXPECT_FALSE(i.GetCurrent());
776 }
777
778 for (auto& o : observer_list)
779 o.Observe(10);
780
781 EXPECT_EQ(11, a.total);
782 EXPECT_EQ(-11, b.total);
783 EXPECT_EQ(11, c.total);
784 EXPECT_EQ(-11, d.total);
785 }
786
787 TEST(ObserverListTest, StdIteratorRemoveBack) {
788 ObserverList<Foo> observer_list;
789 Adder a(1), b(-1), c(1), d(-1);
790 DisrupterSelf disrupter(&observer_list);
791
792 observer_list.AddObserver(&a);
793 observer_list.AddObserver(&b);
794 observer_list.AddObserver(&c);
795 observer_list.AddObserver(&d);
796 observer_list.AddObserver(&disrupter);
797
798 for (auto& o : observer_list)
799 o.Observe(1);
800
801 for (auto& o : observer_list)
802 o.Observe(10);
803
804 EXPECT_EQ(11, a.total);
805 EXPECT_EQ(-11, b.total);
806 EXPECT_EQ(11, c.total);
807 EXPECT_EQ(-11, d.total);
808 }
809
545 } // namespace base 810 } // 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