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

Unified Diff: base/task/task_queue_manager_unittest.cc

Issue 637303003: content: Add task queue manager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Strip out everything else than TaskQueueManager. Added tests. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/task/task_queue_manager_unittest.cc
diff --git a/base/task/task_queue_manager_unittest.cc b/base/task/task_queue_manager_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9adea94c8f406ecf41ab909433978f1480c09d8f
--- /dev/null
+++ b/base/task/task_queue_manager_unittest.cc
@@ -0,0 +1,307 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/task/task_queue_manager.h"
+
+#include "base/task/task_queue_scheduler.h"
+#include "base/test/test_simple_task_runner.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace {
+
+class SchedulerForTest : public TaskQueueScheduler {
+ public:
+ SchedulerForTest() {}
+
+ virtual void RegisterWorkQueues(
+ const std::vector<const TaskQueue*>& work_queues) override {
+ work_queues_ = work_queues;
+ }
+
+ virtual bool ChooseWorkQueueToService(size_t* out_queue_index) override {
+ if (queues_to_service_.empty())
+ return false;
+ *out_queue_index = queues_to_service_.front();
+ queues_to_service_.pop_front();
+ return true;
+ }
+
+ void AppendQueueToService(size_t queue_index) {
+ queues_to_service_.push_back(queue_index);
+ }
+
+ const std::vector<const TaskQueue*>& work_queues() { return work_queues_; }
+
+ private:
+ std::deque<size_t> queues_to_service_;
+ std::vector<const base::TaskQueue*> work_queues_;
+};
+
+class TaskQueueManagerTest : public testing::Test {
+ public:
+ protected:
+ void Initialize(size_t num_queues) {
+ test_task_runner_ = make_scoped_refptr(new TestSimpleTaskRunner());
+ scheduler_ = make_scoped_ptr(new SchedulerForTest);
+ manager_ = make_scoped_ptr(
+ new TaskQueueManager(num_queues, test_task_runner_, scheduler_.get()));
+ }
+
+ scoped_refptr<TestSimpleTaskRunner> test_task_runner_;
+ scoped_ptr<SchedulerForTest> scheduler_;
+ scoped_ptr<TaskQueueManager> manager_;
+};
+
+void TestTask(int value, std::vector<int>* out_result) {
+ out_result->push_back(value);
+}
+
+TEST_F(TaskQueueManagerTest, SingleQueuePosting) {
+ Initialize(1u);
+ EXPECT_EQ(1u, scheduler_->work_queues().size());
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ runner->PostTask(FROM_HERE, Bind(&TestTask, 1, &run_order));
+ runner->PostTask(FROM_HERE, Bind(&TestTask, 2, &run_order));
+ runner->PostTask(FROM_HERE, Bind(&TestTask, 3, &run_order));
+
+ scheduler_->AppendQueueToService(0);
+ scheduler_->AppendQueueToService(0);
+ scheduler_->AppendQueueToService(0);
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+ EXPECT_EQ(2, run_order[1]);
+ EXPECT_EQ(3, run_order[2]);
+}
+
+TEST_F(TaskQueueManagerTest, MultiQueuePosting) {
+ Initialize(3u);
+ EXPECT_EQ(3u, scheduler_->work_queues().size());
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runners[3] = {
+ manager_->TaskRunnerForQueue(0),
+ manager_->TaskRunnerForQueue(1),
+ manager_->TaskRunnerForQueue(2)};
+
+ scheduler_->AppendQueueToService(0);
+ scheduler_->AppendQueueToService(1);
+ scheduler_->AppendQueueToService(2);
+ scheduler_->AppendQueueToService(0);
+ scheduler_->AppendQueueToService(1);
+ scheduler_->AppendQueueToService(2);
+
+ runners[0]->PostTask(FROM_HERE, Bind(&TestTask, 1, &run_order));
+ runners[0]->PostTask(FROM_HERE, Bind(&TestTask, 2, &run_order));
+ runners[1]->PostTask(FROM_HERE, Bind(&TestTask, 3, &run_order));
+ runners[1]->PostTask(FROM_HERE, Bind(&TestTask, 4, &run_order));
+ runners[2]->PostTask(FROM_HERE, Bind(&TestTask, 5, &run_order));
+ runners[2]->PostTask(FROM_HERE, Bind(&TestTask, 6, &run_order));
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+ EXPECT_EQ(3, run_order[1]);
+ EXPECT_EQ(5, run_order[2]);
+ EXPECT_EQ(2, run_order[3]);
+ EXPECT_EQ(4, run_order[4]);
+ EXPECT_EQ(6, run_order[5]);
+}
+
+TEST_F(TaskQueueManagerTest, NonNestableTaskPosting) {
+ Initialize(1u);
+ EXPECT_EQ(1u, scheduler_->work_queues().size());
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ runner->PostNonNestableTask(FROM_HERE, Bind(&TestTask, 1, &run_order));
+
+ // Non-nestable tasks never make it to the scheduler.
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, QueuePolling) {
+ Initialize(1u);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ EXPECT_FALSE(manager_->PollQueue(0));
+ runner->PostTask(FROM_HERE, Bind(&TestTask, 1, &run_order));
+ EXPECT_TRUE(manager_->PollQueue(0));
+
+ scheduler_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_FALSE(manager_->PollQueue(0));
+}
+
+TEST_F(TaskQueueManagerTest, DelayedTaskPosting) {
+ Initialize(1u);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ scheduler_->AppendQueueToService(0);
+
+ TimeDelta delay(TimeDelta::FromMilliseconds(10));
+ runner->PostDelayedTask(FROM_HERE, Bind(&TestTask, 1, &run_order), delay);
+ EXPECT_EQ(delay, test_task_runner_->NextPendingTaskDelay());
+ EXPECT_FALSE(manager_->PollQueue(0));
+ EXPECT_TRUE(run_order.empty());
+
+ // The task is inserted to the incoming queue only after the delay.
+ test_task_runner_->RunPendingTasks();
+ EXPECT_TRUE(manager_->PollQueue(0));
+ EXPECT_TRUE(run_order.empty());
+
+ // After the delay the task runs normally.
+ scheduler_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, ManualPumping) {
+ Initialize(1u);
+ manager_->SetAutoPump(0, false);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ // Posting a task when pumping is disabled doesn't result in work getting
+ // posted.
+ runner->PostTask(FROM_HERE, Bind(&TestTask, 1, &run_order));
+ EXPECT_FALSE(test_task_runner_->HasPendingTask());
+
+ // However polling still works.
+ EXPECT_TRUE(manager_->PollQueue(0));
+
+ // After pumping the task runs normally.
+ manager_->PumpQueue(0);
+ EXPECT_TRUE(test_task_runner_->HasPendingTask());
+ scheduler_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, ManualPumpingToggle) {
+ Initialize(1u);
+ manager_->SetAutoPump(0, false);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ // Posting a task when pumping is disabled doesn't result in work getting
+ // posted.
+ runner->PostTask(FROM_HERE, Bind(&TestTask, 1, &run_order));
+ EXPECT_FALSE(test_task_runner_->HasPendingTask());
+
+ // When pumping is enabled the task runs normally.
+ manager_->SetAutoPump(0, true);
+ EXPECT_TRUE(test_task_runner_->HasPendingTask());
+ scheduler_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, DenyRunning) {
+ Initialize(1u);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+ runner->PostTask(FROM_HERE, Bind(&TestTask, 1, &run_order));
+
+ // Since we haven't scheduled a work queue to be selected, the task doesn't
+ // run.
+ test_task_runner_->RunUntilIdle();
+ EXPECT_TRUE(run_order.empty());
+
+ // Pumping the queue again with a scheduled work queue runs the task.
+ manager_->PumpQueue(0);
+ scheduler_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, ManualPumpingWithDelayedTask) {
+ Initialize(1u);
+ manager_->SetAutoPump(0, false);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ // Posting a delayed task when pumping will apply the delay, but won't cause
+ // work to executed afterwards.
+ TimeDelta delay(TimeDelta::FromMilliseconds(10));
+ runner->PostDelayedTask(FROM_HERE, Bind(&TestTask, 1, &run_order), delay);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_TRUE(run_order.empty());
+
+ // After pumping the task runs normally.
+ manager_->PumpQueue(0);
+ EXPECT_TRUE(test_task_runner_->HasPendingTask());
+ scheduler_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+void ReentrantTestTask(scoped_refptr<base::SingleThreadTaskRunner> runner,
+ int countdown,
+ std::vector<int>* out_result) {
+ out_result->push_back(countdown);
+ if (--countdown) {
+ runner->PostTask(FROM_HERE,
+ Bind(&ReentrantTestTask, runner, countdown, out_result));
+ }
+}
+
+TEST_F(TaskQueueManagerTest, ReentrantPosting) {
+ Initialize(1u);
+ EXPECT_EQ(1u, scheduler_->work_queues().size());
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ runner->PostTask(FROM_HERE, Bind(&ReentrantTestTask, runner, 3, &run_order));
+
+ scheduler_->AppendQueueToService(0);
+ scheduler_->AppendQueueToService(0);
+ scheduler_->AppendQueueToService(0);
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(3, run_order[0]);
+ EXPECT_EQ(2, run_order[1]);
+ EXPECT_EQ(1, run_order[2]);
+}
+
+TEST_F(TaskQueueManagerTest, NoTasksAfterShutdown) {
+ Initialize(1u);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ runner->PostTask(FROM_HERE, Bind(&TestTask, 1, &run_order));
+ manager_.reset();
+ scheduler_.reset();
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_TRUE(run_order.empty());
+}
+
+} // namespace
+} // namespace base

Powered by Google App Engine
This is Rietveld 408576698