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

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

Powered by Google App Engine
This is Rietveld 408576698