blob: d3646316d842323b4c01d54150714879165dd081 [file] [log] [blame]
[email protected]ec04d3f2013-06-06 21:31:391// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Francois Doray9f68b1a2017-12-25 13:41:585// TestBrowserThreadBundle is a convenience class which allows usage of these
6// APIs within its scope:
7// - Same APIs as base::test::ScopedTaskEnvironment.
8// - content::BrowserThread.
[email protected]ec04d3f2013-06-06 21:31:399//
Francois Doray9f68b1a2017-12-25 13:41:5810// Only tests that need the BrowserThread API should instantiate a
11// TestBrowserThreadBundle. Use base::test::ScopedTaskEnvironment otherwise.
12//
13// By default, BrowserThread::UI/IO are backed by a single shared MessageLoop on
14// the main thread. If a test truly needs BrowserThread::IO tasks to run on a
15// separate thread, it can pass the REAL_IO_THREAD option to the constructor.
Gabriel Charette52fa3ae2019-04-15 21:44:3716// ThreadPool tasks always run on dedicated threads.
[email protected]ec04d3f2013-06-06 21:31:3917//
fdoray575c4b22017-04-05 19:25:5118// To synchronously run tasks from the shared MessageLoop:
19//
20// ... until there are no undelayed tasks in the shared MessageLoop:
21// base::RunLoop::RunUntilIdle();
22//
23// ... until there are no undelayed tasks in the shared MessageLoop, in
Gabriel Charette52fa3ae2019-04-15 21:44:3724// ThreadPool (excluding tasks not posted from the shared MessageLoop's
25// thread or ThreadPool):
Gabriel Charette01507a22017-09-27 21:30:0826// content::RunAllTasksUntilIdle();
fdoray575c4b22017-04-05 19:25:5127//
28// ... until a condition is met:
29// base::RunLoop run_loop;
30// // Runs until a task running in the shared MessageLoop calls
31// // run_loop.Quit() or runs run_loop.QuitClosure() (&run_loop or
32// // run_loop.QuitClosure() must be kept somewhere accessible by that task).
33// run_loop.Run();
34//
Gabriel Charette52fa3ae2019-04-15 21:44:3735// To wait until there are no pending undelayed tasks in ThreadPool, without
Gabriel Charettea1e0a372017-09-14 18:48:2136// running tasks from the shared MessageLoop:
Gabriel Charette43fd3702019-05-29 16:36:5137// base::ThreadPoolInstance::Get()->FlushForTesting();
fdoray575c4b22017-04-05 19:25:5138//
Francois Doray9f68b1a2017-12-25 13:41:5839// The destructor of TestBrowserThreadBundle runs remaining UI/IO tasks and
Gabriel Charette52fa3ae2019-04-15 21:44:3740// remaining thread pool tasks.
[email protected]ec04d3f2013-06-06 21:31:3941//
Francois Doray9f68b1a2017-12-25 13:41:5842// If a test needs to pump IO messages on the main thread, it should use the
fdoray575c4b22017-04-05 19:25:5143// IO_MAINLOOP option. Most of the time, IO_MAINLOOP avoids needing to use a
fdorayad58f832016-12-19 18:06:4644// REAL_IO_THREAD.
aberent8f1ce402016-01-13 12:01:3845//
46// For some tests it is important to emulate real browser startup. During real
Gabriel Charette52fa3ae2019-04-15 21:44:3747// browser startup, the main MessageLoop and the ThreadPool are created
Francois Doray69f889f2017-08-02 15:42:1248// before browser threads. Passing DONT_CREATE_BROWSER_THREADS to constructor
49// will delay creating browser threads until the test explicitly calls
50// CreateBrowserThreads().
aberent8f1ce402016-01-13 12:01:3851//
Francois Doray69f889f2017-08-02 15:42:1252// DONT_CREATE_BROWSER_THREADS should only be used when the options specify at
53// least one real thread other than the main thread.
gab1f58e952017-05-04 23:28:5154//
fdoray8c580522017-05-08 16:59:4155// TestBrowserThreadBundle may be instantiated in a scope where there is already
56// a base::test::ScopedTaskEnvironment. In that case, it will use the
Gabriel Charette52fa3ae2019-04-15 21:44:3757// MessageLoop and the ThreadPool provided by this
fdoray8c580522017-05-08 16:59:4158// base::test::ScopedTaskEnvironment instead of creating its own. The ability to
59// have a base::test::ScopedTaskEnvironment and a TestBrowserThreadBundle in the
60// same scope is useful when a fixture that inherits from a fixture that
61// provides a base::test::ScopedTaskEnvironment needs to add support for browser
62// threads.
63//
gab1f58e952017-05-04 23:28:5164// Basic usage:
65//
66// class MyTestFixture : public testing::Test {
67// public:
68// (...)
69//
70// protected:
71// // Must be the first member (or at least before any member that cares
72// // about tasks) to be initialized first and destroyed last. protected
73// // instead of private visibility will allow controlling the task
74// // environment (e.g. clock) once such features are added (see
75// // base::test::ScopedTaskEnvironment for details), until then it at least
76// // doesn't hurt :).
77// content::TestBrowserThreadBundle test_browser_thread_bundle_;
78//
79// // Other members go here (or further below in private section.)
80// };
[email protected]ec04d3f2013-06-06 21:31:3981
sdefresne634eec92014-12-18 13:02:5482#ifndef CONTENT_PUBLIC_TEST_TEST_BROWSER_THREAD_BUNDLE_H_
83#define CONTENT_PUBLIC_TEST_TEST_BROWSER_THREAD_BUNDLE_H_
[email protected]ec04d3f2013-06-06 21:31:3984
dcheng6003e0b2016-04-09 18:42:3485#include <memory>
86
Alex Clarkef0527a9b2019-01-23 10:43:2587#include "base/compiler_specific.h"
avi652869c2015-12-25 01:48:4588#include "base/macros.h"
Alex Clarke1052bb02018-12-14 09:44:1689#include "base/test/scoped_task_environment.h"
Robert Liao0bde45e2017-06-22 21:16:0390#include "build/build_config.h"
[email protected]ec04d3f2013-06-06 21:31:3991
92namespace base {
Robert Liao0bde45e2017-06-22 21:16:0393#if defined(OS_WIN)
94namespace win {
95class ScopedCOMInitializer;
96} // namespace win
97#endif
[email protected]ec04d3f2013-06-06 21:31:3998} // namespace base
99
100namespace content {
101
102class TestBrowserThread;
103
Alex Clarkef0527a9b2019-01-23 10:43:25104// Note: to drive these threads (e.g. run all tasks until idle or FastForwardBy)
105// see base::test::ScopedTaskEnvironment which this is a subclass of.
Alex Clarke1052bb02018-12-14 09:44:16106class TestBrowserThreadBundle : public base::test::ScopedTaskEnvironment {
[email protected]ec04d3f2013-06-06 21:31:39107 public:
Alex Clarkef0527a9b2019-01-23 10:43:25108 enum Options { REAL_IO_THREAD };
109
110 // The main thread will use a MessageLoopForIO (and support the
111 // base::FileDescriptorWatcher API on POSIX).
112 // TODO(alexclarke): Replace IO_MAINLOOP usage by MainThreadType::IO and
113 // remove this.
114 static constexpr MainThreadType IO_MAINLOOP = MainThreadType::IO;
115
116 struct ValidTraits {
117 ValidTraits(ScopedTaskEnvironment::ValidTrait);
118 ValidTraits(Options);
[email protected]ec04d3f2013-06-06 21:31:39119 };
120
Alex Clarkef0527a9b2019-01-23 10:43:25121 // Constructor which accepts zero or more traits to configure the
122 // ScopedTaskEnvironment and optionally request a real IO thread. Unlike
123 // ScopedTaskEnvironment the default MainThreadType for
124 // TestBrowserThreadBundle is MainThreadType::UI.
125 template <
126 class... ArgTypes,
127 class CheckArgumentsAreValid = std::enable_if_t<
128 base::trait_helpers::AreValidTraits<ValidTraits, ArgTypes...>::value>>
129 NOINLINE TestBrowserThreadBundle(const ArgTypes... args)
130 : TestBrowserThreadBundle(
131 base::test::ScopedTaskEnvironment(
Alex Clarke831ed1e62019-02-18 21:10:08132 SubclassCreatesDefaultTaskRunner{},
Alex Clarkef0527a9b2019-01-23 10:43:25133 base::trait_helpers::GetEnum<MainThreadType,
134 MainThreadType::UI>(args...),
135 base::trait_helpers::Exclude<MainThreadType, Options>::Filter(
136 args)...),
137 UseRealIOThread(
138 base::trait_helpers::GetOptionalEnum<Options>(args...))) {}
Alex Clarke1052bb02018-12-14 09:44:16139
Gabriel Charette52fa3ae2019-04-15 21:44:37140 // Runs all tasks posted to ThreadPool and main thread until idle.
Gabriel Charette147335ea2018-03-22 15:59:19141 // Note: At the moment, this will not process BrowserThread::IO if this
142 // TestBrowserThreadBundle is using a REAL_IO_THREAD.
Gabriel Charette52fa3ae2019-04-15 21:44:37143 // TODO(robliao): fix this by making ThreadPool aware of all MessageLoops.
Gabriel Charette147335ea2018-03-22 15:59:19144 //
145 // Note that this is not the cleanest way to run until idle as it will return
146 // early if it depends on an async condition that isn't guaranteed to have
147 // occurred yet. The best way to run until a condition is met is with RunLoop:
148 //
149 // void KickoffAsyncFoo(base::OnceClosure on_done);
150 //
151 // base::RunLoop run_loop;
152 // KickoffAsyncFoo(run_loop.QuitClosure());
153 // run_loop.Run();
154 //
Gabriel Charetted4c59d02018-03-21 20:12:26155
Gabriel Charette147335ea2018-03-22 15:59:19156 // Flush the IO thread. Replacement for RunLoop::RunUntilIdle() for tests that
157 // have a REAL_IO_THREAD. As with RunUntilIdle() above, prefer using
158 // RunLoop+QuitClosure() to await an async condition.
159 void RunIOThreadUntilIdle();
160
Alex Clarke1052bb02018-12-14 09:44:16161 ~TestBrowserThreadBundle() override;
[email protected]ec04d3f2013-06-06 21:31:39162
163 private:
Alex Clarkef0527a9b2019-01-23 10:43:25164 // The template constructor has to be in the header but it delegates to this
165 // constructor to initialize all other members out-of-line.
166 TestBrowserThreadBundle(
167 base::test::ScopedTaskEnvironment&& scoped_task_environment,
168 bool real_io_thread);
169
aberent8f1ce402016-01-13 12:01:38170 void Init();
[email protected]ec04d3f2013-06-06 21:31:39171
Alex Clarkef0527a9b2019-01-23 10:43:25172 static constexpr bool UseRealIOThread(base::Optional<Options> options) {
173 if (!options)
174 return false;
175 return *options == Options::REAL_IO_THREAD;
176 }
177
178 constexpr bool HasIOMainLoop() const {
179 return main_thread_type() == MainThreadType::IO ||
180 main_thread_type() == MainThreadType::IO_MOCK_TIME;
181 }
182
183 const bool real_io_thread_;
dcheng6003e0b2016-04-09 18:42:34184 std::unique_ptr<TestBrowserThread> ui_thread_;
dcheng6003e0b2016-04-09 18:42:34185 std::unique_ptr<TestBrowserThread> io_thread_;
[email protected]ec04d3f2013-06-06 21:31:39186
Robert Liao0bde45e2017-06-22 21:16:03187#if defined(OS_WIN)
188 std::unique_ptr<base::win::ScopedCOMInitializer> com_initializer_;
189#endif
190
[email protected]ec04d3f2013-06-06 21:31:39191 DISALLOW_COPY_AND_ASSIGN(TestBrowserThreadBundle);
192};
193
194} // namespace content
195
sdefresne634eec92014-12-18 13:02:54196#endif // CONTENT_PUBLIC_TEST_TEST_BROWSER_THREAD_BUNDLE_H_