OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |