Chromium Code Reviews| Index: base/run_loop_unittest.cc |
| diff --git a/base/run_loop_unittest.cc b/base/run_loop_unittest.cc |
| index ea596c60fb76f89946967e985fb690627937c2ef..3c23a02330f5969d8c5e476083833d7931ce4609 100644 |
| --- a/base/run_loop_unittest.cc |
| +++ b/base/run_loop_unittest.cc |
| @@ -8,8 +8,10 @@ |
| #include "base/bind_helpers.h" |
| #include "base/location.h" |
| #include "base/macros.h" |
| -#include "base/message_loop/message_loop.h" |
| #include "base/single_thread_task_runner.h" |
| +#include "base/synchronization/waitable_event.h" |
| +#include "base/task_scheduler/post_task.h" |
| +#include "base/test/scoped_task_environment.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| @@ -52,7 +54,7 @@ class RunLoopTest : public testing::Test { |
| protected: |
| RunLoopTest() = default; |
| - MessageLoop message_loop_; |
| + test::ScopedTaskEnvironment task_environment_; |
| RunLoop run_loop_; |
| int counter_ = 0; |
| @@ -114,6 +116,70 @@ TEST_F(RunLoopTest, QuitWhenIdleClosureAfterRunLoopScope) { |
| quit_when_idle_closure.Run(); |
| } |
| +// Verify that QuitClosure can be executed from another sequence. |
| +TEST_F(RunLoopTest, QuitFromOtherSequence) { |
| + scoped_refptr<SequencedTaskRunner> other_sequence = |
| + CreateSequencedTaskRunnerWithTraits({}); |
| + |
| + // Always expected to run before asynchronous Quit() kicks in. |
| + ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_))); |
| + |
| + WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL, |
| + WaitableEvent::InitialState::NOT_SIGNALED); |
| + other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure()); |
|
danakj
2017/05/19 18:53:34
These tests all verify QuitClosure() but not Quit(
gab
2017/05/19 19:38:16
Done.
|
| + other_sequence->PostTask( |
| + FROM_HERE, |
| + base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit))); |
| + |
| + // Anything that's posted after the Quit closure was posted back to this |
| + // sequence shouldn't get a chance to run. |
| + loop_was_quit.Wait(); |
| + ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_))); |
| + |
| + run_loop_.Run(); |
| + |
| + EXPECT_EQ(1, counter_); |
| +} |
| + |
| +// Verify that QuitClosure can be executed from another sequence even when the |
| +// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above. |
| +TEST_F(RunLoopTest, QuitFromOtherSequenceRacy) { |
| + scoped_refptr<SequencedTaskRunner> other_sequence = |
| + CreateSequencedTaskRunnerWithTraits({}); |
| + |
| + // Always expected to run before asynchronous Quit() kicks in. |
| + ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_))); |
| + |
| + other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure()); |
| + |
| + run_loop_.Run(); |
| + |
| + EXPECT_EQ(1, counter_); |
| +} |
| + |
| +// Verify that QuitWhenIdleClosure can be executed from another sequence. |
| +TEST_F(RunLoopTest, QuitWhenIdleFromOtherSequence) { |
| + scoped_refptr<SequencedTaskRunner> other_sequence = |
| + CreateSequencedTaskRunnerWithTraits({}); |
| + |
| + ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_))); |
| + |
| + other_sequence->PostTask(FROM_HERE, run_loop_.QuitWhenIdleClosure()); |
| + |
| + ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_))); |
| + |
| + run_loop_.Run(); |
| + |
| + // Regardless of the outcome of the race this thread shouldn't have been idle |
| + // until the counter was ticked twice. |
| + EXPECT_EQ(2, counter_); |
| +} |
| + |
| TEST_F(RunLoopTest, IsRunningOnCurrentThread) { |
| EXPECT_FALSE(RunLoop::IsRunningOnCurrentThread()); |
| ThreadTaskRunnerHandle::Get()->PostTask( |