task_runner_test_template.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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
  3. // found in the LICENSE file.
  4. // This file defines tests that implementations of TaskRunner should
  5. // pass in order to be conformant, as well as test cases for optional behavior.
  6. // Here's how you use it to test your implementation.
  7. //
  8. // Say your class is called MyTaskRunner. Then you need to define a
  9. // class called MyTaskRunnerTestDelegate in my_task_runner_unittest.cc
  10. // like this:
  11. //
  12. // class MyTaskRunnerTestDelegate {
  13. // public:
  14. // // Tasks posted to the task runner after this and before
  15. // // StopTaskRunner() is called is called should run successfully.
  16. // void StartTaskRunner() {
  17. // ...
  18. // }
  19. //
  20. // // Should return the task runner implementation. Only called
  21. // // after StartTaskRunner and before StopTaskRunner.
  22. // scoped_refptr<MyTaskRunner> GetTaskRunner() {
  23. // ...
  24. // }
  25. //
  26. // // Stop the task runner and make sure all tasks posted before
  27. // // this is called are run. Caveat: delayed tasks are not run,
  28. // they're simply deleted.
  29. // void StopTaskRunner() {
  30. // ...
  31. // }
  32. // };
  33. //
  34. // The TaskRunnerTest test harness will have a member variable of
  35. // this delegate type and will call its functions in the various
  36. // tests.
  37. //
  38. // Then you simply #include this file as well as gtest.h and add the
  39. // following statement to my_task_runner_unittest.cc:
  40. //
  41. // INSTANTIATE_TYPED_TEST_SUITE_P(
  42. // MyTaskRunner, TaskRunnerTest, MyTaskRunnerTestDelegate);
  43. //
  44. // Easy!
  45. #ifndef BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
  46. #define BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
  47. #include <cstddef>
  48. #include <map>
  49. #include "base/bind.h"
  50. #include "base/callback.h"
  51. #include "base/location.h"
  52. #include "base/macros.h"
  53. #include "base/memory/ref_counted.h"
  54. #include "base/single_thread_task_runner.h"
  55. #include "base/synchronization/condition_variable.h"
  56. #include "base/synchronization/lock.h"
  57. #include "base/task_runner.h"
  58. #include "base/threading/thread.h"
  59. #include "testing/gtest/include/gtest/gtest.h"
  60. namespace base {
  61. namespace test {
  62. // Utility class that keeps track of how many times particular tasks
  63. // are run.
  64. class TaskTracker : public RefCountedThreadSafe<TaskTracker> {
  65. public:
  66. TaskTracker();
  67. // Returns a closure that runs the given task and increments the run
  68. // count of |i| by one. |task| may be null. It is guaranteed that
  69. // only one task wrapped by a given tracker will be run at a time.
  70. RepeatingClosure WrapTask(RepeatingClosure task, int i);
  71. std::map<int, int> GetTaskRunCounts() const;
  72. // Returns after the tracker observes a total of |count| task completions.
  73. void WaitForCompletedTasks(int count);
  74. private:
  75. friend class RefCountedThreadSafe<TaskTracker>;
  76. ~TaskTracker();
  77. void RunTask(RepeatingClosure task, int i);
  78. mutable Lock lock_;
  79. std::map<int, int> task_run_counts_;
  80. int task_runs_;
  81. ConditionVariable task_runs_cv_;
  82. DISALLOW_COPY_AND_ASSIGN(TaskTracker);
  83. };
  84. } // namespace test
  85. template <typename TaskRunnerTestDelegate>
  86. class TaskRunnerTest : public testing::Test {
  87. protected:
  88. TaskRunnerTest() : task_tracker_(base::MakeRefCounted<test::TaskTracker>()) {}
  89. const scoped_refptr<test::TaskTracker> task_tracker_;
  90. TaskRunnerTestDelegate delegate_;
  91. };
  92. TYPED_TEST_SUITE_P(TaskRunnerTest);
  93. // We can't really test much, since TaskRunner provides very few
  94. // guarantees.
  95. // Post a bunch of tasks to the task runner. They should all
  96. // complete.
  97. TYPED_TEST_P(TaskRunnerTest, Basic) {
  98. std::map<int, int> expected_task_run_counts;
  99. this->delegate_.StartTaskRunner();
  100. scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner();
  101. // Post each ith task i+1 times.
  102. for (int i = 0; i < 20; ++i) {
  103. RepeatingClosure ith_task =
  104. this->task_tracker_->WrapTask(RepeatingClosure(), i);
  105. for (int j = 0; j < i + 1; ++j) {
  106. task_runner->PostTask(FROM_HERE, ith_task);
  107. ++expected_task_run_counts[i];
  108. }
  109. }
  110. this->delegate_.StopTaskRunner();
  111. EXPECT_EQ(expected_task_run_counts,
  112. this->task_tracker_->GetTaskRunCounts());
  113. }
  114. // Post a bunch of delayed tasks to the task runner. They should all
  115. // complete.
  116. TYPED_TEST_P(TaskRunnerTest, Delayed) {
  117. std::map<int, int> expected_task_run_counts;
  118. int expected_total_tasks = 0;
  119. this->delegate_.StartTaskRunner();
  120. scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner();
  121. // Post each ith task i+1 times with delays from 0-i.
  122. for (int i = 0; i < 20; ++i) {
  123. RepeatingClosure ith_task =
  124. this->task_tracker_->WrapTask(RepeatingClosure(), i);
  125. for (int j = 0; j < i + 1; ++j) {
  126. task_runner->PostDelayedTask(
  127. FROM_HERE, ith_task, base::TimeDelta::FromMilliseconds(j));
  128. ++expected_task_run_counts[i];
  129. ++expected_total_tasks;
  130. }
  131. }
  132. this->task_tracker_->WaitForCompletedTasks(expected_total_tasks);
  133. this->delegate_.StopTaskRunner();
  134. EXPECT_EQ(expected_task_run_counts,
  135. this->task_tracker_->GetTaskRunCounts());
  136. }
  137. // The TaskRunnerTest test case verifies behaviour that is expected from a
  138. // task runner in order to be conformant.
  139. REGISTER_TYPED_TEST_SUITE_P(TaskRunnerTest, Basic, Delayed);
  140. } // namespace base
  141. #endif // BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_