// Copyright 2020 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/test/scoped_run_loop_timeout.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/location.h" #include "base/task/sequenced_task_runner.h" #include "base/test/bind.h" #include "base/test/gtest_util.h" #include "base/test/task_environment.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest-spi.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace test { TEST(ScopedRunLoopTimeoutTest, TimesOut) { TaskEnvironment task_environment; RunLoop run_loop; static constexpr auto kArbitraryTimeout = Milliseconds(10); ScopedRunLoopTimeout run_timeout(FROM_HERE, kArbitraryTimeout); // Since the delayed task will be posted only after the message pump starts // running, the ScopedRunLoopTimeout will already have started to elapse, // so if Run() exits at the correct time then our delayed task will not run. SequencedTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, BindOnce(IgnoreResult(&SequencedTaskRunner::PostDelayedTask), SequencedTaskRunner::GetCurrentDefault(), FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE), kArbitraryTimeout)); // This task should get to run before Run() times-out. SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, MakeExpectedRunClosure(FROM_HERE), kArbitraryTimeout); // EXPECT_FATAL_FAILURE() can only reference globals and statics. static RunLoop& static_loop = run_loop; EXPECT_FATAL_FAILURE(static_loop.Run(), "Run() timed out."); } TEST(ScopedRunLoopTimeoutTest, RunTasksUntilTimeout) { TaskEnvironment task_environment; RunLoop run_loop; static constexpr auto kArbitraryTimeout = Milliseconds(10); ScopedRunLoopTimeout run_timeout(FROM_HERE, kArbitraryTimeout); // Posting a task with the same delay as our timeout, immediately before // calling Run(), means it should get to run. Since this uses QuitWhenIdle(), // the Run() timeout callback should also get to run. SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, MakeExpectedRunClosure(FROM_HERE), kArbitraryTimeout); // EXPECT_FATAL_FAILURE() can only reference globals and statics. static RunLoop& static_loop = run_loop; EXPECT_FATAL_FAILURE(static_loop.Run(), "Run() timed out."); } TEST(ScopedRunLoopTimeoutTest, OnTimeoutLog) { TaskEnvironment task_environment; RunLoop run_loop; static constexpr auto kArbitraryTimeout = Milliseconds(10); ScopedRunLoopTimeout run_timeout( FROM_HERE, kArbitraryTimeout, BindRepeating([]() -> std::string { return "I like kittens!"; })); // EXPECT_FATAL_FAILURE() can only reference globals and statics. static RunLoop& static_loop = run_loop; #if defined(__clang__) && defined(_MSC_VER) EXPECT_FATAL_FAILURE( static_loop.Run(), "Run() timed out. Timeout set at " "TestBody@base\\test\\scoped_run_loop_timeout_unittest.cc:70.\n" "I like kittens!"); } #else EXPECT_FATAL_FAILURE( static_loop.Run(), "Run() timed out. Timeout set at " "TestBody@base/test/scoped_run_loop_timeout_unittest.cc:70.\n" "I like kittens!"); } #endif } // namespace test } // namespace base