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 }; 26 27 class Adder : public Foo { 28 public: 29 explicit Adder(int scaler) : total(0), scaler_(scaler) {} 30 void Observe(int x) override { total += x * scaler_; } 31 ~Adder() override {} 32 int total; 33 34 private: 35 int scaler_; 36 }; 37 38 class Disrupter : public Foo { 39 public: 40 Disrupter(ObserverList<Foo>* list, Foo* doomed) 41 : list_(list), 42 doomed_(doomed) { 43 } 44 ~Disrupter() override {} 45 void Observe(int x) override { list_->RemoveObserver(doomed_); } 46 47 private: 48 ObserverList<Foo>* list_; 49 Foo* doomed_; 50 }; 51 52 class ThreadSafeDisrupter : public Foo { 53 public: 54 ThreadSafeDisrupter(ObserverListThreadSafe<Foo>* list, Foo* doomed) 55 : list_(list), 56 doomed_(doomed) { 57 } 58 ~ThreadSafeDisrupter() override {} 59 void Observe(int x) override { list_->RemoveObserver(doomed_); } 60 61 private: 62 ObserverListThreadSafe<Foo>* list_; 63 Foo* doomed_; 64 }; 65 66 template <typename ObserverListType> 67 class AddInObserve : public Foo { 68 public: 69 explicit AddInObserve(ObserverListType* observer_list) 70 : added(false), 71 observer_list(observer_list), 72 adder(1) { 73 } 74 75 void Observe(int x) override { 76 if (!added) { 77 added = true; 78 observer_list->AddObserver(&adder); 79 } 80 } 81 82 bool added; 83 ObserverListType* observer_list; 84 Adder adder; 85 }; 86 87 88 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test. 89 90 // A thread for use in the ThreadSafeObserver test 91 // which will add and remove itself from the notification 92 // list repeatedly. 93 class AddRemoveThread : public PlatformThread::Delegate, 94 public Foo { 95 public: 96 AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify) 97 : list_(list), 98 loop_(nullptr), 99 in_list_(false), 100 start_(Time::Now()), 101 count_observes_(0), 102 count_addtask_(0), 103 do_notifies_(notify), 104 weak_factory_(this) { 105 } 106 107 ~AddRemoveThread() override {} 108 109 void ThreadMain() override { 110 loop_ = new MessageLoop(); // Fire up a message loop. 111 loop_->task_runner()->PostTask( 112 FROM_HERE, 113 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr())); 114 RunLoop().Run(); 115 //LOG(ERROR) << "Loop 0x" << std::hex << loop_ << " done. " << 116 // count_observes_ << ", " << count_addtask_; 117 delete loop_; 118 loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef); 119 delete this; 120 } 121 122 // This task just keeps posting to itself in an attempt 123 // to race with the notifier. 124 void AddTask() { 125 count_addtask_++; 126 127 if ((Time::Now() - start_).InMilliseconds() > kThreadRunTime) { 128 VLOG(1) << "DONE!"; 129 return; 130 } 131 132 if (!in_list_) { 133 list_->AddObserver(this); 134 in_list_ = true; 135 } 136 137 if (do_notifies_) { 138 list_->Notify(FROM_HERE, &Foo::Observe, 10); 139 } 140 141 loop_->task_runner()->PostTask( 142 FROM_HERE, 143 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr())); 144 } 145 146 void Quit() { 147 loop_->task_runner()->PostTask(FROM_HERE, 148 MessageLoop::QuitWhenIdleClosure()); 149 } 150 151 void Observe(int x) override { 152 count_observes_++; 153 154 // If we're getting called after we removed ourselves from 155 // the list, that is very bad! 156 DCHECK(in_list_); 157 158 // This callback should fire on the appropriate thread 159 EXPECT_EQ(loop_, MessageLoop::current()); 160 161 list_->RemoveObserver(this); 162 in_list_ = false; 163 } 164 165 private: 166 ObserverListThreadSafe<Foo>* list_; 167 MessageLoop* loop_; 168 bool in_list_; // Are we currently registered for notifications. 169 // in_list_ is only used on |this| thread. 170 Time start_; // The time we started the test. 171 172 int count_observes_; // Number of times we observed. 173 int count_addtask_; // Number of times thread AddTask was called 174 bool do_notifies_; // Whether these threads should do notifications. 175 176 base::WeakPtrFactory<AddRemoveThread> weak_factory_; 177 }; 178 179 TEST(ObserverListTest, BasicTest) { 180 ObserverList<Foo> observer_list; 181 Adder a(1), b(-1), c(1), d(-1), e(-1); 182 Disrupter evil(&observer_list, &c); 183 184 observer_list.AddObserver(&a); 185 observer_list.AddObserver(&b); 186 187 EXPECT_TRUE(observer_list.HasObserver(&a)); 188 EXPECT_FALSE(observer_list.HasObserver(&c)); 189 190 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10)); 191 192 observer_list.AddObserver(&evil); 193 observer_list.AddObserver(&c); 194 observer_list.AddObserver(&d); 195 196 // Removing an observer not in the list should do nothing. 197 observer_list.RemoveObserver(&e); 198 199 FOR_EACH_OBSERVER(Foo, observer_list, Observe(10)); 200 201 EXPECT_EQ(20, a.total); 202 EXPECT_EQ(-20, b.total); 203 EXPECT_EQ(0, c.total); 204 EXPECT_EQ(-10, d.total); 205 EXPECT_EQ(0, e.total); 206 } 207 208 TEST(ObserverListThreadSafeTest, BasicTest) { 209 MessageLoop loop; 210 211 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 212 new ObserverListThreadSafe<Foo>); 213 Adder a(1); 214 Adder b(-1); 215 Adder c(1); 216 Adder d(-1); 217 ThreadSafeDisrupter evil(observer_list.get(), &c); 218 219 observer_list->AddObserver(&a); 220 observer_list->AddObserver(&b); 221 222 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 223 RunLoop().RunUntilIdle(); 224 225 observer_list->AddObserver(&evil); 226 observer_list->AddObserver(&c); 227 observer_list->AddObserver(&d); 228 229 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 230 RunLoop().RunUntilIdle(); 231 232 EXPECT_EQ(20, a.total); 233 EXPECT_EQ(-20, b.total); 234 EXPECT_EQ(0, c.total); 235 EXPECT_EQ(-10, d.total); 236 } 237 238 TEST(ObserverListThreadSafeTest, RemoveObserver) { 239 MessageLoop loop; 240 241 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 242 new ObserverListThreadSafe<Foo>); 243 Adder a(1), b(1); 244 245 // A workaround for the compiler bug. See http://crbug.com/121960. 246 EXPECT_NE(&a, &b); 247 248 // Should do nothing. 249 observer_list->RemoveObserver(&a); 250 observer_list->RemoveObserver(&b); 251 252 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 253 RunLoop().RunUntilIdle(); 254 255 EXPECT_EQ(0, a.total); 256 EXPECT_EQ(0, b.total); 257 258 observer_list->AddObserver(&a); 259 260 // Should also do nothing. 261 observer_list->RemoveObserver(&b); 262 263 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 264 RunLoop().RunUntilIdle(); 265 266 EXPECT_EQ(10, a.total); 267 EXPECT_EQ(0, b.total); 268 } 269 270 TEST(ObserverListThreadSafeTest, WithoutMessageLoop) { 271 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 272 new ObserverListThreadSafe<Foo>); 273 274 Adder a(1), b(1), c(1); 275 276 // No MessageLoop, so these should not be added. 277 observer_list->AddObserver(&a); 278 observer_list->AddObserver(&b); 279 280 { 281 // Add c when there's a loop. 282 MessageLoop loop; 283 observer_list->AddObserver(&c); 284 285 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 286 RunLoop().RunUntilIdle(); 287 288 EXPECT_EQ(0, a.total); 289 EXPECT_EQ(0, b.total); 290 EXPECT_EQ(10, c.total); 291 292 // Now add a when there's a loop. 293 observer_list->AddObserver(&a); 294 295 // Remove c when there's a loop. 296 observer_list->RemoveObserver(&c); 297 298 // Notify again. 299 observer_list->Notify(FROM_HERE, &Foo::Observe, 20); 300 RunLoop().RunUntilIdle(); 301 302 EXPECT_EQ(20, a.total); 303 EXPECT_EQ(0, b.total); 304 EXPECT_EQ(10, c.total); 305 } 306 307 // Removing should always succeed with or without a loop. 308 observer_list->RemoveObserver(&a); 309 310 // Notifying should not fail but should also be a no-op. 311 MessageLoop loop; 312 observer_list->AddObserver(&b); 313 observer_list->Notify(FROM_HERE, &Foo::Observe, 30); 314 RunLoop().RunUntilIdle(); 315 316 EXPECT_EQ(20, a.total); 317 EXPECT_EQ(30, b.total); 318 EXPECT_EQ(10, c.total); 319 } 320 321 class FooRemover : public Foo { 322 public: 323 explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {} 324 ~FooRemover() override {} 325 326 void AddFooToRemove(Foo* foo) { 327 foos_.push_back(foo); 328 } 329 330 void Observe(int x) override { 331 std::vector<Foo*> tmp; 332 tmp.swap(foos_); 333 for (std::vector<Foo*>::iterator it = tmp.begin(); 334 it != tmp.end(); ++it) { 335 list_->RemoveObserver(*it); 336 } 337 } 338 339 private: 340 const scoped_refptr<ObserverListThreadSafe<Foo> > list_; 341 std::vector<Foo*> foos_; 342 }; 343 344 TEST(ObserverListThreadSafeTest, RemoveMultipleObservers) { 345 MessageLoop loop; 346 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 347 new ObserverListThreadSafe<Foo>); 348 349 FooRemover a(observer_list.get()); 350 Adder b(1); 351 352 observer_list->AddObserver(&a); 353 observer_list->AddObserver(&b); 354 355 a.AddFooToRemove(&a); 356 a.AddFooToRemove(&b); 357 358 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 359 RunLoop().RunUntilIdle(); 360 } 361 362 // A test driver for a multi-threaded notification loop. Runs a number 363 // of observer threads, each of which constantly adds/removes itself 364 // from the observer list. Optionally, if cross_thread_notifies is set 365 // to true, the observer threads will also trigger notifications to 366 // all observers. 367 static void ThreadSafeObserverHarness(int num_threads, 368 bool cross_thread_notifies) { 369 MessageLoop loop; 370 371 const int kMaxThreads = 15; 372 num_threads = num_threads > kMaxThreads ? kMaxThreads : num_threads; 373 374 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 375 new ObserverListThreadSafe<Foo>); 376 Adder a(1); 377 Adder b(-1); 378 Adder c(1); 379 Adder d(-1); 380 381 observer_list->AddObserver(&a); 382 observer_list->AddObserver(&b); 383 384 AddRemoveThread* threaded_observer[kMaxThreads]; 385 base::PlatformThreadHandle threads[kMaxThreads]; 386 for (int index = 0; index < num_threads; index++) { 387 threaded_observer[index] = new AddRemoveThread(observer_list.get(), false); 388 EXPECT_TRUE(PlatformThread::Create(0, 389 threaded_observer[index], &threads[index])); 390 } 391 392 Time start = Time::Now(); 393 while (true) { 394 if ((Time::Now() - start).InMilliseconds() > kThreadRunTime) 395 break; 396 397 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 398 399 RunLoop().RunUntilIdle(); 400 } 401 402 for (int index = 0; index < num_threads; index++) { 403 threaded_observer[index]->Quit(); 404 PlatformThread::Join(threads[index]); 405 } 406 } 407 408 TEST(ObserverListThreadSafeTest, CrossThreadObserver) { 409 // Use 7 observer threads. Notifications only come from 410 // the main thread. 411 ThreadSafeObserverHarness(7, false); 412 } 413 414 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) { 415 // Use 3 observer threads. Notifications will fire from 416 // the main thread and all 3 observer threads. 417 ThreadSafeObserverHarness(3, true); 418 } 419 420 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) { 421 MessageLoop* loop = new MessageLoop; 422 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 423 new ObserverListThreadSafe<Foo>); 424 425 Adder a(1); 426 observer_list->AddObserver(&a); 427 delete loop; 428 // Test passes if we don't crash here. 429 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 430 } 431 432 TEST(ObserverListTest, Existing) { 433 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); 434 Adder a(1); 435 AddInObserve<ObserverList<Foo> > b(&observer_list); 436 437 observer_list.AddObserver(&a); 438 observer_list.AddObserver(&b); 439 440 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); 441 442 EXPECT_TRUE(b.added); 443 // B's adder should not have been notified because it was added during 444 // notification. 445 EXPECT_EQ(0, b.adder.total); 446 447 // Notify again to make sure b's adder is notified. 448 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); 449 EXPECT_EQ(1, b.adder.total); 450 } 451 452 // Same as above, but for ObserverListThreadSafe 453 TEST(ObserverListThreadSafeTest, Existing) { 454 MessageLoop loop; 455 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 456 new ObserverListThreadSafe<Foo>(ObserverList<Foo>::NOTIFY_EXISTING_ONLY)); 457 Adder a(1); 458 AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get()); 459 460 observer_list->AddObserver(&a); 461 observer_list->AddObserver(&b); 462 463 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 464 RunLoop().RunUntilIdle(); 465 466 EXPECT_TRUE(b.added); 467 // B's adder should not have been notified because it was added during 468 // notification. 469 EXPECT_EQ(0, b.adder.total); 470 471 // Notify again to make sure b's adder is notified. 472 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 473 RunLoop().RunUntilIdle(); 474 EXPECT_EQ(1, b.adder.total); 475 } 476 477 class AddInClearObserve : public Foo { 478 public: 479 explicit AddInClearObserve(ObserverList<Foo>* list) 480 : list_(list), added_(false), adder_(1) {} 481 482 void Observe(int /* x */) override { 483 list_->Clear(); 484 list_->AddObserver(&adder_); 485 added_ = true; 486 } 487 488 bool added() const { return added_; } 489 const Adder& adder() const { return adder_; } 490 491 private: 492 ObserverList<Foo>* const list_; 493 494 bool added_; 495 Adder adder_; 496 }; 497 498 TEST(ObserverListTest, ClearNotifyAll) { 499 ObserverList<Foo> observer_list; 500 AddInClearObserve a(&observer_list); 501 502 observer_list.AddObserver(&a); 503 504 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); 505 EXPECT_TRUE(a.added()); 506 EXPECT_EQ(1, a.adder().total) 507 << "Adder should observe once and have sum of 1."; 508 } 509 510 TEST(ObserverListTest, ClearNotifyExistingOnly) { 511 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); 512 AddInClearObserve a(&observer_list); 513 514 observer_list.AddObserver(&a); 515 516 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); 517 EXPECT_TRUE(a.added()); 518 EXPECT_EQ(0, a.adder().total) 519 << "Adder should not observe, so sum should still be 0."; 520 } 521 522 class ListDestructor : public Foo { 523 public: 524 explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {} 525 ~ListDestructor() override {} 526 527 void Observe(int x) override { delete list_; } 528 529 private: 530 ObserverList<Foo>* list_; 531 }; 532 533 534 TEST(ObserverListTest, IteratorOutlivesList) { 535 ObserverList<Foo>* observer_list = new ObserverList<Foo>; 536 ListDestructor a(observer_list); 537 observer_list->AddObserver(&a); 538 539 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0)); 540 // If this test fails, there'll be Valgrind errors when this function goes out 541 // of scope. 542 } 543 544 } // namespace 545 } // namespace base 546