- add sources.
[platform/framework/web/crosswalk.git] / src / base / test / sequenced_task_runner_test_template.cc
1 // Copyright (c) 2012 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 "base/test/sequenced_task_runner_test_template.h"
6
7 #include <ostream>
8
9 #include "base/location.h"
10
11 namespace base {
12
13 namespace internal {
14
15 TaskEvent::TaskEvent(int i, Type type)
16   : i(i), type(type) {
17 }
18
19 SequencedTaskTracker::SequencedTaskTracker()
20     : next_post_i_(0),
21       task_end_count_(0),
22       task_end_cv_(&lock_) {
23 }
24
25 void SequencedTaskTracker::PostWrappedNonNestableTask(
26     const scoped_refptr<SequencedTaskRunner>& task_runner,
27     const Closure& task) {
28   AutoLock event_lock(lock_);
29   const int post_i = next_post_i_++;
30   Closure wrapped_task = Bind(&SequencedTaskTracker::RunTask, this,
31                               task, post_i);
32   task_runner->PostNonNestableTask(FROM_HERE, wrapped_task);
33   TaskPosted(post_i);
34 }
35
36 void SequencedTaskTracker::PostWrappedNestableTask(
37     const scoped_refptr<SequencedTaskRunner>& task_runner,
38     const Closure& task) {
39   AutoLock event_lock(lock_);
40   const int post_i = next_post_i_++;
41   Closure wrapped_task = Bind(&SequencedTaskTracker::RunTask, this,
42                               task, post_i);
43   task_runner->PostTask(FROM_HERE, wrapped_task);
44   TaskPosted(post_i);
45 }
46
47 void SequencedTaskTracker::PostWrappedDelayedNonNestableTask(
48     const scoped_refptr<SequencedTaskRunner>& task_runner,
49     const Closure& task,
50     TimeDelta delay) {
51   AutoLock event_lock(lock_);
52   const int post_i = next_post_i_++;
53   Closure wrapped_task = Bind(&SequencedTaskTracker::RunTask, this,
54                               task, post_i);
55   task_runner->PostNonNestableDelayedTask(FROM_HERE, wrapped_task, delay);
56   TaskPosted(post_i);
57 }
58
59 void SequencedTaskTracker::PostNonNestableTasks(
60     const scoped_refptr<SequencedTaskRunner>& task_runner,
61     int task_count) {
62   for (int i = 0; i < task_count; ++i) {
63     PostWrappedNonNestableTask(task_runner, Closure());
64   }
65 }
66
67 void SequencedTaskTracker::RunTask(const Closure& task, int task_i) {
68   TaskStarted(task_i);
69   if (!task.is_null())
70     task.Run();
71   TaskEnded(task_i);
72 }
73
74 void SequencedTaskTracker::TaskPosted(int i) {
75   // Caller must own |lock_|.
76   events_.push_back(TaskEvent(i, TaskEvent::POST));
77 }
78
79 void SequencedTaskTracker::TaskStarted(int i) {
80   AutoLock lock(lock_);
81   events_.push_back(TaskEvent(i, TaskEvent::START));
82 }
83
84 void SequencedTaskTracker::TaskEnded(int i) {
85   AutoLock lock(lock_);
86   events_.push_back(TaskEvent(i, TaskEvent::END));
87   ++task_end_count_;
88   task_end_cv_.Signal();
89 }
90
91 const std::vector<TaskEvent>&
92 SequencedTaskTracker::GetTaskEvents() const {
93   return events_;
94 }
95
96 void SequencedTaskTracker::WaitForCompletedTasks(int count) {
97   AutoLock lock(lock_);
98   while (task_end_count_ < count)
99     task_end_cv_.Wait();
100 }
101
102 SequencedTaskTracker::~SequencedTaskTracker() {
103 }
104
105 void PrintTo(const TaskEvent& event, std::ostream* os) {
106   *os << "(i=" << event.i << ", type=";
107   switch (event.type) {
108     case TaskEvent::POST: *os << "POST"; break;
109     case TaskEvent::START: *os << "START"; break;
110     case TaskEvent::END: *os << "END"; break;
111   }
112   *os << ")";
113 }
114
115 namespace {
116
117 // Returns the task ordinals for the task event type |type| in the order that
118 // they were recorded.
119 std::vector<int> GetEventTypeOrder(const std::vector<TaskEvent>& events,
120                                    TaskEvent::Type type) {
121   std::vector<int> tasks;
122   std::vector<TaskEvent>::const_iterator event;
123   for (event = events.begin(); event != events.end(); ++event) {
124     if (event->type == type)
125       tasks.push_back(event->i);
126   }
127   return tasks;
128 }
129
130 // Returns all task events for task |task_i|.
131 std::vector<TaskEvent::Type> GetEventsForTask(
132     const std::vector<TaskEvent>& events,
133     int task_i) {
134   std::vector<TaskEvent::Type> task_event_orders;
135   std::vector<TaskEvent>::const_iterator event;
136   for (event = events.begin(); event != events.end(); ++event) {
137     if (event->i == task_i)
138       task_event_orders.push_back(event->type);
139   }
140   return task_event_orders;
141 }
142
143 // Checks that the task events for each task in |events| occur in the order
144 // {POST, START, END}, and that there is only one instance of each event type
145 // per task.
146 ::testing::AssertionResult CheckEventOrdersForEachTask(
147     const std::vector<TaskEvent>& events,
148     int task_count) {
149   std::vector<TaskEvent::Type> expected_order;
150   expected_order.push_back(TaskEvent::POST);
151   expected_order.push_back(TaskEvent::START);
152   expected_order.push_back(TaskEvent::END);
153
154   // This is O(n^2), but it runs fast enough currently so is not worth
155   // optimizing.
156   for (int i = 0; i < task_count; ++i) {
157     const std::vector<TaskEvent::Type> task_events =
158         GetEventsForTask(events, i);
159     if (task_events != expected_order) {
160       return ::testing::AssertionFailure()
161           << "Events for task " << i << " are out of order; expected: "
162           << ::testing::PrintToString(expected_order) << "; actual: "
163           << ::testing::PrintToString(task_events);
164     }
165   }
166   return ::testing::AssertionSuccess();
167 }
168
169 // Checks that no two tasks were running at the same time. I.e. the only
170 // events allowed between the START and END of a task are the POSTs of other
171 // tasks.
172 ::testing::AssertionResult CheckNoTaskRunsOverlap(
173     const std::vector<TaskEvent>& events) {
174   // If > -1, we're currently inside a START, END pair.
175   int current_task_i = -1;
176
177   std::vector<TaskEvent>::const_iterator event;
178   for (event = events.begin(); event != events.end(); ++event) {
179     bool spurious_event_found = false;
180
181     if (current_task_i == -1) {  // Not inside a START, END pair.
182       switch (event->type) {
183         case TaskEvent::POST:
184           break;
185         case TaskEvent::START:
186           current_task_i = event->i;
187           break;
188         case TaskEvent::END:
189           spurious_event_found = true;
190           break;
191       }
192
193     } else {  // Inside a START, END pair.
194       bool interleaved_task_detected = false;
195
196       switch (event->type) {
197         case TaskEvent::POST:
198           if (event->i == current_task_i)
199             spurious_event_found = true;
200           break;
201         case TaskEvent::START:
202           interleaved_task_detected = true;
203           break;
204         case TaskEvent::END:
205           if (event->i != current_task_i)
206             interleaved_task_detected = true;
207           else
208             current_task_i = -1;
209           break;
210       }
211
212       if (interleaved_task_detected) {
213         return ::testing::AssertionFailure()
214             << "Found event " << ::testing::PrintToString(*event)
215             << " between START and END events for task " << current_task_i
216             << "; event dump: " << ::testing::PrintToString(events);
217       }
218     }
219
220     if (spurious_event_found) {
221       const int event_i = event - events.begin();
222       return ::testing::AssertionFailure()
223           << "Spurious event " << ::testing::PrintToString(*event)
224           << " at position " << event_i << "; event dump: "
225           << ::testing::PrintToString(events);
226     }
227   }
228
229   return ::testing::AssertionSuccess();
230 }
231
232 }  // namespace
233
234 ::testing::AssertionResult CheckNonNestableInvariants(
235     const std::vector<TaskEvent>& events,
236     int task_count) {
237   const std::vector<int> post_order =
238       GetEventTypeOrder(events, TaskEvent::POST);
239   const std::vector<int> start_order =
240       GetEventTypeOrder(events, TaskEvent::START);
241   const std::vector<int> end_order =
242       GetEventTypeOrder(events, TaskEvent::END);
243
244   if (start_order != post_order) {
245     return ::testing::AssertionFailure()
246         << "Expected START order (which equals actual POST order): \n"
247         << ::testing::PrintToString(post_order)
248         << "\n Actual START order:\n"
249         << ::testing::PrintToString(start_order);
250   }
251
252   if (end_order != post_order) {
253     return ::testing::AssertionFailure()
254         << "Expected END order (which equals actual POST order): \n"
255         << ::testing::PrintToString(post_order)
256         << "\n Actual END order:\n"
257         << ::testing::PrintToString(end_order);
258   }
259
260   const ::testing::AssertionResult result =
261       CheckEventOrdersForEachTask(events, task_count);
262   if (!result)
263     return result;
264
265   return CheckNoTaskRunsOverlap(events);
266 }
267
268 }  // namespace internal
269
270 }  // namespace base