blob: 70d506c1604627f7f4d7fe261f1f20b667e7128a [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
Gabriel Charettee2b632b2017-08-02 03:52:167#include <utility>
8
fdoraya4f28ec2016-06-10 00:08:589#include "base/bind.h"
10#include "base/bind_helpers.h"
Brett Wilsona62d9c02017-09-20 20:53:2011#include "base/containers/queue.h"
fdoraya4f28ec2016-06-10 00:08:5812#include "base/location.h"
13#include "base/macros.h"
Gabriel Charettee2b632b2017-08-02 03:52:1614#include "base/memory/ptr_util.h"
15#include "base/memory/ref_counted.h"
fdoraya4f28ec2016-06-10 00:08:5816#include "base/single_thread_task_runner.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"
Gabriel Charettee2b632b2017-08-02 03:52:1619#include "base/test/gtest_util.h"
gabcf5e4ce2017-05-19 22:56:5720#include "base/test/scoped_task_environment.h"
Gabriel Charette3ff403e2017-08-07 04:22:4821#include "base/test/test_timeouts.h"
Gabriel Charettee2b632b2017-08-02 03:52:1622#include "base/threading/platform_thread.h"
23#include "base/threading/thread.h"
24#include "base/threading/thread_checker_impl.h"
fdoraya4f28ec2016-06-10 00:08:5825#include "base/threading/thread_task_runner_handle.h"
Gabriel Charettee2b632b2017-08-02 03:52:1626#include "build/build_config.h"
gab7af9dc02017-05-05 13:38:5427#include "testing/gmock/include/gmock/gmock.h"
fdoraya4f28ec2016-06-10 00:08:5828#include "testing/gtest/include/gtest/gtest.h"
29
30namespace base {
31
32namespace {
33
34void QuitWhenIdleTask(RunLoop* run_loop, int* counter) {
35 run_loop->QuitWhenIdle();
36 ++(*counter);
37}
38
39void ShouldRunTask(int* counter) {
40 ++(*counter);
41}
42
43void ShouldNotRunTask() {
44 ADD_FAILURE() << "Ran a task that shouldn't run.";
45}
46
47void RunNestedLoopTask(int* counter) {
Gabriel Charette3ff403e2017-08-07 04:22:4848 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
fdoraya4f28ec2016-06-10 00:08:5849
50 // This task should quit |nested_run_loop| but not the main RunLoop.
51 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:4452 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&nested_run_loop),
53 Unretained(counter)));
fdoraya4f28ec2016-06-10 00:08:5854
55 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik92b7a422017-04-11 15:00:4456 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdoraya4f28ec2016-06-10 00:08:5857
fdoraya4f28ec2016-06-10 00:08:5858 nested_run_loop.Run();
59
60 ++(*counter);
61}
62
Gabriel Charettee2b632b2017-08-02 03:52:1663// A simple SingleThreadTaskRunner that just queues undelayed tasks (and ignores
64// delayed tasks). Tasks can then be processed one by one by ProcessTask() which
65// will return true if it processed a task and false otherwise.
66class SimpleSingleThreadTaskRunner : public SingleThreadTaskRunner {
67 public:
68 SimpleSingleThreadTaskRunner() = default;
fdoraya4f28ec2016-06-10 00:08:5869
Brett Wilson8e88b312017-09-12 05:22:1670 bool PostDelayedTask(const Location& from_here,
Gabriel Charettee2b632b2017-08-02 03:52:1671 OnceClosure task,
72 base::TimeDelta delay) override {
73 if (delay > base::TimeDelta())
74 return false;
75 AutoLock auto_lock(tasks_lock_);
76 pending_tasks_.push(std::move(task));
77 return true;
78 }
79
Brett Wilson8e88b312017-09-12 05:22:1680 bool PostNonNestableDelayedTask(const Location& from_here,
Gabriel Charettee2b632b2017-08-02 03:52:1681 OnceClosure task,
82 base::TimeDelta delay) override {
83 return PostDelayedTask(from_here, std::move(task), delay);
84 }
85
86 bool RunsTasksInCurrentSequence() const override {
87 return origin_thread_checker_.CalledOnValidThread();
88 }
89
Gabriel Charette1ef212b2017-12-03 12:47:2190 bool ProcessSingleTask() {
Gabriel Charettee2b632b2017-08-02 03:52:1691 OnceClosure task;
92 {
93 AutoLock auto_lock(tasks_lock_);
94 if (pending_tasks_.empty())
95 return false;
96 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
Gabriel Charette1ef212b2017-12-03 12:47:21105 base::queue<OnceClosure> TakePendingTasks() {
106 AutoLock auto_lock(tasks_lock_);
107 base::queue<OnceClosure> pending_tasks;
108 std::swap(pending_tasks, pending_tasks_);
109 return pending_tasks;
110 }
111
Gabriel Charettee2b632b2017-08-02 03:52:16112 private:
113 ~SimpleSingleThreadTaskRunner() override = default;
114
115 Lock tasks_lock_;
Brett Wilsona62d9c02017-09-20 20:53:20116 base::queue<OnceClosure> pending_tasks_;
Gabriel Charettee2b632b2017-08-02 03:52:16117
118 // RunLoop relies on RunsTasksInCurrentSequence() signal. Use a
119 // ThreadCheckerImpl to be able to reliably provide that signal even in
120 // non-dcheck builds.
121 ThreadCheckerImpl origin_thread_checker_;
122
123 DISALLOW_COPY_AND_ASSIGN(SimpleSingleThreadTaskRunner);
124};
125
Gabriel Charette1ef212b2017-12-03 12:47:21126// The basis of all TestDelegates, allows safely injecting a OnceClosure to be
127// run in the next idle phase of this delegate's Run() implementation. This can
128// be used to have code run on a thread that is otherwise livelocked in an idle
129// phase (sometimes a simple PostTask() won't do it -- e.g. when processing
130// application tasks is disallowed).
131class InjectableTestDelegate : public RunLoop::Delegate {
Gabriel Charettee2b632b2017-08-02 03:52:16132 public:
Gabriel Charette1ef212b2017-12-03 12:47:21133 void InjectClosureOnDelegate(OnceClosure closure) {
134 AutoLock auto_lock(closure_lock_);
135 closure_ = std::move(closure);
136 }
Gabriel Charettee2b632b2017-08-02 03:52:16137
Gabriel Charette1ef212b2017-12-03 12:47:21138 bool RunInjectedClosure() {
139 AutoLock auto_lock(closure_lock_);
140 if (closure_.is_null())
141 return false;
142 std::move(closure_).Run();
143 return true;
144 }
145
146 private:
147 Lock closure_lock_;
148 OnceClosure closure_;
149};
150
151// A simple test RunLoop::Delegate to exercise Runloop logic independent of any
152// other base constructs. BindToCurrentThread() must be called before this
153// TestBoundDelegate is operational.
154class TestBoundDelegate final : public InjectableTestDelegate {
155 public:
156 TestBoundDelegate() = default;
157
158 // Makes this TestBoundDelegate become the RunLoop::Delegate and
159 // ThreadTaskRunnerHandle for this thread.
Gabriel Charettee2b632b2017-08-02 03:52:16160 void BindToCurrentThread() {
161 thread_task_runner_handle_ =
Jeremy Roman9532f252017-08-16 23:27:24162 std::make_unique<ThreadTaskRunnerHandle>(simple_task_runner_);
Gabriel Charettea3ec9612017-12-14 17:22:40163 RunLoop::RegisterDelegateForCurrentThread(this);
Gabriel Charettee2b632b2017-08-02 03:52:16164 }
165
166 private:
Gabriel Charetteb030a4a2017-10-26 01:04:40167 void Run(bool application_tasks_allowed) override {
Gabriel Charette3ff403e2017-08-07 04:22:48168 if (nested_run_allowing_tasks_incoming_) {
Gabriel Charette1ef212b2017-12-03 12:47:21169 EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
Gabriel Charetteb030a4a2017-10-26 01:04:40170 EXPECT_TRUE(application_tasks_allowed);
Gabriel Charette1ef212b2017-12-03 12:47:21171 } else if (RunLoop::IsNestedOnCurrentThread()) {
Gabriel Charetteb030a4a2017-10-26 01:04:40172 EXPECT_FALSE(application_tasks_allowed);
Gabriel Charette3ff403e2017-08-07 04:22:48173 }
174 nested_run_allowing_tasks_incoming_ = false;
175
Gabriel Charettee2b632b2017-08-02 03:52:16176 while (!should_quit_) {
Gabriel Charette1ef212b2017-12-03 12:47:21177 if (application_tasks_allowed && simple_task_runner_->ProcessSingleTask())
Gabriel Charettee2b632b2017-08-02 03:52:16178 continue;
179
Gabriel Charettea3ec9612017-12-14 17:22:40180 if (ShouldQuitWhenIdle())
Gabriel Charettee2b632b2017-08-02 03:52:16181 break;
182
Gabriel Charette1ef212b2017-12-03 12:47:21183 if (RunInjectedClosure())
184 continue;
Gabriel Charette3ff403e2017-08-07 04:22:48185
Gabriel Charettee2b632b2017-08-02 03:52:16186 PlatformThread::YieldCurrentThread();
187 }
188 should_quit_ = false;
189 }
190
191 void Quit() override { should_quit_ = true; }
192
Gabriel Charette3ff403e2017-08-07 04:22:48193 void EnsureWorkScheduled() override {
194 nested_run_allowing_tasks_incoming_ = true;
195 }
196
197 // True if the next invocation of Run() is expected to be from a
198 // kNestableTasksAllowed RunLoop.
199 bool nested_run_allowing_tasks_incoming_ = false;
200
Gabriel Charettee2b632b2017-08-02 03:52:16201 scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
202 MakeRefCounted<SimpleSingleThreadTaskRunner>();
Gabriel Charette1ef212b2017-12-03 12:47:21203
Gabriel Charettee2b632b2017-08-02 03:52:16204 std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
205
206 bool should_quit_ = false;
Gabriel Charette1ef212b2017-12-03 12:47:21207};
208
209// A test RunLoop::Delegate meant to override an existing RunLoop::Delegate.
210// TakeOverCurrentThread() must be called before this TestBoundDelegate is
211// operational.
212class TestOverridingDelegate final : public InjectableTestDelegate {
213 public:
214 TestOverridingDelegate() = default;
215
216 // Overrides the existing RunLoop::Delegate and ThreadTaskRunnerHandles on
217 // this thread with this TestOverridingDelegate's.
218 void TakeOverCurrentThread() {
Gabriel Charettea3ec9612017-12-14 17:22:40219 overridden_task_runner_ = ThreadTaskRunnerHandle::Get();
220 ASSERT_TRUE(overridden_task_runner_);
Gabriel Charette1ef212b2017-12-03 12:47:21221 thread_task_runner_handle_override_scope_ =
222 ThreadTaskRunnerHandle::OverrideForTesting(
223 simple_task_runner_,
224 ThreadTaskRunnerHandle::OverrideType::kTakeOverThread);
225
Gabriel Charettea3ec9612017-12-14 17:22:40226 // TestOverridingDelegate::Run() is designed with the assumption that the
227 // overridden Delegate's Run() always returns control to it when it becomes
228 // idle.
229 overridden_delegate_ = RunLoop::OverrideDelegateForCurrentThreadForTesting(
230 this, base::BindRepeating([]() { return true; }));
231 ASSERT_TRUE(overridden_delegate_);
Gabriel Charette1ef212b2017-12-03 12:47:21232 }
233
234 private:
235 void Run(bool application_tasks_allowed) override {
236 while (!should_quit_) {
237 auto pending_tasks = simple_task_runner_->TakePendingTasks();
238 if (!pending_tasks.empty()) {
239 while (!pending_tasks.empty()) {
Gabriel Charettea3ec9612017-12-14 17:22:40240 overridden_task_runner_->PostTask(FROM_HERE,
241 std::move(pending_tasks.front()));
Gabriel Charette1ef212b2017-12-03 12:47:21242 pending_tasks.pop();
243 }
Gabriel Charettea3ec9612017-12-14 17:22:40244 overridden_delegate_->Run(application_tasks_allowed);
Gabriel Charette1ef212b2017-12-03 12:47:21245 continue;
246 }
247
Gabriel Charettea3ec9612017-12-14 17:22:40248 if (ShouldQuitWhenIdle())
Gabriel Charette1ef212b2017-12-03 12:47:21249 break;
250
251 if (RunInjectedClosure())
252 continue;
253
254 PlatformThread::YieldCurrentThread();
255 }
256 should_quit_ = false;
257 }
258
259 void Quit() override {
260 should_quit_ = true;
Gabriel Charettea3ec9612017-12-14 17:22:40261 overridden_delegate_->Quit();
Gabriel Charette1ef212b2017-12-03 12:47:21262 }
263
264 void EnsureWorkScheduled() override {
Gabriel Charettea3ec9612017-12-14 17:22:40265 overridden_delegate_->EnsureWorkScheduled();
Gabriel Charette1ef212b2017-12-03 12:47:21266 }
267
268 scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
269 MakeRefCounted<SimpleSingleThreadTaskRunner>();
270
271 ScopedClosureRunner thread_task_runner_handle_override_scope_;
272
Gabriel Charettea3ec9612017-12-14 17:22:40273 scoped_refptr<SingleThreadTaskRunner> overridden_task_runner_;
274 RunLoop::Delegate* overridden_delegate_;
Gabriel Charette1ef212b2017-12-03 12:47:21275
276 bool should_quit_ = false;
Gabriel Charettee2b632b2017-08-02 03:52:16277};
278
279enum class RunLoopTestType {
280 // Runs all RunLoopTests under a ScopedTaskEnvironment to make sure real world
281 // scenarios work.
282 kRealEnvironment,
283
284 // Runs all RunLoopTests under a test RunLoop::Delegate to make sure the
285 // delegate interface fully works standalone.
286 kTestDelegate,
Gabriel Charette1ef212b2017-12-03 12:47:21287
288 // Runs all RunLoopTests through a RunLoop::Delegate which overrides a
289 // kRealEnvironment's registered RunLoop::Delegate.
290 kOverridingTestDelegate,
Gabriel Charettee2b632b2017-08-02 03:52:16291};
292
293// The task environment for the RunLoopTest of a given type. A separate class
294// so it can be instantiated on the stack in the RunLoopTest fixture.
295class RunLoopTestEnvironment {
296 public:
297 RunLoopTestEnvironment(RunLoopTestType type) {
298 switch (type) {
Gabriel Charette1ef212b2017-12-03 12:47:21299 case RunLoopTestType::kRealEnvironment: {
Jeremy Roman9532f252017-08-16 23:27:24300 task_environment_ = std::make_unique<test::ScopedTaskEnvironment>();
Gabriel Charettee2b632b2017-08-02 03:52:16301 break;
Gabriel Charette1ef212b2017-12-03 12:47:21302 }
303 case RunLoopTestType::kTestDelegate: {
304 auto test_delegate = std::make_unique<TestBoundDelegate>();
305 test_delegate->BindToCurrentThread();
306 test_delegate_ = std::move(test_delegate);
Gabriel Charettee2b632b2017-08-02 03:52:16307 break;
Gabriel Charette1ef212b2017-12-03 12:47:21308 }
309 case RunLoopTestType::kOverridingTestDelegate: {
310 task_environment_ = std::make_unique<test::ScopedTaskEnvironment>();
311 auto test_delegate = std::make_unique<TestOverridingDelegate>();
312 test_delegate->TakeOverCurrentThread();
313 test_delegate_ = std::move(test_delegate);
314 break;
315 }
Gabriel Charettee2b632b2017-08-02 03:52:16316 }
317 }
318
319 private:
Gabriel Charette1ef212b2017-12-03 12:47:21320 // Instantiates one or the other based on the RunLoopTestType (or both in the
321 // kOverridingTestDelegate case).
Gabriel Charettee2b632b2017-08-02 03:52:16322 std::unique_ptr<test::ScopedTaskEnvironment> task_environment_;
Gabriel Charette1ef212b2017-12-03 12:47:21323 std::unique_ptr<InjectableTestDelegate> test_delegate_;
Gabriel Charettee2b632b2017-08-02 03:52:16324};
325
326class RunLoopTest : public testing::TestWithParam<RunLoopTestType> {
327 protected:
328 RunLoopTest() : test_environment_(GetParam()) {}
329
330 RunLoopTestEnvironment test_environment_;
fdoraya4f28ec2016-06-10 00:08:58331 RunLoop run_loop_;
332 int counter_ = 0;
333
334 private:
335 DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
336};
337
338} // namespace
339
Gabriel Charettee2b632b2017-08-02 03:52:16340TEST_P(RunLoopTest, QuitWhenIdle) {
gab7af9dc02017-05-05 13:38:54341 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:44342 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
343 Unretained(&counter_)));
gab7af9dc02017-05-05 13:38:54344 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:44345 FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
gab7af9dc02017-05-05 13:38:54346 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik92b7a422017-04-11 15:00:44347 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdoraya4f28ec2016-06-10 00:08:58348
349 run_loop_.Run();
350 EXPECT_EQ(2, counter_);
351}
352
Gabriel Charettee2b632b2017-08-02 03:52:16353TEST_P(RunLoopTest, QuitWhenIdleNestedLoop) {
gab7af9dc02017-05-05 13:38:54354 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:44355 FROM_HERE, BindOnce(&RunNestedLoopTask, Unretained(&counter_)));
gab7af9dc02017-05-05 13:38:54356 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:44357 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
358 Unretained(&counter_)));
gab7af9dc02017-05-05 13:38:54359 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:44360 FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
gab7af9dc02017-05-05 13:38:54361 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik92b7a422017-04-11 15:00:44362 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdoraya4f28ec2016-06-10 00:08:58363
364 run_loop_.Run();
365 EXPECT_EQ(4, counter_);
366}
367
Gabriel Charettee2b632b2017-08-02 03:52:16368TEST_P(RunLoopTest, QuitWhenIdleClosure) {
gab7af9dc02017-05-05 13:38:54369 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
370 run_loop_.QuitWhenIdleClosure());
371 ThreadTaskRunnerHandle::Get()->PostTask(
tzik92b7a422017-04-11 15:00:44372 FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
gab7af9dc02017-05-05 13:38:54373 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik92b7a422017-04-11 15:00:44374 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdoraya3658602016-06-10 18:23:15375
376 run_loop_.Run();
377 EXPECT_EQ(1, counter_);
378}
379
380// Verify that the QuitWhenIdleClosure() can run after the RunLoop has been
381// deleted. It should have no effect.
Gabriel Charettee2b632b2017-08-02 03:52:16382TEST_P(RunLoopTest, QuitWhenIdleClosureAfterRunLoopScope) {
fdoraya3658602016-06-10 18:23:15383 Closure quit_when_idle_closure;
384 {
385 RunLoop run_loop;
386 quit_when_idle_closure = run_loop.QuitWhenIdleClosure();
387 run_loop.RunUntilIdle();
388 }
389 quit_when_idle_closure.Run();
390}
391
gabcf5e4ce2017-05-19 22:56:57392// Verify that Quit can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16393TEST_P(RunLoopTest, QuitFromOtherSequence) {
394 Thread other_thread("test");
395 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57396 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16397 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57398
399 // Always expected to run before asynchronous Quit() kicks in.
400 ThreadTaskRunnerHandle::Get()->PostTask(
401 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
402
403 WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
404 WaitableEvent::InitialState::NOT_SIGNALED);
405 other_sequence->PostTask(
406 FROM_HERE, base::BindOnce([](RunLoop* run_loop) { run_loop->Quit(); },
407 Unretained(&run_loop_)));
408 other_sequence->PostTask(
409 FROM_HERE,
410 base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
411
412 // Anything that's posted after the Quit closure was posted back to this
413 // sequence shouldn't get a chance to run.
414 loop_was_quit.Wait();
Gabriel Charettee2b632b2017-08-02 03:52:16415 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
416 base::BindOnce(&ShouldNotRunTask));
gabcf5e4ce2017-05-19 22:56:57417
418 run_loop_.Run();
419
420 EXPECT_EQ(1, counter_);
421}
422
423// Verify that QuitClosure can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16424TEST_P(RunLoopTest, QuitFromOtherSequenceWithClosure) {
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
430 // Always expected to run before asynchronous Quit() kicks in.
431 ThreadTaskRunnerHandle::Get()->PostTask(
432 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
433
434 WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
435 WaitableEvent::InitialState::NOT_SIGNALED);
436 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
437 other_sequence->PostTask(
438 FROM_HERE,
439 base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
440
441 // Anything that's posted after the Quit closure was posted back to this
442 // sequence shouldn't get a chance to run.
443 loop_was_quit.Wait();
Gabriel Charettee2b632b2017-08-02 03:52:16444 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
445 base::BindOnce(&ShouldNotRunTask));
gabcf5e4ce2017-05-19 22:56:57446
447 run_loop_.Run();
448
449 EXPECT_EQ(1, counter_);
450}
451
452// Verify that Quit can be executed from another sequence even when the
453// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
Gabriel Charettee2b632b2017-08-02 03:52:16454TEST_P(RunLoopTest, QuitFromOtherSequenceRacy) {
455 Thread other_thread("test");
456 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57457 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16458 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57459
460 // Always expected to run before asynchronous Quit() kicks in.
461 ThreadTaskRunnerHandle::Get()->PostTask(
462 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
463
464 other_sequence->PostTask(
465 FROM_HERE, base::BindOnce([](RunLoop* run_loop) { run_loop->Quit(); },
466 Unretained(&run_loop_)));
467
468 run_loop_.Run();
469
470 EXPECT_EQ(1, counter_);
471}
472
473// Verify that QuitClosure can be executed from another sequence even when the
474// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
Gabriel Charettee2b632b2017-08-02 03:52:16475TEST_P(RunLoopTest, QuitFromOtherSequenceRacyWithClosure) {
476 Thread other_thread("test");
477 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57478 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16479 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57480
481 // Always expected to run before asynchronous Quit() kicks in.
482 ThreadTaskRunnerHandle::Get()->PostTask(
483 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
484
485 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
486
487 run_loop_.Run();
488
489 EXPECT_EQ(1, counter_);
490}
491
492// Verify that QuitWhenIdle can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16493TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequence) {
494 Thread other_thread("test");
495 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57496 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16497 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57498
499 ThreadTaskRunnerHandle::Get()->PostTask(
500 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
501
502 other_sequence->PostTask(
503 FROM_HERE,
504 base::BindOnce([](RunLoop* run_loop) { run_loop->QuitWhenIdle(); },
505 Unretained(&run_loop_)));
506
507 ThreadTaskRunnerHandle::Get()->PostTask(
508 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
509
510 run_loop_.Run();
511
512 // Regardless of the outcome of the race this thread shouldn't have been idle
513 // until the counter was ticked twice.
514 EXPECT_EQ(2, counter_);
515}
516
517// Verify that QuitWhenIdleClosure can be executed from another sequence.
Gabriel Charettee2b632b2017-08-02 03:52:16518TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequenceWithClosure) {
519 Thread other_thread("test");
520 other_thread.Start();
gabcf5e4ce2017-05-19 22:56:57521 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charettee2b632b2017-08-02 03:52:16522 other_thread.task_runner();
gabcf5e4ce2017-05-19 22:56:57523
524 ThreadTaskRunnerHandle::Get()->PostTask(
525 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
526
527 other_sequence->PostTask(FROM_HERE, run_loop_.QuitWhenIdleClosure());
528
529 ThreadTaskRunnerHandle::Get()->PostTask(
530 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
531
532 run_loop_.Run();
533
534 // Regardless of the outcome of the race this thread shouldn't have been idle
535 // until the counter was ticked twice.
536 EXPECT_EQ(2, counter_);
537}
538
Gabriel Charettee2b632b2017-08-02 03:52:16539TEST_P(RunLoopTest, IsRunningOnCurrentThread) {
gab7af9dc02017-05-05 13:38:54540 EXPECT_FALSE(RunLoop::IsRunningOnCurrentThread());
541 ThreadTaskRunnerHandle::Get()->PostTask(
542 FROM_HERE,
tzik0c100dc2017-06-26 06:13:17543 BindOnce([]() { EXPECT_TRUE(RunLoop::IsRunningOnCurrentThread()); }));
gab7af9dc02017-05-05 13:38:54544 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
545 run_loop_.Run();
546}
547
Gabriel Charettee2b632b2017-08-02 03:52:16548TEST_P(RunLoopTest, IsNestedOnCurrentThread) {
gab7af9dc02017-05-05 13:38:54549 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
550
551 ThreadTaskRunnerHandle::Get()->PostTask(
tzik0c100dc2017-06-26 06:13:17552 FROM_HERE, BindOnce([]() {
gab7af9dc02017-05-05 13:38:54553 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
554
Gabriel Charette3ff403e2017-08-07 04:22:48555 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
gab7af9dc02017-05-05 13:38:54556
557 ThreadTaskRunnerHandle::Get()->PostTask(
tzik0c100dc2017-06-26 06:13:17558 FROM_HERE, BindOnce([]() {
559 EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
560 }));
gab7af9dc02017-05-05 13:38:54561 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
562 nested_run_loop.QuitClosure());
563
564 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
gab7af9dc02017-05-05 13:38:54565 nested_run_loop.Run();
566 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
567 }));
568
569 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
570 run_loop_.Run();
571}
572
Francois Doray80bdddf2018-01-04 16:17:32573namespace {
574
gab7af9dc02017-05-05 13:38:54575class MockNestingObserver : public RunLoop::NestingObserver {
576 public:
577 MockNestingObserver() = default;
578
579 // RunLoop::NestingObserver:
580 MOCK_METHOD0(OnBeginNestedRunLoop, void());
Francois Doray80bdddf2018-01-04 16:17:32581 MOCK_METHOD0(OnExitNestedRunLoop, void());
gab7af9dc02017-05-05 13:38:54582
583 private:
584 DISALLOW_COPY_AND_ASSIGN(MockNestingObserver);
585};
586
Francois Doray80bdddf2018-01-04 16:17:32587class MockTask {
588 public:
589 MockTask() = default;
590 MOCK_METHOD0(Task, void());
591
592 private:
593 DISALLOW_COPY_AND_ASSIGN(MockTask);
594};
595
596} // namespace
597
Gabriel Charettee2b632b2017-08-02 03:52:16598TEST_P(RunLoopTest, NestingObservers) {
gab7af9dc02017-05-05 13:38:54599 testing::StrictMock<MockNestingObserver> nesting_observer;
Francois Doray80bdddf2018-01-04 16:17:32600 testing::StrictMock<MockTask> mock_task_a;
601 testing::StrictMock<MockTask> mock_task_b;
gab7af9dc02017-05-05 13:38:54602
603 RunLoop::AddNestingObserverOnCurrentThread(&nesting_observer);
604
605 const RepeatingClosure run_nested_loop = Bind([]() {
Gabriel Charette3ff403e2017-08-07 04:22:48606 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
gab7af9dc02017-05-05 13:38:54607 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
608 nested_run_loop.QuitClosure());
gab7af9dc02017-05-05 13:38:54609 nested_run_loop.Run();
610 });
611
Francois Doray80bdddf2018-01-04 16:17:32612 // Generate a stack of nested RunLoops. OnBeginNestedRunLoop() is expected
613 // when beginning each nesting depth and OnExitNestedRunLoop() is expected
Gabriel Charetted8839442018-03-15 18:56:22614 // when exiting each nesting depth. Each one of these tasks is ahead of the
615 // QuitClosures as those are only posted at the end of the queue when
616 // |run_nested_loop| is executed.
gab7af9dc02017-05-05 13:38:54617 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
Francois Doray80bdddf2018-01-04 16:17:32618 ThreadTaskRunnerHandle::Get()->PostTask(
619 FROM_HERE,
620 base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_a)));
gab7af9dc02017-05-05 13:38:54621 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
Francois Doray80bdddf2018-01-04 16:17:32622 ThreadTaskRunnerHandle::Get()->PostTask(
623 FROM_HERE,
624 base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_b)));
gab7af9dc02017-05-05 13:38:54625
Francois Doray80bdddf2018-01-04 16:17:32626 {
627 testing::InSequence in_sequence;
628 EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
629 EXPECT_CALL(mock_task_a, Task());
630 EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
631 EXPECT_CALL(mock_task_b, Task());
632 EXPECT_CALL(nesting_observer, OnExitNestedRunLoop()).Times(2);
633 }
634 run_loop_.RunUntilIdle();
gab7af9dc02017-05-05 13:38:54635
636 RunLoop::RemoveNestingObserverOnCurrentThread(&nesting_observer);
637}
638
Gabriel Charettea44975052017-08-21 23:14:04639TEST_P(RunLoopTest, DisallowRunningForTesting) {
640 RunLoop::ScopedDisallowRunningForTesting disallow_running;
641 EXPECT_DCHECK_DEATH({ run_loop_.Run(); });
642}
643
644TEST_P(RunLoopTest, ExpiredDisallowRunningForTesting) {
645 { RunLoop::ScopedDisallowRunningForTesting disallow_running; }
646 // Running should be fine after |disallow_running| goes out of scope.
647 run_loop_.RunUntilIdle();
648}
649
Gabriel Charettee2b632b2017-08-02 03:52:16650INSTANTIATE_TEST_CASE_P(Real,
651 RunLoopTest,
652 testing::Values(RunLoopTestType::kRealEnvironment));
653INSTANTIATE_TEST_CASE_P(Mock,
654 RunLoopTest,
655 testing::Values(RunLoopTestType::kTestDelegate));
Gabriel Charette1ef212b2017-12-03 12:47:21656INSTANTIATE_TEST_CASE_P(
657 OverridingMock,
658 RunLoopTest,
659 testing::Values(RunLoopTestType::kOverridingTestDelegate));
Gabriel Charettee2b632b2017-08-02 03:52:16660
661TEST(RunLoopDeathTest, MustRegisterBeforeInstantiating) {
Gabriel Charette1ef212b2017-12-03 12:47:21662 TestBoundDelegate unbound_test_delegate_;
Wez39ee6102018-04-14 21:33:59663 // RunLoop::RunLoop() should CHECK fetching the ThreadTaskRunnerHandle.
664 EXPECT_DEATH_IF_SUPPORTED({ RunLoop(); }, "");
Gabriel Charettee2b632b2017-08-02 03:52:16665}
666
Gabriel Charette3ff403e2017-08-07 04:22:48667TEST(RunLoopDelegateTest, NestableTasksDontRunInDefaultNestedLoops) {
Gabriel Charette1ef212b2017-12-03 12:47:21668 TestBoundDelegate test_delegate;
Gabriel Charette3ff403e2017-08-07 04:22:48669 test_delegate.BindToCurrentThread();
670
671 base::Thread other_thread("test");
672 other_thread.Start();
673
674 RunLoop main_loop;
675 // A nested run loop which isn't kNestableTasksAllowed.
676 RunLoop nested_run_loop(RunLoop::Type::kDefault);
677
678 bool nested_run_loop_ended = false;
679
680 // The first task on the main loop will result in a nested run loop. Since
681 // it's not kNestableTasksAllowed, no further task should be processed until
682 // it's quit.
683 ThreadTaskRunnerHandle::Get()->PostTask(
684 FROM_HERE,
685 BindOnce([](RunLoop* nested_run_loop) { nested_run_loop->Run(); },
686 Unretained(&nested_run_loop)));
687
688 // Post a task that will fail if it runs inside the nested run loop.
689 ThreadTaskRunnerHandle::Get()->PostTask(
690 FROM_HERE, BindOnce(
691 [](const bool& nested_run_loop_ended,
692 OnceClosure continuation_callback) {
693 EXPECT_TRUE(nested_run_loop_ended);
694 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
695 std::move(continuation_callback).Run();
696 },
697 ConstRef(nested_run_loop_ended), main_loop.QuitClosure()));
698
699 // Post a task flipping the boolean bit for extra verification right before
700 // quitting |nested_run_loop|.
701 other_thread.task_runner()->PostDelayedTask(
702 FROM_HERE,
703 BindOnce(
704 [](bool* nested_run_loop_ended) {
705 EXPECT_FALSE(*nested_run_loop_ended);
706 *nested_run_loop_ended = true;
707 },
708 Unretained(&nested_run_loop_ended)),
709 TestTimeouts::tiny_timeout());
710 // Post an async delayed task to exit the run loop when idle. This confirms
711 // that (1) the test task only ran in the main loop after the nested loop
712 // exited and (2) the nested run loop actually considers itself idle while
713 // spinning. Note: The quit closure needs to be injected directly on the
714 // delegate as invoking QuitWhenIdle() off-thread results in a thread bounce
715 // which will not processed because of the very logic under test (nestable
716 // tasks don't run in |nested_run_loop|).
717 other_thread.task_runner()->PostDelayedTask(
718 FROM_HERE,
719 BindOnce(
Gabriel Charette1ef212b2017-12-03 12:47:21720 [](TestBoundDelegate* test_delegate, OnceClosure injected_closure) {
721 test_delegate->InjectClosureOnDelegate(std::move(injected_closure));
Gabriel Charette3ff403e2017-08-07 04:22:48722 },
723 Unretained(&test_delegate), nested_run_loop.QuitWhenIdleClosure()),
724 TestTimeouts::tiny_timeout());
725
726 main_loop.Run();
727}
728
fdoraya4f28ec2016-06-10 00:08:58729} // namespace base