xref: /aosp_15_r20/external/cronet/base/task/sequenced_task_runner_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2016 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/task/sequenced_task_runner.h"
6 
7 #include <utility>
8 
9 #include "base/functional/bind.h"
10 #include "base/functional/callback.h"
11 #include "base/functional/callback_helpers.h"
12 #include "base/gtest_prod_util.h"
13 #include "base/location.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/memory/scoped_refptr.h"
16 #include "base/run_loop.h"
17 #include "base/sequence_checker_impl.h"
18 #include "base/task/sequenced_task_runner.h"
19 #include "base/task/thread_pool.h"
20 #include "base/test/bind.h"
21 #include "base/test/gtest_util.h"
22 #include "base/test/null_task_runner.h"
23 #include "base/test/task_environment.h"
24 #include "base/test/test_mock_time_task_runner.h"
25 #include "base/test/test_simple_task_runner.h"
26 #include "base/threading/thread.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 
29 namespace base {
30 namespace {
31 
32 class FlagOnDelete {
33  public:
FlagOnDelete(bool * deleted,scoped_refptr<SequencedTaskRunner> expected_deletion_sequence)34   FlagOnDelete(bool* deleted,
35                scoped_refptr<SequencedTaskRunner> expected_deletion_sequence)
36       : deleted_(deleted),
37         expected_deletion_sequence_(std::move(expected_deletion_sequence)) {}
38   FlagOnDelete(const FlagOnDelete&) = delete;
39   FlagOnDelete& operator=(const FlagOnDelete&) = delete;
40 
~FlagOnDelete()41   ~FlagOnDelete() {
42     EXPECT_FALSE(*deleted_);
43     *deleted_ = true;
44     if (expected_deletion_sequence_)
45       EXPECT_TRUE(expected_deletion_sequence_->RunsTasksInCurrentSequence());
46   }
47 
48  private:
49   raw_ptr<bool> deleted_;
50   const scoped_refptr<SequencedTaskRunner> expected_deletion_sequence_;
51 };
52 
53 class SequencedTaskRunnerTest : public testing::Test {
54  public:
55   SequencedTaskRunnerTest(const SequencedTaskRunnerTest&) = delete;
56   SequencedTaskRunnerTest& operator=(const SequencedTaskRunnerTest&) = delete;
57 
58  protected:
SequencedTaskRunnerTest()59   SequencedTaskRunnerTest() : foreign_thread_("foreign") {}
60 
SetUp()61   void SetUp() override {
62     foreign_thread_.Start();
63     foreign_runner_ = foreign_thread_.task_runner();
64   }
65 
66   scoped_refptr<SequencedTaskRunner> foreign_runner_;
67 
68   Thread foreign_thread_;
69 
70  private:
71   test::TaskEnvironment task_environment_;
72 };
73 
74 }  // namespace
75 
76 using SequenceBoundUniquePtr =
77     std::unique_ptr<FlagOnDelete, OnTaskRunnerDeleter>;
78 
TEST_F(SequencedTaskRunnerTest,OnTaskRunnerDeleterOnMainThread)79 TEST_F(SequencedTaskRunnerTest, OnTaskRunnerDeleterOnMainThread) {
80   bool deleted_on_main_thread = false;
81   SequenceBoundUniquePtr ptr(
82       new FlagOnDelete(&deleted_on_main_thread,
83                        SequencedTaskRunner::GetCurrentDefault()),
84       OnTaskRunnerDeleter(SequencedTaskRunner::GetCurrentDefault()));
85   EXPECT_FALSE(deleted_on_main_thread);
86   foreign_runner_->PostTask(FROM_HERE, DoNothingWithBoundArgs(std::move(ptr)));
87 
88   {
89     RunLoop run_loop;
90     foreign_runner_->PostTaskAndReply(FROM_HERE, BindOnce([] {}),
91                                       run_loop.QuitClosure());
92     run_loop.Run();
93   }
94   EXPECT_TRUE(deleted_on_main_thread);
95 }
96 
TEST_F(SequencedTaskRunnerTest,OnTaskRunnerDeleterTargetStoppedEarly)97 TEST_F(SequencedTaskRunnerTest, OnTaskRunnerDeleterTargetStoppedEarly) {
98   bool deleted_on_main_thread = false;
99   FlagOnDelete* raw = new FlagOnDelete(
100       &deleted_on_main_thread, SequencedTaskRunner::GetCurrentDefault());
101   SequenceBoundUniquePtr ptr(raw, OnTaskRunnerDeleter(foreign_runner_));
102   EXPECT_FALSE(deleted_on_main_thread);
103 
104   // Stopping the target ahead of deleting |ptr| should make its
105   // OnTaskRunnerDeleter no-op.
106   foreign_thread_.Stop();
107   ptr = nullptr;
108   EXPECT_FALSE(deleted_on_main_thread);
109 
110   delete raw;
111   EXPECT_TRUE(deleted_on_main_thread);
112 }
113 
TEST_F(SequencedTaskRunnerTest,DelayedTaskHandle_RunTask)114 TEST_F(SequencedTaskRunnerTest, DelayedTaskHandle_RunTask) {
115   auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
116 
117   bool task_ran = false;
118   DelayedTaskHandle delayed_task_handle =
119       task_runner->PostCancelableDelayedTask(
120           subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
121           BindLambdaForTesting([&task_ran]() { task_ran = true; }), Seconds(1));
122   EXPECT_TRUE(delayed_task_handle.IsValid());
123   EXPECT_TRUE(task_runner->HasPendingTask());
124 
125   // Run the delayed task.
126   task_runner->FastForwardUntilNoTasksRemain();
127 
128   EXPECT_FALSE(delayed_task_handle.IsValid());
129   EXPECT_FALSE(task_runner->HasPendingTask());
130   EXPECT_TRUE(task_ran);
131 }
132 
TEST_F(SequencedTaskRunnerTest,DelayedTaskHandle_CancelTask)133 TEST_F(SequencedTaskRunnerTest, DelayedTaskHandle_CancelTask) {
134   auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
135 
136   bool task_ran = false;
137   DelayedTaskHandle delayed_task_handle =
138       task_runner->PostCancelableDelayedTask(
139           subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
140           BindLambdaForTesting([&task_ran]() { task_ran = true; }), Seconds(1));
141   EXPECT_TRUE(delayed_task_handle.IsValid());
142   EXPECT_TRUE(task_runner->HasPendingTask());
143 
144   // Cancel the delayed task.
145   delayed_task_handle.CancelTask();
146 
147   EXPECT_FALSE(delayed_task_handle.IsValid());
148   EXPECT_FALSE(task_runner->HasPendingTask());
149   EXPECT_FALSE(task_ran);
150 }
151 
TEST_F(SequencedTaskRunnerTest,DelayedTaskHandle_DestroyTask)152 TEST_F(SequencedTaskRunnerTest, DelayedTaskHandle_DestroyTask) {
153   auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
154 
155   bool task_ran = false;
156   DelayedTaskHandle delayed_task_handle =
157       task_runner->PostCancelableDelayedTask(
158           subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
159           BindLambdaForTesting([&task_ran]() { task_ran = true; }), Seconds(1));
160   EXPECT_TRUE(delayed_task_handle.IsValid());
161   EXPECT_TRUE(task_runner->HasPendingTask());
162 
163   // Destroy the pending task.
164   task_runner->ClearPendingTasks();
165 
166   EXPECT_FALSE(delayed_task_handle.IsValid());
167   EXPECT_FALSE(task_runner->HasPendingTask());
168   EXPECT_FALSE(task_ran);
169 }
170 
171 // Tests that if PostCancelableDelayedTask() fails, the returned handle will be
172 // invalid.
TEST_F(SequencedTaskRunnerTest,DelayedTaskHandle_PostTaskFailed)173 TEST_F(SequencedTaskRunnerTest, DelayedTaskHandle_PostTaskFailed) {
174   auto task_runner = MakeRefCounted<NullTaskRunner>();
175 
176   bool task_ran = false;
177   DelayedTaskHandle delayed_task_handle =
178       task_runner->PostCancelableDelayedTask(
179           subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
180           BindLambdaForTesting([&task_ran]() { task_ran = true; }), Seconds(1));
181   EXPECT_FALSE(delayed_task_handle.IsValid());
182   EXPECT_FALSE(task_ran);
183 }
184 
185 namespace {
186 
187 // Tests for the SequencedTaskRunner::CurrentDefaultHandle machinery.
188 class SequencedTaskRunnerCurrentDefaultHandleTest : public ::testing::Test {
189  protected:
190   // Verifies that the context it runs on has a
191   // SequencedTaskRunner::CurrentDefaultHandle and that posting to it results in
192   // the posted task running in that same context (sequence).
VerifyCurrentSequencedTaskRunner()193   static void VerifyCurrentSequencedTaskRunner() {
194     ASSERT_TRUE(SequencedTaskRunner::HasCurrentDefault());
195     scoped_refptr<SequencedTaskRunner> task_runner =
196         SequencedTaskRunner::GetCurrentDefault();
197     ASSERT_TRUE(task_runner);
198 
199     // Use SequenceCheckerImpl to make sure it's not a no-op in Release builds.
200     std::unique_ptr<SequenceCheckerImpl> sequence_checker =
201         std::make_unique<SequenceCheckerImpl>();
202     task_runner->PostTask(
203         FROM_HERE,
204         base::BindOnce(
205             &SequencedTaskRunnerCurrentDefaultHandleTest::CheckValidSequence,
206             std::move(sequence_checker)));
207   }
208 
CheckValidSequence(std::unique_ptr<SequenceCheckerImpl> sequence_checker)209   static void CheckValidSequence(
210       std::unique_ptr<SequenceCheckerImpl> sequence_checker) {
211     EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
212   }
213 
214   test::TaskEnvironment task_environment_;
215 };
216 
217 }  // namespace
218 
TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest,FromTaskEnvironment)219 TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest, FromTaskEnvironment) {
220   VerifyCurrentSequencedTaskRunner();
221   RunLoop().RunUntilIdle();
222 }
223 
TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest,FromThreadPoolSequencedTask)224 TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest,
225        FromThreadPoolSequencedTask) {
226   base::ThreadPool::CreateSequencedTaskRunner({})->PostTask(
227       FROM_HERE, base::BindOnce(&SequencedTaskRunnerCurrentDefaultHandleTest::
228                                     VerifyCurrentSequencedTaskRunner));
229   task_environment_.RunUntilIdle();
230 }
231 
TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest,NoHandleFromUnsequencedTask)232 TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest,
233        NoHandleFromUnsequencedTask) {
234   base::ThreadPool::PostTask(base::BindOnce(
235       []() { EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault()); }));
236   task_environment_.RunUntilIdle();
237 }
238 
239 // Verify that `CurrentDefaultHandle` can be used to set the current default
240 // `SequencedTaskRunner` to null in a scope that already has a default.
TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest,OverrideWithNull)241 TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest, OverrideWithNull) {
242   EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
243   auto tr1 = SequencedTaskRunner::GetCurrentDefault();
244   EXPECT_TRUE(tr1);
245 
246   {
247     SequencedTaskRunner::CurrentDefaultHandle handle(
248         nullptr, SequencedTaskRunner::CurrentDefaultHandle::MayAlreadyExist{});
249     EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
250     EXPECT_CHECK_DEATH(
251         { auto tr2 = SequencedTaskRunner::GetCurrentDefault(); });
252   }
253 
254   EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
255   EXPECT_EQ(tr1, SequencedTaskRunner::GetCurrentDefault());
256 }
257 
258 // Verify that `CurrentDefaultHandle` can be used to set the current default
259 // `SequencedTaskRunner` to a non-null value in a scope that already has a
260 // default.
TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest,OverrideWithNonNull)261 TEST_F(SequencedTaskRunnerCurrentDefaultHandleTest, OverrideWithNonNull) {
262   EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
263   auto tr1 = SequencedTaskRunner::GetCurrentDefault();
264   EXPECT_TRUE(tr1);
265 
266   {
267     auto tr2 = MakeRefCounted<TestSimpleTaskRunner>();
268     SequencedTaskRunner::CurrentDefaultHandle handle(
269         tr2, SequencedTaskRunner::CurrentDefaultHandle::MayAlreadyExist{});
270     EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
271     EXPECT_EQ(tr2, SequencedTaskRunner::GetCurrentDefault());
272   }
273 
274   EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
275   EXPECT_EQ(tr1, SequencedTaskRunner::GetCurrentDefault());
276 }
277 
TEST(SequencedTaskRunnerCurrentDefaultHandleTestWithoutTaskEnvironment,FromHandleInScope)278 TEST(SequencedTaskRunnerCurrentDefaultHandleTestWithoutTaskEnvironment,
279      FromHandleInScope) {
280   scoped_refptr<SequencedTaskRunner> test_task_runner =
281       MakeRefCounted<TestSimpleTaskRunner>();
282   EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
283   EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
284   {
285     SequencedTaskRunner::CurrentDefaultHandle current_default(test_task_runner);
286     EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
287     EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
288     EXPECT_EQ(test_task_runner, SequencedTaskRunner::GetCurrentDefault());
289   }
290   EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
291   EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
292 }
293 
294 }  // namespace base
295