xref: /aosp_15_r20/external/libchrome/base/task_scheduler/delayed_task_manager_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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
3 // found in the LICENSE file.
4 
5 #include "base/task_scheduler/delayed_task_manager.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/task_scheduler/task.h"
15 #include "base/test/bind_test_util.h"
16 #include "base/test/test_mock_time_task_runner.h"
17 #include "base/threading/thread.h"
18 #include "base/time/time.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace base {
23 namespace internal {
24 namespace {
25 
26 constexpr TimeDelta kLongDelay = TimeDelta::FromHours(1);
27 
28 class MockTask {
29  public:
30   MOCK_METHOD0(Run, void());
31 };
32 
RunTask(Task task)33 void RunTask(Task task) {
34   std::move(task.task).Run();
35 }
36 
37 class TaskSchedulerDelayedTaskManagerTest : public testing::Test {
38  protected:
TaskSchedulerDelayedTaskManagerTest()39   TaskSchedulerDelayedTaskManagerTest()
40       : delayed_task_manager_(
41             service_thread_task_runner_->DeprecatedGetMockTickClock()),
42         task_(FROM_HERE,
43               BindOnce(&MockTask::Run, Unretained(&mock_task_)),
44               TaskTraits(),
45               kLongDelay) {
46     // The constructor of Task computes |delayed_run_time| by adding |delay| to
47     // the real time. Recompute it by adding |delay| to the mock time.
48     task_.delayed_run_time =
49         service_thread_task_runner_->GetMockTickClock()->NowTicks() +
50         kLongDelay;
51   }
52   ~TaskSchedulerDelayedTaskManagerTest() override = default;
53 
54   const scoped_refptr<TestMockTimeTaskRunner> service_thread_task_runner_ =
55       MakeRefCounted<TestMockTimeTaskRunner>();
56   DelayedTaskManager delayed_task_manager_;
57   testing::StrictMock<MockTask> mock_task_;
58   Task task_;
59 
60  private:
61   DISALLOW_COPY_AND_ASSIGN(TaskSchedulerDelayedTaskManagerTest);
62 };
63 
64 }  // namespace
65 
66 // Verify that a delayed task isn't forwarded before Start().
TEST_F(TaskSchedulerDelayedTaskManagerTest,DelayedTaskDoesNotRunBeforeStart)67 TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskDoesNotRunBeforeStart) {
68   // Send |task| to the DelayedTaskManager.
69   delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
70 
71   // Fast-forward time until the task is ripe for execution. Since Start() has
72   // not been called, the task should not be forwarded to RunTask() (MockTask is
73   // a StrictMock without expectations so test will fail if RunTask() runs it).
74   service_thread_task_runner_->FastForwardBy(kLongDelay);
75 }
76 
77 // Verify that a delayed task added before Start() and whose delay expires after
78 // Start() is forwarded when its delay expires.
TEST_F(TaskSchedulerDelayedTaskManagerTest,DelayedTaskPostedBeforeStartExpiresAfterStartRunsOnExpire)79 TEST_F(TaskSchedulerDelayedTaskManagerTest,
80        DelayedTaskPostedBeforeStartExpiresAfterStartRunsOnExpire) {
81   // Send |task| to the DelayedTaskManager.
82   delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
83 
84   delayed_task_manager_.Start(service_thread_task_runner_);
85 
86   // Run tasks on the service thread. Don't expect any forwarding to
87   // |task_target_| since the task isn't ripe for execution.
88   service_thread_task_runner_->RunUntilIdle();
89 
90   // Fast-forward time until the task is ripe for execution. Expect the task to
91   // be forwarded to RunTask().
92   EXPECT_CALL(mock_task_, Run());
93   service_thread_task_runner_->FastForwardBy(kLongDelay);
94 }
95 
96 // Verify that a delayed task added before Start() and whose delay expires
97 // before Start() is forwarded when Start() is called.
TEST_F(TaskSchedulerDelayedTaskManagerTest,DelayedTaskPostedBeforeStartExpiresBeforeStartRunsOnStart)98 TEST_F(TaskSchedulerDelayedTaskManagerTest,
99        DelayedTaskPostedBeforeStartExpiresBeforeStartRunsOnStart) {
100   // Send |task| to the DelayedTaskManager.
101   delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
102 
103   // Run tasks on the service thread. Don't expect any forwarding to
104   // |task_target_| since the task isn't ripe for execution.
105   service_thread_task_runner_->RunUntilIdle();
106 
107   // Fast-forward time until the task is ripe for execution. Don't expect the
108   // task to be forwarded since Start() hasn't been called yet.
109   service_thread_task_runner_->FastForwardBy(kLongDelay);
110 
111   // Start the DelayedTaskManager. Expect the task to be forwarded to RunTask().
112   EXPECT_CALL(mock_task_, Run());
113   delayed_task_manager_.Start(service_thread_task_runner_);
114   service_thread_task_runner_->RunUntilIdle();
115 }
116 
117 // Verify that a delayed task added after Start() isn't forwarded before it is
118 // ripe for execution.
TEST_F(TaskSchedulerDelayedTaskManagerTest,DelayedTaskDoesNotRunTooEarly)119 TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskDoesNotRunTooEarly) {
120   delayed_task_manager_.Start(service_thread_task_runner_);
121 
122   // Send |task| to the DelayedTaskManager.
123   delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
124 
125   // Run tasks that are ripe for execution. Don't expect any forwarding to
126   // RunTask().
127   service_thread_task_runner_->RunUntilIdle();
128 }
129 
130 // Verify that a delayed task added after Start() is forwarded when it is ripe
131 // for execution.
TEST_F(TaskSchedulerDelayedTaskManagerTest,DelayedTaskRunsAfterDelay)132 TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskRunsAfterDelay) {
133   delayed_task_manager_.Start(service_thread_task_runner_);
134 
135   // Send |task| to the DelayedTaskManager.
136   delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
137 
138   // Fast-forward time. Expect the task to be forwarded to RunTask().
139   EXPECT_CALL(mock_task_, Run());
140   service_thread_task_runner_->FastForwardBy(kLongDelay);
141 }
142 
143 // Verify that multiple delayed tasks added after Start() are forwarded when
144 // they are ripe for execution.
TEST_F(TaskSchedulerDelayedTaskManagerTest,DelayedTasksRunAfterDelay)145 TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTasksRunAfterDelay) {
146   delayed_task_manager_.Start(service_thread_task_runner_);
147 
148   testing::StrictMock<MockTask> mock_task_a;
149   Task task_a(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_a)),
150               TaskTraits(), TimeDelta::FromHours(1));
151 
152   testing::StrictMock<MockTask> mock_task_b;
153   Task task_b(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_b)),
154               TaskTraits(), TimeDelta::FromHours(2));
155 
156   testing::StrictMock<MockTask> mock_task_c;
157   Task task_c(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_c)),
158               TaskTraits(), TimeDelta::FromHours(1));
159 
160   // Send tasks to the DelayedTaskManager.
161   delayed_task_manager_.AddDelayedTask(std::move(task_a), BindOnce(&RunTask));
162   delayed_task_manager_.AddDelayedTask(std::move(task_b), BindOnce(&RunTask));
163   delayed_task_manager_.AddDelayedTask(std::move(task_c), BindOnce(&RunTask));
164 
165   // Run tasks that are ripe for execution on the service thread. Don't expect
166   // any call to RunTask().
167   service_thread_task_runner_->RunUntilIdle();
168 
169   // Fast-forward time. Expect |task_a| and |task_c| to be forwarded to
170   // |task_target_|.
171   EXPECT_CALL(mock_task_a, Run());
172   EXPECT_CALL(mock_task_c, Run());
173   service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1));
174   testing::Mock::VerifyAndClear(&mock_task_a);
175   testing::Mock::VerifyAndClear(&mock_task_c);
176 
177   // Fast-forward time. Expect |task_b| to be forwarded to RunTask().
178   EXPECT_CALL(mock_task_b, Run());
179   service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1));
180   testing::Mock::VerifyAndClear(&mock_task_b);
181 }
182 
TEST_F(TaskSchedulerDelayedTaskManagerTest,PostTaskDuringStart)183 TEST_F(TaskSchedulerDelayedTaskManagerTest, PostTaskDuringStart) {
184   Thread other_thread("Test");
185   other_thread.StartAndWaitForTesting();
186 
187   WaitableEvent task_posted;
188 
189   other_thread.task_runner()->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
190                                          delayed_task_manager_.AddDelayedTask(
191                                              std::move(task_),
192                                              BindOnce(&RunTask));
193                                          task_posted.Signal();
194                                        }));
195 
196   delayed_task_manager_.Start(service_thread_task_runner_);
197 
198   // The test is testing a race between AddDelayedTask/Start but it still needs
199   // synchronization to ensure we don't do the final verification before the
200   // task itself is posted.
201   task_posted.Wait();
202 
203   // Fast-forward time. Expect the task to be forwarded to RunTask().
204   EXPECT_CALL(mock_task_, Run());
205   service_thread_task_runner_->FastForwardBy(kLongDelay);
206 }
207 
208 }  // namespace internal
209 }  // namespace base
210