Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / cc / resources / task_graph_runner_unittest.cc
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 "cc/resources/task_graph_runner.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/synchronization/lock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace cc {
14 namespace {
15
16 const int kNamespaceCount = 3;
17
18 class TaskGraphRunnerTestBase {
19  public:
20   struct Task {
21     Task(int namespace_index,
22          unsigned id,
23          unsigned dependent_id,
24          unsigned dependent_count,
25          unsigned priority)
26         : namespace_index(namespace_index),
27           id(id),
28           dependent_id(dependent_id),
29           dependent_count(dependent_count),
30           priority(priority) {}
31
32     int namespace_index;
33     unsigned id;
34     unsigned dependent_id;
35     unsigned dependent_count;
36     unsigned priority;
37   };
38
39   void ResetIds(int namespace_index) {
40     run_task_ids_[namespace_index].clear();
41     on_task_completed_ids_[namespace_index].clear();
42   }
43
44   void RunAllTasks(int namespace_index) {
45     task_graph_runner_->WaitForTasksToFinishRunning(
46         namespace_token_[namespace_index]);
47
48     internal::Task::Vector completed_tasks;
49     task_graph_runner_->CollectCompletedTasks(namespace_token_[namespace_index],
50                                               &completed_tasks);
51     for (internal::Task::Vector::const_iterator it = completed_tasks.begin();
52          it != completed_tasks.end();
53          ++it) {
54       FakeTaskImpl* task = static_cast<FakeTaskImpl*>(it->get());
55       task->CompleteOnOriginThread();
56     }
57   }
58
59   void RunTaskOnWorkerThread(int namespace_index, unsigned id) {
60     base::AutoLock lock(run_task_ids_lock_);
61     run_task_ids_[namespace_index].push_back(id);
62   }
63
64   void OnTaskCompleted(int namespace_index, unsigned id) {
65     on_task_completed_ids_[namespace_index].push_back(id);
66   }
67
68   const std::vector<unsigned>& run_task_ids(int namespace_index) {
69     return run_task_ids_[namespace_index];
70   }
71
72   const std::vector<unsigned>& on_task_completed_ids(int namespace_index) {
73     return on_task_completed_ids_[namespace_index];
74   }
75
76   void ScheduleTasks(int namespace_index, const std::vector<Task>& tasks) {
77     internal::Task::Vector new_tasks;
78     internal::Task::Vector new_dependents;
79     internal::TaskGraph new_graph;
80
81     for (std::vector<Task>::const_iterator it = tasks.begin();
82          it != tasks.end();
83          ++it) {
84       scoped_refptr<FakeTaskImpl> new_task(
85           new FakeTaskImpl(this, it->namespace_index, it->id));
86       new_graph.nodes.push_back(
87           internal::TaskGraph::Node(new_task.get(), it->priority, 0u));
88       for (unsigned i = 0; i < it->dependent_count; ++i) {
89         scoped_refptr<FakeDependentTaskImpl> new_dependent_task(
90             new FakeDependentTaskImpl(
91                 this, it->namespace_index, it->dependent_id));
92         new_graph.nodes.push_back(internal::TaskGraph::Node(
93             new_dependent_task.get(), it->priority, 1u));
94         new_graph.edges.push_back(internal::TaskGraph::Edge(
95             new_task.get(), new_dependent_task.get()));
96
97         new_dependents.push_back(new_dependent_task.get());
98       }
99
100       new_tasks.push_back(new_task.get());
101     }
102
103     task_graph_runner_->SetTaskGraph(namespace_token_[namespace_index],
104                                      &new_graph);
105
106     dependents_[namespace_index].swap(new_dependents);
107     tasks_[namespace_index].swap(new_tasks);
108   }
109
110  protected:
111   class FakeTaskImpl : public internal::Task {
112    public:
113     FakeTaskImpl(TaskGraphRunnerTestBase* test, int namespace_index, int id)
114         : test_(test), namespace_index_(namespace_index), id_(id) {}
115
116     // Overridden from internal::Task:
117     virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
118       test_->RunTaskOnWorkerThread(namespace_index_, id_);
119     }
120
121     virtual void CompleteOnOriginThread() {
122       test_->OnTaskCompleted(namespace_index_, id_);
123     }
124
125    protected:
126     virtual ~FakeTaskImpl() {}
127
128    private:
129     TaskGraphRunnerTestBase* test_;
130     int namespace_index_;
131     int id_;
132
133     DISALLOW_COPY_AND_ASSIGN(FakeTaskImpl);
134   };
135
136   class FakeDependentTaskImpl : public FakeTaskImpl {
137    public:
138     FakeDependentTaskImpl(TaskGraphRunnerTestBase* test,
139                           int namespace_index,
140                           int id)
141         : FakeTaskImpl(test, namespace_index, id) {}
142
143     // Overridden from FakeTaskImpl:
144     virtual void CompleteOnOriginThread() OVERRIDE {}
145
146    private:
147     virtual ~FakeDependentTaskImpl() {}
148
149     DISALLOW_COPY_AND_ASSIGN(FakeDependentTaskImpl);
150   };
151
152   scoped_ptr<internal::TaskGraphRunner> task_graph_runner_;
153   internal::NamespaceToken namespace_token_[kNamespaceCount];
154   internal::Task::Vector tasks_[kNamespaceCount];
155   internal::Task::Vector dependents_[kNamespaceCount];
156   std::vector<unsigned> run_task_ids_[kNamespaceCount];
157   base::Lock run_task_ids_lock_;
158   std::vector<unsigned> on_task_completed_ids_[kNamespaceCount];
159 };
160
161 class TaskGraphRunnerTest : public TaskGraphRunnerTestBase,
162                             public testing::TestWithParam<int> {
163  public:
164   // Overridden from testing::Test:
165   virtual void SetUp() OVERRIDE {
166     task_graph_runner_ =
167         make_scoped_ptr(new internal::TaskGraphRunner(GetParam(), "Test"));
168     for (int i = 0; i < kNamespaceCount; ++i)
169       namespace_token_[i] = task_graph_runner_->GetNamespaceToken();
170   }
171   virtual void TearDown() OVERRIDE { task_graph_runner_.reset(); }
172 };
173
174 TEST_P(TaskGraphRunnerTest, Basic) {
175   for (int i = 0; i < kNamespaceCount; ++i) {
176     EXPECT_EQ(0u, run_task_ids(i).size());
177     EXPECT_EQ(0u, on_task_completed_ids(i).size());
178
179     ScheduleTasks(i, std::vector<Task>(1, Task(i, 0u, 0u, 0u, 0u)));
180   }
181
182   for (int i = 0; i < kNamespaceCount; ++i) {
183     RunAllTasks(i);
184
185     EXPECT_EQ(1u, run_task_ids(i).size());
186     EXPECT_EQ(1u, on_task_completed_ids(i).size());
187   }
188
189   for (int i = 0; i < kNamespaceCount; ++i)
190     ScheduleTasks(i, std::vector<Task>(1, Task(i, 0u, 0u, 1u, 0u)));
191
192   for (int i = 0; i < kNamespaceCount; ++i) {
193     RunAllTasks(i);
194
195     EXPECT_EQ(3u, run_task_ids(i).size());
196     EXPECT_EQ(2u, on_task_completed_ids(i).size());
197   }
198
199   for (int i = 0; i < kNamespaceCount; ++i)
200     ScheduleTasks(i, std::vector<Task>(1, Task(i, 0u, 0u, 2u, 0u)));
201
202   for (int i = 0; i < kNamespaceCount; ++i) {
203     RunAllTasks(i);
204
205     EXPECT_EQ(6u, run_task_ids(i).size());
206     EXPECT_EQ(3u, on_task_completed_ids(i).size());
207   }
208 }
209
210 TEST_P(TaskGraphRunnerTest, Dependencies) {
211   for (int i = 0; i < kNamespaceCount; ++i) {
212     ScheduleTasks(i,
213                   std::vector<Task>(1,
214                                     Task(i,
215                                          0u,
216                                          1u,
217                                          1u,  // 1 dependent
218                                          0u)));
219   }
220
221   for (int i = 0; i < kNamespaceCount; ++i) {
222     RunAllTasks(i);
223
224     // Check if task ran before dependent.
225     ASSERT_EQ(2u, run_task_ids(i).size());
226     EXPECT_EQ(0u, run_task_ids(i)[0]);
227     EXPECT_EQ(1u, run_task_ids(i)[1]);
228     ASSERT_EQ(1u, on_task_completed_ids(i).size());
229     EXPECT_EQ(0u, on_task_completed_ids(i)[0]);
230   }
231
232   for (int i = 0; i < kNamespaceCount; ++i) {
233     ScheduleTasks(i,
234                   std::vector<Task>(1,
235                                     Task(i,
236                                          2u,
237                                          3u,
238                                          2u,  // 2 dependents
239                                          0u)));
240   }
241
242   for (int i = 0; i < kNamespaceCount; ++i) {
243     RunAllTasks(i);
244
245     // Task should only run once.
246     ASSERT_EQ(5u, run_task_ids(i).size());
247     EXPECT_EQ(2u, run_task_ids(i)[2]);
248     EXPECT_EQ(3u, run_task_ids(i)[3]);
249     EXPECT_EQ(3u, run_task_ids(i)[4]);
250     ASSERT_EQ(2u, on_task_completed_ids(i).size());
251     EXPECT_EQ(2u, on_task_completed_ids(i)[1]);
252   }
253 }
254
255 INSTANTIATE_TEST_CASE_P(TaskGraphRunnerTests,
256                         TaskGraphRunnerTest,
257                         ::testing::Range(1, 5));
258
259 class TaskGraphRunnerSingleThreadTest : public TaskGraphRunnerTestBase,
260                                         public testing::Test {
261  public:
262   // Overridden from testing::Test:
263   virtual void SetUp() OVERRIDE {
264     task_graph_runner_ =
265         make_scoped_ptr(new internal::TaskGraphRunner(1, "Test"));
266     for (int i = 0; i < kNamespaceCount; ++i)
267       namespace_token_[i] = task_graph_runner_->GetNamespaceToken();
268   }
269   virtual void TearDown() OVERRIDE { task_graph_runner_.reset(); }
270 };
271
272 TEST_F(TaskGraphRunnerSingleThreadTest, Priority) {
273   for (int i = 0; i < kNamespaceCount; ++i) {
274     Task tasks[] = {Task(i, 0u, 2u, 1u, 1u),  // Priority 1
275                     Task(i, 1u, 3u, 1u, 0u)   // Priority 0
276     };
277     ScheduleTasks(i, std::vector<Task>(tasks, tasks + arraysize(tasks)));
278   }
279
280   for (int i = 0; i < kNamespaceCount; ++i) {
281     RunAllTasks(i);
282
283     // Check if tasks ran in order of priority.
284     ASSERT_EQ(4u, run_task_ids(i).size());
285     EXPECT_EQ(1u, run_task_ids(i)[0]);
286     EXPECT_EQ(3u, run_task_ids(i)[1]);
287     EXPECT_EQ(0u, run_task_ids(i)[2]);
288     EXPECT_EQ(2u, run_task_ids(i)[3]);
289     ASSERT_EQ(2u, on_task_completed_ids(i).size());
290     EXPECT_EQ(1u, on_task_completed_ids(i)[0]);
291     EXPECT_EQ(0u, on_task_completed_ids(i)[1]);
292   }
293 }
294
295 }  // namespace
296 }  // namespace cc