[M94 Dev][Tizen] Fix for errors for generating ninja files
[platform/framework/web/chromium-efl.git] / base / run_loop_unittest.cc
1 // 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
7 #include <functional>
8 #include <memory>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/containers/queue.h"
14 #include "base/location.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/synchronization/lock.h"
19 #include "base/synchronization/waitable_event.h"
20 #include "base/test/bind.h"
21 #include "base/test/gtest_util.h"
22 #include "base/test/scoped_run_loop_timeout.h"
23 #include "base/test/task_environment.h"
24 #include "base/test/test_timeouts.h"
25 #include "base/threading/platform_thread.h"
26 #include "base/threading/sequenced_task_runner_handle.h"
27 #include "base/threading/thread.h"
28 #include "base/threading/thread_checker_impl.h"
29 #include "base/threading/thread_task_runner_handle.h"
30 #include "build/build_config.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33
34 namespace base {
35
36 namespace {
37
38 void QuitWhenIdleTask(RunLoop* run_loop, int* counter) {
39   run_loop->QuitWhenIdle();
40   ++(*counter);
41 }
42
43 void RunNestedLoopTask(int* counter) {
44   RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
45
46   // This task should quit |nested_run_loop| but not the main RunLoop.
47   ThreadTaskRunnerHandle::Get()->PostTask(
48       FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&nested_run_loop),
49                           Unretained(counter)));
50
51   ThreadTaskRunnerHandle::Get()->PostDelayedTask(
52       FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), TimeDelta::FromDays(1));
53
54   nested_run_loop.Run();
55
56   ++(*counter);
57 }
58
59 // A simple SingleThreadTaskRunner that just queues undelayed tasks (and ignores
60 // delayed tasks). Tasks can then be processed one by one by ProcessTask() which
61 // will return true if it processed a task and false otherwise.
62 class SimpleSingleThreadTaskRunner : public SingleThreadTaskRunner {
63  public:
64   SimpleSingleThreadTaskRunner() = default;
65   SimpleSingleThreadTaskRunner(const SimpleSingleThreadTaskRunner&) = delete;
66   SimpleSingleThreadTaskRunner& operator=(const SimpleSingleThreadTaskRunner&) =
67       delete;
68
69   bool PostDelayedTask(const Location& from_here,
70                        OnceClosure task,
71                        base::TimeDelta delay) override {
72     if (delay > base::TimeDelta())
73       return false;
74     AutoLock auto_lock(tasks_lock_);
75     pending_tasks_.push(std::move(task));
76     return true;
77   }
78
79   bool PostNonNestableDelayedTask(const Location& from_here,
80                                   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
89   bool ProcessSingleTask() {
90     OnceClosure task;
91     {
92       AutoLock auto_lock(tasks_lock_);
93       if (pending_tasks_.empty())
94         return false;
95       task = std::move(pending_tasks_.front());
96       pending_tasks_.pop();
97     }
98     // It's important to Run() after pop() and outside the lock as |task| may
99     // run a nested loop which will re-enter ProcessSingleTask().
100     std::move(task).Run();
101     return true;
102   }
103
104  private:
105   ~SimpleSingleThreadTaskRunner() override = default;
106
107   Lock tasks_lock_;
108   base::queue<OnceClosure> pending_tasks_;
109
110   // RunLoop relies on RunsTasksInCurrentSequence() signal. Use a
111   // ThreadCheckerImpl to be able to reliably provide that signal even in
112   // non-dcheck builds.
113   ThreadCheckerImpl origin_thread_checker_;
114 };
115
116 // The basis of all TestDelegates, allows safely injecting a OnceClosure to be
117 // run in the next idle phase of this delegate's Run() implementation. This can
118 // be used to have code run on a thread that is otherwise livelocked in an idle
119 // phase (sometimes a simple PostTask() won't do it -- e.g. when processing
120 // application tasks is disallowed).
121 class InjectableTestDelegate : public RunLoop::Delegate {
122  public:
123   void InjectClosureOnDelegate(OnceClosure closure) {
124     AutoLock auto_lock(closure_lock_);
125     closure_ = std::move(closure);
126   }
127
128   bool RunInjectedClosure() {
129     AutoLock auto_lock(closure_lock_);
130     if (closure_.is_null())
131       return false;
132     std::move(closure_).Run();
133     return true;
134   }
135
136  private:
137   Lock closure_lock_;
138   OnceClosure closure_;
139 };
140
141 // A simple test RunLoop::Delegate to exercise Runloop logic independent of any
142 // other base constructs. BindToCurrentThread() must be called before this
143 // TestBoundDelegate is operational.
144 class TestBoundDelegate final : public InjectableTestDelegate {
145  public:
146   TestBoundDelegate() = default;
147
148   // Makes this TestBoundDelegate become the RunLoop::Delegate and
149   // ThreadTaskRunnerHandle for this thread.
150   void BindToCurrentThread() {
151     thread_task_runner_handle_ =
152         std::make_unique<ThreadTaskRunnerHandle>(simple_task_runner_);
153     RunLoop::RegisterDelegateForCurrentThread(this);
154   }
155
156  private:
157   void Run(bool application_tasks_allowed, TimeDelta timeout) override {
158     if (nested_run_allowing_tasks_incoming_) {
159       EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
160       EXPECT_TRUE(application_tasks_allowed);
161     } else if (RunLoop::IsNestedOnCurrentThread()) {
162       EXPECT_FALSE(application_tasks_allowed);
163     }
164     nested_run_allowing_tasks_incoming_ = false;
165
166     while (!should_quit_) {
167       if (application_tasks_allowed && simple_task_runner_->ProcessSingleTask())
168         continue;
169
170       if (ShouldQuitWhenIdle())
171         break;
172
173       if (RunInjectedClosure())
174         continue;
175
176       PlatformThread::YieldCurrentThread();
177     }
178     should_quit_ = false;
179   }
180
181   void Quit() override { should_quit_ = true; }
182
183   void EnsureWorkScheduled() override {
184     nested_run_allowing_tasks_incoming_ = true;
185   }
186
187   // True if the next invocation of Run() is expected to be from a
188   // kNestableTasksAllowed RunLoop.
189   bool nested_run_allowing_tasks_incoming_ = false;
190
191   scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
192       MakeRefCounted<SimpleSingleThreadTaskRunner>();
193
194   std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
195
196   bool should_quit_ = false;
197 };
198
199 enum class RunLoopTestType {
200   // Runs all RunLoopTests under a TaskEnvironment to make sure real world
201   // scenarios work.
202   kRealEnvironment,
203
204   // Runs all RunLoopTests under a test RunLoop::Delegate to make sure the
205   // delegate interface fully works standalone.
206   kTestDelegate,
207 };
208
209 // The task environment for the RunLoopTest of a given type. A separate class
210 // so it can be instantiated on the stack in the RunLoopTest fixture.
211 class RunLoopTestEnvironment {
212  public:
213   explicit RunLoopTestEnvironment(RunLoopTestType type) {
214     switch (type) {
215       case RunLoopTestType::kRealEnvironment: {
216         task_environment_ = std::make_unique<test::TaskEnvironment>();
217         break;
218       }
219       case RunLoopTestType::kTestDelegate: {
220         auto test_delegate = std::make_unique<TestBoundDelegate>();
221         test_delegate->BindToCurrentThread();
222         test_delegate_ = std::move(test_delegate);
223         break;
224       }
225     }
226   }
227
228  private:
229   // Instantiates one or the other based on the RunLoopTestType.
230   std::unique_ptr<test::TaskEnvironment> task_environment_;
231   std::unique_ptr<InjectableTestDelegate> test_delegate_;
232 };
233
234 class RunLoopTest : public testing::TestWithParam<RunLoopTestType> {
235  public:
236   RunLoopTest(const RunLoopTest&) = delete;
237   RunLoopTest& operator=(const RunLoopTest&) = delete;
238
239  protected:
240   RunLoopTest() : test_environment_(GetParam()) {}
241
242   RunLoopTestEnvironment test_environment_;
243   RunLoop run_loop_;
244 };
245
246 }  // namespace
247
248 TEST_P(RunLoopTest, QuitWhenIdle) {
249   int counter = 0;
250   ThreadTaskRunnerHandle::Get()->PostTask(
251       FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
252                           Unretained(&counter)));
253   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
254                                           MakeExpectedRunClosure(FROM_HERE));
255   ThreadTaskRunnerHandle::Get()->PostDelayedTask(
256       FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), TimeDelta::FromDays(1));
257
258   run_loop_.Run();
259   EXPECT_EQ(1, counter);
260 }
261
262 TEST_P(RunLoopTest, QuitWhenIdleNestedLoop) {
263   int counter = 0;
264   ThreadTaskRunnerHandle::Get()->PostTask(
265       FROM_HERE, BindOnce(&RunNestedLoopTask, Unretained(&counter)));
266   ThreadTaskRunnerHandle::Get()->PostTask(
267       FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
268                           Unretained(&counter)));
269   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
270                                           MakeExpectedRunClosure(FROM_HERE));
271   ThreadTaskRunnerHandle::Get()->PostDelayedTask(
272       FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), TimeDelta::FromDays(1));
273
274   run_loop_.Run();
275   EXPECT_EQ(3, counter);
276 }
277
278 TEST_P(RunLoopTest, QuitWhenIdleClosure) {
279   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
280                                           run_loop_.QuitWhenIdleClosure());
281   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
282                                           MakeExpectedRunClosure(FROM_HERE));
283   ThreadTaskRunnerHandle::Get()->PostDelayedTask(
284       FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), TimeDelta::FromDays(1));
285
286   run_loop_.Run();
287 }
288
289 // Verify that the QuitWhenIdleClosure() can run after the RunLoop has been
290 // deleted. It should have no effect.
291 TEST_P(RunLoopTest, QuitWhenIdleClosureAfterRunLoopScope) {
292   RepeatingClosure quit_when_idle_closure;
293   {
294     RunLoop run_loop;
295     quit_when_idle_closure = run_loop.QuitWhenIdleClosure();
296     run_loop.RunUntilIdle();
297   }
298   quit_when_idle_closure.Run();
299 }
300
301 // Verify that Quit can be executed from another sequence.
302 TEST_P(RunLoopTest, QuitFromOtherSequence) {
303   Thread other_thread("test");
304   other_thread.Start();
305   scoped_refptr<SequencedTaskRunner> other_sequence =
306       other_thread.task_runner();
307
308   // Always expected to run before asynchronous Quit() kicks in.
309   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
310                                           MakeExpectedRunClosure(FROM_HERE));
311
312   WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
313                               WaitableEvent::InitialState::NOT_SIGNALED);
314   other_sequence->PostTask(
315       FROM_HERE, base::BindOnce([](RunLoop* run_loop) { run_loop->Quit(); },
316                                 Unretained(&run_loop_)));
317   other_sequence->PostTask(
318       FROM_HERE,
319       base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
320
321   // Anything that's posted after the Quit closure was posted back to this
322   // sequence shouldn't get a chance to run.
323   loop_was_quit.Wait();
324   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
325                                           MakeExpectedNotRunClosure(FROM_HERE));
326
327   run_loop_.Run();
328 }
329
330 // Verify that QuitClosure can be executed from another sequence.
331 TEST_P(RunLoopTest, QuitFromOtherSequenceWithClosure) {
332   Thread other_thread("test");
333   other_thread.Start();
334   scoped_refptr<SequencedTaskRunner> other_sequence =
335       other_thread.task_runner();
336
337   // Always expected to run before asynchronous Quit() kicks in.
338   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
339                                           MakeExpectedRunClosure(FROM_HERE));
340
341   WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
342                               WaitableEvent::InitialState::NOT_SIGNALED);
343   other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
344   other_sequence->PostTask(
345       FROM_HERE,
346       base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
347
348   // Anything that's posted after the Quit closure was posted back to this
349   // sequence shouldn't get a chance to run.
350   loop_was_quit.Wait();
351   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
352                                           MakeExpectedNotRunClosure(FROM_HERE));
353
354   run_loop_.Run();
355 }
356
357 // Verify that Quit can be executed from another sequence even when the
358 // Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
359 TEST_P(RunLoopTest, QuitFromOtherSequenceRacy) {
360   Thread other_thread("test");
361   other_thread.Start();
362   scoped_refptr<SequencedTaskRunner> other_sequence =
363       other_thread.task_runner();
364
365   // Always expected to run before asynchronous Quit() kicks in.
366   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
367                                           MakeExpectedRunClosure(FROM_HERE));
368
369   other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
370
371   run_loop_.Run();
372 }
373
374 // Verify that QuitClosure can be executed from another sequence even when the
375 // Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
376 TEST_P(RunLoopTest, QuitFromOtherSequenceRacyWithClosure) {
377   Thread other_thread("test");
378   other_thread.Start();
379   scoped_refptr<SequencedTaskRunner> other_sequence =
380       other_thread.task_runner();
381
382   // Always expected to run before asynchronous Quit() kicks in.
383   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
384                                           MakeExpectedRunClosure(FROM_HERE));
385
386   other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
387
388   run_loop_.Run();
389 }
390
391 // Verify that QuitWhenIdle can be executed from another sequence.
392 TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequence) {
393   Thread other_thread("test");
394   other_thread.Start();
395   scoped_refptr<SequencedTaskRunner> other_sequence =
396       other_thread.task_runner();
397
398   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
399                                           MakeExpectedRunClosure(FROM_HERE));
400
401   other_sequence->PostTask(
402       FROM_HERE,
403       base::BindOnce([](RunLoop* run_loop) { run_loop->QuitWhenIdle(); },
404                      Unretained(&run_loop_)));
405
406   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
407                                           MakeExpectedRunClosure(FROM_HERE));
408
409   run_loop_.Run();
410
411   // Regardless of the outcome of the race this thread shouldn't have been idle
412   // until both tasks posted to this sequence have run.
413 }
414
415 // Verify that QuitWhenIdleClosure can be executed from another sequence.
416 TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequenceWithClosure) {
417   Thread other_thread("test");
418   other_thread.Start();
419   scoped_refptr<SequencedTaskRunner> other_sequence =
420       other_thread.task_runner();
421
422   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
423                                           MakeExpectedRunClosure(FROM_HERE));
424
425   other_sequence->PostTask(FROM_HERE, run_loop_.QuitWhenIdleClosure());
426
427   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
428                                           MakeExpectedRunClosure(FROM_HERE));
429
430   run_loop_.Run();
431
432   // Regardless of the outcome of the race this thread shouldn't have been idle
433   // until the both tasks posted to this sequence have run.
434 }
435
436 TEST_P(RunLoopTest, IsRunningOnCurrentThread) {
437   EXPECT_FALSE(RunLoop::IsRunningOnCurrentThread());
438   ThreadTaskRunnerHandle::Get()->PostTask(
439       FROM_HERE,
440       BindOnce([]() { EXPECT_TRUE(RunLoop::IsRunningOnCurrentThread()); }));
441   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
442   run_loop_.Run();
443 }
444
445 TEST_P(RunLoopTest, IsNestedOnCurrentThread) {
446   EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
447
448   ThreadTaskRunnerHandle::Get()->PostTask(
449       FROM_HERE, BindOnce([]() {
450         EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
451
452         RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
453
454         ThreadTaskRunnerHandle::Get()->PostTask(
455             FROM_HERE, BindOnce([]() {
456               EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
457             }));
458         ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
459                                                 nested_run_loop.QuitClosure());
460
461         EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
462         nested_run_loop.Run();
463         EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
464       }));
465
466   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
467   run_loop_.Run();
468 }
469
470 TEST_P(RunLoopTest, CannotRunMoreThanOnce) {
471   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
472   run_loop_.Run();
473   EXPECT_DCHECK_DEATH({ run_loop_.Run(); });
474 }
475
476 TEST_P(RunLoopTest, CanRunUntilIdleMoreThanOnce) {
477   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, DoNothing());
478   run_loop_.RunUntilIdle();
479
480   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, DoNothing());
481   run_loop_.RunUntilIdle();
482   run_loop_.RunUntilIdle();
483 }
484
485 TEST_P(RunLoopTest, CanRunUntilIdleThenRunIfNotQuit) {
486   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, DoNothing());
487   run_loop_.RunUntilIdle();
488
489   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
490   run_loop_.Run();
491 }
492
493 TEST_P(RunLoopTest, CannotRunUntilIdleThenRunIfQuit) {
494   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
495   run_loop_.RunUntilIdle();
496
497   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, DoNothing());
498   EXPECT_DCHECK_DEATH({ run_loop_.Run(); });
499 }
500
501 TEST_P(RunLoopTest, CannotRunAgainIfQuitWhenIdle) {
502   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
503                                           run_loop_.QuitWhenIdleClosure());
504   run_loop_.RunUntilIdle();
505
506   EXPECT_DCHECK_DEATH({ run_loop_.RunUntilIdle(); });
507 }
508
509 namespace {
510
511 class MockNestingObserver : public RunLoop::NestingObserver {
512  public:
513   MockNestingObserver() = default;
514   MockNestingObserver(const MockNestingObserver&) = delete;
515   MockNestingObserver& operator=(const MockNestingObserver&) = delete;
516
517   // RunLoop::NestingObserver:
518   MOCK_METHOD0(OnBeginNestedRunLoop, void());
519   MOCK_METHOD0(OnExitNestedRunLoop, void());
520 };
521
522 class MockTask {
523  public:
524   MockTask() = default;
525   MockTask(const MockTask&) = delete;
526   MockTask& operator=(const MockTask&) = delete;
527
528   MOCK_METHOD0(Task, void());
529 };
530
531 }  // namespace
532
533 TEST_P(RunLoopTest, NestingObservers) {
534   testing::StrictMock<MockNestingObserver> nesting_observer;
535   testing::StrictMock<MockTask> mock_task_a;
536   testing::StrictMock<MockTask> mock_task_b;
537
538   RunLoop::AddNestingObserverOnCurrentThread(&nesting_observer);
539
540   const RepeatingClosure run_nested_loop = BindRepeating([]() {
541     RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
542     ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
543                                             nested_run_loop.QuitClosure());
544     nested_run_loop.Run();
545   });
546
547   // Generate a stack of nested RunLoops. OnBeginNestedRunLoop() is expected
548   // when beginning each nesting depth and OnExitNestedRunLoop() is expected
549   // when exiting each nesting depth. Each one of these tasks is ahead of the
550   // QuitClosures as those are only posted at the end of the queue when
551   // |run_nested_loop| is executed.
552   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
553   ThreadTaskRunnerHandle::Get()->PostTask(
554       FROM_HERE,
555       base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_a)));
556   ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
557   ThreadTaskRunnerHandle::Get()->PostTask(
558       FROM_HERE,
559       base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_b)));
560
561   {
562     testing::InSequence in_sequence;
563     EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
564     EXPECT_CALL(mock_task_a, Task());
565     EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
566     EXPECT_CALL(mock_task_b, Task());
567     EXPECT_CALL(nesting_observer, OnExitNestedRunLoop()).Times(2);
568   }
569   run_loop_.RunUntilIdle();
570
571   RunLoop::RemoveNestingObserverOnCurrentThread(&nesting_observer);
572 }
573
574 TEST_P(RunLoopTest, DisallowRunning) {
575   RunLoop::ScopedDisallowRunning disallow_running;
576   EXPECT_DCHECK_DEATH({ run_loop_.RunUntilIdle(); });
577 }
578
579 TEST_P(RunLoopTest, ExpiredDisallowRunning) {
580   { RunLoop::ScopedDisallowRunning disallow_running; }
581   // Running should be fine after |disallow_running| goes out of scope.
582   run_loop_.RunUntilIdle();
583 }
584
585 INSTANTIATE_TEST_SUITE_P(Real,
586                          RunLoopTest,
587                          testing::Values(RunLoopTestType::kRealEnvironment));
588 INSTANTIATE_TEST_SUITE_P(Mock,
589                          RunLoopTest,
590                          testing::Values(RunLoopTestType::kTestDelegate));
591
592 TEST(RunLoopDeathTest, MustRegisterBeforeInstantiating) {
593   TestBoundDelegate unbound_test_delegate_;
594   // RunLoop::RunLoop() should CHECK fetching the ThreadTaskRunnerHandle.
595   EXPECT_DEATH_IF_SUPPORTED({ RunLoop(); }, "");
596 }
597
598 TEST(RunLoopDelegateTest, NestableTasksDontRunInDefaultNestedLoops) {
599   TestBoundDelegate test_delegate;
600   test_delegate.BindToCurrentThread();
601
602   base::Thread other_thread("test");
603   other_thread.Start();
604
605   RunLoop main_loop;
606   // A nested run loop which isn't kNestableTasksAllowed.
607   RunLoop nested_run_loop(RunLoop::Type::kDefault);
608
609   bool nested_run_loop_ended = false;
610
611   // The first task on the main loop will result in a nested run loop. Since
612   // it's not kNestableTasksAllowed, no further task should be processed until
613   // it's quit.
614   ThreadTaskRunnerHandle::Get()->PostTask(
615       FROM_HERE,
616       BindOnce([](RunLoop* nested_run_loop) { nested_run_loop->Run(); },
617                Unretained(&nested_run_loop)));
618
619   // Post a task that will fail if it runs inside the nested run loop.
620   ThreadTaskRunnerHandle::Get()->PostTask(
621       FROM_HERE,
622       BindOnce(
623           [](const bool& nested_run_loop_ended,
624              OnceClosure continuation_callback) {
625             EXPECT_TRUE(nested_run_loop_ended);
626             EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
627             std::move(continuation_callback).Run();
628           },
629           std::cref(nested_run_loop_ended), main_loop.QuitClosure()));
630
631   // Post a task flipping the boolean bit for extra verification right before
632   // quitting |nested_run_loop|.
633   other_thread.task_runner()->PostDelayedTask(
634       FROM_HERE,
635       BindOnce(
636           [](bool* nested_run_loop_ended) {
637             EXPECT_FALSE(*nested_run_loop_ended);
638             *nested_run_loop_ended = true;
639           },
640           Unretained(&nested_run_loop_ended)),
641       TestTimeouts::tiny_timeout());
642   // Post an async delayed task to exit the run loop when idle. This confirms
643   // that (1) the test task only ran in the main loop after the nested loop
644   // exited and (2) the nested run loop actually considers itself idle while
645   // spinning. Note: The quit closure needs to be injected directly on the
646   // delegate as invoking QuitWhenIdle() off-thread results in a thread bounce
647   // which will not processed because of the very logic under test (nestable
648   // tasks don't run in |nested_run_loop|).
649   other_thread.task_runner()->PostDelayedTask(
650       FROM_HERE,
651       BindOnce(
652           [](TestBoundDelegate* test_delegate, OnceClosure injected_closure) {
653             test_delegate->InjectClosureOnDelegate(std::move(injected_closure));
654           },
655           Unretained(&test_delegate), nested_run_loop.QuitWhenIdleClosure()),
656       TestTimeouts::tiny_timeout());
657
658   main_loop.Run();
659 }
660
661 }  // namespace base