blob: 96060f4a6601bdfbbe0d21cdaf41afe2b4271892 [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 <utility>
8
fdorayf36496f2016-06-10 09:08:58 +09009#include "base/bind.h"
10#include "base/bind_helpers.h"
Brett Wilsonaf47cf02017-09-21 05:53:20 +090011#include "base/containers/queue.h"
fdorayf36496f2016-06-10 09:08:58 +090012#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 Charette3c6f00b2017-08-07 13:22:48 +090021#include "base/test/test_timeouts.h"
Gabriel Charette31fc1322017-08-02 12:52:16 +090022#include "base/threading/platform_thread.h"
23#include "base/threading/thread.h"
24#include "base/threading/thread_checker_impl.h"
fdorayf36496f2016-06-10 09:08:58 +090025#include "base/threading/thread_task_runner_handle.h"
Gabriel Charette31fc1322017-08-02 12:52:16 +090026#include "build/build_config.h"
gab029f59e2017-05-05 22:38:54 +090027#include "testing/gmock/include/gmock/gmock.h"
fdorayf36496f2016-06-10 09:08:58 +090028#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 Charette3c6f00b2017-08-07 13:22:48 +090048 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
fdorayf36496f2016-06-10 09:08:58 +090049
50 // This task should quit |nested_run_loop| but not the main RunLoop.
51 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +090052 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&nested_run_loop),
53 Unretained(counter)));
fdorayf36496f2016-06-10 09:08:58 +090054
55 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik6bdbeb22017-04-12 00:00:44 +090056 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdorayf36496f2016-06-10 09:08:58 +090057
fdorayf36496f2016-06-10 09:08:58 +090058 nested_run_loop.Run();
59
60 ++(*counter);
61}
62
Gabriel Charette31fc1322017-08-02 12:52:16 +090063// 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;
fdorayf36496f2016-06-10 09:08:58 +090069
Brett Wilson89388db2017-09-12 14:22:16 +090070 bool PostDelayedTask(const Location& from_here,
Gabriel Charette31fc1322017-08-02 12:52:16 +090071 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 Wilson89388db2017-09-12 14:22:16 +090080 bool PostNonNestableDelayedTask(const Location& from_here,
Gabriel Charette31fc1322017-08-02 12:52:16 +090081 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 Charettef1f94cb2017-12-03 21:47:21 +090090 bool ProcessSingleTask() {
Gabriel Charette31fc1322017-08-02 12:52:16 +090091 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 Charettef1f94cb2017-12-03 21:47:21 +0900100 // run a nested loop which will re-enter ProcessSingleTask().
Gabriel Charette31fc1322017-08-02 12:52:16 +0900101 std::move(task).Run();
102 return true;
103 }
104
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900105 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 Charette31fc1322017-08-02 12:52:16 +0900112 private:
113 ~SimpleSingleThreadTaskRunner() override = default;
114
115 Lock tasks_lock_;
Brett Wilsonaf47cf02017-09-21 05:53:20 +0900116 base::queue<OnceClosure> pending_tasks_;
Gabriel Charette31fc1322017-08-02 12:52:16 +0900117
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 Charettef1f94cb2017-12-03 21:47:21 +0900126// 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 Charette31fc1322017-08-02 12:52:16 +0900132 public:
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900133 void InjectClosureOnDelegate(OnceClosure closure) {
134 AutoLock auto_lock(closure_lock_);
135 closure_ = std::move(closure);
136 }
Gabriel Charette31fc1322017-08-02 12:52:16 +0900137
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900138 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 Charette31fc1322017-08-02 12:52:16 +0900160 void BindToCurrentThread() {
161 thread_task_runner_handle_ =
Jeremy Romancd0c4672017-08-17 08:27:24 +0900162 std::make_unique<ThreadTaskRunnerHandle>(simple_task_runner_);
Gabriel Charette17d93712017-12-15 02:22:40 +0900163 RunLoop::RegisterDelegateForCurrentThread(this);
Gabriel Charette31fc1322017-08-02 12:52:16 +0900164 }
165
166 private:
Gabriel Charettee0390592017-10-26 10:04:40 +0900167 void Run(bool application_tasks_allowed) override {
Gabriel Charette3c6f00b2017-08-07 13:22:48 +0900168 if (nested_run_allowing_tasks_incoming_) {
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900169 EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
Gabriel Charettee0390592017-10-26 10:04:40 +0900170 EXPECT_TRUE(application_tasks_allowed);
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900171 } else if (RunLoop::IsNestedOnCurrentThread()) {
Gabriel Charettee0390592017-10-26 10:04:40 +0900172 EXPECT_FALSE(application_tasks_allowed);
Gabriel Charette3c6f00b2017-08-07 13:22:48 +0900173 }
174 nested_run_allowing_tasks_incoming_ = false;
175
Gabriel Charette31fc1322017-08-02 12:52:16 +0900176 while (!should_quit_) {
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900177 if (application_tasks_allowed && simple_task_runner_->ProcessSingleTask())
Gabriel Charette31fc1322017-08-02 12:52:16 +0900178 continue;
179
Gabriel Charette17d93712017-12-15 02:22:40 +0900180 if (ShouldQuitWhenIdle())
Gabriel Charette31fc1322017-08-02 12:52:16 +0900181 break;
182
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900183 if (RunInjectedClosure())
184 continue;
Gabriel Charette3c6f00b2017-08-07 13:22:48 +0900185
Gabriel Charette31fc1322017-08-02 12:52:16 +0900186 PlatformThread::YieldCurrentThread();
187 }
188 should_quit_ = false;
189 }
190
191 void Quit() override { should_quit_ = true; }
192
Gabriel Charette3c6f00b2017-08-07 13:22:48 +0900193 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 Charette31fc1322017-08-02 12:52:16 +0900201 scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
202 MakeRefCounted<SimpleSingleThreadTaskRunner>();
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900203
Gabriel Charette31fc1322017-08-02 12:52:16 +0900204 std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
205
206 bool should_quit_ = false;
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900207};
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 Charette17d93712017-12-15 02:22:40 +0900219 overridden_task_runner_ = ThreadTaskRunnerHandle::Get();
220 ASSERT_TRUE(overridden_task_runner_);
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900221 thread_task_runner_handle_override_scope_ =
222 ThreadTaskRunnerHandle::OverrideForTesting(
223 simple_task_runner_,
224 ThreadTaskRunnerHandle::OverrideType::kTakeOverThread);
225
Gabriel Charette17d93712017-12-15 02:22:40 +0900226 // 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 Charettef1f94cb2017-12-03 21:47:21 +0900232 }
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 Charette17d93712017-12-15 02:22:40 +0900240 overridden_task_runner_->PostTask(FROM_HERE,
241 std::move(pending_tasks.front()));
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900242 pending_tasks.pop();
243 }
Gabriel Charette17d93712017-12-15 02:22:40 +0900244 overridden_delegate_->Run(application_tasks_allowed);
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900245 continue;
246 }
247
Gabriel Charette17d93712017-12-15 02:22:40 +0900248 if (ShouldQuitWhenIdle())
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900249 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 Charette17d93712017-12-15 02:22:40 +0900261 overridden_delegate_->Quit();
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900262 }
263
264 void EnsureWorkScheduled() override {
Gabriel Charette17d93712017-12-15 02:22:40 +0900265 overridden_delegate_->EnsureWorkScheduled();
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900266 }
267
268 scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
269 MakeRefCounted<SimpleSingleThreadTaskRunner>();
270
271 ScopedClosureRunner thread_task_runner_handle_override_scope_;
272
Gabriel Charette17d93712017-12-15 02:22:40 +0900273 scoped_refptr<SingleThreadTaskRunner> overridden_task_runner_;
274 RunLoop::Delegate* overridden_delegate_;
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900275
276 bool should_quit_ = false;
Gabriel Charette31fc1322017-08-02 12:52:16 +0900277};
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 Charettef1f94cb2017-12-03 21:47:21 +0900287
288 // Runs all RunLoopTests through a RunLoop::Delegate which overrides a
289 // kRealEnvironment's registered RunLoop::Delegate.
290 kOverridingTestDelegate,
Gabriel Charette31fc1322017-08-02 12:52:16 +0900291};
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 Charettef1f94cb2017-12-03 21:47:21 +0900299 case RunLoopTestType::kRealEnvironment: {
Jeremy Romancd0c4672017-08-17 08:27:24 +0900300 task_environment_ = std::make_unique<test::ScopedTaskEnvironment>();
Gabriel Charette31fc1322017-08-02 12:52:16 +0900301 break;
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900302 }
303 case RunLoopTestType::kTestDelegate: {
304 auto test_delegate = std::make_unique<TestBoundDelegate>();
305 test_delegate->BindToCurrentThread();
306 test_delegate_ = std::move(test_delegate);
Gabriel Charette31fc1322017-08-02 12:52:16 +0900307 break;
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900308 }
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 Charette31fc1322017-08-02 12:52:16 +0900316 }
317 }
318
319 private:
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900320 // Instantiates one or the other based on the RunLoopTestType (or both in the
321 // kOverridingTestDelegate case).
Gabriel Charette31fc1322017-08-02 12:52:16 +0900322 std::unique_ptr<test::ScopedTaskEnvironment> task_environment_;
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900323 std::unique_ptr<InjectableTestDelegate> test_delegate_;
Gabriel Charette31fc1322017-08-02 12:52:16 +0900324};
325
326class RunLoopTest : public testing::TestWithParam<RunLoopTestType> {
327 protected:
328 RunLoopTest() : test_environment_(GetParam()) {}
329
330 RunLoopTestEnvironment test_environment_;
fdorayf36496f2016-06-10 09:08:58 +0900331 RunLoop run_loop_;
332 int counter_ = 0;
333
334 private:
335 DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
336};
337
338} // namespace
339
Gabriel Charette31fc1322017-08-02 12:52:16 +0900340TEST_P(RunLoopTest, QuitWhenIdle) {
gab029f59e2017-05-05 22:38:54 +0900341 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900342 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
343 Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900344 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900345 FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900346 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik6bdbeb22017-04-12 00:00:44 +0900347 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdorayf36496f2016-06-10 09:08:58 +0900348
349 run_loop_.Run();
350 EXPECT_EQ(2, counter_);
351}
352
Gabriel Charette31fc1322017-08-02 12:52:16 +0900353TEST_P(RunLoopTest, QuitWhenIdleNestedLoop) {
gab029f59e2017-05-05 22:38:54 +0900354 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900355 FROM_HERE, BindOnce(&RunNestedLoopTask, Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900356 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900357 FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
358 Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900359 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900360 FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900361 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik6bdbeb22017-04-12 00:00:44 +0900362 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdorayf36496f2016-06-10 09:08:58 +0900363
364 run_loop_.Run();
365 EXPECT_EQ(4, counter_);
366}
367
Gabriel Charette31fc1322017-08-02 12:52:16 +0900368TEST_P(RunLoopTest, QuitWhenIdleClosure) {
gab029f59e2017-05-05 22:38:54 +0900369 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
370 run_loop_.QuitWhenIdleClosure());
371 ThreadTaskRunnerHandle::Get()->PostTask(
tzik6bdbeb22017-04-12 00:00:44 +0900372 FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
gab029f59e2017-05-05 22:38:54 +0900373 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tzik6bdbeb22017-04-12 00:00:44 +0900374 FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
fdoray995fbe12016-06-11 03:23:15 +0900375
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 Charette31fc1322017-08-02 12:52:16 +0900382TEST_P(RunLoopTest, QuitWhenIdleClosureAfterRunLoopScope) {
fdoray995fbe12016-06-11 03:23:15 +0900383 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
gab7e2af5c2017-05-20 07:56:57 +0900392// Verify that Quit can be executed from another sequence.
Gabriel Charette31fc1322017-08-02 12:52:16 +0900393TEST_P(RunLoopTest, QuitFromOtherSequence) {
394 Thread other_thread("test");
395 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900396 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900397 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900398
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 Charette31fc1322017-08-02 12:52:16 +0900415 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
416 base::BindOnce(&ShouldNotRunTask));
gab7e2af5c2017-05-20 07:56:57 +0900417
418 run_loop_.Run();
419
420 EXPECT_EQ(1, counter_);
421}
422
423// Verify that QuitClosure can be executed from another sequence.
Gabriel Charette31fc1322017-08-02 12:52:16 +0900424TEST_P(RunLoopTest, QuitFromOtherSequenceWithClosure) {
425 Thread other_thread("test");
426 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900427 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900428 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900429
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 Charette31fc1322017-08-02 12:52:16 +0900444 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
445 base::BindOnce(&ShouldNotRunTask));
gab7e2af5c2017-05-20 07:56:57 +0900446
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 Charette31fc1322017-08-02 12:52:16 +0900454TEST_P(RunLoopTest, QuitFromOtherSequenceRacy) {
455 Thread other_thread("test");
456 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900457 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900458 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900459
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 Charette31fc1322017-08-02 12:52:16 +0900475TEST_P(RunLoopTest, QuitFromOtherSequenceRacyWithClosure) {
476 Thread other_thread("test");
477 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900478 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900479 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900480
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 Charette31fc1322017-08-02 12:52:16 +0900493TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequence) {
494 Thread other_thread("test");
495 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900496 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900497 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900498
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 Charette31fc1322017-08-02 12:52:16 +0900518TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequenceWithClosure) {
519 Thread other_thread("test");
520 other_thread.Start();
gab7e2af5c2017-05-20 07:56:57 +0900521 scoped_refptr<SequencedTaskRunner> other_sequence =
Gabriel Charette31fc1322017-08-02 12:52:16 +0900522 other_thread.task_runner();
gab7e2af5c2017-05-20 07:56:57 +0900523
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 Charette31fc1322017-08-02 12:52:16 +0900539TEST_P(RunLoopTest, IsRunningOnCurrentThread) {
gab029f59e2017-05-05 22:38:54 +0900540 EXPECT_FALSE(RunLoop::IsRunningOnCurrentThread());
541 ThreadTaskRunnerHandle::Get()->PostTask(
542 FROM_HERE,
tzik330d83f2017-06-26 15:13:17 +0900543 BindOnce([]() { EXPECT_TRUE(RunLoop::IsRunningOnCurrentThread()); }));
gab029f59e2017-05-05 22:38:54 +0900544 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
545 run_loop_.Run();
546}
547
Gabriel Charette31fc1322017-08-02 12:52:16 +0900548TEST_P(RunLoopTest, IsNestedOnCurrentThread) {
gab029f59e2017-05-05 22:38:54 +0900549 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
550
551 ThreadTaskRunnerHandle::Get()->PostTask(
tzik330d83f2017-06-26 15:13:17 +0900552 FROM_HERE, BindOnce([]() {
gab029f59e2017-05-05 22:38:54 +0900553 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
554
Gabriel Charette3c6f00b2017-08-07 13:22:48 +0900555 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
gab029f59e2017-05-05 22:38:54 +0900556
557 ThreadTaskRunnerHandle::Get()->PostTask(
tzik330d83f2017-06-26 15:13:17 +0900558 FROM_HERE, BindOnce([]() {
559 EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
560 }));
gab029f59e2017-05-05 22:38:54 +0900561 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
562 nested_run_loop.QuitClosure());
563
564 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
gab029f59e2017-05-05 22:38:54 +0900565 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 Doraycb68b612018-01-05 01:17:32 +0900573namespace {
574
gab029f59e2017-05-05 22:38:54 +0900575class MockNestingObserver : public RunLoop::NestingObserver {
576 public:
577 MockNestingObserver() = default;
578
579 // RunLoop::NestingObserver:
580 MOCK_METHOD0(OnBeginNestedRunLoop, void());
Francois Doraycb68b612018-01-05 01:17:32 +0900581 MOCK_METHOD0(OnExitNestedRunLoop, void());
gab029f59e2017-05-05 22:38:54 +0900582
583 private:
584 DISALLOW_COPY_AND_ASSIGN(MockNestingObserver);
585};
586
Francois Doraycb68b612018-01-05 01:17:32 +0900587class 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 Charette31fc1322017-08-02 12:52:16 +0900598TEST_P(RunLoopTest, NestingObservers) {
gab029f59e2017-05-05 22:38:54 +0900599 EXPECT_TRUE(RunLoop::IsNestingAllowedOnCurrentThread());
600
601 testing::StrictMock<MockNestingObserver> nesting_observer;
Francois Doraycb68b612018-01-05 01:17:32 +0900602 testing::StrictMock<MockTask> mock_task_a;
603 testing::StrictMock<MockTask> mock_task_b;
gab029f59e2017-05-05 22:38:54 +0900604
605 RunLoop::AddNestingObserverOnCurrentThread(&nesting_observer);
606
607 const RepeatingClosure run_nested_loop = Bind([]() {
Gabriel Charette3c6f00b2017-08-07 13:22:48 +0900608 RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
gab029f59e2017-05-05 22:38:54 +0900609 ThreadTaskRunnerHandle::Get()->PostTask(
tzik330d83f2017-06-26 15:13:17 +0900610 FROM_HERE, BindOnce([]() {
gab029f59e2017-05-05 22:38:54 +0900611 EXPECT_TRUE(RunLoop::IsNestingAllowedOnCurrentThread());
612 }));
613 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
614 nested_run_loop.QuitClosure());
gab029f59e2017-05-05 22:38:54 +0900615 nested_run_loop.Run();
616 });
617
Francois Doraycb68b612018-01-05 01:17:32 +0900618 // Generate a stack of nested RunLoops. OnBeginNestedRunLoop() is expected
619 // when beginning each nesting depth and OnExitNestedRunLoop() is expected
620 // when exiting each nesting depth.
gab029f59e2017-05-05 22:38:54 +0900621 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
Francois Doraycb68b612018-01-05 01:17:32 +0900622 ThreadTaskRunnerHandle::Get()->PostTask(
623 FROM_HERE,
624 base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_a)));
gab029f59e2017-05-05 22:38:54 +0900625 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
Francois Doraycb68b612018-01-05 01:17:32 +0900626 ThreadTaskRunnerHandle::Get()->PostTask(
627 FROM_HERE,
628 base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_b)));
gab029f59e2017-05-05 22:38:54 +0900629
Francois Doraycb68b612018-01-05 01:17:32 +0900630 {
631 testing::InSequence in_sequence;
632 EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
633 EXPECT_CALL(mock_task_a, Task());
634 EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
635 EXPECT_CALL(mock_task_b, Task());
636 EXPECT_CALL(nesting_observer, OnExitNestedRunLoop()).Times(2);
637 }
638 run_loop_.RunUntilIdle();
gab029f59e2017-05-05 22:38:54 +0900639
640 RunLoop::RemoveNestingObserverOnCurrentThread(&nesting_observer);
641}
642
643// Disabled on Android per http://crbug.com/643760.
644#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
Gabriel Charette31fc1322017-08-02 12:52:16 +0900645TEST_P(RunLoopTest, DisallowNestingDeathTest) {
gab029f59e2017-05-05 22:38:54 +0900646 EXPECT_TRUE(RunLoop::IsNestingAllowedOnCurrentThread());
647 RunLoop::DisallowNestingOnCurrentThread();
648 EXPECT_FALSE(RunLoop::IsNestingAllowedOnCurrentThread());
649
tzik330d83f2017-06-26 15:13:17 +0900650 ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, BindOnce([]() {
gab029f59e2017-05-05 22:38:54 +0900651 RunLoop nested_run_loop;
652 nested_run_loop.RunUntilIdle();
653 }));
gab9e917e82017-05-06 04:24:10 +0900654 EXPECT_DEATH({ run_loop_.RunUntilIdle(); }, "");
gab029f59e2017-05-05 22:38:54 +0900655}
656#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
657
Gabriel Charette250436f2017-08-22 08:14:04 +0900658TEST_P(RunLoopTest, DisallowRunningForTesting) {
659 RunLoop::ScopedDisallowRunningForTesting disallow_running;
660 EXPECT_DCHECK_DEATH({ run_loop_.Run(); });
661}
662
663TEST_P(RunLoopTest, ExpiredDisallowRunningForTesting) {
664 { RunLoop::ScopedDisallowRunningForTesting disallow_running; }
665 // Running should be fine after |disallow_running| goes out of scope.
666 run_loop_.RunUntilIdle();
667}
668
Gabriel Charette31fc1322017-08-02 12:52:16 +0900669INSTANTIATE_TEST_CASE_P(Real,
670 RunLoopTest,
671 testing::Values(RunLoopTestType::kRealEnvironment));
672INSTANTIATE_TEST_CASE_P(Mock,
673 RunLoopTest,
674 testing::Values(RunLoopTestType::kTestDelegate));
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900675INSTANTIATE_TEST_CASE_P(
676 OverridingMock,
677 RunLoopTest,
678 testing::Values(RunLoopTestType::kOverridingTestDelegate));
Gabriel Charette31fc1322017-08-02 12:52:16 +0900679
680TEST(RunLoopDeathTest, MustRegisterBeforeInstantiating) {
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900681 TestBoundDelegate unbound_test_delegate_;
Gabriel Charette31fc1322017-08-02 12:52:16 +0900682 // Exercise the DCHECK in RunLoop::RunLoop().
683 EXPECT_DCHECK_DEATH({ RunLoop(); });
684}
685
Gabriel Charette3c6f00b2017-08-07 13:22:48 +0900686TEST(RunLoopDelegateTest, NestableTasksDontRunInDefaultNestedLoops) {
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900687 TestBoundDelegate test_delegate;
Gabriel Charette3c6f00b2017-08-07 13:22:48 +0900688 test_delegate.BindToCurrentThread();
689
690 base::Thread other_thread("test");
691 other_thread.Start();
692
693 RunLoop main_loop;
694 // A nested run loop which isn't kNestableTasksAllowed.
695 RunLoop nested_run_loop(RunLoop::Type::kDefault);
696
697 bool nested_run_loop_ended = false;
698
699 // The first task on the main loop will result in a nested run loop. Since
700 // it's not kNestableTasksAllowed, no further task should be processed until
701 // it's quit.
702 ThreadTaskRunnerHandle::Get()->PostTask(
703 FROM_HERE,
704 BindOnce([](RunLoop* nested_run_loop) { nested_run_loop->Run(); },
705 Unretained(&nested_run_loop)));
706
707 // Post a task that will fail if it runs inside the nested run loop.
708 ThreadTaskRunnerHandle::Get()->PostTask(
709 FROM_HERE, BindOnce(
710 [](const bool& nested_run_loop_ended,
711 OnceClosure continuation_callback) {
712 EXPECT_TRUE(nested_run_loop_ended);
713 EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
714 std::move(continuation_callback).Run();
715 },
716 ConstRef(nested_run_loop_ended), main_loop.QuitClosure()));
717
718 // Post a task flipping the boolean bit for extra verification right before
719 // quitting |nested_run_loop|.
720 other_thread.task_runner()->PostDelayedTask(
721 FROM_HERE,
722 BindOnce(
723 [](bool* nested_run_loop_ended) {
724 EXPECT_FALSE(*nested_run_loop_ended);
725 *nested_run_loop_ended = true;
726 },
727 Unretained(&nested_run_loop_ended)),
728 TestTimeouts::tiny_timeout());
729 // Post an async delayed task to exit the run loop when idle. This confirms
730 // that (1) the test task only ran in the main loop after the nested loop
731 // exited and (2) the nested run loop actually considers itself idle while
732 // spinning. Note: The quit closure needs to be injected directly on the
733 // delegate as invoking QuitWhenIdle() off-thread results in a thread bounce
734 // which will not processed because of the very logic under test (nestable
735 // tasks don't run in |nested_run_loop|).
736 other_thread.task_runner()->PostDelayedTask(
737 FROM_HERE,
738 BindOnce(
Gabriel Charettef1f94cb2017-12-03 21:47:21 +0900739 [](TestBoundDelegate* test_delegate, OnceClosure injected_closure) {
740 test_delegate->InjectClosureOnDelegate(std::move(injected_closure));
Gabriel Charette3c6f00b2017-08-07 13:22:48 +0900741 },
742 Unretained(&test_delegate), nested_run_loop.QuitWhenIdleClosure()),
743 TestTimeouts::tiny_timeout());
744
745 main_loop.Run();
746}
747
fdorayf36496f2016-06-10 09:08:58 +0900748} // namespace base