525 lines
22 KiB
C++
525 lines
22 KiB
C++
// Copyright 2017 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef BASE_TEST_TASK_ENVIRONMENT_H_
|
|
#define BASE_TEST_TASK_ENVIRONMENT_H_
|
|
|
|
#include <memory>
|
|
|
|
#include "base/compiler_specific.h"
|
|
#include "base/functional/callback_forward.h"
|
|
#include "base/memory/raw_ptr_exclusion.h"
|
|
#include "base/memory/ref_counted.h"
|
|
#include "base/observer_list_types.h"
|
|
#include "base/run_loop.h"
|
|
#include "base/task/lazy_thread_pool_task_runner.h"
|
|
#include "base/task/sequence_manager/sequence_manager.h"
|
|
#include "base/task/single_thread_task_runner.h"
|
|
#include "base/test/scoped_run_loop_timeout.h"
|
|
#include "base/threading/thread_checker.h"
|
|
#include "base/time/time.h"
|
|
#include "base/traits_bag.h"
|
|
#include "build/build_config.h"
|
|
|
|
namespace base {
|
|
|
|
class Clock;
|
|
class FileDescriptorWatcher;
|
|
class TickClock;
|
|
|
|
namespace subtle {
|
|
class ScopedTimeClockOverrides;
|
|
}
|
|
|
|
namespace test {
|
|
|
|
// This header exposes SingleThreadTaskEnvironment and TaskEnvironment.
|
|
//
|
|
// SingleThreadTaskEnvironment enables the following APIs within its scope:
|
|
// - (SingleThread|Sequenced)TaskRunner::CurrentDefaultHandle on the main
|
|
// thread
|
|
// - RunLoop on the main thread
|
|
//
|
|
// TaskEnvironment additionally enables:
|
|
// - posting to base::ThreadPool through base/task/thread_pool.h.
|
|
//
|
|
// Hint: For content::BrowserThreads, use content::BrowserTaskEnvironment.
|
|
//
|
|
// Tests should prefer SingleThreadTaskEnvironment over TaskEnvironment when the
|
|
// former is sufficient.
|
|
//
|
|
// Tasks posted to the (SingleThread|Sequenced)TaskRunner::CurrentDefaultHandle
|
|
// run synchronously when RunLoop::Run(UntilIdle) or
|
|
// TaskEnvironment::RunUntil(Idle|Quit) is called on the main thread.
|
|
//
|
|
// The TaskEnvironment requires TestTimeouts::Initialize() to be called in order
|
|
// to run posted tasks, so that it can watch for problematic long-running tasks.
|
|
//
|
|
// The TimeSource trait can be used to request that delayed tasks be under the
|
|
// manual control of RunLoop::Run() and TaskEnvironment::FastForward*() methods.
|
|
//
|
|
// If a TaskEnvironment's ThreadPoolExecutionMode is QUEUED, ThreadPool tasks
|
|
// run when RunUntilIdle(), RunUntilQuit(), or ~TaskEnvironment is called. If
|
|
// ThreadPoolExecutionMode is ASYNC, they run as they are posted.
|
|
//
|
|
// All TaskEnvironment methods must be called from the main thread.
|
|
//
|
|
// Usage:
|
|
//
|
|
// class MyTestFixture : public testing::Test {
|
|
// public:
|
|
// (...)
|
|
//
|
|
// // protected rather than private visibility will allow controlling the
|
|
// // task environment (e.g. RunUntilIdle(), FastForwardBy(), etc.). from the
|
|
// // test body.
|
|
// protected:
|
|
// // Must generally be the first member to be initialized first and
|
|
// // destroyed last (some members that require single-threaded
|
|
// // initialization and tear down may need to come before -- e.g.
|
|
// // base::test::ScopedFeatureList). Extra traits, like TimeSource, are
|
|
// // best provided inline when declaring the TaskEnvironment, as
|
|
// // such:
|
|
// base::test::TaskEnvironment task_environment_{
|
|
// base::test::TaskEnvironment::TimeSource::MOCK_TIME};
|
|
//
|
|
// // Other members go here (or further below in private section.)
|
|
// };
|
|
class TaskEnvironment {
|
|
protected:
|
|
// This enables a two-phase initialization for sub classes such as
|
|
// content::BrowserTaskEnvironment which need to provide the default task
|
|
// queue because they instantiate a scheduler on the same thread. Subclasses
|
|
// using this trait must invoke DeferredInitFromSubclass() before running the
|
|
// task environment.
|
|
struct SubclassCreatesDefaultTaskRunner {};
|
|
|
|
public:
|
|
enum class TimeSource {
|
|
// Delayed tasks and Time/TimeTicks::Now() use the real-time system clock.
|
|
SYSTEM_TIME,
|
|
|
|
// Delayed tasks use a mock clock which only advances when reaching "idle"
|
|
// during a RunLoop::Run() call on the main thread or a FastForward*() call
|
|
// to this TaskEnvironment. "idle" is defined as the main thread and thread
|
|
// pool being out of ready tasks. In that situation : time advances to the
|
|
// soonest delay between main thread and thread pool delayed tasks,
|
|
// according to the semantics of the current Run*() or FastForward*() call.
|
|
//
|
|
// This also mocks Time/TimeTicks::Now() with the same mock clock.
|
|
// Time::Now() and TimeTicks::Now() (with respect to its origin) start
|
|
// without submillisecond components.
|
|
//
|
|
// Warning some platform APIs are still real-time, e.g.:
|
|
// * PlatformThread::Sleep
|
|
// * WaitableEvent::TimedWait
|
|
// * ConditionVariable::TimedWait
|
|
// * Delayed tasks on unmanaged base::Thread's and other custom task
|
|
// runners.
|
|
MOCK_TIME,
|
|
|
|
DEFAULT = SYSTEM_TIME
|
|
};
|
|
|
|
// This type will determine what types of messages will get pumped by the main
|
|
// thread.
|
|
// Note: If your test needs to use a custom MessagePump you should
|
|
// consider using a SingleThreadTaskExecutor instead.
|
|
enum class MainThreadType {
|
|
// The main thread doesn't pump system messages.
|
|
DEFAULT,
|
|
// The main thread pumps UI messages.
|
|
UI,
|
|
// The main thread pumps asynchronous IO messages and supports the
|
|
// FileDescriptorWatcher API on POSIX.
|
|
IO,
|
|
};
|
|
|
|
// Note that this is irrelevant (and ignored) under
|
|
// ThreadingMode::MAIN_THREAD_ONLY
|
|
enum class ThreadPoolExecutionMode {
|
|
// Thread pool tasks are queued and only executed when RunUntilIdle(),
|
|
// FastForwardBy(), or FastForwardUntilNoTasksRemain() are explicitly
|
|
// called. Note: RunLoop::Run() does *not* unblock the ThreadPool in this
|
|
// mode (it strictly runs only the main thread).
|
|
QUEUED,
|
|
// Thread pool tasks run as they are posted. RunUntilIdle() can still be
|
|
// used to block until done.
|
|
// Note that regardless of this trait, delayed tasks are always "queued"
|
|
// under TimeSource::MOCK_TIME mode.
|
|
ASYNC,
|
|
DEFAULT = ASYNC
|
|
};
|
|
|
|
enum class ThreadingMode {
|
|
// ThreadPool will be initialized, thus adding support for multi-threaded
|
|
// tests.
|
|
MULTIPLE_THREADS,
|
|
// No thread pool will be initialized. Useful for tests that want to run
|
|
// single threaded. Prefer using SingleThreadTaskEnvironment over this
|
|
// trait.
|
|
MAIN_THREAD_ONLY,
|
|
DEFAULT = MULTIPLE_THREADS
|
|
};
|
|
|
|
// On Windows, sets the COM environment for the ThreadPoolInstance. Ignored
|
|
// on other platforms.
|
|
enum class ThreadPoolCOMEnvironment {
|
|
// Do not initialize COM for the pool's workers.
|
|
NONE,
|
|
|
|
// Place the pool's workers in a COM MTA.
|
|
COM_MTA,
|
|
|
|
// Enable the MTA by default in unit tests to match the browser process's
|
|
// ThreadPoolInstance configuration.
|
|
//
|
|
// This has the adverse side-effect of enabling the MTA in non-browser unit
|
|
// tests as well but the downside there is not as bad as not having it in
|
|
// browser unit tests. It just means some COM asserts may pass in unit
|
|
// tests where they wouldn't in integration tests or prod. That's okay
|
|
// because unit tests are already generally very loose on allowing I/O,
|
|
// waits, etc. Such misuse will still be caught in later phases (and COM
|
|
// usage should already be pretty much inexistent in sandboxed processes).
|
|
DEFAULT = COM_MTA,
|
|
};
|
|
|
|
// List of traits that are valid inputs for the constructor below.
|
|
struct ValidTraits {
|
|
ValidTraits(TimeSource);
|
|
ValidTraits(MainThreadType);
|
|
ValidTraits(ThreadPoolExecutionMode);
|
|
ValidTraits(SubclassCreatesDefaultTaskRunner);
|
|
ValidTraits(ThreadingMode);
|
|
ValidTraits(ThreadPoolCOMEnvironment);
|
|
};
|
|
|
|
// Constructor accepts zero or more traits which customize the testing
|
|
// environment.
|
|
template <typename... TaskEnvironmentTraits,
|
|
class CheckArgumentsAreValid = std::enable_if_t<
|
|
trait_helpers::AreValidTraits<ValidTraits,
|
|
TaskEnvironmentTraits...>::value>>
|
|
NOINLINE explicit TaskEnvironment(TaskEnvironmentTraits... traits)
|
|
: TaskEnvironment(sequence_manager::SequenceManager::PrioritySettings::
|
|
CreateDefault(),
|
|
traits...) {}
|
|
|
|
TaskEnvironment(const TaskEnvironment&) = delete;
|
|
TaskEnvironment& operator=(const TaskEnvironment&) = delete;
|
|
|
|
// Waits until no undelayed ThreadPool tasks remain. Then, unregisters the
|
|
// ThreadPoolInstance and the
|
|
// (SingleThread|Sequenced)TaskRunner::CurrentDefaultHandle.
|
|
virtual ~TaskEnvironment();
|
|
|
|
// 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. This will
|
|
// always return true if called right after RunUntilIdle.
|
|
bool MainThreadIsIdle() const;
|
|
|
|
// Returns a RepeatingClosure that ends the next call to RunUntilQuit(). The
|
|
// quit closures must be obtained from the thread owning the TaskEnvironment
|
|
// but may then be invoked from any thread. To avoid a potential race
|
|
// condition, do not call QuitClosure() while RunUntilQuit() is running.
|
|
RepeatingClosure QuitClosure();
|
|
|
|
// Runs tasks on both the main thread and the thread pool, until a quit
|
|
// closure is executed. When RunUntilQuit() returns, all previous quit
|
|
// closures are invalidated, and will have no effect on future calls. Be sure
|
|
// to create a new quit closure before calling RunUntilQuit() again.
|
|
void RunUntilQuit();
|
|
|
|
// Runs tasks until both the
|
|
// (SingleThread|Sequenced)TaskRunner::CurrentDefaultHandle and the
|
|
// ThreadPool's non-delayed queues are empty. While RunUntilIdle() is quite
|
|
// practical and sometimes even necessary -- for example, to flush all tasks
|
|
// bound to Unretained() state before destroying test members -- it should be
|
|
// used with caution per the following warnings:
|
|
//
|
|
// WARNING #1: This may run long (flakily timeout) and even never return! Do
|
|
// not use this when repeating tasks such as animated web pages
|
|
// are present.
|
|
// WARNING #2: This may return too early! For example, if used to run until an
|
|
// incoming event has occurred but that event depends on a task in
|
|
// a different queue -- e.g. a standalone base::Thread or a system
|
|
// event.
|
|
//
|
|
// As such, prefer RunLoop::Run() with an explicit RunLoop::QuitClosure() when
|
|
// possible.
|
|
void RunUntilIdle();
|
|
|
|
// Only valid for instances using TimeSource::MOCK_TIME. Fast-forwards
|
|
// virtual time by |delta|, causing all tasks on the main thread and thread
|
|
// pool with a remaining delay less than or equal to |delta| to be executed in
|
|
// their natural order before this returns. |delta| must be non-negative. Upon
|
|
// returning from this method, NowTicks() will be >= the initial |NowTicks() +
|
|
// delta|. It is guaranteed to be == iff tasks executed in this
|
|
// FastForwardBy() didn't result in nested calls to time-advancing-methods.
|
|
void FastForwardBy(TimeDelta delta);
|
|
|
|
// Only valid for instances using TimeSource::MOCK_TIME.
|
|
// Short for FastForwardBy(TimeDelta::Max()).
|
|
//
|
|
// WARNING: This has the same caveat as RunUntilIdle() and is even more likely
|
|
// to spin forever (any RepeatingTimer will cause this).
|
|
void FastForwardUntilNoTasksRemain();
|
|
|
|
// Only valid for instances using TimeSource::MOCK_TIME. Advances virtual time
|
|
// by |delta|. Unlike FastForwardBy, this does not run tasks. Prefer
|
|
// FastForwardBy() when possible but this can be useful when testing blocked
|
|
// pending tasks where being idle (required to fast-forward) is not possible.
|
|
//
|
|
// Delayed tasks that are ripe as a result of this will be scheduled.
|
|
// RunUntilIdle() can be used after this call to ensure those tasks have run.
|
|
// Note: AdvanceClock(delta) + RunUntilIdle() is slightly different from
|
|
// FastForwardBy(delta) in that time passes instantly before running any task
|
|
// (whereas FastForwardBy() will advance the clock in the smallest increments
|
|
// possible at a time). Hence FastForwardBy() is more realistic but
|
|
// AdvanceClock() can be useful when testing edge case scenarios that
|
|
// specifically handle more time than expected to have passed.
|
|
void AdvanceClock(TimeDelta delta);
|
|
|
|
bool UsesMockTime() const { return !!mock_clock_; }
|
|
|
|
// Only valid for instances using TimeSource::MOCK_TIME. Returns a
|
|
// TickClock whose time is updated by FastForward(By|UntilNoTasksRemain).
|
|
const TickClock* GetMockTickClock() const;
|
|
|
|
// Only valid for instances using TimeSource::MOCK_TIME. Returns a
|
|
// Clock whose time is updated by FastForward(By|UntilNoTasksRemain). The
|
|
// initial value is implementation defined and should be queried by tests that
|
|
// depend on it.
|
|
// TickClock should be used instead of Clock to measure elapsed time in a
|
|
// process. See time.h.
|
|
const Clock* GetMockClock() const;
|
|
|
|
// Only valid for instances using TimeSource::MOCK_TIME. Returns the current
|
|
// virtual tick time (based on a realistic Now(), sampled when this
|
|
// TaskEnvironment was created, and manually advanced from that point on).
|
|
// This is always equivalent to base::TimeTicks::Now() under
|
|
// TimeSource::MOCK_TIME.
|
|
base::TimeTicks NowTicks() const;
|
|
|
|
// Only valid for instances using TimeSource::MOCK_TIME. Returns the number of
|
|
// pending tasks (delayed and non-delayed) of the main thread's TaskRunner.
|
|
// When debugging, you can use DescribeCurrentTasks() to see what those are.
|
|
size_t GetPendingMainThreadTaskCount() const;
|
|
|
|
// Only valid for instances using TimeSource::MOCK_TIME.
|
|
// Returns the delay until the next pending task of the main thread's
|
|
// TaskRunner if there is one, otherwise it returns TimeDelta::Max().
|
|
TimeDelta NextMainThreadPendingTaskDelay() const;
|
|
|
|
// Only valid for instances using TimeSource::MOCK_TIME.
|
|
// Returns true iff the next task is delayed. Returns false if the next task
|
|
// is immediate or if there is no next task.
|
|
bool NextTaskIsDelayed() const;
|
|
|
|
// For debugging purposes: Dumps information about pending tasks on the main
|
|
// thread, and currently running tasks on the thread pool.
|
|
void DescribeCurrentTasks() const;
|
|
|
|
// Detach ThreadCheckers (will rebind on next usage), useful for the odd test
|
|
// suite which doesn't run on the main thread but still has exclusive access
|
|
// to driving this TaskEnvironment (e.g. WaylandClientTestSuiteServer).
|
|
void DetachFromThread();
|
|
|
|
class TestTaskTracker;
|
|
// Callers outside of TaskEnvironment may not use the returned pointer. They
|
|
// should just use base::ThreadPoolInstance::Get().
|
|
static TestTaskTracker* CreateThreadPool();
|
|
|
|
class DestructionObserver : public CheckedObserver {
|
|
public:
|
|
DestructionObserver() = default;
|
|
~DestructionObserver() override = default;
|
|
|
|
DestructionObserver(const DestructionObserver&) = delete;
|
|
DestructionObserver& operator=(const DestructionObserver&) = delete;
|
|
|
|
virtual void WillDestroyCurrentTaskEnvironment() = 0;
|
|
};
|
|
|
|
// Adds/removes a DestructionObserver to any TaskEnvironment. Observers are
|
|
// notified when any TaskEnvironment goes out of scope (other than with a move
|
|
// operation). Must be called on the main thread.
|
|
static void AddDestructionObserver(DestructionObserver* observer);
|
|
static void RemoveDestructionObserver(DestructionObserver* observer);
|
|
|
|
// Instantiating a ParallelExecutionFence waits for all currently running
|
|
// ThreadPool tasks before the constructor returns and from then on prevents
|
|
// additional tasks from running during its lifetime.
|
|
//
|
|
// Must be instantiated from the test main thread.
|
|
class ParallelExecutionFence {
|
|
public:
|
|
// Instantiates a ParallelExecutionFence, crashes with an optional
|
|
// |error_message| if not invoked from test main thread.
|
|
explicit ParallelExecutionFence(const char* error_message = "");
|
|
~ParallelExecutionFence();
|
|
|
|
ParallelExecutionFence(const ParallelExecutionFence&) = delete;
|
|
ParallelExecutionFence& operator=(const ParallelExecutionFence& other) =
|
|
delete;
|
|
|
|
private:
|
|
bool previously_allowed_to_run_ = false;
|
|
};
|
|
|
|
// The number of foreground workers in the ThreadPool managed by a
|
|
// TaskEnvironment instance. This can be used to determine the maximum
|
|
// parallelism in tests that require each parallel task it spawns to be
|
|
// running at once. Having multiple threads prevents deadlocks should some
|
|
// blocking APIs not use ScopedBlockingCall. It also allows enough concurrency
|
|
// to allow TSAN to spot data races.
|
|
static constexpr int kNumForegroundThreadPoolThreads = 4;
|
|
|
|
protected:
|
|
template <typename... TaskEnvironmentTraits,
|
|
class CheckArgumentsAreValid = std::enable_if_t<
|
|
trait_helpers::AreValidTraits<ValidTraits,
|
|
TaskEnvironmentTraits...>::value>>
|
|
NOINLINE static TaskEnvironment CreateTaskEnvironmentWithPriorities(
|
|
sequence_manager::SequenceManager::PrioritySettings priority_settings,
|
|
TaskEnvironmentTraits... traits) {
|
|
return TaskEnvironment(std::move(priority_settings), traits...);
|
|
}
|
|
|
|
// Constructor accepts zero or more traits which customize the testing
|
|
// environment.
|
|
template <typename... TaskEnvironmentTraits,
|
|
class CheckArgumentsAreValid = std::enable_if_t<
|
|
trait_helpers::AreValidTraits<ValidTraits,
|
|
TaskEnvironmentTraits...>::value>>
|
|
NOINLINE explicit TaskEnvironment(
|
|
sequence_manager::SequenceManager::PrioritySettings priority_settings,
|
|
TaskEnvironmentTraits... traits)
|
|
: TaskEnvironment(
|
|
std::move(priority_settings),
|
|
trait_helpers::GetEnum<TimeSource, TimeSource::DEFAULT>(traits...),
|
|
trait_helpers::GetEnum<MainThreadType, MainThreadType::DEFAULT>(
|
|
traits...),
|
|
trait_helpers::GetEnum<ThreadPoolExecutionMode,
|
|
ThreadPoolExecutionMode::DEFAULT>(traits...),
|
|
trait_helpers::GetEnum<ThreadingMode, ThreadingMode::DEFAULT>(
|
|
traits...),
|
|
trait_helpers::GetEnum<ThreadPoolCOMEnvironment,
|
|
ThreadPoolCOMEnvironment::DEFAULT>(
|
|
traits...),
|
|
trait_helpers::HasTrait<SubclassCreatesDefaultTaskRunner,
|
|
TaskEnvironmentTraits...>(),
|
|
trait_helpers::NotATraitTag()) {}
|
|
|
|
TaskEnvironment(TaskEnvironment&& other);
|
|
|
|
constexpr MainThreadType main_thread_type() const {
|
|
return main_thread_type_;
|
|
}
|
|
|
|
constexpr ThreadPoolExecutionMode thread_pool_execution_mode() const {
|
|
return thread_pool_execution_mode_;
|
|
}
|
|
|
|
// Returns the MockTimeDomain driving this TaskEnvironment if this instance is
|
|
// using TimeSource::MOCK_TIME, nullptr otherwise.
|
|
sequence_manager::TimeDomain* GetMockTimeDomain() const;
|
|
|
|
sequence_manager::SequenceManager* sequence_manager() const;
|
|
|
|
void DeferredInitFromSubclass(
|
|
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
|
|
|
|
// Derived classes may need to control when the task environment goes away
|
|
// (e.g. ~FooTaskEnvironment() may want to effectively trigger
|
|
// ~TaskEnvironment() before its members are destroyed).
|
|
void DestroyTaskEnvironment();
|
|
|
|
private:
|
|
class MockTimeDomain;
|
|
|
|
void InitializeThreadPool();
|
|
void ShutdownAndJoinThreadPool();
|
|
void DestroyThreadPool();
|
|
|
|
void CompleteInitialization();
|
|
|
|
// The template constructor has to be in the header but it delegates to this
|
|
// constructor to initialize all other members out-of-line.
|
|
TaskEnvironment(
|
|
sequence_manager::SequenceManager::PrioritySettings priority_settings,
|
|
TimeSource time_source,
|
|
MainThreadType main_thread_type,
|
|
ThreadPoolExecutionMode thread_pool_execution_mode,
|
|
ThreadingMode threading_mode,
|
|
ThreadPoolCOMEnvironment thread_pool_com_environment,
|
|
bool subclass_creates_default_taskrunner,
|
|
trait_helpers::NotATraitTag tag);
|
|
|
|
const MainThreadType main_thread_type_;
|
|
const ThreadPoolExecutionMode thread_pool_execution_mode_;
|
|
const ThreadingMode threading_mode_;
|
|
const ThreadPoolCOMEnvironment thread_pool_com_environment_;
|
|
const bool subclass_creates_default_taskrunner_;
|
|
|
|
std::unique_ptr<sequence_manager::SequenceManager> sequence_manager_;
|
|
|
|
// Manages the clock under TimeSource::MOCK_TIME modes. Null in
|
|
// TimeSource::SYSTEM_TIME mode.
|
|
std::unique_ptr<MockTimeDomain> mock_time_domain_;
|
|
|
|
// Overrides Time/TimeTicks::Now() under TimeSource::MOCK_TIME mode.
|
|
// Null in other modes.
|
|
std::unique_ptr<subtle::ScopedTimeClockOverrides> time_overrides_;
|
|
|
|
scoped_refptr<sequence_manager::TaskQueue> task_queue_;
|
|
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
|
|
|
// Only set for instances using TimeSource::MOCK_TIME.
|
|
std::unique_ptr<Clock> mock_clock_;
|
|
|
|
#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
|
|
// Enables the FileDescriptorWatcher API iff running a MainThreadType::IO.
|
|
std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher_;
|
|
#endif
|
|
|
|
// Owned by the ThreadPoolInstance.
|
|
// This field is not a raw_ptr<> because it was filtered by the rewriter for:
|
|
// #union
|
|
RAW_PTR_EXCLUSION TestTaskTracker* task_tracker_ = nullptr;
|
|
|
|
// Ensures destruction of lazy TaskRunners when this is destroyed.
|
|
std::unique_ptr<base::internal::ScopedLazyTaskRunnerListForTesting>
|
|
scoped_lazy_task_runner_list_for_testing_;
|
|
|
|
// Sets RunLoop::Run() to LOG(FATAL) if not Quit() in a timely manner.
|
|
std::unique_ptr<ScopedRunLoopTimeout> run_loop_timeout_;
|
|
|
|
std::unique_ptr<bool> owns_instance_ = std::make_unique<bool>(true);
|
|
|
|
std::unique_ptr<RunLoop> run_until_quit_loop_;
|
|
|
|
// Used to verify thread-affinity of operations that must occur on the main
|
|
// thread. This is the case for anything that modifies or drives the
|
|
// |sequence_manager_|.
|
|
THREAD_CHECKER(main_thread_checker_);
|
|
};
|
|
|
|
// SingleThreadTaskEnvironment takes the same traits as TaskEnvironment and is
|
|
// used the exact same way. It's a short-form for
|
|
// TaskEnvironment{TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY, ...};
|
|
class SingleThreadTaskEnvironment : public TaskEnvironment {
|
|
public:
|
|
template <class... ArgTypes>
|
|
SingleThreadTaskEnvironment(ArgTypes... args)
|
|
: TaskEnvironment(ThreadingMode::MAIN_THREAD_ONLY, args...) {}
|
|
};
|
|
|
|
} // namespace test
|
|
} // namespace base
|
|
|
|
#endif // BASE_TEST_TASK_ENVIRONMENT_H_
|