blob: 90a6b71e2d7e24794833b8ba271ada9c809ad2ec [file] [log] [blame]
fdoraya4f28ec2016-06-10 00:08:581// Copyright 2016 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
5#include "base/run_loop.h"
6
jdoerrie9d7236f62019-03-05 13:00:237#include <functional>
Gabriel Charettee2b632b2017-08-02 03:52:168#include <utility>
9
fdoraya4f28ec2016-06-10 00:08:5810#include "base/bind.h"
11#include "base/bind_helpers.h"
Brett Wilsona62d9c02017-09-20 20:53:2012#include "base/containers/queue.h"
fdoraya4f28ec2016-06-10 00:08:5813#include "base/location.h"
14#include "base/macros.h"
Gabriel Charettee2b632b2017-08-02 03:52:1615#include "base/memory/ptr_util.h"
16#include "base/memory/ref_counted.h"
fdoraya4f28ec2016-06-10 00:08:5817#include "base/single_thread_task_runner.h"
Gabriel Charettee2b632b2017-08-02 03:52:1618#include "base/synchronization/lock.h"
gabcf5e4ce2017-05-19 22:56:5719#include "base/synchronization/waitable_event.h"
Wezbbffcc52019-02-21 02:01:2020#include "base/test/bind_test_util.h"
Gabriel Charettee2b632b2017-08-02 03:52:1621#include "base/test/gtest_util.h"
gabcf5e4ce2017-05-19 22:56:5722#include "base/test/scoped_task_environment.h"
Gabriel Charette3ff403e2017-08-07 04:22:4823#include "base/test/test_timeouts.h"
Gabriel Charettee2b632b2017-08-02 03:52:1624#include "base/threading/platform_thread.h"
Wezd9e4cb772019-01-09 03:07:0325#include "base/threading/sequenced_task_runner_handle.h"
Gabriel Charettee2b632b2017-08-02 03:52:1626#include "base/threading/thread.h"
27#include "base/threading/thread_checker_impl.h"
fdoraya4f28ec2016-06-10 00:08:5828#include "base/threading/thread_task_runner_handle.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.
46 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:4447 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&nested_run_loop),
48 Unretained(counter)));
fdoraya4f28ec2016-06-10 00:08:5849
50 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
Wezbbffcc52019-02-21 02:01:2051 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), TimeDelta::FromDays(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;
fdoraya4f28ec2016-06-10 00:08:5864
Brett Wilson8e88b312017-09-12 05:22:1665 bool PostDelayedTask(const Location& from_here,
Gabriel Charettee2b632b2017-08-02 03:52:1666 OnceClosure task,
67 base::TimeDelta delay) override {
68 if (delay > base::TimeDelta())
69 return false;
70 AutoLock auto_lock(tasks_lock_);
71 pending_tasks_.push(std::move(task));
72 return true;
73 }
74
Brett Wilson8e88b312017-09-12 05:22:1675 bool PostNonNestableDelayedTask(const Location& from_here,
Gabriel Charettee2b632b2017-08-02 03:52:1676 OnceClosure task,
77 base::TimeDelta delay) override {
78 return PostDelayedTask(from_here, std::move(task), delay);
79 }
80
81 bool RunsTasksInCurrentSequence() const override {
82 return origin_thread_checker_.CalledOnValidThread();
83 }
84
Gabriel Charette1ef212b2017-12-03 12:47:2185 bool ProcessSingleTask() {
Gabriel Charettee2b632b2017-08-02 03:52:1686 OnceClosure task;
87 {
88 AutoLock auto_lock(tasks_lock_);
89 if (pending_tasks_.empty())
90 return false;
91 task = std::move(pending_tasks_.front());
92 pending_tasks_.pop();
93 }
94 // It's important to Run() after pop() and outside the lock as |task| may
Gabriel Charette1ef212b2017-12-03 12:47:2195 // run a nested loop which will re-enter ProcessSingleTask().
Gabriel Charettee2b632b2017-08-02 03:52:1696 std::move(task).Run();
97 return true;
98 }
99
100 private:
101 ~SimpleSingleThreadTaskRunner() override = default;
102
103 Lock tasks_lock_;
Brett Wilsona62d9c02017-09-20 20:53:20104 base::queue<OnceClosure> pending_tasks_;
Gabriel Charettee2b632b2017-08-02 03:52:16105
106 // RunLoop relies on RunsTasksInCurrentSequence() signal. Use a
107 // ThreadCheckerImpl to be able to reliably provide that signal even in
108 // non-dcheck builds.
109 ThreadCheckerImpl origin_thread_checker_;
110
111 DISALLOW_COPY_AND_ASSIGN(SimpleSingleThreadTaskRunner);
112};
113
Gabriel Charette1ef212b2017-12-03 12:47:21114// The basis of all TestDelegates, allows safely injecting a OnceClosure to be
115// run in the next idle phase of this delegate's Run() implementation. This can
116// be used to have code run on a thread that is otherwise livelocked in an idle
117// phase (sometimes a simple PostTask() won't do it -- e.g. when processing
118// application tasks is disallowed).
119class InjectableTestDelegate : public RunLoop::Delegate {
Gabriel Charettee2b632b2017-08-02 03:52:16120 public:
Gabriel Charette1ef212b2017-12-03 12:47:21121 void InjectClosureOnDelegate(OnceClosure closure) {
122 AutoLock auto_lock(closure_lock_);
123 closure_ = std::move(closure);
124 }
Gabriel Charettee2b632b2017-08-02 03:52:16125
Gabriel Charette1ef212b2017-12-03 12:47:21126 bool RunInjectedClosure() {
127 AutoLock auto_lock(closure_lock_);
128 if (closure_.is_null())
129 return false;
130 std::move(closure_).Run();
131 return true;
132 }
133
134 private:
135 Lock closure_lock_;
136 OnceClosure closure_;
137};
138
139// A simple test RunLoop::Delegate to exercise Runloop logic independent of any
140// other base constructs. BindToCurrentThread() must be called before this
141// TestBoundDelegate is operational.
142class TestBoundDelegate final : public InjectableTestDelegate {
143 public:
144 TestBoundDelegate() = default;
145
146 // Makes this TestBoundDelegate become the RunLoop::Delegate and
147 // ThreadTaskRunnerHandle for this thread.
Gabriel Charettee2b632b2017-08-02 03:52:16148 void BindToCurrentThread() {
149 thread_task_runner_handle_ =
Jeremy Roman9532f252017-08-16 23:27:24150 std::make_unique<ThreadTaskRunnerHandle>(simple_task_runner_);
Gabriel Charettea3ec9612017-12-14 17:22:40151 RunLoop::RegisterDelegateForCurrentThread(this);
Gabriel Charettee2b632b2017-08-02 03:52:16152 }
153
154 private:
Gabriel Charetteb030a4a2017-10-26 01:04:40155 void Run(bool application_tasks_allowed) override {
Gabriel Charette3ff403e2017-08-07 04:22:48156 if (nested_run_allowing_tasks_incoming_) {
Gabriel Charette1ef212b2017-12-03 12:47:21157 EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
Gabriel Charetteb030a4a2017-10-26 01:04:40158 EXPECT_TRUE(application_tasks_allowed);
Gabriel Charette1ef212b2017-12-03 12:47:21159 } else if (RunLoop::IsNestedOnCurrentThread()) {
Gabriel Charetteb030a4a2017-10-26 01:04:40160 EXPECT_FALSE(application_tasks_allowed);
Gabriel Charette3ff403e2017-08-07 04:22:48161 }
162 nested_run_allowing_tasks_incoming_ = false;
163
Gabriel Charettee2b632b2017-08-02 03:52:16164 while (!should_quit_) {
Gabriel Charette1ef212b2017-12-03 12:47:21165 if (application_tasks_allowed && simple_task_runner_->ProcessSingleTask())
Gabriel Charettee2b632b2017-08-02 03:52:16166 continue;
167
Gabriel Charettea3ec9612017-12-14 17:22:40168 if (ShouldQuitWhenIdle())
Gabriel Charettee2b632b2017-08-02 03:52:16169 break;
170
Gabriel Charette1ef212b2017-12-03 12:47:21171 if (RunInjectedClosure())
172 continue;
Gabriel Charette3ff403e2017-08-07 04:22:48173
Gabriel Charettee2b632b2017-08-02 03:52:16174 PlatformThread::YieldCurrentThread();
175 }
176 should_quit_ = false;
177 }
178
179 void Quit() override { should_quit_ = true; }
180
Gabriel Charette3ff403e2017-08-07 04:22:48181 void EnsureWorkScheduled() override {
182 nested_run_allowing_tasks_incoming_ = true;
183 }
184
185 // True if the next invocation of Run() is expected to be from a
186 // kNestableTasksAllowed RunLoop.
187 bool nested_run_allowing_tasks_incoming_ = false;
188
Gabriel Charettee2b632b2017-08-02 03:52:16189 scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
190 MakeRefCounted<SimpleSingleThreadTaskRunner>();
Gabriel Charette1ef212b2017-12-03 12:47:21191
Gabriel Charettee2b632b2017-08-02 03:52:16192 std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
193
194 bool should_quit_ = false;
Gabriel Charette1ef212b2017-12-03 12:47:21195};
196
Gabriel Charettee2b632b2017-08-02 03:52:16197enum class RunLoopTestType {
198 // Runs all RunLoopTests under a ScopedTaskEnvironment to make sure real world
199 // scenarios work.
200 kRealEnvironment,
201
202 // Runs all RunLoopTests under a test RunLoop::Delegate to make sure the
203 // delegate interface fully works standalone.
204 kTestDelegate,
205};
206
207// The task environment for the RunLoopTest of a given type. A separate class
208// so it can be instantiated on the stack in the RunLoopTest fixture.
209class RunLoopTestEnvironment {
210 public:
211 RunLoopTestEnvironment(RunLoopTestType type) {
212 switch (type) {
Gabriel Charette1ef212b2017-12-03 12:47:21213 case RunLoopTestType::kRealEnvironment: {
Jeremy Roman9532f252017-08-16 23:27:24214 task_environment_ = std::make_unique<test::ScopedTaskEnvironment>();
Gabriel Charettee2b632b2017-08-02 03:52:16215 break;
Gabriel Charette1ef212b2017-12-03 12:47:21216 }
217 case RunLoopTestType::kTestDelegate: {
218 auto test_delegate = std::make_unique<TestBoundDelegate>();
219 test_delegate->BindToCurrentThread();
220 test_delegate_ = std::move(test_delegate);
Gabriel Charettee2b632b2017-08-02 03:52:16221 break;
Gabriel Charette1ef212b2017-12-03 12:47:21222 }
Gabriel Charettee2b632b2017-08-02 03:52:16223 }
224 }
225
226 private:
Gabriel Charette50518fc2018-05-22 17:53:22227 // Instantiates one or the other based on the RunLoopTestType.
Gabriel Charettee2b632b2017-08-02 03:52:16228 std::unique_ptr<test::ScopedTaskEnvironment> task_environment_;
Gabriel Charette1ef212b2017-12-03 12:47:21229 std::unique_ptr<InjectableTestDelegate> test_delegate_;
Gabriel Charettee2b632b2017-08-02 03:52:16230};
231
232class RunLoopTest : public testing::TestWithParam<RunLoopTestType> {
233 protected:
234 RunLoopTest() : test_environment_(GetParam()) {}
235
236 RunLoopTestEnvironment test_environment_;
fdoraya4f28ec2016-06-10 00:08:58237 RunLoop run_loop_;
fdoraya4f28ec2016-06-10 00:08:58238
239 private:
240 DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
241};
242
243} // namespace
244
Gabriel Charettee2b632b2017-08-02 03:52:16245TEST_P(RunLoopTest, QuitWhenIdle) {
Wezbbffcc52019-02-21 02:01:20246 int counter = 0;
gab7af9dc02017-05-05 13:38:54247 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:44248 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
Wezbbffcc52019-02-21 02:01:20249 Unretained(&counter)));
250 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
251 MakeExpectedRunClosure(FROM_HERE));
gab7af9dc02017-05-05 13:38:54252 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
Wezbbffcc52019-02-21 02:01:20253 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), TimeDelta::FromDays(1));
fdoraya4f28ec2016-06-10 00:08:58254
255 run_loop_.Run();
Wezbbffcc52019-02-21 02:01:20256 EXPECT_EQ(1, counter);
fdoraya4f28ec2016-06-10 00:08:58257}
258
Gabriel Charettee2b632b2017-08-02 03:52:16259TEST_P(RunLoopTest, QuitWhenIdleNestedLoop) {
Wezbbffcc52019-02-21 02:01:20260 int counter = 0;
gab7af9dc02017-05-05 13:38:54261 ThreadTaskRunnerHandle::Get()->PostTask(
Wezbbffcc52019-02-21 02:01:20262 FROM_HERE, BindOnce(&RunNestedLoopTask, Unretained(&counter)));
gab7af9dc02017-05-05 13:38:54263 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:44264 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
Wezbbffcc52019-02-21 02:01:20265 Unretained(&counter)));
266 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
267 MakeExpectedRunClosure(FROM_HERE));
gab7af9dc02017-05-05 13:38:54268 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
Wezbbffcc52019-02-21 02:01:20269 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), TimeDelta::FromDays(1));
fdoraya4f28ec2016-06-10 00:08:58270
271 run_loop_.Run();
Wezbbffcc52019-02-21 02:01:20272 EXPECT_EQ(3, counter);
fdoraya4f28ec2016-06-10 00:08:58273}
274
Gabriel Charettee2b632b2017-08-02 03:52:16275TEST_P(RunLoopTest, QuitWhenIdleClosure) {
gab7af9dc02017-05-05 13:38:54276 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
277 run_loop_.QuitWhenIdleClosure());
Wezbbffcc52019-02-21 02:01:20278 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
279 MakeExpectedRunClosure(FROM_HERE));
gab7af9dc02017-05-05 13:38:54280 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
Wezbbffcc52019-02-21 02:01:20281 FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), TimeDelta::FromDays(1));
fdoraya3658602016-06-10 18:23:15282
283 run_loop_.Run();
fdoraya3658602016-06-10 18:23:15284}
285
286// Verify that the QuitWhenIdleClosure() can run after the RunLoop has been
287// deleted. It should have no effect.
Gabriel Charettee2b632b2017-08-02 03:52:16288TEST_P(RunLoopTest, QuitWhenIdleClosureAfterRunLoopScope) {
fdoraya3658602016-06-10 18:23:15289 Closure quit_when_idle_closure;
290 {
291 RunLoop run_loop;
292 quit_when_idle_closure = run_loop.QuitWhenIdleClosure();
293 run_loop.RunUntilIdle();
294 }
295 quit_when_idle_closure.Run();
296}
297
gabcf5e4ce2017-05-19 22:56:57298// Verify that Quit can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16299TEST_P(RunLoopTest, QuitFromOtherSequence) {
300 Thread other_thread("test");
301 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57302 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16303 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57304
305 // Always expected to run before asynchronous Quit() kicks in.
Wezbbffcc52019-02-21 02:01:20306 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
307 MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57308
309 WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
310 WaitableEvent::InitialState::NOT_SIGNALED);
311 other_sequence->PostTask(
312 FROM_HERE, base::BindOnce([](RunLoop* run_loop) { run_loop->Quit(); },
313 Unretained(&run_loop_)));
314 other_sequence->PostTask(
315 FROM_HERE,
316 base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
317
318 // Anything that's posted after the Quit closure was posted back to this
319 // sequence shouldn't get a chance to run.
320 loop_was_quit.Wait();
Gabriel Charettee2b632b2017-08-02 03:52:16321 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
Wezbbffcc52019-02-21 02:01:20322 MakeExpectedNotRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57323
324 run_loop_.Run();
gabcf5e4ce2017-05-19 22:56:57325}
326
327// Verify that QuitClosure can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16328TEST_P(RunLoopTest, QuitFromOtherSequenceWithClosure) {
329 Thread other_thread("test");
330 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57331 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16332 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57333
334 // Always expected to run before asynchronous Quit() kicks in.
Wezbbffcc52019-02-21 02:01:20335 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
336 MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57337
338 WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
339 WaitableEvent::InitialState::NOT_SIGNALED);
340 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
341 other_sequence->PostTask(
342 FROM_HERE,
343 base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
344
345 // Anything that's posted after the Quit closure was posted back to this
346 // sequence shouldn't get a chance to run.
347 loop_was_quit.Wait();
Gabriel Charettee2b632b2017-08-02 03:52:16348 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
Wezbbffcc52019-02-21 02:01:20349 MakeExpectedNotRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57350
351 run_loop_.Run();
gabcf5e4ce2017-05-19 22:56:57352}
353
354// Verify that Quit can be executed from another sequence even when the
355// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
Gabriel Charettee2b632b2017-08-02 03:52:16356TEST_P(RunLoopTest, QuitFromOtherSequenceRacy) {
357 Thread other_thread("test");
358 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57359 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16360 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57361
362 // Always expected to run before asynchronous Quit() kicks in.
Wezbbffcc52019-02-21 02:01:20363 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
364 MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57365
Wezbbffcc52019-02-21 02:01:20366 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
gabcf5e4ce2017-05-19 22:56:57367
368 run_loop_.Run();
gabcf5e4ce2017-05-19 22:56:57369}
370
371// Verify that QuitClosure can be executed from another sequence even when the
372// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
Gabriel Charettee2b632b2017-08-02 03:52:16373TEST_P(RunLoopTest, QuitFromOtherSequenceRacyWithClosure) {
374 Thread other_thread("test");
375 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57376 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16377 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57378
379 // Always expected to run before asynchronous Quit() kicks in.
Wezbbffcc52019-02-21 02:01:20380 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
381 MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57382
383 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
384
385 run_loop_.Run();
gabcf5e4ce2017-05-19 22:56:57386}
387
388// Verify that QuitWhenIdle can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16389TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequence) {
390 Thread other_thread("test");
391 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57392 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16393 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57394
Wezbbffcc52019-02-21 02:01:20395 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
396 MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57397
398 other_sequence->PostTask(
399 FROM_HERE,
400 base::BindOnce([](RunLoop* run_loop) { run_loop->QuitWhenIdle(); },
401 Unretained(&run_loop_)));
402
Wezbbffcc52019-02-21 02:01:20403 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
404 MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57405
406 run_loop_.Run();
407
408 // Regardless of the outcome of the race this thread shouldn't have been idle
Wezbbffcc52019-02-21 02:01:20409 // until both tasks posted to this sequence have run.
gabcf5e4ce2017-05-19 22:56:57410}
411
412// Verify that QuitWhenIdleClosure can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16413TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequenceWithClosure) {
414 Thread other_thread("test");
415 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57416 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16417 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57418
Wezbbffcc52019-02-21 02:01:20419 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
420 MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57421
422 other_sequence->PostTask(FROM_HERE, run_loop_.QuitWhenIdleClosure());
423
Wezbbffcc52019-02-21 02:01:20424 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
425 MakeExpectedRunClosure(FROM_HERE));
gabcf5e4ce2017-05-19 22:56:57426
427 run_loop_.Run();
428
429 // Regardless of the outcome of the race this thread shouldn't have been idle
Wezbbffcc52019-02-21 02:01:20430 // until the both tasks posted to this sequence have run.
gabcf5e4ce2017-05-19 22:56:57431}
432
Gabriel Charettee2b632b2017-08-02 03:52:16433TEST_P(RunLoopTest, IsRunningOnCurrentThread) {
gab7af9dc02017-05-05 13:38:54434 EXPECT_FALSE(RunLoop::IsRunningOnCurrentThread());
435 ThreadTaskRunnerHandle::Get()->PostTask(
436 FROM_HERE,
tzik0c100dc2017-06-26 06:13:17437 BindOnce([]() { EXPECT_TRUE(RunLoop::IsRunningOnCurrentThread()); }));
gab7af9dc02017-05-05 13:38:54438 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
439 run_loop_.Run();
440}
441
Gabriel Charettee2b632b2017-08-02 03:52:16442TEST_P(RunLoopTest, IsNestedOnCurrentThread) {
gab7af9dc02017-05-05 13:38:54443 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
444
445 ThreadTaskRunnerHandle::Get()->PostTask(
tzik0c100dc2017-06-26 06:13:17446 FROM_HERE, BindOnce([]() {
gab7af9dc02017-05-05 13:38:54447 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
448
Gabriel Charette3ff403e2017-08-07 04:22:48449 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
gab7af9dc02017-05-05 13:38:54450
451 ThreadTaskRunnerHandle::Get()->PostTask(
tzik0c100dc2017-06-26 06:13:17452 FROM_HERE, BindOnce([]() {
453 EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
454 }));
gab7af9dc02017-05-05 13:38:54455 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
456 nested_run_loop.QuitClosure());
457
458 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
gab7af9dc02017-05-05 13:38:54459 nested_run_loop.Run();
460 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
461 }));
462
463 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
464 run_loop_.Run();
465}
466
Francois Doray80bdddf2018-01-04 16:17:32467namespace {
468
gab7af9dc02017-05-05 13:38:54469class MockNestingObserver : public RunLoop::NestingObserver {
470 public:
471 MockNestingObserver() = default;
472
473 // RunLoop::NestingObserver:
474 MOCK_METHOD0(OnBeginNestedRunLoop, void());
Francois Doray80bdddf2018-01-04 16:17:32475 MOCK_METHOD0(OnExitNestedRunLoop, void());
gab7af9dc02017-05-05 13:38:54476
477 private:
478 DISALLOW_COPY_AND_ASSIGN(MockNestingObserver);
479};
480
Francois Doray80bdddf2018-01-04 16:17:32481class MockTask {
482 public:
483 MockTask() = default;
484 MOCK_METHOD0(Task, void());
485
486 private:
487 DISALLOW_COPY_AND_ASSIGN(MockTask);
488};
489
490} // namespace
491
Gabriel Charettee2b632b2017-08-02 03:52:16492TEST_P(RunLoopTest, NestingObservers) {
gab7af9dc02017-05-05 13:38:54493 testing::StrictMock<MockNestingObserver> nesting_observer;
Francois Doray80bdddf2018-01-04 16:17:32494 testing::StrictMock<MockTask> mock_task_a;
495 testing::StrictMock<MockTask> mock_task_b;
gab7af9dc02017-05-05 13:38:54496
497 RunLoop::AddNestingObserverOnCurrentThread(&nesting_observer);
498
499 const RepeatingClosure run_nested_loop = Bind([]() {
Gabriel Charette3ff403e2017-08-07 04:22:48500 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
gab7af9dc02017-05-05 13:38:54501 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
502 nested_run_loop.QuitClosure());
gab7af9dc02017-05-05 13:38:54503 nested_run_loop.Run();
504 });
505
Francois Doray80bdddf2018-01-04 16:17:32506 // Generate a stack of nested RunLoops. OnBeginNestedRunLoop() is expected
507 // when beginning each nesting depth and OnExitNestedRunLoop() is expected
Gabriel Charetted8839442018-03-15 18:56:22508 // when exiting each nesting depth. Each one of these tasks is ahead of the
509 // QuitClosures as those are only posted at the end of the queue when
510 // |run_nested_loop| is executed.
gab7af9dc02017-05-05 13:38:54511 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
Francois Doray80bdddf2018-01-04 16:17:32512 ThreadTaskRunnerHandle::Get()->PostTask(
513 FROM_HERE,
514 base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_a)));
gab7af9dc02017-05-05 13:38:54515 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
Francois Doray80bdddf2018-01-04 16:17:32516 ThreadTaskRunnerHandle::Get()->PostTask(
517 FROM_HERE,
518 base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_b)));
gab7af9dc02017-05-05 13:38:54519
Francois Doray80bdddf2018-01-04 16:17:32520 {
521 testing::InSequence in_sequence;
522 EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
523 EXPECT_CALL(mock_task_a, Task());
524 EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
525 EXPECT_CALL(mock_task_b, Task());
526 EXPECT_CALL(nesting_observer, OnExitNestedRunLoop()).Times(2);
527 }
528 run_loop_.RunUntilIdle();
gab7af9dc02017-05-05 13:38:54529
530 RunLoop::RemoveNestingObserverOnCurrentThread(&nesting_observer);
531}
532
Gabriel Charettea44975052017-08-21 23:14:04533TEST_P(RunLoopTest, DisallowRunningForTesting) {
534 RunLoop::ScopedDisallowRunningForTesting disallow_running;
Gabriel Charettef3fd8f02018-05-22 15:31:48535 EXPECT_DCHECK_DEATH({ run_loop_.RunUntilIdle(); });
Gabriel Charettea44975052017-08-21 23:14:04536}
537
538TEST_P(RunLoopTest, ExpiredDisallowRunningForTesting) {
539 { RunLoop::ScopedDisallowRunningForTesting disallow_running; }
540 // Running should be fine after |disallow_running| goes out of scope.
541 run_loop_.RunUntilIdle();
542}
543
Victor Costan033b9ac2019-01-29 00:52:16544INSTANTIATE_TEST_SUITE_P(Real,
545 RunLoopTest,
546 testing::Values(RunLoopTestType::kRealEnvironment));
547INSTANTIATE_TEST_SUITE_P(Mock,
548 RunLoopTest,
549 testing::Values(RunLoopTestType::kTestDelegate));
Gabriel Charettee2b632b2017-08-02 03:52:16550
Wezd9e4cb772019-01-09 03:07:03551TEST(ScopedRunTimeoutForTestTest, TimesOut) {
552 test::ScopedTaskEnvironment task_environment;
553 RunLoop run_loop;
554
555 static constexpr auto kArbitraryTimeout =
556 base::TimeDelta::FromMilliseconds(10);
Wezbbffcc52019-02-21 02:01:20557 RunLoop::ScopedRunTimeoutForTest run_timeout(
558 kArbitraryTimeout, MakeExpectedRunAtLeastOnceClosure(FROM_HERE));
Wezd9e4cb772019-01-09 03:07:03559
560 // Since the delayed task will be posted only after the message pump starts
561 // running, the ScopedRunTimeoutForTest will already have started to elapse,
562 // so if Run() exits at the correct time then our delayed task will not run.
563 SequencedTaskRunnerHandle::Get()->PostTask(
564 FROM_HERE,
565 base::BindOnce(base::IgnoreResult(&SequencedTaskRunner::PostDelayedTask),
566 SequencedTaskRunnerHandle::Get(), FROM_HERE,
Wezbbffcc52019-02-21 02:01:20567 MakeExpectedNotRunClosure(FROM_HERE), kArbitraryTimeout));
Wezd9e4cb772019-01-09 03:07:03568
569 // This task should get to run before Run() times-out.
Wezd9e4cb772019-01-09 03:07:03570 SequencedTaskRunnerHandle::Get()->PostDelayedTask(
Wezbbffcc52019-02-21 02:01:20571 FROM_HERE, MakeExpectedRunClosure(FROM_HERE), kArbitraryTimeout);
Wezd9e4cb772019-01-09 03:07:03572
573 run_loop.Run();
Wezd9e4cb772019-01-09 03:07:03574}
575
576TEST(ScopedRunTimeoutForTestTest, RunTasksUntilTimeout) {
577 test::ScopedTaskEnvironment task_environment;
578 RunLoop run_loop;
579
580 static constexpr auto kArbitraryTimeout =
581 base::TimeDelta::FromMilliseconds(10);
Wezbbffcc52019-02-21 02:01:20582 RunLoop::ScopedRunTimeoutForTest run_timeout(
583 kArbitraryTimeout, MakeExpectedRunAtLeastOnceClosure(FROM_HERE));
Wezd9e4cb772019-01-09 03:07:03584
585 // Posting a task with the same delay as our timeout, immediately before
Wezbbffcc52019-02-21 02:01:20586 // calling Run(), means it should get to run. Since this uses QuitWhenIdle(),
587 // the Run() timeout callback should also get to run.
Wezd9e4cb772019-01-09 03:07:03588 SequencedTaskRunnerHandle::Get()->PostDelayedTask(
Wezbbffcc52019-02-21 02:01:20589 FROM_HERE, MakeExpectedRunClosure(FROM_HERE), kArbitraryTimeout);
Wezd9e4cb772019-01-09 03:07:03590
591 run_loop.Run();
Wezd9e4cb772019-01-09 03:07:03592}
593
Gabriel Charettee2b632b2017-08-02 03:52:16594TEST(RunLoopDeathTest, MustRegisterBeforeInstantiating) {
Gabriel Charette1ef212b2017-12-03 12:47:21595 TestBoundDelegate unbound_test_delegate_;
Wez39ee6102018-04-14 21:33:59596 // RunLoop::RunLoop() should CHECK fetching the ThreadTaskRunnerHandle.
597 EXPECT_DEATH_IF_SUPPORTED({ RunLoop(); }, "");
Gabriel Charettee2b632b2017-08-02 03:52:16598}
599
Gabriel Charette3ff403e2017-08-07 04:22:48600TEST(RunLoopDelegateTest, NestableTasksDontRunInDefaultNestedLoops) {
Gabriel Charette1ef212b2017-12-03 12:47:21601 TestBoundDelegate test_delegate;
Gabriel Charette3ff403e2017-08-07 04:22:48602 test_delegate.BindToCurrentThread();
603
604 base::Thread other_thread("test");
605 other_thread.Start();
606
607 RunLoop main_loop;
608 // A nested run loop which isn't kNestableTasksAllowed.
609 RunLoop nested_run_loop(RunLoop::Type::kDefault);
610
611 bool nested_run_loop_ended = false;
612
613 // The first task on the main loop will result in a nested run loop. Since
614 // it's not kNestableTasksAllowed, no further task should be processed until
615 // it's quit.
616 ThreadTaskRunnerHandle::Get()->PostTask(
617 FROM_HERE,
618 BindOnce([](RunLoop* nested_run_loop) { nested_run_loop->Run(); },
619 Unretained(&nested_run_loop)));
620
621 // Post a task that will fail if it runs inside the nested run loop.
622 ThreadTaskRunnerHandle::Get()->PostTask(
jdoerrie9d7236f62019-03-05 13:00:23623 FROM_HERE,
624 BindOnce(
625 [](const bool& nested_run_loop_ended,
626 OnceClosure continuation_callback) {
627 EXPECT_TRUE(nested_run_loop_ended);
628 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
629 std::move(continuation_callback).Run();
630 },
631 std::cref(nested_run_loop_ended), main_loop.QuitClosure()));
Gabriel Charette3ff403e2017-08-07 04:22:48632
633 // Post a task flipping the boolean bit for extra verification right before
634 // quitting |nested_run_loop|.
635 other_thread.task_runner()->PostDelayedTask(
636 FROM_HERE,
637 BindOnce(
638 [](bool* nested_run_loop_ended) {
639 EXPECT_FALSE(*nested_run_loop_ended);
640 *nested_run_loop_ended = true;
641 },
642 Unretained(&nested_run_loop_ended)),
643 TestTimeouts::tiny_timeout());
644 // Post an async delayed task to exit the run loop when idle. This confirms
645 // that (1) the test task only ran in the main loop after the nested loop
646 // exited and (2) the nested run loop actually considers itself idle while
647 // spinning. Note: The quit closure needs to be injected directly on the
648 // delegate as invoking QuitWhenIdle() off-thread results in a thread bounce
649 // which will not processed because of the very logic under test (nestable
650 // tasks don't run in |nested_run_loop|).
651 other_thread.task_runner()->PostDelayedTask(
652 FROM_HERE,
653 BindOnce(
Gabriel Charette1ef212b2017-12-03 12:47:21654 [](TestBoundDelegate* test_delegate, OnceClosure injected_closure) {
655 test_delegate->InjectClosureOnDelegate(std::move(injected_closure));
Gabriel Charette3ff403e2017-08-07 04:22:48656 },
657 Unretained(&test_delegate), nested_run_loop.QuitWhenIdleClosure()),
658 TestTimeouts::tiny_timeout());
659
660 main_loop.Run();
661}
662
fdoraya4f28ec2016-06-10 00:08:58663} // namespace base