| 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 TaskRunner should | 5 // This class defines tests that implementations of TaskRunner should |
| 6 // pass in order to be conformant. Here's how you use it to test your | 6 // pass in order to be conformant. Here's how you use it to test your |
| 7 // implementation. | 7 // implementation. |
| 8 // | 8 // |
| 9 // Say your class is called MyTaskRunner. Then you need to define a | 9 // Say your class is called MyTaskRunner. Then you need to define a |
| 10 // class called MyTaskRunnerTestDelegate in my_task_runner_unittest.cc | 10 // class called MyTaskRunnerTestDelegate in my_task_runner_unittest.cc |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 | 50 |
| 51 #ifndef BASE_TASK_RUNNER_TEST_TEMPLATE_H_ | 51 #ifndef BASE_TASK_RUNNER_TEST_TEMPLATE_H_ |
| 52 #define BASE_TASK_RUNNER_TEST_TEMPLATE_H_ | 52 #define BASE_TASK_RUNNER_TEST_TEMPLATE_H_ |
| 53 #pragma once | 53 #pragma once |
| 54 | 54 |
| 55 #include <cstddef> | 55 #include <cstddef> |
| 56 #include <map> | 56 #include <map> |
| 57 | 57 |
| 58 #include "base/basictypes.h" | 58 #include "base/basictypes.h" |
| 59 #include "base/bind.h" | 59 #include "base/bind.h" |
| 60 #include "base/callback.h" |
| 60 #include "base/memory/ref_counted.h" | 61 #include "base/memory/ref_counted.h" |
| 61 #include "base/synchronization/lock.h" | 62 #include "base/synchronization/lock.h" |
| 62 #include "base/task_runner.h" | 63 #include "base/task_runner.h" |
| 64 #include "base/threading/thread.h" |
| 63 #include "base/tracked_objects.h" | 65 #include "base/tracked_objects.h" |
| 64 #include "testing/gtest/include/gtest/gtest.h" | 66 #include "testing/gtest/include/gtest/gtest.h" |
| 65 | 67 |
| 66 namespace base { | 68 namespace base { |
| 67 | 69 |
| 68 // Utility class used in the tests below. | 70 namespace internal { |
| 71 |
| 72 // Utility class that keeps track of how many times particular tasks |
| 73 // are run. |
| 69 class TaskTracker : public RefCountedThreadSafe<TaskTracker> { | 74 class TaskTracker : public RefCountedThreadSafe<TaskTracker> { |
| 70 public: | 75 public: |
| 71 TaskTracker(); | 76 TaskTracker(); |
| 72 | 77 |
| 73 void RunTask(int i); | 78 // Returns a closure that runs the given task and increments the run |
| 79 // count of |i| by one. |task| may be null. It is guaranteed that |
| 80 // only one task wrapped by a given tracker will be run at a time. |
| 81 Closure WrapTask(const Closure& task, int i); |
| 74 | 82 |
| 75 std::map<int, int> GetTaskRunCounts() const; | 83 std::map<int, int> GetTaskRunCounts() const; |
| 76 | 84 |
| 77 private: | 85 private: |
| 78 friend class RefCountedThreadSafe<TaskTracker>; | 86 friend class RefCountedThreadSafe<TaskTracker>; |
| 79 | 87 |
| 80 ~TaskTracker(); | 88 ~TaskTracker(); |
| 81 | 89 |
| 90 void RunTask(const Closure& task, int i); |
| 91 |
| 82 mutable Lock task_run_counts_lock_; | 92 mutable Lock task_run_counts_lock_; |
| 83 std::map<int, int> task_run_counts_; | 93 std::map<int, int> task_run_counts_; |
| 84 | 94 |
| 85 DISALLOW_COPY_AND_ASSIGN(TaskTracker); | 95 DISALLOW_COPY_AND_ASSIGN(TaskTracker); |
| 86 }; | 96 }; |
| 87 | 97 |
| 98 } // namespace internal |
| 99 |
| 88 template <typename TaskRunnerTestDelegate> | 100 template <typename TaskRunnerTestDelegate> |
| 89 class TaskRunnerTest : public testing::Test { | 101 class TaskRunnerTest : public testing::Test { |
| 90 protected: | 102 protected: |
| 91 TaskRunnerTest() : task_tracker_(new TaskTracker()) {} | 103 TaskRunnerTest() : task_tracker_(new internal::TaskTracker()) {} |
| 92 | 104 |
| 93 const scoped_refptr<TaskTracker> task_tracker_; | 105 const scoped_refptr<internal::TaskTracker> task_tracker_; |
| 94 TaskRunnerTestDelegate delegate_; | 106 TaskRunnerTestDelegate delegate_; |
| 95 }; | 107 }; |
| 96 | 108 |
| 97 TYPED_TEST_CASE_P(TaskRunnerTest); | 109 TYPED_TEST_CASE_P(TaskRunnerTest); |
| 98 | 110 |
| 99 // We can't really test much, since TaskRunner provides very few | 111 // We can't really test much, since TaskRunner provides very few |
| 100 // guarantees. | 112 // guarantees. |
| 101 | 113 |
| 102 // Post a bunch of tasks to the task runner. They should all | 114 // Post a bunch of tasks to the task runner. They should all |
| 103 // complete. | 115 // complete. |
| 104 TYPED_TEST_P(TaskRunnerTest, Basic) { | 116 TYPED_TEST_P(TaskRunnerTest, Basic) { |
| 105 std::map<int, int> expected_task_run_counts; | 117 std::map<int, int> expected_task_run_counts; |
| 106 | 118 |
| 107 this->delegate_.StartTaskRunner(); | 119 this->delegate_.StartTaskRunner(); |
| 108 scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner(); | 120 scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner(); |
| 109 // Post each ith task i+1 times. | 121 // Post each ith task i+1 times. |
| 110 for (int i = 0; i < 20; ++i) { | 122 for (int i = 0; i < 20; ++i) { |
| 111 Closure task = Bind(&TaskTracker::RunTask, this->task_tracker_, i); | 123 const Closure& ith_task = this->task_tracker_->WrapTask(Closure(), i); |
| 112 for (int j = 0; j < i + 1; ++j) { | 124 for (int j = 0; j < i + 1; ++j) { |
| 113 task_runner->PostTask(FROM_HERE, task); | 125 task_runner->PostTask(FROM_HERE, ith_task); |
| 114 ++expected_task_run_counts[i]; | 126 ++expected_task_run_counts[i]; |
| 115 } | 127 } |
| 116 } | 128 } |
| 117 this->delegate_.StopTaskRunner(); | 129 this->delegate_.StopTaskRunner(); |
| 118 | 130 |
| 119 EXPECT_EQ(expected_task_run_counts, | 131 EXPECT_EQ(expected_task_run_counts, |
| 120 this->task_tracker_->GetTaskRunCounts()); | 132 this->task_tracker_->GetTaskRunCounts()); |
| 121 } | 133 } |
| 122 | 134 |
| 123 // Post a bunch of delayed tasks to the task runner. They should all | 135 // Post a bunch of delayed tasks to the task runner. They should all |
| 124 // complete. | 136 // complete. |
| 125 TYPED_TEST_P(TaskRunnerTest, Delayed) { | 137 TYPED_TEST_P(TaskRunnerTest, Delayed) { |
| 126 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { | 138 if (!this->delegate_.TaskRunnerHandlesNonZeroDelays()) { |
| 127 DLOG(INFO) << "This TaskRunner doesn't handle non-zero delays; skipping"; | 139 DLOG(INFO) << "This TaskRunner doesn't handle non-zero delays; skipping"; |
| 128 return; | 140 return; |
| 129 } | 141 } |
| 130 | 142 |
| 131 std::map<int, int> expected_task_run_counts; | 143 std::map<int, int> expected_task_run_counts; |
| 132 | 144 |
| 133 this->delegate_.StartTaskRunner(); | 145 this->delegate_.StartTaskRunner(); |
| 134 scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner(); | 146 scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner(); |
| 135 // Post each ith task i+1 times with delays from 0-i. | 147 // Post each ith task i+1 times with delays from 0-i. |
| 136 for (int i = 0; i < 20; ++i) { | 148 for (int i = 0; i < 20; ++i) { |
| 137 Closure task = Bind(&TaskTracker::RunTask, this->task_tracker_, i); | 149 const Closure& ith_task = this->task_tracker_->WrapTask(Closure(), i); |
| 138 for (int j = 0; j < i + 1; ++j) { | 150 for (int j = 0; j < i + 1; ++j) { |
| 139 task_runner->PostDelayedTask(FROM_HERE, task, j); | 151 task_runner->PostDelayedTask(FROM_HERE, ith_task, j); |
| 140 ++expected_task_run_counts[i]; | 152 ++expected_task_run_counts[i]; |
| 141 } | 153 } |
| 142 } | 154 } |
| 143 this->delegate_.StopTaskRunner(); | 155 this->delegate_.StopTaskRunner(); |
| 144 | 156 |
| 145 EXPECT_EQ(expected_task_run_counts, | 157 EXPECT_EQ(expected_task_run_counts, |
| 146 this->task_tracker_->GetTaskRunCounts()); | 158 this->task_tracker_->GetTaskRunCounts()); |
| 147 } | 159 } |
| 148 | 160 |
| 149 // TODO(akalin): Add test to verify RunsTaskOnCurrentThread() returns | 161 namespace internal { |
| 150 // true for tasks runs on the TaskRunner and returns false on a | |
| 151 // separate PlatformThread. | |
| 152 | 162 |
| 153 REGISTER_TYPED_TEST_CASE_P(TaskRunnerTest, Basic, Delayed); | 163 // Calls RunsTasksOnCurrentThread() on |task_runner| and expects it to |
| 164 // equal |expected_value|. |
| 165 void ExpectRunsTasksOnCurrentThread( |
| 166 bool expected_value, |
| 167 const scoped_refptr<TaskRunner>& task_runner); |
| 168 |
| 169 } // namespace internal |
| 170 |
| 171 // Post a bunch of tasks to the task runner as well as to a separate |
| 172 // thread, each checking the value of RunsTasksOnCurrentThread(), |
| 173 // which should return true for the tasks posted on the task runner |
| 174 // and false for the tasks posted on the separate thread. |
| 175 TYPED_TEST_P(TaskRunnerTest, RunsTasksOnCurrentThread) { |
| 176 std::map<int, int> expected_task_run_counts; |
| 177 |
| 178 Thread thread("Non-task-runner thread"); |
| 179 ASSERT_TRUE(thread.Start()); |
| 180 this->delegate_.StartTaskRunner(); |
| 181 |
| 182 scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner(); |
| 183 // Post each ith task i+1 times on the task runner and i+1 times on |
| 184 // the non-task-runner thread. |
| 185 for (int i = 0; i < 20; ++i) { |
| 186 const Closure& ith_task_runner_task = |
| 187 this->task_tracker_->WrapTask( |
| 188 Bind(&internal::ExpectRunsTasksOnCurrentThread, |
| 189 true, task_runner), |
| 190 i); |
| 191 const Closure& ith_non_task_runner_task = |
| 192 this->task_tracker_->WrapTask( |
| 193 Bind(&internal::ExpectRunsTasksOnCurrentThread, |
| 194 false, task_runner), |
| 195 i); |
| 196 for (int j = 0; j < i + 1; ++j) { |
| 197 task_runner->PostTask(FROM_HERE, ith_task_runner_task); |
| 198 thread.message_loop()->PostTask(FROM_HERE, ith_non_task_runner_task); |
| 199 expected_task_run_counts[i] += 2; |
| 200 } |
| 201 } |
| 202 |
| 203 this->delegate_.StopTaskRunner(); |
| 204 thread.Stop(); |
| 205 |
| 206 EXPECT_EQ(expected_task_run_counts, |
| 207 this->task_tracker_->GetTaskRunCounts()); |
| 208 } |
| 209 |
| 210 REGISTER_TYPED_TEST_CASE_P( |
| 211 TaskRunnerTest, Basic, Delayed, RunsTasksOnCurrentThread); |
| 154 | 212 |
| 155 } // namespace base | 213 } // namespace base |
| 156 | 214 |
| 157 #endif //#define BASE_TASK_RUNNER_TEST_TEMPLATE_H_ | 215 #endif //#define BASE_TASK_RUNNER_TEST_TEMPLATE_H_ |
| OLD | NEW |