Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(361)

Side by Side Diff: base/test/sequenced_task_runner_test_template.cc

Issue 9663075: Implementation of SequencedTaskRunner based on SequencedWorkerPool. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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>
Francois 2012/03/26 09:33:21 For SequencedTaskTracker::TaskEvent::PrintTo, whic
8
9 #include "base/tracked_objects.h"
akalin 2012/03/26 18:44:08 looks like this should be base/location.h (this ch
Francois 2012/03/28 14:32:42 Done.
10
11 namespace base {
12
13 namespace internal {
14
15 SequencedTaskTracker::TaskEvent::TaskEvent(int i_in, Type type_in)
akalin 2012/03/26 18:44:08 don't use _in, just name them the same; C++'s vari
Francois 2012/03/28 14:32:42 Done.
16 : i(i_in), type(type_in) {
17 }
18
19 SequencedTaskTracker::SequencedTaskTracker() : next_post_i_(0) {
20 }
21
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);
31 }
32
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);
42 }
43
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);
54 }
55
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());
61 }
62 }
63
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);
69 }
70
71 void SequencedTaskTracker::TaskPosted(int i) {
72 // Caller must own |lock_|.
73 events_.push_back(TaskEvent(i, TaskEvent::POST));
74 }
75
76 void SequencedTaskTracker::TaskStarted(int i) {
77 AutoLock lock(lock_);
78 events_.push_back(TaskEvent(i, TaskEvent::START));
79 }
80
81 void SequencedTaskTracker::TaskEnded(int i) {
82 AutoLock lock(lock_);
83 events_.push_back(TaskEvent(i, TaskEvent::END));
84 }
85
86 const std::vector<SequencedTaskTracker::TaskEvent>&
87 SequencedTaskTracker::GetTaskEvents() const {
88 return events_;
89 }
90
91 SequencedTaskTracker::~SequencedTaskTracker() {
92 }
93
94 void PrintTo(const SequencedTaskTracker::TaskEvent& event, std::ostream* os) {
95 *os << "(i=" << event.i << ", type=";
96 switch (event.type) {
97 case SequencedTaskTracker::TaskEvent::POST: *os << "POST"; break;
98 case SequencedTaskTracker::TaskEvent::START: *os << "START"; break;
99 case SequencedTaskTracker::TaskEvent::END: *os << "END"; break;
100 }
101 *os << ")";
102 }
103
104 void SleepForOneSecond() {
105 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
106 }
107
108 typedef SequencedTaskTracker::TaskEvent TaskEvent;
109
110 namespace {
111
112 // Returns the task ordinals for the task event type |type| in the order that
113 // they were recorded.
114 std::vector<int> GetEventTypeOrder(const std::vector<TaskEvent>& events,
115 TaskEvent::Type type) {
116 std::vector<int> tasks;
117 std::vector<TaskEvent>::const_iterator event;
118 for (event = events.begin(); event != events.end(); ++event) {
119 if (event->type == type)
120 tasks.push_back(event->i);
121 }
122 return tasks;
123 }
124
125 // Returns all task events for task |task_i|.
126 std::vector<TaskEvent::Type> GetEventsForTask(
127 const std::vector<TaskEvent>& events,
128 int task_i) {
129 std::vector<TaskEvent::Type> task_event_orders;
130 std::vector<TaskEvent>::const_iterator event;
131 for (event = events.begin(); event != events.end(); ++event) {
132 if (event->i == task_i)
133 task_event_orders.push_back(event->type);
134 }
135 return task_event_orders;
136 }
137
138 // Checks that the task events for each task in |events| occur in the order
139 // {POST, START, END}, and that there is only one instance of each event type
140 // per task.
141 ::testing::AssertionResult CheckEventOrdersForEachTask(
142 const std::vector<TaskEvent>& events,
143 int task_count) {
144 std::vector<TaskEvent::Type> expected_order;
145 expected_order.push_back(TaskEvent::POST);
146 expected_order.push_back(TaskEvent::START);
147 expected_order.push_back(TaskEvent::END);
148
149 for (int i = 0; i < task_count; ++i) {
akalin 2012/03/26 18:44:08 This takes n^2 time, which isn't great but probabl
Francois 2012/03/28 14:32:42 Done.
150 const std::vector<TaskEvent::Type> task_events =
151 GetEventsForTask(events, i);
152 if (task_events != expected_order) {
153 return ::testing::AssertionFailure()
154 << "Events for task " << i << " are out of order; expected: "
155 << ::testing::PrintToString(expected_order) << "; actual: "
156 << ::testing::PrintToString(task_events);
157 }
158 }
159 return ::testing::AssertionSuccess();
160 }
161
162 // Checks that no two tasks were running at the same time. I.e. the only
163 // events allowed between the START and END of a task are the POSTs of other
164 // tasks.
165 ::testing::AssertionResult CheckNoTaskRunsOverlap(
166 const std::vector<TaskEvent>& events) {
167 // If > -1, we're currently inside a START, END pair.
168 int current_task_i = -1;
169
170 std::vector<TaskEvent>::const_iterator event;
171 for (event = events.begin(); event != events.end(); ++event) {
172 bool spurious_event_found = false;
173
174 if (current_task_i == -1) { // Not inside a START, END pair.
175 switch (event->type) {
176 case TaskEvent::POST:
177 break;
178 case TaskEvent::START:
179 current_task_i = event->i;
180 break;
181 case TaskEvent::END:
182 spurious_event_found = true;
183 break;
184 }
185
186 } else { // Inside a START, END pair.
187 bool interleaved_task_detected = false;
188
189 switch (event->type) {
190 case TaskEvent::POST:
191 if (event->i == current_task_i)
192 spurious_event_found = true;
193 break;
194 case TaskEvent::START:
195 interleaved_task_detected = true;
196 break;
197 case TaskEvent::END:
198 if (event->i != current_task_i)
199 interleaved_task_detected = true;
200 else
201 current_task_i = -1;
202 break;
203 }
204
205 if (interleaved_task_detected) {
206 return ::testing::AssertionFailure()
207 << "Found event " << ::testing::PrintToString(*event)
208 << " between START and END events for task " << current_task_i
209 << "; event dump: " << ::testing::PrintToString(events);
210 }
211 }
212
213 if (spurious_event_found) {
214 const int event_i = event - events.begin();
215 return ::testing::AssertionFailure()
216 << "Spurious event " << ::testing::PrintToString(*event)
217 << " at position " << event_i << "; event dump: "
218 << ::testing::PrintToString(events);
219 }
220 }
221
222 return ::testing::AssertionSuccess();
223 }
224
225 } // namespace
226
227 ::testing::AssertionResult CheckNonNestableInvariants(
228 const std::vector<TaskEvent>& events,
229 int task_count) {
230 const std::vector<int> post_order =
231 GetEventTypeOrder(events, TaskEvent::POST);
232 const std::vector<int> start_order =
233 GetEventTypeOrder(events, TaskEvent::START);
234 const std::vector<int> end_order =
235 GetEventTypeOrder(events, TaskEvent::END);
236
237 if (start_order != post_order) {
238 return ::testing::AssertionFailure()
239 << "Expected START order (which equals actual POST order): \n"
240 << ::testing::PrintToString(post_order)
241 << "\n Actual START order:\n"
242 << ::testing::PrintToString(start_order);
243 }
244
245 if (end_order != post_order) {
246 return ::testing::AssertionFailure()
247 << "Expected END order (which equals actual POST order): \n"
248 << ::testing::PrintToString(post_order)
249 << "\n Actual END order:\n"
250 << ::testing::PrintToString(end_order);
251 }
252
253 const ::testing::AssertionResult result =
254 CheckEventOrdersForEachTask(events, task_count);
255 if (!result)
256 return result;
257
258 return CheckNoTaskRunsOverlap(events);
259 }
260
261 } // namespace internal
262
263 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698