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 // Returns after the tracker observes a total of |count| task completions. |
| 66 void WaitForCompletedTasks(int count); |
| 67 |
64 private: | 68 private: |
65 friend class RefCountedThreadSafe<SequencedTaskTracker>; | 69 friend class RefCountedThreadSafe<SequencedTaskTracker>; |
66 | 70 |
67 ~SequencedTaskTracker(); | 71 ~SequencedTaskTracker(); |
68 | 72 |
69 // A task which runs |task|, recording the start and end events. | 73 // A task which runs |task|, recording the start and end events. |
70 void RunTask(const Closure& task, int task_i); | 74 void RunTask(const Closure& task, int task_i); |
71 | 75 |
72 // Records a post event for task |i|. The owner is expected to be holding | 76 // Records a post event for task |i|. The owner is expected to be holding |
73 // |lock_| (unlike |TaskStarted| and |TaskEnded|). | 77 // |lock_| (unlike |TaskStarted| and |TaskEnded|). |
74 void TaskPosted(int i); | 78 void TaskPosted(int i); |
75 | 79 |
76 // Records a start event for task |i|. | 80 // Records a start event for task |i|. |
77 void TaskStarted(int i); | 81 void TaskStarted(int i); |
78 | 82 |
79 // Records a end event for task |i|. | 83 // Records a end event for task |i|. |
80 void TaskEnded(int i); | 84 void TaskEnded(int i); |
81 | 85 |
82 // Protects events_ and next_post_i_. | 86 // Protects events_, next_post_i_, task_end_count_ and task_end_cv_. |
83 Lock lock_; | 87 Lock lock_; |
84 | 88 |
85 // The events as they occurred for each task (protected by lock_). | 89 // The events as they occurred for each task (protected by lock_). |
86 std::vector<TaskEvent> events_; | 90 std::vector<TaskEvent> events_; |
87 | 91 |
88 // The ordinal to be used for the next task-posting task (protected by | 92 // The ordinal to be used for the next task-posting task (protected by |
89 // lock_). | 93 // lock_). |
90 int next_post_i_; | 94 int next_post_i_; |
91 | 95 |
| 96 // The number of task end events we've received. |
| 97 int task_end_count_; |
| 98 ConditionVariable task_end_cv_; |
| 99 |
92 DISALLOW_COPY_AND_ASSIGN(SequencedTaskTracker); | 100 DISALLOW_COPY_AND_ASSIGN(SequencedTaskTracker); |
93 }; | 101 }; |
94 | 102 |
95 void PrintTo(const TaskEvent& event, std::ostream* os); | 103 void PrintTo(const TaskEvent& event, std::ostream* os); |
96 | 104 |
97 // Checks the non-nestable task invariants for all tasks in |events|. | 105 // Checks the non-nestable task invariants for all tasks in |events|. |
98 // | 106 // |
99 // The invariants are: | 107 // The invariants are: |
100 // 1) Events started and ended in the same order that they were posted. | 108 // 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}, | 109 // 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. | 110 // 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 | 111 // 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. | 112 // other tasks. I.e. tasks were run sequentially, not interleaved. |
105 ::testing::AssertionResult CheckNonNestableInvariants( | 113 ::testing::AssertionResult CheckNonNestableInvariants( |
106 const std::vector<TaskEvent>& events, | 114 const std::vector<TaskEvent>& events, |
107 int task_count); | 115 int task_count); |
108 | 116 |
109 } // namespace internal | 117 } // namespace internal |
110 | 118 |
111 template <typename TaskRunnerTestDelegate> | 119 template <typename TaskRunnerTestDelegate> |
112 class SequencedTaskRunnerTest : public testing::Test { | 120 class SequencedTaskRunnerTest : public testing::Test { |
113 protected: | 121 protected: |
114 SequencedTaskRunnerTest() | 122 SequencedTaskRunnerTest() |
115 : task_tracker_(new internal::SequencedTaskTracker()) {} | 123 : task_tracker_(new internal::SequencedTaskTracker()) {} |
116 | 124 |
117 const scoped_refptr<internal::SequencedTaskTracker> task_tracker_; | 125 const scoped_refptr<internal::SequencedTaskTracker> task_tracker_; |
118 TaskRunnerTestDelegate delegate_; | 126 TaskRunnerTestDelegate delegate_; |
119 }; | 127 }; |
120 | 128 |
121 TYPED_TEST_CASE_P(SequencedTaskRunnerTest); | 129 TYPED_TEST_CASE_P(SequencedTaskRunnerTest); |
122 | 130 |
123 // This test posts N non-nestable tasks in sequence, and expects them to run | 131 // 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 | 132 // in FIFO order, with no part of any two tasks' execution |
125 // overlapping. I.e. that each task starts only after the previously-posted | 133 // 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 = | 192 const scoped_refptr<SequencedTaskRunner> task_runner = |
185 this->delegate_.GetTaskRunner(); | 193 this->delegate_.GetTaskRunner(); |
186 | 194 |
187 for (int i = 0; i < kTaskCount; ++i) { | 195 for (int i = 0; i < kTaskCount; ++i) { |
188 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 196 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
189 task_runner, | 197 task_runner, |
190 Closure(), | 198 Closure(), |
191 TimeDelta::FromMilliseconds(kDelayIncrementMs * i)); | 199 TimeDelta::FromMilliseconds(kDelayIncrementMs * i)); |
192 } | 200 } |
193 | 201 |
| 202 this->task_tracker_->WaitForCompletedTasks(kTaskCount); |
194 this->delegate_.StopTaskRunner(); | 203 this->delegate_.StopTaskRunner(); |
195 | 204 |
196 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 205 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
197 kTaskCount)); | 206 kTaskCount)); |
198 } | 207 } |
199 | 208 |
200 // This test posts a fast, non-nestable task from within each of a number of | 209 // 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 | 210 // 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. | 211 // were posted in and that there is no execution overlap whatsoever. |
203 TYPED_TEST_P(SequencedTaskRunnerTest, NonNestablePostFromNonNestableTask) { | 212 TYPED_TEST_P(SequencedTaskRunnerTest, NonNestablePostFromNonNestableTask) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 const int kTaskCount = 1; | 246 const int kTaskCount = 1; |
238 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100); | 247 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100); |
239 | 248 |
240 this->delegate_.StartTaskRunner(); | 249 this->delegate_.StartTaskRunner(); |
241 const scoped_refptr<SequencedTaskRunner> task_runner = | 250 const scoped_refptr<SequencedTaskRunner> task_runner = |
242 this->delegate_.GetTaskRunner(); | 251 this->delegate_.GetTaskRunner(); |
243 | 252 |
244 Time time_before_run = Time::Now(); | 253 Time time_before_run = Time::Now(); |
245 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 254 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
246 task_runner, Closure(), kDelay); | 255 task_runner, Closure(), kDelay); |
| 256 this->task_tracker_->WaitForCompletedTasks(kTaskCount); |
247 this->delegate_.StopTaskRunner(); | 257 this->delegate_.StopTaskRunner(); |
248 Time time_after_run = Time::Now(); | 258 Time time_after_run = Time::Now(); |
249 | 259 |
250 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 260 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
251 kTaskCount)); | 261 kTaskCount)); |
252 EXPECT_LE(kDelay, time_after_run - time_before_run); | 262 EXPECT_LE(kDelay, time_after_run - time_before_run); |
253 } | 263 } |
254 | 264 |
255 // This test posts two tasks with the same delay, and checks that the tasks are | 265 // 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. | 266 // run in the order in which they were posted. |
(...skipping 14 matching lines...) Expand all Loading... |
271 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100); | 281 const TimeDelta kDelay = TimeDelta::FromMilliseconds(100); |
272 | 282 |
273 this->delegate_.StartTaskRunner(); | 283 this->delegate_.StartTaskRunner(); |
274 const scoped_refptr<SequencedTaskRunner> task_runner = | 284 const scoped_refptr<SequencedTaskRunner> task_runner = |
275 this->delegate_.GetTaskRunner(); | 285 this->delegate_.GetTaskRunner(); |
276 | 286 |
277 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 287 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
278 task_runner, Closure(), kDelay); | 288 task_runner, Closure(), kDelay); |
279 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 289 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
280 task_runner, Closure(), kDelay); | 290 task_runner, Closure(), kDelay); |
| 291 this->task_tracker_->WaitForCompletedTasks(kTaskCount); |
281 this->delegate_.StopTaskRunner(); | 292 this->delegate_.StopTaskRunner(); |
282 | 293 |
283 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 294 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
284 kTaskCount)); | 295 kTaskCount)); |
285 } | 296 } |
286 | 297 |
287 // This test posts a normal task and a delayed task, and checks that the | 298 // 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 | 299 // delayed task runs after the normal task even if the normal task takes |
289 // a long time to run. | 300 // a long time to run. |
290 TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterLongTask) { | 301 TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterLongTask) { |
291 // TODO(akalin): Remove this check (http://crbug.com/149144). | 302 // TODO(akalin): Remove this check (http://crbug.com/149144). |
292 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { | 303 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { |
293 DLOG(INFO) << "This SequencedTaskRunner doesn't handle " | 304 DLOG(INFO) << "This SequencedTaskRunner doesn't handle " |
294 "non-zero delays; skipping"; | 305 "non-zero delays; skipping"; |
295 return; | 306 return; |
296 } | 307 } |
297 | 308 |
298 const int kTaskCount = 2; | 309 const int kTaskCount = 2; |
299 | 310 |
300 this->delegate_.StartTaskRunner(); | 311 this->delegate_.StartTaskRunner(); |
301 const scoped_refptr<SequencedTaskRunner> task_runner = | 312 const scoped_refptr<SequencedTaskRunner> task_runner = |
302 this->delegate_.GetTaskRunner(); | 313 this->delegate_.GetTaskRunner(); |
303 | 314 |
304 this->task_tracker_->PostWrappedNonNestableTask( | 315 this->task_tracker_->PostWrappedNonNestableTask( |
305 task_runner, base::Bind(&PlatformThread::Sleep, | 316 task_runner, base::Bind(&PlatformThread::Sleep, |
306 TimeDelta::FromMilliseconds(50))); | 317 TimeDelta::FromMilliseconds(50))); |
307 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 318 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
308 task_runner, Closure(), TimeDelta::FromMilliseconds(10)); | 319 task_runner, Closure(), TimeDelta::FromMilliseconds(10)); |
| 320 this->task_tracker_->WaitForCompletedTasks(kTaskCount); |
309 this->delegate_.StopTaskRunner(); | 321 this->delegate_.StopTaskRunner(); |
310 | 322 |
311 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 323 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
312 kTaskCount)); | 324 kTaskCount)); |
313 } | 325 } |
314 | 326 |
315 // Test that a pile of normal tasks and a delayed task run in the | 327 // Test that a pile of normal tasks and a delayed task run in the |
316 // time-to-run order. | 328 // time-to-run order. |
317 TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterManyLongTasks) { | 329 TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterManyLongTasks) { |
318 // TODO(akalin): Remove this check (http://crbug.com/149144). | 330 // TODO(akalin): Remove this check (http://crbug.com/149144). |
319 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { | 331 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { |
320 DLOG(INFO) << "This SequencedTaskRunner doesn't handle " | 332 DLOG(INFO) << "This SequencedTaskRunner doesn't handle " |
321 "non-zero delays; skipping"; | 333 "non-zero delays; skipping"; |
322 return; | 334 return; |
323 } | 335 } |
324 | 336 |
325 const int kTaskCount = 11; | 337 const int kTaskCount = 11; |
326 | 338 |
327 this->delegate_.StartTaskRunner(); | 339 this->delegate_.StartTaskRunner(); |
328 const scoped_refptr<SequencedTaskRunner> task_runner = | 340 const scoped_refptr<SequencedTaskRunner> task_runner = |
329 this->delegate_.GetTaskRunner(); | 341 this->delegate_.GetTaskRunner(); |
330 | 342 |
331 for (int i = 0; i < kTaskCount - 1; i++) { | 343 for (int i = 0; i < kTaskCount - 1; i++) { |
332 this->task_tracker_->PostWrappedNonNestableTask( | 344 this->task_tracker_->PostWrappedNonNestableTask( |
333 task_runner, base::Bind(&PlatformThread::Sleep, | 345 task_runner, base::Bind(&PlatformThread::Sleep, |
334 TimeDelta::FromMilliseconds(50))); | 346 TimeDelta::FromMilliseconds(50))); |
335 } | 347 } |
336 this->task_tracker_->PostWrappedDelayedNonNestableTask( | 348 this->task_tracker_->PostWrappedDelayedNonNestableTask( |
337 task_runner, Closure(), TimeDelta::FromMilliseconds(10)); | 349 task_runner, Closure(), TimeDelta::FromMilliseconds(10)); |
| 350 this->task_tracker_->WaitForCompletedTasks(kTaskCount); |
338 this->delegate_.StopTaskRunner(); | 351 this->delegate_.StopTaskRunner(); |
339 | 352 |
340 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), | 353 EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
341 kTaskCount)); | 354 kTaskCount)); |
342 } | 355 } |
343 | 356 |
344 | 357 |
345 // TODO(francoisk777@gmail.com) Add a test, similiar to the above, which runs | 358 // TODO(francoisk777@gmail.com) Add a test, similiar to the above, which runs |
346 // some tasked nestedly (which should be implemented in the test | 359 // some tasked nestedly (which should be implemented in the test |
347 // delegate). Also add, to the the test delegate, a predicate which checks | 360 // delegate). Also add, to the the test delegate, a predicate which checks |
348 // whether the implementation supports nested tasks. | 361 // whether the implementation supports nested tasks. |
349 // | 362 // |
350 | 363 |
351 REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerTest, | 364 REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerTest, |
352 SequentialNonNestable, | 365 SequentialNonNestable, |
353 SequentialNestable, | 366 SequentialNestable, |
354 SequentialDelayedNonNestable, | 367 SequentialDelayedNonNestable, |
355 NonNestablePostFromNonNestableTask, | 368 NonNestablePostFromNonNestableTask, |
356 DelayedTaskBasic, | 369 DelayedTaskBasic, |
357 DelayedTasksSameDelay, | 370 DelayedTasksSameDelay, |
358 DelayedTaskAfterLongTask, | 371 DelayedTaskAfterLongTask, |
359 DelayedTaskAfterManyLongTasks); | 372 DelayedTaskAfterManyLongTasks); |
360 | 373 |
361 } // namespace base | 374 } // namespace base |
362 | 375 |
363 #endif // BASE_TASK_RUNNER_TEST_TEMPLATE_H_ | 376 #endif // BASE_TASK_RUNNER_TEST_TEMPLATE_H_ |
OLD | NEW |