1 // Copyright 2017 The Chromium Authors
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/test/test_mock_time_task_runner.h"
6
7 #include "base/cancelable_callback.h"
8 #include "base/functional/bind.h"
9 #include "base/functional/callback_helpers.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/run_loop.h"
12 #include "base/task/sequenced_task_runner.h"
13 #include "base/task/single_thread_task_runner.h"
14 #include "base/test/bind.h"
15 #include "base/test/gtest_util.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/threading/thread.h"
18 #include "base/time/time.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace base {
22
23 // Basic usage should work the same from default and bound
24 // TestMockTimeTaskRunners.
TEST(TestMockTimeTaskRunnerTest,Basic)25 TEST(TestMockTimeTaskRunnerTest, Basic) {
26 static constexpr TestMockTimeTaskRunner::Type kTestCases[] = {
27 TestMockTimeTaskRunner::Type::kStandalone,
28 TestMockTimeTaskRunner::Type::kBoundToThread};
29
30 for (auto type : kTestCases) {
31 SCOPED_TRACE(static_cast<int>(type));
32
33 auto mock_time_task_runner = MakeRefCounted<TestMockTimeTaskRunner>(type);
34 int counter = 0;
35
36 mock_time_task_runner->PostTask(
37 FROM_HERE, base::BindOnce([](int* counter) { *counter += 1; },
38 Unretained(&counter)));
39 mock_time_task_runner->PostTask(
40 FROM_HERE, base::BindOnce([](int* counter) { *counter += 32; },
41 Unretained(&counter)));
42 mock_time_task_runner->PostDelayedTask(
43 FROM_HERE,
44 base::BindOnce([](int* counter) { *counter += 256; },
45 Unretained(&counter)),
46 Seconds(3));
47 mock_time_task_runner->PostDelayedTask(
48 FROM_HERE,
49 base::BindOnce([](int* counter) { *counter += 64; },
50 Unretained(&counter)),
51 Seconds(1));
52 mock_time_task_runner->PostDelayedTask(
53 FROM_HERE,
54 base::BindOnce([](int* counter) { *counter += 1024; },
55 Unretained(&counter)),
56 Minutes(20));
57 mock_time_task_runner->PostDelayedTask(
58 FROM_HERE,
59 base::BindOnce([](int* counter) { *counter += 4096; },
60 Unretained(&counter)),
61 Days(20));
62
63 int expected_value = 0;
64 EXPECT_EQ(expected_value, counter);
65 mock_time_task_runner->RunUntilIdle();
66 expected_value += 1;
67 expected_value += 32;
68 EXPECT_EQ(expected_value, counter);
69
70 mock_time_task_runner->RunUntilIdle();
71 EXPECT_EQ(expected_value, counter);
72
73 mock_time_task_runner->FastForwardBy(Seconds(1));
74 expected_value += 64;
75 EXPECT_EQ(expected_value, counter);
76
77 mock_time_task_runner->FastForwardBy(Seconds(5));
78 expected_value += 256;
79 EXPECT_EQ(expected_value, counter);
80
81 mock_time_task_runner->FastForwardUntilNoTasksRemain();
82 expected_value += 1024;
83 expected_value += 4096;
84 EXPECT_EQ(expected_value, counter);
85 }
86 }
87
88 // A default TestMockTimeTaskRunner shouldn't result in a thread association.
TEST(TestMockTimeTaskRunnerTest,DefaultUnbound)89 TEST(TestMockTimeTaskRunnerTest, DefaultUnbound) {
90 auto unbound_mock_time_task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
91 EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
92 EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
93 EXPECT_DEATH_IF_SUPPORTED({ RunLoop().RunUntilIdle(); }, "");
94 }
95
TEST(TestMockTimeTaskRunnerTest,RunLoopDriveableWhenBound)96 TEST(TestMockTimeTaskRunnerTest, RunLoopDriveableWhenBound) {
97 auto bound_mock_time_task_runner = MakeRefCounted<TestMockTimeTaskRunner>(
98 TestMockTimeTaskRunner::Type::kBoundToThread);
99
100 int counter = 0;
101 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
102 FROM_HERE, base::BindOnce([](int* counter) { *counter += 1; },
103 Unretained(&counter)));
104 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
105 FROM_HERE, base::BindOnce([](int* counter) { *counter += 32; },
106 Unretained(&counter)));
107 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
108 FROM_HERE,
109 base::BindOnce([](int* counter) { *counter += 256; },
110 Unretained(&counter)),
111 Seconds(3));
112 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
113 FROM_HERE,
114 base::BindOnce([](int* counter) { *counter += 64; },
115 Unretained(&counter)),
116 Seconds(1));
117 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
118 FROM_HERE,
119 base::BindOnce([](int* counter) { *counter += 1024; },
120 Unretained(&counter)),
121 Minutes(20));
122 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
123 FROM_HERE,
124 base::BindOnce([](int* counter) { *counter += 4096; },
125 Unretained(&counter)),
126 Days(20));
127
128 int expected_value = 0;
129 EXPECT_EQ(expected_value, counter);
130 RunLoop().RunUntilIdle();
131 expected_value += 1;
132 expected_value += 32;
133 EXPECT_EQ(expected_value, counter);
134
135 RunLoop().RunUntilIdle();
136 EXPECT_EQ(expected_value, counter);
137
138 {
139 RunLoop run_loop;
140 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
141 FROM_HERE, run_loop.QuitClosure(), Seconds(1));
142 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
143 FROM_HERE,
144 base::BindOnce([](int* counter) { *counter += 8192; },
145 Unretained(&counter)),
146 Seconds(1));
147
148 // The QuitClosure() should be ordered between the 64 and the 8192
149 // increments and should preempt the latter.
150 run_loop.Run();
151 expected_value += 64;
152 EXPECT_EQ(expected_value, counter);
153
154 // Running until idle should process the 8192 increment whose delay has
155 // expired in the previous Run().
156 RunLoop().RunUntilIdle();
157 expected_value += 8192;
158 EXPECT_EQ(expected_value, counter);
159 }
160
161 {
162 RunLoop run_loop;
163 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
164 FROM_HERE, run_loop.QuitWhenIdleClosure(), Seconds(5));
165 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
166 FROM_HERE,
167 base::BindOnce([](int* counter) { *counter += 16384; },
168 Unretained(&counter)),
169 Seconds(5));
170
171 // The QuitWhenIdleClosure() shouldn't preempt equally delayed tasks and as
172 // such the 16384 increment should be processed before quitting.
173 run_loop.Run();
174 expected_value += 256;
175 expected_value += 16384;
176 EXPECT_EQ(expected_value, counter);
177 }
178
179 // Process the remaining tasks (note: do not mimic this elsewhere,
180 // TestMockTimeTaskRunner::FastForwardUntilNoTasksRemain() is a better API to
181 // do this, this is just done here for the purpose of extensively testing the
182 // RunLoop approach).
183 RunLoop run_loop;
184 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
185 FROM_HERE, run_loop.QuitWhenIdleClosure(), Days(50));
186
187 run_loop.Run();
188 expected_value += 1024;
189 expected_value += 4096;
190 EXPECT_EQ(expected_value, counter);
191 }
192
TEST(TestMockTimeTaskRunnerTest,AvoidCaptureWhenBound)193 TEST(TestMockTimeTaskRunnerTest, AvoidCaptureWhenBound) {
194 // Make sure that capturing the active task runner --- which sometimes happens
195 // unknowingly due to ThreadsafeObserverList deep within some singleton ---
196 // does not keep the entire TestMockTimeTaskRunner alive, as in bound mode
197 // that's a RunLoop::Delegate, and leaking that renders any further tests that
198 // need RunLoop support unrunnable.
199 //
200 // (This used to happen when code run from ProcessAllTasksNoLaterThan grabbed
201 // the runner.).
202 scoped_refptr<SingleThreadTaskRunner> captured;
203 {
204 auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>(
205 TestMockTimeTaskRunner::Type::kBoundToThread);
206
207 task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&] {
208 captured =
209 SingleThreadTaskRunner::GetCurrentDefault();
210 }));
211 task_runner->RunUntilIdle();
212 }
213
214 {
215 // This should not complain about RunLoop::Delegate already existing.
216 auto task_runner2 = MakeRefCounted<TestMockTimeTaskRunner>(
217 TestMockTimeTaskRunner::Type::kBoundToThread);
218 }
219 }
220
221 // Regression test that receiving the quit-when-idle signal when already empty
222 // works as intended (i.e. that |TestMockTimeTaskRunner::tasks_lock_cv| is
223 // properly signaled).
TEST(TestMockTimeTaskRunnerTest,RunLoopQuitFromIdle)224 TEST(TestMockTimeTaskRunnerTest, RunLoopQuitFromIdle) {
225 auto bound_mock_time_task_runner = MakeRefCounted<TestMockTimeTaskRunner>(
226 TestMockTimeTaskRunner::Type::kBoundToThread);
227
228 Thread quitting_thread("quitting thread");
229 quitting_thread.Start();
230
231 RunLoop run_loop;
232 quitting_thread.task_runner()->PostDelayedTask(
233 FROM_HERE, run_loop.QuitWhenIdleClosure(), TestTimeouts::tiny_timeout());
234 run_loop.Run();
235 }
236
TEST(TestMockTimeTaskRunnerTest,TakePendingTasks)237 TEST(TestMockTimeTaskRunnerTest, TakePendingTasks) {
238 auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
239 task_runner->PostTask(FROM_HERE, DoNothing());
240 EXPECT_TRUE(task_runner->HasPendingTask());
241 EXPECT_EQ(1u, task_runner->TakePendingTasks().size());
242 EXPECT_FALSE(task_runner->HasPendingTask());
243 }
244
TEST(TestMockTimeTaskRunnerTest,CancelPendingTask)245 TEST(TestMockTimeTaskRunnerTest, CancelPendingTask) {
246 auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
247 CancelableOnceClosure task1(DoNothing());
248 task_runner->PostDelayedTask(FROM_HERE, task1.callback(), Seconds(1));
249 EXPECT_TRUE(task_runner->HasPendingTask());
250 EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
251 EXPECT_EQ(Seconds(1), task_runner->NextPendingTaskDelay());
252 task1.Cancel();
253 EXPECT_FALSE(task_runner->HasPendingTask());
254
255 CancelableOnceClosure task2(DoNothing());
256 task_runner->PostDelayedTask(FROM_HERE, task2.callback(), Seconds(1));
257 task2.Cancel();
258 EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
259
260 CancelableOnceClosure task3(DoNothing());
261 task_runner->PostDelayedTask(FROM_HERE, task3.callback(), Seconds(1));
262 task3.Cancel();
263 EXPECT_EQ(TimeDelta::Max(), task_runner->NextPendingTaskDelay());
264
265 CancelableOnceClosure task4(DoNothing());
266 task_runner->PostDelayedTask(FROM_HERE, task4.callback(), Seconds(1));
267 task4.Cancel();
268 EXPECT_TRUE(task_runner->TakePendingTasks().empty());
269 }
270
TEST(TestMockTimeTaskRunnerTest,NoFastForwardToCancelledTask)271 TEST(TestMockTimeTaskRunnerTest, NoFastForwardToCancelledTask) {
272 auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
273 TimeTicks start_time = task_runner->NowTicks();
274 CancelableOnceClosure task(DoNothing());
275 task_runner->PostDelayedTask(FROM_HERE, task.callback(), Seconds(1));
276 EXPECT_EQ(Seconds(1), task_runner->NextPendingTaskDelay());
277 task.Cancel();
278 task_runner->FastForwardUntilNoTasksRemain();
279 EXPECT_EQ(start_time, task_runner->NowTicks());
280 }
281
TEST(TestMockTimeTaskRunnerTest,AdvanceMockTickClockDoesNotRunTasks)282 TEST(TestMockTimeTaskRunnerTest, AdvanceMockTickClockDoesNotRunTasks) {
283 auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
284 TimeTicks start_time = task_runner->NowTicks();
285 task_runner->PostTask(FROM_HERE, BindOnce([] { ADD_FAILURE(); }));
286 task_runner->PostDelayedTask(FROM_HERE, BindOnce([] { ADD_FAILURE(); }),
287 Seconds(1));
288
289 task_runner->AdvanceMockTickClock(Seconds(3));
290 EXPECT_EQ(start_time + Seconds(3), task_runner->NowTicks());
291 EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
292 }
293
TEST(TestMockTimeTaskRunnerTest,ProcessNextNTasks)294 TEST(TestMockTimeTaskRunnerTest, ProcessNextNTasks) {
295 auto mock_time_task_runner = MakeRefCounted<TestMockTimeTaskRunner>(
296 TestMockTimeTaskRunner::Type::kStandalone);
297 int counter = 0;
298
299 mock_time_task_runner->PostTask(
300 FROM_HERE, base::BindOnce([](int* counter) { *counter += 1; },
301 Unretained(&counter)));
302 mock_time_task_runner->PostTask(
303 FROM_HERE, base::BindOnce([](int* counter) { *counter += 32; },
304 Unretained(&counter)));
305
306 CancelableOnceClosure task1(base::BindOnce(
307 [](int* counter) { *counter += 16; }, Unretained(&counter)));
308 mock_time_task_runner->PostTask(FROM_HERE, task1.callback());
309
310 mock_time_task_runner->PostDelayedTask(
311 FROM_HERE,
312 base::BindOnce([](int* counter) { *counter += 256; },
313 Unretained(&counter)),
314 Seconds(3));
315 mock_time_task_runner->PostDelayedTask(
316 FROM_HERE,
317 base::BindOnce([](int* counter) { *counter += 64; },
318 Unretained(&counter)),
319 Seconds(1));
320 mock_time_task_runner->PostDelayedTask(
321 FROM_HERE,
322 base::BindOnce([](int* counter) { *counter += 1024; },
323 Unretained(&counter)),
324 Minutes(20));
325 mock_time_task_runner->PostDelayedTask(
326 FROM_HERE,
327 base::BindOnce([](int* counter) { *counter += 4096; },
328 Unretained(&counter)),
329 Days(20));
330 task1.Cancel();
331
332 int expected_value = 0;
333 EXPECT_EQ(expected_value, counter);
334 mock_time_task_runner->ProcessNextNTasks(0);
335 EXPECT_EQ(expected_value, counter);
336
337 mock_time_task_runner->ProcessNextNTasks(2);
338 expected_value += 1;
339 expected_value += 32;
340 EXPECT_EQ(expected_value, counter);
341
342 // The next task was canceled, so |counter| shouldn't change.
343 mock_time_task_runner->ProcessNextNTasks(1);
344 EXPECT_EQ(expected_value, counter);
345
346 mock_time_task_runner->ProcessNextNTasks(1);
347 expected_value += 64;
348 EXPECT_EQ(expected_value, counter);
349
350 mock_time_task_runner->ProcessNextNTasks(-1);
351 expected_value += 256;
352 expected_value += 1024;
353 expected_value += 4096;
354 EXPECT_EQ(expected_value, counter);
355 }
356 } // namespace base
357