|  | // Copyright 2017 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef BASE_TEST_SCOPED_TASK_ENVIRONMENT_H_ | 
|  | #define BASE_TEST_SCOPED_TASK_ENVIRONMENT_H_ | 
|  |  | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/ref_counted.h" | 
|  | #include "base/single_thread_task_runner.h" | 
|  | #include "base/task_scheduler/lazy_task_runner.h" | 
|  | #include "build_config.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | namespace internal { | 
|  | class ScopedSetSequenceLocalStorageMapForCurrentThread; | 
|  | class SequenceLocalStorageMap; | 
|  | }  // namespace internal | 
|  |  | 
|  | class FileDescriptorWatcher; | 
|  | class MessageLoop; | 
|  | class TaskScheduler; | 
|  | class TestMockTimeTaskRunner; | 
|  | class TickClock; | 
|  |  | 
|  | namespace test { | 
|  |  | 
|  | // ScopedTaskEnvironment allows usage of these APIs within its scope: | 
|  | // - (Thread|Sequenced)TaskRunnerHandle, on the thread where it lives | 
|  | // - base/task_scheduler/post_task.h, on any thread | 
|  | // | 
|  | // Tests that need either of these APIs should instantiate a | 
|  | // ScopedTaskEnvironment. | 
|  | // | 
|  | // Tasks posted to the (Thread|Sequenced)TaskRunnerHandle run synchronously when | 
|  | // RunLoop::Run(UntilIdle) or ScopedTaskEnvironment::RunUntilIdle is called on | 
|  | // the thread where the ScopedTaskEnvironment lives. | 
|  | // | 
|  | // Tasks posted through base/task_scheduler/post_task.h run on dedicated | 
|  | // threads. If ExecutionMode is QUEUED, they run when RunUntilIdle() or | 
|  | // ~ScopedTaskEnvironment is called. If ExecutionMode is ASYNC, they run | 
|  | // as they are posted. | 
|  | // | 
|  | // All methods of ScopedTaskEnvironment must be called from the same thread. | 
|  | // | 
|  | // Usage: | 
|  | // | 
|  | //   class MyTestFixture : public testing::Test { | 
|  | //    public: | 
|  | //     (...) | 
|  | // | 
|  | //    protected: | 
|  | //     // Must be the first member (or at least before any member that cares | 
|  | //     // about tasks) to be initialized first and destroyed last. protected | 
|  | //     // instead of private visibility will allow controlling the task | 
|  | //     // environment (e.g. clock) once such features are added (see design doc | 
|  | //     // below for details), until then it at least doesn't hurt :). | 
|  | //     base::test::ScopedTaskEnvironment scoped_task_environment_; | 
|  | // | 
|  | //     // Other members go here (or further below in private section.) | 
|  | //   }; | 
|  | // | 
|  | // Design and future improvements documented in | 
|  | // https://docs.google.com/document/d/1QabRo8c7D9LsYY3cEcaPQbOCLo8Tu-6VLykYXyl3Pkk/edit | 
|  | class ScopedTaskEnvironment { | 
|  | public: | 
|  | enum class MainThreadType { | 
|  | // The main thread doesn't pump system messages. | 
|  | DEFAULT, | 
|  | // The main thread doesn't pump system messages and uses a mock clock for | 
|  | // delayed tasks (controllable via FastForward*() methods). | 
|  | // TODO(gab): Make this the default |main_thread_type|. | 
|  | // TODO(gab): Also mock the TaskScheduler's clock simultaneously (this | 
|  | // currently only mocks the main thread's clock). | 
|  | MOCK_TIME, | 
|  | // The main thread pumps UI messages. | 
|  | UI, | 
|  | // The main thread pumps asynchronous IO messages and supports the | 
|  | // FileDescriptorWatcher API on POSIX. | 
|  | IO, | 
|  | }; | 
|  |  | 
|  | enum class ExecutionMode { | 
|  | // Tasks are queued and only executed when RunUntilIdle() is explicitly | 
|  | // called. | 
|  | QUEUED, | 
|  | // Tasks run as they are posted. RunUntilIdle() can still be used to block | 
|  | // until done. | 
|  | ASYNC, | 
|  | }; | 
|  |  | 
|  | ScopedTaskEnvironment( | 
|  | MainThreadType main_thread_type = MainThreadType::DEFAULT, | 
|  | ExecutionMode execution_control_mode = ExecutionMode::ASYNC); | 
|  |  | 
|  | // Waits until no undelayed TaskScheduler tasks remain. Then, unregisters the | 
|  | // TaskScheduler and the (Thread|Sequenced)TaskRunnerHandle. | 
|  | ~ScopedTaskEnvironment(); | 
|  |  | 
|  | // Returns a TaskRunner that schedules tasks on the main thread. | 
|  | scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner(); | 
|  |  | 
|  | // Returns whether the main thread's TaskRunner has pending tasks. | 
|  | bool MainThreadHasPendingTask() const; | 
|  |  | 
|  | // Runs tasks until both the (Thread|Sequenced)TaskRunnerHandle and the | 
|  | // TaskScheduler's non-delayed queues are empty. | 
|  | void RunUntilIdle(); | 
|  |  | 
|  | // Only valid for instances with a MOCK_TIME MainThreadType. Fast-forwards | 
|  | // virtual time by |delta|, causing all tasks on the main thread with a | 
|  | // remaining delay less than or equal to |delta| to be executed before this | 
|  | // returns. |delta| must be non-negative. | 
|  | // TODO(gab): Make this apply to TaskScheduler delayed tasks as well | 
|  | // (currently only main thread time is mocked). | 
|  | void FastForwardBy(TimeDelta delta); | 
|  |  | 
|  | // Only valid for instances with a MOCK_TIME MainThreadType. | 
|  | // Short for FastForwardBy(TimeDelta::Max()). | 
|  | void FastForwardUntilNoTasksRemain(); | 
|  |  | 
|  | // Only valid for instances with a MOCK_TIME MainThreadType.  Returns a | 
|  | // TickClock whose time is updated by FastForward(By|UntilNoTasksRemain). | 
|  | const TickClock* GetMockTickClock(); | 
|  | std::unique_ptr<TickClock> DeprecatedGetMockTickClock(); | 
|  |  | 
|  | // Only valid for instances with a MOCK_TIME MainThreadType. | 
|  | // Returns the number of pending tasks of the main thread's TaskRunner. | 
|  | size_t GetPendingMainThreadTaskCount() const; | 
|  |  | 
|  | // Only valid for instances with a MOCK_TIME MainThreadType. | 
|  | // Returns the delay until the next delayed pending task of the main thread's | 
|  | // TaskRunner. | 
|  | TimeDelta NextMainThreadPendingTaskDelay() const; | 
|  |  | 
|  | private: | 
|  | class TestTaskTracker; | 
|  |  | 
|  | const ExecutionMode execution_control_mode_; | 
|  |  | 
|  | // Exactly one of these will be non-null to provide the task environment on | 
|  | // the main thread. Users of this class should NOT rely on the presence of a | 
|  | // MessageLoop beyond (Thread|Sequenced)TaskRunnerHandle and RunLoop as | 
|  | // the backing implementation of each MainThreadType may change over time. | 
|  | const std::unique_ptr<MessageLoop> message_loop_; | 
|  | const scoped_refptr<TestMockTimeTaskRunner> mock_time_task_runner_; | 
|  |  | 
|  | // Non-null in MOCK_TIME, where an explicit SequenceLocalStorageMap needs to | 
|  | // be provided. TODO(gab): This can be removed once mock time support is added | 
|  | // to MessageLoop directly. | 
|  | const std::unique_ptr<internal::SequenceLocalStorageMap> slsm_for_mock_time_; | 
|  | const std::unique_ptr< | 
|  | internal::ScopedSetSequenceLocalStorageMapForCurrentThread> | 
|  | slsm_registration_for_mock_time_; | 
|  |  | 
|  | #if defined(OS_POSIX) | 
|  | // Enables the FileDescriptorWatcher API iff running a MainThreadType::IO. | 
|  | const std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher_; | 
|  | #endif | 
|  |  | 
|  | const TaskScheduler* task_scheduler_ = nullptr; | 
|  |  | 
|  | // Owned by |task_scheduler_|. | 
|  | TestTaskTracker* const task_tracker_; | 
|  |  | 
|  | // Ensures destruction of lazy TaskRunners when this is destroyed. | 
|  | internal::ScopedLazyTaskRunnerListForTesting | 
|  | scoped_lazy_task_runner_list_for_testing_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(ScopedTaskEnvironment); | 
|  | }; | 
|  |  | 
|  | }  // namespace test | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_TEST_SCOPED_ASYNC_TASK_SCHEDULER_H_ |