• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/thread_pool/pooled_single_thread_task_runner_manager.h"
6 
7 #include "base/functional/bind.h"
8 #include "base/functional/callback_helpers.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/memory/raw_ptr.h"
11 #include "base/synchronization/atomic_flag.h"
12 #include "base/synchronization/lock.h"
13 #include "base/task/task_traits.h"
14 #include "base/task/thread_pool/can_run_policy_test.h"
15 #include "base/task/thread_pool/delayed_task_manager.h"
16 #include "base/task/thread_pool/environment_config.h"
17 #include "base/task/thread_pool/task_tracker.h"
18 #include "base/task/thread_pool/test_utils.h"
19 #include "base/test/bind.h"
20 #include "base/test/gtest_util.h"
21 #include "base/test/scoped_feature_list.h"
22 #include "base/test/test_timeouts.h"
23 #include "base/test/test_waitable_event.h"
24 #include "base/threading/platform_thread.h"
25 #include "base/threading/simple_thread.h"
26 #include "base/threading/thread.h"
27 #include "base/threading/thread_restrictions.h"
28 #include "build/build_config.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 
31 #if BUILDFLAG(IS_WIN)
32 #include <windows.h>
33 
34 #include "base/win/com_init_util.h"
35 #include "base/win/current_module.h"
36 #endif  // BUILDFLAG(IS_WIN)
37 
38 namespace base {
39 namespace internal {
40 
41 namespace {
42 
43 class PooledSingleThreadTaskRunnerManagerTest : public testing::Test {
44  public:
45   PooledSingleThreadTaskRunnerManagerTest(
46       const PooledSingleThreadTaskRunnerManagerTest&) = delete;
47   PooledSingleThreadTaskRunnerManagerTest& operator=(
48       const PooledSingleThreadTaskRunnerManagerTest&) = delete;
49 
50  protected:
51   PooledSingleThreadTaskRunnerManagerTest() = default;
52 
SetUp()53   void SetUp() override {
54     service_thread_.Start();
55     delayed_task_manager_.Start(service_thread_.task_runner());
56     single_thread_task_runner_manager_ =
57         std::make_unique<PooledSingleThreadTaskRunnerManager>(
58             task_tracker_.GetTrackedRef(), &delayed_task_manager_);
59     StartSingleThreadTaskRunnerManagerFromSetUp();
60   }
61 
TearDown()62   void TearDown() override {
63     if (single_thread_task_runner_manager_)
64       TearDownSingleThreadTaskRunnerManager();
65     delayed_task_manager_.Shutdown();
66     service_thread_.Stop();
67   }
68 
StartSingleThreadTaskRunnerManagerFromSetUp()69   virtual void StartSingleThreadTaskRunnerManagerFromSetUp() {
70     single_thread_task_runner_manager_->Start(service_thread_.task_runner());
71   }
72 
TearDownSingleThreadTaskRunnerManager()73   virtual void TearDownSingleThreadTaskRunnerManager() {
74     single_thread_task_runner_manager_->JoinForTesting();
75     single_thread_task_runner_manager_.reset();
76   }
77 
78   Thread service_thread_{"ThreadPoolServiceThread"};
79   TaskTracker task_tracker_;
80   DelayedTaskManager delayed_task_manager_;
81   std::unique_ptr<PooledSingleThreadTaskRunnerManager>
82       single_thread_task_runner_manager_;
83 };
84 
CaptureThreadRef(PlatformThreadRef * thread_ref)85 void CaptureThreadRef(PlatformThreadRef* thread_ref) {
86   ASSERT_TRUE(thread_ref);
87   *thread_ref = PlatformThread::CurrentRef();
88 }
89 
ShouldNotRun()90 void ShouldNotRun() {
91   ADD_FAILURE() << "Ran a task that shouldn't run.";
92 }
93 
94 }  // namespace
95 
TEST_F(PooledSingleThreadTaskRunnerManagerTest,DifferentThreadsUsed)96 TEST_F(PooledSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) {
97   scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
98       single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
99           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
100           SingleThreadTaskRunnerThreadMode::DEDICATED);
101   scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
102       single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
103           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
104           SingleThreadTaskRunnerThreadMode::DEDICATED);
105 
106   PlatformThreadRef thread_ref_1;
107   task_runner_1->PostTask(FROM_HERE,
108                           BindOnce(&CaptureThreadRef, &thread_ref_1));
109   PlatformThreadRef thread_ref_2;
110   task_runner_2->PostTask(FROM_HERE,
111                           BindOnce(&CaptureThreadRef, &thread_ref_2));
112 
113   test::ShutdownTaskTracker(&task_tracker_);
114 
115   ASSERT_FALSE(thread_ref_1.is_null());
116   ASSERT_FALSE(thread_ref_2.is_null());
117   EXPECT_NE(thread_ref_1, thread_ref_2);
118 }
119 
TEST_F(PooledSingleThreadTaskRunnerManagerTest,SameThreadUsed)120 TEST_F(PooledSingleThreadTaskRunnerManagerTest, SameThreadUsed) {
121   scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
122       single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
123           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
124           SingleThreadTaskRunnerThreadMode::SHARED);
125   scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
126       single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
127           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
128           SingleThreadTaskRunnerThreadMode::SHARED);
129 
130   PlatformThreadRef thread_ref_1;
131   task_runner_1->PostTask(FROM_HERE,
132                           BindOnce(&CaptureThreadRef, &thread_ref_1));
133   PlatformThreadRef thread_ref_2;
134   task_runner_2->PostTask(FROM_HERE,
135                           BindOnce(&CaptureThreadRef, &thread_ref_2));
136 
137   test::ShutdownTaskTracker(&task_tracker_);
138 
139   ASSERT_FALSE(thread_ref_1.is_null());
140   ASSERT_FALSE(thread_ref_2.is_null());
141   EXPECT_EQ(thread_ref_1, thread_ref_2);
142 }
143 
TEST_F(PooledSingleThreadTaskRunnerManagerTest,RunsTasksInCurrentSequence)144 TEST_F(PooledSingleThreadTaskRunnerManagerTest, RunsTasksInCurrentSequence) {
145   scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
146       single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
147           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
148           SingleThreadTaskRunnerThreadMode::DEDICATED);
149   scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
150       single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
151           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
152           SingleThreadTaskRunnerThreadMode::DEDICATED);
153 
154   EXPECT_FALSE(task_runner_1->RunsTasksInCurrentSequence());
155   EXPECT_FALSE(task_runner_2->RunsTasksInCurrentSequence());
156 
157   task_runner_1->PostTask(
158       FROM_HERE,
159       BindOnce(
160           [](scoped_refptr<SingleThreadTaskRunner> task_runner_1,
161              scoped_refptr<SingleThreadTaskRunner> task_runner_2) {
162             EXPECT_TRUE(task_runner_1->RunsTasksInCurrentSequence());
163             EXPECT_FALSE(task_runner_2->RunsTasksInCurrentSequence());
164           },
165           task_runner_1, task_runner_2));
166 
167   task_runner_2->PostTask(
168       FROM_HERE,
169       BindOnce(
170           [](scoped_refptr<SingleThreadTaskRunner> task_runner_1,
171              scoped_refptr<SingleThreadTaskRunner> task_runner_2) {
172             EXPECT_FALSE(task_runner_1->RunsTasksInCurrentSequence());
173             EXPECT_TRUE(task_runner_2->RunsTasksInCurrentSequence());
174           },
175           task_runner_1, task_runner_2));
176 
177   test::ShutdownTaskTracker(&task_tracker_);
178 }
179 
TEST_F(PooledSingleThreadTaskRunnerManagerTest,SharedWithBaseSyncPrimitivesDCHECKs)180 TEST_F(PooledSingleThreadTaskRunnerManagerTest,
181        SharedWithBaseSyncPrimitivesDCHECKs) {
182   GTEST_FLAG_SET(death_test_style, "threadsafe");
183   EXPECT_DCHECK_DEATH({
184     single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
185         {WithBaseSyncPrimitives()}, SingleThreadTaskRunnerThreadMode::SHARED);
186   });
187 }
188 
189 // Regression test for https://crbug.com/829786
TEST_F(PooledSingleThreadTaskRunnerManagerTest,ContinueOnShutdownDoesNotBlockBlockShutdown)190 TEST_F(PooledSingleThreadTaskRunnerManagerTest,
191        ContinueOnShutdownDoesNotBlockBlockShutdown) {
192   TestWaitableEvent task_has_started;
193   TestWaitableEvent task_can_continue;
194 
195   // Post a CONTINUE_ON_SHUTDOWN task that waits on
196   // |task_can_continue| to a shared SingleThreadTaskRunner.
197   single_thread_task_runner_manager_
198       ->CreateSingleThreadTaskRunner(
199           {TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
200           SingleThreadTaskRunnerThreadMode::SHARED)
201       ->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
202                    task_has_started.Signal();
203                    task_can_continue.Wait();
204                  }));
205 
206   task_has_started.Wait();
207 
208   // Post a BLOCK_SHUTDOWN task to a shared SingleThreadTaskRunner.
209   single_thread_task_runner_manager_
210       ->CreateSingleThreadTaskRunner({TaskShutdownBehavior::BLOCK_SHUTDOWN},
211                                      SingleThreadTaskRunnerThreadMode::SHARED)
212       ->PostTask(FROM_HERE, DoNothing());
213 
214   // Shutdown should not hang even though the first task hasn't finished.
215   test::ShutdownTaskTracker(&task_tracker_);
216 
217   // Let the first task finish.
218   task_can_continue.Signal();
219 
220   // Tear down from the test body to prevent accesses to |task_can_continue|
221   // after it goes out of scope.
222   TearDownSingleThreadTaskRunnerManager();
223 }
224 
225 namespace {
226 
227 class PooledSingleThreadTaskRunnerManagerCommonTest
228     : public PooledSingleThreadTaskRunnerManagerTest,
229       public ::testing::WithParamInterface<
230           std::tuple<SingleThreadTaskRunnerThreadMode,
231                      bool /* enable_utility_threads */>> {
232  public:
PooledSingleThreadTaskRunnerManagerCommonTest()233   PooledSingleThreadTaskRunnerManagerCommonTest() {
234     if (std::get<1>(GetParam())) {
235       feature_list_.InitWithFeatures({kUseUtilityThreadGroup}, {});
236     }
237   }
238   PooledSingleThreadTaskRunnerManagerCommonTest(
239       const PooledSingleThreadTaskRunnerManagerCommonTest&) = delete;
240   PooledSingleThreadTaskRunnerManagerCommonTest& operator=(
241       const PooledSingleThreadTaskRunnerManagerCommonTest&) = delete;
242 
CreateTaskRunner(TaskTraits traits={})243   scoped_refptr<SingleThreadTaskRunner> CreateTaskRunner(
244       TaskTraits traits = {}) {
245     return single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
246         traits, GetSingleThreadTaskRunnerThreadMode());
247   }
248 
GetSingleThreadTaskRunnerThreadMode() const249   SingleThreadTaskRunnerThreadMode GetSingleThreadTaskRunnerThreadMode() const {
250     return std::get<0>(GetParam());
251   }
252 
253  protected:
254   const bool use_utility_thread_group_ =
255       CanUseUtilityThreadTypeForWorkerThread() && std::get<1>(GetParam());
256   base::test::ScopedFeatureList feature_list_;
257 };
258 
259 }  // namespace
260 
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,ThreadTypeSetCorrectly)261 TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, ThreadTypeSetCorrectly) {
262   const struct {
263     TaskTraits traits;
264     ThreadType expected_thread_type;
265   } test_cases[] = {
266       {{TaskPriority::BEST_EFFORT},
267        CanUseBackgroundThreadTypeForWorkerThread() ? ThreadType::kBackground
268        : use_utility_thread_group_                 ? ThreadType::kUtility
269                                                    : ThreadType::kDefault},
270       {{TaskPriority::BEST_EFFORT, ThreadPolicy::PREFER_BACKGROUND},
271        CanUseBackgroundThreadTypeForWorkerThread() ? ThreadType::kBackground
272        : use_utility_thread_group_                 ? ThreadType::kUtility
273                                                    : ThreadType::kDefault},
274       {{TaskPriority::BEST_EFFORT, ThreadPolicy::MUST_USE_FOREGROUND},
275        ThreadType::kDefault},
276       {{TaskPriority::USER_VISIBLE},
277        use_utility_thread_group_ ? ThreadType::kUtility : ThreadType::kDefault},
278       {{TaskPriority::USER_VISIBLE, ThreadPolicy::PREFER_BACKGROUND},
279        use_utility_thread_group_ ? ThreadType::kUtility : ThreadType::kDefault},
280       {{TaskPriority::USER_VISIBLE, ThreadPolicy::MUST_USE_FOREGROUND},
281        ThreadType::kDefault},
282       {{TaskPriority::USER_BLOCKING}, ThreadType::kDefault},
283       {{TaskPriority::USER_BLOCKING, ThreadPolicy::PREFER_BACKGROUND},
284        ThreadType::kDefault},
285       {{TaskPriority::USER_BLOCKING, ThreadPolicy::MUST_USE_FOREGROUND},
286        ThreadType::kDefault}};
287 
288   // Why are events used here instead of the task tracker?
289   // Shutting down can cause priorities to get raised. This means we have to use
290   // events to determine when a task is run.
291   for (auto& test_case : test_cases) {
292     TestWaitableEvent event;
293     CreateTaskRunner(test_case.traits)
294         ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
295                      EXPECT_EQ(test_case.expected_thread_type,
296                                PlatformThread::GetCurrentThreadType());
297                      event.Signal();
298                    }));
299     event.Wait();
300   }
301 }
302 
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,ThreadNamesSet)303 TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, ThreadNamesSet) {
304   const std::string maybe_shared(
305       GetSingleThreadTaskRunnerThreadMode() ==
306               SingleThreadTaskRunnerThreadMode::DEDICATED
307           ? ""
308           : "Shared");
309   const std::string background =
310       "^ThreadPoolSingleThread" + maybe_shared + "Background\\d+$";
311   const std::string utility =
312       "^ThreadPoolSingleThread" + maybe_shared + "Utility\\d+$";
313   const std::string foreground =
314       "^ThreadPoolSingleThread" + maybe_shared + "Foreground\\d+$";
315   const std::string background_blocking =
316       "^ThreadPoolSingleThread" + maybe_shared + "BackgroundBlocking\\d+$";
317   const std::string utility_blocking =
318       "^ThreadPoolSingleThread" + maybe_shared + "UtilityBlocking\\d+$";
319   const std::string foreground_blocking =
320       "^ThreadPoolSingleThread" + maybe_shared + "ForegroundBlocking\\d+$";
321 
322   const struct {
323     TaskTraits traits;
324     std::string expected_thread_name;
325   } test_cases[] = {
326       // Non-MayBlock()
327       {{TaskPriority::BEST_EFFORT},
328        CanUseBackgroundThreadTypeForWorkerThread() ? background
329        : use_utility_thread_group_                 ? utility
330                                                    : foreground},
331       {{TaskPriority::BEST_EFFORT, ThreadPolicy::PREFER_BACKGROUND},
332        CanUseBackgroundThreadTypeForWorkerThread() ? background
333        : use_utility_thread_group_                 ? utility
334                                                    : foreground},
335       {{TaskPriority::BEST_EFFORT, ThreadPolicy::MUST_USE_FOREGROUND},
336        foreground},
337       {{TaskPriority::USER_VISIBLE},
338        use_utility_thread_group_ ? utility : foreground},
339       {{TaskPriority::USER_VISIBLE, ThreadPolicy::PREFER_BACKGROUND},
340        use_utility_thread_group_ ? utility : foreground},
341       {{TaskPriority::USER_VISIBLE, ThreadPolicy::MUST_USE_FOREGROUND},
342        foreground},
343       {{TaskPriority::USER_BLOCKING}, foreground},
344       {{TaskPriority::USER_BLOCKING, ThreadPolicy::PREFER_BACKGROUND},
345        foreground},
346       {{TaskPriority::USER_BLOCKING, ThreadPolicy::MUST_USE_FOREGROUND},
347        foreground},
348 
349       // MayBlock()
350       {{TaskPriority::BEST_EFFORT, MayBlock()},
351        CanUseBackgroundThreadTypeForWorkerThread() ? background_blocking
352        : use_utility_thread_group_                 ? utility_blocking
353                                                    : foreground_blocking},
354       {{TaskPriority::BEST_EFFORT, ThreadPolicy::PREFER_BACKGROUND, MayBlock()},
355        CanUseBackgroundThreadTypeForWorkerThread() ? background_blocking
356        : use_utility_thread_group_                 ? utility_blocking
357                                                    : foreground_blocking},
358       {{TaskPriority::BEST_EFFORT, ThreadPolicy::MUST_USE_FOREGROUND,
359         MayBlock()},
360        foreground_blocking},
361       {{TaskPriority::USER_VISIBLE, MayBlock()},
362        use_utility_thread_group_ ? utility_blocking : foreground_blocking},
363       {{TaskPriority::USER_VISIBLE, ThreadPolicy::PREFER_BACKGROUND,
364         MayBlock()},
365        use_utility_thread_group_ ? utility_blocking : foreground_blocking},
366       {{TaskPriority::USER_VISIBLE, ThreadPolicy::MUST_USE_FOREGROUND,
367         MayBlock()},
368 
369        foreground_blocking},
370       {{TaskPriority::USER_BLOCKING, MayBlock()}, foreground_blocking},
371       {{TaskPriority::USER_BLOCKING, ThreadPolicy::PREFER_BACKGROUND,
372         MayBlock()},
373        foreground_blocking},
374       {{TaskPriority::USER_BLOCKING, ThreadPolicy::MUST_USE_FOREGROUND,
375         MayBlock()},
376        foreground_blocking}};
377 
378   for (auto& test_case : test_cases) {
379     TestWaitableEvent event;
380     CreateTaskRunner(test_case.traits)
381         ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
382                      EXPECT_THAT(PlatformThread::GetName(),
383                                  ::testing::MatchesRegex(
384                                      test_case.expected_thread_name));
385                      event.Signal();
386                    }));
387     event.Wait();
388   }
389 }
390 
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,PostTaskAfterShutdown)391 TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PostTaskAfterShutdown) {
392   auto task_runner = CreateTaskRunner();
393   test::ShutdownTaskTracker(&task_tracker_);
394   EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun)));
395 }
396 
397 // Verify that a Task runs shortly after its delay expires.
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,PostDelayedTask)398 TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PostDelayedTask) {
399   TestWaitableEvent task_ran(WaitableEvent::ResetPolicy::AUTOMATIC);
400   auto task_runner = CreateTaskRunner();
401 
402   // Wait until the task runner is up and running to make sure the test below is
403   // solely timing the delayed task, not bringing up a physical thread.
404   task_runner->PostTask(
405       FROM_HERE, BindOnce(&TestWaitableEvent::Signal, Unretained(&task_ran)));
406   task_ran.Wait();
407   ASSERT_TRUE(!task_ran.IsSignaled());
408 
409 
410   // Post a task with a short delay.
411   const TimeTicks start_time = TimeTicks::Now();
412   EXPECT_TRUE(task_runner->PostDelayedTask(
413       FROM_HERE, BindOnce(&TestWaitableEvent::Signal, Unretained(&task_ran)),
414       TestTimeouts::tiny_timeout()));
415 
416   // Wait until the task runs.
417   task_ran.Wait();
418 
419   // Expect the task to run after its delay expires, but no more than a
420   // reasonable amount of time after that (overloaded bots can be slow sometimes
421   // so give it 10X flexibility).
422   const TimeDelta actual_delay = TimeTicks::Now() - start_time;
423   EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout());
424   EXPECT_LT(actual_delay, 10 * TestTimeouts::tiny_timeout());
425 }
426 
427 // Verify that posting tasks after the single-thread manager is destroyed fails
428 // but doesn't crash.
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,PostTaskAfterDestroy)429 TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PostTaskAfterDestroy) {
430   auto task_runner = CreateTaskRunner();
431   EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing()));
432   test::ShutdownTaskTracker(&task_tracker_);
433   TearDownSingleThreadTaskRunnerManager();
434   EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun)));
435 }
436 
437 // Verify that tasks only run when allowed by the CanRunPolicy.
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,CanRunPolicyBasic)438 TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, CanRunPolicyBasic) {
439   test::TestCanRunPolicyBasic(
440       single_thread_task_runner_manager_.get(),
441       [this](TaskPriority priority) { return CreateTaskRunner({priority}); },
442       &task_tracker_);
443 }
444 
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,CanRunPolicyUpdatedBeforeRun)445 TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,
446        CanRunPolicyUpdatedBeforeRun) {
447   test::TestCanRunPolicyChangedBeforeRun(
448       single_thread_task_runner_manager_.get(),
449       [this](TaskPriority priority) { return CreateTaskRunner({priority}); },
450       &task_tracker_);
451 }
452 
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,CanRunPolicyLoad)453 TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, CanRunPolicyLoad) {
454   test::TestCanRunPolicyLoad(
455       single_thread_task_runner_manager_.get(),
456       [this](TaskPriority priority) { return CreateTaskRunner({priority}); },
457       &task_tracker_);
458 }
459 
460 INSTANTIATE_TEST_SUITE_P(
461     SharedAndDedicated,
462     PooledSingleThreadTaskRunnerManagerCommonTest,
463     ::testing::Combine(
464         ::testing::Values(SingleThreadTaskRunnerThreadMode::SHARED,
465                           SingleThreadTaskRunnerThreadMode::DEDICATED),
466         ::testing::Values(false, true)));
467 
468 namespace {
469 
470 class CallJoinFromDifferentThread : public SimpleThread {
471  public:
CallJoinFromDifferentThread(PooledSingleThreadTaskRunnerManager * manager_to_join)472   CallJoinFromDifferentThread(
473       PooledSingleThreadTaskRunnerManager* manager_to_join)
474       : SimpleThread("PooledSingleThreadTaskRunnerManagerJoinThread"),
475         manager_to_join_(manager_to_join) {}
476 
477   CallJoinFromDifferentThread(const CallJoinFromDifferentThread&) = delete;
478   CallJoinFromDifferentThread& operator=(const CallJoinFromDifferentThread&) =
479       delete;
480   ~CallJoinFromDifferentThread() override = default;
481 
Run()482   void Run() override {
483     run_started_event_.Signal();
484     manager_to_join_->JoinForTesting();
485   }
486 
WaitForRunToStart()487   void WaitForRunToStart() { run_started_event_.Wait(); }
488 
489  private:
490   const raw_ptr<PooledSingleThreadTaskRunnerManager> manager_to_join_;
491   TestWaitableEvent run_started_event_;
492 };
493 
494 class PooledSingleThreadTaskRunnerManagerJoinTest
495     : public PooledSingleThreadTaskRunnerManagerTest {
496  public:
497   PooledSingleThreadTaskRunnerManagerJoinTest() = default;
498   PooledSingleThreadTaskRunnerManagerJoinTest(
499       const PooledSingleThreadTaskRunnerManagerJoinTest&) = delete;
500   PooledSingleThreadTaskRunnerManagerJoinTest& operator=(
501       const PooledSingleThreadTaskRunnerManagerJoinTest&) = delete;
502   ~PooledSingleThreadTaskRunnerManagerJoinTest() override = default;
503 
504  protected:
TearDownSingleThreadTaskRunnerManager()505   void TearDownSingleThreadTaskRunnerManager() override {
506     // The tests themselves are responsible for calling JoinForTesting().
507     single_thread_task_runner_manager_.reset();
508   }
509 };
510 
511 }  // namespace
512 
TEST_F(PooledSingleThreadTaskRunnerManagerJoinTest,ConcurrentJoin)513 TEST_F(PooledSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) {
514   // Exercises the codepath where the workers are unavailable for unregistration
515   // because of a Join call.
516   TestWaitableEvent task_running;
517   TestWaitableEvent task_blocking;
518 
519   {
520     auto task_runner =
521         single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
522             {WithBaseSyncPrimitives()},
523             SingleThreadTaskRunnerThreadMode::DEDICATED);
524     EXPECT_TRUE(task_runner->PostTask(
525         FROM_HERE,
526         BindOnce(&TestWaitableEvent::Signal, Unretained(&task_running))));
527     EXPECT_TRUE(task_runner->PostTask(
528         FROM_HERE,
529         BindOnce(&TestWaitableEvent::Wait, Unretained(&task_blocking))));
530   }
531 
532   task_running.Wait();
533   CallJoinFromDifferentThread join_from_different_thread(
534       single_thread_task_runner_manager_.get());
535   join_from_different_thread.Start();
536   join_from_different_thread.WaitForRunToStart();
537   task_blocking.Signal();
538   join_from_different_thread.Join();
539 }
540 
TEST_F(PooledSingleThreadTaskRunnerManagerJoinTest,ConcurrentJoinExtraSkippedTask)541 TEST_F(PooledSingleThreadTaskRunnerManagerJoinTest,
542        ConcurrentJoinExtraSkippedTask) {
543   // Tests to make sure that tasks are properly cleaned up at Join, allowing
544   // SingleThreadTaskRunners to unregister themselves.
545   TestWaitableEvent task_running;
546   TestWaitableEvent task_blocking;
547 
548   {
549     auto task_runner =
550         single_thread_task_runner_manager_->CreateSingleThreadTaskRunner(
551             {WithBaseSyncPrimitives()},
552             SingleThreadTaskRunnerThreadMode::DEDICATED);
553     EXPECT_TRUE(task_runner->PostTask(
554         FROM_HERE,
555         BindOnce(&TestWaitableEvent::Signal, Unretained(&task_running))));
556     EXPECT_TRUE(task_runner->PostTask(
557         FROM_HERE,
558         BindOnce(&TestWaitableEvent::Wait, Unretained(&task_blocking))));
559     EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing()));
560   }
561 
562   task_running.Wait();
563   CallJoinFromDifferentThread join_from_different_thread(
564       single_thread_task_runner_manager_.get());
565   join_from_different_thread.Start();
566   join_from_different_thread.WaitForRunToStart();
567   task_blocking.Signal();
568   join_from_different_thread.Join();
569 }
570 
571 #if BUILDFLAG(IS_WIN)
572 
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,COMSTAInitialized)573 TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, COMSTAInitialized) {
574   scoped_refptr<SingleThreadTaskRunner> com_task_runner =
575       single_thread_task_runner_manager_->CreateCOMSTATaskRunner(
576           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
577           GetSingleThreadTaskRunnerThreadMode());
578 
579   com_task_runner->PostTask(FROM_HERE, BindOnce(&win::AssertComApartmentType,
580                                                 win::ComApartmentType::STA));
581 
582   test::ShutdownTaskTracker(&task_tracker_);
583 }
584 
TEST_F(PooledSingleThreadTaskRunnerManagerTest,COMSTASameThreadUsed)585 TEST_F(PooledSingleThreadTaskRunnerManagerTest, COMSTASameThreadUsed) {
586   scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
587       single_thread_task_runner_manager_->CreateCOMSTATaskRunner(
588           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
589           SingleThreadTaskRunnerThreadMode::SHARED);
590   scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
591       single_thread_task_runner_manager_->CreateCOMSTATaskRunner(
592           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
593           SingleThreadTaskRunnerThreadMode::SHARED);
594 
595   PlatformThreadRef thread_ref_1;
596   task_runner_1->PostTask(FROM_HERE,
597                           BindOnce(&CaptureThreadRef, &thread_ref_1));
598   PlatformThreadRef thread_ref_2;
599   task_runner_2->PostTask(FROM_HERE,
600                           BindOnce(&CaptureThreadRef, &thread_ref_2));
601 
602   test::ShutdownTaskTracker(&task_tracker_);
603 
604   ASSERT_FALSE(thread_ref_1.is_null());
605   ASSERT_FALSE(thread_ref_2.is_null());
606   EXPECT_EQ(thread_ref_1, thread_ref_2);
607 }
608 
609 namespace {
610 
611 const wchar_t* const kTestWindowClassName =
612     L"PooledSingleThreadTaskRunnerManagerTestWinMessageWindow";
613 
614 class PooledSingleThreadTaskRunnerManagerTestWin
615     : public PooledSingleThreadTaskRunnerManagerTest {
616  public:
617   PooledSingleThreadTaskRunnerManagerTestWin() = default;
618   PooledSingleThreadTaskRunnerManagerTestWin(
619       const PooledSingleThreadTaskRunnerManagerTestWin&) = delete;
620   PooledSingleThreadTaskRunnerManagerTestWin& operator=(
621       const PooledSingleThreadTaskRunnerManagerTestWin&) = delete;
622 
SetUp()623   void SetUp() override {
624     PooledSingleThreadTaskRunnerManagerTest::SetUp();
625     register_class_succeeded_ = RegisterTestWindowClass();
626     ASSERT_TRUE(register_class_succeeded_);
627   }
628 
TearDown()629   void TearDown() override {
630     if (register_class_succeeded_)
631       ::UnregisterClass(kTestWindowClassName, CURRENT_MODULE());
632 
633     PooledSingleThreadTaskRunnerManagerTest::TearDown();
634   }
635 
CreateTestWindow()636   HWND CreateTestWindow() {
637     return CreateWindow(kTestWindowClassName, kTestWindowClassName, 0, 0, 0, 0,
638                         0, HWND_MESSAGE, nullptr, CURRENT_MODULE(), nullptr);
639   }
640 
641  private:
RegisterTestWindowClass()642   bool RegisterTestWindowClass() {
643     WNDCLASSEX window_class = {};
644     window_class.cbSize = sizeof(window_class);
645     window_class.lpfnWndProc = &::DefWindowProc;
646     window_class.hInstance = CURRENT_MODULE();
647     window_class.lpszClassName = kTestWindowClassName;
648     return !!::RegisterClassEx(&window_class);
649   }
650 
651   bool register_class_succeeded_ = false;
652 };
653 
654 }  // namespace
655 
TEST_F(PooledSingleThreadTaskRunnerManagerTestWin,PumpsMessages)656 TEST_F(PooledSingleThreadTaskRunnerManagerTestWin, PumpsMessages) {
657   scoped_refptr<SingleThreadTaskRunner> com_task_runner =
658       single_thread_task_runner_manager_->CreateCOMSTATaskRunner(
659           {TaskShutdownBehavior::BLOCK_SHUTDOWN},
660           SingleThreadTaskRunnerThreadMode::DEDICATED);
661   HWND hwnd = nullptr;
662   // HWNDs process messages on the thread that created them, so we have to
663   // create them within the context of the task runner to properly simulate a
664   // COM callback.
665   com_task_runner->PostTask(
666       FROM_HERE,
667       BindOnce([](PooledSingleThreadTaskRunnerManagerTestWin* test_harness,
668                   HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); },
669                Unretained(this), &hwnd));
670 
671   task_tracker_.FlushForTesting();
672 
673   ASSERT_NE(hwnd, nullptr);
674   // If the message pump isn't running, we will hang here. This simulates how
675   // COM would receive a callback with its own message HWND.
676   SendMessage(hwnd, WM_USER, 0, 0);
677 
678   com_task_runner->PostTask(
679       FROM_HERE, BindOnce([](HWND hwnd) { ::DestroyWindow(hwnd); }, hwnd));
680 
681   test::ShutdownTaskTracker(&task_tracker_);
682 }
683 
684 #endif  // BUILDFLAG(IS_WIN)
685 
686 namespace {
687 
688 class PooledSingleThreadTaskRunnerManagerStartTest
689     : public PooledSingleThreadTaskRunnerManagerTest {
690  public:
691   PooledSingleThreadTaskRunnerManagerStartTest() = default;
692   PooledSingleThreadTaskRunnerManagerStartTest(
693       const PooledSingleThreadTaskRunnerManagerStartTest&) = delete;
694   PooledSingleThreadTaskRunnerManagerStartTest& operator=(
695       const PooledSingleThreadTaskRunnerManagerStartTest&) = delete;
696 
697  private:
StartSingleThreadTaskRunnerManagerFromSetUp()698   void StartSingleThreadTaskRunnerManagerFromSetUp() override {
699     // Start() is called in the test body rather than in SetUp().
700   }
701 };
702 
703 }  // namespace
704 
705 // Verify that a task posted before Start() doesn't run until Start() is called.
TEST_F(PooledSingleThreadTaskRunnerManagerStartTest,PostTaskBeforeStart)706 TEST_F(PooledSingleThreadTaskRunnerManagerStartTest, PostTaskBeforeStart) {
707   AtomicFlag manager_started;
708   TestWaitableEvent task_finished;
709   single_thread_task_runner_manager_
710       ->CreateSingleThreadTaskRunner(
711           {}, SingleThreadTaskRunnerThreadMode::DEDICATED)
712       ->PostTask(FROM_HERE,
713                  BindOnce(
714                      [](TestWaitableEvent* task_finished,
715                         AtomicFlag* manager_started) {
716                        // The task should not run before Start().
717                        EXPECT_TRUE(manager_started->IsSet());
718                        task_finished->Signal();
719                      },
720                      Unretained(&task_finished), Unretained(&manager_started)));
721 
722   // Wait a little bit to make sure that the task doesn't run before start.
723   // Note: This test won't catch a case where the task runs between setting
724   // |manager_started| and calling Start(). However, we expect the test to be
725   // flaky if the tested code allows that to happen.
726   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
727   manager_started.Set();
728   single_thread_task_runner_manager_->Start(service_thread_.task_runner());
729 
730   // Wait for the task to complete to keep |manager_started| alive.
731   task_finished.Wait();
732 }
733 
734 }  // namespace internal
735 }  // namespace base
736