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