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 3 // found in the LICENSE file. 4 5 #include "base/observer_list.h" 6 #include "base/observer_list_threadsafe.h" 7 8 #include <vector> 9 10 #include "base/compiler_specific.h" 11 #include "base/location.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/run_loop.h" 14 #include "base/single_thread_task_runner.h" 15 #include "base/threading/platform_thread.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 namespace base { 19 namespace { 20 21 class Foo { 22 public: 23 virtual void Observe(int x) = 0; 24 virtual ~Foo() {} 25 virtual int GetValue() const { return 0; } 26 }; 27 28 class Adder : public Foo { 29 public: 30 explicit Adder(int scaler) : total(0), scaler_(scaler) {} 31 ~Adder() override {} 32 33 void Observe(int x) override { total += x * scaler_; } 34 int GetValue() const override { return total; } 35 36 int total; 37 38 private: 39 int scaler_; 40 }; 41 42 class Disrupter : public Foo { 43 public: 44 Disrupter(ObserverList<Foo>* list, Foo* doomed, bool remove_self) 45 : list_(list), doomed_(doomed), remove_self_(remove_self) {} 46 Disrupter(ObserverList<Foo>* list, Foo* doomed) 47 : Disrupter(list, doomed, false) {} 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_); 58 } 59 60 void SetDoomed(Foo* doomed) { doomed_ = doomed; } 61 62 private: 63 ObserverList<Foo>* list_; 64 Foo* doomed_; 65 bool remove_self_; 66 }; 67 68 class ThreadSafeDisrupter : public Foo { 69 public: 70 ThreadSafeDisrupter(ObserverListThreadSafe<Foo>* list, Foo* doomed) 71 : list_(list), 72 doomed_(doomed) { 73 } 74 ~ThreadSafeDisrupter() override {} 75 void Observe(int x) override { list_->RemoveObserver(doomed_); } 76 77 private: 78 ObserverListThreadSafe<Foo>* list_; 79 Foo* doomed_; 80 }; 81 82 template <typename ObserverListType> 83 class AddInObserve : public Foo { 84 public: 85 explicit AddInObserve(ObserverListType* observer_list) 86 : observer_list(observer_list), to_add_() {} 87 88 void SetToAdd(Foo* to_add) { to_add_ = to_add; } 89 90 void Observe(int x) override { 91 if (to_add_) { 92 observer_list->AddObserver(to_add_); 93 to_add_ = nullptr; 94 } 95 } 96 97 ObserverListType* observer_list; 98 Foo* to_add_; 99 }; 100 101 102 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test. 103 104 // A thread for use in the ThreadSafeObserver test 105 // which will add and remove itself from the notification 106 // list repeatedly. 107 class AddRemoveThread : public PlatformThread::Delegate, 108 public Foo { 109 public: 110 AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify) 111 : list_(list), 112 loop_(nullptr), 113 in_list_(false), 114 start_(Time::Now()), 115 count_observes_(0), 116 count_addtask_(0), 117 do_notifies_(notify), 118 weak_factory_(this) { 119 } 120 121 ~AddRemoveThread() override {} 122 123 void ThreadMain() override { 124 loop_ = new MessageLoop(); // Fire up a message loop. 125 loop_->task_runner()->PostTask( 126 FROM_HERE, 127 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr())); 128 RunLoop().Run(); 129 delete loop_; 130 loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef); 131 delete this; 132 } 133 134 // This task just keeps posting to itself in an attempt 135 // to race with the notifier. 136 void AddTask() { 137 count_addtask_++; 138 139 if ((Time::Now() - start_).InMilliseconds() > kThreadRunTime) { 140 VLOG(1) << "DONE!"; 141 return; 142 } 143 144 if (!in_list_) { 145 list_->AddObserver(this); 146 in_list_ = true; 147 } 148 149 if (do_notifies_) { 150 list_->Notify(FROM_HERE, &Foo::Observe, 10); 151 } 152 153 loop_->task_runner()->PostTask( 154 FROM_HERE, 155 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr())); 156 } 157 158 void Quit() { 159 loop_->task_runner()->PostTask(FROM_HERE, 160 MessageLoop::QuitWhenIdleClosure()); 161 } 162 163 void Observe(int x) override { 164 count_observes_++; 165 166 // If we're getting called after we removed ourselves from 167 // the list, that is very bad! 168 DCHECK(in_list_); 169 170 // This callback should fire on the appropriate thread 171 EXPECT_EQ(loop_, MessageLoop::current()); 172 173 list_->RemoveObserver(this); 174 in_list_ = false; 175 } 176 177 private: 178 ObserverListThreadSafe<Foo>* list_; 179 MessageLoop* loop_; 180 bool in_list_; // Are we currently registered for notifications. 181 // in_list_ is only used on |this| thread. 182 Time start_; // The time we started the test. 183 184 int count_observes_; // Number of times we observed. 185 int count_addtask_; // Number of times thread AddTask was called 186 bool do_notifies_; // Whether these threads should do notifications. 187 188 base::WeakPtrFactory<AddRemoveThread> weak_factory_; 189 }; 190 191 } // namespace 192 193 TEST(ObserverListTest, BasicTest) { 194 ObserverList<Foo> observer_list; 195 Adder a(1), b(-1), c(1), d(-1), e(-1); 196 Disrupter evil(&observer_list, &c); 197 198 observer_list.AddObserver(&a); 199 observer_list.AddObserver(&b); 200 201 EXPECT_TRUE(observer_list.HasObserver(&a)); 202 EXPECT_FALSE(observer_list.HasObserver(&c)); 203 204 for (auto& observer : observer_list) 205 observer.Observe(10); 206 207 observer_list.AddObserver(&evil); 208 observer_list.AddObserver(&c); 209 observer_list.AddObserver(&d); 210 211 // Removing an observer not in the list should do nothing. 212 observer_list.RemoveObserver(&e); 213 214 for (auto& observer : observer_list) 215 observer.Observe(10); 216 217 EXPECT_EQ(20, a.total); 218 EXPECT_EQ(-20, b.total); 219 EXPECT_EQ(0, c.total); 220 EXPECT_EQ(-10, d.total); 221 EXPECT_EQ(0, e.total); 222 } 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 (auto& observer : observer_list) 233 observer.Observe(10); 234 235 observer_list.AddObserver(&evil); 236 observer_list.AddObserver(&c); 237 observer_list.AddObserver(&d); 238 239 for (auto& observer : observer_list) 240 observer.Observe(10); 241 242 EXPECT_EQ(20, a.total); 243 EXPECT_EQ(-20, b.total); 244 EXPECT_EQ(10, c.total); 245 EXPECT_EQ(-10, d.total); 246 } 247 248 TEST(ObserverListTest, DisruptBefore) { 249 ObserverList<Foo> observer_list; 250 Adder a(1), b(-1), c(1), d(-1); 251 Disrupter evil(&observer_list, &b); 252 253 observer_list.AddObserver(&a); 254 observer_list.AddObserver(&b); 255 observer_list.AddObserver(&evil); 256 observer_list.AddObserver(&c); 257 observer_list.AddObserver(&d); 258 259 for (auto& observer : observer_list) 260 observer.Observe(10); 261 for (auto& observer : observer_list) 262 observer.Observe(10); 263 264 EXPECT_EQ(20, a.total); 265 EXPECT_EQ(-10, b.total); 266 EXPECT_EQ(20, c.total); 267 EXPECT_EQ(-20, d.total); 268 } 269 270 TEST(ObserverListThreadSafeTest, BasicTest) { 271 MessageLoop loop; 272 273 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 274 new ObserverListThreadSafe<Foo>); 275 Adder a(1); 276 Adder b(-1); 277 Adder c(1); 278 Adder d(-1); 279 ThreadSafeDisrupter evil(observer_list.get(), &c); 280 281 observer_list->AddObserver(&a); 282 observer_list->AddObserver(&b); 283 284 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 285 RunLoop().RunUntilIdle(); 286 287 observer_list->AddObserver(&evil); 288 observer_list->AddObserver(&c); 289 observer_list->AddObserver(&d); 290 291 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 292 RunLoop().RunUntilIdle(); 293 294 EXPECT_EQ(20, a.total); 295 EXPECT_EQ(-20, b.total); 296 EXPECT_EQ(0, c.total); 297 EXPECT_EQ(-10, d.total); 298 } 299 300 TEST(ObserverListThreadSafeTest, RemoveObserver) { 301 MessageLoop loop; 302 303 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 304 new ObserverListThreadSafe<Foo>); 305 Adder a(1), b(1); 306 307 // A workaround for the compiler bug. See http://crbug.com/121960. 308 EXPECT_NE(&a, &b); 309 310 // Should do nothing. 311 observer_list->RemoveObserver(&a); 312 observer_list->RemoveObserver(&b); 313 314 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 315 RunLoop().RunUntilIdle(); 316 317 EXPECT_EQ(0, a.total); 318 EXPECT_EQ(0, b.total); 319 320 observer_list->AddObserver(&a); 321 322 // Should also do nothing. 323 observer_list->RemoveObserver(&b); 324 325 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 326 RunLoop().RunUntilIdle(); 327 328 EXPECT_EQ(10, a.total); 329 EXPECT_EQ(0, b.total); 330 } 331 332 TEST(ObserverListThreadSafeTest, WithoutMessageLoop) { 333 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 334 new ObserverListThreadSafe<Foo>); 335 336 Adder a(1), b(1), c(1); 337 338 // No MessageLoop, so these should not be added. 339 observer_list->AddObserver(&a); 340 observer_list->AddObserver(&b); 341 342 { 343 // Add c when there's a loop. 344 MessageLoop loop; 345 observer_list->AddObserver(&c); 346 347 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 348 RunLoop().RunUntilIdle(); 349 350 EXPECT_EQ(0, a.total); 351 EXPECT_EQ(0, b.total); 352 EXPECT_EQ(10, c.total); 353 354 // Now add a when there's a loop. 355 observer_list->AddObserver(&a); 356 357 // Remove c when there's a loop. 358 observer_list->RemoveObserver(&c); 359 360 // Notify again. 361 observer_list->Notify(FROM_HERE, &Foo::Observe, 20); 362 RunLoop().RunUntilIdle(); 363 364 EXPECT_EQ(20, a.total); 365 EXPECT_EQ(0, b.total); 366 EXPECT_EQ(10, c.total); 367 } 368 369 // Removing should always succeed with or without a loop. 370 observer_list->RemoveObserver(&a); 371 372 // Notifying should not fail but should also be a no-op. 373 MessageLoop loop; 374 observer_list->AddObserver(&b); 375 observer_list->Notify(FROM_HERE, &Foo::Observe, 30); 376 RunLoop().RunUntilIdle(); 377 378 EXPECT_EQ(20, a.total); 379 EXPECT_EQ(30, b.total); 380 EXPECT_EQ(10, c.total); 381 } 382 383 class FooRemover : public Foo { 384 public: 385 explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {} 386 ~FooRemover() override {} 387 388 void AddFooToRemove(Foo* foo) { 389 foos_.push_back(foo); 390 } 391 392 void Observe(int x) override { 393 std::vector<Foo*> tmp; 394 tmp.swap(foos_); 395 for (std::vector<Foo*>::iterator it = tmp.begin(); 396 it != tmp.end(); ++it) { 397 list_->RemoveObserver(*it); 398 } 399 } 400 401 private: 402 const scoped_refptr<ObserverListThreadSafe<Foo> > list_; 403 std::vector<Foo*> foos_; 404 }; 405 406 TEST(ObserverListThreadSafeTest, RemoveMultipleObservers) { 407 MessageLoop loop; 408 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 409 new ObserverListThreadSafe<Foo>); 410 411 FooRemover a(observer_list.get()); 412 Adder b(1); 413 414 observer_list->AddObserver(&a); 415 observer_list->AddObserver(&b); 416 417 a.AddFooToRemove(&a); 418 a.AddFooToRemove(&b); 419 420 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 421 RunLoop().RunUntilIdle(); 422 } 423 424 // A test driver for a multi-threaded notification loop. Runs a number 425 // of observer threads, each of which constantly adds/removes itself 426 // from the observer list. Optionally, if cross_thread_notifies is set 427 // to true, the observer threads will also trigger notifications to 428 // all observers. 429 static void ThreadSafeObserverHarness(int num_threads, 430 bool cross_thread_notifies) { 431 MessageLoop loop; 432 433 const int kMaxThreads = 15; 434 num_threads = num_threads > kMaxThreads ? kMaxThreads : num_threads; 435 436 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 437 new ObserverListThreadSafe<Foo>); 438 Adder a(1); 439 Adder b(-1); 440 Adder c(1); 441 Adder d(-1); 442 443 observer_list->AddObserver(&a); 444 observer_list->AddObserver(&b); 445 446 AddRemoveThread* threaded_observer[kMaxThreads]; 447 base::PlatformThreadHandle threads[kMaxThreads]; 448 for (int index = 0; index < num_threads; index++) { 449 threaded_observer[index] = new AddRemoveThread(observer_list.get(), false); 450 EXPECT_TRUE(PlatformThread::Create(0, 451 threaded_observer[index], &threads[index])); 452 } 453 454 Time start = Time::Now(); 455 while (true) { 456 if ((Time::Now() - start).InMilliseconds() > kThreadRunTime) 457 break; 458 459 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 460 461 RunLoop().RunUntilIdle(); 462 } 463 464 for (int index = 0; index < num_threads; index++) { 465 threaded_observer[index]->Quit(); 466 PlatformThread::Join(threads[index]); 467 } 468 } 469 470 TEST(ObserverListThreadSafeTest, CrossThreadObserver) { 471 // Use 7 observer threads. Notifications only come from 472 // the main thread. 473 ThreadSafeObserverHarness(7, false); 474 } 475 476 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) { 477 // Use 3 observer threads. Notifications will fire from 478 // the main thread and all 3 observer threads. 479 ThreadSafeObserverHarness(3, true); 480 } 481 482 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) { 483 MessageLoop* loop = new MessageLoop; 484 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 485 new ObserverListThreadSafe<Foo>); 486 487 Adder a(1); 488 observer_list->AddObserver(&a); 489 delete loop; 490 // Test passes if we don't crash here. 491 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 492 } 493 494 TEST(ObserverListTest, Existing) { 495 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); 496 Adder a(1); 497 AddInObserve<ObserverList<Foo> > b(&observer_list); 498 Adder c(1); 499 b.SetToAdd(&c); 500 501 observer_list.AddObserver(&a); 502 observer_list.AddObserver(&b); 503 504 for (auto& observer : observer_list) 505 observer.Observe(1); 506 507 EXPECT_FALSE(b.to_add_); 508 // B's adder should not have been notified because it was added during 509 // notification. 510 EXPECT_EQ(0, c.total); 511 512 // Notify again to make sure b's adder is notified. 513 for (auto& observer : observer_list) 514 observer.Observe(1); 515 EXPECT_EQ(1, c.total); 516 } 517 518 // Same as above, but for ObserverListThreadSafe 519 TEST(ObserverListThreadSafeTest, Existing) { 520 MessageLoop loop; 521 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 522 new ObserverListThreadSafe<Foo>(ObserverList<Foo>::NOTIFY_EXISTING_ONLY)); 523 Adder a(1); 524 AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get()); 525 Adder c(1); 526 b.SetToAdd(&c); 527 528 observer_list->AddObserver(&a); 529 observer_list->AddObserver(&b); 530 531 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 532 RunLoop().RunUntilIdle(); 533 534 EXPECT_FALSE(b.to_add_); 535 // B's adder should not have been notified because it was added during 536 // notification. 537 EXPECT_EQ(0, c.total); 538 539 // Notify again to make sure b's adder is notified. 540 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 541 RunLoop().RunUntilIdle(); 542 EXPECT_EQ(1, c.total); 543 } 544 545 class AddInClearObserve : public Foo { 546 public: 547 explicit AddInClearObserve(ObserverList<Foo>* list) 548 : list_(list), added_(false), adder_(1) {} 549 550 void Observe(int /* x */) override { 551 list_->Clear(); 552 list_->AddObserver(&adder_); 553 added_ = true; 554 } 555 556 bool added() const { return added_; } 557 const Adder& adder() const { return adder_; } 558 559 private: 560 ObserverList<Foo>* const list_; 561 562 bool added_; 563 Adder adder_; 564 }; 565 566 TEST(ObserverListTest, ClearNotifyAll) { 567 ObserverList<Foo> observer_list; 568 AddInClearObserve a(&observer_list); 569 570 observer_list.AddObserver(&a); 571 572 for (auto& observer : observer_list) 573 observer.Observe(1); 574 EXPECT_TRUE(a.added()); 575 EXPECT_EQ(1, a.adder().total) 576 << "Adder should observe once and have sum of 1."; 577 } 578 579 TEST(ObserverListTest, ClearNotifyExistingOnly) { 580 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); 581 AddInClearObserve a(&observer_list); 582 583 observer_list.AddObserver(&a); 584 585 for (auto& observer : observer_list) 586 observer.Observe(1); 587 EXPECT_TRUE(a.added()); 588 EXPECT_EQ(0, a.adder().total) 589 << "Adder should not observe, so sum should still be 0."; 590 } 591 592 class ListDestructor : public Foo { 593 public: 594 explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {} 595 ~ListDestructor() override {} 596 597 void Observe(int x) override { delete list_; } 598 599 private: 600 ObserverList<Foo>* list_; 601 }; 602 603 604 TEST(ObserverListTest, IteratorOutlivesList) { 605 ObserverList<Foo>* observer_list = new ObserverList<Foo>; 606 ListDestructor a(observer_list); 607 observer_list->AddObserver(&a); 608 609 for (auto& observer : *observer_list) 610 observer.Observe(0); 611 // If this test fails, there'll be Valgrind errors when this function goes out 612 // of scope. 613 } 614 615 TEST(ObserverListTest, BasicStdIterator) { 616 using FooList = ObserverList<Foo>; 617 FooList observer_list; 618 619 // An optimization: begin() and end() do not involve weak pointers on 620 // empty list. 621 EXPECT_FALSE(observer_list.begin().list_); 622 EXPECT_FALSE(observer_list.end().list_); 623 624 // Iterate over empty list: no effect, no crash. 625 for (auto& i : observer_list) 626 i.Observe(10); 627 628 Adder a(1), b(-1), c(1), d(-1); 629 630 observer_list.AddObserver(&a); 631 observer_list.AddObserver(&b); 632 observer_list.AddObserver(&c); 633 observer_list.AddObserver(&d); 634 635 for (FooList::iterator i = observer_list.begin(), e = observer_list.end(); 636 i != e; ++i) 637 i->Observe(1); 638 639 EXPECT_EQ(1, a.total); 640 EXPECT_EQ(-1, b.total); 641 EXPECT_EQ(1, c.total); 642 EXPECT_EQ(-1, d.total); 643 644 // Check an iteration over a 'const view' for a given container. 645 const FooList& const_list = observer_list; 646 for (FooList::const_iterator i = const_list.begin(), e = const_list.end(); 647 i != e; ++i) { 648 EXPECT_EQ(1, std::abs(i->GetValue())); 649 } 650 651 for (const auto& o : const_list) 652 EXPECT_EQ(1, std::abs(o.GetValue())); 653 } 654 655 TEST(ObserverListTest, StdIteratorRemoveItself) { 656 ObserverList<Foo> observer_list; 657 Adder a(1), b(-1), c(1), d(-1); 658 Disrupter disrupter(&observer_list, true); 659 660 observer_list.AddObserver(&a); 661 observer_list.AddObserver(&b); 662 observer_list.AddObserver(&disrupter); 663 observer_list.AddObserver(&c); 664 observer_list.AddObserver(&d); 665 666 for (auto& o : observer_list) 667 o.Observe(1); 668 669 for (auto& o : observer_list) 670 o.Observe(10); 671 672 EXPECT_EQ(11, a.total); 673 EXPECT_EQ(-11, b.total); 674 EXPECT_EQ(11, c.total); 675 EXPECT_EQ(-11, d.total); 676 } 677 678 TEST(ObserverListTest, StdIteratorRemoveBefore) { 679 ObserverList<Foo> observer_list; 680 Adder a(1), b(-1), c(1), d(-1); 681 Disrupter disrupter(&observer_list, &b); 682 683 observer_list.AddObserver(&a); 684 observer_list.AddObserver(&b); 685 observer_list.AddObserver(&disrupter); 686 observer_list.AddObserver(&c); 687 observer_list.AddObserver(&d); 688 689 for (auto& o : observer_list) 690 o.Observe(1); 691 692 for (auto& o : observer_list) 693 o.Observe(10); 694 695 EXPECT_EQ(11, a.total); 696 EXPECT_EQ(-1, b.total); 697 EXPECT_EQ(11, c.total); 698 EXPECT_EQ(-11, d.total); 699 } 700 701 TEST(ObserverListTest, StdIteratorRemoveAfter) { 702 ObserverList<Foo> observer_list; 703 Adder a(1), b(-1), c(1), d(-1); 704 Disrupter disrupter(&observer_list, &c); 705 706 observer_list.AddObserver(&a); 707 observer_list.AddObserver(&b); 708 observer_list.AddObserver(&disrupter); 709 observer_list.AddObserver(&c); 710 observer_list.AddObserver(&d); 711 712 for (auto& o : observer_list) 713 o.Observe(1); 714 715 for (auto& o : observer_list) 716 o.Observe(10); 717 718 EXPECT_EQ(11, a.total); 719 EXPECT_EQ(-11, b.total); 720 EXPECT_EQ(0, c.total); 721 EXPECT_EQ(-11, d.total); 722 } 723 724 TEST(ObserverListTest, StdIteratorRemoveAfterFront) { 725 ObserverList<Foo> observer_list; 726 Adder a(1), b(-1), c(1), d(-1); 727 Disrupter disrupter(&observer_list, &a); 728 729 observer_list.AddObserver(&a); 730 observer_list.AddObserver(&disrupter); 731 observer_list.AddObserver(&b); 732 observer_list.AddObserver(&c); 733 observer_list.AddObserver(&d); 734 735 for (auto& o : observer_list) 736 o.Observe(1); 737 738 for (auto& o : observer_list) 739 o.Observe(10); 740 741 EXPECT_EQ(1, a.total); 742 EXPECT_EQ(-11, b.total); 743 EXPECT_EQ(11, c.total); 744 EXPECT_EQ(-11, d.total); 745 } 746 747 TEST(ObserverListTest, StdIteratorRemoveBeforeBack) { 748 ObserverList<Foo> observer_list; 749 Adder a(1), b(-1), c(1), d(-1); 750 Disrupter disrupter(&observer_list, &d); 751 752 observer_list.AddObserver(&a); 753 observer_list.AddObserver(&b); 754 observer_list.AddObserver(&c); 755 observer_list.AddObserver(&disrupter); 756 observer_list.AddObserver(&d); 757 758 for (auto& o : observer_list) 759 o.Observe(1); 760 761 for (auto& o : observer_list) 762 o.Observe(10); 763 764 EXPECT_EQ(11, a.total); 765 EXPECT_EQ(-11, b.total); 766 EXPECT_EQ(11, c.total); 767 EXPECT_EQ(0, d.total); 768 } 769 770 TEST(ObserverListTest, StdIteratorRemoveFront) { 771 using FooList = ObserverList<Foo>; 772 FooList observer_list; 773 Adder a(1), b(-1), c(1), d(-1); 774 Disrupter disrupter(&observer_list, true); 775 776 observer_list.AddObserver(&disrupter); 777 observer_list.AddObserver(&a); 778 observer_list.AddObserver(&b); 779 observer_list.AddObserver(&c); 780 observer_list.AddObserver(&d); 781 782 bool test_disruptor = true; 783 for (FooList::iterator i = observer_list.begin(), e = observer_list.end(); 784 i != e; ++i) { 785 i->Observe(1); 786 // Check that second call to i->Observe() would crash here. 787 if (test_disruptor) { 788 EXPECT_FALSE(i.GetCurrent()); 789 test_disruptor = false; 790 } 791 } 792 793 for (auto& o : observer_list) 794 o.Observe(10); 795 796 EXPECT_EQ(11, a.total); 797 EXPECT_EQ(-11, b.total); 798 EXPECT_EQ(11, c.total); 799 EXPECT_EQ(-11, d.total); 800 } 801 802 TEST(ObserverListTest, StdIteratorRemoveBack) { 803 ObserverList<Foo> observer_list; 804 Adder a(1), b(-1), c(1), d(-1); 805 Disrupter disrupter(&observer_list, true); 806 807 observer_list.AddObserver(&a); 808 observer_list.AddObserver(&b); 809 observer_list.AddObserver(&c); 810 observer_list.AddObserver(&d); 811 observer_list.AddObserver(&disrupter); 812 813 for (auto& o : observer_list) 814 o.Observe(1); 815 816 for (auto& o : observer_list) 817 o.Observe(10); 818 819 EXPECT_EQ(11, a.total); 820 EXPECT_EQ(-11, b.total); 821 EXPECT_EQ(11, c.total); 822 EXPECT_EQ(-11, d.total); 823 } 824 825 TEST(ObserverListTest, NestedLoop) { 826 ObserverList<Foo> observer_list; 827 Adder a(1), b(-1), c(1), d(-1); 828 Disrupter disrupter(&observer_list, true); 829 830 observer_list.AddObserver(&disrupter); 831 observer_list.AddObserver(&a); 832 observer_list.AddObserver(&b); 833 observer_list.AddObserver(&c); 834 observer_list.AddObserver(&d); 835 836 for (auto& o : observer_list) { 837 o.Observe(10); 838 839 for (auto& o : observer_list) 840 o.Observe(1); 841 } 842 843 EXPECT_EQ(15, a.total); 844 EXPECT_EQ(-15, b.total); 845 EXPECT_EQ(15, c.total); 846 EXPECT_EQ(-15, d.total); 847 } 848 849 TEST(ObserverListTest, NonCompactList) { 850 ObserverList<Foo> observer_list; 851 Adder a(1), b(-1); 852 853 Disrupter disrupter1(&observer_list, true); 854 Disrupter disrupter2(&observer_list, true); 855 856 // Disrupt itself and another one. 857 disrupter1.SetDoomed(&disrupter2); 858 859 observer_list.AddObserver(&disrupter1); 860 observer_list.AddObserver(&disrupter2); 861 observer_list.AddObserver(&a); 862 observer_list.AddObserver(&b); 863 864 for (auto& o : observer_list) { 865 // Get the { nullptr, nullptr, &a, &b } non-compact list 866 // on the first inner pass. 867 o.Observe(10); 868 869 for (auto& o : observer_list) 870 o.Observe(1); 871 } 872 873 EXPECT_EQ(13, a.total); 874 EXPECT_EQ(-13, b.total); 875 } 876 877 TEST(ObserverListTest, BecomesEmptyThanNonEmpty) { 878 ObserverList<Foo> observer_list; 879 Adder a(1), b(-1); 880 881 Disrupter disrupter1(&observer_list, true); 882 Disrupter disrupter2(&observer_list, true); 883 884 // Disrupt itself and another one. 885 disrupter1.SetDoomed(&disrupter2); 886 887 observer_list.AddObserver(&disrupter1); 888 observer_list.AddObserver(&disrupter2); 889 890 bool add_observers = true; 891 for (auto& o : observer_list) { 892 // Get the { nullptr, nullptr } empty list on the first inner pass. 893 o.Observe(10); 894 895 for (auto& o : observer_list) 896 o.Observe(1); 897 898 if (add_observers) { 899 observer_list.AddObserver(&a); 900 observer_list.AddObserver(&b); 901 add_observers = false; 902 } 903 } 904 905 EXPECT_EQ(12, a.total); 906 EXPECT_EQ(-12, b.total); 907 } 908 909 TEST(ObserverListTest, AddObserverInTheLastObserve) { 910 using FooList = ObserverList<Foo>; 911 FooList observer_list; 912 913 AddInObserve<FooList> a(&observer_list); 914 Adder b(-1); 915 916 a.SetToAdd(&b); 917 observer_list.AddObserver(&a); 918 919 auto it = observer_list.begin(); 920 while (it != observer_list.end()) { 921 auto& observer = *it; 922 // Intentionally increment the iterator before calling Observe(). The 923 // ObserverList starts with only one observer, and it == observer_list.end() 924 // should be true after the next line. 925 ++it; 926 // However, the first Observe() call will add a second observer: at this 927 // point, it != observer_list.end() should be true, and Observe() should be 928 // called on the newly added observer on the next iteration of the loop. 929 observer.Observe(10); 930 } 931 932 EXPECT_EQ(-10, b.total); 933 } 934 935 } // namespace base 936