xref: /aosp_15_r20/external/cronet/base/test/scoped_run_loop_timeout_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
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/test/scoped_run_loop_timeout.h"
6 
7 #include "base/functional/bind.h"
8 #include "base/functional/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/task/sequenced_task_runner.h"
11 #include "base/test/bind.h"
12 #include "base/test/gtest_util.h"
13 #include "base/test/mock_callback.h"
14 #include "base/test/task_environment.h"
15 #include "base/time/time.h"
16 #include "testing/gtest/include/gtest/gtest-spi.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace base::test {
20 
TEST(ScopedRunLoopTimeoutTest,TimesOut)21 TEST(ScopedRunLoopTimeoutTest, TimesOut) {
22   TaskEnvironment task_environment;
23   RunLoop run_loop;
24 
25   static constexpr auto kArbitraryTimeout = Milliseconds(10);
26   ScopedRunLoopTimeout run_timeout(FROM_HERE, kArbitraryTimeout);
27 
28   // Since the delayed task will be posted only after the message pump starts
29   // running, the ScopedRunLoopTimeout will already have started to elapse,
30   // so if Run() exits at the correct time then our delayed task will not run.
31   SequencedTaskRunner::GetCurrentDefault()->PostTask(
32       FROM_HERE,
33       BindOnce(IgnoreResult(&SequencedTaskRunner::PostDelayedTask),
34                SequencedTaskRunner::GetCurrentDefault(), FROM_HERE,
35                MakeExpectedNotRunClosure(FROM_HERE), kArbitraryTimeout));
36 
37   // This task should get to run before Run() times-out.
38   SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
39       FROM_HERE, MakeExpectedRunClosure(FROM_HERE), kArbitraryTimeout);
40 
41   // EXPECT_NONFATAL_FAILURE() can only reference globals and statics.
42   static RunLoop& static_loop = run_loop;
43   EXPECT_NONFATAL_FAILURE(static_loop.Run(), "Run() timed out.");
44 }
45 
TEST(ScopedRunLoopTimeoutTest,RunTasksUntilTimeout)46 TEST(ScopedRunLoopTimeoutTest, RunTasksUntilTimeout) {
47   TaskEnvironment task_environment;
48   RunLoop run_loop;
49 
50   static constexpr auto kArbitraryTimeout = Milliseconds(10);
51   ScopedRunLoopTimeout run_timeout(FROM_HERE, kArbitraryTimeout);
52 
53   // Posting a task with the same delay as our timeout, immediately before
54   // calling Run(), means it should get to run. Since this uses QuitWhenIdle(),
55   // the Run() timeout callback should also get to run.
56   SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
57       FROM_HERE, MakeExpectedRunClosure(FROM_HERE), kArbitraryTimeout);
58 
59   // EXPECT_NONFATAL_FAILURE() can only reference globals and statics.
60   static RunLoop& static_loop = run_loop;
61   EXPECT_NONFATAL_FAILURE(static_loop.Run(), "Run() timed out.");
62 }
63 
TEST(ScopedRunLoopTimeoutTest,TimesOutWithInheritedTimeoutValue)64 TEST(ScopedRunLoopTimeoutTest, TimesOutWithInheritedTimeoutValue) {
65   testing::StrictMock<base::MockCallback<RepeatingCallback<std::string()>>>
66       log_callback;
67   TaskEnvironment task_environment;
68   RunLoop run_loop;
69 
70   static constexpr auto kArbitraryTimeout = Milliseconds(10);
71   ScopedRunLoopTimeout run_timeout(FROM_HERE, kArbitraryTimeout);
72   ScopedRunLoopTimeout run_timeout2(FROM_HERE, std::nullopt,
73                                     log_callback.Get());
74 
75   // Since the delayed task will be posted only after the message pump starts
76   // running, the ScopedRunLoopTimeout will already have started to elapse,
77   // so if Run() exits at the correct time then our delayed task will not run.
78   SequencedTaskRunner::GetCurrentDefault()->PostTask(
79       FROM_HERE,
80       BindOnce(IgnoreResult(&SequencedTaskRunner::PostDelayedTask),
81                SequencedTaskRunner::GetCurrentDefault(), FROM_HERE,
82                MakeExpectedNotRunClosure(FROM_HERE), kArbitraryTimeout));
83 
84   // This task should get to run before Run() times-out.
85   SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
86       FROM_HERE, MakeExpectedRunClosure(FROM_HERE), kArbitraryTimeout);
87 
88   EXPECT_CALL(log_callback, Run).WillOnce(testing::Return(std::string()));
89 
90   // EXPECT_NONFATAL_FAILURE() can only reference globals and statics.
91   static RunLoop& static_loop = run_loop;
92   EXPECT_NONFATAL_FAILURE(static_loop.Run(), "Run() timed out.");
93 }
94 
TEST(ScopedRunLoopTimeoutTest,RunTasksUntilTimeoutWithInheritedTimeoutValue)95 TEST(ScopedRunLoopTimeoutTest, RunTasksUntilTimeoutWithInheritedTimeoutValue) {
96   testing::StrictMock<base::MockCallback<RepeatingCallback<std::string()>>>
97       log_callback;
98   TaskEnvironment task_environment;
99   RunLoop run_loop;
100 
101   static constexpr auto kArbitraryTimeout = Milliseconds(10);
102   ScopedRunLoopTimeout run_timeout(FROM_HERE, kArbitraryTimeout);
103   ScopedRunLoopTimeout run_timeout2(FROM_HERE, std::nullopt,
104                                     log_callback.Get());
105 
106   // Posting a task with the same delay as our timeout, immediately before
107   // calling Run(), means it should get to run. Since this uses QuitWhenIdle(),
108   // the Run() timeout callback should also get to run.
109   SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
110       FROM_HERE, MakeExpectedRunClosure(FROM_HERE), kArbitraryTimeout);
111 
112   EXPECT_CALL(log_callback, Run).WillOnce(testing::Return(std::string()));
113 
114   // EXPECT_NONFATAL_FAILURE() can only reference globals and statics.
115   static RunLoop& static_loop = run_loop;
116   EXPECT_NONFATAL_FAILURE(static_loop.Run(), "Run() timed out.");
117 }
118 
119 namespace {
120 
121 constexpr char kErrorMessage[] = "I like kittens!";
122 
123 // Previously these tests hard-coded the file and line numbers; this function
124 // instead generates the expected message given any `FROM_HERE` type location.
GetExpectedTimeoutMessage(const Location & from,const char * expected_message)125 std::string GetExpectedTimeoutMessage(const Location& from,
126                                       const char* expected_message) {
127   std::ostringstream oss;
128   oss << "RunLoop::Run() timed out. Timeout set at " << from.function_name()
129       << "@" << from.file_name() << ":" << from.line_number() << ".\n"
130       << expected_message;
131   return oss.str();
132 }
133 
134 }  // namespace
135 
TEST(ScopedRunLoopTimeoutTest,OnTimeoutLog)136 TEST(ScopedRunLoopTimeoutTest, OnTimeoutLog) {
137   TaskEnvironment task_environment;
138   RunLoop run_loop;
139 
140   static constexpr auto kArbitraryTimeout = Milliseconds(10);
141   const auto location = FROM_HERE;
142   ScopedRunLoopTimeout run_timeout(
143       location, kArbitraryTimeout,
144       BindRepeating([]() -> std::string { return kErrorMessage; }));
145 
146   // EXPECT_NONFATAL_FAILURE() can only reference globals and statics.
147   static RunLoop& static_loop = run_loop;
148   EXPECT_NONFATAL_FAILURE(static_loop.Run(),
149                           GetExpectedTimeoutMessage(location, kErrorMessage));
150 }
151 
TEST(ScopedRunLoopTimeoutTest,OnTimeoutLogWithNestedTimeouts)152 TEST(ScopedRunLoopTimeoutTest, OnTimeoutLogWithNestedTimeouts) {
153   TaskEnvironment task_environment;
154   RunLoop run_loop;
155 
156   static constexpr auto kArbitraryTimeout = Milliseconds(10);
157   ScopedRunLoopTimeout run_timeout(
158       FROM_HERE, base::Hours(1),
159       BindRepeating([]() -> std::string { return "I like puppies!"; }));
160   const auto location = FROM_HERE;
161   ScopedRunLoopTimeout run_timeout2(
162       location, kArbitraryTimeout,
163       BindRepeating([]() -> std::string { return kErrorMessage; }));
164 
165   // EXPECT_NONFATAL_FAILURE() can only reference globals and statics.
166   static RunLoop& static_loop = run_loop;
167   EXPECT_NONFATAL_FAILURE(static_loop.Run(),
168                           GetExpectedTimeoutMessage(location, kErrorMessage));
169 }
170 
TEST(ScopedRunLoopTimeoutTest,OverwriteTimeoutCallbackForTesting)171 TEST(ScopedRunLoopTimeoutTest, OverwriteTimeoutCallbackForTesting) {
172   TaskEnvironment task_environment;
173   RunLoop run_loop;
174 
175   bool custom_handler_called = false;
176   ScopedRunLoopTimeout::TimeoutCallback cb = DoNothing();
177   ScopedRunLoopTimeout::SetTimeoutCallbackForTesting(
178       std::make_unique<ScopedRunLoopTimeout::TimeoutCallback>(
179           std::move(cb).Then(BindLambdaForTesting(
180               [&custom_handler_called]() { custom_handler_called = true; }))));
181   static constexpr auto kArbitraryTimeout = Milliseconds(1);
182   const auto location = FROM_HERE;
183   ScopedRunLoopTimeout run_timeout(
184       location, kArbitraryTimeout,
185       BindRepeating([]() -> std::string { return kErrorMessage; }));
186 
187   // EXPECT_NONFATAL_FAILURE() can only reference globals and statics.
188   static RunLoop& static_loop = run_loop;
189   EXPECT_NONFATAL_FAILURE(static_loop.Run(),
190                           GetExpectedTimeoutMessage(location, kErrorMessage));
191 
192   EXPECT_TRUE(custom_handler_called);
193 
194   ScopedRunLoopTimeout::SetTimeoutCallbackForTesting(nullptr);
195 }
196 
197 }  // namespace base::test
198