Fixed last bookmark button hiding behavior.
[chromium-blink-merge.git] / base / test / sequenced_task_runner_test_template.cc
blob50487d2fd7bef6c5c1df3b2acc4a8b945259c1ad
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.
5 #include "base/test/sequenced_task_runner_test_template.h"
7 #include <ostream>
9 #include "base/location.h"
11 namespace base {
13 namespace internal {
15 TaskEvent::TaskEvent(int i, Type type)
16 : i(i), type(type) {
19 SequencedTaskTracker::SequencedTaskTracker() : next_post_i_(0) {
22 void SequencedTaskTracker::PostWrappedNonNestableTask(
23 const scoped_refptr<SequencedTaskRunner>& task_runner,
24 const Closure& task) {
25 AutoLock event_lock(lock_);
26 const int post_i = next_post_i_++;
27 Closure wrapped_task = Bind(&SequencedTaskTracker::RunTask, this,
28 task, post_i);
29 task_runner->PostNonNestableTask(FROM_HERE, wrapped_task);
30 TaskPosted(post_i);
33 void SequencedTaskTracker::PostWrappedNestableTask(
34 const scoped_refptr<SequencedTaskRunner>& task_runner,
35 const Closure& task) {
36 AutoLock event_lock(lock_);
37 const int post_i = next_post_i_++;
38 Closure wrapped_task = Bind(&SequencedTaskTracker::RunTask, this,
39 task, post_i);
40 task_runner->PostTask(FROM_HERE, wrapped_task);
41 TaskPosted(post_i);
44 void SequencedTaskTracker::PostWrappedDelayedNonNestableTask(
45 const scoped_refptr<SequencedTaskRunner>& task_runner,
46 const Closure& task,
47 TimeDelta delay) {
48 AutoLock event_lock(lock_);
49 const int post_i = next_post_i_++;
50 Closure wrapped_task = Bind(&SequencedTaskTracker::RunTask, this,
51 task, post_i);
52 task_runner->PostNonNestableDelayedTask(FROM_HERE, wrapped_task, delay);
53 TaskPosted(post_i);
56 void SequencedTaskTracker::PostNonNestableTasks(
57 const scoped_refptr<SequencedTaskRunner>& task_runner,
58 int task_count) {
59 for (int i = 0; i < task_count; ++i) {
60 PostWrappedNonNestableTask(task_runner, Closure());
64 void SequencedTaskTracker::RunTask(const Closure& task, int task_i) {
65 TaskStarted(task_i);
66 if (!task.is_null())
67 task.Run();
68 TaskEnded(task_i);
71 void SequencedTaskTracker::TaskPosted(int i) {
72 // Caller must own |lock_|.
73 events_.push_back(TaskEvent(i, TaskEvent::POST));
76 void SequencedTaskTracker::TaskStarted(int i) {
77 AutoLock lock(lock_);
78 events_.push_back(TaskEvent(i, TaskEvent::START));
81 void SequencedTaskTracker::TaskEnded(int i) {
82 AutoLock lock(lock_);
83 events_.push_back(TaskEvent(i, TaskEvent::END));
86 const std::vector<TaskEvent>&
87 SequencedTaskTracker::GetTaskEvents() const {
88 return events_;
91 SequencedTaskTracker::~SequencedTaskTracker() {
94 void PrintTo(const TaskEvent& event, std::ostream* os) {
95 *os << "(i=" << event.i << ", type=";
96 switch (event.type) {
97 case TaskEvent::POST: *os << "POST"; break;
98 case TaskEvent::START: *os << "START"; break;
99 case TaskEvent::END: *os << "END"; break;
101 *os << ")";
104 namespace {
106 // Returns the task ordinals for the task event type |type| in the order that
107 // they were recorded.
108 std::vector<int> GetEventTypeOrder(const std::vector<TaskEvent>& events,
109 TaskEvent::Type type) {
110 std::vector<int> tasks;
111 std::vector<TaskEvent>::const_iterator event;
112 for (event = events.begin(); event != events.end(); ++event) {
113 if (event->type == type)
114 tasks.push_back(event->i);
116 return tasks;
119 // Returns all task events for task |task_i|.
120 std::vector<TaskEvent::Type> GetEventsForTask(
121 const std::vector<TaskEvent>& events,
122 int task_i) {
123 std::vector<TaskEvent::Type> task_event_orders;
124 std::vector<TaskEvent>::const_iterator event;
125 for (event = events.begin(); event != events.end(); ++event) {
126 if (event->i == task_i)
127 task_event_orders.push_back(event->type);
129 return task_event_orders;
132 // Checks that the task events for each task in |events| occur in the order
133 // {POST, START, END}, and that there is only one instance of each event type
134 // per task.
135 ::testing::AssertionResult CheckEventOrdersForEachTask(
136 const std::vector<TaskEvent>& events,
137 int task_count) {
138 std::vector<TaskEvent::Type> expected_order;
139 expected_order.push_back(TaskEvent::POST);
140 expected_order.push_back(TaskEvent::START);
141 expected_order.push_back(TaskEvent::END);
143 // This is O(n^2), but it runs fast enough currently so is not worth
144 // optimizing.
145 for (int i = 0; i < task_count; ++i) {
146 const std::vector<TaskEvent::Type> task_events =
147 GetEventsForTask(events, i);
148 if (task_events != expected_order) {
149 return ::testing::AssertionFailure()
150 << "Events for task " << i << " are out of order; expected: "
151 << ::testing::PrintToString(expected_order) << "; actual: "
152 << ::testing::PrintToString(task_events);
155 return ::testing::AssertionSuccess();
158 // Checks that no two tasks were running at the same time. I.e. the only
159 // events allowed between the START and END of a task are the POSTs of other
160 // tasks.
161 ::testing::AssertionResult CheckNoTaskRunsOverlap(
162 const std::vector<TaskEvent>& events) {
163 // If > -1, we're currently inside a START, END pair.
164 int current_task_i = -1;
166 std::vector<TaskEvent>::const_iterator event;
167 for (event = events.begin(); event != events.end(); ++event) {
168 bool spurious_event_found = false;
170 if (current_task_i == -1) { // Not inside a START, END pair.
171 switch (event->type) {
172 case TaskEvent::POST:
173 break;
174 case TaskEvent::START:
175 current_task_i = event->i;
176 break;
177 case TaskEvent::END:
178 spurious_event_found = true;
179 break;
182 } else { // Inside a START, END pair.
183 bool interleaved_task_detected = false;
185 switch (event->type) {
186 case TaskEvent::POST:
187 if (event->i == current_task_i)
188 spurious_event_found = true;
189 break;
190 case TaskEvent::START:
191 interleaved_task_detected = true;
192 break;
193 case TaskEvent::END:
194 if (event->i != current_task_i)
195 interleaved_task_detected = true;
196 else
197 current_task_i = -1;
198 break;
201 if (interleaved_task_detected) {
202 return ::testing::AssertionFailure()
203 << "Found event " << ::testing::PrintToString(*event)
204 << " between START and END events for task " << current_task_i
205 << "; event dump: " << ::testing::PrintToString(events);
209 if (spurious_event_found) {
210 const int event_i = event - events.begin();
211 return ::testing::AssertionFailure()
212 << "Spurious event " << ::testing::PrintToString(*event)
213 << " at position " << event_i << "; event dump: "
214 << ::testing::PrintToString(events);
218 return ::testing::AssertionSuccess();
221 } // namespace
223 ::testing::AssertionResult CheckNonNestableInvariants(
224 const std::vector<TaskEvent>& events,
225 int task_count) {
226 const std::vector<int> post_order =
227 GetEventTypeOrder(events, TaskEvent::POST);
228 const std::vector<int> start_order =
229 GetEventTypeOrder(events, TaskEvent::START);
230 const std::vector<int> end_order =
231 GetEventTypeOrder(events, TaskEvent::END);
233 if (start_order != post_order) {
234 return ::testing::AssertionFailure()
235 << "Expected START order (which equals actual POST order): \n"
236 << ::testing::PrintToString(post_order)
237 << "\n Actual START order:\n"
238 << ::testing::PrintToString(start_order);
241 if (end_order != post_order) {
242 return ::testing::AssertionFailure()
243 << "Expected END order (which equals actual POST order): \n"
244 << ::testing::PrintToString(post_order)
245 << "\n Actual END order:\n"
246 << ::testing::PrintToString(end_order);
249 const ::testing::AssertionResult result =
250 CheckEventOrdersForEachTask(events, task_count);
251 if (!result)
252 return result;
254 return CheckNoTaskRunsOverlap(events);
257 } // namespace internal
259 } // namespace base