blob: 856381e9a4fb570c8645c7b55f543c4445d5777c [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2016 The Chromium Authors
fdoraya4f28ec2016-06-10 00:08:582// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/run_loop.h"
6
jdoerrie9d7236f62019-03-05 13:00:237#include <functional>
David Bienvenu5f4d4f02020-09-27 16:55:038#include <memory>
Gabriel Charettee2b632b2017-08-02 03:52:169#include <utility>
10
Brett Wilsona62d9c02017-09-20 20:53:2011#include "base/containers/queue.h"
Avi Drissman63e1f992023-01-13 18:54:4312#include "base/functional/bind.h"
13#include "base/functional/callback_helpers.h"
fdoraya4f28ec2016-06-10 00:08:5814#include "base/location.h"
Gabriel Charettee2b632b2017-08-02 03:52:1615#include "base/memory/ptr_util.h"
16#include "base/memory/ref_counted.h"
Gabriel Charettee2b632b2017-08-02 03:52:1617#include "base/synchronization/lock.h"
gabcf5e4ce2017-05-19 22:56:5718#include "base/synchronization/waitable_event.h"
Sean Maher7d0e8052022-12-09 01:46:3219#include "base/task/sequenced_task_runner.h"
Patrick Monette643cdf62021-10-15 19:13:4220#include "base/task/single_thread_task_runner.h"
Guido Urdanetaef4e91942020-11-09 15:06:2421#include "base/test/bind.h"
Gabriel Charettee2b632b2017-08-02 03:52:1622#include "base/test/gtest_util.h"
Wez9d5dd282020-02-10 17:21:2223#include "base/test/scoped_run_loop_timeout.h"
Gabriel Charettec7108742019-08-23 03:31:4024#include "base/test/task_environment.h"
Gabriel Charette3ff403e2017-08-07 04:22:4825#include "base/test/test_timeouts.h"
Gabriel Charettee2b632b2017-08-02 03:52:1626#include "base/threading/platform_thread.h"
27#include "base/threading/thread.h"
28#include "base/threading/thread_checker_impl.h"
Gabriel Charettee2b632b2017-08-02 03:52:1629#include "build/build_config.h"
gab7af9dc02017-05-05 13:38:5430#include "testing/gmock/include/gmock/gmock.h"
fdoraya4f28ec2016-06-10 00:08:5831#include "testing/gtest/include/gtest/gtest.h"
32
33namespace base {
34
35namespace {
36
37void QuitWhenIdleTask(RunLoop* run_loop, int* counter) {
38 run_loop->QuitWhenIdle();
39 ++(*counter);
40}
41
fdoraya4f28ec2016-06-10 00:08:5842void RunNestedLoopTask(int* counter) {
Gabriel Charette3ff403e2017-08-07 04:22:4843 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
fdoraya4f28ec2016-06-10 00:08:5844
45 // This task should quit |nested_run_loop| but not the main RunLoop.
Sean Maher7d0e8052022-12-09 01:46:3246 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
tzik92b7a422017-04-11 15:00:4447 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&nested_run_loop),
48 Unretained(counter)));
fdoraya4f28ec2016-06-10 00:08:5849
Sean Maher7d0e8052022-12-09 01:46:3250 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
Peter Kasting53fd6ee2021-10-05 20:40:4851 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), Days(1));
fdoraya4f28ec2016-06-10 00:08:5852
fdoraya4f28ec2016-06-10 00:08:5853 nested_run_loop.Run();
54
55 ++(*counter);
56}
57
Gabriel Charettee2b632b2017-08-02 03:52:1658// A simple SingleThreadTaskRunner that just queues undelayed tasks (and ignores
59// delayed tasks). Tasks can then be processed one by one by ProcessTask() which
60// will return true if it processed a task and false otherwise.
61class SimpleSingleThreadTaskRunner : public SingleThreadTaskRunner {
62 public:
63 SimpleSingleThreadTaskRunner() = default;
David Bienvenu5f4d4f02020-09-27 16:55:0364 SimpleSingleThreadTaskRunner(const SimpleSingleThreadTaskRunner&) = delete;
65 SimpleSingleThreadTaskRunner& operator=(const SimpleSingleThreadTaskRunner&) =
66 delete;
fdoraya4f28ec2016-06-10 00:08:5867
Brett Wilson8e88b312017-09-12 05:22:1668 bool PostDelayedTask(const Location& from_here,
Gabriel Charettee2b632b2017-08-02 03:52:1669 OnceClosure task,
70 base::TimeDelta delay) override {
Peter Kasting134ef9af2024-12-28 02:30:0971 if (delay.is_positive()) {
Gabriel Charettee2b632b2017-08-02 03:52:1672 return false;
Peter Kasting134ef9af2024-12-28 02:30:0973 }
Gabriel Charettee2b632b2017-08-02 03:52:1674 AutoLock auto_lock(tasks_lock_);
75 pending_tasks_.push(std::move(task));
76 return true;
77 }
78
Brett Wilson8e88b312017-09-12 05:22:1679 bool PostNonNestableDelayedTask(const Location& from_here,
Gabriel Charettee2b632b2017-08-02 03:52:1680 OnceClosure task,
81 base::TimeDelta delay) override {
82 return PostDelayedTask(from_here, std::move(task), delay);
83 }
84
85 bool RunsTasksInCurrentSequence() const override {
86 return origin_thread_checker_.CalledOnValidThread();
87 }
88
Gabriel Charette1ef212b2017-12-03 12:47:2189 bool ProcessSingleTask() {
Gabriel Charettee2b632b2017-08-02 03:52:1690 OnceClosure task;
91 {
92 AutoLock auto_lock(tasks_lock_);
Peter Kasting134ef9af2024-12-28 02:30:0993 if (pending_tasks_.empty()) {
Gabriel Charettee2b632b2017-08-02 03:52:1694 return false;
Peter Kasting134ef9af2024-12-28 02:30:0995 }
Gabriel Charettee2b632b2017-08-02 03:52:1696 task = std::move(pending_tasks_.front());
97 pending_tasks_.pop();
98 }
99 // It's important to Run() after pop() and outside the lock as |task| may
Gabriel Charette1ef212b2017-12-03 12:47:21100 // run a nested loop which will re-enter ProcessSingleTask().
Gabriel Charettee2b632b2017-08-02 03:52:16101 std::move(task).Run();
102 return true;
103 }
104
105 private:
106 ~SimpleSingleThreadTaskRunner() override = default;
107
108 Lock tasks_lock_;
Brett Wilsona62d9c02017-09-20 20:53:20109 base::queue<OnceClosure> pending_tasks_;
Gabriel Charettee2b632b2017-08-02 03:52:16110
111 // RunLoop relies on RunsTasksInCurrentSequence() signal. Use a
112 // ThreadCheckerImpl to be able to reliably provide that signal even in
113 // non-dcheck builds.
114 ThreadCheckerImpl origin_thread_checker_;
Gabriel Charettee2b632b2017-08-02 03:52:16115};
116
Gabriel Charette1ef212b2017-12-03 12:47:21117// The basis of all TestDelegates, allows safely injecting a OnceClosure to be
118// run in the next idle phase of this delegate's Run() implementation. This can
119// be used to have code run on a thread that is otherwise livelocked in an idle
120// phase (sometimes a simple PostTask() won't do it -- e.g. when processing
121// application tasks is disallowed).
122class InjectableTestDelegate : public RunLoop::Delegate {
Gabriel Charettee2b632b2017-08-02 03:52:16123 public:
Gabriel Charette1ef212b2017-12-03 12:47:21124 void InjectClosureOnDelegate(OnceClosure closure) {
125 AutoLock auto_lock(closure_lock_);
126 closure_ = std::move(closure);
127 }
Gabriel Charettee2b632b2017-08-02 03:52:16128
Gabriel Charette1ef212b2017-12-03 12:47:21129 bool RunInjectedClosure() {
130 AutoLock auto_lock(closure_lock_);
Peter Kasting134ef9af2024-12-28 02:30:09131 if (closure_.is_null()) {
Gabriel Charette1ef212b2017-12-03 12:47:21132 return false;
Peter Kasting134ef9af2024-12-28 02:30:09133 }
Gabriel Charette1ef212b2017-12-03 12:47:21134 std::move(closure_).Run();
135 return true;
136 }
137
138 private:
139 Lock closure_lock_;
140 OnceClosure closure_;
141};
142
143// A simple test RunLoop::Delegate to exercise Runloop logic independent of any
144// other base constructs. BindToCurrentThread() must be called before this
145// TestBoundDelegate is operational.
146class TestBoundDelegate final : public InjectableTestDelegate {
147 public:
148 TestBoundDelegate() = default;
149
150 // Makes this TestBoundDelegate become the RunLoop::Delegate and
Sean Maher70f2942932023-01-04 22:15:06151 // SingleThreadTaskRunner::CurrentDefaultHandle for this thread.
Gabriel Charettee2b632b2017-08-02 03:52:16152 void BindToCurrentThread() {
153 thread_task_runner_handle_ =
Sean Maher9d43acc2022-12-01 17:42:01154 std::make_unique<SingleThreadTaskRunner::CurrentDefaultHandle>(
155 simple_task_runner_);
Gabriel Charettea3ec9612017-12-14 17:22:40156 RunLoop::RegisterDelegateForCurrentThread(this);
Gabriel Charettee2b632b2017-08-02 03:52:16157 }
158
159 private:
Alex Clarke9752bbf2019-04-01 10:41:20160 void Run(bool application_tasks_allowed, TimeDelta timeout) override {
Gabriel Charette3ff403e2017-08-07 04:22:48161 if (nested_run_allowing_tasks_incoming_) {
Gabriel Charette1ef212b2017-12-03 12:47:21162 EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
Gabriel Charetteb030a4a2017-10-26 01:04:40163 EXPECT_TRUE(application_tasks_allowed);
Gabriel Charette1ef212b2017-12-03 12:47:21164 } else if (RunLoop::IsNestedOnCurrentThread()) {
Gabriel Charetteb030a4a2017-10-26 01:04:40165 EXPECT_FALSE(application_tasks_allowed);
Gabriel Charette3ff403e2017-08-07 04:22:48166 }
167 nested_run_allowing_tasks_incoming_ = false;
168
Gabriel Charettee2b632b2017-08-02 03:52:16169 while (!should_quit_) {
Peter Kasting134ef9af2024-12-28 02:30:09170 if (application_tasks_allowed &&
171 simple_task_runner_->ProcessSingleTask()) {
Gabriel Charettee2b632b2017-08-02 03:52:16172 continue;
Peter Kasting134ef9af2024-12-28 02:30:09173 }
Gabriel Charettee2b632b2017-08-02 03:52:16174
Peter Kasting134ef9af2024-12-28 02:30:09175 if (ShouldQuitWhenIdle()) {
Gabriel Charettee2b632b2017-08-02 03:52:16176 break;
Peter Kasting134ef9af2024-12-28 02:30:09177 }
Gabriel Charettee2b632b2017-08-02 03:52:16178
Peter Kasting134ef9af2024-12-28 02:30:09179 if (RunInjectedClosure()) {
Gabriel Charette1ef212b2017-12-03 12:47:21180 continue;
Peter Kasting134ef9af2024-12-28 02:30:09181 }
Gabriel Charette3ff403e2017-08-07 04:22:48182
Gabriel Charettee2b632b2017-08-02 03:52:16183 PlatformThread::YieldCurrentThread();
184 }
185 should_quit_ = false;
186 }
187
188 void Quit() override { should_quit_ = true; }
189
Gabriel Charette3ff403e2017-08-07 04:22:48190 void EnsureWorkScheduled() override {
191 nested_run_allowing_tasks_incoming_ = true;
192 }
193
194 // True if the next invocation of Run() is expected to be from a
195 // kNestableTasksAllowed RunLoop.
196 bool nested_run_allowing_tasks_incoming_ = false;
197
Gabriel Charettee2b632b2017-08-02 03:52:16198 scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
199 MakeRefCounted<SimpleSingleThreadTaskRunner>();
Gabriel Charette1ef212b2017-12-03 12:47:21200
Sean Maher9d43acc2022-12-01 17:42:01201 std::unique_ptr<SingleThreadTaskRunner::CurrentDefaultHandle>
202 thread_task_runner_handle_;
Gabriel Charettee2b632b2017-08-02 03:52:16203
204 bool should_quit_ = false;
Gabriel Charette1ef212b2017-12-03 12:47:21205};
206
Gabriel Charettee2b632b2017-08-02 03:52:16207enum class RunLoopTestType {
Gabriel Charette694c3c332019-08-19 14:53:05208 // Runs all RunLoopTests under a TaskEnvironment to make sure real world
Gabriel Charettee2b632b2017-08-02 03:52:16209 // scenarios work.
210 kRealEnvironment,
211
212 // Runs all RunLoopTests under a test RunLoop::Delegate to make sure the
213 // delegate interface fully works standalone.
214 kTestDelegate,
215};
216
217// The task environment for the RunLoopTest of a given type. A separate class
218// so it can be instantiated on the stack in the RunLoopTest fixture.
219class RunLoopTestEnvironment {
220 public:
David Bienvenu5f4d4f02020-09-27 16:55:03221 explicit RunLoopTestEnvironment(RunLoopTestType type) {
Gabriel Charettee2b632b2017-08-02 03:52:16222 switch (type) {
Gabriel Charette1ef212b2017-12-03 12:47:21223 case RunLoopTestType::kRealEnvironment: {
Gabriel Charette694c3c332019-08-19 14:53:05224 task_environment_ = std::make_unique<test::TaskEnvironment>();
Gabriel Charettee2b632b2017-08-02 03:52:16225 break;
Gabriel Charette1ef212b2017-12-03 12:47:21226 }
227 case RunLoopTestType::kTestDelegate: {
228 auto test_delegate = std::make_unique<TestBoundDelegate>();
229 test_delegate->BindToCurrentThread();
230 test_delegate_ = std::move(test_delegate);
Gabriel Charettee2b632b2017-08-02 03:52:16231 break;
Gabriel Charette1ef212b2017-12-03 12:47:21232 }
Gabriel Charettee2b632b2017-08-02 03:52:16233 }
234 }
235
236 private:
Gabriel Charette50518fc2018-05-22 17:53:22237 // Instantiates one or the other based on the RunLoopTestType.
Gabriel Charette694c3c332019-08-19 14:53:05238 std::unique_ptr<test::TaskEnvironment> task_environment_;
Gabriel Charette1ef212b2017-12-03 12:47:21239 std::unique_ptr<InjectableTestDelegate> test_delegate_;
Gabriel Charettee2b632b2017-08-02 03:52:16240};
241
242class RunLoopTest : public testing::TestWithParam<RunLoopTestType> {
David Bienvenu5f4d4f02020-09-27 16:55:03243 public:
244 RunLoopTest(const RunLoopTest&) = delete;
245 RunLoopTest& operator=(const RunLoopTest&) = delete;
246
Gabriel Charettee2b632b2017-08-02 03:52:16247 protected:
248 RunLoopTest() : test_environment_(GetParam()) {}
249
250 RunLoopTestEnvironment test_environment_;
fdoraya4f28ec2016-06-10 00:08:58251 RunLoop run_loop_;
fdoraya4f28ec2016-06-10 00:08:58252};
253
254} // namespace
255
Gabriel Charettee2b632b2017-08-02 03:52:16256TEST_P(RunLoopTest, QuitWhenIdle) {
Wezbbffcc52019-02-21 02:01:20257 int counter = 0;
Sean Maher7d0e8052022-12-09 01:46:32258 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
tzik92b7a422017-04-11 15:00:44259 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
Wezbbffcc52019-02-21 02:01:20260 Unretained(&counter)));
Sean Maher7d0e8052022-12-09 01:46:32261 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
262 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
263 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
Peter Kasting53fd6ee2021-10-05 20:40:48264 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), Days(1));
fdoraya4f28ec2016-06-10 00:08:58265
266 run_loop_.Run();
Wezbbffcc52019-02-21 02:01:20267 EXPECT_EQ(1, counter);
fdoraya4f28ec2016-06-10 00:08:58268}
269
Gabriel Charettee2b632b2017-08-02 03:52:16270TEST_P(RunLoopTest, QuitWhenIdleNestedLoop) {
Wezbbffcc52019-02-21 02:01:20271 int counter = 0;
Sean Maher7d0e8052022-12-09 01:46:32272 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Wezbbffcc52019-02-21 02:01:20273 FROM_HERE, BindOnce(&RunNestedLoopTask, Unretained(&counter)));
Sean Maher7d0e8052022-12-09 01:46:32274 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
tzik92b7a422017-04-11 15:00:44275 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
Wezbbffcc52019-02-21 02:01:20276 Unretained(&counter)));
Sean Maher7d0e8052022-12-09 01:46:32277 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
278 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
279 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
Peter Kasting53fd6ee2021-10-05 20:40:48280 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), Days(1));
fdoraya4f28ec2016-06-10 00:08:58281
282 run_loop_.Run();
Wezbbffcc52019-02-21 02:01:20283 EXPECT_EQ(3, counter);
fdoraya4f28ec2016-06-10 00:08:58284}
285
Gabriel Charettee2b632b2017-08-02 03:52:16286TEST_P(RunLoopTest, QuitWhenIdleClosure) {
Sean Maher7d0e8052022-12-09 01:46:32287 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
288 FROM_HERE, run_loop_.QuitWhenIdleClosure());
289 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
290 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
291 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
Peter Kasting53fd6ee2021-10-05 20:40:48292 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), Days(1));
fdoraya3658602016-06-10 18:23:15293
294 run_loop_.Run();
fdoraya3658602016-06-10 18:23:15295}
296
297// Verify that the QuitWhenIdleClosure() can run after the RunLoop has been
298// deleted. It should have no effect.
Gabriel Charettee2b632b2017-08-02 03:52:16299TEST_P(RunLoopTest, QuitWhenIdleClosureAfterRunLoopScope) {
kylechar650caf02019-07-17 03:25:41300 RepeatingClosure quit_when_idle_closure;
fdoraya3658602016-06-10 18:23:15301 {
302 RunLoop run_loop;
303 quit_when_idle_closure = run_loop.QuitWhenIdleClosure();
304 run_loop.RunUntilIdle();
305 }
306 quit_when_idle_closure.Run();
307}
308
gabcf5e4ce2017-05-19 22:56:57309// Verify that Quit can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16310TEST_P(RunLoopTest, QuitFromOtherSequence) {
311 Thread other_thread("test");
312 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57313 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16314 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57315
316 // Always expected to run before asynchronous Quit() kicks in.
Sean Maher7d0e8052022-12-09 01:46:32317 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
318 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57319
320 WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
321 WaitableEvent::InitialState::NOT_SIGNALED);
322 other_sequence->PostTask(
323 FROM_HERE, base::BindOnce([](RunLoop* run_loop) { run_loop->Quit(); },
324 Unretained(&run_loop_)));
325 other_sequence->PostTask(
326 FROM_HERE,
327 base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
328
329 // Anything that's posted after the Quit closure was posted back to this
330 // sequence shouldn't get a chance to run.
331 loop_was_quit.Wait();
Sean Maher7d0e8052022-12-09 01:46:32332 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
333 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57334
335 run_loop_.Run();
gabcf5e4ce2017-05-19 22:56:57336}
337
338// Verify that QuitClosure can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16339TEST_P(RunLoopTest, QuitFromOtherSequenceWithClosure) {
340 Thread other_thread("test");
341 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57342 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16343 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57344
345 // Always expected to run before asynchronous Quit() kicks in.
Sean Maher7d0e8052022-12-09 01:46:32346 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
347 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57348
349 WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
350 WaitableEvent::InitialState::NOT_SIGNALED);
351 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
352 other_sequence->PostTask(
353 FROM_HERE,
354 base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
355
356 // Anything that's posted after the Quit closure was posted back to this
357 // sequence shouldn't get a chance to run.
358 loop_was_quit.Wait();
Sean Maher7d0e8052022-12-09 01:46:32359 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
360 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57361
362 run_loop_.Run();
gabcf5e4ce2017-05-19 22:56:57363}
364
365// Verify that Quit can be executed from another sequence even when the
366// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
Gabriel Charettee2b632b2017-08-02 03:52:16367TEST_P(RunLoopTest, QuitFromOtherSequenceRacy) {
368 Thread other_thread("test");
369 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57370 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16371 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57372
373 // Always expected to run before asynchronous Quit() kicks in.
Sean Maher7d0e8052022-12-09 01:46:32374 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
375 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57376
Wezbbffcc52019-02-21 02:01:20377 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
gabcf5e4ce2017-05-19 22:56:57378
379 run_loop_.Run();
gabcf5e4ce2017-05-19 22:56:57380}
381
382// Verify that QuitClosure can be executed from another sequence even when the
383// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
Gabriel Charettee2b632b2017-08-02 03:52:16384TEST_P(RunLoopTest, QuitFromOtherSequenceRacyWithClosure) {
385 Thread other_thread("test");
386 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57387 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16388 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57389
390 // Always expected to run before asynchronous Quit() kicks in.
Sean Maher7d0e8052022-12-09 01:46:32391 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
392 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57393
394 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
395
396 run_loop_.Run();
gabcf5e4ce2017-05-19 22:56:57397}
398
399// Verify that QuitWhenIdle can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16400TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequence) {
401 Thread other_thread("test");
402 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57403 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16404 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57405
Sean Maher7d0e8052022-12-09 01:46:32406 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
407 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57408
409 other_sequence->PostTask(
410 FROM_HERE,
411 base::BindOnce([](RunLoop* run_loop) { run_loop->QuitWhenIdle(); },
412 Unretained(&run_loop_)));
413
Sean Maher7d0e8052022-12-09 01:46:32414 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
415 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57416
417 run_loop_.Run();
418
419 // Regardless of the outcome of the race this thread shouldn't have been idle
Wezbbffcc52019-02-21 02:01:20420 // until both tasks posted to this sequence have run.
gabcf5e4ce2017-05-19 22:56:57421}
422
423// Verify that QuitWhenIdleClosure can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16424TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequenceWithClosure) {
425 Thread other_thread("test");
426 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57427 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16428 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57429
Sean Maher7d0e8052022-12-09 01:46:32430 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
431 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57432
433 other_sequence->PostTask(FROM_HERE, run_loop_.QuitWhenIdleClosure());
434
Sean Maher7d0e8052022-12-09 01:46:32435 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
436 FROM_HERE, MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57437
438 run_loop_.Run();
439
440 // Regardless of the outcome of the race this thread shouldn't have been idle
Wezbbffcc52019-02-21 02:01:20441 // until the both tasks posted to this sequence have run.
gabcf5e4ce2017-05-19 22:56:57442}
443
Gabriel Charettee2b632b2017-08-02 03:52:16444TEST_P(RunLoopTest, IsRunningOnCurrentThread) {
gab7af9dc02017-05-05 13:38:54445 EXPECT_FALSE(RunLoop::IsRunningOnCurrentThread());
Sean Maher7d0e8052022-12-09 01:46:32446 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
gab7af9dc02017-05-05 13:38:54447 FROM_HERE,
Sorin Jianuad4cc6232024-10-08 19:06:01448 BindOnce([] { EXPECT_TRUE(RunLoop::IsRunningOnCurrentThread()); }));
Sean Maher7d0e8052022-12-09 01:46:32449 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
450 FROM_HERE, run_loop_.QuitClosure());
gab7af9dc02017-05-05 13:38:54451 run_loop_.Run();
452}
453
Gabriel Charettee2b632b2017-08-02 03:52:16454TEST_P(RunLoopTest, IsNestedOnCurrentThread) {
gab7af9dc02017-05-05 13:38:54455 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
456
Sean Maher7d0e8052022-12-09 01:46:32457 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Sorin Jianuad4cc6232024-10-08 19:06:01458 FROM_HERE, BindOnce([] {
gab7af9dc02017-05-05 13:38:54459 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
460
Gabriel Charette3ff403e2017-08-07 04:22:48461 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
gab7af9dc02017-05-05 13:38:54462
Sean Maher7d0e8052022-12-09 01:46:32463 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Sorin Jianuad4cc6232024-10-08 19:06:01464 FROM_HERE,
465 BindOnce([] { EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread()); }));
Sean Maher7d0e8052022-12-09 01:46:32466 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
467 FROM_HERE, nested_run_loop.QuitClosure());
gab7af9dc02017-05-05 13:38:54468
469 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
gab7af9dc02017-05-05 13:38:54470 nested_run_loop.Run();
471 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
472 }));
473
Sean Maher7d0e8052022-12-09 01:46:32474 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
475 FROM_HERE, run_loop_.QuitClosure());
gab7af9dc02017-05-05 13:38:54476 run_loop_.Run();
477}
478
Gabriel Charette2a53350172021-05-06 20:22:55479TEST_P(RunLoopTest, CannotRunMoreThanOnce) {
Sean Maher7d0e8052022-12-09 01:46:32480 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
481 FROM_HERE, run_loop_.QuitClosure());
Gabriel Charette2a53350172021-05-06 20:22:55482 run_loop_.Run();
483 EXPECT_DCHECK_DEATH({ run_loop_.Run(); });
484}
485
486TEST_P(RunLoopTest, CanRunUntilIdleMoreThanOnce) {
Sean Maher7d0e8052022-12-09 01:46:32487 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, DoNothing());
Gabriel Charette2a53350172021-05-06 20:22:55488 run_loop_.RunUntilIdle();
489
Sean Maher7d0e8052022-12-09 01:46:32490 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, DoNothing());
Gabriel Charette2a53350172021-05-06 20:22:55491 run_loop_.RunUntilIdle();
492 run_loop_.RunUntilIdle();
493}
494
495TEST_P(RunLoopTest, CanRunUntilIdleThenRunIfNotQuit) {
Sean Maher7d0e8052022-12-09 01:46:32496 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, DoNothing());
Gabriel Charette2a53350172021-05-06 20:22:55497 run_loop_.RunUntilIdle();
498
Sean Maher7d0e8052022-12-09 01:46:32499 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
500 FROM_HERE, run_loop_.QuitClosure());
Gabriel Charette2a53350172021-05-06 20:22:55501 run_loop_.Run();
502}
503
504TEST_P(RunLoopTest, CannotRunUntilIdleThenRunIfQuit) {
Sean Maher7d0e8052022-12-09 01:46:32505 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
506 FROM_HERE, run_loop_.QuitClosure());
Gabriel Charette2a53350172021-05-06 20:22:55507 run_loop_.RunUntilIdle();
508
Sean Maher7d0e8052022-12-09 01:46:32509 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, DoNothing());
Gabriel Charette2a53350172021-05-06 20:22:55510 EXPECT_DCHECK_DEATH({ run_loop_.Run(); });
511}
512
513TEST_P(RunLoopTest, CannotRunAgainIfQuitWhenIdle) {
Sean Maher7d0e8052022-12-09 01:46:32514 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
515 FROM_HERE, run_loop_.QuitWhenIdleClosure());
Gabriel Charette2a53350172021-05-06 20:22:55516 run_loop_.RunUntilIdle();
517
518 EXPECT_DCHECK_DEATH({ run_loop_.RunUntilIdle(); });
519}
520
Francois Doray80bdddf2018-01-04 16:17:32521namespace {
522
gab7af9dc02017-05-05 13:38:54523class MockNestingObserver : public RunLoop::NestingObserver {
524 public:
525 MockNestingObserver() = default;
David Bienvenu5f4d4f02020-09-27 16:55:03526 MockNestingObserver(const MockNestingObserver&) = delete;
527 MockNestingObserver& operator=(const MockNestingObserver&) = delete;
gab7af9dc02017-05-05 13:38:54528
529 // RunLoop::NestingObserver:
Lei Zhange9f2f482025-03-04 22:40:26530 MOCK_METHOD(void, OnBeginNestedRunLoop, ());
531 MOCK_METHOD(void, OnExitNestedRunLoop, ());
gab7af9dc02017-05-05 13:38:54532};
533
Francois Doray80bdddf2018-01-04 16:17:32534class MockTask {
535 public:
536 MockTask() = default;
David Bienvenu5f4d4f02020-09-27 16:55:03537 MockTask(const MockTask&) = delete;
538 MockTask& operator=(const MockTask&) = delete;
Francois Doray80bdddf2018-01-04 16:17:32539
David Bienvenu5f4d4f02020-09-27 16:55:03540 MOCK_METHOD0(Task, void());
Francois Doray80bdddf2018-01-04 16:17:32541};
542
543} // namespace
544
Gabriel Charettee2b632b2017-08-02 03:52:16545TEST_P(RunLoopTest, NestingObservers) {
gab7af9dc02017-05-05 13:38:54546 testing::StrictMock<MockNestingObserver> nesting_observer;
Francois Doray80bdddf2018-01-04 16:17:32547 testing::StrictMock<MockTask> mock_task_a;
548 testing::StrictMock<MockTask> mock_task_b;
gab7af9dc02017-05-05 13:38:54549
550 RunLoop::AddNestingObserverOnCurrentThread(&nesting_observer);
551
Sorin Jianuad4cc6232024-10-08 19:06:01552 const RepeatingClosure run_nested_loop = BindRepeating([] {
Gabriel Charette3ff403e2017-08-07 04:22:48553 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
Sean Maher7d0e8052022-12-09 01:46:32554 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
555 FROM_HERE, nested_run_loop.QuitClosure());
gab7af9dc02017-05-05 13:38:54556 nested_run_loop.Run();
557 });
558
Francois Doray80bdddf2018-01-04 16:17:32559 // Generate a stack of nested RunLoops. OnBeginNestedRunLoop() is expected
560 // when beginning each nesting depth and OnExitNestedRunLoop() is expected
Gabriel Charetted8839442018-03-15 18:56:22561 // when exiting each nesting depth. Each one of these tasks is ahead of the
562 // QuitClosures as those are only posted at the end of the queue when
563 // |run_nested_loop| is executed.
Sean Maher7d0e8052022-12-09 01:46:32564 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
565 run_nested_loop);
566 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Francois Doray80bdddf2018-01-04 16:17:32567 FROM_HERE,
568 base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_a)));
Sean Maher7d0e8052022-12-09 01:46:32569 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
570 run_nested_loop);
571 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Francois Doray80bdddf2018-01-04 16:17:32572 FROM_HERE,
573 base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_b)));
gab7af9dc02017-05-05 13:38:54574
Francois Doray80bdddf2018-01-04 16:17:32575 {
576 testing::InSequence in_sequence;
577 EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
578 EXPECT_CALL(mock_task_a, Task());
579 EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
580 EXPECT_CALL(mock_task_b, Task());
581 EXPECT_CALL(nesting_observer, OnExitNestedRunLoop()).Times(2);
582 }
583 run_loop_.RunUntilIdle();
gab7af9dc02017-05-05 13:38:54584
585 RunLoop::RemoveNestingObserverOnCurrentThread(&nesting_observer);
586}
587
Minoru Chikamune76ba6822021-01-12 10:39:51588TEST_P(RunLoopTest, DisallowRunning) {
Hans Wennborg9b292ba2022-02-15 16:01:29589 ScopedDisallowRunningRunLoop disallow_running;
Gabriel Charettef3fd8f02018-05-22 15:31:48590 EXPECT_DCHECK_DEATH({ run_loop_.RunUntilIdle(); });
Gabriel Charettea44975052017-08-21 23:14:04591}
592
Minoru Chikamune76ba6822021-01-12 10:39:51593TEST_P(RunLoopTest, ExpiredDisallowRunning) {
Hans Wennborg9b292ba2022-02-15 16:01:29594 { ScopedDisallowRunningRunLoop disallow_running; }
Gabriel Charettea44975052017-08-21 23:14:04595 // Running should be fine after |disallow_running| goes out of scope.
596 run_loop_.RunUntilIdle();
597}
598
Victor Costan033b9ac2019-01-29 00:52:16599INSTANTIATE_TEST_SUITE_P(Real,
600 RunLoopTest,
601 testing::Values(RunLoopTestType::kRealEnvironment));
602INSTANTIATE_TEST_SUITE_P(Mock,
603 RunLoopTest,
604 testing::Values(RunLoopTestType::kTestDelegate));
Gabriel Charettee2b632b2017-08-02 03:52:16605
606TEST(RunLoopDeathTest, MustRegisterBeforeInstantiating) {
Gabriel Charette1ef212b2017-12-03 12:47:21607 TestBoundDelegate unbound_test_delegate_;
Sean Maher70f2942932023-01-04 22:15:06608 // RunLoop::RunLoop() should CHECK fetching the
609 // SingleThreadTaskRunner::CurrentDefaultHandle.
Wez39ee6102018-04-14 21:33:59610 EXPECT_DEATH_IF_SUPPORTED({ RunLoop(); }, "");
Gabriel Charettee2b632b2017-08-02 03:52:16611}
612
Gabriel Charette3ff403e2017-08-07 04:22:48613TEST(RunLoopDelegateTest, NestableTasksDontRunInDefaultNestedLoops) {
Gabriel Charette1ef212b2017-12-03 12:47:21614 TestBoundDelegate test_delegate;
Gabriel Charette3ff403e2017-08-07 04:22:48615 test_delegate.BindToCurrentThread();
616
617 base::Thread other_thread("test");
618 other_thread.Start();
619
620 RunLoop main_loop;
621 // A nested run loop which isn't kNestableTasksAllowed.
622 RunLoop nested_run_loop(RunLoop::Type::kDefault);
623
624 bool nested_run_loop_ended = false;
625
626 // The first task on the main loop will result in a nested run loop. Since
627 // it's not kNestableTasksAllowed, no further task should be processed until
628 // it's quit.
Sean Maher7d0e8052022-12-09 01:46:32629 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
Gabriel Charette3ff403e2017-08-07 04:22:48630 FROM_HERE,
631 BindOnce([](RunLoop* nested_run_loop) { nested_run_loop->Run(); },
632 Unretained(&nested_run_loop)));
633
634 // Post a task that will fail if it runs inside the nested run loop.
Sean Maher7d0e8052022-12-09 01:46:32635 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
jdoerrie9d7236f62019-03-05 13:00:23636 FROM_HERE,
637 BindOnce(
638 [](const bool& nested_run_loop_ended,
639 OnceClosure continuation_callback) {
640 EXPECT_TRUE(nested_run_loop_ended);
641 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
642 std::move(continuation_callback).Run();
643 },
644 std::cref(nested_run_loop_ended), main_loop.QuitClosure()));
Gabriel Charette3ff403e2017-08-07 04:22:48645
646 // Post a task flipping the boolean bit for extra verification right before
647 // quitting |nested_run_loop|.
648 other_thread.task_runner()->PostDelayedTask(
649 FROM_HERE,
650 BindOnce(
651 [](bool* nested_run_loop_ended) {
652 EXPECT_FALSE(*nested_run_loop_ended);
653 *nested_run_loop_ended = true;
654 },
655 Unretained(&nested_run_loop_ended)),
656 TestTimeouts::tiny_timeout());
657 // Post an async delayed task to exit the run loop when idle. This confirms
658 // that (1) the test task only ran in the main loop after the nested loop
659 // exited and (2) the nested run loop actually considers itself idle while
660 // spinning. Note: The quit closure needs to be injected directly on the
661 // delegate as invoking QuitWhenIdle() off-thread results in a thread bounce
662 // which will not processed because of the very logic under test (nestable
663 // tasks don't run in |nested_run_loop|).
664 other_thread.task_runner()->PostDelayedTask(
665 FROM_HERE,
666 BindOnce(
Gabriel Charette1ef212b2017-12-03 12:47:21667 [](TestBoundDelegate* test_delegate, OnceClosure injected_closure) {
668 test_delegate->InjectClosureOnDelegate(std::move(injected_closure));
Gabriel Charette3ff403e2017-08-07 04:22:48669 },
670 Unretained(&test_delegate), nested_run_loop.QuitWhenIdleClosure()),
671 TestTimeouts::tiny_timeout());
672
673 main_loop.Run();
674}
675
fdoraya4f28ec2016-06-10 00:08:58676} // namespace base