cc: Make picture pile base thread safe.
[chromium-blink-merge.git] / content / renderer / scheduler / task_queue_manager_unittest.cc
blob43238250180c20cc6b776a94ab0f7f2e548f9d80
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"
12 namespace content {
13 namespace {
15 class SelectorForTest : public TaskQueueSelector {
16 public:
17 SelectorForTest() {}
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())
26 return false;
27 *out_queue_index = queues_to_service_.front();
28 queues_to_service_.pop_front();
29 return true;
32 void AppendQueueToService(size_t queue_index) {
33 queues_to_service_.push_back(queue_index);
36 const std::vector<const base::TaskQueue*>& work_queues() {
37 return work_queues_;
40 private:
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 {
48 protected:
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) {
66 Initialize(1u);
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) {
88 Initialize(3u);
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) {
121 Initialize(1u);
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) {
136 Initialize(1u);
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) {
152 Initialize(1u);
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) {
179 Initialize(1u);
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
187 // posted.
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) {
203 Initialize(1u);
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
211 // posted.
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) {
224 Initialize(1u);
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
232 // run.
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) {
244 Initialize(1u);
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) {
268 Initialize(1u);
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
276 // queue.
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,
286 int countdown,
287 std::vector<int>* out_result) {
288 out_result->push_back(countdown);
289 if (--countdown) {
290 runner->PostTask(FROM_HERE,
291 Bind(&ReentrantTestTask, runner, countdown, out_result));
295 TEST_F(TaskQueueManagerTest, ReentrantPosting) {
296 Initialize(1u);
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) {
316 Initialize(1u);
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));
323 manager_.reset();
324 selector_.reset();
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");
347 thread.Start();
348 thread.message_loop()->PostTask(
349 FROM_HERE, base::Bind(&PostTaskToRunner, runner, &run_order));
350 thread.Stop();
352 selector_->AppendQueueToService(0);
353 message_loop.RunUntilIdle();
354 EXPECT_EQ(1, run_order[0]);
357 } // namespace
358 } // namespace content