| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/task_scheduler/delayed_task_manager.h" | 5 #include "base/task_scheduler/delayed_task_manager.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/memory/ptr_util.h" |
| 11 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 12 #include "base/sequenced_task_runner.h" | |
| 13 #include "base/single_thread_task_runner.h" | |
| 14 #include "base/task_runner.h" | |
| 15 #include "base/task_scheduler/scheduler_worker_pool.h" | |
| 16 #include "base/task_scheduler/sequence.h" | |
| 17 #include "base/task_scheduler/task.h" | 13 #include "base/task_scheduler/task.h" |
| 18 #include "base/test/test_mock_time_task_runner.h" | 14 #include "base/test/test_mock_time_task_runner.h" |
| 19 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 20 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 22 | 18 |
| 23 namespace base { | 19 namespace base { |
| 24 namespace internal { | 20 namespace internal { |
| 25 namespace { | 21 namespace { |
| 26 | 22 |
| 27 constexpr TimeDelta kLongDelay = TimeDelta::FromHours(1); | 23 constexpr TimeDelta kLongDelay = TimeDelta::FromHours(1); |
| 28 | 24 |
| 29 class MockSchedulerWorkerPool : public SchedulerWorkerPool { | 25 class MockTaskTarget { |
| 30 public: | 26 public: |
| 31 // SchedulerWorkerPool: | 27 MockTaskTarget() = default; |
| 32 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits( | 28 ~MockTaskTarget() = default; |
| 33 const TaskTraits& traits) override { | 29 |
| 34 ADD_FAILURE() << "Call to unimplemented method."; | 30 // gMock currently doesn't support move-only types, so PostTaskNowCallback() |
| 35 return nullptr; | 31 // handles the move-only type and forwards to the mocked method. |
| 32 MOCK_METHOD1(DoPostTaskNowCallback, void(const Task*)); |
| 33 |
| 34 void PostTaskNowCallback(std::unique_ptr<Task> task) { |
| 35 DoPostTaskNowCallback(task.get()); |
| 36 } | 36 } |
| 37 | 37 |
| 38 scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits( | 38 private: |
| 39 const TaskTraits& traits) override { | 39 DISALLOW_COPY_AND_ASSIGN(MockTaskTarget); |
| 40 ADD_FAILURE() << "Call to unimplemented method."; | 40 }; |
| 41 return nullptr; | |
| 42 } | |
| 43 | 41 |
| 44 scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits( | 42 class TaskSchedulerDelayedTaskManagerTest : public testing::Test { |
| 45 const TaskTraits& traits) override { | 43 public: |
| 46 ADD_FAILURE() << "Call to unimplemented method."; | 44 TaskSchedulerDelayedTaskManagerTest() |
| 47 return nullptr; | 45 : service_thread_task_runner_(new TestMockTimeTaskRunner), |
| 48 } | 46 delayed_task_manager_(service_thread_task_runner_) {} |
| 47 ~TaskSchedulerDelayedTaskManagerTest() override = default; |
| 49 | 48 |
| 50 void ReEnqueueSequence(scoped_refptr<Sequence> sequence, | 49 protected: |
| 51 const SequenceSortKey& sequence_sort_key) override { | 50 scoped_refptr<TestMockTimeTaskRunner> service_thread_task_runner_; |
| 52 ADD_FAILURE() << "Call to unimplemented method."; | 51 DelayedTaskManager delayed_task_manager_; |
| 53 } | |
| 54 | 52 |
| 55 bool PostTaskWithSequence(std::unique_ptr<Task> task, | 53 private: |
| 56 scoped_refptr<Sequence> sequence, | 54 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerDelayedTaskManagerTest); |
| 57 SchedulerWorker* worker) override { | |
| 58 ADD_FAILURE() << "Call to unimplemented method."; | |
| 59 return true; | |
| 60 } | |
| 61 | |
| 62 void PostTaskWithSequenceNow(std::unique_ptr<Task> task, | |
| 63 scoped_refptr<Sequence> sequence, | |
| 64 SchedulerWorker* worker) override { | |
| 65 PostTaskWithSequenceNowMock(task.get(), sequence.get(), worker); | |
| 66 } | |
| 67 | |
| 68 MOCK_METHOD3(PostTaskWithSequenceNowMock, | |
| 69 void(const Task*, | |
| 70 const Sequence*, | |
| 71 const SchedulerWorker* worker)); | |
| 72 }; | 55 }; |
| 73 | 56 |
| 74 } // namespace | 57 } // namespace |
| 75 | 58 |
| 76 // Verify that a delayed task isn't forwarded to its SchedulerWorkerPool before | 59 // Verify that a delayed task isn't forwarded before it is ripe for execution. |
| 77 // it is ripe for execution. | 60 TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskDoesNotRunTooEarly) { |
| 78 TEST(TaskSchedulerDelayedTaskManagerTest, DelayedTaskDoesNotRunTooEarly) { | 61 auto task = |
| 79 scoped_refptr<TestMockTimeTaskRunner> service_thread_task_runner( | 62 MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), kLongDelay); |
| 80 new TestMockTimeTaskRunner); | |
| 81 DelayedTaskManager manager(service_thread_task_runner); | |
| 82 | 63 |
| 83 std::unique_ptr<Task> task( | 64 testing::StrictMock<MockTaskTarget> task_target; |
| 84 new Task(FROM_HERE, Bind(&DoNothing), TaskTraits(), kLongDelay)); | |
| 85 scoped_refptr<Sequence> sequence(new Sequence); | |
| 86 testing::StrictMock<MockSchedulerWorkerPool> worker_pool; | |
| 87 | 65 |
| 88 // Send |task| to the DelayedTaskManager. | 66 // Send |task| to the DelayedTaskManager. |
| 89 manager.AddDelayedTask(std::move(task), sequence, nullptr, &worker_pool); | 67 delayed_task_manager_.AddDelayedTask( |
| 68 std::move(task), |
| 69 Bind(&MockTaskTarget::PostTaskNowCallback, Unretained(&task_target))); |
| 90 | 70 |
| 91 // Run tasks that are ripe for execution. Don't expect any call to the mock | 71 // Run tasks that are ripe for execution. Don't expect any forwarding to |
| 92 // method of |worker_pool|. | 72 // |task_target|. |
| 93 service_thread_task_runner->RunUntilIdle(); | 73 service_thread_task_runner_->RunUntilIdle(); |
| 94 } | 74 } |
| 95 | 75 |
| 96 // Verify that a delayed task is forwarded to its SchedulerWorkerPool when it is | 76 // Verify that a delayed task is forwarded when it is ripe for execution. |
| 97 // ripe for execution. | 77 TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskRunsAfterDelay) { |
| 98 TEST(TaskSchedulerDelayedTaskManagerTest, DelayedTaskRunsAfterDelay) { | 78 auto task = |
| 99 scoped_refptr<TestMockTimeTaskRunner> service_thread_task_runner( | 79 MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), kLongDelay); |
| 100 new TestMockTimeTaskRunner); | 80 const Task* task_raw = task.get(); |
| 101 DelayedTaskManager manager(service_thread_task_runner); | |
| 102 | 81 |
| 103 std::unique_ptr<Task> task( | 82 testing::StrictMock<MockTaskTarget> task_target; |
| 104 new Task(FROM_HERE, Bind(&DoNothing), TaskTraits(), kLongDelay)); | |
| 105 const Task* task_raw = task.get(); | |
| 106 scoped_refptr<Sequence> sequence(new Sequence); | |
| 107 testing::StrictMock<MockSchedulerWorkerPool> worker_pool; | |
| 108 | 83 |
| 109 // Send |task| to the DelayedTaskManager. | 84 // Send |task| to the DelayedTaskManager. |
| 110 manager.AddDelayedTask(std::move(task), sequence, nullptr, &worker_pool); | 85 delayed_task_manager_.AddDelayedTask( |
| 86 std::move(task), |
| 87 Bind(&MockTaskTarget::PostTaskNowCallback, Unretained(&task_target))); |
| 111 | 88 |
| 112 // Fast-forward time. Expect a call to the mock method of |worker_pool|. | 89 // Fast-forward time. Expect the task is forwarded to |task_target|. |
| 113 EXPECT_CALL(worker_pool, | 90 EXPECT_CALL(task_target, DoPostTaskNowCallback(task_raw)); |
| 114 PostTaskWithSequenceNowMock(task_raw, sequence.get(), nullptr)); | 91 service_thread_task_runner_->FastForwardBy(kLongDelay); |
| 115 service_thread_task_runner->FastForwardBy(kLongDelay); | |
| 116 } | 92 } |
| 117 | 93 |
| 118 // Verify that multiple delayed task are forwarded to their SchedulerWorkerPool | 94 // Verify that multiple delayed tasks are forwarded when they are ripe for |
| 119 // when they are ripe for execution. | 95 // execution. |
| 120 TEST(TaskSchedulerDelayedTaskManagerTest, DelayedTasksRunAfterDelay) { | 96 TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTasksRunAfterDelay) { |
| 121 scoped_refptr<TestMockTimeTaskRunner> service_thread_task_runner( | 97 auto task_a = MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), |
| 122 new TestMockTimeTaskRunner); | 98 TimeDelta::FromHours(1)); |
| 123 DelayedTaskManager manager(service_thread_task_runner); | |
| 124 | |
| 125 scoped_refptr<Sequence> sequence(new Sequence); | |
| 126 testing::StrictMock<MockSchedulerWorkerPool> worker_pool; | |
| 127 | |
| 128 std::unique_ptr<Task> task_a(new Task(FROM_HERE, Bind(&DoNothing), | |
| 129 TaskTraits(), TimeDelta::FromHours(1))); | |
| 130 const Task* task_a_raw = task_a.get(); | 99 const Task* task_a_raw = task_a.get(); |
| 131 | 100 |
| 132 std::unique_ptr<Task> task_b(new Task(FROM_HERE, Bind(&DoNothing), | 101 auto task_b = MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), |
| 133 TaskTraits(), TimeDelta::FromHours(2))); | 102 TimeDelta::FromHours(2)); |
| 134 const Task* task_b_raw = task_b.get(); | 103 const Task* task_b_raw = task_b.get(); |
| 135 | 104 |
| 136 std::unique_ptr<Task> task_c(new Task(FROM_HERE, Bind(&DoNothing), | 105 auto task_c = MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), TaskTraits(), |
| 137 TaskTraits(), TimeDelta::FromHours(1))); | 106 TimeDelta::FromHours(1)); |
| 138 const Task* task_c_raw = task_c.get(); | 107 const Task* task_c_raw = task_c.get(); |
| 139 | 108 |
| 109 testing::StrictMock<MockTaskTarget> task_target; |
| 110 |
| 140 // Send tasks to the DelayedTaskManager. | 111 // Send tasks to the DelayedTaskManager. |
| 141 manager.AddDelayedTask(std::move(task_a), sequence, nullptr, &worker_pool); | 112 delayed_task_manager_.AddDelayedTask( |
| 142 manager.AddDelayedTask(std::move(task_b), sequence, nullptr, &worker_pool); | 113 std::move(task_a), |
| 143 manager.AddDelayedTask(std::move(task_c), sequence, nullptr, &worker_pool); | 114 Bind(&MockTaskTarget::PostTaskNowCallback, Unretained(&task_target))); |
| 115 delayed_task_manager_.AddDelayedTask( |
| 116 std::move(task_b), |
| 117 Bind(&MockTaskTarget::PostTaskNowCallback, Unretained(&task_target))); |
| 118 delayed_task_manager_.AddDelayedTask( |
| 119 std::move(task_c), |
| 120 Bind(&MockTaskTarget::PostTaskNowCallback, Unretained(&task_target))); |
| 144 | 121 |
| 145 // Run tasks that are ripe for execution on the service thread. Don't expect | 122 // Run tasks that are ripe for execution on the service thread. Don't expect |
| 146 // any call to the mock method of |worker_pool|. | 123 // any call to |task_target|. |
| 147 service_thread_task_runner->RunUntilIdle(); | 124 service_thread_task_runner_->RunUntilIdle(); |
| 148 | 125 |
| 149 // Fast-forward time. Expect |task_a_raw| and |task_c_raw| to be forwarded to | 126 // Fast-forward time. Expect |task_a_raw| and |task_c_raw| to be forwarded to |
| 150 // the worker pool. | 127 // |task_target|. |
| 151 EXPECT_CALL(worker_pool, | 128 EXPECT_CALL(task_target, DoPostTaskNowCallback(task_a_raw)); |
| 152 PostTaskWithSequenceNowMock(task_a_raw, sequence.get(), nullptr)); | 129 EXPECT_CALL(task_target, DoPostTaskNowCallback(task_c_raw)); |
| 153 EXPECT_CALL(worker_pool, | 130 service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1)); |
| 154 PostTaskWithSequenceNowMock(task_c_raw, sequence.get(), nullptr)); | 131 testing::Mock::VerifyAndClear(&task_target); |
| 155 service_thread_task_runner->FastForwardBy(TimeDelta::FromHours(1)); | |
| 156 testing::Mock::VerifyAndClear(&worker_pool); | |
| 157 | 132 |
| 158 // Fast-forward time. Expect |task_b_raw| to be forwarded to the worker pool. | 133 // Fast-forward time. Expect |task_b_raw| to be forwarded to |task_target|. |
| 159 EXPECT_CALL(worker_pool, | 134 EXPECT_CALL(task_target, DoPostTaskNowCallback(task_b_raw)); |
| 160 PostTaskWithSequenceNowMock(task_b_raw, sequence.get(), nullptr)); | 135 service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1)); |
| 161 service_thread_task_runner->FastForwardBy(TimeDelta::FromHours(1)); | 136 testing::Mock::VerifyAndClear(&task_target); |
| 162 testing::Mock::VerifyAndClear(&worker_pool); | |
| 163 } | 137 } |
| 164 | 138 |
| 165 } // namespace internal | 139 } // namespace internal |
| 166 } // namespace base | 140 } // namespace base |
| OLD | NEW |