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 "components/scheduler/base/task_queue_manager.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include <utility> | |
10 | |
11 #include "base/location.h" | |
12 #include "base/memory/ptr_util.h" | |
13 #include "base/memory/ref_counted_memory.h" | |
14 #include "base/run_loop.h" | |
15 #include "base/single_thread_task_runner.h" | |
16 #include "base/test/simple_test_tick_clock.h" | |
17 #include "base/test/trace_event_analyzer.h" | |
18 #include "base/threading/thread.h" | |
19 #include "base/trace_event/blame_context.h" | |
20 #include "base/trace_event/trace_buffer.h" | |
21 #include "cc/test/ordered_simple_task_runner.h" | |
22 #include "components/scheduler/base/real_time_domain.h" | |
23 #include "components/scheduler/base/task_queue_impl.h" | |
24 #include "components/scheduler/base/task_queue_manager_delegate_for_test.h" | |
25 #include "components/scheduler/base/task_queue_selector.h" | |
26 #include "components/scheduler/base/test_count_uses_time_source.h" | |
27 #include "components/scheduler/base/test_task_time_tracker.h" | |
28 #include "components/scheduler/base/test_time_source.h" | |
29 #include "components/scheduler/base/virtual_time_domain.h" | |
30 #include "components/scheduler/base/work_queue.h" | |
31 #include "components/scheduler/base/work_queue_sets.h" | |
32 #include "testing/gmock/include/gmock/gmock.h" | |
33 | |
34 using testing::ElementsAre; | |
35 using testing::ElementsAreArray; | |
36 using testing::_; | |
37 using scheduler::internal::EnqueueOrder; | |
38 | |
39 namespace scheduler { | |
40 | |
41 class MessageLoopTaskRunner : public TaskQueueManagerDelegateForTest { | |
42 public: | |
43 static scoped_refptr<MessageLoopTaskRunner> Create( | |
44 std::unique_ptr<base::TickClock> tick_clock) { | |
45 return make_scoped_refptr(new MessageLoopTaskRunner(std::move(tick_clock))); | |
46 } | |
47 | |
48 // NestableTaskRunner implementation. | |
49 bool IsNested() const override { | |
50 return base::MessageLoop::current()->IsNested(); | |
51 } | |
52 | |
53 private: | |
54 explicit MessageLoopTaskRunner(std::unique_ptr<base::TickClock> tick_clock) | |
55 : TaskQueueManagerDelegateForTest( | |
56 base::MessageLoop::current()->task_runner(), | |
57 std::move(tick_clock)) {} | |
58 ~MessageLoopTaskRunner() override {} | |
59 }; | |
60 | |
61 class TaskQueueManagerTest : public testing::Test { | |
62 public: | |
63 TaskQueueManagerTest() {} | |
64 void DeleteTaskQueueManager() { manager_.reset(); } | |
65 | |
66 protected: | |
67 void InitializeWithClock(size_t num_queues, | |
68 std::unique_ptr<base::TickClock> test_time_source) { | |
69 test_task_runner_ = make_scoped_refptr( | |
70 new cc::OrderedSimpleTaskRunner(now_src_.get(), false)); | |
71 main_task_runner_ = TaskQueueManagerDelegateForTest::Create( | |
72 test_task_runner_.get(), | |
73 base::WrapUnique(new TestTimeSource(now_src_.get()))); | |
74 | |
75 manager_ = base::WrapUnique(new TaskQueueManager( | |
76 main_task_runner_, "test.scheduler", "test.scheduler", | |
77 "test.scheduler.debug")); | |
78 manager_->SetTaskTimeTracker(&test_task_time_tracker_); | |
79 | |
80 for (size_t i = 0; i < num_queues; i++) | |
81 runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); | |
82 } | |
83 | |
84 void Initialize(size_t num_queues) { | |
85 now_src_.reset(new base::SimpleTestTickClock()); | |
86 now_src_->Advance(base::TimeDelta::FromMicroseconds(1000)); | |
87 InitializeWithClock(num_queues, | |
88 base::WrapUnique(new TestTimeSource(now_src_.get()))); | |
89 } | |
90 | |
91 void InitializeWithRealMessageLoop(size_t num_queues) { | |
92 now_src_.reset(new base::SimpleTestTickClock()); | |
93 message_loop_.reset(new base::MessageLoop()); | |
94 // A null clock triggers some assertions. | |
95 now_src_->Advance(base::TimeDelta::FromMicroseconds(1000)); | |
96 manager_ = base::WrapUnique(new TaskQueueManager( | |
97 MessageLoopTaskRunner::Create( | |
98 base::WrapUnique(new TestTimeSource(now_src_.get()))), | |
99 "test.scheduler", "test.scheduler", "test.scheduler.debug")); | |
100 manager_->SetTaskTimeTracker(&test_task_time_tracker_); | |
101 | |
102 for (size_t i = 0; i < num_queues; i++) | |
103 runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); | |
104 } | |
105 | |
106 std::unique_ptr<base::MessageLoop> message_loop_; | |
107 std::unique_ptr<base::SimpleTestTickClock> now_src_; | |
108 scoped_refptr<TaskQueueManagerDelegateForTest> main_task_runner_; | |
109 scoped_refptr<cc::OrderedSimpleTaskRunner> test_task_runner_; | |
110 std::unique_ptr<TaskQueueManager> manager_; | |
111 std::vector<scoped_refptr<internal::TaskQueueImpl>> runners_; | |
112 TestTaskTimeTracker test_task_time_tracker_; | |
113 }; | |
114 | |
115 void PostFromNestedRunloop(base::MessageLoop* message_loop, | |
116 base::SingleThreadTaskRunner* runner, | |
117 std::vector<std::pair<base::Closure, bool>>* tasks) { | |
118 base::MessageLoop::ScopedNestableTaskAllower allow(message_loop); | |
119 for (std::pair<base::Closure, bool>& pair : *tasks) { | |
120 if (pair.second) { | |
121 runner->PostTask(FROM_HERE, pair.first); | |
122 } else { | |
123 runner->PostNonNestableTask(FROM_HERE, pair.first); | |
124 } | |
125 } | |
126 base::RunLoop().RunUntilIdle(); | |
127 } | |
128 | |
129 void NopTask() {} | |
130 | |
131 TEST_F(TaskQueueManagerTest, | |
132 NowCalledMinimumNumberOfTimesToComputeTaskDurations) { | |
133 message_loop_.reset(new base::MessageLoop()); | |
134 // This memory is managed by the TaskQueueManager, but we need to hold a | |
135 // pointer to this object to read out how many times Now was called. | |
136 TestCountUsesTimeSource* test_count_uses_time_source = | |
137 new TestCountUsesTimeSource(); | |
138 | |
139 manager_ = base::WrapUnique(new TaskQueueManager( | |
140 MessageLoopTaskRunner::Create( | |
141 base::WrapUnique(test_count_uses_time_source)), | |
142 "test.scheduler", "test.scheduler", "test.scheduler.debug")); | |
143 manager_->SetWorkBatchSize(6); | |
144 manager_->SetTaskTimeTracker(&test_task_time_tracker_); | |
145 | |
146 for (size_t i = 0; i < 3; i++) | |
147 runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); | |
148 | |
149 runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
150 runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
151 runners_[1]->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
152 runners_[1]->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
153 runners_[2]->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
154 runners_[2]->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
155 | |
156 base::RunLoop().RunUntilIdle(); | |
157 // We need to call Now for the beginning of the first task, and then the end | |
158 // of every task after. We reuse the end time of one task for the start time | |
159 // of the next task. In this case, there were 6 tasks, so we expect 7 calls to | |
160 // Now. | |
161 EXPECT_EQ(7, test_count_uses_time_source->now_calls_count()); | |
162 } | |
163 | |
164 TEST_F(TaskQueueManagerTest, | |
165 NowNotCalledForNestedTasks) { | |
166 message_loop_.reset(new base::MessageLoop()); | |
167 // This memory is managed by the TaskQueueManager, but we need to hold a | |
168 // pointer to this object to read out how many times Now was called. | |
169 TestCountUsesTimeSource* test_count_uses_time_source = | |
170 new TestCountUsesTimeSource(); | |
171 | |
172 manager_ = base::WrapUnique(new TaskQueueManager( | |
173 MessageLoopTaskRunner::Create( | |
174 base::WrapUnique(test_count_uses_time_source)), | |
175 "test.scheduler", "test.scheduler", "test.scheduler.debug")); | |
176 manager_->SetTaskTimeTracker(&test_task_time_tracker_); | |
177 | |
178 runners_.push_back(manager_->NewTaskQueue(TaskQueue::Spec("test_queue"))); | |
179 | |
180 std::vector<std::pair<base::Closure, bool>> tasks_to_post_from_nested_loop; | |
181 for (int i = 0; i <= 6; ++i) { | |
182 tasks_to_post_from_nested_loop.push_back( | |
183 std::make_pair(base::Bind(&NopTask), true)); | |
184 } | |
185 | |
186 runners_[0]->PostTask( | |
187 FROM_HERE, base::Bind(&PostFromNestedRunloop, message_loop_.get(), | |
188 base::RetainedRef(runners_[0]), | |
189 base::Unretained(&tasks_to_post_from_nested_loop))); | |
190 | |
191 base::RunLoop().RunUntilIdle(); | |
192 // We need to call Now twice, to measure the start and end of the outermost | |
193 // task. We shouldn't call it for any of the nested tasks. | |
194 EXPECT_EQ(2, test_count_uses_time_source->now_calls_count()); | |
195 } | |
196 | |
197 void NullTask() {} | |
198 | |
199 void TestTask(EnqueueOrder value, std::vector<EnqueueOrder>* out_result) { | |
200 out_result->push_back(value); | |
201 } | |
202 | |
203 TEST_F(TaskQueueManagerTest, SingleQueuePosting) { | |
204 Initialize(1u); | |
205 | |
206 std::vector<EnqueueOrder> run_order; | |
207 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
208 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
209 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
210 | |
211 test_task_runner_->RunUntilIdle(); | |
212 EXPECT_THAT(run_order, ElementsAre(1, 2, 3)); | |
213 } | |
214 | |
215 TEST_F(TaskQueueManagerTest, MultiQueuePosting) { | |
216 Initialize(3u); | |
217 | |
218 std::vector<EnqueueOrder> run_order; | |
219 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
220 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
221 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
222 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order)); | |
223 runners_[2]->PostTask(FROM_HERE, base::Bind(&TestTask, 5, &run_order)); | |
224 runners_[2]->PostTask(FROM_HERE, base::Bind(&TestTask, 6, &run_order)); | |
225 | |
226 test_task_runner_->RunUntilIdle(); | |
227 EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4, 5, 6)); | |
228 } | |
229 | |
230 TEST_F(TaskQueueManagerTest, NonNestableTaskPosting) { | |
231 InitializeWithRealMessageLoop(1u); | |
232 | |
233 std::vector<EnqueueOrder> run_order; | |
234 runners_[0]->PostNonNestableTask(FROM_HERE, | |
235 base::Bind(&TestTask, 1, &run_order)); | |
236 | |
237 base::RunLoop().RunUntilIdle(); | |
238 EXPECT_THAT(run_order, ElementsAre(1)); | |
239 } | |
240 | |
241 TEST_F(TaskQueueManagerTest, NonNestableTaskExecutesInExpectedOrder) { | |
242 InitializeWithRealMessageLoop(1u); | |
243 | |
244 std::vector<EnqueueOrder> run_order; | |
245 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
246 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
247 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
248 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order)); | |
249 runners_[0]->PostNonNestableTask(FROM_HERE, | |
250 base::Bind(&TestTask, 5, &run_order)); | |
251 | |
252 base::RunLoop().RunUntilIdle(); | |
253 EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4, 5)); | |
254 } | |
255 | |
256 TEST_F(TaskQueueManagerTest, NonNestableTaskDoesntExecuteInNestedLoop) { | |
257 InitializeWithRealMessageLoop(1u); | |
258 | |
259 std::vector<EnqueueOrder> run_order; | |
260 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
261 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
262 | |
263 std::vector<std::pair<base::Closure, bool>> tasks_to_post_from_nested_loop; | |
264 tasks_to_post_from_nested_loop.push_back( | |
265 std::make_pair(base::Bind(&TestTask, 3, &run_order), false)); | |
266 tasks_to_post_from_nested_loop.push_back( | |
267 std::make_pair(base::Bind(&TestTask, 4, &run_order), true)); | |
268 tasks_to_post_from_nested_loop.push_back( | |
269 std::make_pair(base::Bind(&TestTask, 5, &run_order), true)); | |
270 | |
271 runners_[0]->PostTask( | |
272 FROM_HERE, base::Bind(&PostFromNestedRunloop, message_loop_.get(), | |
273 base::RetainedRef(runners_[0]), | |
274 base::Unretained(&tasks_to_post_from_nested_loop))); | |
275 | |
276 base::RunLoop().RunUntilIdle(); | |
277 // Note we expect task 3 to run last because it's non-nestable. | |
278 EXPECT_THAT(run_order, ElementsAre(1, 2, 4, 5, 3)); | |
279 } | |
280 | |
281 TEST_F(TaskQueueManagerTest, QueuePolling) { | |
282 Initialize(1u); | |
283 | |
284 std::vector<EnqueueOrder> run_order; | |
285 EXPECT_FALSE(runners_[0]->HasPendingImmediateWork()); | |
286 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
287 EXPECT_TRUE(runners_[0]->HasPendingImmediateWork()); | |
288 | |
289 test_task_runner_->RunUntilIdle(); | |
290 EXPECT_FALSE(runners_[0]->HasPendingImmediateWork()); | |
291 } | |
292 | |
293 TEST_F(TaskQueueManagerTest, DelayedTaskPosting) { | |
294 Initialize(1u); | |
295 | |
296 std::vector<EnqueueOrder> run_order; | |
297 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); | |
298 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
299 delay); | |
300 EXPECT_EQ(delay, test_task_runner_->DelayToNextTaskTime()); | |
301 EXPECT_FALSE(runners_[0]->HasPendingImmediateWork()); | |
302 EXPECT_TRUE(run_order.empty()); | |
303 | |
304 // The task doesn't run before the delay has completed. | |
305 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(9)); | |
306 EXPECT_TRUE(run_order.empty()); | |
307 | |
308 // After the delay has completed, the task runs normally. | |
309 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); | |
310 EXPECT_THAT(run_order, ElementsAre(1)); | |
311 EXPECT_FALSE(runners_[0]->HasPendingImmediateWork()); | |
312 } | |
313 | |
314 bool MessageLoopTaskCounter(size_t* count) { | |
315 *count = *count + 1; | |
316 return true; | |
317 } | |
318 | |
319 TEST_F(TaskQueueManagerTest, DelayedTaskExecutedInOneMessageLoopTask) { | |
320 Initialize(1u); | |
321 | |
322 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); | |
323 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay); | |
324 | |
325 size_t task_count = 0; | |
326 test_task_runner_->RunTasksWhile( | |
327 base::Bind(&MessageLoopTaskCounter, &task_count)); | |
328 EXPECT_EQ(1u, task_count); | |
329 } | |
330 | |
331 TEST_F(TaskQueueManagerTest, DelayedTaskPosting_MultipleTasks_DecendingOrder) { | |
332 Initialize(1u); | |
333 | |
334 std::vector<EnqueueOrder> run_order; | |
335 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
336 base::TimeDelta::FromMilliseconds(10)); | |
337 | |
338 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), | |
339 base::TimeDelta::FromMilliseconds(8)); | |
340 | |
341 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), | |
342 base::TimeDelta::FromMilliseconds(5)); | |
343 | |
344 EXPECT_EQ(base::TimeDelta::FromMilliseconds(5), | |
345 test_task_runner_->DelayToNextTaskTime()); | |
346 | |
347 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(5)); | |
348 EXPECT_THAT(run_order, ElementsAre(3)); | |
349 EXPECT_EQ(base::TimeDelta::FromMilliseconds(3), | |
350 test_task_runner_->DelayToNextTaskTime()); | |
351 | |
352 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(3)); | |
353 EXPECT_THAT(run_order, ElementsAre(3, 2)); | |
354 EXPECT_EQ(base::TimeDelta::FromMilliseconds(2), | |
355 test_task_runner_->DelayToNextTaskTime()); | |
356 | |
357 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(2)); | |
358 EXPECT_THAT(run_order, ElementsAre(3, 2, 1)); | |
359 } | |
360 | |
361 TEST_F(TaskQueueManagerTest, DelayedTaskPosting_MultipleTasks_AscendingOrder) { | |
362 Initialize(1u); | |
363 | |
364 std::vector<EnqueueOrder> run_order; | |
365 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
366 base::TimeDelta::FromMilliseconds(1)); | |
367 | |
368 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), | |
369 base::TimeDelta::FromMilliseconds(5)); | |
370 | |
371 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), | |
372 base::TimeDelta::FromMilliseconds(10)); | |
373 | |
374 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1), | |
375 test_task_runner_->DelayToNextTaskTime()); | |
376 | |
377 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(1)); | |
378 EXPECT_THAT(run_order, ElementsAre(1)); | |
379 EXPECT_EQ(base::TimeDelta::FromMilliseconds(4), | |
380 test_task_runner_->DelayToNextTaskTime()); | |
381 | |
382 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(4)); | |
383 EXPECT_THAT(run_order, ElementsAre(1, 2)); | |
384 EXPECT_EQ(base::TimeDelta::FromMilliseconds(5), | |
385 test_task_runner_->DelayToNextTaskTime()); | |
386 | |
387 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(5)); | |
388 EXPECT_THAT(run_order, ElementsAre(1, 2, 3)); | |
389 } | |
390 | |
391 TEST_F(TaskQueueManagerTest, PostDelayedTask_SharesUnderlyingDelayedTasks) { | |
392 Initialize(1u); | |
393 | |
394 std::vector<EnqueueOrder> run_order; | |
395 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); | |
396 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
397 delay); | |
398 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), | |
399 delay); | |
400 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), | |
401 delay); | |
402 | |
403 EXPECT_EQ(1u, test_task_runner_->NumPendingTasks()); | |
404 } | |
405 | |
406 class TestObject { | |
407 public: | |
408 ~TestObject() { destructor_count_++; } | |
409 | |
410 void Run() { FAIL() << "TestObject::Run should not be called"; } | |
411 | |
412 static int destructor_count_; | |
413 }; | |
414 | |
415 int TestObject::destructor_count_ = 0; | |
416 | |
417 TEST_F(TaskQueueManagerTest, PendingDelayedTasksRemovedOnShutdown) { | |
418 Initialize(1u); | |
419 | |
420 TestObject::destructor_count_ = 0; | |
421 | |
422 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); | |
423 runners_[0]->PostDelayedTask( | |
424 FROM_HERE, base::Bind(&TestObject::Run, base::Owned(new TestObject())), | |
425 delay); | |
426 runners_[0]->PostTask( | |
427 FROM_HERE, base::Bind(&TestObject::Run, base::Owned(new TestObject()))); | |
428 | |
429 manager_.reset(); | |
430 | |
431 EXPECT_EQ(2, TestObject::destructor_count_); | |
432 } | |
433 | |
434 TEST_F(TaskQueueManagerTest, ManualPumping) { | |
435 Initialize(1u); | |
436 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
437 | |
438 std::vector<EnqueueOrder> run_order; | |
439 // Posting a task when pumping is disabled doesn't result in work getting | |
440 // posted. | |
441 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
442 EXPECT_FALSE(test_task_runner_->HasPendingTasks()); | |
443 | |
444 // However polling still works. | |
445 EXPECT_TRUE(runners_[0]->HasPendingImmediateWork()); | |
446 | |
447 // After pumping the task runs normally. | |
448 LazyNow lazy_now(now_src_.get()); | |
449 runners_[0]->PumpQueue(&lazy_now, true); | |
450 EXPECT_TRUE(test_task_runner_->HasPendingTasks()); | |
451 test_task_runner_->RunUntilIdle(); | |
452 EXPECT_THAT(run_order, ElementsAre(1)); | |
453 } | |
454 | |
455 TEST_F(TaskQueueManagerTest, ManualPumpingToggle) { | |
456 Initialize(1u); | |
457 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
458 | |
459 std::vector<EnqueueOrder> run_order; | |
460 // Posting a task when pumping is disabled doesn't result in work getting | |
461 // posted. | |
462 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
463 EXPECT_FALSE(test_task_runner_->HasPendingTasks()); | |
464 | |
465 // When pumping is enabled the task runs normally. | |
466 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO); | |
467 EXPECT_TRUE(test_task_runner_->HasPendingTasks()); | |
468 test_task_runner_->RunUntilIdle(); | |
469 EXPECT_THAT(run_order, ElementsAre(1)); | |
470 } | |
471 | |
472 TEST_F(TaskQueueManagerTest, DenyRunning_BeforePosting) { | |
473 Initialize(1u); | |
474 | |
475 std::vector<EnqueueOrder> run_order; | |
476 runners_[0]->SetQueueEnabled(false); | |
477 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
478 | |
479 test_task_runner_->RunUntilIdle(); | |
480 EXPECT_TRUE(run_order.empty()); | |
481 | |
482 runners_[0]->SetQueueEnabled(true); | |
483 test_task_runner_->RunUntilIdle(); | |
484 EXPECT_THAT(run_order, ElementsAre(1)); | |
485 } | |
486 | |
487 TEST_F(TaskQueueManagerTest, DenyRunning_AfterPosting) { | |
488 Initialize(1u); | |
489 | |
490 std::vector<EnqueueOrder> run_order; | |
491 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
492 runners_[0]->SetQueueEnabled(false); | |
493 | |
494 test_task_runner_->RunUntilIdle(); | |
495 EXPECT_TRUE(run_order.empty()); | |
496 | |
497 runners_[0]->SetQueueEnabled(true); | |
498 test_task_runner_->RunUntilIdle(); | |
499 EXPECT_THAT(run_order, ElementsAre(1)); | |
500 } | |
501 | |
502 TEST_F(TaskQueueManagerTest, DenyRunning_ManuallyPumpedTransitionsToAuto) { | |
503 Initialize(1u); | |
504 | |
505 std::vector<EnqueueOrder> run_order; | |
506 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
507 runners_[0]->SetQueueEnabled(false); | |
508 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
509 | |
510 test_task_runner_->RunUntilIdle(); | |
511 EXPECT_TRUE(run_order.empty()); | |
512 | |
513 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO); | |
514 runners_[0]->SetQueueEnabled(true); | |
515 test_task_runner_->RunUntilIdle(); | |
516 EXPECT_THAT(run_order, ElementsAre(1)); | |
517 } | |
518 | |
519 TEST_F(TaskQueueManagerTest, ManualPumpingWithDelayedTask) { | |
520 Initialize(1u); | |
521 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
522 | |
523 std::vector<EnqueueOrder> run_order; | |
524 // Posting a delayed task when pumping will apply the delay, but won't cause | |
525 // work to executed afterwards. | |
526 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); | |
527 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
528 delay); | |
529 | |
530 // After pumping but before the delay period has expired, task does not run. | |
531 LazyNow lazy_now1(now_src_.get()); | |
532 runners_[0]->PumpQueue(&lazy_now1, true); | |
533 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(5)); | |
534 EXPECT_TRUE(run_order.empty()); | |
535 | |
536 // Once the delay has expired, pumping causes the task to run. | |
537 now_src_->Advance(base::TimeDelta::FromMilliseconds(5)); | |
538 LazyNow lazy_now2(now_src_.get()); | |
539 runners_[0]->PumpQueue(&lazy_now2, true); | |
540 EXPECT_TRUE(test_task_runner_->HasPendingTasks()); | |
541 test_task_runner_->RunPendingTasks(); | |
542 EXPECT_THAT(run_order, ElementsAre(1)); | |
543 } | |
544 | |
545 TEST_F(TaskQueueManagerTest, ManualPumpingWithMultipleDelayedTasks) { | |
546 Initialize(1u); | |
547 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
548 | |
549 std::vector<EnqueueOrder> run_order; | |
550 // Posting a delayed task when pumping will apply the delay, but won't cause | |
551 // work to executed afterwards. | |
552 base::TimeDelta delay1(base::TimeDelta::FromMilliseconds(1)); | |
553 base::TimeDelta delay2(base::TimeDelta::FromMilliseconds(10)); | |
554 base::TimeDelta delay3(base::TimeDelta::FromMilliseconds(20)); | |
555 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
556 delay1); | |
557 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), | |
558 delay2); | |
559 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), | |
560 delay3); | |
561 | |
562 now_src_->Advance(base::TimeDelta::FromMilliseconds(15)); | |
563 test_task_runner_->RunUntilIdle(); | |
564 EXPECT_TRUE(run_order.empty()); | |
565 | |
566 // Once the delay has expired, pumping causes the task to run. | |
567 LazyNow lazy_now(now_src_.get()); | |
568 runners_[0]->PumpQueue(&lazy_now, true); | |
569 test_task_runner_->RunUntilIdle(); | |
570 EXPECT_THAT(run_order, ElementsAre(1, 2)); | |
571 } | |
572 | |
573 TEST_F(TaskQueueManagerTest, DelayedTasksDontAutoRunWithManualPumping) { | |
574 Initialize(1u); | |
575 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
576 | |
577 std::vector<EnqueueOrder> run_order; | |
578 base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); | |
579 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
580 delay); | |
581 | |
582 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(10)); | |
583 EXPECT_TRUE(run_order.empty()); | |
584 } | |
585 | |
586 TEST_F(TaskQueueManagerTest, ManualPumpingWithNonEmptyWorkQueue) { | |
587 Initialize(1u); | |
588 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
589 | |
590 std::vector<EnqueueOrder> run_order; | |
591 // Posting two tasks and pumping twice should result in two tasks in the work | |
592 // queue. | |
593 LazyNow lazy_now(now_src_.get()); | |
594 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
595 runners_[0]->PumpQueue(&lazy_now, true); | |
596 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
597 runners_[0]->PumpQueue(&lazy_now, true); | |
598 | |
599 EXPECT_EQ(2u, runners_[0]->immediate_work_queue()->Size()); | |
600 } | |
601 | |
602 void ReentrantTestTask(scoped_refptr<base::SingleThreadTaskRunner> runner, | |
603 int countdown, | |
604 std::vector<EnqueueOrder>* out_result) { | |
605 out_result->push_back(countdown); | |
606 if (--countdown) { | |
607 runner->PostTask(FROM_HERE, | |
608 Bind(&ReentrantTestTask, runner, countdown, out_result)); | |
609 } | |
610 } | |
611 | |
612 TEST_F(TaskQueueManagerTest, ReentrantPosting) { | |
613 Initialize(1u); | |
614 | |
615 std::vector<EnqueueOrder> run_order; | |
616 runners_[0]->PostTask(FROM_HERE, | |
617 Bind(&ReentrantTestTask, runners_[0], 3, &run_order)); | |
618 | |
619 test_task_runner_->RunUntilIdle(); | |
620 EXPECT_THAT(run_order, ElementsAre(3, 2, 1)); | |
621 } | |
622 | |
623 TEST_F(TaskQueueManagerTest, NoTasksAfterShutdown) { | |
624 Initialize(1u); | |
625 | |
626 std::vector<EnqueueOrder> run_order; | |
627 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
628 manager_.reset(); | |
629 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
630 | |
631 test_task_runner_->RunUntilIdle(); | |
632 EXPECT_TRUE(run_order.empty()); | |
633 } | |
634 | |
635 void PostTaskToRunner(scoped_refptr<base::SingleThreadTaskRunner> runner, | |
636 std::vector<EnqueueOrder>* run_order) { | |
637 runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, run_order)); | |
638 } | |
639 | |
640 TEST_F(TaskQueueManagerTest, PostFromThread) { | |
641 InitializeWithRealMessageLoop(1u); | |
642 | |
643 std::vector<EnqueueOrder> run_order; | |
644 base::Thread thread("TestThread"); | |
645 thread.Start(); | |
646 thread.task_runner()->PostTask( | |
647 FROM_HERE, base::Bind(&PostTaskToRunner, runners_[0], &run_order)); | |
648 thread.Stop(); | |
649 | |
650 base::RunLoop().RunUntilIdle(); | |
651 EXPECT_THAT(run_order, ElementsAre(1)); | |
652 } | |
653 | |
654 void RePostingTestTask(scoped_refptr<base::SingleThreadTaskRunner> runner, | |
655 int* run_count) { | |
656 (*run_count)++; | |
657 runner->PostTask(FROM_HERE, Bind(&RePostingTestTask, | |
658 base::Unretained(runner.get()), run_count)); | |
659 } | |
660 | |
661 TEST_F(TaskQueueManagerTest, DoWorkCantPostItselfMultipleTimes) { | |
662 Initialize(1u); | |
663 | |
664 int run_count = 0; | |
665 runners_[0]->PostTask( | |
666 FROM_HERE, base::Bind(&RePostingTestTask, runners_[0], &run_count)); | |
667 | |
668 test_task_runner_->RunPendingTasks(); | |
669 // NOTE without the executing_task_ check in MaybeScheduleDoWork there | |
670 // will be two tasks here. | |
671 EXPECT_EQ(1u, test_task_runner_->NumPendingTasks()); | |
672 EXPECT_EQ(1, run_count); | |
673 } | |
674 | |
675 TEST_F(TaskQueueManagerTest, PostFromNestedRunloop) { | |
676 InitializeWithRealMessageLoop(1u); | |
677 | |
678 std::vector<EnqueueOrder> run_order; | |
679 std::vector<std::pair<base::Closure, bool>> tasks_to_post_from_nested_loop; | |
680 tasks_to_post_from_nested_loop.push_back( | |
681 std::make_pair(base::Bind(&TestTask, 1, &run_order), true)); | |
682 | |
683 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 0, &run_order)); | |
684 runners_[0]->PostTask( | |
685 FROM_HERE, base::Bind(&PostFromNestedRunloop, message_loop_.get(), | |
686 base::RetainedRef(runners_[0]), | |
687 base::Unretained(&tasks_to_post_from_nested_loop))); | |
688 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
689 | |
690 base::RunLoop().RunUntilIdle(); | |
691 | |
692 EXPECT_THAT(run_order, ElementsAre(0, 2, 1)); | |
693 } | |
694 | |
695 TEST_F(TaskQueueManagerTest, WorkBatching) { | |
696 Initialize(1u); | |
697 | |
698 manager_->SetWorkBatchSize(2); | |
699 | |
700 std::vector<EnqueueOrder> run_order; | |
701 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
702 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
703 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
704 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order)); | |
705 | |
706 // Running one task in the host message loop should cause two posted tasks to | |
707 // get executed. | |
708 EXPECT_EQ(test_task_runner_->NumPendingTasks(), 1u); | |
709 test_task_runner_->RunPendingTasks(); | |
710 EXPECT_THAT(run_order, ElementsAre(1, 2)); | |
711 | |
712 // The second task runs the remaining two posted tasks. | |
713 EXPECT_EQ(test_task_runner_->NumPendingTasks(), 1u); | |
714 test_task_runner_->RunPendingTasks(); | |
715 EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4)); | |
716 } | |
717 | |
718 TEST_F(TaskQueueManagerTest, AutoPumpAfterWakeup) { | |
719 Initialize(2u); | |
720 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::AFTER_WAKEUP); | |
721 | |
722 std::vector<EnqueueOrder> run_order; | |
723 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
724 test_task_runner_->RunUntilIdle(); | |
725 EXPECT_TRUE(run_order.empty()); // Shouldn't run - no other task to wake TQM. | |
726 | |
727 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
728 test_task_runner_->RunUntilIdle(); | |
729 EXPECT_TRUE(run_order.empty()); // Still shouldn't wake TQM. | |
730 | |
731 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
732 test_task_runner_->RunUntilIdle(); | |
733 // Executing a task on an auto pumped queue should wake the TQM. | |
734 EXPECT_THAT(run_order, ElementsAre(3, 1, 2)); | |
735 } | |
736 | |
737 TEST_F(TaskQueueManagerTest, AutoPumpAfterWakeupWhenAlreadyAwake) { | |
738 Initialize(2u); | |
739 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::AFTER_WAKEUP); | |
740 | |
741 std::vector<EnqueueOrder> run_order; | |
742 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
743 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
744 test_task_runner_->RunUntilIdle(); | |
745 EXPECT_THAT(run_order, ElementsAre(2, 1)); // TQM was already awake. | |
746 } | |
747 | |
748 TEST_F(TaskQueueManagerTest, | |
749 AutoPumpAfterWakeupTriggeredByManuallyPumpedQueue) { | |
750 Initialize(2u); | |
751 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::AFTER_WAKEUP); | |
752 runners_[1]->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
753 | |
754 std::vector<EnqueueOrder> run_order; | |
755 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
756 test_task_runner_->RunUntilIdle(); | |
757 EXPECT_TRUE(run_order.empty()); // Shouldn't run - no other task to wake TQM. | |
758 | |
759 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
760 test_task_runner_->RunUntilIdle(); | |
761 // This still shouldn't wake TQM as manual queue was not pumped. | |
762 EXPECT_TRUE(run_order.empty()); | |
763 | |
764 LazyNow lazy_now(now_src_.get()); | |
765 runners_[1]->PumpQueue(&lazy_now, true); | |
766 test_task_runner_->RunUntilIdle(); | |
767 // Executing a task on an auto pumped queue should wake the TQM. | |
768 EXPECT_THAT(run_order, ElementsAre(2, 1)); | |
769 } | |
770 | |
771 void TestPostingTask(scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
772 base::Closure task) { | |
773 task_runner->PostTask(FROM_HERE, task); | |
774 } | |
775 | |
776 TEST_F(TaskQueueManagerTest, AutoPumpAfterWakeupFromTask) { | |
777 Initialize(2u); | |
778 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::AFTER_WAKEUP); | |
779 | |
780 std::vector<EnqueueOrder> run_order; | |
781 // Check that a task which posts a task to an auto pump after wakeup queue | |
782 // doesn't cause the queue to wake up. | |
783 base::Closure after_wakeup_task = base::Bind(&TestTask, 1, &run_order); | |
784 runners_[1]->PostTask( | |
785 FROM_HERE, base::Bind(&TestPostingTask, runners_[0], after_wakeup_task)); | |
786 test_task_runner_->RunUntilIdle(); | |
787 EXPECT_TRUE(run_order.empty()); | |
788 | |
789 // Wake up the queue. | |
790 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
791 test_task_runner_->RunUntilIdle(); | |
792 EXPECT_THAT(run_order, ElementsAre(2, 1)); | |
793 } | |
794 | |
795 TEST_F(TaskQueueManagerTest, AutoPumpAfterWakeupFromMultipleTasks) { | |
796 Initialize(2u); | |
797 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::AFTER_WAKEUP); | |
798 | |
799 std::vector<EnqueueOrder> run_order; | |
800 // Check that a task which posts a task to an auto pump after wakeup queue | |
801 // doesn't cause the queue to wake up. | |
802 base::Closure after_wakeup_task_1 = base::Bind(&TestTask, 1, &run_order); | |
803 base::Closure after_wakeup_task_2 = base::Bind(&TestTask, 2, &run_order); | |
804 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestPostingTask, runners_[0], | |
805 after_wakeup_task_1)); | |
806 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestPostingTask, runners_[0], | |
807 after_wakeup_task_2)); | |
808 test_task_runner_->RunUntilIdle(); | |
809 EXPECT_TRUE(run_order.empty()); | |
810 | |
811 // Wake up the queue. | |
812 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
813 test_task_runner_->RunUntilIdle(); | |
814 EXPECT_THAT(run_order, ElementsAre(3, 1, 2)); | |
815 } | |
816 | |
817 TEST_F(TaskQueueManagerTest, AutoPumpAfterWakeupBecomesQuiescent) { | |
818 Initialize(2u); | |
819 runners_[0]->SetPumpPolicy(TaskQueue::PumpPolicy::AFTER_WAKEUP); | |
820 | |
821 int run_count = 0; | |
822 // Check that if multiple tasks reposts themselves onto a pump-after-wakeup | |
823 // queue they don't wake each other and will eventually stop when no other | |
824 // tasks execute. | |
825 runners_[0]->PostTask( | |
826 FROM_HERE, base::Bind(&RePostingTestTask, runners_[0], &run_count)); | |
827 runners_[0]->PostTask( | |
828 FROM_HERE, base::Bind(&RePostingTestTask, runners_[0], &run_count)); | |
829 runners_[1]->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
830 test_task_runner_->RunUntilIdle(); | |
831 // The reposting tasks posted to the after wakeup queue shouldn't have woken | |
832 // each other up. | |
833 EXPECT_EQ(2, run_count); | |
834 } | |
835 | |
836 TEST_F(TaskQueueManagerTest, AutoPumpAfterWakeupWithDontWakeQueue) { | |
837 Initialize(1u); | |
838 | |
839 scoped_refptr<internal::TaskQueueImpl> queue0 = manager_->NewTaskQueue( | |
840 TaskQueue::Spec("test_queue 0") | |
841 .SetPumpPolicy(TaskQueue::PumpPolicy::AFTER_WAKEUP)); | |
842 scoped_refptr<internal::TaskQueueImpl> queue1 = manager_->NewTaskQueue( | |
843 TaskQueue::Spec("test_queue 0") | |
844 .SetWakeupPolicy(TaskQueue::WakeupPolicy::DONT_WAKE_OTHER_QUEUES)); | |
845 scoped_refptr<internal::TaskQueueImpl> queue2 = runners_[0]; | |
846 | |
847 std::vector<EnqueueOrder> run_order; | |
848 queue0->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
849 queue1->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
850 test_task_runner_->RunUntilIdle(); | |
851 // Executing a DONT_WAKE_OTHER_QUEUES queue shouldn't wake the autopump after | |
852 // wakeup queue. | |
853 EXPECT_THAT(run_order, ElementsAre(2)); | |
854 | |
855 queue2->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
856 test_task_runner_->RunUntilIdle(); | |
857 // Executing a CAN_WAKE_OTHER_QUEUES queue should wake the autopump after | |
858 // wakeup queue. | |
859 EXPECT_THAT(run_order, ElementsAre(2, 3, 1)); | |
860 } | |
861 | |
862 class MockTaskObserver : public base::MessageLoop::TaskObserver { | |
863 public: | |
864 MOCK_METHOD1(DidProcessTask, void(const base::PendingTask& task)); | |
865 MOCK_METHOD1(WillProcessTask, void(const base::PendingTask& task)); | |
866 }; | |
867 | |
868 TEST_F(TaskQueueManagerTest, TaskObserverAdding) { | |
869 InitializeWithRealMessageLoop(1u); | |
870 MockTaskObserver observer; | |
871 | |
872 manager_->SetWorkBatchSize(2); | |
873 manager_->AddTaskObserver(&observer); | |
874 | |
875 std::vector<EnqueueOrder> run_order; | |
876 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
877 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
878 | |
879 EXPECT_CALL(observer, WillProcessTask(_)).Times(2); | |
880 EXPECT_CALL(observer, DidProcessTask(_)).Times(2); | |
881 base::RunLoop().RunUntilIdle(); | |
882 } | |
883 | |
884 TEST_F(TaskQueueManagerTest, TaskObserverRemoving) { | |
885 InitializeWithRealMessageLoop(1u); | |
886 MockTaskObserver observer; | |
887 manager_->SetWorkBatchSize(2); | |
888 manager_->AddTaskObserver(&observer); | |
889 manager_->RemoveTaskObserver(&observer); | |
890 | |
891 std::vector<EnqueueOrder> run_order; | |
892 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
893 | |
894 EXPECT_CALL(observer, WillProcessTask(_)).Times(0); | |
895 EXPECT_CALL(observer, DidProcessTask(_)).Times(0); | |
896 | |
897 base::RunLoop().RunUntilIdle(); | |
898 } | |
899 | |
900 void RemoveObserverTask(TaskQueueManager* manager, | |
901 base::MessageLoop::TaskObserver* observer) { | |
902 manager->RemoveTaskObserver(observer); | |
903 } | |
904 | |
905 TEST_F(TaskQueueManagerTest, TaskObserverRemovingInsideTask) { | |
906 InitializeWithRealMessageLoop(1u); | |
907 MockTaskObserver observer; | |
908 manager_->SetWorkBatchSize(3); | |
909 manager_->AddTaskObserver(&observer); | |
910 | |
911 runners_[0]->PostTask( | |
912 FROM_HERE, base::Bind(&RemoveObserverTask, manager_.get(), &observer)); | |
913 | |
914 EXPECT_CALL(observer, WillProcessTask(_)).Times(1); | |
915 EXPECT_CALL(observer, DidProcessTask(_)).Times(0); | |
916 base::RunLoop().RunUntilIdle(); | |
917 } | |
918 | |
919 TEST_F(TaskQueueManagerTest, QueueTaskObserverAdding) { | |
920 InitializeWithRealMessageLoop(2u); | |
921 MockTaskObserver observer; | |
922 | |
923 manager_->SetWorkBatchSize(2); | |
924 runners_[0]->AddTaskObserver(&observer); | |
925 | |
926 std::vector<EnqueueOrder> run_order; | |
927 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
928 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
929 | |
930 EXPECT_CALL(observer, WillProcessTask(_)).Times(1); | |
931 EXPECT_CALL(observer, DidProcessTask(_)).Times(1); | |
932 base::RunLoop().RunUntilIdle(); | |
933 } | |
934 | |
935 TEST_F(TaskQueueManagerTest, QueueTaskObserverRemoving) { | |
936 InitializeWithRealMessageLoop(1u); | |
937 MockTaskObserver observer; | |
938 manager_->SetWorkBatchSize(2); | |
939 runners_[0]->AddTaskObserver(&observer); | |
940 runners_[0]->RemoveTaskObserver(&observer); | |
941 | |
942 std::vector<EnqueueOrder> run_order; | |
943 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
944 | |
945 EXPECT_CALL(observer, WillProcessTask(_)).Times(0); | |
946 EXPECT_CALL(observer, DidProcessTask(_)).Times(0); | |
947 | |
948 base::RunLoop().RunUntilIdle(); | |
949 } | |
950 | |
951 void RemoveQueueObserverTask(scoped_refptr<TaskQueue> queue, | |
952 base::MessageLoop::TaskObserver* observer) { | |
953 queue->RemoveTaskObserver(observer); | |
954 } | |
955 | |
956 TEST_F(TaskQueueManagerTest, QueueTaskObserverRemovingInsideTask) { | |
957 InitializeWithRealMessageLoop(1u); | |
958 MockTaskObserver observer; | |
959 runners_[0]->AddTaskObserver(&observer); | |
960 | |
961 runners_[0]->PostTask( | |
962 FROM_HERE, base::Bind(&RemoveQueueObserverTask, runners_[0], &observer)); | |
963 | |
964 EXPECT_CALL(observer, WillProcessTask(_)).Times(1); | |
965 EXPECT_CALL(observer, DidProcessTask(_)).Times(0); | |
966 base::RunLoop().RunUntilIdle(); | |
967 } | |
968 | |
969 TEST_F(TaskQueueManagerTest, ThreadCheckAfterTermination) { | |
970 Initialize(1u); | |
971 EXPECT_TRUE(runners_[0]->RunsTasksOnCurrentThread()); | |
972 manager_.reset(); | |
973 EXPECT_TRUE(runners_[0]->RunsTasksOnCurrentThread()); | |
974 } | |
975 | |
976 TEST_F(TaskQueueManagerTest, TimeDomain_NextScheduledRunTime) { | |
977 Initialize(2u); | |
978 now_src_->Advance(base::TimeDelta::FromMicroseconds(10000)); | |
979 | |
980 // With no delayed tasks. | |
981 base::TimeTicks run_time; | |
982 EXPECT_FALSE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); | |
983 | |
984 // With a non-delayed task. | |
985 runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
986 EXPECT_FALSE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); | |
987 | |
988 // With a delayed task. | |
989 base::TimeDelta expected_delay = base::TimeDelta::FromMilliseconds(50); | |
990 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), expected_delay); | |
991 EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); | |
992 EXPECT_EQ(now_src_->NowTicks() + expected_delay, run_time); | |
993 | |
994 // With another delayed task in the same queue with a longer delay. | |
995 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), | |
996 base::TimeDelta::FromMilliseconds(100)); | |
997 EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); | |
998 EXPECT_EQ(now_src_->NowTicks() + expected_delay, run_time); | |
999 | |
1000 // With another delayed task in the same queue with a shorter delay. | |
1001 expected_delay = base::TimeDelta::FromMilliseconds(20); | |
1002 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), expected_delay); | |
1003 EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); | |
1004 EXPECT_EQ(now_src_->NowTicks() + expected_delay, run_time); | |
1005 | |
1006 // With another delayed task in a different queue with a shorter delay. | |
1007 expected_delay = base::TimeDelta::FromMilliseconds(10); | |
1008 runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), expected_delay); | |
1009 EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); | |
1010 EXPECT_EQ(now_src_->NowTicks() + expected_delay, run_time); | |
1011 | |
1012 // Test it updates as time progresses | |
1013 now_src_->Advance(expected_delay); | |
1014 EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); | |
1015 EXPECT_EQ(now_src_->NowTicks(), run_time); | |
1016 } | |
1017 | |
1018 TEST_F(TaskQueueManagerTest, TimeDomain_NextScheduledRunTime_MultipleQueues) { | |
1019 Initialize(3u); | |
1020 | |
1021 base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(50); | |
1022 base::TimeDelta delay2 = base::TimeDelta::FromMilliseconds(5); | |
1023 base::TimeDelta delay3 = base::TimeDelta::FromMilliseconds(10); | |
1024 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay1); | |
1025 runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay2); | |
1026 runners_[2]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), delay3); | |
1027 runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
1028 | |
1029 base::TimeTicks run_time; | |
1030 EXPECT_TRUE(manager_->real_time_domain()->NextScheduledRunTime(&run_time)); | |
1031 EXPECT_EQ(now_src_->NowTicks() + delay2, run_time); | |
1032 } | |
1033 | |
1034 TEST_F(TaskQueueManagerTest, DeleteTaskQueueManagerInsideATask) { | |
1035 Initialize(1u); | |
1036 | |
1037 runners_[0]->PostTask( | |
1038 FROM_HERE, base::Bind(&TaskQueueManagerTest::DeleteTaskQueueManager, | |
1039 base::Unretained(this))); | |
1040 | |
1041 // This should not crash, assuming DoWork detects the TaskQueueManager has | |
1042 // been deleted. | |
1043 test_task_runner_->RunUntilIdle(); | |
1044 } | |
1045 | |
1046 TEST_F(TaskQueueManagerTest, GetAndClearSystemIsQuiescentBit) { | |
1047 Initialize(3u); | |
1048 | |
1049 scoped_refptr<internal::TaskQueueImpl> queue0 = manager_->NewTaskQueue( | |
1050 TaskQueue::Spec("test_queue 0").SetShouldMonitorQuiescence(true)); | |
1051 scoped_refptr<internal::TaskQueueImpl> queue1 = manager_->NewTaskQueue( | |
1052 TaskQueue::Spec("test_queue 1").SetShouldMonitorQuiescence(true)); | |
1053 scoped_refptr<internal::TaskQueueImpl> queue2 = manager_->NewTaskQueue( | |
1054 TaskQueue::Spec("test_queue 2").SetShouldMonitorQuiescence(false)); | |
1055 | |
1056 EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit()); | |
1057 | |
1058 queue0->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
1059 test_task_runner_->RunUntilIdle(); | |
1060 EXPECT_FALSE(manager_->GetAndClearSystemIsQuiescentBit()); | |
1061 EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit()); | |
1062 | |
1063 queue1->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
1064 test_task_runner_->RunUntilIdle(); | |
1065 EXPECT_FALSE(manager_->GetAndClearSystemIsQuiescentBit()); | |
1066 EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit()); | |
1067 | |
1068 queue2->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
1069 test_task_runner_->RunUntilIdle(); | |
1070 EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit()); | |
1071 | |
1072 queue0->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
1073 queue1->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
1074 test_task_runner_->RunUntilIdle(); | |
1075 EXPECT_FALSE(manager_->GetAndClearSystemIsQuiescentBit()); | |
1076 EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit()); | |
1077 } | |
1078 | |
1079 TEST_F(TaskQueueManagerTest, HasPendingImmediateWork) { | |
1080 Initialize(2u); | |
1081 internal::TaskQueueImpl* queue0 = runners_[0].get(); | |
1082 internal::TaskQueueImpl* queue1 = runners_[1].get(); | |
1083 queue0->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO); | |
1084 queue1->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
1085 | |
1086 EXPECT_FALSE(queue0->HasPendingImmediateWork()); | |
1087 EXPECT_FALSE(queue1->HasPendingImmediateWork()); | |
1088 | |
1089 queue0->PostTask(FROM_HERE, base::Bind(NullTask)); | |
1090 queue1->PostTask(FROM_HERE, base::Bind(NullTask)); | |
1091 EXPECT_TRUE(queue0->HasPendingImmediateWork()); | |
1092 EXPECT_TRUE(queue1->HasPendingImmediateWork()); | |
1093 | |
1094 test_task_runner_->RunUntilIdle(); | |
1095 EXPECT_FALSE(queue0->HasPendingImmediateWork()); | |
1096 EXPECT_TRUE(queue1->HasPendingImmediateWork()); | |
1097 | |
1098 LazyNow lazy_now(now_src_.get()); | |
1099 queue1->PumpQueue(&lazy_now, true); | |
1100 EXPECT_FALSE(queue0->HasPendingImmediateWork()); | |
1101 EXPECT_TRUE(queue1->HasPendingImmediateWork()); | |
1102 | |
1103 test_task_runner_->RunUntilIdle(); | |
1104 EXPECT_FALSE(queue0->HasPendingImmediateWork()); | |
1105 EXPECT_FALSE(queue1->HasPendingImmediateWork()); | |
1106 } | |
1107 | |
1108 TEST_F(TaskQueueManagerTest, HasPendingImmediateWorkAndNeedsPumping) { | |
1109 Initialize(2u); | |
1110 internal::TaskQueueImpl* queue0 = runners_[0].get(); | |
1111 internal::TaskQueueImpl* queue1 = runners_[1].get(); | |
1112 queue0->SetPumpPolicy(TaskQueue::PumpPolicy::AUTO); | |
1113 queue1->SetPumpPolicy(TaskQueue::PumpPolicy::MANUAL); | |
1114 | |
1115 EXPECT_FALSE(queue0->HasPendingImmediateWork()); | |
1116 EXPECT_FALSE(queue0->NeedsPumping()); | |
1117 EXPECT_FALSE(queue1->HasPendingImmediateWork()); | |
1118 EXPECT_FALSE(queue1->NeedsPumping()); | |
1119 | |
1120 queue0->PostTask(FROM_HERE, base::Bind(NullTask)); | |
1121 queue0->PostTask(FROM_HERE, base::Bind(NullTask)); | |
1122 queue1->PostTask(FROM_HERE, base::Bind(NullTask)); | |
1123 EXPECT_TRUE(queue0->HasPendingImmediateWork()); | |
1124 EXPECT_TRUE(queue0->NeedsPumping()); | |
1125 EXPECT_TRUE(queue1->HasPendingImmediateWork()); | |
1126 EXPECT_TRUE(queue1->NeedsPumping()); | |
1127 | |
1128 test_task_runner_->SetRunTaskLimit(1); | |
1129 test_task_runner_->RunPendingTasks(); | |
1130 EXPECT_TRUE(queue0->HasPendingImmediateWork()); | |
1131 EXPECT_FALSE(queue0->NeedsPumping()); | |
1132 EXPECT_TRUE(queue1->HasPendingImmediateWork()); | |
1133 EXPECT_TRUE(queue1->NeedsPumping()); | |
1134 | |
1135 test_task_runner_->ClearRunTaskLimit(); | |
1136 test_task_runner_->RunUntilIdle(); | |
1137 EXPECT_FALSE(queue0->HasPendingImmediateWork()); | |
1138 EXPECT_FALSE(queue0->NeedsPumping()); | |
1139 EXPECT_TRUE(queue1->HasPendingImmediateWork()); | |
1140 EXPECT_TRUE(queue1->NeedsPumping()); | |
1141 | |
1142 LazyNow lazy_now(now_src_.get()); | |
1143 queue1->PumpQueue(&lazy_now, true); | |
1144 EXPECT_FALSE(queue0->HasPendingImmediateWork()); | |
1145 EXPECT_FALSE(queue0->NeedsPumping()); | |
1146 EXPECT_TRUE(queue1->HasPendingImmediateWork()); | |
1147 EXPECT_FALSE(queue1->NeedsPumping()); | |
1148 | |
1149 test_task_runner_->RunUntilIdle(); | |
1150 EXPECT_FALSE(queue0->HasPendingImmediateWork()); | |
1151 EXPECT_FALSE(queue0->NeedsPumping()); | |
1152 EXPECT_FALSE(queue1->HasPendingImmediateWork()); | |
1153 EXPECT_FALSE(queue1->NeedsPumping()); | |
1154 } | |
1155 | |
1156 void ExpensiveTestTask(int value, | |
1157 base::SimpleTestTickClock* clock, | |
1158 std::vector<EnqueueOrder>* out_result) { | |
1159 out_result->push_back(value); | |
1160 clock->Advance(base::TimeDelta::FromMilliseconds(1)); | |
1161 } | |
1162 | |
1163 TEST_F(TaskQueueManagerTest, ImmediateAndDelayedTaskInterleaving) { | |
1164 Initialize(1u); | |
1165 | |
1166 std::vector<EnqueueOrder> run_order; | |
1167 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10); | |
1168 for (int i = 10; i < 19; i++) { | |
1169 runners_[0]->PostDelayedTask( | |
1170 FROM_HERE, | |
1171 base::Bind(&ExpensiveTestTask, i, now_src_.get(), &run_order), | |
1172 delay); | |
1173 } | |
1174 | |
1175 test_task_runner_->RunForPeriod(delay); | |
1176 | |
1177 for (int i = 0; i < 9; i++) { | |
1178 runners_[0]->PostTask( | |
1179 FROM_HERE, | |
1180 base::Bind(&ExpensiveTestTask, i, now_src_.get(), &run_order)); | |
1181 } | |
1182 | |
1183 test_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
1184 test_task_runner_->RunUntilIdle(); | |
1185 | |
1186 // Delayed tasks are not allowed to starve out immediate work which is why | |
1187 // some of the immediate tasks run out of order. | |
1188 int expected_run_order[] = { | |
1189 10, 11, 12, 13, 0, 14, 15, 16, 1, 17, 18, 2, 3, 4, 5, 6, 7, 8 | |
1190 }; | |
1191 EXPECT_THAT(run_order, ElementsAreArray(expected_run_order)); | |
1192 } | |
1193 | |
1194 TEST_F(TaskQueueManagerTest, | |
1195 DelayedTaskDoesNotSkipAHeadOfNonDelayedTask_SameQueue) { | |
1196 Initialize(1u); | |
1197 | |
1198 std::vector<EnqueueOrder> run_order; | |
1199 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10); | |
1200 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
1201 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
1202 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
1203 delay); | |
1204 | |
1205 now_src_->Advance(delay * 2); | |
1206 test_task_runner_->RunUntilIdle(); | |
1207 | |
1208 EXPECT_THAT(run_order, ElementsAre(2, 3, 1)); | |
1209 } | |
1210 | |
1211 TEST_F(TaskQueueManagerTest, | |
1212 DelayedTaskDoesNotSkipAHeadOfNonDelayedTask_DifferentQueues) { | |
1213 Initialize(2u); | |
1214 | |
1215 std::vector<EnqueueOrder> run_order; | |
1216 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10); | |
1217 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
1218 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
1219 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
1220 delay); | |
1221 | |
1222 now_src_->Advance(delay * 2); | |
1223 test_task_runner_->RunUntilIdle(); | |
1224 | |
1225 EXPECT_THAT(run_order, ElementsAre(2, 3, 1)); | |
1226 } | |
1227 | |
1228 TEST_F(TaskQueueManagerTest, DelayedTaskDoesNotSkipAHeadOfShorterDelayedTask) { | |
1229 Initialize(2u); | |
1230 | |
1231 std::vector<EnqueueOrder> run_order; | |
1232 base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(10); | |
1233 base::TimeDelta delay2 = base::TimeDelta::FromMilliseconds(5); | |
1234 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
1235 delay1); | |
1236 runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), | |
1237 delay2); | |
1238 | |
1239 now_src_->Advance(delay1 * 2); | |
1240 test_task_runner_->RunUntilIdle(); | |
1241 | |
1242 EXPECT_THAT(run_order, ElementsAre(2, 1)); | |
1243 } | |
1244 | |
1245 void CheckIsNested(bool* is_nested) { | |
1246 *is_nested = base::MessageLoop::current()->IsNested(); | |
1247 } | |
1248 | |
1249 void PostAndQuitFromNestedRunloop(base::RunLoop* run_loop, | |
1250 base::SingleThreadTaskRunner* runner, | |
1251 bool* was_nested) { | |
1252 base::MessageLoop::ScopedNestableTaskAllower allow( | |
1253 base::MessageLoop::current()); | |
1254 runner->PostTask(FROM_HERE, run_loop->QuitClosure()); | |
1255 runner->PostTask(FROM_HERE, base::Bind(&CheckIsNested, was_nested)); | |
1256 run_loop->Run(); | |
1257 } | |
1258 | |
1259 TEST_F(TaskQueueManagerTest, QuitWhileNested) { | |
1260 // This test makes sure we don't continue running a work batch after a nested | |
1261 // run loop has been exited in the middle of the batch. | |
1262 InitializeWithRealMessageLoop(1u); | |
1263 manager_->SetWorkBatchSize(2); | |
1264 | |
1265 bool was_nested = true; | |
1266 base::RunLoop run_loop; | |
1267 runners_[0]->PostTask(FROM_HERE, base::Bind(&PostAndQuitFromNestedRunloop, | |
1268 base::Unretained(&run_loop), | |
1269 base::RetainedRef(runners_[0]), | |
1270 base::Unretained(&was_nested))); | |
1271 | |
1272 base::RunLoop().RunUntilIdle(); | |
1273 EXPECT_FALSE(was_nested); | |
1274 } | |
1275 | |
1276 class SequenceNumberCapturingTaskObserver | |
1277 : public base::MessageLoop::TaskObserver { | |
1278 public: | |
1279 // MessageLoop::TaskObserver overrides. | |
1280 void WillProcessTask(const base::PendingTask& pending_task) override {} | |
1281 void DidProcessTask(const base::PendingTask& pending_task) override { | |
1282 sequence_numbers_.push_back(pending_task.sequence_num); | |
1283 } | |
1284 | |
1285 const std::vector<EnqueueOrder>& sequence_numbers() const { | |
1286 return sequence_numbers_; | |
1287 } | |
1288 | |
1289 private: | |
1290 std::vector<EnqueueOrder> sequence_numbers_; | |
1291 }; | |
1292 | |
1293 TEST_F(TaskQueueManagerTest, SequenceNumSetWhenTaskIsPosted) { | |
1294 Initialize(1u); | |
1295 | |
1296 SequenceNumberCapturingTaskObserver observer; | |
1297 manager_->AddTaskObserver(&observer); | |
1298 | |
1299 // Register four tasks that will run in reverse order. | |
1300 std::vector<EnqueueOrder> run_order; | |
1301 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
1302 base::TimeDelta::FromMilliseconds(30)); | |
1303 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), | |
1304 base::TimeDelta::FromMilliseconds(20)); | |
1305 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), | |
1306 base::TimeDelta::FromMilliseconds(10)); | |
1307 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order)); | |
1308 | |
1309 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(40)); | |
1310 ASSERT_THAT(run_order, ElementsAre(4, 3, 2, 1)); | |
1311 | |
1312 // The sequence numbers are a zero-based monotonically incrememting counter | |
1313 // which should be set when the task is posted rather than when it's enqueued | |
1314 // onto the Incoming queue. | |
1315 EXPECT_THAT(observer.sequence_numbers(), ElementsAre(3, 2, 1, 0)); | |
1316 | |
1317 manager_->RemoveTaskObserver(&observer); | |
1318 } | |
1319 | |
1320 TEST_F(TaskQueueManagerTest, NewTaskQueues) { | |
1321 Initialize(1u); | |
1322 | |
1323 scoped_refptr<internal::TaskQueueImpl> queue1 = | |
1324 manager_->NewTaskQueue(TaskQueue::Spec("foo")); | |
1325 scoped_refptr<internal::TaskQueueImpl> queue2 = | |
1326 manager_->NewTaskQueue(TaskQueue::Spec("bar")); | |
1327 scoped_refptr<internal::TaskQueueImpl> queue3 = | |
1328 manager_->NewTaskQueue(TaskQueue::Spec("baz")); | |
1329 | |
1330 ASSERT_NE(queue1, queue2); | |
1331 ASSERT_NE(queue1, queue3); | |
1332 ASSERT_NE(queue2, queue3); | |
1333 | |
1334 std::vector<EnqueueOrder> run_order; | |
1335 queue1->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
1336 queue2->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
1337 queue3->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
1338 test_task_runner_->RunUntilIdle(); | |
1339 | |
1340 EXPECT_THAT(run_order, ElementsAre(1, 2, 3)); | |
1341 } | |
1342 | |
1343 TEST_F(TaskQueueManagerTest, UnregisterTaskQueue) { | |
1344 Initialize(1u); | |
1345 | |
1346 scoped_refptr<internal::TaskQueueImpl> queue1 = | |
1347 manager_->NewTaskQueue(TaskQueue::Spec("foo")); | |
1348 scoped_refptr<internal::TaskQueueImpl> queue2 = | |
1349 manager_->NewTaskQueue(TaskQueue::Spec("bar")); | |
1350 scoped_refptr<internal::TaskQueueImpl> queue3 = | |
1351 manager_->NewTaskQueue(TaskQueue::Spec("baz")); | |
1352 | |
1353 ASSERT_NE(queue1, queue2); | |
1354 ASSERT_NE(queue1, queue3); | |
1355 ASSERT_NE(queue2, queue3); | |
1356 | |
1357 std::vector<EnqueueOrder> run_order; | |
1358 queue1->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
1359 queue2->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
1360 queue3->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
1361 | |
1362 queue2->UnregisterTaskQueue(); | |
1363 test_task_runner_->RunUntilIdle(); | |
1364 | |
1365 EXPECT_THAT(run_order, ElementsAre(1, 3)); | |
1366 } | |
1367 | |
1368 TEST_F(TaskQueueManagerTest, UnregisterTaskQueue_WithDelayedTasks) { | |
1369 Initialize(2u); | |
1370 | |
1371 // Register three delayed tasks | |
1372 std::vector<EnqueueOrder> run_order; | |
1373 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
1374 base::TimeDelta::FromMilliseconds(10)); | |
1375 runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), | |
1376 base::TimeDelta::FromMilliseconds(20)); | |
1377 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), | |
1378 base::TimeDelta::FromMilliseconds(30)); | |
1379 | |
1380 runners_[1]->UnregisterTaskQueue(); | |
1381 test_task_runner_->RunUntilIdle(); | |
1382 | |
1383 test_task_runner_->RunForPeriod(base::TimeDelta::FromMilliseconds(40)); | |
1384 ASSERT_THAT(run_order, ElementsAre(1, 3)); | |
1385 } | |
1386 | |
1387 namespace { | |
1388 void UnregisterQueue(scoped_refptr<internal::TaskQueueImpl> queue) { | |
1389 queue->UnregisterTaskQueue(); | |
1390 } | |
1391 } | |
1392 | |
1393 TEST_F(TaskQueueManagerTest, UnregisterTaskQueue_InTasks) { | |
1394 Initialize(3u); | |
1395 | |
1396 std::vector<EnqueueOrder> run_order; | |
1397 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
1398 runners_[0]->PostTask(FROM_HERE, base::Bind(&UnregisterQueue, runners_[1])); | |
1399 runners_[0]->PostTask(FROM_HERE, base::Bind(&UnregisterQueue, runners_[2])); | |
1400 runners_[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order)); | |
1401 runners_[2]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order)); | |
1402 | |
1403 test_task_runner_->RunUntilIdle(); | |
1404 ASSERT_THAT(run_order, ElementsAre(1)); | |
1405 } | |
1406 | |
1407 void PostTestTasksFromNestedMessageLoop( | |
1408 base::MessageLoop* message_loop, | |
1409 scoped_refptr<base::SingleThreadTaskRunner> main_runner, | |
1410 scoped_refptr<base::SingleThreadTaskRunner> wake_up_runner, | |
1411 std::vector<EnqueueOrder>* run_order) { | |
1412 base::MessageLoop::ScopedNestableTaskAllower allow(message_loop); | |
1413 main_runner->PostNonNestableTask(FROM_HERE, | |
1414 base::Bind(&TestTask, 1, run_order)); | |
1415 // The following should never get executed. | |
1416 wake_up_runner->PostTask(FROM_HERE, base::Bind(&TestTask, 2, run_order)); | |
1417 base::RunLoop().RunUntilIdle(); | |
1418 } | |
1419 | |
1420 TEST_F(TaskQueueManagerTest, DeferredNonNestableTaskDoesNotTriggerWakeUp) { | |
1421 // This test checks that running (i.e., deferring) a non-nestable task in a | |
1422 // nested run loop does not trigger the pumping of an on-wakeup queue. | |
1423 InitializeWithRealMessageLoop(2u); | |
1424 runners_[1]->SetPumpPolicy(TaskQueue::PumpPolicy::AFTER_WAKEUP); | |
1425 | |
1426 std::vector<EnqueueOrder> run_order; | |
1427 runners_[0]->PostTask( | |
1428 FROM_HERE, | |
1429 base::Bind(&PostTestTasksFromNestedMessageLoop, message_loop_.get(), | |
1430 runners_[0], runners_[1], base::Unretained(&run_order))); | |
1431 | |
1432 base::RunLoop().RunUntilIdle(); | |
1433 ASSERT_THAT(run_order, ElementsAre(1)); | |
1434 } | |
1435 | |
1436 namespace { | |
1437 | |
1438 class MockObserver : public TaskQueueManager::Observer { | |
1439 public: | |
1440 MOCK_METHOD1(OnUnregisterTaskQueue, | |
1441 void(const scoped_refptr<TaskQueue>& queue)); | |
1442 MOCK_METHOD2(OnTriedToExecuteBlockedTask, | |
1443 void(const TaskQueue& queue, const base::PendingTask& task)); | |
1444 }; | |
1445 | |
1446 } // namespace | |
1447 | |
1448 TEST_F(TaskQueueManagerTest, OnUnregisterTaskQueue) { | |
1449 Initialize(0u); | |
1450 | |
1451 MockObserver observer; | |
1452 manager_->SetObserver(&observer); | |
1453 | |
1454 scoped_refptr<internal::TaskQueueImpl> task_queue = | |
1455 manager_->NewTaskQueue(TaskQueue::Spec("test_queue")); | |
1456 | |
1457 EXPECT_CALL(observer, OnUnregisterTaskQueue(_)).Times(1); | |
1458 task_queue->UnregisterTaskQueue(); | |
1459 | |
1460 manager_->SetObserver(nullptr); | |
1461 } | |
1462 | |
1463 TEST_F(TaskQueueManagerTest, OnTriedToExecuteBlockedTask) { | |
1464 Initialize(0u); | |
1465 | |
1466 MockObserver observer; | |
1467 manager_->SetObserver(&observer); | |
1468 | |
1469 scoped_refptr<internal::TaskQueueImpl> task_queue = manager_->NewTaskQueue( | |
1470 TaskQueue::Spec("test_queue").SetShouldReportWhenExecutionBlocked(true)); | |
1471 task_queue->SetQueueEnabled(false); | |
1472 task_queue->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
1473 | |
1474 EXPECT_CALL(observer, OnTriedToExecuteBlockedTask(_, _)).Times(1); | |
1475 test_task_runner_->RunPendingTasks(); | |
1476 | |
1477 manager_->SetObserver(nullptr); | |
1478 } | |
1479 | |
1480 TEST_F(TaskQueueManagerTest, ExecutedNonBlockedTask) { | |
1481 Initialize(0u); | |
1482 | |
1483 MockObserver observer; | |
1484 manager_->SetObserver(&observer); | |
1485 | |
1486 scoped_refptr<internal::TaskQueueImpl> task_queue = manager_->NewTaskQueue( | |
1487 TaskQueue::Spec("test_queue").SetShouldReportWhenExecutionBlocked(true)); | |
1488 task_queue->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
1489 | |
1490 EXPECT_CALL(observer, OnTriedToExecuteBlockedTask(_, _)).Times(0); | |
1491 test_task_runner_->RunPendingTasks(); | |
1492 | |
1493 manager_->SetObserver(nullptr); | |
1494 } | |
1495 | |
1496 void HasOneRefTask(std::vector<bool>* log, internal::TaskQueueImpl* tq) { | |
1497 log->push_back(tq->HasOneRef()); | |
1498 } | |
1499 | |
1500 TEST_F(TaskQueueManagerTest, UnregisterTaskQueueInNestedLoop) { | |
1501 InitializeWithRealMessageLoop(1u); | |
1502 | |
1503 // We retain a reference to the task queue even when the manager has deleted | |
1504 // its reference. | |
1505 scoped_refptr<internal::TaskQueueImpl> task_queue = | |
1506 manager_->NewTaskQueue(TaskQueue::Spec("test_queue")); | |
1507 | |
1508 std::vector<bool> log; | |
1509 std::vector<std::pair<base::Closure, bool>> tasks_to_post_from_nested_loop; | |
1510 | |
1511 // Inside a nested run loop, call task_queue->UnregisterTaskQueue, bookended | |
1512 // by calls to HasOneRefTask to make sure the manager doesn't release its | |
1513 // reference until the nested run loop exits. | |
1514 // NB: This first HasOneRefTask is a sanity check. | |
1515 tasks_to_post_from_nested_loop.push_back( | |
1516 std::make_pair(base::Bind(&HasOneRefTask, base::Unretained(&log), | |
1517 base::Unretained(task_queue.get())), | |
1518 true)); | |
1519 tasks_to_post_from_nested_loop.push_back(std::make_pair( | |
1520 base::Bind(&internal::TaskQueueImpl::UnregisterTaskQueue, | |
1521 base::Unretained(task_queue.get())), true)); | |
1522 tasks_to_post_from_nested_loop.push_back( | |
1523 std::make_pair(base::Bind(&HasOneRefTask, base::Unretained(&log), | |
1524 base::Unretained(task_queue.get())), | |
1525 true)); | |
1526 runners_[0]->PostTask( | |
1527 FROM_HERE, base::Bind(&PostFromNestedRunloop, message_loop_.get(), | |
1528 base::RetainedRef(runners_[0]), | |
1529 base::Unretained(&tasks_to_post_from_nested_loop))); | |
1530 base::RunLoop().RunUntilIdle(); | |
1531 | |
1532 // Add a final call to HasOneRefTask. This gives the manager a chance to | |
1533 // release its reference, and checks that it has. | |
1534 runners_[0]->PostTask(FROM_HERE, | |
1535 base::Bind(&HasOneRefTask, base::Unretained(&log), | |
1536 base::Unretained(task_queue.get()))); | |
1537 base::RunLoop().RunUntilIdle(); | |
1538 | |
1539 EXPECT_THAT(log, ElementsAre(false, false, true)); | |
1540 } | |
1541 | |
1542 TEST_F(TaskQueueManagerTest, TimeDomainsAreIndependant) { | |
1543 Initialize(2u); | |
1544 | |
1545 base::TimeTicks start_time = manager_->delegate()->NowTicks(); | |
1546 std::unique_ptr<VirtualTimeDomain> domain_a( | |
1547 new VirtualTimeDomain(nullptr, start_time)); | |
1548 std::unique_ptr<VirtualTimeDomain> domain_b( | |
1549 new VirtualTimeDomain(nullptr, start_time)); | |
1550 manager_->RegisterTimeDomain(domain_a.get()); | |
1551 manager_->RegisterTimeDomain(domain_b.get()); | |
1552 runners_[0]->SetTimeDomain(domain_a.get()); | |
1553 runners_[1]->SetTimeDomain(domain_b.get()); | |
1554 | |
1555 std::vector<EnqueueOrder> run_order; | |
1556 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
1557 base::TimeDelta::FromMilliseconds(10)); | |
1558 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), | |
1559 base::TimeDelta::FromMilliseconds(20)); | |
1560 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), | |
1561 base::TimeDelta::FromMilliseconds(30)); | |
1562 | |
1563 runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order), | |
1564 base::TimeDelta::FromMilliseconds(10)); | |
1565 runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 5, &run_order), | |
1566 base::TimeDelta::FromMilliseconds(20)); | |
1567 runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 6, &run_order), | |
1568 base::TimeDelta::FromMilliseconds(30)); | |
1569 | |
1570 domain_b->AdvanceTo(start_time + base::TimeDelta::FromMilliseconds(50)); | |
1571 manager_->MaybeScheduleImmediateWork(FROM_HERE); | |
1572 | |
1573 test_task_runner_->RunUntilIdle(); | |
1574 EXPECT_THAT(run_order, ElementsAre(4, 5, 6)); | |
1575 | |
1576 domain_a->AdvanceTo(start_time + base::TimeDelta::FromMilliseconds(50)); | |
1577 manager_->MaybeScheduleImmediateWork(FROM_HERE); | |
1578 | |
1579 test_task_runner_->RunUntilIdle(); | |
1580 EXPECT_THAT(run_order, ElementsAre(4, 5, 6, 1, 2, 3)); | |
1581 | |
1582 runners_[0]->UnregisterTaskQueue(); | |
1583 runners_[1]->UnregisterTaskQueue(); | |
1584 | |
1585 manager_->UnregisterTimeDomain(domain_a.get()); | |
1586 manager_->UnregisterTimeDomain(domain_b.get()); | |
1587 } | |
1588 | |
1589 TEST_F(TaskQueueManagerTest, TimeDomainMigration) { | |
1590 Initialize(1u); | |
1591 | |
1592 base::TimeTicks start_time = manager_->delegate()->NowTicks(); | |
1593 std::unique_ptr<VirtualTimeDomain> domain_a( | |
1594 new VirtualTimeDomain(nullptr, start_time)); | |
1595 manager_->RegisterTimeDomain(domain_a.get()); | |
1596 runners_[0]->SetTimeDomain(domain_a.get()); | |
1597 | |
1598 std::vector<EnqueueOrder> run_order; | |
1599 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order), | |
1600 base::TimeDelta::FromMilliseconds(10)); | |
1601 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order), | |
1602 base::TimeDelta::FromMilliseconds(20)); | |
1603 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order), | |
1604 base::TimeDelta::FromMilliseconds(30)); | |
1605 runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order), | |
1606 base::TimeDelta::FromMilliseconds(40)); | |
1607 | |
1608 domain_a->AdvanceTo(start_time + base::TimeDelta::FromMilliseconds(20)); | |
1609 manager_->MaybeScheduleImmediateWork(FROM_HERE); | |
1610 test_task_runner_->RunUntilIdle(); | |
1611 EXPECT_THAT(run_order, ElementsAre(1, 2)); | |
1612 | |
1613 std::unique_ptr<VirtualTimeDomain> domain_b( | |
1614 new VirtualTimeDomain(nullptr, start_time)); | |
1615 manager_->RegisterTimeDomain(domain_b.get()); | |
1616 runners_[0]->SetTimeDomain(domain_b.get()); | |
1617 | |
1618 domain_b->AdvanceTo(start_time + base::TimeDelta::FromMilliseconds(50)); | |
1619 manager_->MaybeScheduleImmediateWork(FROM_HERE); | |
1620 | |
1621 test_task_runner_->RunUntilIdle(); | |
1622 EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4)); | |
1623 | |
1624 runners_[0]->UnregisterTaskQueue(); | |
1625 | |
1626 manager_->UnregisterTimeDomain(domain_a.get()); | |
1627 manager_->UnregisterTimeDomain(domain_b.get()); | |
1628 } | |
1629 | |
1630 TEST_F(TaskQueueManagerTest, TimeDomainMigrationWithIncomingImmediateTasks) { | |
1631 Initialize(1u); | |
1632 | |
1633 base::TimeTicks start_time = manager_->delegate()->NowTicks(); | |
1634 std::unique_ptr<VirtualTimeDomain> domain_a( | |
1635 new VirtualTimeDomain(nullptr, start_time)); | |
1636 std::unique_ptr<VirtualTimeDomain> domain_b( | |
1637 new VirtualTimeDomain(nullptr, start_time)); | |
1638 manager_->RegisterTimeDomain(domain_a.get()); | |
1639 manager_->RegisterTimeDomain(domain_b.get()); | |
1640 | |
1641 runners_[0]->SetTimeDomain(domain_a.get()); | |
1642 std::vector<EnqueueOrder> run_order; | |
1643 runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); | |
1644 runners_[0]->SetTimeDomain(domain_b.get()); | |
1645 | |
1646 test_task_runner_->RunUntilIdle(); | |
1647 EXPECT_THAT(run_order, ElementsAre(1)); | |
1648 | |
1649 runners_[0]->UnregisterTaskQueue(); | |
1650 | |
1651 manager_->UnregisterTimeDomain(domain_a.get()); | |
1652 manager_->UnregisterTimeDomain(domain_b.get()); | |
1653 } | |
1654 | |
1655 namespace { | |
1656 void ChromiumRunloopInspectionTask( | |
1657 scoped_refptr<cc::OrderedSimpleTaskRunner> test_task_runner) { | |
1658 EXPECT_EQ(1u, test_task_runner->NumPendingTasks()); | |
1659 } | |
1660 } // namespace | |
1661 | |
1662 TEST_F(TaskQueueManagerTest, NumberOfPendingTasksOnChromiumRunLoop) { | |
1663 Initialize(1u); | |
1664 | |
1665 // NOTE because tasks posted to the chromiumrun loop are not cancellable, we | |
1666 // will end up with a lot more tasks posted if the delayed tasks were posted | |
1667 // in the reverse order. | |
1668 // TODO(alexclarke): Consider talking to the message pump directly. | |
1669 test_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
1670 for (int i = 1; i < 100; i++) { | |
1671 runners_[0]->PostDelayedTask( | |
1672 FROM_HERE, | |
1673 base::Bind(&ChromiumRunloopInspectionTask, test_task_runner_), | |
1674 base::TimeDelta::FromMilliseconds(i)); | |
1675 } | |
1676 test_task_runner_->RunUntilIdle(); | |
1677 } | |
1678 | |
1679 namespace { | |
1680 | |
1681 class QuadraticTask { | |
1682 public: | |
1683 QuadraticTask(scoped_refptr<internal::TaskQueueImpl> task_queue, | |
1684 base::TimeDelta delay, | |
1685 base::SimpleTestTickClock* now_src) | |
1686 : count_(0), task_queue_(task_queue), delay_(delay), now_src_(now_src) {} | |
1687 | |
1688 void SetShouldExit(base::Callback<bool()> should_exit) { | |
1689 should_exit_ = should_exit; | |
1690 } | |
1691 | |
1692 void Run() { | |
1693 if (should_exit_.Run()) | |
1694 return; | |
1695 count_++; | |
1696 task_queue_->PostDelayedTask( | |
1697 FROM_HERE, base::Bind(&QuadraticTask::Run, base::Unretained(this)), | |
1698 delay_); | |
1699 task_queue_->PostDelayedTask( | |
1700 FROM_HERE, base::Bind(&QuadraticTask::Run, base::Unretained(this)), | |
1701 delay_); | |
1702 now_src_->Advance(base::TimeDelta::FromMilliseconds(5)); | |
1703 } | |
1704 | |
1705 int count() const { return count_; } | |
1706 | |
1707 private: | |
1708 int count_; | |
1709 scoped_refptr<internal::TaskQueueImpl> task_queue_; | |
1710 base::TimeDelta delay_; | |
1711 base::Callback<bool()> should_exit_; | |
1712 base::SimpleTestTickClock* now_src_; | |
1713 }; | |
1714 | |
1715 class LinearTask { | |
1716 public: | |
1717 LinearTask(scoped_refptr<internal::TaskQueueImpl> task_queue, | |
1718 base::TimeDelta delay, | |
1719 base::SimpleTestTickClock* now_src) | |
1720 : count_(0), task_queue_(task_queue), delay_(delay), now_src_(now_src) {} | |
1721 | |
1722 void SetShouldExit(base::Callback<bool()> should_exit) { | |
1723 should_exit_ = should_exit; | |
1724 } | |
1725 | |
1726 void Run() { | |
1727 if (should_exit_.Run()) | |
1728 return; | |
1729 count_++; | |
1730 task_queue_->PostDelayedTask( | |
1731 FROM_HERE, base::Bind(&LinearTask::Run, base::Unretained(this)), | |
1732 delay_); | |
1733 now_src_->Advance(base::TimeDelta::FromMilliseconds(5)); | |
1734 } | |
1735 | |
1736 int count() const { return count_; } | |
1737 | |
1738 private: | |
1739 int count_; | |
1740 scoped_refptr<internal::TaskQueueImpl> task_queue_; | |
1741 base::TimeDelta delay_; | |
1742 base::Callback<bool()> should_exit_; | |
1743 base::SimpleTestTickClock* now_src_; | |
1744 }; | |
1745 | |
1746 bool ShouldExit(QuadraticTask* quadratic_task, LinearTask* linear_task) { | |
1747 return quadratic_task->count() == 1000 || linear_task->count() == 1000; | |
1748 } | |
1749 | |
1750 } // namespace | |
1751 | |
1752 TEST_F(TaskQueueManagerTest, | |
1753 DelayedTasksDontBadlyStarveNonDelayedWork_SameQueue) { | |
1754 Initialize(1u); | |
1755 | |
1756 QuadraticTask quadratic_delayed_task( | |
1757 runners_[0], base::TimeDelta::FromMilliseconds(10), now_src_.get()); | |
1758 LinearTask linear_immediate_task(runners_[0], base::TimeDelta(), | |
1759 now_src_.get()); | |
1760 base::Callback<bool()> should_exit = | |
1761 base::Bind(ShouldExit, &quadratic_delayed_task, &linear_immediate_task); | |
1762 quadratic_delayed_task.SetShouldExit(should_exit); | |
1763 linear_immediate_task.SetShouldExit(should_exit); | |
1764 | |
1765 quadratic_delayed_task.Run(); | |
1766 linear_immediate_task.Run(); | |
1767 | |
1768 test_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
1769 test_task_runner_->RunUntilIdle(); | |
1770 | |
1771 double ratio = static_cast<double>(linear_immediate_task.count()) / | |
1772 static_cast<double>(quadratic_delayed_task.count()); | |
1773 | |
1774 EXPECT_GT(ratio, 0.333); | |
1775 EXPECT_LT(ratio, 1.1); | |
1776 } | |
1777 | |
1778 TEST_F(TaskQueueManagerTest, ImmediateWorkCanStarveDelayedTasks_SameQueue) { | |
1779 Initialize(1u); | |
1780 | |
1781 QuadraticTask quadratic_immediate_task(runners_[0], base::TimeDelta(), | |
1782 now_src_.get()); | |
1783 LinearTask linear_delayed_task( | |
1784 runners_[0], base::TimeDelta::FromMilliseconds(10), now_src_.get()); | |
1785 base::Callback<bool()> should_exit = | |
1786 base::Bind(&ShouldExit, &quadratic_immediate_task, &linear_delayed_task); | |
1787 | |
1788 quadratic_immediate_task.SetShouldExit(should_exit); | |
1789 linear_delayed_task.SetShouldExit(should_exit); | |
1790 | |
1791 quadratic_immediate_task.Run(); | |
1792 linear_delayed_task.Run(); | |
1793 | |
1794 test_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
1795 test_task_runner_->RunUntilIdle(); | |
1796 | |
1797 double ratio = static_cast<double>(linear_delayed_task.count()) / | |
1798 static_cast<double>(quadratic_immediate_task.count()); | |
1799 | |
1800 // This is by design, we want to enforce a strict ordering in task execution | |
1801 // where by delayed tasks can not skip ahead of non-delayed work. | |
1802 EXPECT_GT(ratio, 0.0); | |
1803 EXPECT_LT(ratio, 0.1); | |
1804 } | |
1805 | |
1806 TEST_F(TaskQueueManagerTest, | |
1807 DelayedTasksDontBadlyStarveNonDelayedWork_DifferentQueue) { | |
1808 Initialize(2u); | |
1809 | |
1810 QuadraticTask quadratic_delayed_task( | |
1811 runners_[0], base::TimeDelta::FromMilliseconds(10), now_src_.get()); | |
1812 LinearTask linear_immediate_task(runners_[1], base::TimeDelta(), | |
1813 now_src_.get()); | |
1814 base::Callback<bool()> should_exit = | |
1815 base::Bind(ShouldExit, &quadratic_delayed_task, &linear_immediate_task); | |
1816 quadratic_delayed_task.SetShouldExit(should_exit); | |
1817 linear_immediate_task.SetShouldExit(should_exit); | |
1818 | |
1819 quadratic_delayed_task.Run(); | |
1820 linear_immediate_task.Run(); | |
1821 | |
1822 test_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
1823 test_task_runner_->RunUntilIdle(); | |
1824 | |
1825 double ratio = static_cast<double>(linear_immediate_task.count()) / | |
1826 static_cast<double>(quadratic_delayed_task.count()); | |
1827 | |
1828 EXPECT_GT(ratio, 0.333); | |
1829 EXPECT_LT(ratio, 1.1); | |
1830 } | |
1831 | |
1832 TEST_F(TaskQueueManagerTest, | |
1833 ImmediateWorkCanStarveDelayedTasks_DifferentQueue) { | |
1834 Initialize(2u); | |
1835 | |
1836 QuadraticTask quadratic_immediate_task(runners_[0], base::TimeDelta(), | |
1837 now_src_.get()); | |
1838 LinearTask linear_delayed_task( | |
1839 runners_[1], base::TimeDelta::FromMilliseconds(10), now_src_.get()); | |
1840 base::Callback<bool()> should_exit = | |
1841 base::Bind(&ShouldExit, &quadratic_immediate_task, &linear_delayed_task); | |
1842 | |
1843 quadratic_immediate_task.SetShouldExit(should_exit); | |
1844 linear_delayed_task.SetShouldExit(should_exit); | |
1845 | |
1846 quadratic_immediate_task.Run(); | |
1847 linear_delayed_task.Run(); | |
1848 | |
1849 test_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
1850 test_task_runner_->RunUntilIdle(); | |
1851 | |
1852 double ratio = static_cast<double>(linear_delayed_task.count()) / | |
1853 static_cast<double>(quadratic_immediate_task.count()); | |
1854 | |
1855 // This is by design, we want to enforce a strict ordering in task execution | |
1856 // where by delayed tasks can not skip ahead of non-delayed work. | |
1857 EXPECT_GT(ratio, 0.0); | |
1858 EXPECT_LT(ratio, 0.1); | |
1859 } | |
1860 | |
1861 TEST_F(TaskQueueManagerTest, CurrentlyExecutingTaskQueue_NoTaskRunning) { | |
1862 Initialize(1u); | |
1863 | |
1864 EXPECT_EQ(nullptr, manager_->currently_executing_task_queue()); | |
1865 } | |
1866 | |
1867 namespace { | |
1868 void CurrentlyExecutingTaskQueueTestTask(TaskQueueManager* task_queue_manager, | |
1869 std::vector<TaskQueue*>* task_sources) { | |
1870 task_sources->push_back(task_queue_manager->currently_executing_task_queue()); | |
1871 } | |
1872 } | |
1873 | |
1874 TEST_F(TaskQueueManagerTest, CurrentlyExecutingTaskQueue_TaskRunning) { | |
1875 Initialize(2u); | |
1876 | |
1877 internal::TaskQueueImpl* queue0 = runners_[0].get(); | |
1878 internal::TaskQueueImpl* queue1 = runners_[1].get(); | |
1879 | |
1880 std::vector<TaskQueue*> task_sources; | |
1881 queue0->PostTask(FROM_HERE, base::Bind(&CurrentlyExecutingTaskQueueTestTask, | |
1882 manager_.get(), &task_sources)); | |
1883 queue1->PostTask(FROM_HERE, base::Bind(&CurrentlyExecutingTaskQueueTestTask, | |
1884 manager_.get(), &task_sources)); | |
1885 test_task_runner_->RunUntilIdle(); | |
1886 | |
1887 EXPECT_THAT(task_sources, ElementsAre(queue0, queue1)); | |
1888 EXPECT_EQ(nullptr, manager_->currently_executing_task_queue()); | |
1889 } | |
1890 | |
1891 namespace { | |
1892 void RunloopCurrentlyExecutingTaskQueueTestTask( | |
1893 base::MessageLoop* message_loop, | |
1894 TaskQueueManager* task_queue_manager, | |
1895 std::vector<TaskQueue*>* task_sources, | |
1896 std::vector<std::pair<base::Closure, TaskQueue*>>* tasks) { | |
1897 base::MessageLoop::ScopedNestableTaskAllower allow(message_loop); | |
1898 task_sources->push_back(task_queue_manager->currently_executing_task_queue()); | |
1899 | |
1900 for (std::pair<base::Closure, TaskQueue*>& pair : *tasks) { | |
1901 pair.second->PostTask(FROM_HERE, pair.first); | |
1902 } | |
1903 | |
1904 base::RunLoop().RunUntilIdle(); | |
1905 task_sources->push_back(task_queue_manager->currently_executing_task_queue()); | |
1906 } | |
1907 } | |
1908 | |
1909 TEST_F(TaskQueueManagerTest, CurrentlyExecutingTaskQueue_NestedLoop) { | |
1910 InitializeWithRealMessageLoop(3u); | |
1911 | |
1912 TaskQueue* queue0 = runners_[0].get(); | |
1913 TaskQueue* queue1 = runners_[1].get(); | |
1914 TaskQueue* queue2 = runners_[2].get(); | |
1915 | |
1916 std::vector<TaskQueue*> task_sources; | |
1917 std::vector<std::pair<base::Closure, TaskQueue*>> | |
1918 tasks_to_post_from_nested_loop; | |
1919 tasks_to_post_from_nested_loop.push_back( | |
1920 std::make_pair(base::Bind(&CurrentlyExecutingTaskQueueTestTask, | |
1921 manager_.get(), &task_sources), | |
1922 queue1)); | |
1923 tasks_to_post_from_nested_loop.push_back( | |
1924 std::make_pair(base::Bind(&CurrentlyExecutingTaskQueueTestTask, | |
1925 manager_.get(), &task_sources), | |
1926 queue2)); | |
1927 | |
1928 queue0->PostTask( | |
1929 FROM_HERE, base::Bind(&RunloopCurrentlyExecutingTaskQueueTestTask, | |
1930 message_loop_.get(), manager_.get(), &task_sources, | |
1931 &tasks_to_post_from_nested_loop)); | |
1932 | |
1933 base::RunLoop().RunUntilIdle(); | |
1934 EXPECT_THAT(task_sources, ElementsAre(queue0, queue1, queue2, queue0)); | |
1935 EXPECT_EQ(nullptr, manager_->currently_executing_task_queue()); | |
1936 } | |
1937 | |
1938 void OnTraceDataCollected(base::Closure quit_closure, | |
1939 base::trace_event::TraceResultBuffer* buffer, | |
1940 const scoped_refptr<base::RefCountedString>& json, | |
1941 bool has_more_events) { | |
1942 buffer->AddFragment(json->data()); | |
1943 if (!has_more_events) | |
1944 quit_closure.Run(); | |
1945 } | |
1946 | |
1947 class TaskQueueManagerTestWithTracing : public TaskQueueManagerTest { | |
1948 public: | |
1949 void StartTracing(); | |
1950 void StopTracing(); | |
1951 std::unique_ptr<trace_analyzer::TraceAnalyzer> CreateTraceAnalyzer(); | |
1952 }; | |
1953 | |
1954 void TaskQueueManagerTestWithTracing::StartTracing() { | |
1955 base::trace_event::TraceLog::GetInstance()->SetEnabled( | |
1956 base::trace_event::TraceConfig("*"), | |
1957 base::trace_event::TraceLog::RECORDING_MODE); | |
1958 } | |
1959 | |
1960 void TaskQueueManagerTestWithTracing::StopTracing() { | |
1961 base::trace_event::TraceLog::GetInstance()->SetDisabled(); | |
1962 } | |
1963 | |
1964 std::unique_ptr<trace_analyzer::TraceAnalyzer> | |
1965 TaskQueueManagerTestWithTracing::CreateTraceAnalyzer() { | |
1966 base::trace_event::TraceResultBuffer buffer; | |
1967 base::trace_event::TraceResultBuffer::SimpleOutput trace_output; | |
1968 buffer.SetOutputCallback(trace_output.GetCallback()); | |
1969 base::RunLoop run_loop; | |
1970 buffer.Start(); | |
1971 base::trace_event::TraceLog::GetInstance()->Flush( | |
1972 Bind(&OnTraceDataCollected, run_loop.QuitClosure(), | |
1973 base::Unretained(&buffer))); | |
1974 run_loop.Run(); | |
1975 buffer.Finish(); | |
1976 | |
1977 return base::WrapUnique( | |
1978 trace_analyzer::TraceAnalyzer::Create(trace_output.json_output)); | |
1979 } | |
1980 | |
1981 TEST_F(TaskQueueManagerTestWithTracing, BlameContextAttribution) { | |
1982 using trace_analyzer::Query; | |
1983 | |
1984 InitializeWithRealMessageLoop(1u); | |
1985 TaskQueue* queue = runners_[0].get(); | |
1986 | |
1987 StartTracing(); | |
1988 { | |
1989 base::trace_event::BlameContext blame_context("cat", "name", "type", | |
1990 "scope", 0, nullptr); | |
1991 blame_context.Initialize(); | |
1992 queue->SetBlameContext(&blame_context); | |
1993 queue->PostTask(FROM_HERE, base::Bind(&NopTask)); | |
1994 base::RunLoop().RunUntilIdle(); | |
1995 } | |
1996 StopTracing(); | |
1997 std::unique_ptr<trace_analyzer::TraceAnalyzer> analyzer = | |
1998 CreateTraceAnalyzer(); | |
1999 | |
2000 trace_analyzer::TraceEventVector events; | |
2001 Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_ENTER_CONTEXT) || | |
2002 Query::EventPhaseIs(TRACE_EVENT_PHASE_LEAVE_CONTEXT); | |
2003 analyzer->FindEvents(q, &events); | |
2004 | |
2005 EXPECT_EQ(2u, events.size()); | |
2006 } | |
2007 | |
2008 } // namespace scheduler | |
OLD | NEW |