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