Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: content/renderer/scheduler/task_queue_manager_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698