Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: base/observer_list_unittest.cc

Issue 2592143003: Allow ObserverListThreadSafe to be used from sequenced tasks. (Closed)
Patch Set: rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
7 6
7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h"
10 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
11 #include "base/location.h" 12 #include "base/location.h"
12 #include "base/memory/weak_ptr.h" 13 #include "base/memory/weak_ptr.h"
14 #include "base/observer_list_threadsafe.h"
13 #include "base/run_loop.h" 15 #include "base/run_loop.h"
16 #include "base/sequenced_task_runner.h"
14 #include "base/single_thread_task_runner.h" 17 #include "base/single_thread_task_runner.h"
18 #include "base/task_scheduler/post_task.h"
19 #include "base/test/scoped_task_scheduler.h"
15 #include "base/threading/platform_thread.h" 20 #include "base/threading/platform_thread.h"
16 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
17 22
18 namespace base { 23 namespace base {
19 namespace { 24 namespace {
20 25
21 class Foo { 26 class Foo {
22 public: 27 public:
23 virtual void Observe(int x) = 0; 28 virtual void Observe(int x) = 0;
24 virtual ~Foo() {} 29 virtual ~Foo() {}
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 // Should also do nothing. 327 // Should also do nothing.
323 observer_list->RemoveObserver(&b); 328 observer_list->RemoveObserver(&b);
324 329
325 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 330 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
326 RunLoop().RunUntilIdle(); 331 RunLoop().RunUntilIdle();
327 332
328 EXPECT_EQ(10, a.total); 333 EXPECT_EQ(10, a.total);
329 EXPECT_EQ(0, b.total); 334 EXPECT_EQ(0, b.total);
330 } 335 }
331 336
332 TEST(ObserverListThreadSafeTest, WithoutMessageLoop) { 337 TEST(ObserverListThreadSafeTest, WithoutSequence) {
333 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 338 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
334 new ObserverListThreadSafe<Foo>); 339 new ObserverListThreadSafe<Foo>);
335 340
336 Adder a(1), b(1), c(1); 341 Adder a(1), b(1), c(1);
337 342
338 // No MessageLoop, so these should not be added. 343 // No sequence, so these should not be added.
339 observer_list->AddObserver(&a); 344 observer_list->AddObserver(&a);
340 observer_list->AddObserver(&b); 345 observer_list->AddObserver(&b);
341 346
342 { 347 {
343 // Add c when there's a loop. 348 // Add c when there's a sequence.
344 MessageLoop loop; 349 MessageLoop loop;
345 observer_list->AddObserver(&c); 350 observer_list->AddObserver(&c);
346 351
347 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); 352 observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
348 RunLoop().RunUntilIdle(); 353 RunLoop().RunUntilIdle();
349 354
350 EXPECT_EQ(0, a.total); 355 EXPECT_EQ(0, a.total);
351 EXPECT_EQ(0, b.total); 356 EXPECT_EQ(0, b.total);
352 EXPECT_EQ(10, c.total); 357 EXPECT_EQ(10, c.total);
353 358
354 // Now add a when there's a loop. 359 // Now add a when there's a sequence.
355 observer_list->AddObserver(&a); 360 observer_list->AddObserver(&a);
356 361
357 // Remove c when there's a loop. 362 // Remove c when there's a sequence.
358 observer_list->RemoveObserver(&c); 363 observer_list->RemoveObserver(&c);
359 364
360 // Notify again. 365 // Notify again.
361 observer_list->Notify(FROM_HERE, &Foo::Observe, 20); 366 observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
362 RunLoop().RunUntilIdle(); 367 RunLoop().RunUntilIdle();
363 368
364 EXPECT_EQ(20, a.total); 369 EXPECT_EQ(20, a.total);
365 EXPECT_EQ(0, b.total); 370 EXPECT_EQ(0, b.total);
366 EXPECT_EQ(10, c.total); 371 EXPECT_EQ(10, c.total);
367 } 372 }
368 373
369 // Removing should always succeed with or without a loop. 374 // Removing should always succeed with or without a sequence.
370 observer_list->RemoveObserver(&a); 375 observer_list->RemoveObserver(&a);
371 376
372 // Notifying should not fail but should also be a no-op. 377 // Notifying should not fail but should also be a no-op.
373 MessageLoop loop; 378 MessageLoop loop;
374 observer_list->AddObserver(&b); 379 observer_list->AddObserver(&b);
375 observer_list->Notify(FROM_HERE, &Foo::Observe, 30); 380 observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
376 RunLoop().RunUntilIdle(); 381 RunLoop().RunUntilIdle();
377 382
378 EXPECT_EQ(20, a.total); 383 EXPECT_EQ(20, a.total);
379 EXPECT_EQ(30, b.total); 384 EXPECT_EQ(30, b.total);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( 489 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
485 new ObserverListThreadSafe<Foo>); 490 new ObserverListThreadSafe<Foo>);
486 491
487 Adder a(1); 492 Adder a(1);
488 observer_list->AddObserver(&a); 493 observer_list->AddObserver(&a);
489 delete loop; 494 delete loop;
490 // Test passes if we don't crash here. 495 // Test passes if we don't crash here.
491 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); 496 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
492 } 497 }
493 498
499 namespace {
500
501 class SequenceVerificationObserver : public Foo {
502 public:
503 explicit SequenceVerificationObserver(
504 scoped_refptr<SequencedTaskRunner> task_runner)
505 : task_runner_(std::move(task_runner)) {}
506 ~SequenceVerificationObserver() override = default;
507
508 void Observe(int x) override {
509 called_on_valid_sequence_ = task_runner_->RunsTasksOnCurrentThread();
510 }
511
512 bool called_on_valid_sequence() const { return called_on_valid_sequence_; }
513
514 private:
515 const scoped_refptr<SequencedTaskRunner> task_runner_;
516 bool called_on_valid_sequence_ = false;
517
518 DISALLOW_COPY_AND_ASSIGN(SequenceVerificationObserver);
519 };
520
521 } // namespace
522
523 // Verify that observers are notified on the correct sequence.
524 TEST(ObserverListThreadSafeTest, NotificationOnValidSequence) {
525 using ObserverListType = ObserverListThreadSafe<Foo>;
526
527 test::ScopedTaskScheduler scoped_task_scheduler;
528
529 auto task_runner_1 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
530 auto task_runner_2 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
531
532 auto observer_list = make_scoped_refptr(new ObserverListType());
533
534 SequenceVerificationObserver observer_1(task_runner_1);
535 SequenceVerificationObserver observer_2(task_runner_2);
536
537 task_runner_1->PostTask(FROM_HERE,
538 Bind(&ObserverListType::AddObserver, observer_list,
539 Unretained(&observer_1)));
540 task_runner_2->PostTask(FROM_HERE,
541 Bind(&ObserverListType::AddObserver, observer_list,
542 Unretained(&observer_2)));
543
544 RunLoop().RunUntilIdle();
545
546 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
547
548 RunLoop().RunUntilIdle();
549
550 EXPECT_TRUE(observer_1.called_on_valid_sequence());
551 EXPECT_TRUE(observer_2.called_on_valid_sequence());
552 }
553
554 // Verify that when an observer is added to a NOTIFY_ALL ObserverListThreadSafe
555 // from a notification, it is itself notified.
556 TEST(ObserverListThreadSafeTest, AddObserverFromNotificationNotifyAll) {
557 using ObserverListType = ObserverListThreadSafe<Foo>;
558
559 MessageLoop message_loop;
560 auto observer_list = make_scoped_refptr(new ObserverListType());
561
562 Adder observer_added_from_notification(1);
563
564 AddInObserve<ObserverListType> initial_observer(observer_list.get());
565 initial_observer.SetToAdd(&observer_added_from_notification);
566 observer_list->AddObserver(&initial_observer);
567
568 observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
569
570 RunLoop().RunUntilIdle();
571
572 EXPECT_EQ(1, observer_added_from_notification.GetValue());
573 }
574
494 TEST(ObserverListTest, Existing) { 575 TEST(ObserverListTest, Existing) {
495 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); 576 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY);
496 Adder a(1); 577 Adder a(1);
497 AddInObserve<ObserverList<Foo> > b(&observer_list); 578 AddInObserve<ObserverList<Foo> > b(&observer_list);
498 Adder c(1); 579 Adder c(1);
499 b.SetToAdd(&c); 580 b.SetToAdd(&c);
500 581
501 observer_list.AddObserver(&a); 582 observer_list.AddObserver(&a);
502 observer_list.AddObserver(&b); 583 observer_list.AddObserver(&b);
503 584
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 // However, the first Observe() call will add a second observer: at this 1007 // 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 1008 // 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. 1009 // called on the newly added observer on the next iteration of the loop.
929 observer.Observe(10); 1010 observer.Observe(10);
930 } 1011 }
931 1012
932 EXPECT_EQ(-10, b.total); 1013 EXPECT_EQ(-10, b.total);
933 } 1014 }
934 1015
935 } // namespace base 1016 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698