Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / content / renderer / scheduler / task_queue_manager_unittest.cc
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.
4
5 #include "content/renderer/scheduler/task_queue_manager.h"
6
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"
11
12 namespace content {
13 namespace {
14
15 class SelectorForTest : public TaskQueueSelector {
16  public:
17   SelectorForTest() {}
18
19   void RegisterWorkQueues(
20       const std::vector<const base::TaskQueue*>& work_queues) override {
21     work_queues_ = work_queues;
22   }
23
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;
30   }
31
32   void AppendQueueToService(size_t queue_index) {
33     queues_to_service_.push_back(queue_index);
34   }
35
36   const std::vector<const base::TaskQueue*>& work_queues() {
37     return work_queues_;
38   }
39
40  private:
41   std::deque<size_t> queues_to_service_;
42   std::vector<const base::TaskQueue*> work_queues_;
43
44   DISALLOW_COPY_AND_ASSIGN(SelectorForTest);
45 };
46
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()));
54   }
55
56   scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_;
57   scoped_ptr<SelectorForTest> selector_;
58   scoped_ptr<TaskQueueManager> manager_;
59 };
60
61 void TestTask(int value, std::vector<int>* out_result) {
62   out_result->push_back(value);
63 }
64
65 TEST_F(TaskQueueManagerTest, SingleQueuePosting) {
66   Initialize(1u);
67   EXPECT_EQ(1u, selector_->work_queues().size());
68
69   std::vector<int> run_order;
70   scoped_refptr<base::SingleThreadTaskRunner> runner =
71       manager_->TaskRunnerForQueue(0);
72
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));
76
77   selector_->AppendQueueToService(0);
78   selector_->AppendQueueToService(0);
79   selector_->AppendQueueToService(0);
80
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]);
85 }
86
87 TEST_F(TaskQueueManagerTest, MultiQueuePosting) {
88   Initialize(3u);
89   EXPECT_EQ(3u, selector_->work_queues().size());
90
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)};
96
97   selector_->AppendQueueToService(0);
98   selector_->AppendQueueToService(1);
99   selector_->AppendQueueToService(2);
100   selector_->AppendQueueToService(0);
101   selector_->AppendQueueToService(1);
102   selector_->AppendQueueToService(2);
103
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));
110
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]);
118 }
119
120 TEST_F(TaskQueueManagerTest, NonNestableTaskPosting) {
121   Initialize(1u);
122   EXPECT_EQ(1u, selector_->work_queues().size());
123
124   std::vector<int> run_order;
125   scoped_refptr<base::SingleThreadTaskRunner> runner =
126       manager_->TaskRunnerForQueue(0);
127
128   runner->PostNonNestableTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
129
130   // Non-nestable tasks never make it to the selector.
131   test_task_runner_->RunUntilIdle();
132   EXPECT_EQ(1, run_order[0]);
133 }
134
135 TEST_F(TaskQueueManagerTest, QueuePolling) {
136   Initialize(1u);
137
138   std::vector<int> run_order;
139   scoped_refptr<base::SingleThreadTaskRunner> runner =
140       manager_->TaskRunnerForQueue(0);
141
142   EXPECT_TRUE(manager_->IsQueueEmpty(0));
143   runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
144   EXPECT_FALSE(manager_->IsQueueEmpty(0));
145
146   selector_->AppendQueueToService(0);
147   test_task_runner_->RunUntilIdle();
148   EXPECT_TRUE(manager_->IsQueueEmpty(0));
149 }
150
151 TEST_F(TaskQueueManagerTest, DelayedTaskPosting) {
152   Initialize(1u);
153
154   std::vector<int> run_order;
155   scoped_refptr<base::SingleThreadTaskRunner> runner =
156       manager_->TaskRunnerForQueue(0);
157
158   selector_->AppendQueueToService(0);
159
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());
166
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());
171
172   // After the delay the task runs normally.
173   selector_->AppendQueueToService(0);
174   test_task_runner_->RunUntilIdle();
175   EXPECT_EQ(1, run_order[0]);
176 }
177
178 TEST_F(TaskQueueManagerTest, ManualPumping) {
179   Initialize(1u);
180   manager_->SetAutoPump(0, false);
181
182   std::vector<int> run_order;
183   scoped_refptr<base::SingleThreadTaskRunner> runner =
184       manager_->TaskRunnerForQueue(0);
185
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());
190
191   // However polling still works.
192   EXPECT_FALSE(manager_->IsQueueEmpty(0));
193
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]);
200 }
201
202 TEST_F(TaskQueueManagerTest, ManualPumpingToggle) {
203   Initialize(1u);
204   manager_->SetAutoPump(0, false);
205
206   std::vector<int> run_order;
207   scoped_refptr<base::SingleThreadTaskRunner> runner =
208       manager_->TaskRunnerForQueue(0);
209
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());
214
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]);
221 }
222
223 TEST_F(TaskQueueManagerTest, DenyRunning) {
224   Initialize(1u);
225
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));
230
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());
235
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]);
241 }
242
243 TEST_F(TaskQueueManagerTest, ManualPumpingWithDelayedTask) {
244   Initialize(1u);
245   manager_->SetAutoPump(0, false);
246
247   std::vector<int> run_order;
248   scoped_refptr<base::SingleThreadTaskRunner> runner =
249       manager_->TaskRunnerForQueue(0);
250
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());
258
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]);
265 }
266
267 TEST_F(TaskQueueManagerTest, ManualPumpingWithNonEmptyWorkQueue) {
268   Initialize(1u);
269   manager_->SetAutoPump(0, false);
270
271   std::vector<int> run_order;
272   scoped_refptr<base::SingleThreadTaskRunner> runner =
273       manager_->TaskRunnerForQueue(0);
274
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);
281
282   EXPECT_EQ(2u, selector_->work_queues()[0]->size());
283 }
284
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));
292   }
293 }
294
295 TEST_F(TaskQueueManagerTest, ReentrantPosting) {
296   Initialize(1u);
297   EXPECT_EQ(1u, selector_->work_queues().size());
298
299   std::vector<int> run_order;
300   scoped_refptr<base::SingleThreadTaskRunner> runner =
301       manager_->TaskRunnerForQueue(0);
302
303   runner->PostTask(FROM_HERE, Bind(&ReentrantTestTask, runner, 3, &run_order));
304
305   selector_->AppendQueueToService(0);
306   selector_->AppendQueueToService(0);
307   selector_->AppendQueueToService(0);
308
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]);
313 }
314
315 TEST_F(TaskQueueManagerTest, NoTasksAfterShutdown) {
316   Initialize(1u);
317
318   std::vector<int> run_order;
319   scoped_refptr<base::SingleThreadTaskRunner> runner =
320       manager_->TaskRunnerForQueue(0);
321
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));
326
327   test_task_runner_->RunUntilIdle();
328   EXPECT_TRUE(run_order.empty());
329 }
330
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));
334 }
335
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()));
341
342   std::vector<int> run_order;
343   scoped_refptr<base::SingleThreadTaskRunner> runner =
344       manager_->TaskRunnerForQueue(0);
345
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();
351
352   selector_->AppendQueueToService(0);
353   message_loop.RunUntilIdle();
354   EXPECT_EQ(1, run_order[0]);
355 }
356
357 }  // namespace
358 }  // namespace content