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

Side by Side Diff: base/timer/timer_unittest.cc

Issue 2491613004: Make base::Timer sequence-friendly. (Closed)
Patch Set: merge up to r442293 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/timer/timer.h" 5 #include "base/timer/timer.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/callback.h" 13 #include "base/callback.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_loop.h"
17 #include "base/run_loop.h" 17 #include "base/run_loop.h"
18 #include "base/sequenced_task_runner.h" 18 #include "base/sequenced_task_runner.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/synchronization/waitable_event.h" 19 #include "base/synchronization/waitable_event.h"
21 #include "base/test/sequenced_worker_pool_owner.h" 20 #include "base/test/sequenced_worker_pool_owner.h"
22 #include "base/test/test_mock_time_task_runner.h" 21 #include "base/test/test_mock_time_task_runner.h"
23 #include "base/threading/platform_thread.h" 22 #include "base/threading/platform_thread.h"
24 #include "base/threading/sequenced_task_runner_handle.h" 23 #include "base/threading/sequenced_task_runner_handle.h"
25 #include "base/threading/thread.h" 24 #include "base/threading/thread.h"
26 #include "base/threading/thread_task_runner_handle.h"
27 #include "base/time/tick_clock.h" 25 #include "base/time/tick_clock.h"
28 #include "base/time/time.h" 26 #include "base/time/time.h"
29 #include "build/build_config.h" 27 #include "build/build_config.h"
30 #include "testing/gtest/include/gtest/gtest.h" 28 #include "testing/gtest/include/gtest/gtest.h"
31 29
32 namespace base { 30 namespace base {
33 31
34 namespace { 32 namespace {
35 33
36 // The message loops on which each timer should be tested. 34 // The message loops on which each timer should be tested.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 public: 98 public:
101 // |did_run|, if provided, will be signaled when Run() fires. 99 // |did_run|, if provided, will be signaled when Run() fires.
102 explicit OneShotTimerTester( 100 explicit OneShotTimerTester(
103 WaitableEvent* did_run = nullptr, 101 WaitableEvent* did_run = nullptr,
104 const TimeDelta& delay = TimeDelta::FromMilliseconds(10)) 102 const TimeDelta& delay = TimeDelta::FromMilliseconds(10))
105 : OneShotTimerTesterBase(did_run, delay), 103 : OneShotTimerTesterBase(did_run, delay),
106 quit_closure_(run_loop_.QuitClosure()) {} 104 quit_closure_(run_loop_.QuitClosure()) {}
107 105
108 ~OneShotTimerTester() override = default; 106 ~OneShotTimerTester() override = default;
109 107
110 void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner) { 108 void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) {
111 timer_->SetTaskRunner(std::move(task_runner)); 109 timer_->SetTaskRunner(std::move(task_runner));
112 110
113 // Run() will be invoked on |task_runner| but |run_loop_|'s QuitClosure 111 // Run() will be invoked on |task_runner| but |run_loop_|'s QuitClosure
114 // needs to run on this thread (where the MessageLoop lives). 112 // needs to run on this thread (where the MessageLoop lives).
115 quit_closure_ = 113 quit_closure_ = Bind(IgnoreResult(&SequencedTaskRunner::PostTask),
116 Bind(IgnoreResult(&SingleThreadTaskRunner::PostTask), 114 SequencedTaskRunnerHandle::Get(), FROM_HERE,
117 ThreadTaskRunnerHandle::Get(), FROM_HERE, run_loop_.QuitClosure()); 115 run_loop_.QuitClosure());
118 } 116 }
119 117
120 // Blocks until Run() executes and confirms that Run() didn't fire before 118 // Blocks until Run() executes and confirms that Run() didn't fire before
121 // |delay_| expired. 119 // |delay_| expired.
122 void WaitAndConfirmTimerFiredAfterDelay() { 120 void WaitAndConfirmTimerFiredAfterDelay() {
123 run_loop_.Run(); 121 run_loop_.Run();
124 122
125 EXPECT_NE(TimeTicks(), started_time()); 123 EXPECT_NE(TimeTicks(), started_time());
126 EXPECT_GE(TimeTicks::Now() - started_time(), delay()); 124 EXPECT_GE(TimeTicks::Now() - started_time(), delay());
127 } 125 }
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 false); 614 false);
617 EXPECT_FALSE(timer.IsRunning()); 615 EXPECT_FALSE(timer.IsRunning());
618 timer.Reset(); 616 timer.Reset();
619 EXPECT_TRUE(timer.IsRunning()); 617 EXPECT_TRUE(timer.IsRunning());
620 timer.Stop(); 618 timer.Stop();
621 EXPECT_FALSE(timer.IsRunning()); 619 EXPECT_FALSE(timer.IsRunning());
622 timer.Reset(); 620 timer.Reset();
623 EXPECT_TRUE(timer.IsRunning()); 621 EXPECT_TRUE(timer.IsRunning());
624 } 622 }
625 623
624 //-----------------------------------------------------------------------------
625
626 namespace { 626 namespace {
627 627
628 bool g_callback_happened1 = false; 628 bool g_callback_happened1 = false;
629 bool g_callback_happened2 = false; 629 bool g_callback_happened2 = false;
630 630
631 void ClearAllCallbackHappened() { 631 void ClearAllCallbackHappened() {
632 g_callback_happened1 = false; 632 g_callback_happened1 = false;
633 g_callback_happened2 = false; 633 g_callback_happened2 = false;
634 } 634 }
635 635
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), 669 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
670 Bind(&SetCallbackHappened1)); 670 Bind(&SetCallbackHappened1));
671 timer.Reset(); 671 timer.Reset();
672 // Since Reset happened before task ran, the user_task must not be cleared: 672 // Since Reset happened before task ran, the user_task must not be cleared:
673 ASSERT_FALSE(timer.user_task().is_null()); 673 ASSERT_FALSE(timer.user_task().is_null());
674 RunLoop().Run(); 674 RunLoop().Run();
675 EXPECT_TRUE(g_callback_happened1); 675 EXPECT_TRUE(g_callback_happened1);
676 } 676 }
677 } 677 }
678 678
679 namespace {
680
681 const size_t kNumWorkerThreads = 3;
682
683 // Fixture for tests requiring a worker pool. Includes a WaitableEvent so
684 // that cases may Wait() on one thread and Signal() (explicitly, or implicitly
685 // via helper methods) on another.
686 class TimerSequenceTest : public testing::Test {
687 public:
688 TimerSequenceTest()
689 : event_(WaitableEvent::ResetPolicy::AUTOMATIC,
690 WaitableEvent::InitialState::NOT_SIGNALED) {}
691
692 void SetUp() override {
693 pool1_owner_.reset(
694 new SequencedWorkerPoolOwner(kNumWorkerThreads, "test1"));
695 pool2_owner_.reset(
696 new SequencedWorkerPoolOwner(kNumWorkerThreads, "test2"));
697 }
698
699 // Block until Signal() is called on another thread.
700 void Wait() { event_.Wait(); }
701
702 void Signal() { event_.Signal(); }
703
704 // Helper to augment a task with a subsequent call to Signal().
705 Closure TaskWithSignal(const Closure& task) {
706 return Bind(&TimerSequenceTest::RunTaskAndSignal, Unretained(this), task);
707 }
708
709 // Create the timer.
710 void CreateTimer() { timer_.reset(new OneShotTimer); }
711
712 // Schedule an event on the timer.
713 void StartTimer(TimeDelta delay, const Closure& task) {
714 timer_->Start(FROM_HERE, delay, task);
715 }
716
717 void SetTaskRunnerForTimer(scoped_refptr<SequencedTaskRunner> task_runner) {
718 timer_->SetTaskRunner(std::move(task_runner));
719 }
720
721 // Tell the timer to abandon the task.
722 void AbandonTask() {
723 EXPECT_TRUE(timer_->IsRunning());
724 // Reset() to call Timer::AbandonScheduledTask()
725 timer_->Reset();
726 EXPECT_TRUE(timer_->IsRunning());
727 timer_->Stop();
728 EXPECT_FALSE(timer_->IsRunning());
729 }
730
731 static void VerifyAffinity(const SequencedTaskRunner* task_runner) {
732 EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread());
733 }
734
735 // Delete the timer.
736 void DeleteTimer() { timer_.reset(); }
737
738 protected:
739 const scoped_refptr<SequencedWorkerPool>& pool1() {
740 return pool1_owner_->pool();
741 }
742 const scoped_refptr<SequencedWorkerPool>& pool2() {
743 return pool2_owner_->pool();
744 }
745
746 private:
747 void RunTaskAndSignal(const Closure& task) {
748 task.Run();
749 Signal();
750 }
751
752 WaitableEvent event_;
753
754 MessageLoop message_loop_;
755 std::unique_ptr<SequencedWorkerPoolOwner> pool1_owner_;
756 std::unique_ptr<SequencedWorkerPoolOwner> pool2_owner_;
757
758 std::unique_ptr<OneShotTimer> timer_;
759
760 DISALLOW_COPY_AND_ASSIGN(TimerSequenceTest);
761 };
762
763 } // namespace
764
765 TEST_F(TimerSequenceTest, OneShotTimerTaskOnPoolThread) {
766 scoped_refptr<SequencedTaskRunner> task_runner =
767 pool1()->GetSequencedTaskRunner(pool1()->GetSequenceToken());
768
769 // Timer is created on this thread.
770 CreateTimer();
771
772 // Task will execute on a pool thread.
773 SetTaskRunnerForTimer(task_runner);
774 StartTimer(TimeDelta::FromMilliseconds(1),
775 Bind(&TimerSequenceTest::Signal, Unretained(this)));
776 Wait();
777
778 // Timer will be destroyed on this thread.
779 DeleteTimer();
780 }
781
782 TEST_F(TimerSequenceTest, OneShotTimerUsedOnPoolThread) {
783 scoped_refptr<SequencedTaskRunner> task_runner =
784 pool1()->GetSequencedTaskRunner(pool1()->GetSequenceToken());
785
786 // Timer is created on this thread.
787 CreateTimer();
788
789 // Task will be scheduled from a pool thread.
790 task_runner->PostTask(
791 FROM_HERE, Bind(&TimerSequenceTest::StartTimer, Unretained(this),
792 TimeDelta::FromMilliseconds(1),
793 Bind(&TimerSequenceTest::Signal, Unretained(this))));
794 Wait();
795
796 // Timer must be destroyed on pool thread, too.
797 task_runner->PostTask(
798 FROM_HERE,
799 TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
800 Wait();
801 }
802
803 TEST_F(TimerSequenceTest, OneShotTimerTwoPoolsAbandonTask) {
804 scoped_refptr<SequencedTaskRunner> task_runner1 =
805 pool1()->GetSequencedTaskRunner(pool1()->GetSequenceToken());
806 scoped_refptr<SequencedTaskRunner> task_runner2 =
807 pool2()->GetSequencedTaskRunner(pool2()->GetSequenceToken());
808
809 // Create timer on pool #1.
810 task_runner1->PostTask(
811 FROM_HERE,
812 TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
813 Wait();
814
815 // And tell it to execute on a different pool (#2).
816 task_runner1->PostTask(
817 FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
818 Unretained(this), task_runner2)));
819 Wait();
820
821 // Task will be scheduled from pool #1.
822 task_runner1->PostTask(FROM_HERE,
823 Bind(&TimerSequenceTest::StartTimer, Unretained(this),
824 TimeDelta::FromHours(1), Bind(&DoNothing)));
825
826 // Abandon task - must be called from scheduling pool (#1).
827 task_runner1->PostTask(
828 FROM_HERE,
829 TaskWithSignal(Bind(&TimerSequenceTest::AbandonTask, Unretained(this))));
830 Wait();
831
832 // Timer must be destroyed on the pool it was scheduled from (#1).
833 task_runner1->PostTask(
834 FROM_HERE,
835 TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
836 Wait();
837 }
838
839 TEST_F(TimerSequenceTest, OneShotTimerUsedAndTaskedOnDifferentPools) {
840 scoped_refptr<SequencedTaskRunner> task_runner1 =
841 pool1()->GetSequencedTaskRunner(pool1()->GetSequenceToken());
842 scoped_refptr<SequencedTaskRunner> task_runner2 =
843 pool2()->GetSequencedTaskRunner(pool2()->GetSequenceToken());
844
845 // Create timer on pool #1.
846 task_runner1->PostTask(
847 FROM_HERE,
848 TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
849 Wait();
850
851 // And tell it to execute on a different pool (#2).
852 task_runner1->PostTask(
853 FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
854 Unretained(this), task_runner2)));
855 Wait();
856
857 // Task will be scheduled from pool #1.
858 task_runner1->PostTask(
859 FROM_HERE, Bind(&TimerSequenceTest::StartTimer, Unretained(this),
860 TimeDelta::FromMilliseconds(1),
861 TaskWithSignal(Bind(&TimerSequenceTest::VerifyAffinity,
862 Unretained(task_runner2.get())))));
863
864 Wait();
865
866 // Timer must be destroyed on the pool it was scheduled from (#1).
867 task_runner1->PostTask(
868 FROM_HERE,
869 TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
870 Wait();
871 }
872
679 } // namespace base 873 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698