OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This class defines tests that implementations of SequencedTaskRunner should | 5 // This class defines tests that implementations of SequencedTaskRunner should |
6 // pass in order to be conformant. See task_runner_test_template.h for a | 6 // pass in order to be conformant. See task_runner_test_template.h for a |
7 // description of how to use the constructs in this file; these work the same. | 7 // description of how to use the constructs in this file; these work the same. |
8 | 8 |
9 #ifndef BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ | 9 #ifndef BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ |
10 #define BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ | 10 #define BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ |
11 | 11 |
12 #include <cstddef> | 12 #include <cstddef> |
13 #include <iosfwd> | 13 #include <iosfwd> |
14 #include <vector> | 14 #include <vector> |
15 | 15 |
16 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
17 #include "base/bind.h" | 17 #include "base/bind.h" |
18 #include "base/callback.h" | 18 #include "base/callback.h" |
19 #include "base/memory/ref_counted.h" | 19 #include "base/memory/ref_counted.h" |
20 #include "base/sequenced_task_runner.h" | 20 #include "base/sequenced_task_runner.h" |
21 #include "base/synchronization/condition_variable.h" | |
21 #include "base/synchronization/lock.h" | 22 #include "base/synchronization/lock.h" |
22 #include "base/time.h" | 23 #include "base/time.h" |
23 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
24 | 25 |
25 namespace base { | 26 namespace base { |
26 | 27 |
27 namespace internal { | 28 namespace internal { |
28 | 29 |
29 struct TaskEvent { | 30 struct TaskEvent { |
30 enum Type { POST, START, END }; | 31 enum Type { POST, START, END }; |
(...skipping 23 matching lines...) Expand all Loading... | |
54 const Closure& task, | 55 const Closure& task, |
55 TimeDelta delay); | 56 TimeDelta delay); |
56 | 57 |
57 // Posts |task_count| non-nestable tasks. | 58 // Posts |task_count| non-nestable tasks. |
58 void PostNonNestableTasks( | 59 void PostNonNestableTasks( |
59 const scoped_refptr<SequencedTaskRunner>& task_runner, | 60 const scoped_refptr<SequencedTaskRunner>& task_runner, |
60 int task_count); | 61 int task_count); |
61 | 62 |
62 const std::vector<TaskEvent>& GetTaskEvents() const; | 63 const std::vector<TaskEvent>& GetTaskEvents() const; |
63 | 64 |
65 void WaitForTasksToComplete(int count); | |
66 | |
64 private: | 67 private: |
65 friend class RefCountedThreadSafe<SequencedTaskTracker>; | 68 friend class RefCountedThreadSafe<SequencedTaskTracker>; |
66 | 69 |
67 ~SequencedTaskTracker(); | 70 ~SequencedTaskTracker(); |
68 | 71 |
69 // A task which runs |task|, recording the start and end events. | 72 // A task which runs |task|, recording the start and end events. |
70 void RunTask(const Closure& task, int task_i); | 73 void RunTask(const Closure& task, int task_i); |
71 | 74 |
72 // Records a post event for task |i|. The owner is expected to be holding | 75 // Records a post event for task |i|. The owner is expected to be holding |
73 // |lock_| (unlike |TaskStarted| and |TaskEnded|). | 76 // |lock_| (unlike |TaskStarted| and |TaskEnded|). |
74 void TaskPosted(int i); | 77 void TaskPosted(int i); |
75 | 78 |
76 // Records a start event for task |i|. | 79 // Records a start event for task |i|. |
77 void TaskStarted(int i); | 80 void TaskStarted(int i); |
78 | 81 |
79 // Records a end event for task |i|. | 82 // Records a end event for task |i|. |
80 void TaskEnded(int i); | 83 void TaskEnded(int i); |
81 | 84 |
82 // Protects events_ and next_post_i_. | 85 // Protects events_, next_post_i_, task_end_count_ and task_end_cv_. |
83 Lock lock_; | 86 Lock lock_; |
84 | 87 |
85 // The events as they occurred for each task (protected by lock_). | 88 // The events as they occurred for each task (protected by lock_). |
86 std::vector<TaskEvent> events_; | 89 std::vector<TaskEvent> events_; |
87 | 90 |
88 // The ordinal to be used for the next task-posting task (protected by | 91 // The ordinal to be used for the next task-posting task (protected by |
89 // lock_). | 92 // lock_). |
90 int next_post_i_; | 93 int next_post_i_; |
91 | 94 |
95 // The number of task ends we've received. | |
96 int task_end_count_; | |
97 ConditionVariable task_end_cv_; | |
98 | |
92 DISALLOW_COPY_AND_ASSIGN(SequencedTaskTracker); | 99 DISALLOW_COPY_AND_ASSIGN(SequencedTaskTracker); |
93 }; | 100 }; |
94 | 101 |
95 void PrintTo(const TaskEvent& event, std::ostream* os); | 102 void PrintTo(const TaskEvent& event, std::ostream* os); |
96 | 103 |
97 // Checks the non-nestable task invariants for all tasks in |events|. | 104 // Checks the non-nestable task invariants for all tasks in |events|. |
98 // | 105 // |
99 // The invariants are: | 106 // The invariants are: |
100 // 1) Events started and ended in the same order that they were posted. | 107 // 1) Events started and ended in the same order that they were posted. |
101 // 2) Events for an individual tasks occur in the order {POST, START, END}, | 108 // 2) Events for an individual tasks occur in the order {POST, START, END}, |
102 // and there is only one instance of each event type for a task. | 109 // and there is only one instance of each event type for a task. |
103 // 3) The only events between a task's START and END events are the POSTs of | 110 // 3) The only events between a task's START and END events are the POSTs of |
104 // other tasks. I.e. tasks were run sequentially, not interleaved. | 111 // other tasks. I.e. tasks were run sequentially, not interleaved. |
105 ::testing::AssertionResult CheckNonNestableInvariants( | 112 ::testing::AssertionResult CheckNonNestableInvariants( |
106 const std::vector<TaskEvent>& events, | 113 const std::vector<TaskEvent>& events, |
107 int task_count); | 114 int task_count); |
108 | 115 |
109 } // namespace internal | 116 } // namespace internal |
110 | 117 |
111 template <typename TaskRunnerTestDelegate> | 118 template <typename TaskRunnerTestDelegate> |
112 class SequencedTaskRunnerTest : public testing::Test { | 119 class SequencedTaskRunnerTest : public testing::Test { |
113 protected: | 120 protected: |
114 SequencedTaskRunnerTest() | 121 SequencedTaskRunnerTest() |
115 : task_tracker_(new internal::SequencedTaskTracker()) {} | 122 : task_tracker_(new internal::SequencedTaskTracker()) {} |
jar (doing other things)
2013/02/22 23:39:47
nit: indent 4 more.
michaeln
2013/02/23 01:10:16
Done.
| |
116 | 123 |
117 const scoped_refptr<internal::SequencedTaskTracker> task_tracker_; | 124 const scoped_refptr<internal::SequencedTaskTracker> task_tracker_; |
118 TaskRunnerTestDelegate delegate_; | 125 TaskRunnerTestDelegate delegate_; |
119 }; | 126 }; |
120 | 127 |
121 TYPED_TEST_CASE_P(SequencedTaskRunnerTest); | 128 TYPED_TEST_CASE_P(SequencedTaskRunnerTest); |
122 | 129 |
123 // This test posts N non-nestable tasks in sequence, and expects them to run | 130 // This test posts N non-nestable tasks in sequence, and expects them to run |
124 // in FIFO order, with no part of any two tasks' execution | 131 // in FIFO order, with no part of any two tasks' execution |
125 // overlapping. I.e. that each task starts only after the previously-posted | 132 // overlapping. I.e. that each task starts only after the previously-posted |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 const scoped_refptr<SequencedTaskRunner> task_runner = | 191 const scoped_refptr<SequencedTaskRunner> task_runner = |
185 this->delegate_.GetTaskRunner(); | 192 this->delegate_.GetTaskRunner(); |
186 | 193 |
187 for (int i = 0; i < kTaskCount; ++i) { | 194 for (int i = 0; i < kTaskCount; ++i) { |
188 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 195 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
189 task_runner, | 196 task_runner, |
190 Closure(), | 197 Closure(), |
191 TimeDelta::FromMilliseconds(kDelayIncrementMs * i)); | 198 TimeDelta::FromMilliseconds(kDelayIncrementMs * i)); |
192 } | 199 } |
193 | 200 |
201 this->task_tracker_->WaitForTasksToComplete(kTaskCount); | |
194 this->delegate_.StopTaskRunner(); | 202 this->delegate_.StopTaskRunner(); |
195 | 203 |
196 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 204 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
197 kTaskCount)); | 205 kTaskCount)); |
198 } | 206 } |
199 | 207 |
200 // This test posts a fast, non-nestable task from within each of a number of | 208 // This test posts a fast, non-nestable task from within each of a number of |
201 // slow, non-nestable tasks and checks that they all run in the sequence they | 209 // slow, non-nestable tasks and checks that they all run in the sequence they |
202 // were posted in and that there is no execution overlap whatsoever. | 210 // were posted in and that there is no execution overlap whatsoever. |
203 TYPED_TEST_P(SequencedTaskRunnerTest, NonNestablePostFromNonNestableTask) { | 211 TYPED_TEST_P(SequencedTaskRunnerTest, NonNestablePostFromNonNestableTask) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
237 const int kTaskCount = 1; | 245 const int kTaskCount = 1; |
238 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100); | 246 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100); |
239 | 247 |
240 this->delegate_.StartTaskRunner(); | 248 this->delegate_.StartTaskRunner(); |
241 const scoped_refptr<SequencedTaskRunner> task_runner = | 249 const scoped_refptr<SequencedTaskRunner> task_runner = |
242 this->delegate_.GetTaskRunner(); | 250 this->delegate_.GetTaskRunner(); |
243 | 251 |
244 Time time_before_run = Time::Now(); | 252 Time time_before_run = Time::Now(); |
245 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 253 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
246 task_runner, Closure(), kDelay); | 254 task_runner, Closure(), kDelay); |
255 this->task_tracker_->WaitForTasksToComplete(1); | |
247 this->delegate_.StopTaskRunner(); | 256 this->delegate_.StopTaskRunner(); |
248 Time time_after_run = Time::Now(); | 257 Time time_after_run = Time::Now(); |
249 | 258 |
250 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 259 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
251 kTaskCount)); | 260 kTaskCount)); |
252 EXPECT_LE(kDelay, time_after_run - time_before_run); | 261 EXPECT_LE(kDelay, time_after_run - time_before_run); |
253 } | 262 } |
254 | 263 |
255 // This test posts two tasks with the same delay, and checks that the tasks are | 264 // This test posts two tasks with the same delay, and checks that the tasks are |
256 // run in the order in which they were posted. | 265 // run in the order in which they were posted. |
(...skipping 14 matching lines...) Expand all Loading... | |
271 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100); | 280 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100); |
272 | 281 |
273 this->delegate_.StartTaskRunner(); | 282 this->delegate_.StartTaskRunner(); |
274 const scoped_refptr<SequencedTaskRunner> task_runner = | 283 const scoped_refptr<SequencedTaskRunner> task_runner = |
275 this->delegate_.GetTaskRunner(); | 284 this->delegate_.GetTaskRunner(); |
276 | 285 |
277 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 286 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
278 task_runner, Closure(), kDelay); | 287 task_runner, Closure(), kDelay); |
279 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 288 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
280 task_runner, Closure(), kDelay); | 289 task_runner, Closure(), kDelay); |
290 this->task_tracker_->WaitForTasksToComplete(kTaskCount); | |
281 this->delegate_.StopTaskRunner(); | 291 this->delegate_.StopTaskRunner(); |
282 | 292 |
283 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 293 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
284 kTaskCount)); | 294 kTaskCount)); |
285 } | 295 } |
286 | 296 |
287 // This test posts a normal task and a delayed task, and checks that the | 297 // This test posts a normal task and a delayed task, and checks that the |
288 // delayed task runs after the normal task even if the normal task takes | 298 // delayed task runs after the normal task even if the normal task takes |
289 // a long time to run. | 299 // a long time to run. |
290 TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterLongTask) { | 300 TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterLongTask) { |
291 // TODO(akalin): Remove this check (http://crbug.com/149144). | 301 // TODO(akalin): Remove this check (http://crbug.com/149144). |
292 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { | 302 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { |
293 DLOG(INFO) << "This SequencedTaskRunner doesn't handle " | 303 DLOG(INFO) << "This SequencedTaskRunner doesn't handle " |
294 "non-zero delays; skipping"; | 304 "non-zero delays; skipping"; |
295 return; | 305 return; |
296 } | 306 } |
297 | 307 |
298 const int kTaskCount = 2; | 308 const int kTaskCount = 2; |
299 | 309 |
300 this->delegate_.StartTaskRunner(); | 310 this->delegate_.StartTaskRunner(); |
301 const scoped_refptr<SequencedTaskRunner> task_runner = | 311 const scoped_refptr<SequencedTaskRunner> task_runner = |
302 this->delegate_.GetTaskRunner(); | 312 this->delegate_.GetTaskRunner(); |
303 | 313 |
304 this->task_tracker_->PostWrappedNonNestableTask( | 314 this->task_tracker_->PostWrappedNonNestableTask( |
305 task_runner, base::Bind(&PlatformThread::Sleep, | 315 task_runner, base::Bind(&PlatformThread::Sleep, |
306 TimeDelta::FromMilliseconds(50))); | 316 TimeDelta::FromMilliseconds(50))); |
307 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 317 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
308 task_runner, Closure(), TimeDelta::FromMilliseconds(10)); | 318 task_runner, Closure(), TimeDelta::FromMilliseconds(10)); |
319 this->task_tracker_->WaitForTasksToComplete(kTaskCount); | |
309 this->delegate_.StopTaskRunner(); | 320 this->delegate_.StopTaskRunner(); |
310 | 321 |
311 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 322 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
312 kTaskCount)); | 323 kTaskCount)); |
313 } | 324 } |
314 | 325 |
315 // Test that a pile of normal tasks and a delayed task run in the | 326 // Test that a pile of normal tasks and a delayed task run in the |
316 // time-to-run order. | 327 // time-to-run order. |
317 TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterManyLongTasks) { | 328 TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterManyLongTasks) { |
318 // TODO(akalin): Remove this check (http://crbug.com/149144). | 329 // TODO(akalin): Remove this check (http://crbug.com/149144). |
319 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { | 330 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { |
320 DLOG(INFO) << "This SequencedTaskRunner doesn't handle " | 331 DLOG(INFO) << "This SequencedTaskRunner doesn't handle " |
321 "non-zero delays; skipping"; | 332 "non-zero delays; skipping"; |
322 return; | 333 return; |
323 } | 334 } |
324 | 335 |
325 const int kTaskCount = 11; | 336 const int kTaskCount = 11; |
326 | 337 |
327 this->delegate_.StartTaskRunner(); | 338 this->delegate_.StartTaskRunner(); |
328 const scoped_refptr<SequencedTaskRunner> task_runner = | 339 const scoped_refptr<SequencedTaskRunner> task_runner = |
329 this->delegate_.GetTaskRunner(); | 340 this->delegate_.GetTaskRunner(); |
330 | 341 |
331 for (int i = 0; i < kTaskCount - 1; i++) { | 342 for (int i = 0; i < kTaskCount - 1; i++) { |
332 this->task_tracker_->PostWrappedNonNestableTask( | 343 this->task_tracker_->PostWrappedNonNestableTask( |
333 task_runner, base::Bind(&PlatformThread::Sleep, | 344 task_runner, base::Bind(&PlatformThread::Sleep, |
334 TimeDelta::FromMilliseconds(50))); | 345 TimeDelta::FromMilliseconds(50))); |
335 } | 346 } |
336 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 347 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
337 task_runner, Closure(), TimeDelta::FromMilliseconds(10)); | 348 task_runner, Closure(), TimeDelta::FromMilliseconds(10)); |
349 this->task_tracker_->WaitForTasksToComplete(kTaskCount); | |
338 this->delegate_.StopTaskRunner(); | 350 this->delegate_.StopTaskRunner(); |
339 | 351 |
340 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 352 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
341 kTaskCount)); | 353 kTaskCount)); |
342 } | 354 } |
343 | 355 |
344 | 356 |
345 // TODO(francoisk777@gmail.com) Add a test, similiar to the above, which runs | 357 // TODO(francoisk777@gmail.com) Add a test, similiar to the above, which runs |
346 // some tasked nestedly (which should be implemented in the test | 358 // some tasked nestedly (which should be implemented in the test |
347 // delegate). Also add, to the the test delegate, a predicate which checks | 359 // delegate). Also add, to the the test delegate, a predicate which checks |
348 // whether the implementation supports nested tasks. | 360 // whether the implementation supports nested tasks. |
349 // | 361 // |
350 | 362 |
351 REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerTest, | 363 REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerTest, |
352 SequentialNonNestable, | 364 SequentialNonNestable, |
353 SequentialNestable, | 365 SequentialNestable, |
354 SequentialDelayedNonNestable, | 366 SequentialDelayedNonNestable, |
355 NonNestablePostFromNonNestableTask, | 367 NonNestablePostFromNonNestableTask, |
356 DelayedTaskBasic, | 368 DelayedTaskBasic, |
357 DelayedTasksSameDelay, | 369 DelayedTasksSameDelay, |
358 DelayedTaskAfterLongTask, | 370 DelayedTaskAfterLongTask, |
359 DelayedTaskAfterManyLongTasks); | 371 DelayedTaskAfterManyLongTasks); |
360 | 372 |
361 } // namespace base | 373 } // namespace base |
362 | 374 |
363 #endif // BASE_TASK_RUNNER_TEST_TEMPLATE_H_ | 375 #endif // BASE_TASK_RUNNER_TEST_TEMPLATE_H_ |
OLD | NEW |