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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/base.gypi ('k') | base/test/sequenced_task_runner_test_template.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,243 @@
+// 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 {
+
+struct TaskEvent {
+ enum Type { POST, START, END };
+ TaskEvent(int i, Type type);
+ int i;
+ Type type;
+};
+
+// Utility class used in the tests below.
+class SequencedTaskTracker : public RefCountedThreadSafe<SequencedTaskTracker> {
+ public:
+ SequencedTaskTracker();
+
+ // Posts the non-nestable task |task|, and records its post event.
+ void PostWrappedNonNestableTask(
+ 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_.
+ 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_;
+
+ DISALLOW_COPY_AND_ASSIGN(SequencedTaskTracker);
+};
+
+void PrintTo(const 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<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));
+ 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();
+
+ for (int i = 0; i < parent_count; ++i) {
+ Closure task = Bind(
+ &internal::SequencedTaskTracker::PostNonNestableTasks,
+ this->task_tracker_,
+ task_runner,
+ children_per_parent);
+ 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
« no previous file with comments | « base/base.gypi ('k') | base/test/sequenced_task_runner_test_template.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698