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