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