| Index: base/task_runner_test_template.h
|
| diff --git a/base/task_runner_test_template.h b/base/task_runner_test_template.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..012fa88058387395500c561dbd97d68d1cafa2fc
|
| --- /dev/null
|
| +++ b/base/task_runner_test_template.h
|
| @@ -0,0 +1,157 @@
|
| +// 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 TaskRunner should
|
| +// pass in order to be conformant. Here's how you use it to test your
|
| +// implementation.
|
| +//
|
| +// Say your class is called MyTaskRunner. Then you need to define a
|
| +// class called MyTaskRunnerTestDelegate in my_task_runner_unittest.cc
|
| +// like this:
|
| +//
|
| +// class MyTaskRunnerTestDelegate {
|
| +// public:
|
| +// // Tasks posted to the task runner after this and before
|
| +// // StopTaskRunner() is called is called should run successfully.
|
| +// void StartTaskRunner() {
|
| +// ...
|
| +// }
|
| +//
|
| +// // Should return the task runner implementation. Only called
|
| +// // after StartTaskRunner and before StopTaskRunner.
|
| +// scoped_refptr<MyTaskRunner> GetTaskRunner() {
|
| +// ...
|
| +// }
|
| +//
|
| +// // Stop the task runner and make sure all tasks posted before
|
| +// // this is called are run.
|
| +// void StopTaskRunner() {
|
| +// ...
|
| +// }
|
| +//
|
| +// // Returns whether or not the task runner obeys non-zero delays.
|
| +// bool TaskRunnerHandlesNonZeroDelays() const {
|
| +// return true;
|
| +// }
|
| +// };
|
| +//
|
| +// The TaskRunnerTest test harness will have a member variable of
|
| +// this delegate type and will call its functions in the various
|
| +// tests.
|
| +//
|
| +// Then you simply #include this file as well as gtest.h and add the
|
| +// following statement to my_task_runner_unittest.cc:
|
| +//
|
| +// INSTANTIATE_TYPED_TEST_CASE_P(
|
| +// MyTaskRunner, TaskRunnerTest, MyTaskRunnerTestDelegate);
|
| +//
|
| +// Easy!
|
| +
|
| +#ifndef BASE_TASK_RUNNER_TEST_TEMPLATE_H_
|
| +#define BASE_TASK_RUNNER_TEST_TEMPLATE_H_
|
| +#pragma once
|
| +
|
| +#include <cstddef>
|
| +#include <map>
|
| +
|
| +#include "base/basictypes.h"
|
| +#include "base/bind.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/synchronization/lock.h"
|
| +#include "base/task_runner.h"
|
| +#include "base/tracked_objects.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace base {
|
| +
|
| +// Utility class used in the tests below.
|
| +class TaskTracker : public RefCountedThreadSafe<TaskTracker> {
|
| + public:
|
| + TaskTracker();
|
| +
|
| + void RunTask(int i);
|
| +
|
| + std::map<int, int> GetTaskRunCounts() const;
|
| +
|
| + private:
|
| + friend class RefCountedThreadSafe<TaskTracker>;
|
| +
|
| + ~TaskTracker();
|
| +
|
| + mutable Lock task_run_counts_lock_;
|
| + std::map<int, int> task_run_counts_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TaskTracker);
|
| +};
|
| +
|
| +template <typename TaskRunnerTestDelegate>
|
| +class TaskRunnerTest : public testing::Test {
|
| + protected:
|
| + TaskRunnerTest() : task_tracker_(new TaskTracker()) {}
|
| +
|
| + const scoped_refptr<TaskTracker> task_tracker_;
|
| + TaskRunnerTestDelegate delegate_;
|
| +};
|
| +
|
| +TYPED_TEST_CASE_P(TaskRunnerTest);
|
| +
|
| +// We can't really test much, since TaskRunner provides very few
|
| +// guarantees.
|
| +
|
| +// Post a bunch of tasks to the task runner. They should all
|
| +// complete.
|
| +TYPED_TEST_P(TaskRunnerTest, Basic) {
|
| + std::map<int, int> expected_task_run_counts;
|
| +
|
| + this->delegate_.StartTaskRunner();
|
| + scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner();
|
| + // Post each ith task i+1 times.
|
| + for (int i = 0; i < 20; ++i) {
|
| + Closure task = Bind(&TaskTracker::RunTask, this->task_tracker_, i);
|
| + for (int j = 0; j < i + 1; ++j) {
|
| + task_runner->PostTask(FROM_HERE, task);
|
| + ++expected_task_run_counts[i];
|
| + }
|
| + }
|
| + this->delegate_.StopTaskRunner();
|
| +
|
| + EXPECT_EQ(expected_task_run_counts,
|
| + this->task_tracker_->GetTaskRunCounts());
|
| +}
|
| +
|
| +// Post a bunch of delayed tasks to the task runner. They should all
|
| +// complete.
|
| +TYPED_TEST_P(TaskRunnerTest, Delayed) {
|
| + if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) {
|
| + DLOG(INFO) << "This TaskRunner doesn't handle non-zero delays; skipping";
|
| + return;
|
| + }
|
| +
|
| + std::map<int, int> expected_task_run_counts;
|
| +
|
| + this->delegate_.StartTaskRunner();
|
| + scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner();
|
| + // Post each ith task i+1 times with delays from 0-i.
|
| + for (int i = 0; i < 20; ++i) {
|
| + Closure task = Bind(&TaskTracker::RunTask, this->task_tracker_, i);
|
| + for (int j = 0; j < i + 1; ++j) {
|
| + task_runner->PostDelayedTask(FROM_HERE, task, j);
|
| + ++expected_task_run_counts[i];
|
| + }
|
| + }
|
| + this->delegate_.StopTaskRunner();
|
| +
|
| + EXPECT_EQ(expected_task_run_counts,
|
| + this->task_tracker_->GetTaskRunCounts());
|
| +}
|
| +
|
| +// TODO(akalin): Add test to verify RunsTaskOnCurrentThread() returns
|
| +// true for tasks runs on the TaskRunner and returns false on a
|
| +// separate PlatformThread.
|
| +
|
| +REGISTER_TYPED_TEST_CASE_P(TaskRunnerTest, Basic, Delayed);
|
| +
|
| +} // namespace base
|
| +
|
| +#endif //#define BASE_TASK_RUNNER_TEST_TEMPLATE_H_
|
|
|