Chromium Code Reviews| Index: base/test/sequenced_task_runner_test_template.h |
| =================================================================== |
| --- base/test/sequenced_task_runner_test_template.h (revision 0) |
| +++ base/test/sequenced_task_runner_test_template.h (revision 0) |
| @@ -0,0 +1,244 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +// This class defines tests that implementations of SequencedTaskRunner should |
| +// pass in order to be conformant. See task_runner_test_template.h for a |
| +// description of how to use the constructs in this file; these work the same. |
| + |
| +#ifndef BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ |
| +#define BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ |
| +#pragma once |
| + |
| +#include <cstddef> |
| +#include <iosfwd> |
| +#include <vector> |
| + |
| +#include "base/basictypes.h" |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/sequenced_task_runner.h" |
| +#include "base/synchronization/lock.h" |
| +#include "base/time.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace base { |
| + |
| +namespace internal { |
| + |
| +// Utility class used in the tests below. |
| +class SequencedTaskTracker : public RefCountedThreadSafe<SequencedTaskTracker> { |
| + public: |
| + struct TaskEvent { |
|
akalin
2012/03/26 18:44:08
just pull out this struct, since it's already in a
Francois
2012/03/28 14:32:42
Done.
|
| + enum Type { POST, START, END }; |
| + TaskEvent(int i_in, Type type_in); |
|
akalin
2012/03/26 18:44:08
don't use _in, just name them the same
akalin
2012/03/26 18:44:08
define a default constructor and initialize both v
Francois
2012/03/28 14:32:42
Done.
Francois
2012/03/28 14:32:42
Why define a default constructor if it never gets
akalin
2012/03/29 18:44:38
Just defensive coding; the same reason why it's su
|
| + int i; |
| + Type type; |
| + }; |
| + |
| + SequencedTaskTracker(); |
| + |
| + // Posts the non-nestable task |task|, and records its post event. |
| + void PostWrappedNonNestableTask( |
|
akalin
2012/03/26 18:44:08
the index (int i) should be a member of these func
Francois
2012/03/28 14:32:42
Please see my comment right at the bottom.
|
| + const scoped_refptr<SequencedTaskRunner>& task_runner, |
| + const Closure& task); |
| + |
| + // Posts the nestable task |task|, and records its post event. |
| + void PostWrappedNestableTask( |
| + const scoped_refptr<SequencedTaskRunner>& task_runner, |
| + const Closure& task); |
| + |
| + // Posts the delayed non-nestable task |task|, and records its post event. |
| + void PostWrappedDelayedNonNestableTask( |
| + const scoped_refptr<SequencedTaskRunner>& task_runner, |
| + const Closure& task, |
| + TimeDelta delay); |
| + |
| + // Posts |task_count| non-nestable tasks. |
| + void PostNonNestableTasks( |
| + const scoped_refptr<SequencedTaskRunner>& task_runner, |
| + int task_count); |
| + |
| + const std::vector<TaskEvent>& GetTaskEvents() const; |
| + |
| + private: |
| + friend class RefCountedThreadSafe<SequencedTaskTracker>; |
| + |
| + ~SequencedTaskTracker(); |
| + |
| + // A task which runs |task|, recording the start and end events. |
| + void RunTask(const Closure& task, int task_i); |
| + |
| + // Records a post event for task |i|. The owner is expected to be holding |
| + // |lock_| (unlike |TaskStarted| and |TaskEnded|). |
| + void TaskPosted(int i); |
| + |
| + // Records a start event for task |i|. |
| + void TaskStarted(int i); |
| + |
| + // Records a end event for task |i|. |
| + void TaskEnded(int i); |
| + |
| + // Protects events_ and next_post_i_. |
|
akalin
2012/03/26 18:44:08
events_ only
Francois
2012/03/28 14:32:42
Please see my comment right at the bottom.
|
| + Lock lock_; |
| + |
| + // The events as they occurred for each task (protected by lock_). |
| + std::vector<TaskEvent> events_; |
| + |
| + // The ordinal to be used for the next task-posting task (protected by |
| + // lock_). |
| + int next_post_i_; |
|
akalin
2012/03/26 18:44:08
remove the need for this, since the index should b
Francois
2012/03/28 14:32:42
Please see my comment right at the bottom.
|
| + |
| + DISALLOW_COPY_AND_ASSIGN(SequencedTaskTracker); |
| +}; |
| + |
| +void PrintTo(const SequencedTaskTracker::TaskEvent& event, std::ostream* os); |
| + |
| +void SleepForOneSecond(); |
| + |
| +// Checks the non-nestable task invariants for all tasks in |events|. |
| +// |
| +// The invariants are: |
| +// 1) Events started and ended in the same order that they were posted. |
| +// 2) Events for an individual tasks occur in the order {POST, START, END}, |
| +// and there is only one instance of each event type for a task. |
| +// 3) The only events between a task's START and END events are the POSTs of |
| +// other tasks. I.e. tasks were run sequentially, not interleaved. |
| +::testing::AssertionResult CheckNonNestableInvariants( |
| + const std::vector<SequencedTaskTracker::TaskEvent>& events, |
| + int task_count); |
| + |
| +} // namespace internal |
| + |
| +template <typename TaskRunnerTestDelegate> |
| +class SequencedTaskRunnerTest : public testing::Test { |
| + protected: |
| + SequencedTaskRunnerTest() |
| + : task_tracker_(new internal::SequencedTaskTracker()) {} |
| + |
| + const scoped_refptr<internal::SequencedTaskTracker> task_tracker_; |
| + TaskRunnerTestDelegate delegate_; |
| +}; |
| + |
| +TYPED_TEST_CASE_P(SequencedTaskRunnerTest); |
| + |
| +// This test posts N non-nestable tasks in sequence, and expects them to run |
| +// in FIFO order, with no part of any two tasks' execution |
| +// overlapping. I.e. that each task starts only after the previously-posted |
| +// one has finished. |
| +TYPED_TEST_P(SequencedTaskRunnerTest, SequentialNonNestable) { |
| + const int task_count = 1000; |
| + |
| + this->delegate_.StartTaskRunner(); |
| + const scoped_refptr<SequencedTaskRunner> task_runner = |
| + this->delegate_.GetTaskRunner(); |
| + |
| + this->task_tracker_->PostWrappedNonNestableTask( |
| + task_runner, Bind(&internal::SleepForOneSecond)); |
|
akalin
2012/03/26 18:44:08
with the change above to pass i to PostWrappedNonN
Francois
2012/03/28 14:32:42
Please see my comment right at the bottom.
|
| + for (int i = 1; i < task_count; ++i) { |
| + this->task_tracker_->PostWrappedNonNestableTask(task_runner, Closure()); |
| + } |
| + |
| + this->delegate_.StopTaskRunner(); |
| + |
| + EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
| + task_count)); |
| +} |
| + |
| +// This test posts N nestable tasks in sequence. It has the same expectations |
| +// as SequentialNonNestable because even though the tasks are nestable, they |
| +// will not be run nestedly in this case. |
| +TYPED_TEST_P(SequencedTaskRunnerTest, SequentialNestable) { |
| + const int task_count = 1000; |
| + |
| + this->delegate_.StartTaskRunner(); |
| + const scoped_refptr<SequencedTaskRunner> task_runner = |
| + this->delegate_.GetTaskRunner(); |
| + |
| + this->task_tracker_->PostWrappedNestableTask( |
| + task_runner, |
| + Bind(&internal::SleepForOneSecond)); |
| + for (int i = 1; i < task_count; ++i) { |
| + this->task_tracker_->PostWrappedNestableTask(task_runner, Closure()); |
| + } |
| + |
| + this->delegate_.StopTaskRunner(); |
| + |
| + EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
| + task_count)); |
| +} |
| + |
| +// This test posts non-nestable tasks in order of increasing delay, and checks |
| +// that that the tasks are run in FIFO order and that there is no execution |
| +// overlap whatsoever between any two tasks. |
| +TYPED_TEST_P(SequencedTaskRunnerTest, SequentialDelayedNonNestable) { |
| + if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { |
| + DLOG(INFO) << "This SequencedTaskRunner doesn't handle " |
| + "non-zero delays; skipping"; |
| + return; |
| + } |
| + |
| + const int task_count = 20; |
| + const int delay_increment_ms = 50; |
| + |
| + this->delegate_.StartTaskRunner(); |
| + const scoped_refptr<SequencedTaskRunner> task_runner = |
| + this->delegate_.GetTaskRunner(); |
| + |
| + for (int i = 0; i < task_count; ++i) { |
| + this->task_tracker_->PostWrappedDelayedNonNestableTask( |
| + task_runner, |
| + Closure(), |
| + TimeDelta::FromMilliseconds(delay_increment_ms * i)); |
| + } |
| + |
| + this->delegate_.StopTaskRunner(); |
| + |
| + EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(), |
| + task_count)); |
| +} |
| + |
| +// This test posts a fast, non-nestable task from within each of a number of |
| +// slow, non-nestable tasks and checks that they all run in the sequence they |
| +// were posted in and that there is no execution overlap whatsoever. |
| +TYPED_TEST_P(SequencedTaskRunnerTest, NonNestablePostFromNonNestableTask) { |
| + const int parent_count = 10; |
| + const int children_per_parent = 10; |
| + |
| + this->delegate_.StartTaskRunner(); |
| + const scoped_refptr<SequencedTaskRunner> task_runner = |
| + this->delegate_.GetTaskRunner(); |
| + |
| + const int end = parent_count; |
| + for (int i = 0; i < end; ++i) { |
| + Closure task = Bind( |
| + &internal::SequencedTaskTracker::PostNonNestableTasks, |
| + this->task_tracker_, |
| + task_runner, |
| + children_per_parent); |
|
akalin
2012/03/26 18:44:08
probably would have to pass in a start/end index f
Francois
2012/03/28 14:32:42
This won't work for tests (such as NonNestablePost
|
| + this->task_tracker_->PostWrappedNonNestableTask(task_runner, task); |
| + } |
| + |
| + this->delegate_.StopTaskRunner(); |
| + |
| + EXPECT_TRUE(CheckNonNestableInvariants( |
| + this->task_tracker_->GetTaskEvents(), |
| + parent_count * (children_per_parent + 1))); |
| +} |
| + |
| +// TODO(francoisk777@gmail.com) Add a test, similiar to the above, which runs |
| +// some tasked nestedly (which should be implemented in the test |
| +// delegate). Also add, to the the test delegate, a predicate which checks |
| +// whether the implementation supports nested tasks. |
| +// |
| + |
| +REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerTest, |
| + SequentialNonNestable, |
| + SequentialNestable, |
| + SequentialDelayedNonNestable, |
| + NonNestablePostFromNonNestableTask); |
| + |
| +} // namespace base |
| + |
| +#endif // BASE_TASK_RUNNER_TEST_TEMPLATE_H_ |
| Property changes on: base/test/sequenced_task_runner_test_template.h |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |