xref: /aosp_15_r20/external/cronet/base/task/lazy_thread_pool_task_runner_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 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/lazy_thread_pool_task_runner.h"
6 
7 #include "base/functional/bind.h"
8 #include "base/functional/callback_helpers.h"
9 #include "base/sequence_checker_impl.h"
10 #include "base/task/scoped_set_task_priority_for_current_thread.h"
11 #include "base/test/task_environment.h"
12 #include "base/threading/thread_checker_impl.h"
13 #include "build/build_config.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 #if BUILDFLAG(IS_WIN)
17 #include "base/win/com_init_util.h"
18 #endif
19 
20 namespace base {
21 
22 namespace {
23 
24 LazyThreadPoolSequencedTaskRunner g_sequenced_task_runner_user_visible =
25     LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(
26         TaskTraits(TaskPriority::USER_VISIBLE));
27 LazyThreadPoolSequencedTaskRunner g_sequenced_task_runner_user_blocking =
28     LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(
29         TaskTraits(TaskPriority::USER_BLOCKING));
30 
31 LazyThreadPoolSingleThreadTaskRunner g_single_thread_task_runner_user_visible =
32     LAZY_THREAD_POOL_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(
33         TaskTraits(TaskPriority::USER_VISIBLE),
34         SingleThreadTaskRunnerThreadMode::SHARED);
35 LazyThreadPoolSingleThreadTaskRunner g_single_thread_task_runner_user_blocking =
36     LAZY_THREAD_POOL_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(
37         TaskTraits(TaskPriority::USER_BLOCKING),
38         SingleThreadTaskRunnerThreadMode::SHARED);
39 
40 #if BUILDFLAG(IS_WIN)
41 LazyThreadPoolCOMSTATaskRunner g_com_sta_task_runner_user_visible =
42     LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
43         TaskTraits(TaskPriority::USER_VISIBLE),
44         SingleThreadTaskRunnerThreadMode::SHARED);
45 LazyThreadPoolCOMSTATaskRunner g_com_sta_task_runner_user_blocking =
46     LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
47         TaskTraits(TaskPriority::USER_BLOCKING),
48         SingleThreadTaskRunnerThreadMode::SHARED);
49 #endif  // BUILDFLAG(IS_WIN)
50 
InitCheckers(SequenceCheckerImpl * sequence_checker,ThreadCheckerImpl * thread_checker)51 void InitCheckers(SequenceCheckerImpl* sequence_checker,
52                   ThreadCheckerImpl* thread_checker) {
53   sequence_checker->DetachFromSequence();
54   EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
55   thread_checker->DetachFromThread();
56   EXPECT_TRUE(thread_checker->CalledOnValidThread());
57 }
58 
ExpectSequencedEnvironment(SequenceCheckerImpl * sequence_checker,ThreadCheckerImpl * thread_checker,TaskPriority expected_priority)59 void ExpectSequencedEnvironment(SequenceCheckerImpl* sequence_checker,
60                                 ThreadCheckerImpl* thread_checker,
61                                 TaskPriority expected_priority) {
62   EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
63   EXPECT_FALSE(thread_checker->CalledOnValidThread());
64   EXPECT_EQ(expected_priority, internal::GetTaskPriorityForCurrentThread());
65 }
66 
ExpectSingleThreadEnvironment(SequenceCheckerImpl * sequence_checker,ThreadCheckerImpl * thread_checker,TaskPriority expected_priority,bool expect_com_sta=false)67 void ExpectSingleThreadEnvironment(SequenceCheckerImpl* sequence_checker,
68                                    ThreadCheckerImpl* thread_checker,
69                                    TaskPriority expected_priority
70 #if BUILDFLAG(IS_WIN)
71                                    ,
72                                    bool expect_com_sta = false
73 #endif
74 ) {
75   EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
76   EXPECT_TRUE(thread_checker->CalledOnValidThread());
77   EXPECT_EQ(expected_priority, internal::GetTaskPriorityForCurrentThread());
78 
79 #if BUILDFLAG(IS_WIN)
80   if (expect_com_sta)
81     win::AssertComApartmentType(win::ComApartmentType::STA);
82 #endif
83 }
84 
85 class LazyThreadPoolTaskRunnerEnvironmentTest : public testing::Test {
86  public:
87   LazyThreadPoolTaskRunnerEnvironmentTest(
88       const LazyThreadPoolTaskRunnerEnvironmentTest&) = delete;
89   LazyThreadPoolTaskRunnerEnvironmentTest& operator=(
90       const LazyThreadPoolTaskRunnerEnvironmentTest&) = delete;
91 
92  protected:
93   LazyThreadPoolTaskRunnerEnvironmentTest() = default;
94 
TestTaskRunnerEnvironment(scoped_refptr<SequencedTaskRunner> task_runner,bool expect_single_thread,TaskPriority expected_priority,bool expect_com_sta=false)95   void TestTaskRunnerEnvironment(scoped_refptr<SequencedTaskRunner> task_runner,
96                                  bool expect_single_thread,
97                                  TaskPriority expected_priority
98 #if BUILDFLAG(IS_WIN)
99                                  ,
100                                  bool expect_com_sta = false
101 #endif
102   ) {
103     SequenceCheckerImpl sequence_checker;
104     ThreadCheckerImpl thread_checker;
105     task_runner->PostTask(FROM_HERE,
106                           BindOnce(&InitCheckers, Unretained(&sequence_checker),
107                                    Unretained(&thread_checker)));
108     task_environment_.RunUntilIdle();
109 
110     OnceClosure task =
111         expect_single_thread
112             ? BindOnce(&ExpectSingleThreadEnvironment,
113                        Unretained(&sequence_checker),
114                        Unretained(&thread_checker), expected_priority
115 #if BUILDFLAG(IS_WIN)
116                        ,
117                        expect_com_sta
118 #endif
119                        )
120             : BindOnce(&ExpectSequencedEnvironment,
121                        Unretained(&sequence_checker),
122                        Unretained(&thread_checker), expected_priority);
123     task_runner->PostTask(FROM_HERE, std::move(task));
124     task_environment_.RunUntilIdle();
125   }
126 
127   test::TaskEnvironment task_environment_;
128 };
129 
130 }  // namespace
131 
TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,LazyThreadPoolSequencedTaskRunnerUserVisible)132 TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,
133        LazyThreadPoolSequencedTaskRunnerUserVisible) {
134   TestTaskRunnerEnvironment(g_sequenced_task_runner_user_visible.Get(), false,
135                             TaskPriority::USER_VISIBLE);
136 }
137 
TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,LazyThreadPoolSequencedTaskRunnerUserBlocking)138 TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,
139        LazyThreadPoolSequencedTaskRunnerUserBlocking) {
140   TestTaskRunnerEnvironment(g_sequenced_task_runner_user_blocking.Get(), false,
141                             TaskPriority::USER_BLOCKING);
142 }
143 
TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,LazyThreadPoolSingleThreadTaskRunnerUserVisible)144 TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,
145        LazyThreadPoolSingleThreadTaskRunnerUserVisible) {
146   TestTaskRunnerEnvironment(g_single_thread_task_runner_user_visible.Get(),
147                             true, TaskPriority::USER_VISIBLE);
148 }
149 
TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,LazyThreadPoolSingleThreadTaskRunnerUserBlocking)150 TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,
151        LazyThreadPoolSingleThreadTaskRunnerUserBlocking) {
152   TestTaskRunnerEnvironment(g_single_thread_task_runner_user_blocking.Get(),
153                             true, TaskPriority::USER_BLOCKING);
154 }
155 
156 #if BUILDFLAG(IS_WIN)
TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,LazyThreadPoolCOMSTATaskRunnerUserVisible)157 TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,
158        LazyThreadPoolCOMSTATaskRunnerUserVisible) {
159   TestTaskRunnerEnvironment(g_com_sta_task_runner_user_visible.Get(), true,
160                             TaskPriority::USER_VISIBLE, true);
161 }
162 
TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,LazyThreadPoolCOMSTATaskRunnerUserBlocking)163 TEST_F(LazyThreadPoolTaskRunnerEnvironmentTest,
164        LazyThreadPoolCOMSTATaskRunnerUserBlocking) {
165   TestTaskRunnerEnvironment(g_com_sta_task_runner_user_blocking.Get(), true,
166                             TaskPriority::USER_BLOCKING, true);
167 }
168 #endif  // BUILDFLAG(IS_WIN)
169 
TEST(LazyThreadPoolTaskRunnerTest,LazyThreadPoolSequencedTaskRunnerReset)170 TEST(LazyThreadPoolTaskRunnerTest, LazyThreadPoolSequencedTaskRunnerReset) {
171   for (int i = 0; i < 2; ++i) {
172     test::TaskEnvironment task_environment;
173     // If the TaskRunner isn't released when the test::TaskEnvironment
174     // goes out of scope, the second invocation of the line below will access a
175     // deleted ThreadPoolInstance and crash.
176     g_sequenced_task_runner_user_visible.Get()->PostTask(FROM_HERE,
177                                                          DoNothing());
178   }
179 }
180 
TEST(LazyThreadPoolTaskRunnerTest,LazyThreadPoolSingleThreadTaskRunnerReset)181 TEST(LazyThreadPoolTaskRunnerTest, LazyThreadPoolSingleThreadTaskRunnerReset) {
182   for (int i = 0; i < 2; ++i) {
183     test::TaskEnvironment task_environment;
184     // If the TaskRunner isn't released when the test::TaskEnvironment
185     // goes out of scope, the second invocation of the line below will access a
186     // deleted ThreadPoolInstance and crash.
187     g_single_thread_task_runner_user_visible.Get()->PostTask(FROM_HERE,
188                                                              DoNothing());
189   }
190 }
191 
192 #if BUILDFLAG(IS_WIN)
TEST(LazyThreadPoolTaskRunnerTest,LazyThreadPoolCOMSTATaskRunnerReset)193 TEST(LazyThreadPoolTaskRunnerTest, LazyThreadPoolCOMSTATaskRunnerReset) {
194   for (int i = 0; i < 2; ++i) {
195     test::TaskEnvironment task_environment;
196     // If the TaskRunner isn't released when the test::TaskEnvironment
197     // goes out of scope, the second invocation of the line below will access a
198     // deleted ThreadPoolInstance and crash.
199     g_com_sta_task_runner_user_visible.Get()->PostTask(FROM_HERE, DoNothing());
200   }
201 }
202 #endif  // BUILDFLAG(IS_WIN)
203 
204 }  // namespace base
205