| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013 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 "cc/base/worker_pool.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "cc/base/completion_event.h" | |
| 10 #include "testing/gtest/include/gtest/gtest.h" | |
| 11 | |
| 12 namespace cc { | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 class FakeTaskImpl : public internal::WorkerPoolTask { | |
| 17 public: | |
| 18 FakeTaskImpl(const base::Closure& callback, | |
| 19 const base::Closure& reply, | |
| 20 internal::WorkerPoolTask::TaskVector* dependencies) | |
| 21 : internal::WorkerPoolTask(dependencies), | |
| 22 callback_(callback), | |
| 23 reply_(reply) { | |
| 24 } | |
| 25 FakeTaskImpl(const base::Closure& callback, const base::Closure& reply) | |
| 26 : callback_(callback), | |
| 27 reply_(reply) { | |
| 28 } | |
| 29 | |
| 30 // Overridden from internal::WorkerPoolTask: | |
| 31 virtual void RunOnThread(unsigned thread_index) OVERRIDE { | |
| 32 if (!callback_.is_null()) | |
| 33 callback_.Run(); | |
| 34 } | |
| 35 virtual void DispatchCompletionCallback() OVERRIDE { | |
| 36 if (!reply_.is_null()) | |
| 37 reply_.Run(); | |
| 38 } | |
| 39 | |
| 40 private: | |
| 41 virtual ~FakeTaskImpl() {} | |
| 42 | |
| 43 const base::Closure callback_; | |
| 44 const base::Closure reply_; | |
| 45 }; | |
| 46 | |
| 47 class FakeWorkerPool : public WorkerPool { | |
| 48 public: | |
| 49 FakeWorkerPool() : WorkerPool(1, "test") {} | |
| 50 virtual ~FakeWorkerPool() {} | |
| 51 | |
| 52 static scoped_ptr<FakeWorkerPool> Create() { | |
| 53 return make_scoped_ptr(new FakeWorkerPool); | |
| 54 } | |
| 55 | |
| 56 void ScheduleTasks(const base::Closure& callback, | |
| 57 const base::Closure& reply, | |
| 58 const base::Closure& dependency, | |
| 59 int count) { | |
| 60 scoped_refptr<FakeTaskImpl> dependency_task( | |
| 61 new FakeTaskImpl(dependency, base::Closure())); | |
| 62 | |
| 63 internal::WorkerPoolTask::TaskVector tasks; | |
| 64 for (int i = 0; i < count; ++i) { | |
| 65 internal::WorkerPoolTask::TaskVector dependencies(1, dependency_task); | |
| 66 tasks.push_back(new FakeTaskImpl(callback, reply, &dependencies)); | |
| 67 } | |
| 68 scoped_refptr<FakeTaskImpl> completion_task( | |
| 69 new FakeTaskImpl(base::Bind(&FakeWorkerPool::OnTasksCompleted, | |
| 70 base::Unretained(this)), | |
| 71 base::Closure(), | |
| 72 &tasks)); | |
| 73 | |
| 74 scheduled_tasks_completion_.reset(new CompletionEvent); | |
| 75 | |
| 76 TaskGraph graph; | |
| 77 BuildTaskGraph(completion_task.get(), &graph); | |
| 78 WorkerPool::SetTaskGraph(&graph); | |
| 79 root_.swap(completion_task); | |
| 80 } | |
| 81 | |
| 82 void WaitForTasksToComplete() { | |
| 83 DCHECK(scheduled_tasks_completion_); | |
| 84 scheduled_tasks_completion_->Wait(); | |
| 85 } | |
| 86 | |
| 87 private: | |
| 88 void OnTasksCompleted() { | |
| 89 DCHECK(scheduled_tasks_completion_); | |
| 90 scheduled_tasks_completion_->Signal(); | |
| 91 } | |
| 92 | |
| 93 scoped_refptr<FakeTaskImpl> root_; | |
| 94 scoped_ptr<CompletionEvent> scheduled_tasks_completion_; | |
| 95 }; | |
| 96 | |
| 97 class WorkerPoolTest : public testing::Test { | |
| 98 public: | |
| 99 WorkerPoolTest() {} | |
| 100 virtual ~WorkerPoolTest() {} | |
| 101 | |
| 102 // Overridden from testing::Test: | |
| 103 virtual void SetUp() OVERRIDE { | |
| 104 Reset(); | |
| 105 } | |
| 106 virtual void TearDown() OVERRIDE { | |
| 107 worker_pool_->Shutdown(); | |
| 108 } | |
| 109 | |
| 110 void Reset() { | |
| 111 worker_pool_ = FakeWorkerPool::Create(); | |
| 112 } | |
| 113 | |
| 114 void RunAllTasksAndReset() { | |
| 115 worker_pool_->WaitForTasksToComplete(); | |
| 116 worker_pool_->Shutdown(); | |
| 117 worker_pool_->CheckForCompletedTasks(); | |
| 118 Reset(); | |
| 119 } | |
| 120 | |
| 121 FakeWorkerPool* worker_pool() { | |
| 122 return worker_pool_.get(); | |
| 123 } | |
| 124 | |
| 125 void RunTask(unsigned id) { | |
| 126 run_task_ids_.push_back(id); | |
| 127 } | |
| 128 | |
| 129 void OnTaskCompleted(unsigned id) { | |
| 130 on_task_completed_ids_.push_back(id); | |
| 131 } | |
| 132 | |
| 133 const std::vector<unsigned>& run_task_ids() { | |
| 134 return run_task_ids_; | |
| 135 } | |
| 136 | |
| 137 const std::vector<unsigned>& on_task_completed_ids() { | |
| 138 return on_task_completed_ids_; | |
| 139 } | |
| 140 | |
| 141 private: | |
| 142 scoped_ptr<FakeWorkerPool> worker_pool_; | |
| 143 std::vector<unsigned> run_task_ids_; | |
| 144 std::vector<unsigned> on_task_completed_ids_; | |
| 145 }; | |
| 146 | |
| 147 TEST_F(WorkerPoolTest, Basic) { | |
| 148 EXPECT_EQ(0u, run_task_ids().size()); | |
| 149 EXPECT_EQ(0u, on_task_completed_ids().size()); | |
| 150 | |
| 151 worker_pool()->ScheduleTasks( | |
| 152 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u), | |
| 153 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 0u), | |
| 154 base::Closure(), | |
| 155 1); | |
| 156 RunAllTasksAndReset(); | |
| 157 | |
| 158 EXPECT_EQ(1u, run_task_ids().size()); | |
| 159 EXPECT_EQ(1u, on_task_completed_ids().size()); | |
| 160 | |
| 161 worker_pool()->ScheduleTasks( | |
| 162 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u), | |
| 163 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 0u), | |
| 164 base::Closure(), | |
| 165 2); | |
| 166 RunAllTasksAndReset(); | |
| 167 | |
| 168 EXPECT_EQ(3u, run_task_ids().size()); | |
| 169 EXPECT_EQ(3u, on_task_completed_ids().size()); | |
| 170 } | |
| 171 | |
| 172 TEST_F(WorkerPoolTest, Dependencies) { | |
| 173 worker_pool()->ScheduleTasks( | |
| 174 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 1u), | |
| 175 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 1u), | |
| 176 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u), | |
| 177 1); | |
| 178 RunAllTasksAndReset(); | |
| 179 | |
| 180 // Check if dependency ran before task. | |
| 181 ASSERT_EQ(2u, run_task_ids().size()); | |
| 182 EXPECT_EQ(0u, run_task_ids()[0]); | |
| 183 EXPECT_EQ(1u, run_task_ids()[1]); | |
| 184 ASSERT_EQ(1u, on_task_completed_ids().size()); | |
| 185 EXPECT_EQ(1u, on_task_completed_ids()[0]); | |
| 186 | |
| 187 worker_pool()->ScheduleTasks( | |
| 188 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 1u), | |
| 189 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 1u), | |
| 190 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u), | |
| 191 2); | |
| 192 RunAllTasksAndReset(); | |
| 193 | |
| 194 // Dependency should only run once. | |
| 195 ASSERT_EQ(5u, run_task_ids().size()); | |
| 196 EXPECT_EQ(0u, run_task_ids()[2]); | |
| 197 EXPECT_EQ(1u, run_task_ids()[3]); | |
| 198 EXPECT_EQ(1u, run_task_ids()[4]); | |
| 199 ASSERT_EQ(3u, on_task_completed_ids().size()); | |
| 200 EXPECT_EQ(1u, on_task_completed_ids()[1]); | |
| 201 EXPECT_EQ(1u, on_task_completed_ids()[2]); | |
| 202 } | |
| 203 | |
| 204 } // namespace | |
| 205 | |
| 206 } // namespace cc | |
| OLD | NEW |