This sets up API to release OutputSurface from LTHClient.
[chromium-blink-merge.git] / cc / raster / task_graph_runner_unittest.cc
blobeb9b6d954b7249620d715ea496ede01d3fac900f
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.
5 #include "cc/raster/task_graph_runner.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/synchronization/lock.h"
11 #include "base/threading/simple_thread.h"
12 #include "cc/base/scoped_ptr_deque.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace cc {
16 namespace {
18 const int kNamespaceCount = 3;
20 class TaskGraphRunnerTestBase {
21 public:
22 struct TaskInfo {
23 TaskInfo(int namespace_index,
24 unsigned id,
25 unsigned dependent_id,
26 unsigned dependent_count,
27 unsigned priority)
28 : namespace_index(namespace_index),
29 id(id),
30 dependent_id(dependent_id),
31 dependent_count(dependent_count),
32 priority(priority) {}
34 int namespace_index;
35 unsigned id;
36 unsigned dependent_id;
37 unsigned dependent_count;
38 unsigned priority;
41 TaskGraphRunnerTestBase() : task_graph_runner_(new TaskGraphRunner) {}
43 void ResetIds(int namespace_index) {
44 run_task_ids_[namespace_index].clear();
45 on_task_completed_ids_[namespace_index].clear();
48 void RunAllTasks(int namespace_index) {
49 task_graph_runner_->WaitForTasksToFinishRunning(
50 namespace_token_[namespace_index]);
52 Task::Vector completed_tasks;
53 task_graph_runner_->CollectCompletedTasks(namespace_token_[namespace_index],
54 &completed_tasks);
55 for (Task::Vector::const_iterator it = completed_tasks.begin();
56 it != completed_tasks.end();
57 ++it) {
58 FakeTaskImpl* task = static_cast<FakeTaskImpl*>(it->get());
59 task->CompleteOnOriginThread();
63 void RunTaskOnWorkerThread(int namespace_index, unsigned id) {
64 base::AutoLock lock(run_task_ids_lock_);
65 run_task_ids_[namespace_index].push_back(id);
68 void OnTaskCompleted(int namespace_index, unsigned id) {
69 on_task_completed_ids_[namespace_index].push_back(id);
72 const std::vector<unsigned>& run_task_ids(int namespace_index) {
73 return run_task_ids_[namespace_index];
76 const std::vector<unsigned>& on_task_completed_ids(int namespace_index) {
77 return on_task_completed_ids_[namespace_index];
80 void ScheduleTasks(int namespace_index, const std::vector<TaskInfo>& tasks) {
81 Task::Vector new_tasks;
82 Task::Vector new_dependents;
83 TaskGraph new_graph;
85 for (std::vector<TaskInfo>::const_iterator it = tasks.begin();
86 it != tasks.end();
87 ++it) {
88 scoped_refptr<FakeTaskImpl> new_task(
89 new FakeTaskImpl(this, it->namespace_index, it->id));
90 new_graph.nodes.push_back(
91 TaskGraph::Node(new_task.get(), it->priority, 0u));
92 for (unsigned i = 0; i < it->dependent_count; ++i) {
93 scoped_refptr<FakeDependentTaskImpl> new_dependent_task(
94 new FakeDependentTaskImpl(
95 this, it->namespace_index, it->dependent_id));
96 new_graph.nodes.push_back(
97 TaskGraph::Node(new_dependent_task.get(), it->priority, 1u));
98 new_graph.edges.push_back(
99 TaskGraph::Edge(new_task.get(), new_dependent_task.get()));
101 new_dependents.push_back(new_dependent_task.get());
104 new_tasks.push_back(new_task.get());
107 task_graph_runner_->ScheduleTasks(namespace_token_[namespace_index],
108 &new_graph);
110 dependents_[namespace_index].swap(new_dependents);
111 tasks_[namespace_index].swap(new_tasks);
114 protected:
115 class FakeTaskImpl : public Task {
116 public:
117 FakeTaskImpl(TaskGraphRunnerTestBase* test, int namespace_index, int id)
118 : test_(test), namespace_index_(namespace_index), id_(id) {}
120 // Overridden from Task:
121 void RunOnWorkerThread() override {
122 test_->RunTaskOnWorkerThread(namespace_index_, id_);
125 virtual void CompleteOnOriginThread() {
126 test_->OnTaskCompleted(namespace_index_, id_);
129 protected:
130 ~FakeTaskImpl() override {}
132 private:
133 TaskGraphRunnerTestBase* test_;
134 int namespace_index_;
135 int id_;
137 DISALLOW_COPY_AND_ASSIGN(FakeTaskImpl);
140 class FakeDependentTaskImpl : public FakeTaskImpl {
141 public:
142 FakeDependentTaskImpl(TaskGraphRunnerTestBase* test,
143 int namespace_index,
144 int id)
145 : FakeTaskImpl(test, namespace_index, id) {}
147 // Overridden from FakeTaskImpl:
148 void CompleteOnOriginThread() override {}
150 private:
151 ~FakeDependentTaskImpl() override {}
153 DISALLOW_COPY_AND_ASSIGN(FakeDependentTaskImpl);
156 scoped_ptr<TaskGraphRunner> task_graph_runner_;
157 NamespaceToken namespace_token_[kNamespaceCount];
158 Task::Vector tasks_[kNamespaceCount];
159 Task::Vector dependents_[kNamespaceCount];
160 std::vector<unsigned> run_task_ids_[kNamespaceCount];
161 base::Lock run_task_ids_lock_;
162 std::vector<unsigned> on_task_completed_ids_[kNamespaceCount];
165 class TaskGraphRunnerTest : public TaskGraphRunnerTestBase,
166 public testing::TestWithParam<int>,
167 public base::DelegateSimpleThread::Delegate {
168 public:
169 // Overridden from testing::Test:
170 void SetUp() override {
171 const size_t num_threads = GetParam();
172 while (workers_.size() < num_threads) {
173 scoped_ptr<base::DelegateSimpleThread> worker =
174 make_scoped_ptr(new base::DelegateSimpleThread(this, "TestWorker"));
175 worker->Start();
176 workers_.push_back(worker.Pass());
179 for (int i = 0; i < kNamespaceCount; ++i)
180 namespace_token_[i] = task_graph_runner_->GetNamespaceToken();
182 void TearDown() override {
183 task_graph_runner_->Shutdown();
184 while (workers_.size()) {
185 scoped_ptr<base::DelegateSimpleThread> worker = workers_.take_front();
186 worker->Join();
190 private:
191 // Overridden from base::DelegateSimpleThread::Delegate:
192 void Run() override { task_graph_runner_->Run(); }
194 ScopedPtrDeque<base::DelegateSimpleThread> workers_;
197 TEST_P(TaskGraphRunnerTest, Basic) {
198 for (int i = 0; i < kNamespaceCount; ++i) {
199 EXPECT_EQ(0u, run_task_ids(i).size());
200 EXPECT_EQ(0u, on_task_completed_ids(i).size());
202 ScheduleTasks(i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 0u, 0u)));
205 for (int i = 0; i < kNamespaceCount; ++i) {
206 RunAllTasks(i);
208 EXPECT_EQ(1u, run_task_ids(i).size());
209 EXPECT_EQ(1u, on_task_completed_ids(i).size());
212 for (int i = 0; i < kNamespaceCount; ++i)
213 ScheduleTasks(i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 1u, 0u)));
215 for (int i = 0; i < kNamespaceCount; ++i) {
216 RunAllTasks(i);
218 EXPECT_EQ(3u, run_task_ids(i).size());
219 EXPECT_EQ(2u, on_task_completed_ids(i).size());
222 for (int i = 0; i < kNamespaceCount; ++i)
223 ScheduleTasks(i, std::vector<TaskInfo>(1, TaskInfo(i, 0u, 0u, 2u, 0u)));
225 for (int i = 0; i < kNamespaceCount; ++i) {
226 RunAllTasks(i);
228 EXPECT_EQ(6u, run_task_ids(i).size());
229 EXPECT_EQ(3u, on_task_completed_ids(i).size());
233 TEST_P(TaskGraphRunnerTest, Dependencies) {
234 for (int i = 0; i < kNamespaceCount; ++i) {
235 ScheduleTasks(i,
236 std::vector<TaskInfo>(1,
237 TaskInfo(i,
240 1u, // 1 dependent
241 0u)));
244 for (int i = 0; i < kNamespaceCount; ++i) {
245 RunAllTasks(i);
247 // Check if task ran before dependent.
248 ASSERT_EQ(2u, run_task_ids(i).size());
249 EXPECT_EQ(0u, run_task_ids(i)[0]);
250 EXPECT_EQ(1u, run_task_ids(i)[1]);
251 ASSERT_EQ(1u, on_task_completed_ids(i).size());
252 EXPECT_EQ(0u, on_task_completed_ids(i)[0]);
255 for (int i = 0; i < kNamespaceCount; ++i) {
256 ScheduleTasks(i,
257 std::vector<TaskInfo>(1,
258 TaskInfo(i,
261 2u, // 2 dependents
262 0u)));
265 for (int i = 0; i < kNamespaceCount; ++i) {
266 RunAllTasks(i);
268 // Task should only run once.
269 ASSERT_EQ(5u, run_task_ids(i).size());
270 EXPECT_EQ(2u, run_task_ids(i)[2]);
271 EXPECT_EQ(3u, run_task_ids(i)[3]);
272 EXPECT_EQ(3u, run_task_ids(i)[4]);
273 ASSERT_EQ(2u, on_task_completed_ids(i).size());
274 EXPECT_EQ(2u, on_task_completed_ids(i)[1]);
278 INSTANTIATE_TEST_CASE_P(TaskGraphRunnerTests,
279 TaskGraphRunnerTest,
280 ::testing::Range(1, 5));
282 class TaskGraphRunnerSingleThreadTest
283 : public TaskGraphRunnerTestBase,
284 public testing::Test,
285 public base::DelegateSimpleThread::Delegate {
286 public:
287 // Overridden from testing::Test:
288 void SetUp() override {
289 worker_.reset(new base::DelegateSimpleThread(this, "TestWorker"));
290 worker_->Start();
292 for (int i = 0; i < kNamespaceCount; ++i)
293 namespace_token_[i] = task_graph_runner_->GetNamespaceToken();
295 void TearDown() override {
296 task_graph_runner_->Shutdown();
297 worker_->Join();
300 private:
301 // Overridden from base::DelegateSimpleThread::Delegate:
302 void Run() override { task_graph_runner_->Run(); }
304 scoped_ptr<base::DelegateSimpleThread> worker_;
307 TEST_F(TaskGraphRunnerSingleThreadTest, Priority) {
308 for (int i = 0; i < kNamespaceCount; ++i) {
309 TaskInfo tasks[] = {TaskInfo(i, 0u, 2u, 1u, 1u), // Priority 1
310 TaskInfo(i, 1u, 3u, 1u, 0u) // Priority 0
312 ScheduleTasks(i, std::vector<TaskInfo>(tasks, tasks + arraysize(tasks)));
315 for (int i = 0; i < kNamespaceCount; ++i) {
316 RunAllTasks(i);
318 // Check if tasks ran in order of priority.
319 ASSERT_EQ(4u, run_task_ids(i).size());
320 EXPECT_EQ(1u, run_task_ids(i)[0]);
321 EXPECT_EQ(3u, run_task_ids(i)[1]);
322 EXPECT_EQ(0u, run_task_ids(i)[2]);
323 EXPECT_EQ(2u, run_task_ids(i)[3]);
324 ASSERT_EQ(2u, on_task_completed_ids(i).size());
325 EXPECT_EQ(1u, on_task_completed_ids(i)[0]);
326 EXPECT_EQ(0u, on_task_completed_ids(i)[1]);
330 } // namespace
331 } // namespace cc