// Copyright 2017 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/task/single_thread_task_runner.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" #include "base/test/gtest_util.h" #include "base/test/task_environment.h" #include "base/test/test_simple_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, Basic) { scoped_refptr task_runner( MakeRefCounted()); EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault()); { SingleThreadTaskRunner::CurrentDefaultHandle sttcd1(task_runner); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner, SingleThreadTaskRunner::GetCurrentDefault()); } EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault()); } // Verify that instantiating a `CurrentDefaultHandle` without `MayAlreadyExist` // fails if there is already a current default `SingleThreadTaskRunner`. TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, DeathOnImplicitOverride) { scoped_refptr task_runner( MakeRefCounted()); scoped_refptr overidding_task_runner( MakeRefCounted()); SingleThreadTaskRunner::CurrentDefaultHandle sttcd(task_runner); EXPECT_DCHECK_DEATH({ SingleThreadTaskRunner::CurrentDefaultHandle overriding_sttcd( overidding_task_runner); }); } // Verify nested instantiations of `CurrentHandleOverrideForTesting` in a scope // with a `CurrentDefaultHandle`. TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, NestedOverrideForTesting) { scoped_refptr task_runner_1( MakeRefCounted()); scoped_refptr task_runner_2( MakeRefCounted()); scoped_refptr task_runner_3( MakeRefCounted()); scoped_refptr task_runner_4( MakeRefCounted()); EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault()); { // STTCD in place prior to override. SingleThreadTaskRunner::CurrentDefaultHandle sttcd1(task_runner_1); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_1, SingleThreadTaskRunner::GetCurrentDefault()); { // Override. SingleThreadTaskRunner::CurrentHandleOverrideForTesting sttcd_override_2( task_runner_2); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_2, SingleThreadTaskRunner::GetCurrentDefault()); { // Nested override. SingleThreadTaskRunner::CurrentHandleOverrideForTesting sttcd_override_3(task_runner_3); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_3, SingleThreadTaskRunner::GetCurrentDefault()); } // Back to single override. EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_2, SingleThreadTaskRunner::GetCurrentDefault()); { // Backup to double override with another STTCD. SingleThreadTaskRunner::CurrentHandleOverrideForTesting sttcd_override_4(task_runner_4); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_4, SingleThreadTaskRunner::GetCurrentDefault()); } } // Back to simple STTCD. EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_1, SingleThreadTaskRunner::GetCurrentDefault()); } EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault()); } // Same as above, but using `CurrentDefaultHandle` with `MayAlreadyExist` // instead of `CurrentHandleOverrideForTesting`. TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, NestedOverrideWithMayAlreadyExist) { scoped_refptr task_runner_1( MakeRefCounted()); scoped_refptr task_runner_2( MakeRefCounted()); scoped_refptr task_runner_3( MakeRefCounted()); scoped_refptr task_runner_4( MakeRefCounted()); EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault()); { // STTCD in place prior to override. SingleThreadTaskRunner::CurrentDefaultHandle sttcd1(task_runner_1); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_1, SingleThreadTaskRunner::GetCurrentDefault()); { // Override. SingleThreadTaskRunner::CurrentDefaultHandle sttcd_override_2( task_runner_2, SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_2, SingleThreadTaskRunner::GetCurrentDefault()); { // Nested override. SingleThreadTaskRunner::CurrentDefaultHandle sttcd_override_3( task_runner_3, SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_3, SingleThreadTaskRunner::GetCurrentDefault()); } // Back to single override. EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_2, SingleThreadTaskRunner::GetCurrentDefault()); { // Backup to double override with another STTCD. SingleThreadTaskRunner::CurrentDefaultHandle sttcd_override_4( task_runner_4, SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_4, SingleThreadTaskRunner::GetCurrentDefault()); } } // Back to simple STTCD. EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_1, SingleThreadTaskRunner::GetCurrentDefault()); } EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault()); } // Verify that `CurrentDefaultHandle` can be used to set the current default // `SingleThreadTaskRunner` and `SequencedTaskRunner` to null in a scope that // already has a default. TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, OverrideWithNull) { auto tr1 = MakeRefCounted(); SingleThreadTaskRunner::CurrentDefaultHandle handle( tr1, SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr1, SingleThreadTaskRunner::GetCurrentDefault()); EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr1, SequencedTaskRunner::GetCurrentDefault()); { SingleThreadTaskRunner::CurrentDefaultHandle nested_handle( nullptr, SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}); EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_CHECK_DEATH( { auto tr2 = SingleThreadTaskRunner::GetCurrentDefault(); }); EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault()); EXPECT_CHECK_DEATH( { auto tr2 = SequencedTaskRunner::GetCurrentDefault(); }); } EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr1, SingleThreadTaskRunner::GetCurrentDefault()); EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr1, SequencedTaskRunner::GetCurrentDefault()); } // Verify that `CurrentDefaultHandle` can be used to set the current default // `SingleThreadTaskRunner` and `SequencedTaskRunner` to a non-null value in a // scope that already has a default. TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, OverrideWithNonNull) { auto tr1 = MakeRefCounted(); auto tr2 = MakeRefCounted(); SingleThreadTaskRunner::CurrentDefaultHandle handle( tr1, SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr1, SingleThreadTaskRunner::GetCurrentDefault()); EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr1, SequencedTaskRunner::GetCurrentDefault()); { SingleThreadTaskRunner::CurrentDefaultHandle nested_handle( tr2, SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr2, SingleThreadTaskRunner::GetCurrentDefault()); EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr2, SequencedTaskRunner::GetCurrentDefault()); } EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr1, SingleThreadTaskRunner::GetCurrentDefault()); EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault()); EXPECT_EQ(tr1, SequencedTaskRunner::GetCurrentDefault()); } // Verify nested instantiations of `CurrentHandleOverrideForTesting` in a scope // without a `CurrentDefaultHandle`. TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, OverrideNoExistingSTTCD) { scoped_refptr task_runner_1( MakeRefCounted()); scoped_refptr task_runner_2( MakeRefCounted()); EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault()); { // Override with no STTCD in place. SingleThreadTaskRunner::CurrentHandleOverrideForTesting sttcd_override_1( task_runner_1); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_1, SingleThreadTaskRunner::GetCurrentDefault()); { // Nested override works the same. SingleThreadTaskRunner::CurrentHandleOverrideForTesting sttcd_override_2( task_runner_2); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_2, SingleThreadTaskRunner::GetCurrentDefault()); } // Back to single override. EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner_1, SingleThreadTaskRunner::GetCurrentDefault()); } EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault()); } // Verify that `CurrentDefaultHandle` can't be instantiated without // `MayAlreadyExist` in the scope of a `CurrentHandleOverrideForTesting`. TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, DeathOnSTTCDOverOverride) { scoped_refptr task_runner( MakeRefCounted()); scoped_refptr overidding_task_runner( MakeRefCounted()); SingleThreadTaskRunner::CurrentHandleOverrideForTesting sttcd_override( task_runner); EXPECT_DCHECK_DEATH({ SingleThreadTaskRunner::CurrentDefaultHandle overriding_sttrcd( overidding_task_runner); }); } // Verify that running a `RunLoop` is supported in the scope of a // `CurrentDefaultHandle` with `MayAlreadyExist`. TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, NestedRunLoopAllowedUnderHandleOverride) { test::SingleThreadTaskEnvironment task_environment; EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); scoped_refptr task_runner( MakeRefCounted()); SingleThreadTaskRunner::CurrentDefaultHandle sttrcd_override( task_runner, SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner, SingleThreadTaskRunner::GetCurrentDefault()); EXPECT_EQ(task_runner, SequencedTaskRunner::GetCurrentDefault()); RunLoop().RunUntilIdle(); } // Verify that running a `RunLoop` fails in the scope of a // `CurrentHandleOverrideForTesting`. TEST(SingleThreadTaskRunnerCurrentDefaultHandleTest, NestedRunLoopDisallowedUnderHandleOverrideForTesting) { test::SingleThreadTaskEnvironment task_environment; EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); scoped_refptr task_runner( MakeRefCounted()); SingleThreadTaskRunner::CurrentHandleOverrideForTesting sttcd_override( task_runner); EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault()); EXPECT_EQ(task_runner, SingleThreadTaskRunner::GetCurrentDefault()); EXPECT_EQ(task_runner, SequencedTaskRunner::GetCurrentDefault()); EXPECT_DCHECK_DEATH({ RunLoop().RunUntilIdle(); }); } } // namespace base