blob: 835c6d6884bc430caf4f9afe0bc01c2de774ed85 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]506fc232012-02-29 01:33:032// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
dcastagna29e7fc62015-07-31 23:20:065// This file defines tests that implementations of TaskRunner should
6// pass in order to be conformant, as well as test cases for optional behavior.
7// Here's how you use it to test your implementation.
[email protected]506fc232012-02-29 01:33:038//
9// Say your class is called MyTaskRunner. Then you need to define a
10// class called MyTaskRunnerTestDelegate in my_task_runner_unittest.cc
11// like this:
12//
13// class MyTaskRunnerTestDelegate {
14// public:
15// // Tasks posted to the task runner after this and before
16// // StopTaskRunner() is called is called should run successfully.
17// void StartTaskRunner() {
18// ...
19// }
20//
21// // Should return the task runner implementation. Only called
22// // after StartTaskRunner and before StopTaskRunner.
23// scoped_refptr<MyTaskRunner> GetTaskRunner() {
24// ...
25// }
26//
27// // Stop the task runner and make sure all tasks posted before
[email protected]13ecb5e92013-03-07 01:35:3728// // this is called are run. Caveat: delayed tasks are not run,
Peter Kasting134ef9af2024-12-28 02:30:0929// they're simply deleted.
[email protected]506fc232012-02-29 01:33:0330// void StopTaskRunner() {
31// ...
32// }
[email protected]506fc232012-02-29 01:33:0333// };
34//
35// The TaskRunnerTest test harness will have a member variable of
36// this delegate type and will call its functions in the various
37// tests.
38//
39// Then you simply #include this file as well as gtest.h and add the
40// following statement to my_task_runner_unittest.cc:
41//
Victor Costan033b9ac2019-01-29 00:52:1642// INSTANTIATE_TYPED_TEST_SUITE_P(
[email protected]506fc232012-02-29 01:33:0343// MyTaskRunner, TaskRunnerTest, MyTaskRunnerTestDelegate);
44//
45// Easy!
dcastagna29e7fc62015-07-31 23:20:0646
[email protected]c8cae7c2012-03-09 06:20:1847#ifndef BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
48#define BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
[email protected]506fc232012-02-29 01:33:0349
50#include <cstddef>
51#include <map>
52
Avi Drissman63e1f992023-01-13 18:54:4353#include "base/functional/bind.h"
54#include "base/functional/callback.h"
skyostil054861d2015-04-30 19:06:1555#include "base/location.h"
[email protected]506fc232012-02-29 01:33:0356#include "base/memory/ref_counted.h"
[email protected]13ecb5e92013-03-07 01:35:3757#include "base/synchronization/condition_variable.h"
[email protected]506fc232012-02-29 01:33:0358#include "base/synchronization/lock.h"
Patrick Monette643cdf62021-10-15 19:13:4259#include "base/task/single_thread_task_runner.h"
60#include "base/task/task_runner.h"
[email protected]1ab698d2012-03-09 04:24:3461#include "base/threading/thread.h"
[email protected]506fc232012-02-29 01:33:0362#include "testing/gtest/include/gtest/gtest.h"
63
64namespace base {
65
fdoray39c7a5e2016-03-03 17:58:0866namespace test {
[email protected]1ab698d2012-03-09 04:24:3467
68// Utility class that keeps track of how many times particular tasks
69// are run.
[email protected]506fc232012-02-29 01:33:0370class TaskTracker : public RefCountedThreadSafe<TaskTracker> {
71 public:
72 TaskTracker();
73
Peter Boström75cd3c02021-09-28 15:23:1874 TaskTracker(const TaskTracker&) = delete;
75 TaskTracker& operator=(const TaskTracker&) = delete;
76
[email protected]1ab698d2012-03-09 04:24:3477 // Returns a closure that runs the given task and increments the run
78 // count of |i| by one. |task| may be null. It is guaranteed that
79 // only one task wrapped by a given tracker will be run at a time.
kylechar5c4d56c12019-05-15 17:22:4280 RepeatingClosure WrapTask(RepeatingClosure task, int i);
[email protected]506fc232012-02-29 01:33:0381
82 std::map<int, int> GetTaskRunCounts() const;
83
[email protected]13ecb5e92013-03-07 01:35:3784 // Returns after the tracker observes a total of |count| task completions.
85 void WaitForCompletedTasks(int count);
86
[email protected]506fc232012-02-29 01:33:0387 private:
88 friend class RefCountedThreadSafe<TaskTracker>;
89
90 ~TaskTracker();
91
kylechar5c4d56c12019-05-15 17:22:4292 void RunTask(RepeatingClosure task, int i);
[email protected]1ab698d2012-03-09 04:24:3493
[email protected]13ecb5e92013-03-07 01:35:3794 mutable Lock lock_;
[email protected]506fc232012-02-29 01:33:0395 std::map<int, int> task_run_counts_;
[email protected]13ecb5e92013-03-07 01:35:3796 int task_runs_;
97 ConditionVariable task_runs_cv_;
[email protected]506fc232012-02-29 01:33:0398};
99
fdoray39c7a5e2016-03-03 17:58:08100} // namespace test
[email protected]1ab698d2012-03-09 04:24:34101
[email protected]506fc232012-02-29 01:33:03102template <typename TaskRunnerTestDelegate>
103class TaskRunnerTest : public testing::Test {
104 protected:
kylechar5c4d56c12019-05-15 17:22:42105 TaskRunnerTest() : task_tracker_(base::MakeRefCounted<test::TaskTracker>()) {}
[email protected]506fc232012-02-29 01:33:03106
fdoray39c7a5e2016-03-03 17:58:08107 const scoped_refptr<test::TaskTracker> task_tracker_;
[email protected]506fc232012-02-29 01:33:03108 TaskRunnerTestDelegate delegate_;
109};
110
Victor Costan033b9ac2019-01-29 00:52:16111TYPED_TEST_SUITE_P(TaskRunnerTest);
[email protected]506fc232012-02-29 01:33:03112
113// We can't really test much, since TaskRunner provides very few
114// guarantees.
115
116// Post a bunch of tasks to the task runner. They should all
117// complete.
118TYPED_TEST_P(TaskRunnerTest, Basic) {
119 std::map<int, int> expected_task_run_counts;
120
121 this->delegate_.StartTaskRunner();
122 scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner();
123 // Post each ith task i+1 times.
124 for (int i = 0; i < 20; ++i) {
kylechar5c4d56c12019-05-15 17:22:42125 RepeatingClosure ith_task =
126 this->task_tracker_->WrapTask(RepeatingClosure(), i);
[email protected]506fc232012-02-29 01:33:03127 for (int j = 0; j < i + 1; ++j) {
[email protected]1ab698d2012-03-09 04:24:34128 task_runner->PostTask(FROM_HERE, ith_task);
[email protected]506fc232012-02-29 01:33:03129 ++expected_task_run_counts[i];
130 }
131 }
132 this->delegate_.StopTaskRunner();
133
Peter Kasting134ef9af2024-12-28 02:30:09134 EXPECT_EQ(expected_task_run_counts, this->task_tracker_->GetTaskRunCounts());
[email protected]506fc232012-02-29 01:33:03135}
136
137// Post a bunch of delayed tasks to the task runner. They should all
138// complete.
139TYPED_TEST_P(TaskRunnerTest, Delayed) {
[email protected]506fc232012-02-29 01:33:03140 std::map<int, int> expected_task_run_counts;
[email protected]13ecb5e92013-03-07 01:35:37141 int expected_total_tasks = 0;
[email protected]506fc232012-02-29 01:33:03142
143 this->delegate_.StartTaskRunner();
144 scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner();
145 // Post each ith task i+1 times with delays from 0-i.
146 for (int i = 0; i < 20; ++i) {
kylechar5c4d56c12019-05-15 17:22:42147 RepeatingClosure ith_task =
148 this->task_tracker_->WrapTask(RepeatingClosure(), i);
[email protected]506fc232012-02-29 01:33:03149 for (int j = 0; j < i + 1; ++j) {
Peter Kastinge5a38ed2021-10-02 03:06:35150 task_runner->PostDelayedTask(FROM_HERE, ith_task, base::Milliseconds(j));
[email protected]506fc232012-02-29 01:33:03151 ++expected_task_run_counts[i];
[email protected]13ecb5e92013-03-07 01:35:37152 ++expected_total_tasks;
[email protected]506fc232012-02-29 01:33:03153 }
154 }
[email protected]13ecb5e92013-03-07 01:35:37155 this->task_tracker_->WaitForCompletedTasks(expected_total_tasks);
[email protected]506fc232012-02-29 01:33:03156 this->delegate_.StopTaskRunner();
157
Peter Kasting134ef9af2024-12-28 02:30:09158 EXPECT_EQ(expected_task_run_counts, this->task_tracker_->GetTaskRunCounts());
[email protected]506fc232012-02-29 01:33:03159}
160
dcastagna29e7fc62015-07-31 23:20:06161// The TaskRunnerTest test case verifies behaviour that is expected from a
162// task runner in order to be conformant.
Victor Costan033b9ac2019-01-29 00:52:16163REGISTER_TYPED_TEST_SUITE_P(TaskRunnerTest, Basic, Delayed);
dcastagnaef1312d2015-07-24 23:28:11164
[email protected]506fc232012-02-29 01:33:03165} // namespace base
166
danakj0a448602015-03-10 00:31:16167#endif // BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_