| 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 |