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