test_mock_time_task_runner.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // Copyright 2015 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. #ifndef BASE_TEST_TEST_MOCK_TIME_TASK_RUNNER_H_
  5. #define BASE_TEST_TEST_MOCK_TIME_TASK_RUNNER_H_
  6. #include <stddef.h>
  7. #include <memory>
  8. #include <queue>
  9. #include <vector>
  10. #include "base/callback.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/containers/circular_deque.h"
  13. #include "base/macros.h"
  14. #include "base/run_loop.h"
  15. #include "base/single_thread_task_runner.h"
  16. #include "base/synchronization/condition_variable.h"
  17. #include "base/synchronization/lock.h"
  18. #include "base/test/test_pending_task.h"
  19. #include "base/threading/thread_checker_impl.h"
  20. #include "base/time/clock.h"
  21. #include "base/time/tick_clock.h"
  22. #include "base/time/time.h"
  23. namespace base {
  24. class ThreadTaskRunnerHandle;
  25. // ATTENTION: Prefer using base::test::SingleThreadTaskEnvironment with a
  26. // base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME trait instead.
  27. // The only case where TestMockTimeTaskRunner is necessary is when instantiating
  28. // multiple TestMockTimeTaskRunners in the same test to deterministically
  29. // exercise the result of a race between two simulated threads.
  30. //
  31. // Runs pending tasks in the order of the tasks' post time + delay, and keeps
  32. // track of a mock (virtual) tick clock time that can be fast-forwarded.
  33. //
  34. // TestMockTimeTaskRunner has the following properties:
  35. //
  36. // - Methods RunsTasksInCurrentSequence() and Post[Delayed]Task() can be
  37. // called from any thread, but the rest of the methods must be called on
  38. // the same thread the TestMockTimeTaskRunner was created on.
  39. // - It allows for reentrancy, in that it handles the running of tasks that in
  40. // turn call back into it (e.g., to post more tasks).
  41. // - Tasks are stored in a priority queue, and executed in the increasing
  42. // order of post time + delay, but ignoring nestability.
  43. // - It does not check for overflow when doing time arithmetic. A sufficient
  44. // condition for preventing overflows is to make sure that the sum of all
  45. // posted task delays and fast-forward increments is still representable by
  46. // a TimeDelta, and that adding this delta to the starting values of Time
  47. // and TickTime is still within their respective range.
  48. //
  49. // A TestMockTimeTaskRunner of Type::kBoundToThread has the following additional
  50. // properties:
  51. // - Thread/SequencedTaskRunnerHandle refers to it on its thread.
  52. // - It can be driven by a RunLoop on the thread it was created on.
  53. // RunLoop::Run() will result in running non-delayed tasks until idle and
  54. // then, if RunLoop::QuitWhenIdle() wasn't invoked, fast-forwarding time to
  55. // the next delayed task and looping again. And so on, until either
  56. // RunLoop::Quit() is invoked (quits immediately after the current task) or
  57. // RunLoop::QuitWhenIdle() is invoked (quits before having to fast forward
  58. // time once again). Should RunLoop::Run() process all tasks (including
  59. // delayed ones), it will block until more are posted. As usual,
  60. // RunLoop::RunUntilIdle() is equivalent to RunLoop::Run() followed by an
  61. // immediate RunLoop::QuitWhenIdle().
  62. //
  63. // This is a slightly more sophisticated version of TestSimpleTaskRunner, in
  64. // that it supports running delayed tasks in the correct temporal order.
  65. class TestMockTimeTaskRunner : public SingleThreadTaskRunner,
  66. public RunLoop::Delegate {
  67. public:
  68. // Everything that is executed in the scope of a ScopedContext will behave as
  69. // though it ran under |scope| (i.e. ThreadTaskRunnerHandle,
  70. // RunsTasksInCurrentSequence, etc.). This allows the test body to be all in
  71. // one block when multiple TestMockTimeTaskRunners share the main thread.
  72. // Note: RunLoop isn't supported: will DCHECK if used inside a ScopedContext.
  73. //
  74. // For example:
  75. //
  76. // class ExampleFixture {
  77. // protected:
  78. // DoBarOnFoo() {
  79. // DCHECK(foo_task_runner_->RunsOnCurrentThread());
  80. // EXPECT_EQ(foo_task_runner_, ThreadTaskRunnerHandle::Get());
  81. // DoBar();
  82. // }
  83. //
  84. // // Mock main task runner.
  85. // base::MessageLoop message_loop_;
  86. // base::ScopedMockTimeMessageLoopTaskRunner main_task_runner_;
  87. //
  88. // // Mock foo task runner.
  89. // scoped_refptr<TestMockTimeTaskRunner> foo_task_runner_ =
  90. // new TestMockTimeTaskRunner();
  91. // };
  92. //
  93. // TEST_F(ExampleFixture, DoBarOnFoo) {
  94. // DoThingsOnMain();
  95. // {
  96. // TestMockTimeTaskRunner::ScopedContext scoped_context(
  97. // foo_task_runner_.get());
  98. // DoBarOnFoo();
  99. // }
  100. // DoMoreThingsOnMain();
  101. // }
  102. //
  103. class ScopedContext {
  104. public:
  105. // Note: |scope| is ran until idle as part of this constructor to ensure
  106. // that anything which runs in the underlying scope runs after any already
  107. // pending tasks (the contrary would break the SequencedTaskRunner
  108. // contract).
  109. explicit ScopedContext(scoped_refptr<TestMockTimeTaskRunner> scope);
  110. ~ScopedContext();
  111. private:
  112. ScopedClosureRunner on_destroy_;
  113. DISALLOW_COPY_AND_ASSIGN(ScopedContext);
  114. };
  115. enum class Type {
  116. // A TestMockTimeTaskRunner which can only be driven directly through its
  117. // API. Thread/SequencedTaskRunnerHandle will refer to it only in the scope
  118. // of its tasks.
  119. kStandalone,
  120. // A TestMockTimeTaskRunner which will associate to the thread it is created
  121. // on, enabling RunLoop to drive it and making
  122. // Thread/SequencedTaskRunnerHandle refer to it on that thread.
  123. kBoundToThread,
  124. };
  125. // Constructs an instance whose virtual time will start at the Unix epoch, and
  126. // whose time ticks will start at zero.
  127. TestMockTimeTaskRunner(Type type = Type::kStandalone);
  128. // Constructs an instance starting at the given virtual time and time ticks.
  129. TestMockTimeTaskRunner(Time start_time,
  130. TimeTicks start_ticks,
  131. Type type = Type::kStandalone);
  132. // Fast-forwards virtual time by |delta|, causing all tasks with a remaining
  133. // delay less than or equal to |delta| to be executed. |delta| must be
  134. // non-negative.
  135. void FastForwardBy(TimeDelta delta);
  136. // Fast-forwards virtual time by |delta| but not causing any task execution.
  137. void AdvanceMockTickClock(TimeDelta delta);
  138. // Fast-forward virtual time, but not tick time. May be useful for testing
  139. // timers when simulating suspend/resume or time adjustments. As it doesn't
  140. // advance tick time, no tasks are automatically processed
  141. // (ProcessAllTasksNoLaterThan is not called).
  142. void AdvanceWallClock(TimeDelta delta);
  143. // Fast-forwards virtual time just until all tasks are executed.
  144. void FastForwardUntilNoTasksRemain();
  145. // Executes all tasks that have no remaining delay. Tasks with a remaining
  146. // delay greater than zero will remain enqueued, and no virtual time will
  147. // elapse.
  148. void RunUntilIdle();
  149. // Clears the queue of pending tasks without running them.
  150. void ClearPendingTasks();
  151. // Returns the current virtual time (initially starting at the Unix epoch).
  152. Time Now() const;
  153. // Returns the current virtual tick time (initially starting at 0).
  154. TimeTicks NowTicks() const;
  155. // Returns a Clock that uses the virtual time of |this| as its time source.
  156. // The returned Clock will hold a reference to |this|.
  157. // TODO(tzik): Remove DeprecatedGetMockClock() after updating all callers to
  158. // use non-owning Clock.
  159. std::unique_ptr<Clock> DeprecatedGetMockClock() const;
  160. Clock* GetMockClock() const;
  161. // Returns a TickClock that uses the virtual time ticks of |this| as its tick
  162. // source. The returned TickClock will hold a reference to |this|.
  163. // TODO(tzik): Replace Remove DeprecatedGetMockTickClock() after updating all
  164. // callers to use non-owning TickClock.
  165. std::unique_ptr<TickClock> DeprecatedGetMockTickClock() const;
  166. const TickClock* GetMockTickClock() const;
  167. // Cancelled pending tasks get pruned automatically.
  168. base::circular_deque<TestPendingTask> TakePendingTasks();
  169. bool HasPendingTask();
  170. size_t GetPendingTaskCount();
  171. TimeDelta NextPendingTaskDelay();
  172. // SingleThreadTaskRunner:
  173. bool RunsTasksInCurrentSequence() const override;
  174. bool PostDelayedTask(const Location& from_here,
  175. OnceClosure task,
  176. TimeDelta delay) override;
  177. bool PostNonNestableDelayedTask(const Location& from_here,
  178. OnceClosure task,
  179. TimeDelta delay) override;
  180. protected:
  181. ~TestMockTimeTaskRunner() override;
  182. // Called before the next task to run is selected, so that subclasses have a
  183. // last chance to make sure all tasks are posted.
  184. virtual void OnBeforeSelectingTask();
  185. // Called after the current mock time has been incremented so that subclasses
  186. // can react to the passing of time.
  187. virtual void OnAfterTimePassed();
  188. // Called after each task is run so that subclasses may perform additional
  189. // activities, e.g., pump additional task runners.
  190. virtual void OnAfterTaskRun();
  191. private:
  192. class NonOwningProxyTaskRunner;
  193. // MockClock implements TickClock and Clock. Always returns the then-current
  194. // mock time of |task_runner| as the current time or time ticks.
  195. class MockClock : public TickClock, public Clock {
  196. public:
  197. explicit MockClock(TestMockTimeTaskRunner* task_runner)
  198. : task_runner_(task_runner) {}
  199. // TickClock:
  200. TimeTicks NowTicks() const override;
  201. // Clock:
  202. Time Now() const override;
  203. private:
  204. TestMockTimeTaskRunner* task_runner_;
  205. DISALLOW_COPY_AND_ASSIGN(MockClock);
  206. };
  207. struct TestOrderedPendingTask;
  208. // Predicate that defines a strict weak temporal ordering of tasks.
  209. class TemporalOrder {
  210. public:
  211. bool operator()(const TestOrderedPendingTask& first_task,
  212. const TestOrderedPendingTask& second_task) const;
  213. };
  214. typedef std::priority_queue<TestOrderedPendingTask,
  215. std::vector<TestOrderedPendingTask>,
  216. TemporalOrder> TaskPriorityQueue;
  217. // Core of the implementation for all flavors of fast-forward methods. Given a
  218. // non-negative |max_delta|, runs all tasks with a remaining delay less than
  219. // or equal to |max_delta|, and moves virtual time forward as needed for each
  220. // processed task. Pass in TimeDelta::Max() as |max_delta| to run all tasks.
  221. void ProcessAllTasksNoLaterThan(TimeDelta max_delta);
  222. // Forwards |now_ticks_| until it equals |later_ticks|, and forwards |now_| by
  223. // the same amount. Calls OnAfterTimePassed() if |later_ticks| > |now_ticks_|.
  224. // Does nothing if |later_ticks| <= |now_ticks_|.
  225. void ForwardClocksUntilTickTime(TimeTicks later_ticks);
  226. // Returns the |next_task| to run if there is any with a running time that is
  227. // at most |reference| + |max_delta|. This additional complexity is required
  228. // so that |max_delta| == TimeDelta::Max() can be supported.
  229. bool DequeueNextTask(const TimeTicks& reference,
  230. const TimeDelta& max_delta,
  231. TestPendingTask* next_task);
  232. // RunLoop::Delegate:
  233. void Run(bool application_tasks_allowed, TimeDelta timeout) override;
  234. void Quit() override;
  235. void EnsureWorkScheduled() override;
  236. // Also used for non-dcheck logic (RunsTasksInCurrentSequence()) and as such
  237. // needs to be a ThreadCheckerImpl.
  238. ThreadCheckerImpl thread_checker_;
  239. Time now_;
  240. TimeTicks now_ticks_;
  241. // Temporally ordered heap of pending tasks. Must only be accessed while the
  242. // |tasks_lock_| is held.
  243. TaskPriorityQueue tasks_;
  244. // The ordinal to use for the next task. Must only be accessed while the
  245. // |tasks_lock_| is held.
  246. size_t next_task_ordinal_ = 0;
  247. mutable Lock tasks_lock_;
  248. ConditionVariable tasks_lock_cv_;
  249. const scoped_refptr<NonOwningProxyTaskRunner> proxy_task_runner_;
  250. std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
  251. // Set to true in RunLoop::Delegate::Quit() to signal the topmost
  252. // RunLoop::Delegate::Run() instance to stop, reset to false when it does.
  253. bool quit_run_loop_ = false;
  254. mutable MockClock mock_clock_;
  255. DISALLOW_COPY_AND_ASSIGN(TestMockTimeTaskRunner);
  256. };
  257. } // namespace base
  258. #endif // BASE_TEST_TEST_MOCK_TIME_TASK_RUNNER_H_