• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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