Chromium Code Reviews| 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 |