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

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 <algorithm>
19 #include <vector>
20
21 #include "base/basictypes.h"
22 #include "base/bind.h"
23 #include "base/memory/ref_counted.h"
24 #include "base/sequenced_task_runner.h"
25 #include "base/synchronization/lock.h"
26 #include "base/tracked_objects.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 namespace base {
30
31 namespace internal {
32
33 // Utility class used in the tests below.
34 class SequencedTaskTracker : public RefCountedThreadSafe<SequencedTaskTracker> {
35 public:
36 SequencedTaskTracker();
37
38 int GetNextPostOrdinal();
39
40 void TaskPosted(int i);
41 void TaskStarted(int i);
42 void TaskEnded(int i);
43
44 const std::vector<int>& GetPostOrder() const;
45 const std::vector<int>& GetStartOrder() const;
46 const std::vector<int>& GetEndOrder() const;
47
48 void FastTask(int i);
49 void SlowTask(int i);
50
51 // Task which posts a fast, non-nestable task.
52 void PostFastNonNestableFromSlowNonNestable(
53 scoped_refptr<SequencedTaskRunner> task_runner,
54 const int base_status_i,
55 const int child_count);
56
57 private:
58 friend class RefCountedThreadSafe<SequencedTaskTracker>;
59
60 ~SequencedTaskTracker();
61
62 public:
63 std::vector<int> post_events_;
64 mutable Lock post_lock_;
65
66 private:
67 std::vector<int> start_events_;
68 mutable Lock start_lock_;
69
70 std::vector<int> end_events_;
71 mutable Lock end_lock_;
72
73 int next_post_i_;
74
75 DISALLOW_COPY_AND_ASSIGN(SequencedTaskTracker);
76 };
77
78 } // namespace internal
79
80 template <typename TaskRunnerTestDelegate>
81 class SequencedTaskRunnerTest : public testing::Test {
82 protected:
83 SequencedTaskRunnerTest()
84 : task_tracker_(new internal::SequencedTaskTracker()) {}
85
86 const scoped_refptr<internal::SequencedTaskTracker> task_tracker_;
87 TaskRunnerTestDelegate delegate_;
88 };
89
90 TYPED_TEST_CASE_P(SequencedTaskRunnerTest);
91
92 // This test posts N non-nestable tasks in sequence, and expects them to run
93 // in FIFO order, with no part of any two tasks' execution overlapping.
94 //
95 // It checks that task0 was done by the time task1 started, and task2 only
96 // started after task1 had executed to completion, etc.
97 //
98 // The first task it starts is a slow one which runs for a second, giving the
99 // subsequent ones plenty of time to run if the implementation fails to
100 // enforce the non-nestable property.
101 TYPED_TEST_P(SequencedTaskRunnerTest, SequentialNonNestable) {
102 const int task_count = 1000;
103
104 this->delegate_.StartTaskRunner();
105 scoped_refptr<SequencedTaskRunner> task_runner =
106 this->delegate_.GetTaskRunner();
107
108 for (int i = 0; i < task_count; ++i) {
109 Closure task;
110 if (i == 0) {
111 task = Bind(&internal::SequencedTaskTracker::SlowTask,
112 this->task_tracker_, i);
113 } else {
114 task = Bind(&internal::SequencedTaskTracker::FastTask,
115 this->task_tracker_, i);
116 }
117 this->task_tracker_->TaskPosted(i);
118 task_runner->PostNonNestableTask(FROM_HERE, task);
119 }
120
121 this->delegate_.StopTaskRunner();
122
123 EXPECT_EQ(this->task_tracker_->GetPostOrder(),
124 this->task_tracker_->GetStartOrder());
125 EXPECT_EQ(this->task_tracker_->GetEndOrder(),
126 this->task_tracker_->GetStartOrder());
127 }
128
129 // This test posts N nestable tasks in sequence, and expects them to run in
130 // FIFO order; overlapping execution is allowed.
131 //
132 // It checks only that task_i had started by the time task_i+1 started, for
133 // increasing values of i. Thus it verifies the SequencedTaskRunner guarantee
134 // that nested tasks are run in FIFO order.
135 //
136 // The first task it starts is a slow one which runs for a second, giving the
137 // subsequent ones plenty of time to run in if the implementation fails to
138 // enforce the FIFO property for nestable tasks.
139 TYPED_TEST_P(SequencedTaskRunnerTest, FAILS_SequentialNestable) {
140 const int task_count = 10;
141
142 this->delegate_.StartTaskRunner();
143 scoped_refptr<SequencedTaskRunner> task_runner =
144 this->delegate_.GetTaskRunner();
145
146 for (int i = 0; i < task_count; ++i) {
147 Closure task;
148 if (i == 0) {
149 task = Bind(&internal::SequencedTaskTracker::SlowTask,
150 this->task_tracker_, i);
151 } else {
152 task = Bind(&internal::SequencedTaskTracker::FastTask,
153 this->task_tracker_, i);
154 }
155 this->task_tracker_->TaskPosted(i);
156 task_runner->PostTask(FROM_HERE, task);
157 }
158
159 this->delegate_.StopTaskRunner();
160
161 const std::vector<int>& post_events = this->task_tracker_->GetPostOrder();
162 const std::vector<int>& end_events = this->task_tracker_->GetEndOrder();
163
164 EXPECT_EQ(post_events, this->task_tracker_->GetStartOrder());
165
166 // Check that all posted tasks finished.
167 for (std::size_t i = 0; i < post_events.size(); ++i) {
168 EXPECT_NE(std::find(end_events.begin(), end_events.end(), post_events[i]),
169 end_events.end());
170 }
171 }
172
173 // This test posts non-nestable tasks in order of increasing delay, and checks
174 // that that the tasks are run in FIFO order and that there is no execution
175 // overlap whatsoever between any two tasks.
176 //
177 // If there are 10 tasks, task1 is posted first with a delay of zero, followed
178 // by task2 with a delay of, say, 1, and so forth, until task10 is posted with
179 // a delay of 10. It then checks that task2 started after task1, and only
180 // after task1 had finished, and so forth.
181 TYPED_TEST_P(SequencedTaskRunnerTest, SequentialDelayedNonNestable) {
182 const int task_count = 20;
183 const int delay_increment_ms = 50;
184
185 this->delegate_.StartTaskRunner();
186 scoped_refptr<SequencedTaskRunner> task_runner =
187 this->delegate_.GetTaskRunner();
188
189 for (int i = 0; i < task_count; ++i) {
190 Closure task = Bind(&internal::SequencedTaskTracker::FastTask,
191 this->task_tracker_, i);
192 this->task_tracker_->TaskPosted(i);
193 task_runner->PostNonNestableDelayedTask(
194 FROM_HERE,
195 task,
196 TimeDelta::FromMilliseconds(delay_increment_ms * i));
197 }
198
199 this->delegate_.StopTaskRunner();
200
201 EXPECT_EQ(this->task_tracker_->GetPostOrder(),
202 this->task_tracker_->GetStartOrder());
203 EXPECT_EQ(this->task_tracker_->GetStartOrder(),
204 this->task_tracker_->GetEndOrder());
205 }
206
207 // This test posts a fast, non-nestable task from within each of a number of
208 // slow, non-nestable tasks and checks that they all run in the sequence they
209 // were posted in and that there is no execution overlap whatsoever.
210 TYPED_TEST_P(SequencedTaskRunnerTest, NonNestablePostFromNonNestableTask) {
211 const int parent_count = 1000;
212 const int children_per_parent = 2;
213
214 this->delegate_.StartTaskRunner();
215 scoped_refptr<SequencedTaskRunner> task_runner =
216 this->delegate_.GetTaskRunner();
217
218 const int end = parent_count;
219 for (int i = 0; i < end; ++i) {
220 base::PlatformThread::YieldCurrentThread();
221 AutoLock post_lock(this->task_tracker_->post_lock_);
222 const int post_i = this->task_tracker_->GetNextPostOrdinal();
223 Closure task = Bind(
224 &internal::SequencedTaskTracker::PostFastNonNestableFromSlowNonNestable,
225 this->task_tracker_,
226 task_runner,
227 post_i,
228 children_per_parent);
229 this->task_tracker_->post_events_.push_back(post_i);
230 task_runner->PostNonNestableTask(FROM_HERE, task);
Francois 2012/03/18 16:28:29 The loop body is messy, but I want to hear your co
231 }
232
233 this->delegate_.StopTaskRunner();
234
235 EXPECT_EQ(this->task_tracker_->GetPostOrder(),
236 this->task_tracker_->GetStartOrder());
237 EXPECT_EQ(this->task_tracker_->GetEndOrder(),
238 this->task_tracker_->GetStartOrder());
239 }
240
241 // TODO(francoisk777@gmail.com) Add a test, similiar to the above, which which
242 // runs some tasked nestedly (which should be implemented in the test
243 // delegate). Also add, to the the test delegate, a predicate which checks
244 // whether the implementation supports nested tasks.
245
246 REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerTest,
247 SequentialNonNestable,
248 FAILS_SequentialNestable,
249 SequentialDelayedNonNestable,
250 NonNestablePostFromNonNestableTask);
251
252 } // namespace base
253
254 #endif // BASE_TASK_RUNNER_TEST_TEMPLATE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698