blob: 47896f4301a615fb7dd8ef05ce6b72661aa9dee4 [file] [log] [blame]
fdorayf36496f2016-06-10 09:08:58 +09001// 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 Charette31fc1322017-08-02 12:52:16 +09007#include <queue>
8#include <utility>
9
fdorayf36496f2016-06-10 09:08:58 +090010#include "base/bind.h"
11#include "base/bind_helpers.h"
12#include "base/location.h"
13#include "base/macros.h"
Gabriel Charette31fc1322017-08-02 12:52:16 +090014#include "base/memory/ptr_util.h"
15#include "base/memory/ref_counted.h"
fdorayf36496f2016-06-10 09:08:58 +090016#include "base/single_thread_task_runner.h"
Gabriel Charette31fc1322017-08-02 12:52:16 +090017#include "base/synchronization/lock.h"
gab7e2af5c2017-05-20 07:56:57 +090018#include "base/synchronization/waitable_event.h"
Gabriel Charette31fc1322017-08-02 12:52:16 +090019#include "base/test/gtest_util.h"
gab7e2af5c2017-05-20 07:56:57 +090020#include "base/test/scoped_task_environment.h"
Gabriel Charette31fc1322017-08-02 12:52:16 +090021#include "base/threading/platform_thread.h"
22#include "base/threading/thread.h"
23#include "base/threading/thread_checker_impl.h"
fdorayf36496f2016-06-10 09:08:58 +090024#include "base/threading/thread_task_runner_handle.h"
Gabriel Charette31fc1322017-08-02 12:52:16 +090025#include "build/build_config.h"
gab029f59e2017-05-05 22:38:54 +090026#include "testing/gmock/include/gmock/gmock.h"
fdorayf36496f2016-06-10 09:08:58 +090027#include "testing/gtest/include/gtest/gtest.h"
28
29namespace base {
30
31namespace {
32
33void QuitWhenIdleTask(RunLoop* run_loop, int* counter) {
34 run_loop->QuitWhenIdle();
35 ++(*counter);
36}
37
38void ShouldRunTask(int* counter) {
39 ++(*counter);
40}
41
42void ShouldNotRunTask() {
43 ADD_FAILURE() << "Ran a task that shouldn't run.";
44}
45
46void RunNestedLoopTask(int* counter) {
47 RunLoop nested_run_loop;
48
49 // This task should quit |nested_run_loop| but not the main RunLoop.
50 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +090051 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&nested_run_loop),
52 Unretained(counter)));
fdorayf36496f2016-06-10 09:08:58 +090053
54 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik6bdbeb22017-04-12 00:00:44 +090055 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdorayf36496f2016-06-10 09:08:58 +090056
Gabriel Charette31fc1322017-08-02 12:52:16 +090057 std::unique_ptr<MessageLoop::ScopedNestableTaskAllower> allower;
58 if (MessageLoop::current()) {
59 // Need to allow nestable tasks in MessageLoop driven environments.
60 // TODO(gab): Move nestable task allowance concept to RunLoop.
61 allower = base::MakeUnique<MessageLoop::ScopedNestableTaskAllower>(
62 MessageLoop::current());
63 }
fdorayf36496f2016-06-10 09:08:58 +090064 nested_run_loop.Run();
65
66 ++(*counter);
67}
68
Gabriel Charette31fc1322017-08-02 12:52:16 +090069// A simple SingleThreadTaskRunner that just queues undelayed tasks (and ignores
70// delayed tasks). Tasks can then be processed one by one by ProcessTask() which
71// will return true if it processed a task and false otherwise.
72class SimpleSingleThreadTaskRunner : public SingleThreadTaskRunner {
73 public:
74 SimpleSingleThreadTaskRunner() = default;
fdorayf36496f2016-06-10 09:08:58 +090075
Gabriel Charette31fc1322017-08-02 12:52:16 +090076 bool PostDelayedTask(const tracked_objects::Location& from_here,
77 OnceClosure task,
78 base::TimeDelta delay) override {
79 if (delay > base::TimeDelta())
80 return false;
81 AutoLock auto_lock(tasks_lock_);
82 pending_tasks_.push(std::move(task));
83 return true;
84 }
85
86 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
87 OnceClosure task,
88 base::TimeDelta delay) override {
89 return PostDelayedTask(from_here, std::move(task), delay);
90 }
91
92 bool RunsTasksInCurrentSequence() const override {
93 return origin_thread_checker_.CalledOnValidThread();
94 }
95
96 bool ProcessTask() {
97 OnceClosure task;
98 {
99 AutoLock auto_lock(tasks_lock_);
100 if (pending_tasks_.empty())
101 return false;
102 task = std::move(pending_tasks_.front());
103 pending_tasks_.pop();
104 }
105 // It's important to Run() after pop() and outside the lock as |task| may
106 // run a nested loop which will re-enter ProcessTask().
107 std::move(task).Run();
108 return true;
109 }
110
111 private:
112 ~SimpleSingleThreadTaskRunner() override = default;
113
114 Lock tasks_lock_;
115 std::queue<OnceClosure> pending_tasks_;
116
117 // RunLoop relies on RunsTasksInCurrentSequence() signal. Use a
118 // ThreadCheckerImpl to be able to reliably provide that signal even in
119 // non-dcheck builds.
120 ThreadCheckerImpl origin_thread_checker_;
121
122 DISALLOW_COPY_AND_ASSIGN(SimpleSingleThreadTaskRunner);
123};
124
125// A simple test RunLoop::Delegate to exercise Runloop logic independent of any
126// other base constructs.
127class TestDelegate : public RunLoop::Delegate {
128 public:
129 TestDelegate() = default;
130
131 void BindToCurrentThread() {
132 thread_task_runner_handle_ =
133 MakeUnique<ThreadTaskRunnerHandle>(simple_task_runner_);
134 run_loop_client_ = RunLoop::RegisterDelegateForCurrentThread(this);
135 }
136
137 private:
138 void Run() override {
139 while (!should_quit_) {
140 if (simple_task_runner_->ProcessTask())
141 continue;
142
143 if (run_loop_client_->ShouldQuitWhenIdle())
144 break;
145
146 PlatformThread::YieldCurrentThread();
147 }
148 should_quit_ = false;
149 }
150
151 void Quit() override { should_quit_ = true; }
152
153 scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
154 MakeRefCounted<SimpleSingleThreadTaskRunner>();
155 std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
156
157 bool should_quit_ = false;
158
159 RunLoop::Delegate::Client* run_loop_client_ = nullptr;
160};
161
162enum class RunLoopTestType {
163 // Runs all RunLoopTests under a ScopedTaskEnvironment to make sure real world
164 // scenarios work.
165 kRealEnvironment,
166
167 // Runs all RunLoopTests under a test RunLoop::Delegate to make sure the
168 // delegate interface fully works standalone.
169 kTestDelegate,
170};
171
172// The task environment for the RunLoopTest of a given type. A separate class
173// so it can be instantiated on the stack in the RunLoopTest fixture.
174class RunLoopTestEnvironment {
175 public:
176 RunLoopTestEnvironment(RunLoopTestType type) {
177 switch (type) {
178 case RunLoopTestType::kRealEnvironment:
179 task_environment_ = base::MakeUnique<test::ScopedTaskEnvironment>();
180 break;
181 case RunLoopTestType::kTestDelegate:
182 test_delegate_ = base::MakeUnique<TestDelegate>();
183 test_delegate_->BindToCurrentThread();
184 break;
185 }
186 }
187
188 private:
189 // Instantiates one or the other based on the RunLoopTestType.
190 std::unique_ptr<test::ScopedTaskEnvironment> task_environment_;
191 std::unique_ptr<TestDelegate> test_delegate_;
192};
193
194class RunLoopTest : public testing::TestWithParam<RunLoopTestType> {
195 protected:
196 RunLoopTest() : test_environment_(GetParam()) {}
197
198 RunLoopTestEnvironment test_environment_;
fdorayf36496f2016-06-10 09:08:58 +0900199 RunLoop run_loop_;
200 int counter_ = 0;
201
202 private:
203 DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
204};
205
206} // namespace
207
Gabriel Charette31fc1322017-08-02 12:52:16 +0900208TEST_P(RunLoopTest, QuitWhenIdle) {
gab029f59e2017-05-05 22:38:54 +0900209 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900210 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
211 Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900212 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900213 FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900214 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik6bdbeb22017-04-12 00:00:44 +0900215 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdorayf36496f2016-06-10 09:08:58 +0900216
217 run_loop_.Run();
218 EXPECT_EQ(2, counter_);
219}
220
Gabriel Charette31fc1322017-08-02 12:52:16 +0900221TEST_P(RunLoopTest, QuitWhenIdleNestedLoop) {
gab029f59e2017-05-05 22:38:54 +0900222 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900223 FROM_HERE, BindOnce(&RunNestedLoopTask, Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900224 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900225 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
226 Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900227 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900228 FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900229 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik6bdbeb22017-04-12 00:00:44 +0900230 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdorayf36496f2016-06-10 09:08:58 +0900231
232 run_loop_.Run();
233 EXPECT_EQ(4, counter_);
234}
235
Gabriel Charette31fc1322017-08-02 12:52:16 +0900236TEST_P(RunLoopTest, QuitWhenIdleClosure) {
gab029f59e2017-05-05 22:38:54 +0900237 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
238 run_loop_.QuitWhenIdleClosure());
239 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900240 FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900241 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik6bdbeb22017-04-12 00:00:44 +0900242 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdoray995fbe12016-06-11 03:23:15 +0900243
244 run_loop_.Run();
245 EXPECT_EQ(1, counter_);
246}
247
248// Verify that the QuitWhenIdleClosure() can run after the RunLoop has been
249// deleted. It should have no effect.
Gabriel Charette31fc1322017-08-02 12:52:16 +0900250TEST_P(RunLoopTest, QuitWhenIdleClosureAfterRunLoopScope) {
fdoray995fbe12016-06-11 03:23:15 +0900251 Closure quit_when_idle_closure;
252 {
253 RunLoop run_loop;
254 quit_when_idle_closure = run_loop.QuitWhenIdleClosure();
255 run_loop.RunUntilIdle();
256 }
257 quit_when_idle_closure.Run();
258}
259
gab7e2af5c2017-05-20 07:56:57 +0900260// Verify that Quit can be executed from another sequence.
Gabriel Charette31fc1322017-08-02 12:52:16 +0900261TEST_P(RunLoopTest, QuitFromOtherSequence) {
262 Thread other_thread("test");
263 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900264 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900265 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900266
267 // Always expected to run before asynchronous Quit() kicks in.
268 ThreadTaskRunnerHandle::Get()->PostTask(
269 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
270
271 WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
272 WaitableEvent::InitialState::NOT_SIGNALED);
273 other_sequence->PostTask(
274 FROM_HERE, base::BindOnce([](RunLoop* run_loop) { run_loop->Quit(); },
275 Unretained(&run_loop_)));
276 other_sequence->PostTask(
277 FROM_HERE,
278 base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
279
280 // Anything that's posted after the Quit closure was posted back to this
281 // sequence shouldn't get a chance to run.
282 loop_was_quit.Wait();
Gabriel Charette31fc1322017-08-02 12:52:16 +0900283 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
284 base::BindOnce(&ShouldNotRunTask));
gab7e2af5c2017-05-20 07:56:57 +0900285
286 run_loop_.Run();
287
288 EXPECT_EQ(1, counter_);
289}
290
291// Verify that QuitClosure can be executed from another sequence.
Gabriel Charette31fc1322017-08-02 12:52:16 +0900292TEST_P(RunLoopTest, QuitFromOtherSequenceWithClosure) {
293 Thread other_thread("test");
294 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900295 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900296 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900297
298 // Always expected to run before asynchronous Quit() kicks in.
299 ThreadTaskRunnerHandle::Get()->PostTask(
300 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
301
302 WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
303 WaitableEvent::InitialState::NOT_SIGNALED);
304 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
305 other_sequence->PostTask(
306 FROM_HERE,
307 base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
308
309 // Anything that's posted after the Quit closure was posted back to this
310 // sequence shouldn't get a chance to run.
311 loop_was_quit.Wait();
Gabriel Charette31fc1322017-08-02 12:52:16 +0900312 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
313 base::BindOnce(&ShouldNotRunTask));
gab7e2af5c2017-05-20 07:56:57 +0900314
315 run_loop_.Run();
316
317 EXPECT_EQ(1, counter_);
318}
319
320// Verify that Quit can be executed from another sequence even when the
321// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
Gabriel Charette31fc1322017-08-02 12:52:16 +0900322TEST_P(RunLoopTest, QuitFromOtherSequenceRacy) {
323 Thread other_thread("test");
324 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900325 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900326 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900327
328 // Always expected to run before asynchronous Quit() kicks in.
329 ThreadTaskRunnerHandle::Get()->PostTask(
330 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
331
332 other_sequence->PostTask(
333 FROM_HERE, base::BindOnce([](RunLoop* run_loop) { run_loop->Quit(); },
334 Unretained(&run_loop_)));
335
336 run_loop_.Run();
337
338 EXPECT_EQ(1, counter_);
339}
340
341// Verify that QuitClosure can be executed from another sequence even when the
342// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
Gabriel Charette31fc1322017-08-02 12:52:16 +0900343TEST_P(RunLoopTest, QuitFromOtherSequenceRacyWithClosure) {
344 Thread other_thread("test");
345 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900346 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900347 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900348
349 // Always expected to run before asynchronous Quit() kicks in.
350 ThreadTaskRunnerHandle::Get()->PostTask(
351 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
352
353 other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
354
355 run_loop_.Run();
356
357 EXPECT_EQ(1, counter_);
358}
359
360// Verify that QuitWhenIdle can be executed from another sequence.
Gabriel Charette31fc1322017-08-02 12:52:16 +0900361TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequence) {
362 Thread other_thread("test");
363 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900364 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900365 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900366
367 ThreadTaskRunnerHandle::Get()->PostTask(
368 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
369
370 other_sequence->PostTask(
371 FROM_HERE,
372 base::BindOnce([](RunLoop* run_loop) { run_loop->QuitWhenIdle(); },
373 Unretained(&run_loop_)));
374
375 ThreadTaskRunnerHandle::Get()->PostTask(
376 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
377
378 run_loop_.Run();
379
380 // Regardless of the outcome of the race this thread shouldn't have been idle
381 // until the counter was ticked twice.
382 EXPECT_EQ(2, counter_);
383}
384
385// Verify that QuitWhenIdleClosure can be executed from another sequence.
Gabriel Charette31fc1322017-08-02 12:52:16 +0900386TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequenceWithClosure) {
387 Thread other_thread("test");
388 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900389 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900390 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900391
392 ThreadTaskRunnerHandle::Get()->PostTask(
393 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
394
395 other_sequence->PostTask(FROM_HERE, run_loop_.QuitWhenIdleClosure());
396
397 ThreadTaskRunnerHandle::Get()->PostTask(
398 FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
399
400 run_loop_.Run();
401
402 // Regardless of the outcome of the race this thread shouldn't have been idle
403 // until the counter was ticked twice.
404 EXPECT_EQ(2, counter_);
405}
406
Gabriel Charette31fc1322017-08-02 12:52:16 +0900407TEST_P(RunLoopTest, IsRunningOnCurrentThread) {
gab029f59e2017-05-05 22:38:54 +0900408 EXPECT_FALSE(RunLoop::IsRunningOnCurrentThread());
409 ThreadTaskRunnerHandle::Get()->PostTask(
410 FROM_HERE,
tzik330d83f2017-06-26 15:13:17 +0900411 BindOnce([]() { EXPECT_TRUE(RunLoop::IsRunningOnCurrentThread()); }));
gab029f59e2017-05-05 22:38:54 +0900412 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
413 run_loop_.Run();
414}
415
Gabriel Charette31fc1322017-08-02 12:52:16 +0900416TEST_P(RunLoopTest, IsNestedOnCurrentThread) {
gab029f59e2017-05-05 22:38:54 +0900417 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
418
419 ThreadTaskRunnerHandle::Get()->PostTask(
tzik330d83f2017-06-26 15:13:17 +0900420 FROM_HERE, BindOnce([]() {
gab029f59e2017-05-05 22:38:54 +0900421 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
422
423 RunLoop nested_run_loop;
424
425 ThreadTaskRunnerHandle::Get()->PostTask(
tzik330d83f2017-06-26 15:13:17 +0900426 FROM_HERE, BindOnce([]() {
427 EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
428 }));
gab029f59e2017-05-05 22:38:54 +0900429 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
430 nested_run_loop.QuitClosure());
431
432 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
Gabriel Charette31fc1322017-08-02 12:52:16 +0900433 std::unique_ptr<MessageLoop::ScopedNestableTaskAllower> allower;
434 if (MessageLoop::current()) {
435 // Need to allow nestable tasks in MessageLoop driven environments.
436 // TODO(gab): Move nestable task allowance concept to RunLoop.
437 allower = base::MakeUnique<MessageLoop::ScopedNestableTaskAllower>(
438 MessageLoop::current());
439 }
gab029f59e2017-05-05 22:38:54 +0900440 nested_run_loop.Run();
441 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
442 }));
443
444 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
445 run_loop_.Run();
446}
447
448class MockNestingObserver : public RunLoop::NestingObserver {
449 public:
450 MockNestingObserver() = default;
451
452 // RunLoop::NestingObserver:
453 MOCK_METHOD0(OnBeginNestedRunLoop, void());
454
455 private:
456 DISALLOW_COPY_AND_ASSIGN(MockNestingObserver);
457};
458
Gabriel Charette31fc1322017-08-02 12:52:16 +0900459TEST_P(RunLoopTest, NestingObservers) {
gab029f59e2017-05-05 22:38:54 +0900460 EXPECT_TRUE(RunLoop::IsNestingAllowedOnCurrentThread());
461
462 testing::StrictMock<MockNestingObserver> nesting_observer;
463
464 RunLoop::AddNestingObserverOnCurrentThread(&nesting_observer);
465
466 const RepeatingClosure run_nested_loop = Bind([]() {
467 RunLoop nested_run_loop;
468 ThreadTaskRunnerHandle::Get()->PostTask(
tzik330d83f2017-06-26 15:13:17 +0900469 FROM_HERE, BindOnce([]() {
gab029f59e2017-05-05 22:38:54 +0900470 EXPECT_TRUE(RunLoop::IsNestingAllowedOnCurrentThread());
471 }));
472 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
473 nested_run_loop.QuitClosure());
Gabriel Charette31fc1322017-08-02 12:52:16 +0900474 std::unique_ptr<MessageLoop::ScopedNestableTaskAllower> allower;
475 if (MessageLoop::current()) {
476 // Need to allow nestable tasks in MessageLoop driven environments.
477 // TODO(gab): Move nestable task allowance concept to RunLoop.
478 allower = base::MakeUnique<MessageLoop::ScopedNestableTaskAllower>(
479 MessageLoop::current());
480 }
gab029f59e2017-05-05 22:38:54 +0900481 nested_run_loop.Run();
482 });
483
484 // Generate a stack of nested RunLoops, an OnBeginNestedRunLoop() is
485 // expected when beginning each nesting depth.
486 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
487 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
488 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
489
490 EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop()).Times(2);
491 run_loop_.Run();
492
493 RunLoop::RemoveNestingObserverOnCurrentThread(&nesting_observer);
494}
495
496// Disabled on Android per http://crbug.com/643760.
497#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
Gabriel Charette31fc1322017-08-02 12:52:16 +0900498TEST_P(RunLoopTest, DisallowNestingDeathTest) {
gab029f59e2017-05-05 22:38:54 +0900499 EXPECT_TRUE(RunLoop::IsNestingAllowedOnCurrentThread());
500 RunLoop::DisallowNestingOnCurrentThread();
501 EXPECT_FALSE(RunLoop::IsNestingAllowedOnCurrentThread());
502
tzik330d83f2017-06-26 15:13:17 +0900503 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, BindOnce([]() {
gab029f59e2017-05-05 22:38:54 +0900504 RunLoop nested_run_loop;
505 nested_run_loop.RunUntilIdle();
506 }));
gab9e917e82017-05-06 04:24:10 +0900507 EXPECT_DEATH({ run_loop_.RunUntilIdle(); }, "");
gab029f59e2017-05-05 22:38:54 +0900508}
509#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
510
Gabriel Charette31fc1322017-08-02 12:52:16 +0900511INSTANTIATE_TEST_CASE_P(Real,
512 RunLoopTest,
513 testing::Values(RunLoopTestType::kRealEnvironment));
514INSTANTIATE_TEST_CASE_P(Mock,
515 RunLoopTest,
516 testing::Values(RunLoopTestType::kTestDelegate));
517
518TEST(RunLoopDeathTest, MustRegisterBeforeInstantiating) {
519 TestDelegate unbound_test_delegate_;
520 // Exercise the DCHECK in RunLoop::RunLoop().
521 EXPECT_DCHECK_DEATH({ RunLoop(); });
522}
523
fdorayf36496f2016-06-10 09:08:58 +0900524} // namespace base