1 // Copyright 2017 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 5 #ifndef BASE_TEST_SCOPED_TASK_ENVIRONMENT_H_ 6 #define BASE_TEST_SCOPED_TASK_ENVIRONMENT_H_ 7 8 #include "base/macros.h" 9 #include "base/memory/ref_counted.h" 10 #include "base/single_thread_task_runner.h" 11 #include "base/task_scheduler/lazy_task_runner.h" 12 #include "build/build_config.h" 13 14 namespace base { 15 16 namespace internal { 17 class ScopedSetSequenceLocalStorageMapForCurrentThread; 18 class SequenceLocalStorageMap; 19 } // namespace internal 20 21 class FileDescriptorWatcher; 22 class MessageLoop; 23 class TaskScheduler; 24 class TestMockTimeTaskRunner; 25 class TickClock; 26 27 namespace test { 28 29 // ScopedTaskEnvironment allows usage of these APIs within its scope: 30 // - (Thread|Sequenced)TaskRunnerHandle, on the thread where it lives 31 // - base/task_scheduler/post_task.h, on any thread 32 // 33 // Tests that need either of these APIs should instantiate a 34 // ScopedTaskEnvironment. 35 // 36 // Tasks posted to the (Thread|Sequenced)TaskRunnerHandle run synchronously when 37 // RunLoop::Run(UntilIdle) or ScopedTaskEnvironment::RunUntilIdle is called on 38 // the thread where the ScopedTaskEnvironment lives. 39 // 40 // Tasks posted through base/task_scheduler/post_task.h run on dedicated 41 // threads. If ExecutionMode is QUEUED, they run when RunUntilIdle() or 42 // ~ScopedTaskEnvironment is called. If ExecutionMode is ASYNC, they run 43 // as they are posted. 44 // 45 // All methods of ScopedTaskEnvironment must be called from the same thread. 46 // 47 // Usage: 48 // 49 // class MyTestFixture : public testing::Test { 50 // public: 51 // (...) 52 // 53 // protected: 54 // // Must be the first member (or at least before any member that cares 55 // // about tasks) to be initialized first and destroyed last. protected 56 // // instead of private visibility will allow controlling the task 57 // // environment (e.g. clock) once such features are added (see design doc 58 // // below for details), until then it at least doesn't hurt :). 59 // base::test::ScopedTaskEnvironment scoped_task_environment_; 60 // 61 // // Other members go here (or further below in private section.) 62 // }; 63 // 64 // Design and future improvements documented in 65 // https://docs.google.com/document/d/1QabRo8c7D9LsYY3cEcaPQbOCLo8Tu-6VLykYXyl3Pkk/edit 66 class ScopedTaskEnvironment { 67 public: 68 enum class MainThreadType { 69 // The main thread doesn't pump system messages. 70 DEFAULT, 71 // The main thread doesn't pump system messages and uses a mock clock for 72 // delayed tasks (controllable via FastForward*() methods). 73 // TODO(gab): Make this the default |main_thread_type|. 74 // TODO(gab): Also mock the TaskScheduler's clock simultaneously (this 75 // currently only mocks the main thread's clock). 76 MOCK_TIME, 77 // The main thread pumps UI messages. 78 UI, 79 // The main thread pumps asynchronous IO messages and supports the 80 // FileDescriptorWatcher API on POSIX. 81 IO, 82 }; 83 84 enum class ExecutionMode { 85 // Tasks are queued and only executed when RunUntilIdle() is explicitly 86 // called. 87 QUEUED, 88 // Tasks run as they are posted. RunUntilIdle() can still be used to block 89 // until done. 90 ASYNC, 91 }; 92 93 ScopedTaskEnvironment( 94 MainThreadType main_thread_type = MainThreadType::DEFAULT, 95 ExecutionMode execution_control_mode = ExecutionMode::ASYNC); 96 97 // Waits until no undelayed TaskScheduler tasks remain. Then, unregisters the 98 // TaskScheduler and the (Thread|Sequenced)TaskRunnerHandle. 99 ~ScopedTaskEnvironment(); 100 101 // Returns a TaskRunner that schedules tasks on the main thread. 102 scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner(); 103 104 // Returns whether the main thread's TaskRunner has pending tasks. 105 bool MainThreadHasPendingTask() const; 106 107 // Runs tasks until both the (Thread|Sequenced)TaskRunnerHandle and the 108 // TaskScheduler's non-delayed queues are empty. 109 void RunUntilIdle(); 110 111 // Only valid for instances with a MOCK_TIME MainThreadType. Fast-forwards 112 // virtual time by |delta|, causing all tasks on the main thread with a 113 // remaining delay less than or equal to |delta| to be executed before this 114 // returns. |delta| must be non-negative. 115 // TODO(gab): Make this apply to TaskScheduler delayed tasks as well 116 // (currently only main thread time is mocked). 117 void FastForwardBy(TimeDelta delta); 118 119 // Only valid for instances with a MOCK_TIME MainThreadType. 120 // Short for FastForwardBy(TimeDelta::Max()). 121 void FastForwardUntilNoTasksRemain(); 122 123 // Only valid for instances with a MOCK_TIME MainThreadType. Returns a 124 // TickClock whose time is updated by FastForward(By|UntilNoTasksRemain). 125 const TickClock* GetMockTickClock(); 126 std::unique_ptr<TickClock> DeprecatedGetMockTickClock(); 127 128 // Only valid for instances with a MOCK_TIME MainThreadType. 129 // Returns the number of pending tasks of the main thread's TaskRunner. 130 size_t GetPendingMainThreadTaskCount() const; 131 132 // Only valid for instances with a MOCK_TIME MainThreadType. 133 // Returns the delay until the next delayed pending task of the main thread's 134 // TaskRunner. 135 TimeDelta NextMainThreadPendingTaskDelay() const; 136 137 private: 138 class TestTaskTracker; 139 140 const ExecutionMode execution_control_mode_; 141 142 // Exactly one of these will be non-null to provide the task environment on 143 // the main thread. Users of this class should NOT rely on the presence of a 144 // MessageLoop beyond (Thread|Sequenced)TaskRunnerHandle and RunLoop as 145 // the backing implementation of each MainThreadType may change over time. 146 const std::unique_ptr<MessageLoop> message_loop_; 147 const scoped_refptr<TestMockTimeTaskRunner> mock_time_task_runner_; 148 149 // Non-null in MOCK_TIME, where an explicit SequenceLocalStorageMap needs to 150 // be provided. TODO(gab): This can be removed once mock time support is added 151 // to MessageLoop directly. 152 const std::unique_ptr<internal::SequenceLocalStorageMap> slsm_for_mock_time_; 153 const std::unique_ptr< 154 internal::ScopedSetSequenceLocalStorageMapForCurrentThread> 155 slsm_registration_for_mock_time_; 156 157 #if defined(OS_POSIX) 158 // Enables the FileDescriptorWatcher API iff running a MainThreadType::IO. 159 const std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher_; 160 #endif 161 162 const TaskScheduler* task_scheduler_ = nullptr; 163 164 // Owned by |task_scheduler_|. 165 TestTaskTracker* const task_tracker_; 166 167 // Ensures destruction of lazy TaskRunners when this is destroyed. 168 internal::ScopedLazyTaskRunnerListForTesting 169 scoped_lazy_task_runner_list_for_testing_; 170 171 DISALLOW_COPY_AND_ASSIGN(ScopedTaskEnvironment); 172 }; 173 174 } // namespace test 175 } // namespace base 176 177 #endif // BASE_TEST_SCOPED_ASYNC_TASK_SCHEDULER_H_ 178