1 // Copyright 2014 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.
5 #include "content/renderer/scheduler/task_queue_manager.h"
7 #include "base/test/test_simple_task_runner.h"
8 #include "base/threading/thread.h"
9 #include "content/renderer/scheduler/task_queue_selector.h"
10 #include "testing/gtest/include/gtest/gtest.h"
15 class SelectorForTest
: public TaskQueueSelector
{
19 void RegisterWorkQueues(
20 const std::vector
<const base::TaskQueue
*>& work_queues
) override
{
21 work_queues_
= work_queues
;
24 bool SelectWorkQueueToService(size_t* out_queue_index
) override
{
25 if (queues_to_service_
.empty())
27 *out_queue_index
= queues_to_service_
.front();
28 queues_to_service_
.pop_front();
32 void AppendQueueToService(size_t queue_index
) {
33 queues_to_service_
.push_back(queue_index
);
36 const std::vector
<const base::TaskQueue
*>& work_queues() {
41 std::deque
<size_t> queues_to_service_
;
42 std::vector
<const base::TaskQueue
*> work_queues_
;
44 DISALLOW_COPY_AND_ASSIGN(SelectorForTest
);
47 class TaskQueueManagerTest
: public testing::Test
{
49 void Initialize(size_t num_queues
) {
50 test_task_runner_
= make_scoped_refptr(new base::TestSimpleTaskRunner());
51 selector_
= make_scoped_ptr(new SelectorForTest
);
52 manager_
= make_scoped_ptr(
53 new TaskQueueManager(num_queues
, test_task_runner_
, selector_
.get()));
56 scoped_refptr
<base::TestSimpleTaskRunner
> test_task_runner_
;
57 scoped_ptr
<SelectorForTest
> selector_
;
58 scoped_ptr
<TaskQueueManager
> manager_
;
61 void TestTask(int value
, std::vector
<int>* out_result
) {
62 out_result
->push_back(value
);
65 TEST_F(TaskQueueManagerTest
, SingleQueuePosting
) {
67 EXPECT_EQ(1u, selector_
->work_queues().size());
69 std::vector
<int> run_order
;
70 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
71 manager_
->TaskRunnerForQueue(0);
73 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
74 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 2, &run_order
));
75 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 3, &run_order
));
77 selector_
->AppendQueueToService(0);
78 selector_
->AppendQueueToService(0);
79 selector_
->AppendQueueToService(0);
81 test_task_runner_
->RunUntilIdle();
82 EXPECT_EQ(1, run_order
[0]);
83 EXPECT_EQ(2, run_order
[1]);
84 EXPECT_EQ(3, run_order
[2]);
87 TEST_F(TaskQueueManagerTest
, MultiQueuePosting
) {
89 EXPECT_EQ(3u, selector_
->work_queues().size());
91 std::vector
<int> run_order
;
92 scoped_refptr
<base::SingleThreadTaskRunner
> runners
[3] = {
93 manager_
->TaskRunnerForQueue(0),
94 manager_
->TaskRunnerForQueue(1),
95 manager_
->TaskRunnerForQueue(2)};
97 selector_
->AppendQueueToService(0);
98 selector_
->AppendQueueToService(1);
99 selector_
->AppendQueueToService(2);
100 selector_
->AppendQueueToService(0);
101 selector_
->AppendQueueToService(1);
102 selector_
->AppendQueueToService(2);
104 runners
[0]->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
105 runners
[0]->PostTask(FROM_HERE
, base::Bind(&TestTask
, 2, &run_order
));
106 runners
[1]->PostTask(FROM_HERE
, base::Bind(&TestTask
, 3, &run_order
));
107 runners
[1]->PostTask(FROM_HERE
, base::Bind(&TestTask
, 4, &run_order
));
108 runners
[2]->PostTask(FROM_HERE
, base::Bind(&TestTask
, 5, &run_order
));
109 runners
[2]->PostTask(FROM_HERE
, base::Bind(&TestTask
, 6, &run_order
));
111 test_task_runner_
->RunUntilIdle();
112 EXPECT_EQ(1, run_order
[0]);
113 EXPECT_EQ(3, run_order
[1]);
114 EXPECT_EQ(5, run_order
[2]);
115 EXPECT_EQ(2, run_order
[3]);
116 EXPECT_EQ(4, run_order
[4]);
117 EXPECT_EQ(6, run_order
[5]);
120 TEST_F(TaskQueueManagerTest
, NonNestableTaskPosting
) {
122 EXPECT_EQ(1u, selector_
->work_queues().size());
124 std::vector
<int> run_order
;
125 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
126 manager_
->TaskRunnerForQueue(0);
128 runner
->PostNonNestableTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
130 // Non-nestable tasks never make it to the selector.
131 test_task_runner_
->RunUntilIdle();
132 EXPECT_EQ(1, run_order
[0]);
135 TEST_F(TaskQueueManagerTest
, QueuePolling
) {
138 std::vector
<int> run_order
;
139 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
140 manager_
->TaskRunnerForQueue(0);
142 EXPECT_TRUE(manager_
->IsQueueEmpty(0));
143 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
144 EXPECT_FALSE(manager_
->IsQueueEmpty(0));
146 selector_
->AppendQueueToService(0);
147 test_task_runner_
->RunUntilIdle();
148 EXPECT_TRUE(manager_
->IsQueueEmpty(0));
151 TEST_F(TaskQueueManagerTest
, DelayedTaskPosting
) {
154 std::vector
<int> run_order
;
155 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
156 manager_
->TaskRunnerForQueue(0);
158 selector_
->AppendQueueToService(0);
160 base::TimeDelta
delay(base::TimeDelta::FromMilliseconds(10));
161 runner
->PostDelayedTask(
162 FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
), delay
);
163 EXPECT_EQ(delay
, test_task_runner_
->NextPendingTaskDelay());
164 EXPECT_TRUE(manager_
->IsQueueEmpty(0));
165 EXPECT_TRUE(run_order
.empty());
167 // The task is inserted to the incoming queue only after the delay.
168 test_task_runner_
->RunPendingTasks();
169 EXPECT_FALSE(manager_
->IsQueueEmpty(0));
170 EXPECT_TRUE(run_order
.empty());
172 // After the delay the task runs normally.
173 selector_
->AppendQueueToService(0);
174 test_task_runner_
->RunUntilIdle();
175 EXPECT_EQ(1, run_order
[0]);
178 TEST_F(TaskQueueManagerTest
, ManualPumping
) {
180 manager_
->SetAutoPump(0, false);
182 std::vector
<int> run_order
;
183 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
184 manager_
->TaskRunnerForQueue(0);
186 // Posting a task when pumping is disabled doesn't result in work getting
188 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
189 EXPECT_FALSE(test_task_runner_
->HasPendingTask());
191 // However polling still works.
192 EXPECT_FALSE(manager_
->IsQueueEmpty(0));
194 // After pumping the task runs normally.
195 manager_
->PumpQueue(0);
196 EXPECT_TRUE(test_task_runner_
->HasPendingTask());
197 selector_
->AppendQueueToService(0);
198 test_task_runner_
->RunUntilIdle();
199 EXPECT_EQ(1, run_order
[0]);
202 TEST_F(TaskQueueManagerTest
, ManualPumpingToggle
) {
204 manager_
->SetAutoPump(0, false);
206 std::vector
<int> run_order
;
207 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
208 manager_
->TaskRunnerForQueue(0);
210 // Posting a task when pumping is disabled doesn't result in work getting
212 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
213 EXPECT_FALSE(test_task_runner_
->HasPendingTask());
215 // When pumping is enabled the task runs normally.
216 manager_
->SetAutoPump(0, true);
217 EXPECT_TRUE(test_task_runner_
->HasPendingTask());
218 selector_
->AppendQueueToService(0);
219 test_task_runner_
->RunUntilIdle();
220 EXPECT_EQ(1, run_order
[0]);
223 TEST_F(TaskQueueManagerTest
, DenyRunning
) {
226 std::vector
<int> run_order
;
227 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
228 manager_
->TaskRunnerForQueue(0);
229 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
231 // Since we haven't appended a work queue to be selected, the task doesn't
233 test_task_runner_
->RunUntilIdle();
234 EXPECT_TRUE(run_order
.empty());
236 // Pumping the queue again with a selected work queue runs the task.
237 manager_
->PumpQueue(0);
238 selector_
->AppendQueueToService(0);
239 test_task_runner_
->RunUntilIdle();
240 EXPECT_EQ(1, run_order
[0]);
243 TEST_F(TaskQueueManagerTest
, ManualPumpingWithDelayedTask
) {
245 manager_
->SetAutoPump(0, false);
247 std::vector
<int> run_order
;
248 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
249 manager_
->TaskRunnerForQueue(0);
251 // Posting a delayed task when pumping will apply the delay, but won't cause
252 // work to executed afterwards.
253 base::TimeDelta
delay(base::TimeDelta::FromMilliseconds(10));
254 runner
->PostDelayedTask(
255 FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
), delay
);
256 test_task_runner_
->RunUntilIdle();
257 EXPECT_TRUE(run_order
.empty());
259 // After pumping the task runs normally.
260 manager_
->PumpQueue(0);
261 EXPECT_TRUE(test_task_runner_
->HasPendingTask());
262 selector_
->AppendQueueToService(0);
263 test_task_runner_
->RunUntilIdle();
264 EXPECT_EQ(1, run_order
[0]);
267 TEST_F(TaskQueueManagerTest
, ManualPumpingWithNonEmptyWorkQueue
) {
269 manager_
->SetAutoPump(0, false);
271 std::vector
<int> run_order
;
272 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
273 manager_
->TaskRunnerForQueue(0);
275 // Posting two tasks and pumping twice should result in two tasks in the work
277 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
278 manager_
->PumpQueue(0);
279 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 2, &run_order
));
280 manager_
->PumpQueue(0);
282 EXPECT_EQ(2u, selector_
->work_queues()[0]->size());
285 void ReentrantTestTask(scoped_refptr
<base::SingleThreadTaskRunner
> runner
,
287 std::vector
<int>* out_result
) {
288 out_result
->push_back(countdown
);
290 runner
->PostTask(FROM_HERE
,
291 Bind(&ReentrantTestTask
, runner
, countdown
, out_result
));
295 TEST_F(TaskQueueManagerTest
, ReentrantPosting
) {
297 EXPECT_EQ(1u, selector_
->work_queues().size());
299 std::vector
<int> run_order
;
300 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
301 manager_
->TaskRunnerForQueue(0);
303 runner
->PostTask(FROM_HERE
, Bind(&ReentrantTestTask
, runner
, 3, &run_order
));
305 selector_
->AppendQueueToService(0);
306 selector_
->AppendQueueToService(0);
307 selector_
->AppendQueueToService(0);
309 test_task_runner_
->RunUntilIdle();
310 EXPECT_EQ(3, run_order
[0]);
311 EXPECT_EQ(2, run_order
[1]);
312 EXPECT_EQ(1, run_order
[2]);
315 TEST_F(TaskQueueManagerTest
, NoTasksAfterShutdown
) {
318 std::vector
<int> run_order
;
319 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
320 manager_
->TaskRunnerForQueue(0);
322 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
325 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, &run_order
));
327 test_task_runner_
->RunUntilIdle();
328 EXPECT_TRUE(run_order
.empty());
331 void PostTaskToRunner(scoped_refptr
<base::SingleThreadTaskRunner
> runner
,
332 std::vector
<int>* run_order
) {
333 runner
->PostTask(FROM_HERE
, base::Bind(&TestTask
, 1, run_order
));
336 TEST_F(TaskQueueManagerTest
, PostFromThread
) {
337 base::MessageLoop message_loop
;
338 selector_
= make_scoped_ptr(new SelectorForTest
);
339 manager_
= make_scoped_ptr(
340 new TaskQueueManager(1u, message_loop
.task_runner(), selector_
.get()));
342 std::vector
<int> run_order
;
343 scoped_refptr
<base::SingleThreadTaskRunner
> runner
=
344 manager_
->TaskRunnerForQueue(0);
346 base::Thread
thread("TestThread");
348 thread
.message_loop()->PostTask(
349 FROM_HERE
, base::Bind(&PostTaskToRunner
, runner
, &run_order
));
352 selector_
->AppendQueueToService(0);
353 message_loop
.RunUntilIdle();
354 EXPECT_EQ(1, run_order
[0]);
358 } // namespace content