• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors
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_TASK_ENVIRONMENT_H_
6 #define BASE_TEST_TASK_ENVIRONMENT_H_
7 
8 #include <memory>
9 
10 #include "base/compiler_specific.h"
11 #include "base/functional/callback_forward.h"
12 #include "base/memory/raw_ptr_exclusion.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/observer_list_types.h"
15 #include "base/run_loop.h"
16 #include "base/task/lazy_thread_pool_task_runner.h"
17 #include "base/task/sequence_manager/sequence_manager.h"
18 #include "base/task/single_thread_task_runner.h"
19 #include "base/test/scoped_run_loop_timeout.h"
20 #include "base/threading/thread_checker.h"
21 #include "base/time/time.h"
22 #include "base/traits_bag.h"
23 #include "build/build_config.h"
24 
25 namespace base {
26 
27 class Clock;
28 class FileDescriptorWatcher;
29 class TickClock;
30 
31 namespace subtle {
32 class ScopedTimeClockOverrides;
33 }
34 
35 namespace test {
36 
37 // This header exposes SingleThreadTaskEnvironment and TaskEnvironment.
38 //
39 // SingleThreadTaskEnvironment enables the following APIs within its scope:
40 //  - (SingleThread|Sequenced)TaskRunner::CurrentDefaultHandle on the main
41 //    thread
42 //  - RunLoop on the main thread
43 //
44 // TaskEnvironment additionally enables:
45 //  - posting to base::ThreadPool through base/task/thread_pool.h.
46 //
47 // Hint: For content::BrowserThreads, use content::BrowserTaskEnvironment.
48 //
49 // Tests should prefer SingleThreadTaskEnvironment over TaskEnvironment when the
50 // former is sufficient.
51 //
52 // Tasks posted to the (SingleThread|Sequenced)TaskRunner::CurrentDefaultHandle
53 // run synchronously when RunLoop::Run(UntilIdle) or
54 // TaskEnvironment::RunUntil(Idle|Quit) is called on the main thread.
55 //
56 // The TaskEnvironment requires TestTimeouts::Initialize() to be called in order
57 // to run posted tasks, so that it can watch for problematic long-running tasks.
58 //
59 // The TimeSource trait can be used to request that delayed tasks be under the
60 // manual control of RunLoop::Run() and TaskEnvironment::FastForward*() methods.
61 //
62 // If a TaskEnvironment's ThreadPoolExecutionMode is QUEUED, ThreadPool tasks
63 // run when RunUntilIdle(), RunUntilQuit(), or ~TaskEnvironment is called. If
64 // ThreadPoolExecutionMode is ASYNC, they run as they are posted.
65 //
66 // All TaskEnvironment methods must be called from the main thread.
67 //
68 // Usage:
69 //
70 //   class MyTestFixture : public testing::Test {
71 //    public:
72 //     (...)
73 //
74 //    // protected rather than private visibility will allow controlling the
75 //    // task environment (e.g. RunUntilIdle(), FastForwardBy(), etc.). from the
76 //    // test body.
77 //    protected:
78 //     // Must generally be the first member to be initialized first and
79 //     // destroyed last (some members that require single-threaded
80 //     // initialization and tear down may need to come before -- e.g.
81 //     // base::test::ScopedFeatureList). Extra traits, like TimeSource, are
82 //     // best provided inline when declaring the TaskEnvironment, as
83 //     // such:
84 //     base::test::TaskEnvironment task_environment_{
85 //         base::test::TaskEnvironment::TimeSource::MOCK_TIME};
86 //
87 //     // Other members go here (or further below in private section.)
88 //   };
89 class TaskEnvironment {
90  protected:
91   // This enables a two-phase initialization for sub classes such as
92   // content::BrowserTaskEnvironment which need to provide the default task
93   // queue because they instantiate a scheduler on the same thread. Subclasses
94   // using this trait must invoke DeferredInitFromSubclass() before running the
95   // task environment.
96   struct SubclassCreatesDefaultTaskRunner {};
97 
98  public:
99   enum class TimeSource {
100     // Delayed tasks and Time/TimeTicks::Now() use the real-time system clock.
101     SYSTEM_TIME,
102 
103     // Delayed tasks use a mock clock which only advances when reaching "idle"
104     // during a RunLoop::Run() call on the main thread or a FastForward*() call
105     // to this TaskEnvironment. "idle" is defined as the main thread and thread
106     // pool being out of ready tasks. In that situation : time advances to the
107     // soonest delay between main thread and thread pool delayed tasks,
108     // according to the semantics of the current Run*() or FastForward*() call.
109     //
110     // This also mocks Time/TimeTicks::Now() with the same mock clock.
111     // Time::Now() and TimeTicks::Now() (with respect to its origin) start
112     // without submillisecond components.
113     //
114     // Warning some platform APIs are still real-time, e.g.:
115     //   * PlatformThread::Sleep
116     //   * WaitableEvent::TimedWait
117     //   * ConditionVariable::TimedWait
118     //   * Delayed tasks on unmanaged base::Thread's and other custom task
119     //     runners.
120     MOCK_TIME,
121 
122     DEFAULT = SYSTEM_TIME
123   };
124 
125   // This type will determine what types of messages will get pumped by the main
126   // thread.
127   // Note: If your test needs to use a custom MessagePump you should
128   // consider using a SingleThreadTaskExecutor instead.
129   enum class MainThreadType {
130     // The main thread doesn't pump system messages.
131     DEFAULT,
132     // The main thread pumps UI messages.
133     UI,
134     // The main thread pumps asynchronous IO messages and supports the
135     // FileDescriptorWatcher API on POSIX.
136     IO,
137   };
138 
139   // Note that this is irrelevant (and ignored) under
140   // ThreadingMode::MAIN_THREAD_ONLY
141   enum class ThreadPoolExecutionMode {
142     // Thread pool tasks are queued and only executed when RunUntilIdle(),
143     // FastForwardBy(), or FastForwardUntilNoTasksRemain() are explicitly
144     // called. Note: RunLoop::Run() does *not* unblock the ThreadPool in this
145     // mode (it strictly runs only the main thread).
146     QUEUED,
147     // Thread pool tasks run as they are posted. RunUntilIdle() can still be
148     // used to block until done.
149     // Note that regardless of this trait, delayed tasks are always "queued"
150     // under TimeSource::MOCK_TIME mode.
151     ASYNC,
152     DEFAULT = ASYNC
153   };
154 
155   enum class ThreadingMode {
156     // ThreadPool will be initialized, thus adding support for multi-threaded
157     // tests.
158     MULTIPLE_THREADS,
159     // No thread pool will be initialized. Useful for tests that want to run
160     // single threaded. Prefer using SingleThreadTaskEnvironment over this
161     // trait.
162     MAIN_THREAD_ONLY,
163     DEFAULT = MULTIPLE_THREADS
164   };
165 
166   // On Windows, sets the COM environment for the ThreadPoolInstance. Ignored
167   // on other platforms.
168   enum class ThreadPoolCOMEnvironment {
169     // Do not initialize COM for the pool's workers.
170     NONE,
171 
172     // Place the pool's workers in a COM MTA.
173     COM_MTA,
174 
175     // Enable the MTA by default in unit tests to match the browser process's
176     // ThreadPoolInstance configuration.
177     //
178     // This has the adverse side-effect of enabling the MTA in non-browser unit
179     // tests as well but the downside there is not as bad as not having it in
180     // browser unit tests. It just means some COM asserts may pass in unit
181     // tests where they wouldn't in integration tests or prod. That's okay
182     // because unit tests are already generally very loose on allowing I/O,
183     // waits, etc. Such misuse will still be caught in later phases (and COM
184     // usage should already be pretty much inexistent in sandboxed processes).
185     DEFAULT = COM_MTA,
186   };
187 
188   // List of traits that are valid inputs for the constructor below.
189   struct ValidTraits {
190     ValidTraits(TimeSource);
191     ValidTraits(MainThreadType);
192     ValidTraits(ThreadPoolExecutionMode);
193     ValidTraits(SubclassCreatesDefaultTaskRunner);
194     ValidTraits(ThreadingMode);
195     ValidTraits(ThreadPoolCOMEnvironment);
196   };
197 
198   // Constructor accepts zero or more traits which customize the testing
199   // environment.
200   template <typename... TaskEnvironmentTraits,
201             class CheckArgumentsAreValid = std::enable_if_t<
202                 trait_helpers::AreValidTraits<ValidTraits,
203                                               TaskEnvironmentTraits...>::value>>
TaskEnvironment(TaskEnvironmentTraits...traits)204   NOINLINE explicit TaskEnvironment(TaskEnvironmentTraits... traits)
205       : TaskEnvironment(sequence_manager::SequenceManager::PrioritySettings::
206                             CreateDefault(),
207                         traits...) {}
208 
209   TaskEnvironment(const TaskEnvironment&) = delete;
210   TaskEnvironment& operator=(const TaskEnvironment&) = delete;
211 
212   // Waits until no undelayed ThreadPool tasks remain. Then, unregisters the
213   // ThreadPoolInstance and the
214   // (SingleThread|Sequenced)TaskRunner::CurrentDefaultHandle.
215   virtual ~TaskEnvironment();
216 
217   // Returns a TaskRunner that schedules tasks on the main thread.
218   scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner();
219 
220   // Returns whether the main thread's TaskRunner has pending tasks. This will
221   // always return true if called right after RunUntilIdle.
222   bool MainThreadIsIdle() const;
223 
224   // Returns a RepeatingClosure that ends the next call to RunUntilQuit(). The
225   // quit closures must be obtained from the thread owning the TaskEnvironment
226   // but may then be invoked from any thread. To avoid a potential race
227   // condition, do not call QuitClosure() while RunUntilQuit() is running.
228   RepeatingClosure QuitClosure();
229 
230   // Runs tasks on both the main thread and the thread pool, until a quit
231   // closure is executed. When RunUntilQuit() returns, all previous quit
232   // closures are invalidated, and will have no effect on future calls. Be sure
233   // to create a new quit closure before calling RunUntilQuit() again.
234   void RunUntilQuit();
235 
236   // Runs tasks until both the
237   // (SingleThread|Sequenced)TaskRunner::CurrentDefaultHandle and the
238   // ThreadPool's non-delayed queues are empty.  While RunUntilIdle() is quite
239   // practical and sometimes even necessary -- for example, to flush all tasks
240   // bound to Unretained() state before destroying test members -- it should be
241   // used with caution per the following warnings:
242   //
243   // WARNING #1: This may run long (flakily timeout) and even never return! Do
244   //             not use this when repeating tasks such as animated web pages
245   //             are present.
246   // WARNING #2: This may return too early! For example, if used to run until an
247   //             incoming event has occurred but that event depends on a task in
248   //             a different queue -- e.g. a standalone base::Thread or a system
249   //             event.
250   //
251   // As such, prefer RunLoop::Run() with an explicit RunLoop::QuitClosure() when
252   // possible.
253   void RunUntilIdle();
254 
255   // Only valid for instances using TimeSource::MOCK_TIME. Fast-forwards
256   // virtual time by |delta|, causing all tasks on the main thread and thread
257   // pool with a remaining delay less than or equal to |delta| to be executed in
258   // their natural order before this returns. |delta| must be non-negative. Upon
259   // returning from this method, NowTicks() will be >= the initial |NowTicks() +
260   // delta|. It is guaranteed to be == iff tasks executed in this
261   // FastForwardBy() didn't result in nested calls to time-advancing-methods.
262   void FastForwardBy(TimeDelta delta);
263 
264   // Only valid for instances using TimeSource::MOCK_TIME.
265   // Short for FastForwardBy(TimeDelta::Max()).
266   //
267   // WARNING: This has the same caveat as RunUntilIdle() and is even more likely
268   // to spin forever (any RepeatingTimer will cause this).
269   void FastForwardUntilNoTasksRemain();
270 
271   // Only valid for instances using TimeSource::MOCK_TIME. Advances virtual time
272   // by |delta|. Unlike FastForwardBy, this does not run tasks. Prefer
273   // FastForwardBy() when possible but this can be useful when testing blocked
274   // pending tasks where being idle (required to fast-forward) is not possible.
275   //
276   // Delayed tasks that are ripe as a result of this will be scheduled.
277   // RunUntilIdle() can be used after this call to ensure those tasks have run.
278   // Note: AdvanceClock(delta) + RunUntilIdle() is slightly different from
279   // FastForwardBy(delta) in that time passes instantly before running any task
280   // (whereas FastForwardBy() will advance the clock in the smallest increments
281   // possible at a time). Hence FastForwardBy() is more realistic but
282   // AdvanceClock() can be useful when testing edge case scenarios that
283   // specifically handle more time than expected to have passed.
284   void AdvanceClock(TimeDelta delta);
285 
UsesMockTime()286   bool UsesMockTime() const { return !!mock_clock_; }
287 
288   // Only valid for instances using TimeSource::MOCK_TIME. Returns a
289   // TickClock whose time is updated by FastForward(By|UntilNoTasksRemain).
290   const TickClock* GetMockTickClock() const;
291 
292   // Only valid for instances using TimeSource::MOCK_TIME. Returns a
293   // Clock whose time is updated by FastForward(By|UntilNoTasksRemain). The
294   // initial value is implementation defined and should be queried by tests that
295   // depend on it.
296   // TickClock should be used instead of Clock to measure elapsed time in a
297   // process. See time.h.
298   const Clock* GetMockClock() const;
299 
300   // Only valid for instances using TimeSource::MOCK_TIME. Returns the current
301   // virtual tick time (based on a realistic Now(), sampled when this
302   // TaskEnvironment was created, and manually advanced from that point on).
303   // This is always equivalent to base::TimeTicks::Now() under
304   // TimeSource::MOCK_TIME.
305   base::TimeTicks NowTicks() const;
306 
307   // Only valid for instances using TimeSource::MOCK_TIME. Returns the number of
308   // pending tasks (delayed and non-delayed) of the main thread's TaskRunner.
309   // When debugging, you can use DescribeCurrentTasks() to see what those are.
310   size_t GetPendingMainThreadTaskCount() const;
311 
312   // Only valid for instances using TimeSource::MOCK_TIME.
313   // Returns the delay until the next pending task of the main thread's
314   // TaskRunner if there is one, otherwise it returns TimeDelta::Max().
315   TimeDelta NextMainThreadPendingTaskDelay() const;
316 
317   // Only valid for instances using TimeSource::MOCK_TIME.
318   // Returns true iff the next task is delayed. Returns false if the next task
319   // is immediate or if there is no next task.
320   bool NextTaskIsDelayed() const;
321 
322   // For debugging purposes: Dumps information about pending tasks on the main
323   // thread, and currently running tasks on the thread pool.
324   void DescribeCurrentTasks() const;
325 
326   // Detach ThreadCheckers (will rebind on next usage), useful for the odd test
327   // suite which doesn't run on the main thread but still has exclusive access
328   // to driving this TaskEnvironment (e.g. WaylandClientTestSuiteServer).
329   void DetachFromThread();
330 
331   class TestTaskTracker;
332   // Callers outside of TaskEnvironment may not use the returned pointer. They
333   // should just use base::ThreadPoolInstance::Get().
334   static TestTaskTracker* CreateThreadPool();
335 
336   class DestructionObserver : public CheckedObserver {
337    public:
338     DestructionObserver() = default;
339     ~DestructionObserver() override = default;
340 
341     DestructionObserver(const DestructionObserver&) = delete;
342     DestructionObserver& operator=(const DestructionObserver&) = delete;
343 
344     virtual void WillDestroyCurrentTaskEnvironment() = 0;
345   };
346 
347   // Adds/removes a DestructionObserver to any TaskEnvironment. Observers are
348   // notified when any TaskEnvironment goes out of scope (other than with a move
349   // operation). Must be called on the main thread.
350   static void AddDestructionObserver(DestructionObserver* observer);
351   static void RemoveDestructionObserver(DestructionObserver* observer);
352 
353   // Instantiating a ParallelExecutionFence waits for all currently running
354   // ThreadPool tasks before the constructor returns and from then on prevents
355   // additional tasks from running during its lifetime.
356   //
357   // Must be instantiated from the test main thread.
358   class ParallelExecutionFence {
359    public:
360     // Instantiates a ParallelExecutionFence, crashes with an optional
361     // |error_message| if not invoked from test main thread.
362     explicit ParallelExecutionFence(const char* error_message = "");
363     ~ParallelExecutionFence();
364 
365     ParallelExecutionFence(const ParallelExecutionFence&) = delete;
366     ParallelExecutionFence& operator=(const ParallelExecutionFence& other) =
367         delete;
368 
369    private:
370     bool previously_allowed_to_run_ = false;
371   };
372 
373   // The number of foreground workers in the ThreadPool managed by a
374   // TaskEnvironment instance. This can be used to determine the maximum
375   // parallelism in tests that require each parallel task it spawns to be
376   // running at once. Having multiple threads prevents deadlocks should some
377   // blocking APIs not use ScopedBlockingCall. It also allows enough concurrency
378   // to allow TSAN to spot data races.
379   static constexpr int kNumForegroundThreadPoolThreads = 4;
380 
381  protected:
382   template <typename... TaskEnvironmentTraits,
383             class CheckArgumentsAreValid = std::enable_if_t<
384                 trait_helpers::AreValidTraits<ValidTraits,
385                                               TaskEnvironmentTraits...>::value>>
CreateTaskEnvironmentWithPriorities(sequence_manager::SequenceManager::PrioritySettings priority_settings,TaskEnvironmentTraits...traits)386   NOINLINE static TaskEnvironment CreateTaskEnvironmentWithPriorities(
387       sequence_manager::SequenceManager::PrioritySettings priority_settings,
388       TaskEnvironmentTraits... traits) {
389     return TaskEnvironment(std::move(priority_settings), traits...);
390   }
391 
392   // Constructor accepts zero or more traits which customize the testing
393   // environment.
394   template <typename... TaskEnvironmentTraits,
395             class CheckArgumentsAreValid = std::enable_if_t<
396                 trait_helpers::AreValidTraits<ValidTraits,
397                                               TaskEnvironmentTraits...>::value>>
TaskEnvironment(sequence_manager::SequenceManager::PrioritySettings priority_settings,TaskEnvironmentTraits...traits)398   NOINLINE explicit TaskEnvironment(
399       sequence_manager::SequenceManager::PrioritySettings priority_settings,
400       TaskEnvironmentTraits... traits)
401       : TaskEnvironment(
402             std::move(priority_settings),
403             trait_helpers::GetEnum<TimeSource, TimeSource::DEFAULT>(traits...),
404             trait_helpers::GetEnum<MainThreadType, MainThreadType::DEFAULT>(
405                 traits...),
406             trait_helpers::GetEnum<ThreadPoolExecutionMode,
407                                    ThreadPoolExecutionMode::DEFAULT>(traits...),
408             trait_helpers::GetEnum<ThreadingMode, ThreadingMode::DEFAULT>(
409                 traits...),
410             trait_helpers::GetEnum<ThreadPoolCOMEnvironment,
411                                    ThreadPoolCOMEnvironment::DEFAULT>(
412                 traits...),
413             trait_helpers::HasTrait<SubclassCreatesDefaultTaskRunner,
414                                     TaskEnvironmentTraits...>(),
415             trait_helpers::NotATraitTag()) {}
416 
417   TaskEnvironment(TaskEnvironment&& other);
418 
main_thread_type()419   constexpr MainThreadType main_thread_type() const {
420     return main_thread_type_;
421   }
422 
thread_pool_execution_mode()423   constexpr ThreadPoolExecutionMode thread_pool_execution_mode() const {
424     return thread_pool_execution_mode_;
425   }
426 
427   // Returns the MockTimeDomain driving this TaskEnvironment if this instance is
428   // using TimeSource::MOCK_TIME, nullptr otherwise.
429   sequence_manager::TimeDomain* GetMockTimeDomain() const;
430 
431   sequence_manager::SequenceManager* sequence_manager() const;
432 
433   void DeferredInitFromSubclass(
434       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
435 
436   // Derived classes may need to control when the task environment goes away
437   // (e.g. ~FooTaskEnvironment() may want to effectively trigger
438   // ~TaskEnvironment() before its members are destroyed).
439   void DestroyTaskEnvironment();
440 
441  private:
442   class MockTimeDomain;
443 
444   void InitializeThreadPool();
445   void ShutdownAndJoinThreadPool();
446   void DestroyThreadPool();
447 
448   void CompleteInitialization();
449 
450   // The template constructor has to be in the header but it delegates to this
451   // constructor to initialize all other members out-of-line.
452   TaskEnvironment(
453       sequence_manager::SequenceManager::PrioritySettings priority_settings,
454       TimeSource time_source,
455       MainThreadType main_thread_type,
456       ThreadPoolExecutionMode thread_pool_execution_mode,
457       ThreadingMode threading_mode,
458       ThreadPoolCOMEnvironment thread_pool_com_environment,
459       bool subclass_creates_default_taskrunner,
460       trait_helpers::NotATraitTag tag);
461 
462   const MainThreadType main_thread_type_;
463   const ThreadPoolExecutionMode thread_pool_execution_mode_;
464   const ThreadingMode threading_mode_;
465   const ThreadPoolCOMEnvironment thread_pool_com_environment_;
466   const bool subclass_creates_default_taskrunner_;
467 
468   std::unique_ptr<sequence_manager::SequenceManager> sequence_manager_;
469 
470   // Manages the clock under TimeSource::MOCK_TIME modes. Null in
471   // TimeSource::SYSTEM_TIME mode.
472   std::unique_ptr<MockTimeDomain> mock_time_domain_;
473 
474   // Overrides Time/TimeTicks::Now() under TimeSource::MOCK_TIME mode.
475   // Null in other modes.
476   std::unique_ptr<subtle::ScopedTimeClockOverrides> time_overrides_;
477 
478   scoped_refptr<sequence_manager::TaskQueue> task_queue_;
479   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
480 
481   // Only set for instances using TimeSource::MOCK_TIME.
482   std::unique_ptr<Clock> mock_clock_;
483 
484 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
485   // Enables the FileDescriptorWatcher API iff running a MainThreadType::IO.
486   std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher_;
487 #endif
488 
489   // Owned by the ThreadPoolInstance.
490   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
491   // #union
492   RAW_PTR_EXCLUSION TestTaskTracker* task_tracker_ = nullptr;
493 
494   // Ensures destruction of lazy TaskRunners when this is destroyed.
495   std::unique_ptr<base::internal::ScopedLazyTaskRunnerListForTesting>
496       scoped_lazy_task_runner_list_for_testing_;
497 
498   // Sets RunLoop::Run() to LOG(FATAL) if not Quit() in a timely manner.
499   std::unique_ptr<ScopedRunLoopTimeout> run_loop_timeout_;
500 
501   std::unique_ptr<bool> owns_instance_ = std::make_unique<bool>(true);
502 
503   std::unique_ptr<RunLoop> run_until_quit_loop_;
504 
505   // Used to verify thread-affinity of operations that must occur on the main
506   // thread. This is the case for anything that modifies or drives the
507   // |sequence_manager_|.
508   THREAD_CHECKER(main_thread_checker_);
509 };
510 
511 // SingleThreadTaskEnvironment takes the same traits as TaskEnvironment and is
512 // used the exact same way. It's a short-form for
513 //   TaskEnvironment{TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY, ...};
514 class SingleThreadTaskEnvironment : public TaskEnvironment {
515  public:
516   template <class... ArgTypes>
SingleThreadTaskEnvironment(ArgTypes...args)517   SingleThreadTaskEnvironment(ArgTypes... args)
518       : TaskEnvironment(ThreadingMode::MAIN_THREAD_ONLY, args...) {}
519 };
520 
521 }  // namespace test
522 }  // namespace base
523 
524 #endif  // BASE_TEST_TASK_ENVIRONMENT_H_
525