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