OLD | NEW |
---|---|
(Empty) | |
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 "content/renderer/scheduler/task_queue_selector.h" | |
9 #include "testing/gtest/include/gtest/gtest.h" | |
10 | |
11 namespace content { | |
12 namespace { | |
13 | |
14 class SelectorForTest : public TaskQueueSelector { | |
15 public: | |
16 SelectorForTest() {} | |
17 | |
18 virtual void RegisterWorkQueues( | |
19 const std::vector<const base::TaskQueue*>& work_queues) override { | |
20 work_queues_ = work_queues; | |
21 } | |
22 | |
23 virtual bool SelectWorkQueueToService(size_t* out_queue_index) override { | |
24 if (queues_to_service_.empty()) | |
25 return false; | |
26 *out_queue_index = queues_to_service_.front(); | |
27 queues_to_service_.pop_front(); | |
28 return true; | |
29 } | |
30 | |
31 void AppendQueueToService(size_t queue_index) { | |
32 queues_to_service_.push_back(queue_index); | |
33 } | |
34 | |
35 const std::vector<const base::TaskQueue*>& work_queues() { | |
36 return work_queues_; | |
37 } | |
38 | |
39 private: | |
40 std::deque<size_t> queues_to_service_; | |
41 std::vector<const base::TaskQueue*> work_queues_; | |
42 }; | |
jochen (gone - plz use gerrit)
2014/10/20 13:35:31
nit. disallow copy & assign
Sami
2014/10/20 15:29:57
Done.
| |
43 | |
44 class TaskQueueManagerTest : public testing::Test { | |
45 public: | |
jochen (gone - plz use gerrit)
2014/10/20 13:35:31
nit. not needed
Sami
2014/10/20 15:29:57
Done.
| |
46 protected: | |
47 void Initialize(size_t num_queues) { | |
48 test_task_runner_ = make_scoped_refptr(new base::TestSimpleTaskRunner()); | |
49 selector_ = make_scoped_ptr(new SelectorForTest); | |
50 manager_ = make_scoped_ptr( | |
51 new TaskQueueManager(num_queues, test_task_runner_, selector_.get())); | |
52 } | |
53 | |
54 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_; | |
55 scoped_ptr<SelectorForTest> selector_; | |
56 scoped_ptr<TaskQueueManager> manager_; | |
57 }; | |
58 | |
59 void TestTask(int value, std::vector<int>* out_result) { | |
60 out_result->push_back(value); | |
61 } | |
62 | |
63 TEST_F(TaskQueueManagerTest, SingleQueuePosting) { | |
64 Initialize(1u); | |
65 EXPECT_EQ(1u, selector_->work_queues().size()); | |
66 | |
67 std::vector<int> run_order; | |
68 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
69 manager_->TaskRunnerForQueue(0); | |
70 | |
71 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
72 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
73 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
74 | |
75 selector_->AppendQueueToService(0); | |
76 selector_->AppendQueueToService(0); | |
77 selector_->AppendQueueToService(0); | |
78 | |
79 test_task_runner_->RunUntilIdle(); | |
80 EXPECT_EQ(1, run_order[0]); | |
81 EXPECT_EQ(2, run_order[1]); | |
82 EXPECT_EQ(3, run_order[2]); | |
83 } | |
84 | |
85 TEST_F(TaskQueueManagerTest, MultiQueuePosting) { | |
86 Initialize(3u); | |
87 EXPECT_EQ(3u, selector_->work_queues().size()); | |
88 | |
89 std::vector<int> run_order; | |
90 scoped_refptr<base::SingleThreadTaskRunner> runners[3] = { | |
91 manager_->TaskRunnerForQueue(0), | |
92 manager_->TaskRunnerForQueue(1), | |
93 manager_->TaskRunnerForQueue(2)}; | |
94 | |
95 selector_->AppendQueueToService(0); | |
96 selector_->AppendQueueToService(1); | |
97 selector_->AppendQueueToService(2); | |
98 selector_->AppendQueueToService(0); | |
99 selector_->AppendQueueToService(1); | |
100 selector_->AppendQueueToService(2); | |
101 | |
102 runners[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
103 runners[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
104 runners[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
105 runners[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order)); | |
106 runners[2]->PostTask(FROM_HERE, base::Bind(&TestTask, 5, &run_order)); | |
107 runners[2]->PostTask(FROM_HERE, base::Bind(&TestTask, 6, &run_order)); | |
108 | |
109 test_task_runner_->RunUntilIdle(); | |
110 EXPECT_EQ(1, run_order[0]); | |
111 EXPECT_EQ(3, run_order[1]); | |
112 EXPECT_EQ(5, run_order[2]); | |
113 EXPECT_EQ(2, run_order[3]); | |
114 EXPECT_EQ(4, run_order[4]); | |
115 EXPECT_EQ(6, run_order[5]); | |
116 } | |
117 | |
118 TEST_F(TaskQueueManagerTest, NonNestableTaskPosting) { | |
119 Initialize(1u); | |
120 EXPECT_EQ(1u, selector_->work_queues().size()); | |
121 | |
122 std::vector<int> run_order; | |
123 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
124 manager_->TaskRunnerForQueue(0); | |
125 | |
126 runner->PostNonNestableTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
127 | |
128 // Non-nestable tasks never make it to the selector. | |
129 test_task_runner_->RunUntilIdle(); | |
130 EXPECT_EQ(1, run_order[0]); | |
131 } | |
132 | |
133 TEST_F(TaskQueueManagerTest, QueuePolling) { | |
134 Initialize(1u); | |
135 | |
136 std::vector<int> run_order; | |
137 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
138 manager_->TaskRunnerForQueue(0); | |
139 | |
140 EXPECT_FALSE(manager_->PollQueue(0)); | |
141 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
142 EXPECT_TRUE(manager_->PollQueue(0)); | |
143 | |
144 selector_->AppendQueueToService(0); | |
145 test_task_runner_->RunUntilIdle(); | |
146 EXPECT_FALSE(manager_->PollQueue(0)); | |
147 } | |
148 | |
149 TEST_F(TaskQueueManagerTest, DelayedTaskPosting) { | |
150 Initialize(1u); | |
151 | |
152 std::vector<int> run_order; | |
153 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
154 manager_->TaskRunnerForQueue(0); | |
155 | |
156 selector_->AppendQueueToService(0); | |
157 | |
158 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); | |
159 runner->PostDelayedTask( | |
160 FROM_HERE, base::Bind(&TestTask, 1, &run_order), delay); | |
161 EXPECT_EQ(delay, test_task_runner_->NextPendingTaskDelay()); | |
162 EXPECT_FALSE(manager_->PollQueue(0)); | |
163 EXPECT_TRUE(run_order.empty()); | |
164 | |
165 // The task is inserted to the incoming queue only after the delay. | |
166 test_task_runner_->RunPendingTasks(); | |
167 EXPECT_TRUE(manager_->PollQueue(0)); | |
168 EXPECT_TRUE(run_order.empty()); | |
169 | |
170 // After the delay the task runs normally. | |
171 selector_->AppendQueueToService(0); | |
172 test_task_runner_->RunUntilIdle(); | |
173 EXPECT_EQ(1, run_order[0]); | |
174 } | |
175 | |
176 TEST_F(TaskQueueManagerTest, ManualPumping) { | |
177 Initialize(1u); | |
178 manager_->SetAutoPump(0, false); | |
179 | |
180 std::vector<int> run_order; | |
181 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
182 manager_->TaskRunnerForQueue(0); | |
183 | |
184 // Posting a task when pumping is disabled doesn't result in work getting | |
185 // posted. | |
186 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
187 EXPECT_FALSE(test_task_runner_->HasPendingTask()); | |
188 | |
189 // However polling still works. | |
190 EXPECT_TRUE(manager_->PollQueue(0)); | |
191 | |
192 // After pumping the task runs normally. | |
193 manager_->PumpQueue(0); | |
194 EXPECT_TRUE(test_task_runner_->HasPendingTask()); | |
195 selector_->AppendQueueToService(0); | |
196 test_task_runner_->RunUntilIdle(); | |
197 EXPECT_EQ(1, run_order[0]); | |
198 } | |
199 | |
200 TEST_F(TaskQueueManagerTest, ManualPumpingToggle) { | |
201 Initialize(1u); | |
202 manager_->SetAutoPump(0, false); | |
203 | |
204 std::vector<int> run_order; | |
205 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
206 manager_->TaskRunnerForQueue(0); | |
207 | |
208 // Posting a task when pumping is disabled doesn't result in work getting | |
209 // posted. | |
210 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
211 EXPECT_FALSE(test_task_runner_->HasPendingTask()); | |
212 | |
213 // When pumping is enabled the task runs normally. | |
214 manager_->SetAutoPump(0, true); | |
215 EXPECT_TRUE(test_task_runner_->HasPendingTask()); | |
216 selector_->AppendQueueToService(0); | |
217 test_task_runner_->RunUntilIdle(); | |
218 EXPECT_EQ(1, run_order[0]); | |
219 } | |
220 | |
221 TEST_F(TaskQueueManagerTest, DenyRunning) { | |
222 Initialize(1u); | |
223 | |
224 std::vector<int> run_order; | |
225 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
226 manager_->TaskRunnerForQueue(0); | |
227 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
228 | |
229 // Since we haven't appended a work queue to be selected, the task doesn't | |
230 // run. | |
231 test_task_runner_->RunUntilIdle(); | |
232 EXPECT_TRUE(run_order.empty()); | |
233 | |
234 // Pumping the queue again with a selected work queue runs the task. | |
235 manager_->PumpQueue(0); | |
236 selector_->AppendQueueToService(0); | |
237 test_task_runner_->RunUntilIdle(); | |
238 EXPECT_EQ(1, run_order[0]); | |
239 } | |
240 | |
241 TEST_F(TaskQueueManagerTest, ManualPumpingWithDelayedTask) { | |
242 Initialize(1u); | |
243 manager_->SetAutoPump(0, false); | |
244 | |
245 std::vector<int> run_order; | |
246 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
247 manager_->TaskRunnerForQueue(0); | |
248 | |
249 // Posting a delayed task when pumping will apply the delay, but won't cause | |
250 // work to executed afterwards. | |
251 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); | |
252 runner->PostDelayedTask( | |
253 FROM_HERE, base::Bind(&TestTask, 1, &run_order), delay); | |
254 test_task_runner_->RunUntilIdle(); | |
255 EXPECT_TRUE(run_order.empty()); | |
256 | |
257 // After pumping the task runs normally. | |
258 manager_->PumpQueue(0); | |
259 EXPECT_TRUE(test_task_runner_->HasPendingTask()); | |
260 selector_->AppendQueueToService(0); | |
261 test_task_runner_->RunUntilIdle(); | |
262 EXPECT_EQ(1, run_order[0]); | |
263 } | |
264 | |
265 TEST_F(TaskQueueManagerTest, ManualPumpingWithNonEmptyWorkQueue) { | |
266 Initialize(1u); | |
267 manager_->SetAutoPump(0, false); | |
268 | |
269 std::vector<int> run_order; | |
270 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
271 manager_->TaskRunnerForQueue(0); | |
272 | |
273 // Posting two tasks and pumping twice should result in two tasks in the work | |
274 // queue. | |
275 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
276 manager_->PumpQueue(0); | |
277 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
278 manager_->PumpQueue(0); | |
279 | |
280 EXPECT_EQ(2u, selector_->work_queues()[0]->size()); | |
281 } | |
282 | |
283 void ReentrantTestTask(scoped_refptr<base::SingleThreadTaskRunner> runner, | |
284 int countdown, | |
285 std::vector<int>* out_result) { | |
286 out_result->push_back(countdown); | |
287 if (--countdown) { | |
288 runner->PostTask(FROM_HERE, | |
289 Bind(&ReentrantTestTask, runner, countdown, out_result)); | |
290 } | |
291 } | |
292 | |
293 TEST_F(TaskQueueManagerTest, ReentrantPosting) { | |
294 Initialize(1u); | |
295 EXPECT_EQ(1u, selector_->work_queues().size()); | |
296 | |
297 std::vector<int> run_order; | |
298 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
299 manager_->TaskRunnerForQueue(0); | |
300 | |
301 runner->PostTask(FROM_HERE, Bind(&ReentrantTestTask, runner, 3, &run_order)); | |
302 | |
303 selector_->AppendQueueToService(0); | |
304 selector_->AppendQueueToService(0); | |
305 selector_->AppendQueueToService(0); | |
306 | |
307 test_task_runner_->RunUntilIdle(); | |
308 EXPECT_EQ(3, run_order[0]); | |
309 EXPECT_EQ(2, run_order[1]); | |
310 EXPECT_EQ(1, run_order[2]); | |
311 } | |
312 | |
313 TEST_F(TaskQueueManagerTest, NoTasksAfterShutdown) { | |
314 Initialize(1u); | |
315 | |
316 std::vector<int> run_order; | |
317 scoped_refptr<base::SingleThreadTaskRunner> runner = | |
318 manager_->TaskRunnerForQueue(0); | |
319 | |
320 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
321 manager_.reset(); | |
322 selector_.reset(); | |
323 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
324 | |
325 test_task_runner_->RunUntilIdle(); | |
326 EXPECT_TRUE(run_order.empty()); | |
327 } | |
328 | |
329 } // namespace | |
330 } // namespace content | |
OLD | NEW |