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

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

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 // This class defines tests that implementations of SequencedTaskRunner should
6 // pass in order to be conformant. Here's how you use it to test your
7 // implementation.
8 //
9 // See task_runner_test_template.h for a description of how to use the
10 // constructs in this file; these work the same.
11
12 #ifndef BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
13 #define BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
14 #pragma once
15
16 #include <cstddef>
17
18 #include <vector>
19
20 #include "base/basictypes.h"
21 #include "base/bind.h"
22 #include "base/memory/ref_counted.h"
23 #include "base/synchronization/lock.h"
24 #include "base/sequenced_task_runner.h"
25 #include "base/tracked_objects.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 namespace base {
29
30 // Utility class used in the tests below.
31 class SeqTaskTracker : public RefCountedThreadSafe<SeqTaskTracker> {
akalin 2012/03/13 07:27:11 SeqTaskTracker -> SequencedTaskTracker (abbreviati
akalin 2012/03/13 07:27:11 put this class in the base::internal namespace (y
Francois 2012/03/14 15:43:31 Done.
Francois 2012/03/14 15:43:31 Done.
32 public:
33 // Keeps track of a task's run status. I.e. whether it has run to completion
34 // and whether its predecessor had run to completion by the time it started
35 // running.
36 class TaskStatus {
akalin 2012/03/13 07:27:11 Hmm I think this class may be overkill. I was thi
akalin 2012/03/13 20:00:10 Actually a few corrections. WrapTask should *not*
Francois 2012/03/14 15:43:31 I like your model because it mirrors the task hier
37 public:
38 TaskStatus();
39 TaskStatus(const TaskStatus& ts);
40 TaskStatus& operator=(const TaskStatus& ts);
41 bool operator==(const TaskStatus& ts) const;
42
43 // Claims ownership of this task status for a task.
44 bool Claim();
45 // Whether the owning task has run to completion yet.
46 bool Completed() const;
47 // Whether the previous task (the one which owns the preceding position in
48 // the task status vector) had finished by the time this one started.
49 bool PrevCompletedBefore() const;
50 // Declares that the owning task has run to completion.
51 void SetCompleted();
52 // Declares that the previous task had run to completion by the time the
53 // owning task started.
54 void SetPrevCompletedBefore(const bool b);
55
56 private:
57 mutable Lock lock_;
58 // Whether this status slot has been claimed by a task yet.
59 bool claimed_;
60 bool completed_;
61 // Whether the owning task has set the "completed" flag.
62 bool completed_set_;
63 bool prev_completed_;
64 // Whether the owning task has set the "previous completed" flag.
65 bool prev_completed_set_;
66 };
67
68 typedef std::vector<TaskStatus> TaskStatuses;
69
70 SeqTaskTracker();
71
72 // Pre-allocates memory for the non-nestable task statuses.
73 void SetNonNestableTaskCount(const std::size_t task_count);
akalin 2012/03/13 07:27:11 remove const (doesn't make sense for value paramet
Francois 2012/03/14 15:43:31 Done. But it does make sense to me :) If something
74
75 // Pre-allocates memory for the nestable task statuses.
76 void SetNestableTaskCount(const std::size_t task_count);
77
78 const TaskStatuses& GetNonNestableTaskStatuses() const;
79 const TaskStatuses& GetNestableTaskStatuses() const;
80
81 // A fast, non-nestable task.
82 void FastNonNestableTask(int base_status_i);
83
84 // A fast, nestable task.
85 void FastNestableTask(int parent_task_status_slot);
86
87 // A slow, non-nestable task (sleeps for 1 second).
88 void SlowNonNestableTask(int base_status_i);
89
90 // Posts a fast, non-nestable task from a slow, non-nestable one.
91 void PostFastNonNestableFromSlowNonNestable(
92 scoped_refptr<SequencedTaskRunner> tr,
akalin 2012/03/13 07:27:11 tr -> task_runner (abbreviations are discouraged)
Francois 2012/03/14 15:43:31 Done.
93 const int base_status_i,
94 const int child_count);
95
96 // Posts a fast, nestable task from a slow, non-nestable one.
97 void PostFastNestableFromSlowNonNestable(
98 scoped_refptr<SequencedTaskRunner> tr,
99 const int base_status_i,
100 const int child_count);
101
102 private:
103 friend class RefCountedThreadSafe<SeqTaskTracker>;
104
105 ~SeqTaskTracker();
106
107 // Finds the lowest-numbered non-nestable task status object, beginning at
108 // position |search_from|, which has not yet been claimed.
109 int ClaimNonNestableTaskStatus(const int search_from = 0);
akalin 2012/03/13 07:27:11 default arguments are prohibited by style guide
Francois 2012/03/14 15:43:31 Done.
110
111 // Finds the lowest-numbered nestable task status object, beginning at
112 // position |search_from|, which has not yet been claimed.
113 int ClaimNestableTaskStatus(const int search_from = 0);
akalin 2012/03/13 07:27:11 here too
Francois 2012/03/14 15:43:31 Done.
114
115 TaskStatuses nestable_statuses_;
116 TaskStatuses non_nestable_statuses_;
117
118 DISALLOW_COPY_AND_ASSIGN(SeqTaskTracker);
119 };
120
121 std::ostream& operator<<(std::ostream& os,
akalin 2012/03/13 07:27:11 a ToString() member function is preferred to overl
Francois 2012/03/14 15:43:31 OK, but I added this to customise the output of EX
122 const SeqTaskTracker::TaskStatus& ts);
123
124 template <typename TaskRunnerTestDelegate>
125 class SequencedTaskRunnerTest : public testing::Test {
126 protected:
127 SequencedTaskRunnerTest() : task_tracker_(new SeqTaskTracker()) {
128 good_task_status_prototype_.SetPrevCompletedBefore(true);
129 good_task_status_prototype_.SetCompleted();
130 }
131
132 const scoped_refptr<SeqTaskTracker> task_tracker_;
133 TaskRunnerTestDelegate delegate_;
134 SeqTaskTracker::TaskStatus good_task_status_prototype_;
135 };
136
137 TYPED_TEST_CASE_P(SequencedTaskRunnerTest);
138
139 // This test posts N non-nestable tasks in sequence, and expects them to run
140 // in FIFO order, with no part of any two tasks' execution overlapping.
141 //
142 // It checks that task0 was done by the time task1 started, and task2 only
143 // started after task1 had executed to completion, etc.
144 //
145 // The first task it starts is a slow one which runs for a second, giving the
146 // subsequent ones plenty of time to run if the implementation fails to
147 // enforce the non-nestable property.
148 TYPED_TEST_P(SequencedTaskRunnerTest, SequentialNonNestable) {
149 const int task_count = 1000;
150
151 this->task_tracker_->SetNonNestableTaskCount(task_count);
152 SeqTaskTracker::TaskStatuses expected_statuses(
153 task_count,
154 this->good_task_status_prototype_);
155
156 this->delegate_.StartTaskRunner();
157 scoped_refptr<SequencedTaskRunner> task_runner =
158 this->delegate_.GetTaskRunner();
159
160 for (int i = 0; i < task_count; ++i) {
161 Closure task;
162 if (i == 0) {
163 task = Bind(&SeqTaskTracker::SlowNonNestableTask,
164 this->task_tracker_, i);
165 } else {
166 task = Bind(&SeqTaskTracker::FastNonNestableTask,
167 this->task_tracker_, i);
168 }
169 task_runner->PostNonNestableTask(FROM_HERE, task);
170 }
171
172 this->delegate_.StopTaskRunner();
173
174 EXPECT_EQ(expected_statuses,
175 this->task_tracker_->GetNonNestableTaskStatuses());
176 }
177
178 // This test posts non-nestable tasks in order of increasing delay, and checks
179 // that that the tasks are run in FIFO order and that there is no execution
180 // overlap whatsoever between any two tasks.
181 //
182 // If there are 10 tasks, task1 is posted first with a delay of zero, followed
183 // by task2 with a delay of, say, 1, and so forth, until task10 is posted with
184 // a delay of 10. It then checks that task2 started after task1, and only
185 // after task1 had finished, and so forth.
186 TYPED_TEST_P(SequencedTaskRunnerTest, SequentialDelayedNonNestable) {
187 const int task_count = 20;
akalin 2012/03/13 07:27:11 if you change the logs in PostDelayed...Task to us
Francois 2012/03/14 15:43:31 Done.
188 const int delay_increment_ms = 50;
189
190 this->task_tracker_->SetNonNestableTaskCount(task_count);
191 SeqTaskTracker::TaskStatuses expected_statuses(
192 task_count,
193 this->good_task_status_prototype_);
194
195 this->delegate_.StartTaskRunner();
196 scoped_refptr<SequencedTaskRunner> task_runner =
197 this->delegate_.GetTaskRunner();
198
199 for (int i = 0; i < task_count; ++i) {
200 Closure task = Bind(&SeqTaskTracker::FastNonNestableTask,
201 this->task_tracker_, i);
202 task_runner->PostNonNestableDelayedTask(
203 FROM_HERE,
204 task,
205 TimeDelta::FromMilliseconds(delay_increment_ms * i));
206 }
207
208 this->delegate_.StopTaskRunner();
209
210 EXPECT_EQ(expected_statuses,
211 this->task_tracker_->GetNonNestableTaskStatuses());
212 }
213
214 // This test posts a fast, non-nestable task from within each of a number of
215 // slow, non-nestable tasks and checks that they all run in the sequence they
216 // were posted in and that there is no execution overlap whatsoever.
217 TYPED_TEST_P(SequencedTaskRunnerTest,
218 NonNestablePostFromNonNestableTask) {
219 const int parent_count = 1000;
220 const int children_per_parent = 2;
221 const int task_count = parent_count * (children_per_parent + 1);
222
223 this->task_tracker_->SetNonNestableTaskCount(task_count);
224 SeqTaskTracker::TaskStatuses expected_statuses(
225 task_count,
226 this->good_task_status_prototype_);
227
228 this->delegate_.StartTaskRunner();
229 scoped_refptr<SequencedTaskRunner> task_runner =
230 this->delegate_.GetTaskRunner();
231
232 const int end = parent_count;
233 for (int i = 0; i < end; ++i) {
234 Closure task = Bind(
235 &SeqTaskTracker::PostFastNonNestableFromSlowNonNestable,
236 this->task_tracker_,
237 task_runner,
238 i,
239 children_per_parent);
240 DLOG(INFO) << "XXX Posted parent task " << i;
241 task_runner->PostNonNestableTask(FROM_HERE, task);
242 }
243
244 this->delegate_.StopTaskRunner();
245
246 EXPECT_EQ(expected_statuses,
247 this->task_tracker_->GetNonNestableTaskStatuses());
248 }
249
250 // This test posts a number of fast, nestable tasks from within each of a
251 // number of slow, non-nestable tasks and checks that the non-nestable ones
252 // all run in the sequence they were posted in and that there is no execution
253 // overlap whatsoever.
254 TYPED_TEST_P(SequencedTaskRunnerTest,
255 NestablePostFromNonNestableTask) {
256 const int parent_count = 500;
257 const int children_per_parent = 2;
258
259 this->task_tracker_->SetNonNestableTaskCount(parent_count);
260 SeqTaskTracker::TaskStatuses expected_non_nestable_statuses(
261 parent_count,
262 this->good_task_status_prototype_);
263 this->task_tracker_->SetNestableTaskCount(children_per_parent * parent_count);
264 SeqTaskTracker::TaskStatuses expected_nestable_statuses(
265 children_per_parent * parent_count,
266 this->good_task_status_prototype_);
267
268 this->delegate_.StartTaskRunner();
269 scoped_refptr<SequencedTaskRunner> task_runner =
270 this->delegate_.GetTaskRunner();
271
272 const int end = parent_count;
273 for (int i = 0; i < end; ++i) {
274 Closure task = Bind(
275 &SeqTaskTracker::PostFastNestableFromSlowNonNestable,
276 this->task_tracker_,
277 task_runner,
278 i,
279 children_per_parent);
280 task_runner->PostNonNestableTask(FROM_HERE, task);
281 }
282
283 this->delegate_.StopTaskRunner();
284
285 EXPECT_EQ(expected_non_nestable_statuses,
286 this->task_tracker_->GetNonNestableTaskStatuses());
287 EXPECT_EQ(expected_nestable_statuses,
288 this->task_tracker_->GetNestableTaskStatuses());
289 }
290
akalin 2012/03/13 07:27:11 Add a TODO for a test similar to the above, but ha
Francois 2012/03/14 15:43:31 Done.
291 REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerTest,
292 SequentialNonNestable,
293 SequentialDelayedNonNestable,
294 NonNestablePostFromNonNestableTask,
295 NestablePostFromNonNestableTask);
296
297 } // namespace base
298
299 #endif //#define BASE_TASK_RUNNER_TEST_TEMPLATE_H_
akalin 2012/03/13 07:27:11 no '#define' in comment
Francois 2012/03/14 15:43:31 Done.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698