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

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

Issue 2491613004: Make base::Timer sequence-friendly. (Closed)
Patch Set: rebase Created 4 years 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
« base/timer/timer.cc ('K') | « base/timer/timer.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 22 matching lines...) Expand all
59 // |did_run|, if provided, will be signaled when Run() fires. 57 // |did_run|, if provided, will be signaled when Run() fires.
60 explicit OneShotTimerTester( 58 explicit OneShotTimerTester(
61 WaitableEvent* did_run = nullptr, 59 WaitableEvent* did_run = nullptr,
62 const TimeDelta& delay = TimeDelta::FromMilliseconds(10)) 60 const TimeDelta& delay = TimeDelta::FromMilliseconds(10))
63 : quit_closure_(run_loop_.QuitClosure()), 61 : quit_closure_(run_loop_.QuitClosure()),
64 did_run_(did_run), 62 did_run_(did_run),
65 delay_(delay) {} 63 delay_(delay) {}
66 64
67 virtual ~OneShotTimerTester() = default; 65 virtual ~OneShotTimerTester() = default;
68 66
69 void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner) { 67 void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) {
70 timer_->SetTaskRunner(std::move(task_runner)); 68 timer_->SetTaskRunner(std::move(task_runner));
71 69
72 // Run() will be invoked on |task_runner| but |run_loop_|'s QuitClosure 70 // Run() will be invoked on |task_runner| but |run_loop_|'s QuitClosure
73 // needs to run on this thread (where the MessageLoop lives). 71 // needs to run on this thread (where the MessageLoop lives).
74 quit_closure_ = 72 quit_closure_ = Bind(IgnoreResult(&SingleThreadTaskRunner::PostTask),
75 Bind(IgnoreResult(&SingleThreadTaskRunner::PostTask), 73 SequencedTaskRunnerHandle::Get(), FROM_HERE,
76 ThreadTaskRunnerHandle::Get(), FROM_HERE, run_loop_.QuitClosure()); 74 run_loop_.QuitClosure());
77 } 75 }
78 76
79 void Start() { 77 void Start() {
80 started_time_ = TimeTicks::Now(); 78 started_time_ = TimeTicks::Now();
81 timer_->Start(FROM_HERE, delay_, this, &OneShotTimerTester::Run); 79 timer_->Start(FROM_HERE, delay_, this, &OneShotTimerTester::Run);
82 } 80 }
83 81
84 // Blocks until Run() executes and confirms that Run() didn't fire before 82 // Blocks until Run() executes and confirms that Run() didn't fire before
85 // |delay_| expired. 83 // |delay_| expired.
86 void WaitAndConfirmTimerFiredAfterDelay() { 84 void WaitAndConfirmTimerFiredAfterDelay() {
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10), 642 timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
645 Bind(&SetCallbackHappened1)); 643 Bind(&SetCallbackHappened1));
646 timer.Reset(); 644 timer.Reset();
647 // Since Reset happened before task ran, the user_task must not be cleared: 645 // Since Reset happened before task ran, the user_task must not be cleared:
648 ASSERT_FALSE(timer.user_task().is_null()); 646 ASSERT_FALSE(timer.user_task().is_null());
649 RunLoop().Run(); 647 RunLoop().Run();
650 EXPECT_TRUE(g_callback_happened1); 648 EXPECT_TRUE(g_callback_happened1);
651 } 649 }
652 } 650 }
653 651
652 namespace {
653
654 const size_t kNumWorkerThreads = 3;
655
656 // Fixture for tests requiring a worker pool. Includes a WaitableEvent so
657 // that cases may Wait() on one thread and Signal() (explicitly, or implicitly
658 // via helper methods) on another.
659 class TimerSequenceTest : public testing::Test {
660 public:
661 TimerSequenceTest()
662 : event_(WaitableEvent::ResetPolicy::AUTOMATIC,
663 WaitableEvent::InitialState::NOT_SIGNALED) {}
664
665 void SetUp() override {
666 pool1_owner_.reset(
667 new SequencedWorkerPoolOwner(kNumWorkerThreads, "test1"));
668 pool2_owner_.reset(
669 new SequencedWorkerPoolOwner(kNumWorkerThreads, "test2"));
670 }
671
672 // Block until Signal() is called on another thread.
673 void Wait() { event_.Wait(); }
674
675 void Signal() { event_.Signal(); }
676
677 // Helper to augment a task with a subsequent call to Signal().
678 Closure TaskWithSignal(const Closure& task) {
679 return Bind(&TimerSequenceTest::RunTaskAndSignal, Unretained(this), task);
680 }
681
682 // Create the timer.
683 void CreateTimer() { timer_.reset(new OneShotTimer); }
684
685 // Schedule an event on the timer.
686 void StartTimer(TimeDelta delay, const Closure& task) {
687 timer_->Start(FROM_HERE, delay, task);
688 }
689
690 void SetTaskRunnerForTimer(scoped_refptr<SequencedTaskRunner> task_runner) {
691 timer_->SetTaskRunner(std::move(task_runner));
692 }
693
694 // Tell the timer to abandon the task.
695 void AbandonTask() {
696 EXPECT_TRUE(timer_->IsRunning());
697 // Reset() to call Timer::AbandonScheduledTask()
698 timer_->Reset();
699 EXPECT_TRUE(timer_->IsRunning());
700 timer_->Stop();
701 EXPECT_FALSE(timer_->IsRunning());
702 }
703
704 static void VerifyAffinity(const SequencedTaskRunner* task_runner) {
705 EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread());
706 }
707
708 // Delete the timer.
709 void DeleteTimer() { timer_.reset(); }
710
711 protected:
712 const scoped_refptr<SequencedWorkerPool>& pool1() {
713 return pool1_owner_->pool();
714 }
715 const scoped_refptr<SequencedWorkerPool>& pool2() {
716 return pool2_owner_->pool();
717 }
718
719 private:
720 void RunTaskAndSignal(const Closure& task) {
721 task.Run();
722 Signal();
723 }
724
725 WaitableEvent event_;
726
727 MessageLoop message_loop_;
728 std::unique_ptr<SequencedWorkerPoolOwner> pool1_owner_;
729 std::unique_ptr<SequencedWorkerPoolOwner> pool2_owner_;
730
731 std::unique_ptr<OneShotTimer> timer_;
732
733 DISALLOW_COPY_AND_ASSIGN(TimerSequenceTest);
734 };
735
736 } // namespace
737
738 TEST_F(TimerSequenceTest, OneShotTimerTaskOnPoolThread) {
739 scoped_refptr<SequencedTaskRunner> task_runner =
740 pool1()->GetSequencedTaskRunner(pool1()->GetSequenceToken());
741
742 // Timer is created on this thread.
743 CreateTimer();
744
745 // Task will execute on a pool thread.
746 SetTaskRunnerForTimer(task_runner);
747 StartTimer(TimeDelta::FromMilliseconds(1),
748 Bind(&TimerSequenceTest::Signal, Unretained(this)));
749 Wait();
750
751 // Timer will be destroyed on this thread.
752 DeleteTimer();
753 }
754
755 TEST_F(TimerSequenceTest, OneShotTimerUsedOnPoolThread) {
756 scoped_refptr<SequencedTaskRunner> task_runner =
757 pool1()->GetSequencedTaskRunner(pool1()->GetSequenceToken());
758
759 // Timer is created on this thread.
760 CreateTimer();
761
762 // Task will be scheduled from a pool thread.
763 task_runner->PostTask(
764 FROM_HERE, Bind(&TimerSequenceTest::StartTimer, Unretained(this),
765 TimeDelta::FromMilliseconds(1),
766 Bind(&TimerSequenceTest::Signal, Unretained(this))));
767 Wait();
768
769 // Timer must be destroyed on pool thread, too.
770 task_runner->PostTask(
771 FROM_HERE,
772 TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
773 Wait();
774 }
775
776 TEST_F(TimerSequenceTest, OneShotTimerTwoPoolsAbandonTask) {
777 scoped_refptr<SequencedTaskRunner> task_runner1 =
778 pool1()->GetSequencedTaskRunner(pool1()->GetSequenceToken());
779 scoped_refptr<SequencedTaskRunner> task_runner2 =
780 pool2()->GetSequencedTaskRunner(pool2()->GetSequenceToken());
781
782 // Create timer on pool #1.
783 task_runner1->PostTask(
784 FROM_HERE,
785 TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
786 Wait();
787
788 // And tell it to execute on a different pool (#2).
789 task_runner1->PostTask(
790 FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
791 Unretained(this), task_runner2)));
792 Wait();
793
794 // Task will be scheduled from pool #1.
795 task_runner1->PostTask(FROM_HERE,
796 Bind(&TimerSequenceTest::StartTimer, Unretained(this),
797 TimeDelta::FromHours(1), Bind(&DoNothing)));
798
799 // Abandon task - must be called from scheduling pool (#1).
800 task_runner1->PostTask(
801 FROM_HERE,
802 TaskWithSignal(Bind(&TimerSequenceTest::AbandonTask, Unretained(this))));
803 Wait();
804
805 // Timer must be destroyed on the pool it was scheduled from (#1).
806 task_runner1->PostTask(
807 FROM_HERE,
808 TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
809 Wait();
810 }
811
812 TEST_F(TimerSequenceTest, OneShotTimerUsedAndTaskedOnDifferentPools) {
813 scoped_refptr<SequencedTaskRunner> task_runner1 =
814 pool1()->GetSequencedTaskRunner(pool1()->GetSequenceToken());
815 scoped_refptr<SequencedTaskRunner> task_runner2 =
816 pool2()->GetSequencedTaskRunner(pool2()->GetSequenceToken());
817
818 // Create timer on pool #1.
819 task_runner1->PostTask(
820 FROM_HERE,
821 TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
822 Wait();
823
824 // And tell it to execute on a different pool (#2).
825 task_runner1->PostTask(
826 FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
827 Unretained(this), task_runner2)));
828 Wait();
829
830 // Task will be scheduled from pool #1.
831 task_runner1->PostTask(
832 FROM_HERE, Bind(&TimerSequenceTest::StartTimer, Unretained(this),
833 TimeDelta::FromMilliseconds(1),
834 TaskWithSignal(Bind(&TimerSequenceTest::VerifyAffinity,
835 Unretained(task_runner2.get())))));
836
837 Wait();
838
839 // Timer must be destroyed on the pool it was scheduled from (#1).
840 task_runner1->PostTask(
841 FROM_HERE,
842 TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
843 Wait();
844 }
845
654 } // namespace base 846 } // namespace base
OLDNEW
« base/timer/timer.cc ('K') | « base/timer/timer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698