blob: 45b253166851011c6cb090ab986a463c38fd9d17 [file] [log] [blame]
// 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.
#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"
namespace base {
class MessageLoop;
class TaskScheduler;
class TestMockTimeTaskRunner;
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
class ScopedTaskEnvironment {
enum class MainThreadType {
// The main thread doesn't pump system messages.
// 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).
// The main thread pumps UI messages.
// The main thread pumps asynchronous IO messages.
enum class ExecutionMode {
// Tasks are queued and only executed when RunUntilIdle() is explicitly
// called.
// Tasks run as they are posted. RunUntilIdle() can still be used to block
// until done.
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.
// Returns a TaskRunner that schedules tasks on the main thread.
scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner();
// 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();
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_;
const TaskScheduler* task_scheduler_ = nullptr;
// Owned by |task_scheduler_|.
TestTaskTracker* const task_tracker_;
// Ensures destruction of lazy TaskRunners when this is destroyed.
} // namespace test
} // namespace base