xref: /aosp_15_r20/external/cronet/base/task/thread_pool/thread_pool_impl_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/thread_pool/thread_pool_impl.h"
6 
7 #include <stddef.h>
8 
9 #include <memory>
10 #include <string>
11 #include <tuple>
12 #include <utility>
13 #include <vector>
14 
15 #include "base/base_switches.h"
16 #include "base/cfi_buildflags.h"
17 #include "base/containers/span.h"
18 #include "base/debug/stack_trace.h"
19 #include "base/functional/bind.h"
20 #include "base/functional/callback.h"
21 #include "base/functional/callback_helpers.h"
22 #include "base/memory/raw_ptr.h"
23 #include "base/message_loop/message_pump_type.h"
24 #include "base/metrics/field_trial.h"
25 #include "base/metrics/field_trial_params.h"
26 #include "base/system/sys_info.h"
27 #include "base/task/task_features.h"
28 #include "base/task/task_traits.h"
29 #include "base/task/thread_pool/environment_config.h"
30 #include "base/task/thread_pool/test_task_factory.h"
31 #include "base/task/thread_pool/test_utils.h"
32 #include "base/task/thread_pool/worker_thread_observer.h"
33 #include "base/task/updateable_sequenced_task_runner.h"
34 #include "base/test/bind.h"
35 #include "base/test/gtest_util.h"
36 #include "base/test/scoped_feature_list.h"
37 #include "base/test/test_timeouts.h"
38 #include "base/test/test_waitable_event.h"
39 #include "base/threading/platform_thread.h"
40 #include "base/threading/sequence_local_storage_slot.h"
41 #include "base/threading/simple_thread.h"
42 #include "base/threading/thread.h"
43 #include "base/threading/thread_restrictions.h"
44 #include "base/time/time.h"
45 #include "build/build_config.h"
46 #include "testing/gtest/include/gtest/gtest.h"
47 
48 #if BUILDFLAG(IS_POSIX)
49 #include <unistd.h>
50 
51 #include "base/debug/leak_annotations.h"
52 #include "base/files/file_descriptor_watcher_posix.h"
53 #include "base/files/file_util.h"
54 #include "base/posix/eintr_wrapper.h"
55 #endif  // BUILDFLAG(IS_POSIX)
56 
57 #if BUILDFLAG(IS_WIN)
58 #include "base/win/com_init_util.h"
59 #endif  // BUILDFLAG(IS_WIN)
60 
61 namespace base {
62 namespace internal {
63 
64 namespace {
65 
66 constexpr size_t kMaxNumForegroundThreads = 4;
67 constexpr size_t kMaxNumUtilityThreads = 2;
68 
69 struct TraitsExecutionModePair {
TraitsExecutionModePairbase::internal::__anon90072ec20111::TraitsExecutionModePair70   TraitsExecutionModePair(const TaskTraits& traits,
71                           TaskSourceExecutionMode execution_mode)
72       : traits(traits), execution_mode(execution_mode) {}
73 
74   TaskTraits traits;
75   TaskSourceExecutionMode execution_mode;
76 };
77 
78 // Returns true if a task with |traits| could run at background thread priority
79 // on this platform. Even if this returns true, it is possible that the task
80 // won't run at background thread priority if a native thread group is used.
TraitsSupportBackgroundThreadType(const TaskTraits & traits)81 bool TraitsSupportBackgroundThreadType(const TaskTraits& traits) {
82   return traits.priority() == TaskPriority::BEST_EFFORT &&
83          traits.thread_policy() == ThreadPolicy::PREFER_BACKGROUND &&
84          CanUseBackgroundThreadTypeForWorkerThread();
85 }
86 
87 // Returns true if a task with |traits| could run at utility thread
88 // type on this platform. Even if this returns true, it is possible that the
89 // task won't run at efficient thread priority if a native thread group is used
90 // or the utility thread group is disabled.
TraitsSupportUtilityThreadType(const TaskTraits & traits)91 bool TraitsSupportUtilityThreadType(const TaskTraits& traits) {
92   return traits.priority() <= TaskPriority::USER_VISIBLE &&
93          traits.thread_policy() == ThreadPolicy::PREFER_BACKGROUND &&
94          CanUseUtilityThreadTypeForWorkerThread();
95 }
96 
97 // Verify that the current thread type and I/O restrictions are appropriate to
98 // run a Task with |traits|.
99 // Note: ExecutionMode is verified inside TestTaskFactory.
VerifyTaskEnvironment(const TaskTraits & traits,bool use_resource_efficient_group)100 void VerifyTaskEnvironment(const TaskTraits& traits,
101                            bool use_resource_efficient_group) {
102   const std::string thread_name(PlatformThread::GetName());
103   const bool is_single_threaded =
104       (thread_name.find("SingleThread") != std::string::npos);
105 
106   const bool expect_background_thread_type =
107       TraitsSupportBackgroundThreadType(traits);
108 
109   const bool expect_utility_thread_type =
110       !TraitsSupportBackgroundThreadType(traits) &&
111       TraitsSupportUtilityThreadType(traits) && use_resource_efficient_group;
112 
113   EXPECT_EQ(expect_background_thread_type ? ThreadType::kBackground
114             : expect_utility_thread_type  ? ThreadType::kUtility
115                                           : ThreadType::kDefault,
116             PlatformThread::GetCurrentThreadType());
117 
118   if (traits.may_block())
119     internal::AssertBlockingAllowed();
120   else
121     internal::AssertBlockingDisallowedForTesting();
122 
123   // Verify that the thread the task is running on is named as expected.
124   EXPECT_THAT(thread_name, ::testing::HasSubstr("ThreadPool"));
125 
126   EXPECT_THAT(thread_name, ::testing::HasSubstr(
127                                expect_background_thread_type ? "Background"
128                                : expect_utility_thread_type  ? "Utility"
129                                                              : "Foreground"));
130 
131   if (is_single_threaded) {
132     // SingleThread workers discriminate blocking/non-blocking tasks.
133     if (traits.may_block()) {
134       EXPECT_THAT(thread_name, ::testing::HasSubstr("Blocking"));
135     } else {
136       EXPECT_THAT(thread_name,
137                   ::testing::Not(::testing::HasSubstr("Blocking")));
138     }
139   } else {
140     EXPECT_THAT(thread_name, ::testing::Not(::testing::HasSubstr("Blocking")));
141   }
142 }
143 
VerifyTaskEnvironmentAndSignalEvent(const TaskTraits & traits,bool use_resource_efficient_group,TestWaitableEvent * event)144 void VerifyTaskEnvironmentAndSignalEvent(const TaskTraits& traits,
145                                          bool use_resource_efficient_group,
146                                          TestWaitableEvent* event) {
147   DCHECK(event);
148   VerifyTaskEnvironment(traits, use_resource_efficient_group);
149   event->Signal();
150 }
151 
VerifyTimeAndTaskEnvironmentAndSignalEvent(const TaskTraits & traits,bool use_resource_efficient_group,TimeTicks expected_time,TestWaitableEvent * event)152 void VerifyTimeAndTaskEnvironmentAndSignalEvent(
153     const TaskTraits& traits,
154     bool use_resource_efficient_group,
155     TimeTicks expected_time,
156     TestWaitableEvent* event) {
157   DCHECK(event);
158   EXPECT_LE(expected_time, TimeTicks::Now());
159   VerifyTaskEnvironment(traits, use_resource_efficient_group);
160   event->Signal();
161 }
162 
VerifyOrderAndTaskEnvironmentAndSignalEvent(const TaskTraits & traits,bool use_resource_efficient_group,TestWaitableEvent * expected_previous_event,TestWaitableEvent * event)163 void VerifyOrderAndTaskEnvironmentAndSignalEvent(
164     const TaskTraits& traits,
165     bool use_resource_efficient_group,
166     TestWaitableEvent* expected_previous_event,
167     TestWaitableEvent* event) {
168   DCHECK(event);
169   if (expected_previous_event)
170     EXPECT_TRUE(expected_previous_event->IsSignaled());
171   VerifyTaskEnvironment(traits, use_resource_efficient_group);
172   event->Signal();
173 }
174 
CreateTaskRunnerAndExecutionMode(ThreadPoolImpl * thread_pool,const TaskTraits & traits,TaskSourceExecutionMode execution_mode,SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode=SingleThreadTaskRunnerThreadMode::SHARED)175 scoped_refptr<TaskRunner> CreateTaskRunnerAndExecutionMode(
176     ThreadPoolImpl* thread_pool,
177     const TaskTraits& traits,
178     TaskSourceExecutionMode execution_mode,
179     SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode =
180         SingleThreadTaskRunnerThreadMode::SHARED) {
181   switch (execution_mode) {
182     case TaskSourceExecutionMode::kParallel:
183       return thread_pool->CreateTaskRunner(traits);
184     case TaskSourceExecutionMode::kSequenced:
185       return thread_pool->CreateSequencedTaskRunner(traits);
186     case TaskSourceExecutionMode::kSingleThread: {
187       return thread_pool->CreateSingleThreadTaskRunner(
188           traits, default_single_thread_task_runner_mode);
189     }
190     case TaskSourceExecutionMode::kJob:
191       break;
192   }
193   ADD_FAILURE() << "Unknown ExecutionMode";
194   return nullptr;
195 }
196 
197 class ThreadPostingTasks : public SimpleThread {
198  public:
199   // Creates a thread that posts Tasks to |thread_pool| with |traits| and
200   // |execution_mode|.
ThreadPostingTasks(ThreadPoolImpl * thread_pool,const TaskTraits & traits,bool use_resource_efficient_group,TaskSourceExecutionMode execution_mode)201   ThreadPostingTasks(ThreadPoolImpl* thread_pool,
202                      const TaskTraits& traits,
203                      bool use_resource_efficient_group,
204                      TaskSourceExecutionMode execution_mode)
205       : SimpleThread("ThreadPostingTasks"),
206         traits_(traits),
207         use_resource_efficient_group_(use_resource_efficient_group),
208         factory_(CreateTaskRunnerAndExecutionMode(thread_pool,
209                                                   traits,
210                                                   execution_mode),
211                  execution_mode) {}
212 
213   ThreadPostingTasks(const ThreadPostingTasks&) = delete;
214   ThreadPostingTasks& operator=(const ThreadPostingTasks&) = delete;
215 
WaitForAllTasksToRun()216   void WaitForAllTasksToRun() { factory_.WaitForAllTasksToRun(); }
217 
218  private:
Run()219   void Run() override {
220     const size_t kNumTasksPerThread = 150;
221     for (size_t i = 0; i < kNumTasksPerThread; ++i) {
222       factory_.PostTask(test::TestTaskFactory::PostNestedTask::NO,
223                         BindOnce(&VerifyTaskEnvironment, traits_,
224                                  use_resource_efficient_group_));
225     }
226   }
227 
228   const TaskTraits traits_;
229   bool use_resource_efficient_group_;
230   test::TestTaskFactory factory_;
231 };
232 
233 // Returns a vector with a TraitsExecutionModePair for each valid combination of
234 // {ExecutionMode, TaskPriority, ThreadPolicy, MayBlock()}.
GetTraitsExecutionModePairs()235 std::vector<TraitsExecutionModePair> GetTraitsExecutionModePairs() {
236   std::vector<TraitsExecutionModePair> params;
237 
238   constexpr TaskSourceExecutionMode execution_modes[] = {
239       TaskSourceExecutionMode::kParallel, TaskSourceExecutionMode::kSequenced,
240       TaskSourceExecutionMode::kSingleThread};
241   constexpr ThreadPolicy thread_policies[] = {
242       ThreadPolicy::PREFER_BACKGROUND, ThreadPolicy::MUST_USE_FOREGROUND};
243 
244   for (TaskSourceExecutionMode execution_mode : execution_modes) {
245     for (ThreadPolicy thread_policy : thread_policies) {
246       for (size_t priority_index = static_cast<size_t>(TaskPriority::LOWEST);
247            priority_index <= static_cast<size_t>(TaskPriority::HIGHEST);
248            ++priority_index) {
249         const TaskPriority priority = static_cast<TaskPriority>(priority_index);
250         params.push_back(
251             TraitsExecutionModePair({priority, thread_policy}, execution_mode));
252         params.push_back(TraitsExecutionModePair(
253             {priority, thread_policy, MayBlock()}, execution_mode));
254       }
255     }
256   }
257 
258   return params;
259 }
260 
261 // Returns a vector with enough TraitsExecutionModePairs to cover all valid
262 // combinations of task destination (background/foreground ThreadGroup,
263 // single-thread) and whether the task is affected by a BEST_EFFORT fence.
264 std::vector<TraitsExecutionModePair>
GetTraitsExecutionModePairsToCoverAllSchedulingOptions()265 GetTraitsExecutionModePairsToCoverAllSchedulingOptions() {
266   return {TraitsExecutionModePair({TaskPriority::BEST_EFFORT},
267                                   TaskSourceExecutionMode::kSequenced),
268           TraitsExecutionModePair({TaskPriority::USER_VISIBLE},
269                                   TaskSourceExecutionMode::kSequenced),
270           TraitsExecutionModePair({TaskPriority::USER_BLOCKING},
271                                   TaskSourceExecutionMode::kSequenced),
272           TraitsExecutionModePair({TaskPriority::BEST_EFFORT},
273                                   TaskSourceExecutionMode::kSingleThread),
274           TraitsExecutionModePair({TaskPriority::USER_VISIBLE},
275                                   TaskSourceExecutionMode::kSingleThread),
276           TraitsExecutionModePair({TaskPriority::USER_BLOCKING},
277                                   TaskSourceExecutionMode::kSingleThread)};
278 }
279 
280 class ThreadPoolImplTestBase : public testing::Test {
281  public:
ThreadPoolImplTestBase()282   ThreadPoolImplTestBase()
283       : thread_pool_(std::make_unique<ThreadPoolImpl>("Test")),
284         service_thread_("ServiceThread") {
285     Thread::Options service_thread_options;
286     service_thread_options.message_pump_type = MessagePumpType::IO;
287     service_thread_.StartWithOptions(std::move(service_thread_options));
288   }
289 
290   ThreadPoolImplTestBase(const ThreadPoolImplTestBase&) = delete;
291   ThreadPoolImplTestBase& operator=(const ThreadPoolImplTestBase&) = delete;
292 
293   virtual bool GetUseResourceEfficientThreadGroup() const = 0;
294 
set_worker_thread_observer(std::unique_ptr<WorkerThreadObserver> worker_thread_observer)295   void set_worker_thread_observer(
296       std::unique_ptr<WorkerThreadObserver> worker_thread_observer) {
297     worker_thread_observer_ = std::move(worker_thread_observer);
298   }
299 
StartThreadPool(size_t max_num_foreground_threads=kMaxNumForegroundThreads,size_t max_num_utility_threads=kMaxNumUtilityThreads,TimeDelta reclaim_time=Seconds (30))300   void StartThreadPool(
301       size_t max_num_foreground_threads = kMaxNumForegroundThreads,
302       size_t max_num_utility_threads = kMaxNumUtilityThreads,
303       TimeDelta reclaim_time = Seconds(30)) {
304     SetupFeatures();
305 
306     ThreadPoolInstance::InitParams init_params(max_num_foreground_threads,
307                                                max_num_utility_threads);
308     init_params.suggested_reclaim_time = reclaim_time;
309 
310     thread_pool_->Start(init_params, worker_thread_observer_.get());
311   }
312 
TearDown()313   void TearDown() override {
314     if (did_tear_down_)
315       return;
316 
317     if (thread_pool_) {
318       thread_pool_->FlushForTesting();
319       thread_pool_->JoinForTesting();
320       thread_pool_.reset();
321     }
322     did_tear_down_ = true;
323   }
324 
325   std::unique_ptr<ThreadPoolImpl> thread_pool_;
326   Thread service_thread_;
327 
328  private:
SetupFeatures()329   void SetupFeatures() {
330     std::vector<base::test::FeatureRef> features;
331 
332     if (GetUseResourceEfficientThreadGroup()) {
333       features.push_back(kUseUtilityThreadGroup);
334     }
335 
336     if (!features.empty()) {
337       feature_list_.InitWithFeatures(features, {});
338     }
339   }
340 
341   base::test::ScopedFeatureList feature_list_;
342   std::unique_ptr<WorkerThreadObserver> worker_thread_observer_;
343   bool did_tear_down_ = false;
344 };
345 
346 class ThreadPoolImplTest : public ThreadPoolImplTestBase,
347                            public testing::WithParamInterface<
348                                bool /* use_resource_efficient_thread_group */> {
349  public:
GetUseResourceEfficientThreadGroup() const350   bool GetUseResourceEfficientThreadGroup() const override {
351     return GetParam();
352   }
353 };
354 
355 // Tests run for enough traits and execution mode combinations to cover all
356 // valid combinations of task destination (background/foreground ThreadGroup,
357 // single-thread) and whether the task is affected by a BEST_EFFORT fence.
358 class ThreadPoolImplTest_CoverAllSchedulingOptions
359     : public ThreadPoolImplTestBase,
360       public testing::WithParamInterface<
361           std::tuple<bool /* use_resource_efficient_thread_group */,
362                      TraitsExecutionModePair>> {
363  public:
364   ThreadPoolImplTest_CoverAllSchedulingOptions() = default;
365   ThreadPoolImplTest_CoverAllSchedulingOptions(
366       const ThreadPoolImplTest_CoverAllSchedulingOptions&) = delete;
367   ThreadPoolImplTest_CoverAllSchedulingOptions& operator=(
368       const ThreadPoolImplTest_CoverAllSchedulingOptions&) = delete;
369 
GetUseResourceEfficientThreadGroup() const370   bool GetUseResourceEfficientThreadGroup() const override {
371     return std::get<0>(GetParam());
372   }
GetTraits() const373   TaskTraits GetTraits() const { return std::get<1>(GetParam()).traits; }
GetExecutionMode() const374   TaskSourceExecutionMode GetExecutionMode() const {
375     return std::get<1>(GetParam()).execution_mode;
376   }
377 };
378 
379 }  // namespace
380 
381 // Verifies that a Task posted via PostDelayedTask with parameterized TaskTraits
382 // and no delay runs on a thread with the expected priority and I/O
383 // restrictions. The ExecutionMode parameter is ignored by this test.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskNoDelay)384 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostDelayedTaskNoDelay) {
385   StartThreadPool();
386   TestWaitableEvent task_ran;
387   thread_pool_->PostDelayedTask(
388       FROM_HERE, GetTraits(),
389       BindOnce(&VerifyTaskEnvironmentAndSignalEvent, GetTraits(),
390                GetUseResourceEfficientThreadGroup(), Unretained(&task_ran)),
391       TimeDelta());
392   task_ran.Wait();
393 }
394 
395 // Verifies that a Task posted via PostDelayedTask with parameterized
396 // TaskTraits and a non-zero delay runs on a thread with the expected priority
397 // and I/O restrictions after the delay expires. The ExecutionMode parameter is
398 // ignored by this test.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskWithDelay)399 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostDelayedTaskWithDelay) {
400   StartThreadPool();
401   TestWaitableEvent task_ran;
402   thread_pool_->PostDelayedTask(
403       FROM_HERE, GetTraits(),
404       BindOnce(&VerifyTimeAndTaskEnvironmentAndSignalEvent, GetTraits(),
405                GetUseResourceEfficientThreadGroup(),
406                TimeTicks::Now() + TestTimeouts::tiny_timeout(),
407                Unretained(&task_ran)),
408       TestTimeouts::tiny_timeout());
409   task_ran.Wait();
410 }
411 
412 namespace {
413 
CreateSequencedTaskRunnerAndExecutionMode(ThreadPoolImpl * thread_pool,const TaskTraits & traits,TaskSourceExecutionMode execution_mode,SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode=SingleThreadTaskRunnerThreadMode::SHARED)414 scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerAndExecutionMode(
415     ThreadPoolImpl* thread_pool,
416     const TaskTraits& traits,
417     TaskSourceExecutionMode execution_mode,
418     SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode =
419         SingleThreadTaskRunnerThreadMode::SHARED) {
420   switch (execution_mode) {
421     case TaskSourceExecutionMode::kSequenced:
422       return thread_pool->CreateSequencedTaskRunner(traits);
423     case TaskSourceExecutionMode::kSingleThread: {
424       return thread_pool->CreateSingleThreadTaskRunner(
425           traits, default_single_thread_task_runner_mode);
426     }
427     case TaskSourceExecutionMode::kParallel:
428     case TaskSourceExecutionMode::kJob:
429       ADD_FAILURE() << "Tests below don't cover these modes";
430       return nullptr;
431   }
432   ADD_FAILURE() << "Unknown ExecutionMode";
433   return nullptr;
434 }
435 
436 }  // namespace
437 
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskAtViaTaskRunner)438 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
439        PostDelayedTaskAtViaTaskRunner) {
440   StartThreadPool();
441   TestWaitableEvent task_ran;
442   // Only runs for kSequenced and kSingleThread.
443   auto handle =
444       CreateSequencedTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
445                                                 GetExecutionMode())
446           ->PostCancelableDelayedTaskAt(
447               subtle::PostDelayedTaskPassKeyForTesting(), FROM_HERE,
448               BindOnce(&VerifyTimeAndTaskEnvironmentAndSignalEvent, GetTraits(),
449                        GetUseResourceEfficientThreadGroup(),
450                        TimeTicks::Now() + TestTimeouts::tiny_timeout(),
451                        Unretained(&task_ran)),
452               TimeTicks::Now() + TestTimeouts::tiny_timeout(),
453               subtle::DelayPolicy::kFlexibleNoSooner);
454   task_ran.Wait();
455 }
456 
457 // Verifies that Tasks posted via a TaskRunner with parameterized TaskTraits and
458 // ExecutionMode run on a thread with the expected priority and I/O restrictions
459 // and respect the characteristics of their ExecutionMode.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostTasksViaTaskRunner)460 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostTasksViaTaskRunner) {
461   StartThreadPool();
462   test::TestTaskFactory factory(
463       CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
464                                        GetExecutionMode()),
465       GetExecutionMode());
466 
467   const size_t kNumTasksPerTest = 150;
468   for (size_t i = 0; i < kNumTasksPerTest; ++i) {
469     factory.PostTask(test::TestTaskFactory::PostNestedTask::NO,
470                      BindOnce(&VerifyTaskEnvironment, GetTraits(),
471                               GetUseResourceEfficientThreadGroup()));
472   }
473 
474   factory.WaitForAllTasksToRun();
475 }
476 
477 // Verifies that a task posted via PostDelayedTask without a delay doesn't run
478 // before Start() is called.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskNoDelayBeforeStart)479 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
480        PostDelayedTaskNoDelayBeforeStart) {
481   TestWaitableEvent task_running;
482   thread_pool_->PostDelayedTask(
483       FROM_HERE, GetTraits(),
484       BindOnce(&VerifyTaskEnvironmentAndSignalEvent, GetTraits(),
485                GetUseResourceEfficientThreadGroup(), Unretained(&task_running)),
486       TimeDelta());
487 
488   // Wait a little bit to make sure that the task doesn't run before Start().
489   // Note: This test won't catch a case where the task runs just after the check
490   // and before Start(). However, we expect the test to be flaky if the tested
491   // code allows that to happen.
492   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
493   EXPECT_FALSE(task_running.IsSignaled());
494 
495   StartThreadPool();
496   task_running.Wait();
497 }
498 
499 // Verifies that a task posted via PostDelayedTask with a delay doesn't run
500 // before Start() is called.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostDelayedTaskWithDelayBeforeStart)501 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
502        PostDelayedTaskWithDelayBeforeStart) {
503   TestWaitableEvent task_running;
504   thread_pool_->PostDelayedTask(
505       FROM_HERE, GetTraits(),
506       BindOnce(&VerifyTimeAndTaskEnvironmentAndSignalEvent, GetTraits(),
507                GetUseResourceEfficientThreadGroup(),
508                TimeTicks::Now() + TestTimeouts::tiny_timeout(),
509                Unretained(&task_running)),
510       TestTimeouts::tiny_timeout());
511 
512   // Wait a little bit to make sure that the task doesn't run before Start().
513   // Note: This test won't catch a case where the task runs just after the check
514   // and before Start(). However, we expect the test to be flaky if the tested
515   // code allows that to happen.
516   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
517   EXPECT_FALSE(task_running.IsSignaled());
518 
519   StartThreadPool();
520   task_running.Wait();
521 }
522 
523 // Verifies that a task posted via a TaskRunner doesn't run before Start() is
524 // called.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostTaskViaTaskRunnerBeforeStart)525 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
526        PostTaskViaTaskRunnerBeforeStart) {
527   bool use_resource_efficient_thread_group =
528       GetUseResourceEfficientThreadGroup();
529   // The worker_thread of SingleThreadTaskRunner is selected before
530   // kUseUtilityThreadGroup feature is set up at StartThreadPool().
531   if (GetExecutionMode() == TaskSourceExecutionMode::kSingleThread) {
532     use_resource_efficient_thread_group = false;
533   }
534   TestWaitableEvent task_running;
535   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
536                                    GetExecutionMode())
537       ->PostTask(FROM_HERE,
538                  BindOnce(&VerifyTaskEnvironmentAndSignalEvent, GetTraits(),
539                           use_resource_efficient_thread_group,
540                           Unretained(&task_running)));
541 
542   // Wait a little bit to make sure that the task doesn't run before Start().
543   // Note: This test won't catch a case where the task runs just after the check
544   // and before Start(). However, we expect the test to be flaky if the tested
545   // code allows that to happen.
546   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
547   EXPECT_FALSE(task_running.IsSignaled());
548 
549   StartThreadPool();
550 
551   // This should not hang if the task runs after Start().
552   task_running.Wait();
553 }
554 
555 // Verify that posting tasks after the thread pool was destroyed fails but
556 // doesn't crash.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,PostTaskAfterDestroy)557 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostTaskAfterDestroy) {
558   StartThreadPool();
559 
560   auto task_runner = CreateTaskRunnerAndExecutionMode(
561       thread_pool_.get(), GetTraits(), GetExecutionMode());
562   EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing()));
563   thread_pool_->JoinForTesting();
564   thread_pool_.reset();
565 
566   EXPECT_FALSE(
567       task_runner->PostTask(FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE)));
568 }
569 
570 // Verifies that FlushAsyncForTesting() calls back correctly for all trait and
571 // execution mode pairs.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,FlushAsyncForTestingSimple)572 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
573        FlushAsyncForTestingSimple) {
574   StartThreadPool();
575 
576   TestWaitableEvent unblock_task;
577   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
578                                    GetExecutionMode(),
579                                    SingleThreadTaskRunnerThreadMode::DEDICATED)
580       ->PostTask(FROM_HERE,
581                  BindOnce(&TestWaitableEvent::Wait, Unretained(&unblock_task)));
582 
583   TestWaitableEvent flush_event;
584   thread_pool_->FlushAsyncForTesting(
585       BindOnce(&TestWaitableEvent::Signal, Unretained(&flush_event)));
586   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
587   EXPECT_FALSE(flush_event.IsSignaled());
588 
589   unblock_task.Signal();
590 
591   flush_event.Wait();
592 }
593 
594 // Verifies that BEST_EFFORT tasks don't run when the
595 // --disable-best-effort-tasks command-line switch is specified.
596 //
597 // Not using the same fixture as other tests because we want to append a command
598 // line switch before creating the pool.
TEST(ThreadPoolImplTest_Switch,DisableBestEffortTasksSwitch)599 TEST(ThreadPoolImplTest_Switch, DisableBestEffortTasksSwitch) {
600   CommandLine::ForCurrentProcess()->AppendSwitch(
601       switches::kDisableBestEffortTasks);
602 
603   ThreadPoolImpl thread_pool("Test");
604   ThreadPoolInstance::InitParams init_params(kMaxNumForegroundThreads,
605                                              kMaxNumUtilityThreads);
606   thread_pool.Start(init_params, nullptr);
607 
608   AtomicFlag best_effort_can_run;
609   TestWaitableEvent best_effort_did_run;
610   thread_pool.PostDelayedTask(
611       FROM_HERE,
612       {TaskPriority::BEST_EFFORT, TaskShutdownBehavior::BLOCK_SHUTDOWN},
613       BindLambdaForTesting([&]() {
614         EXPECT_TRUE(best_effort_can_run.IsSet());
615         best_effort_did_run.Signal();
616       }),
617       TimeDelta());
618 
619   TestWaitableEvent user_blocking_did_run;
620   thread_pool.PostDelayedTask(
621       FROM_HERE, {TaskPriority::USER_BLOCKING},
622       BindLambdaForTesting([&]() { user_blocking_did_run.Signal(); }),
623       TimeDelta());
624 
625   // The USER_BLOCKING task should run.
626   user_blocking_did_run.Wait();
627 
628   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
629 
630   // The BEST_EFFORT task should not run when a BEST_EFFORT fence is deleted.
631   thread_pool.BeginBestEffortFence();
632   thread_pool.EndBestEffortFence();
633 
634   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
635 
636   // The BEST_EFFORT task should only run during shutdown.
637   best_effort_can_run.Set();
638   thread_pool.Shutdown();
639   EXPECT_TRUE(best_effort_did_run.IsSignaled());
640   thread_pool.JoinForTesting();
641 }
642 
643 // Verifies that tasks only run when allowed by fences.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,Fence)644 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, Fence) {
645   StartThreadPool();
646 
647   AtomicFlag can_run;
648   TestWaitableEvent did_run;
649   thread_pool_->BeginFence();
650 
651   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
652                                    GetExecutionMode())
653       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
654                    EXPECT_TRUE(can_run.IsSet());
655                    did_run.Signal();
656                  }));
657 
658   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
659 
660   can_run.Set();
661   thread_pool_->EndFence();
662   did_run.Wait();
663 }
664 
665 // Verifies that multiple fences can exist at the same time.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,MultipleFences)666 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, MultipleFences) {
667   StartThreadPool();
668 
669   AtomicFlag can_run;
670   TestWaitableEvent did_run;
671   thread_pool_->BeginFence();
672   thread_pool_->BeginFence();
673 
674   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
675                                    GetExecutionMode())
676       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
677                    EXPECT_TRUE(can_run.IsSet());
678                    did_run.Signal();
679                  }));
680 
681   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
682 
683   thread_pool_->EndFence();
684   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
685 
686   // The task can only run when both fences are removed.
687   can_run.Set();
688   thread_pool_->EndFence();
689 
690   did_run.Wait();
691 }
692 
693 // Verifies that a call to BeginFence() before Start() is honored.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,FenceBeforeStart)694 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, FenceBeforeStart) {
695   thread_pool_->BeginFence();
696   StartThreadPool();
697 
698   AtomicFlag can_run;
699   TestWaitableEvent did_run;
700 
701   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
702                                    GetExecutionMode())
703       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
704                    EXPECT_TRUE(can_run.IsSet());
705                    did_run.Signal();
706                  }));
707 
708   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
709 
710   can_run.Set();
711   thread_pool_->EndFence();
712   did_run.Wait();
713 }
714 
715 // Verifies that tasks only run when allowed by BEST_EFFORT fences.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,BestEffortFence)716 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, BestEffortFence) {
717   StartThreadPool();
718 
719   AtomicFlag can_run;
720   TestWaitableEvent did_run;
721   thread_pool_->BeginBestEffortFence();
722 
723   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
724                                    GetExecutionMode())
725       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
726                    if (GetTraits().priority() == TaskPriority::BEST_EFFORT)
727                      EXPECT_TRUE(can_run.IsSet());
728                    did_run.Signal();
729                  }));
730 
731   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
732 
733   can_run.Set();
734   thread_pool_->EndBestEffortFence();
735   did_run.Wait();
736 }
737 
738 // Verifies that multiple BEST_EFFORT fences can exist at the same time.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,MultipleBestEffortFences)739 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, MultipleBestEffortFences) {
740   StartThreadPool();
741 
742   AtomicFlag can_run;
743   TestWaitableEvent did_run;
744   thread_pool_->BeginBestEffortFence();
745   thread_pool_->BeginBestEffortFence();
746 
747   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
748                                    GetExecutionMode())
749       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
750                    if (GetTraits().priority() == TaskPriority::BEST_EFFORT)
751                      EXPECT_TRUE(can_run.IsSet());
752                    did_run.Signal();
753                  }));
754 
755   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
756 
757   thread_pool_->EndBestEffortFence();
758   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
759 
760   // The task can only run when both fences are removed.
761   can_run.Set();
762   thread_pool_->EndBestEffortFence();
763 
764   did_run.Wait();
765 }
766 
767 // Verifies that a call to BeginBestEffortFence() before Start() is honored.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,BestEffortFenceBeforeStart)768 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
769        BestEffortFenceBeforeStart) {
770   thread_pool_->BeginBestEffortFence();
771   StartThreadPool();
772 
773   AtomicFlag can_run;
774   TestWaitableEvent did_run;
775 
776   CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
777                                    GetExecutionMode())
778       ->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
779                    if (GetTraits().priority() == TaskPriority::BEST_EFFORT)
780                      EXPECT_TRUE(can_run.IsSet());
781                    did_run.Signal();
782                  }));
783 
784   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
785 
786   can_run.Set();
787   thread_pool_->EndBestEffortFence();
788   did_run.Wait();
789 }
790 
791 // Spawns threads that simultaneously post Tasks to TaskRunners with various
792 // TaskTraits and ExecutionModes. Verifies that each Task runs on a thread with
793 // the expected priority and I/O restrictions and respects the characteristics
794 // of its ExecutionMode.
TEST_P(ThreadPoolImplTest,MultipleTraitsExecutionModePair)795 TEST_P(ThreadPoolImplTest, MultipleTraitsExecutionModePair) {
796   StartThreadPool();
797   std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks;
798   for (const auto& test_params : GetTraitsExecutionModePairs()) {
799     threads_posting_tasks.push_back(std::make_unique<ThreadPostingTasks>(
800         thread_pool_.get(), test_params.traits,
801         GetUseResourceEfficientThreadGroup(), test_params.execution_mode));
802     threads_posting_tasks.back()->Start();
803   }
804 
805   for (const auto& thread : threads_posting_tasks) {
806     thread->WaitForAllTasksToRun();
807     thread->Join();
808   }
809 }
810 
TEST_P(ThreadPoolImplTest,GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated)811 TEST_P(ThreadPoolImplTest,
812        GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated) {
813   StartThreadPool();
814 
815   // GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated() does not support
816   // TaskPriority::BEST_EFFORT.
817   GTEST_FLAG_SET(death_test_style, "threadsafe");
818   EXPECT_DCHECK_DEATH({
819     thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
820         {TaskPriority::BEST_EFFORT});
821   });
822   EXPECT_DCHECK_DEATH({
823     thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
824         {MayBlock(), TaskPriority::BEST_EFFORT});
825   });
826 
827   EXPECT_EQ(GetUseResourceEfficientThreadGroup() &&
828                     CanUseUtilityThreadTypeForWorkerThread()
829                 ? kMaxNumUtilityThreads
830                 : kMaxNumForegroundThreads,
831             thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
832                 {TaskPriority::USER_VISIBLE}));
833   EXPECT_EQ(GetUseResourceEfficientThreadGroup() &&
834                     CanUseUtilityThreadTypeForWorkerThread()
835                 ? kMaxNumUtilityThreads
836                 : kMaxNumForegroundThreads,
837             thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
838                 {MayBlock(), TaskPriority::USER_VISIBLE}));
839   EXPECT_EQ(kMaxNumForegroundThreads,
840             thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
841                 {TaskPriority::USER_BLOCKING}));
842   EXPECT_EQ(kMaxNumForegroundThreads,
843             thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
844                 {MayBlock(), TaskPriority::USER_BLOCKING}));
845 }
846 
847 // Verify that the RunsTasksInCurrentSequence() method of a SequencedTaskRunner
848 // returns false when called from a task that isn't part of the sequence.
TEST_P(ThreadPoolImplTest,SequencedRunsTasksInCurrentSequence)849 TEST_P(ThreadPoolImplTest, SequencedRunsTasksInCurrentSequence) {
850   StartThreadPool();
851   auto single_thread_task_runner = thread_pool_->CreateSingleThreadTaskRunner(
852       {}, SingleThreadTaskRunnerThreadMode::SHARED);
853   auto sequenced_task_runner = thread_pool_->CreateSequencedTaskRunner({});
854 
855   TestWaitableEvent task_ran;
856   single_thread_task_runner->PostTask(
857       FROM_HERE,
858       BindOnce(
859           [](scoped_refptr<SequencedTaskRunner> sequenced_task_runner,
860              TestWaitableEvent* task_ran) {
861             EXPECT_FALSE(sequenced_task_runner->RunsTasksInCurrentSequence());
862             task_ran->Signal();
863           },
864           sequenced_task_runner, Unretained(&task_ran)));
865   task_ran.Wait();
866 }
867 
868 // Verify that the RunsTasksInCurrentSequence() method of a
869 // SingleThreadTaskRunner returns false when called from a task that isn't part
870 // of the sequence.
TEST_P(ThreadPoolImplTest,SingleThreadRunsTasksInCurrentSequence)871 TEST_P(ThreadPoolImplTest, SingleThreadRunsTasksInCurrentSequence) {
872   StartThreadPool();
873   auto sequenced_task_runner = thread_pool_->CreateSequencedTaskRunner({});
874   auto single_thread_task_runner = thread_pool_->CreateSingleThreadTaskRunner(
875       {}, SingleThreadTaskRunnerThreadMode::SHARED);
876 
877   TestWaitableEvent task_ran;
878   sequenced_task_runner->PostTask(
879       FROM_HERE,
880       BindOnce(
881           [](scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner,
882              TestWaitableEvent* task_ran) {
883             EXPECT_FALSE(
884                 single_thread_task_runner->RunsTasksInCurrentSequence());
885             task_ran->Signal();
886           },
887           single_thread_task_runner, Unretained(&task_ran)));
888   task_ran.Wait();
889 }
890 
891 #if BUILDFLAG(IS_WIN)
TEST_P(ThreadPoolImplTest,COMSTATaskRunnersRunWithCOMSTA)892 TEST_P(ThreadPoolImplTest, COMSTATaskRunnersRunWithCOMSTA) {
893   StartThreadPool();
894   auto com_sta_task_runner = thread_pool_->CreateCOMSTATaskRunner(
895       {}, SingleThreadTaskRunnerThreadMode::SHARED);
896 
897   TestWaitableEvent task_ran;
898   com_sta_task_runner->PostTask(
899       FROM_HERE, BindOnce(
900                      [](TestWaitableEvent* task_ran) {
901                        win::AssertComApartmentType(win::ComApartmentType::STA);
902                        task_ran->Signal();
903                      },
904                      Unretained(&task_ran)));
905   task_ran.Wait();
906 }
907 #endif  // BUILDFLAG(IS_WIN)
908 
TEST_P(ThreadPoolImplTest,DelayedTasksNotRunAfterShutdown)909 TEST_P(ThreadPoolImplTest, DelayedTasksNotRunAfterShutdown) {
910   StartThreadPool();
911   // As with delayed tasks in general, this is racy. If the task does happen to
912   // run after Shutdown within the timeout, it will fail this test.
913   //
914   // The timeout should be set sufficiently long enough to ensure that the
915   // delayed task did not run. 2x is generally good enough.
916   //
917   // A non-racy way to do this would be to post two sequenced tasks:
918   // 1) Regular Post Task: A WaitableEvent.Wait
919   // 2) Delayed Task: ADD_FAILURE()
920   // and signalling the WaitableEvent after Shutdown() on a different thread
921   // since Shutdown() will block. However, the cost of managing this extra
922   // thread was deemed to be too great for the unlikely race.
923   thread_pool_->PostDelayedTask(FROM_HERE, {},
924                                 BindOnce([]() { ADD_FAILURE(); }),
925                                 TestTimeouts::tiny_timeout());
926   thread_pool_->Shutdown();
927   PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 2);
928 }
929 
930 #if BUILDFLAG(IS_POSIX)
931 
TEST_P(ThreadPoolImplTest,FileDescriptorWatcherNoOpsAfterShutdown)932 TEST_P(ThreadPoolImplTest, FileDescriptorWatcherNoOpsAfterShutdown) {
933   StartThreadPool();
934 
935   int pipes[2];
936   ASSERT_EQ(0, pipe(pipes));
937 
938   scoped_refptr<TaskRunner> blocking_task_runner =
939       thread_pool_->CreateSequencedTaskRunner(
940           {TaskShutdownBehavior::BLOCK_SHUTDOWN});
941   blocking_task_runner->PostTask(
942       FROM_HERE,
943       BindOnce(
944           [](int read_fd) {
945             std::unique_ptr<FileDescriptorWatcher::Controller> controller =
946                 FileDescriptorWatcher::WatchReadable(
947                     read_fd, BindRepeating([]() { NOTREACHED(); }));
948 
949             // This test is for components that intentionally leak their
950             // watchers at shutdown. We can't clean |controller| up because its
951             // destructor will assert that it's being called from the correct
952             // sequence. After the thread pool is shutdown, it is not
953             // possible to run tasks on this sequence.
954             //
955             // Note: Do not inline the controller.release() call into the
956             //       ANNOTATE_LEAKING_OBJECT_PTR as the annotation is removed
957             //       by the preprocessor in non-LEAK_SANITIZER builds,
958             //       effectively breaking this test.
959             ANNOTATE_LEAKING_OBJECT_PTR(controller.get());
960             controller.release();
961           },
962           pipes[0]));
963 
964   thread_pool_->Shutdown();
965 
966   constexpr char kByte = '!';
967   ASSERT_TRUE(WriteFileDescriptor(pipes[1], as_bytes(make_span(&kByte, 1u))));
968 
969   // Give a chance for the file watcher to fire before closing the handles.
970   PlatformThread::Sleep(TestTimeouts::tiny_timeout());
971 
972   EXPECT_EQ(0, IGNORE_EINTR(close(pipes[0])));
973   EXPECT_EQ(0, IGNORE_EINTR(close(pipes[1])));
974 }
975 #endif  // BUILDFLAG(IS_POSIX)
976 
977 #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)
978 
979 // Verify that FileDescriptorWatcher::WatchReadable() can be called from task
980 // running on a task_runner with GetExecutionMode() without a crash.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,FileDescriptorWatcher)981 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, FileDescriptorWatcher) {
982   StartThreadPool();
983 
984   int fds[2];
985   ASSERT_EQ(0, pipe(fds));
986 
987   auto task_runner = CreateTaskRunnerAndExecutionMode(
988       thread_pool_.get(), GetTraits(), GetExecutionMode());
989 
990   EXPECT_TRUE(task_runner->PostTask(
991       FROM_HERE, BindOnce(IgnoreResult(&FileDescriptorWatcher::WatchReadable),
992                           fds[0], DoNothing())));
993 
994   thread_pool_->FlushForTesting();
995 
996   EXPECT_EQ(0, IGNORE_EINTR(close(fds[0])));
997   EXPECT_EQ(0, IGNORE_EINTR(close(fds[1])));
998 }
999 
1000 #endif
1001 
1002 // Verify that tasks posted on the same sequence access the same values on
1003 // SequenceLocalStorage, and tasks on different sequences see different values.
TEST_P(ThreadPoolImplTest,SequenceLocalStorage)1004 TEST_P(ThreadPoolImplTest, SequenceLocalStorage) {
1005   StartThreadPool();
1006 
1007   SequenceLocalStorageSlot<int> slot;
1008   auto sequenced_task_runner1 = thread_pool_->CreateSequencedTaskRunner({});
1009   auto sequenced_task_runner2 = thread_pool_->CreateSequencedTaskRunner({});
1010 
1011   sequenced_task_runner1->PostTask(
1012       FROM_HERE,
1013       BindOnce([](SequenceLocalStorageSlot<int>* slot) { slot->emplace(11); },
1014                &slot));
1015 
1016   sequenced_task_runner1->PostTask(
1017       FROM_HERE, BindOnce(
1018                      [](SequenceLocalStorageSlot<int>* slot) {
1019                        EXPECT_EQ(slot->GetOrCreateValue(), 11);
1020                      },
1021                      &slot));
1022 
1023   sequenced_task_runner2->PostTask(
1024       FROM_HERE, BindOnce(
1025                      [](SequenceLocalStorageSlot<int>* slot) {
1026                        EXPECT_NE(slot->GetOrCreateValue(), 11);
1027                      },
1028                      &slot));
1029 
1030   thread_pool_->FlushForTesting();
1031 }
1032 
TEST_P(ThreadPoolImplTest,FlushAsyncNoTasks)1033 TEST_P(ThreadPoolImplTest, FlushAsyncNoTasks) {
1034   StartThreadPool();
1035   bool called_back = false;
1036   thread_pool_->FlushAsyncForTesting(
1037       BindOnce([](bool* called_back) { *called_back = true; },
1038                Unretained(&called_back)));
1039   EXPECT_TRUE(called_back);
1040 }
1041 
1042 namespace {
1043 
1044 // Verifies that all strings passed as argument are found on the current stack.
1045 // Ignores failures if this configuration doesn't have symbols.
VerifyHasStringsOnStack(const std::string & pool_str,const std::string & shutdown_behavior_str)1046 void VerifyHasStringsOnStack(const std::string& pool_str,
1047                              const std::string& shutdown_behavior_str) {
1048   const std::string stack = debug::StackTrace().ToString();
1049   SCOPED_TRACE(stack);
1050   const bool stack_has_symbols =
1051       stack.find("WorkerThread") != std::string::npos;
1052   if (!stack_has_symbols)
1053     return;
1054 
1055   EXPECT_THAT(stack, ::testing::HasSubstr(pool_str));
1056   EXPECT_THAT(stack, ::testing::HasSubstr(shutdown_behavior_str));
1057 }
1058 
1059 }  // namespace
1060 
1061 #if BUILDFLAG(IS_POSIX)
1062 // Many POSIX bots flakily crash on |debug::StackTrace().ToString()|,
1063 // https://crbug.com/840429.
1064 #define MAYBE_IdentifiableStacks DISABLED_IdentifiableStacks
1065 #elif BUILDFLAG(IS_WIN) && \
1066     (defined(ADDRESS_SANITIZER) || BUILDFLAG(CFI_CAST_CHECK))
1067 // Hangs on WinASan and WinCFI (grabbing StackTrace() too slow?),
1068 // https://crbug.com/845010#c7.
1069 #define MAYBE_IdentifiableStacks DISABLED_IdentifiableStacks
1070 #else
1071 #define MAYBE_IdentifiableStacks IdentifiableStacks
1072 #endif
1073 
1074 // Integration test that verifies that workers have a frame on their stacks
1075 // which easily identifies the type of worker and shutdown behavior (useful to
1076 // diagnose issues from logs without memory dumps).
TEST_P(ThreadPoolImplTest,MAYBE_IdentifiableStacks)1077 TEST_P(ThreadPoolImplTest, MAYBE_IdentifiableStacks) {
1078   StartThreadPool();
1079 
1080   // Shutdown behaviors and expected stack frames.
1081   constexpr std::pair<TaskShutdownBehavior, const char*> shutdown_behaviors[] =
1082       {{TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, "RunContinueOnShutdown"},
1083        {TaskShutdownBehavior::SKIP_ON_SHUTDOWN, "RunSkipOnShutdown"},
1084        {TaskShutdownBehavior::BLOCK_SHUTDOWN, "RunBlockShutdown"}};
1085 
1086   for (const auto& shutdown_behavior : shutdown_behaviors) {
1087     const TaskTraits traits = {shutdown_behavior.first};
1088     const TaskTraits best_effort_traits = {shutdown_behavior.first,
1089                                            TaskPriority::BEST_EFFORT};
1090 
1091     thread_pool_->CreateSequencedTaskRunner(traits)->PostTask(
1092         FROM_HERE, BindOnce(&VerifyHasStringsOnStack, "RunPooledWorker",
1093                             shutdown_behavior.second));
1094     thread_pool_->CreateSequencedTaskRunner(best_effort_traits)
1095         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1096                                        "RunBackgroundPooledWorker",
1097                                        shutdown_behavior.second));
1098 
1099     thread_pool_
1100         ->CreateSingleThreadTaskRunner(traits,
1101                                        SingleThreadTaskRunnerThreadMode::SHARED)
1102         ->PostTask(FROM_HERE,
1103                    BindOnce(&VerifyHasStringsOnStack, "RunSharedWorker",
1104                             shutdown_behavior.second));
1105     thread_pool_
1106         ->CreateSingleThreadTaskRunner(best_effort_traits,
1107                                        SingleThreadTaskRunnerThreadMode::SHARED)
1108         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1109                                        "RunBackgroundSharedWorker",
1110                                        shutdown_behavior.second));
1111 
1112     thread_pool_
1113         ->CreateSingleThreadTaskRunner(
1114             traits, SingleThreadTaskRunnerThreadMode::DEDICATED)
1115         ->PostTask(FROM_HERE,
1116                    BindOnce(&VerifyHasStringsOnStack, "RunDedicatedWorker",
1117                             shutdown_behavior.second));
1118     thread_pool_
1119         ->CreateSingleThreadTaskRunner(
1120             best_effort_traits, SingleThreadTaskRunnerThreadMode::DEDICATED)
1121         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1122                                        "RunBackgroundDedicatedWorker",
1123                                        shutdown_behavior.second));
1124 
1125 #if BUILDFLAG(IS_WIN)
1126     thread_pool_
1127         ->CreateCOMSTATaskRunner(traits,
1128                                  SingleThreadTaskRunnerThreadMode::SHARED)
1129         ->PostTask(FROM_HERE,
1130                    BindOnce(&VerifyHasStringsOnStack, "RunSharedCOMWorker",
1131                             shutdown_behavior.second));
1132     thread_pool_
1133         ->CreateCOMSTATaskRunner(best_effort_traits,
1134                                  SingleThreadTaskRunnerThreadMode::SHARED)
1135         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1136                                        "RunBackgroundSharedCOMWorker",
1137                                        shutdown_behavior.second));
1138 
1139     thread_pool_
1140         ->CreateCOMSTATaskRunner(traits,
1141                                  SingleThreadTaskRunnerThreadMode::DEDICATED)
1142         ->PostTask(FROM_HERE,
1143                    BindOnce(&VerifyHasStringsOnStack, "RunDedicatedCOMWorker",
1144                             shutdown_behavior.second));
1145     thread_pool_
1146         ->CreateCOMSTATaskRunner(best_effort_traits,
1147                                  SingleThreadTaskRunnerThreadMode::DEDICATED)
1148         ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringsOnStack,
1149                                        "RunBackgroundDedicatedCOMWorker",
1150                                        shutdown_behavior.second));
1151 #endif  // BUILDFLAG(IS_WIN)
1152   }
1153 
1154   thread_pool_->FlushForTesting();
1155 }
1156 
TEST_P(ThreadPoolImplTest,WorkerThreadObserver)1157 TEST_P(ThreadPoolImplTest, WorkerThreadObserver) {
1158   auto owned_observer =
1159       std::make_unique<testing::StrictMock<test::MockWorkerThreadObserver>>();
1160   auto* observer = owned_observer.get();
1161   set_worker_thread_observer(std::move(owned_observer));
1162 
1163   // A worker should be created for each thread group. After that, 4 threads
1164   // should be created for each SingleThreadTaskRunnerThreadMode (8 on Windows).
1165   const int kExpectedNumForegroundPoolWorkers = 1;
1166   const int kExpectedNumUtilityPoolWorkers =
1167       GetUseResourceEfficientThreadGroup() &&
1168               CanUseUtilityThreadTypeForWorkerThread()
1169           ? 1
1170           : 0;
1171   const int kExpectedNumBackgroundPoolWorkers =
1172       CanUseBackgroundThreadTypeForWorkerThread() ? 1 : 0;
1173   const int kExpectedNumPoolWorkers = kExpectedNumForegroundPoolWorkers +
1174                                       kExpectedNumUtilityPoolWorkers +
1175                                       kExpectedNumBackgroundPoolWorkers;
1176   const int kExpectedNumSharedSingleThreadedForegroundWorkers = 2;
1177   const int kExpectedNumSharedSingleThreadedUtilityWorkers =
1178       GetUseResourceEfficientThreadGroup() &&
1179               CanUseUtilityThreadTypeForWorkerThread()
1180           ? 2
1181           : 0;
1182   const int kExpectedNumSharedSingleThreadedBackgroundWorkers =
1183       CanUseBackgroundThreadTypeForWorkerThread() ? 2 : 0;
1184   const int kExpectedNumSharedSingleThreadedWorkers =
1185       kExpectedNumSharedSingleThreadedForegroundWorkers +
1186       kExpectedNumSharedSingleThreadedUtilityWorkers +
1187       kExpectedNumSharedSingleThreadedBackgroundWorkers;
1188   const int kExpectedNumDedicatedSingleThreadedWorkers = 6;
1189 
1190   const int kExpectedNumCOMSharedSingleThreadedWorkers =
1191 #if BUILDFLAG(IS_WIN)
1192       kExpectedNumSharedSingleThreadedWorkers;
1193 #else
1194       0;
1195 #endif
1196   const int kExpectedNumCOMDedicatedSingleThreadedWorkers =
1197 #if BUILDFLAG(IS_WIN)
1198       kExpectedNumDedicatedSingleThreadedWorkers;
1199 #else
1200       0;
1201 #endif
1202 
1203   EXPECT_CALL(*observer, OnWorkerThreadMainEntry())
1204       .Times(kExpectedNumPoolWorkers + kExpectedNumSharedSingleThreadedWorkers +
1205              kExpectedNumDedicatedSingleThreadedWorkers +
1206              kExpectedNumCOMSharedSingleThreadedWorkers +
1207              kExpectedNumCOMDedicatedSingleThreadedWorkers);
1208 
1209   // Infinite detach time to prevent workers from invoking
1210   // OnWorkerThreadMainExit() earlier than expected.
1211   StartThreadPool(kMaxNumForegroundThreads, kMaxNumUtilityThreads,
1212                   TimeDelta::Max());
1213 
1214   std::vector<scoped_refptr<SingleThreadTaskRunner>> task_runners;
1215 
1216   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1217       {TaskPriority::BEST_EFFORT}, SingleThreadTaskRunnerThreadMode::SHARED));
1218   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1219       {TaskPriority::BEST_EFFORT, MayBlock()},
1220       SingleThreadTaskRunnerThreadMode::SHARED));
1221   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1222       {TaskPriority::USER_VISIBLE}, SingleThreadTaskRunnerThreadMode::SHARED));
1223   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1224       {TaskPriority::USER_VISIBLE, MayBlock()},
1225       SingleThreadTaskRunnerThreadMode::SHARED));
1226   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1227       {TaskPriority::USER_BLOCKING}, SingleThreadTaskRunnerThreadMode::SHARED));
1228   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1229       {TaskPriority::USER_BLOCKING, MayBlock()},
1230       SingleThreadTaskRunnerThreadMode::SHARED));
1231 
1232   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1233       {TaskPriority::BEST_EFFORT},
1234       SingleThreadTaskRunnerThreadMode::DEDICATED));
1235   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1236       {TaskPriority::BEST_EFFORT, MayBlock()},
1237       SingleThreadTaskRunnerThreadMode::DEDICATED));
1238   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1239       {TaskPriority::USER_VISIBLE},
1240       SingleThreadTaskRunnerThreadMode::DEDICATED));
1241   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1242       {TaskPriority::USER_VISIBLE, MayBlock()},
1243       SingleThreadTaskRunnerThreadMode::DEDICATED));
1244   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1245       {TaskPriority::USER_BLOCKING},
1246       SingleThreadTaskRunnerThreadMode::DEDICATED));
1247   task_runners.push_back(thread_pool_->CreateSingleThreadTaskRunner(
1248       {TaskPriority::USER_BLOCKING, MayBlock()},
1249       SingleThreadTaskRunnerThreadMode::DEDICATED));
1250 
1251 #if BUILDFLAG(IS_WIN)
1252   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1253       {TaskPriority::BEST_EFFORT}, SingleThreadTaskRunnerThreadMode::SHARED));
1254   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1255       {TaskPriority::BEST_EFFORT, MayBlock()},
1256       SingleThreadTaskRunnerThreadMode::SHARED));
1257   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1258       {TaskPriority::USER_VISIBLE}, SingleThreadTaskRunnerThreadMode::SHARED));
1259   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1260       {TaskPriority::USER_VISIBLE, MayBlock()},
1261       SingleThreadTaskRunnerThreadMode::SHARED));
1262   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1263       {TaskPriority::USER_BLOCKING}, SingleThreadTaskRunnerThreadMode::SHARED));
1264   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1265       {TaskPriority::USER_BLOCKING, MayBlock()},
1266       SingleThreadTaskRunnerThreadMode::SHARED));
1267 
1268   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1269       {TaskPriority::BEST_EFFORT},
1270       SingleThreadTaskRunnerThreadMode::DEDICATED));
1271   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1272       {TaskPriority::BEST_EFFORT, MayBlock()},
1273       SingleThreadTaskRunnerThreadMode::DEDICATED));
1274   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1275       {TaskPriority::USER_VISIBLE},
1276       SingleThreadTaskRunnerThreadMode::DEDICATED));
1277   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1278       {TaskPriority::USER_VISIBLE, MayBlock()},
1279       SingleThreadTaskRunnerThreadMode::DEDICATED));
1280   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1281       {TaskPriority::USER_BLOCKING},
1282       SingleThreadTaskRunnerThreadMode::DEDICATED));
1283   task_runners.push_back(thread_pool_->CreateCOMSTATaskRunner(
1284       {TaskPriority::USER_BLOCKING, MayBlock()},
1285       SingleThreadTaskRunnerThreadMode::DEDICATED));
1286 #endif
1287 
1288   for (auto& task_runner : task_runners)
1289     task_runner->PostTask(FROM_HERE, DoNothing());
1290 
1291   // Release single-threaded workers. This should cause dedicated workers to
1292   // invoke OnWorkerThreadMainExit().
1293   observer->AllowCallsOnMainExit(kExpectedNumDedicatedSingleThreadedWorkers +
1294                                  kExpectedNumCOMDedicatedSingleThreadedWorkers);
1295   task_runners.clear();
1296   observer->WaitCallsOnMainExit();
1297 
1298   // Join all remaining workers. This should cause shared single-threaded
1299   // workers and thread pool workers to invoke OnWorkerThreadMainExit().
1300   observer->AllowCallsOnMainExit(kExpectedNumPoolWorkers +
1301                                  kExpectedNumSharedSingleThreadedWorkers +
1302                                  kExpectedNumCOMSharedSingleThreadedWorkers);
1303   TearDown();
1304   observer->WaitCallsOnMainExit();
1305 }
1306 
1307 // Verify a basic EnqueueJobTaskSource() runs the worker task.
TEST_P(ThreadPoolImplTest,ScheduleJobTaskSource)1308 TEST_P(ThreadPoolImplTest, ScheduleJobTaskSource) {
1309   StartThreadPool();
1310 
1311   TestWaitableEvent threads_running;
1312 
1313   auto job_task = base::MakeRefCounted<test::MockJobTask>(
1314       BindLambdaForTesting(
1315           [&threads_running](JobDelegate*) { threads_running.Signal(); }),
1316       /* num_tasks_to_run */ 1);
1317   scoped_refptr<JobTaskSource> task_source =
1318       job_task->GetJobTaskSource(FROM_HERE, {}, thread_pool_.get());
1319 
1320   thread_pool_->EnqueueJobTaskSource(task_source);
1321   threads_running.Wait();
1322 }
1323 
1324 // Verify that calling ShouldYield() returns true for a job task source that
1325 // needs to change thread group because of a priority update.
TEST_P(ThreadPoolImplTest,ThreadGroupChangeShouldYield)1326 TEST_P(ThreadPoolImplTest, ThreadGroupChangeShouldYield) {
1327   StartThreadPool();
1328 
1329   TestWaitableEvent threads_running;
1330   TestWaitableEvent threads_continue;
1331 
1332   auto job_task = base::MakeRefCounted<test::MockJobTask>(
1333       BindLambdaForTesting(
1334           [&threads_running, &threads_continue](JobDelegate* delegate) {
1335             EXPECT_FALSE(delegate->ShouldYield());
1336 
1337             threads_running.Signal();
1338             threads_continue.Wait();
1339 
1340             // The task source needs to yield if background thread groups exist.
1341             EXPECT_EQ(delegate->ShouldYield(),
1342                       CanUseBackgroundThreadTypeForWorkerThread());
1343           }),
1344       /* num_tasks_to_run */ 1);
1345   scoped_refptr<JobTaskSource> task_source = job_task->GetJobTaskSource(
1346       FROM_HERE, {TaskPriority::USER_VISIBLE}, thread_pool_.get());
1347 
1348   thread_pool_->EnqueueJobTaskSource(task_source);
1349   threads_running.Wait();
1350   thread_pool_->UpdatePriority(task_source, TaskPriority::BEST_EFFORT);
1351   threads_continue.Signal();
1352 
1353   // Flush the task tracker to be sure that no local variables are accessed by
1354   // tasks after the end of the scope.
1355   thread_pool_->FlushForTesting();
1356 }
1357 
1358 namespace {
1359 
1360 class MustBeDestroyed {
1361  public:
MustBeDestroyed(bool * was_destroyed)1362   explicit MustBeDestroyed(bool* was_destroyed)
1363       : was_destroyed_(was_destroyed) {}
1364   MustBeDestroyed(const MustBeDestroyed&) = delete;
1365   MustBeDestroyed& operator=(const MustBeDestroyed&) = delete;
~MustBeDestroyed()1366   ~MustBeDestroyed() { *was_destroyed_ = true; }
1367 
1368  private:
1369   const raw_ptr<bool> was_destroyed_;
1370 };
1371 
1372 }  // namespace
1373 
1374 // Regression test for https://crbug.com/945087.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,NoLeakWhenPostingNestedTask)1375 TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
1376        NoLeakWhenPostingNestedTask) {
1377   StartThreadPool();
1378 
1379   SequenceLocalStorageSlot<std::unique_ptr<MustBeDestroyed>> sls;
1380 
1381   bool was_destroyed = false;
1382   auto must_be_destroyed = std::make_unique<MustBeDestroyed>(&was_destroyed);
1383 
1384   auto task_runner = CreateTaskRunnerAndExecutionMode(
1385       thread_pool_.get(), GetTraits(), GetExecutionMode());
1386 
1387   task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&] {
1388                           sls.emplace(std::move(must_be_destroyed));
1389                           task_runner->PostTask(FROM_HERE, DoNothing());
1390                         }));
1391 
1392   TearDown();
1393 
1394   // The TaskRunner should be deleted along with the Sequence and its
1395   // SequenceLocalStorage when dropping this reference.
1396   task_runner = nullptr;
1397 
1398   EXPECT_TRUE(was_destroyed);
1399 }
1400 
1401 namespace {
1402 
1403 struct TaskRunnerAndEvents {
TaskRunnerAndEventsbase::internal::__anon90072ec21a11::TaskRunnerAndEvents1404   TaskRunnerAndEvents(scoped_refptr<UpdateableSequencedTaskRunner> task_runner,
1405                       const TaskPriority updated_priority,
1406                       TestWaitableEvent* expected_previous_event)
1407       : task_runner(std::move(task_runner)),
1408         updated_priority(updated_priority),
1409         expected_previous_event(expected_previous_event) {}
1410 
1411   // The UpdateableSequencedTaskRunner.
1412   scoped_refptr<UpdateableSequencedTaskRunner> task_runner;
1413 
1414   // The priority to use in UpdatePriority().
1415   const TaskPriority updated_priority;
1416 
1417   // Signaled when a task blocking |task_runner| is scheduled.
1418   TestWaitableEvent scheduled;
1419 
1420   // Signaled to release the task blocking |task_runner|.
1421   TestWaitableEvent blocked;
1422 
1423   // Signaled in the task that runs following the priority update.
1424   TestWaitableEvent task_ran;
1425 
1426   // An event that should be signaled before the task following the priority
1427   // update runs.
1428   raw_ptr<TestWaitableEvent> expected_previous_event;
1429 };
1430 
1431 // Create a series of sample task runners that will post tasks at various
1432 // initial priorities, then update priority.
CreateTaskRunnersAndEvents(ThreadPoolImplTest * test,ThreadPolicy thread_policy)1433 std::vector<std::unique_ptr<TaskRunnerAndEvents>> CreateTaskRunnersAndEvents(
1434     ThreadPoolImplTest* test,
1435     ThreadPolicy thread_policy) {
1436   ThreadPoolImpl* thread_pool = test->thread_pool_.get();
1437   std::vector<std::unique_ptr<TaskRunnerAndEvents>> task_runners_and_events;
1438 
1439   // -----
1440   // Task runner that will start as USER_VISIBLE and update to USER_BLOCKING.
1441   // Its task is expected to run first.
1442   task_runners_and_events.push_back(std::make_unique<TaskRunnerAndEvents>(
1443       thread_pool->CreateUpdateableSequencedTaskRunner(
1444           TaskTraits({TaskPriority::USER_VISIBLE, thread_policy})),
1445       TaskPriority::USER_BLOCKING, nullptr));
1446 
1447   // -----
1448   // Task runner that will start as BEST_EFFORT and update to USER_VISIBLE.
1449   // Its task is expected to run after the USER_BLOCKING task runner's task,
1450   // unless resource-efficient thread group exists, in which case they will run
1451   // asynchronously.
1452   TestWaitableEvent* expected_previous_event =
1453       test->GetUseResourceEfficientThreadGroup()
1454           ? nullptr
1455           : &task_runners_and_events.back()->task_ran;
1456   task_runners_and_events.push_back(std::make_unique<TaskRunnerAndEvents>(
1457       thread_pool->CreateUpdateableSequencedTaskRunner(
1458           {TaskPriority::BEST_EFFORT, thread_policy}),
1459       TaskPriority::USER_VISIBLE, expected_previous_event));
1460 
1461   // -----
1462   // Task runner that will start as USER_BLOCKING and update to BEST_EFFORT. Its
1463   // task is expected to run asynchronously with the other two task runners'
1464   // tasks if background thread groups exist, or after the USER_VISIBLE task
1465   // runner's task if not.
1466   //
1467   // If the task following the priority update is expected to run in the
1468   // foreground group, it should be after the task posted to the TaskRunner
1469   // whose priority is updated to USER_VISIBLE.
1470   expected_previous_event =
1471       CanUseBackgroundThreadTypeForWorkerThread() ||
1472               (test->GetUseResourceEfficientThreadGroup() &&
1473                CanUseUtilityThreadTypeForWorkerThread())
1474           ? nullptr
1475           : &task_runners_and_events.back()->task_ran;
1476 
1477   task_runners_and_events.push_back(std::make_unique<TaskRunnerAndEvents>(
1478       thread_pool->CreateUpdateableSequencedTaskRunner(
1479           TaskTraits({TaskPriority::USER_BLOCKING, thread_policy})),
1480       TaskPriority::BEST_EFFORT, expected_previous_event));
1481 
1482   return task_runners_and_events;
1483 }
1484 
1485 // Update the priority of a sequence when it is not scheduled.
TestUpdatePrioritySequenceNotScheduled(ThreadPoolImplTest * test,ThreadPolicy thread_policy)1486 void TestUpdatePrioritySequenceNotScheduled(ThreadPoolImplTest* test,
1487                                             ThreadPolicy thread_policy) {
1488   // This test verifies that tasks run in priority order. With more than 1
1489   // thread per pool, it is possible that tasks don't run in order even if
1490   // threads got tasks from the PriorityQueue in order. Therefore, enforce a
1491   // maximum of 1 thread per pool.
1492   constexpr size_t kLocalMaxNumForegroundThreads = 1;
1493 
1494   test->StartThreadPool(kLocalMaxNumForegroundThreads);
1495   auto task_runners_and_events =
1496       CreateTaskRunnersAndEvents(test, thread_policy);
1497 
1498   // Prevent tasks from running.
1499   test->thread_pool_->BeginFence();
1500 
1501   // Post tasks to multiple task runners while they are at initial priority.
1502   // They won't run immediately because of the call to BeginFence() above.
1503   for (auto& task_runner_and_events : task_runners_and_events) {
1504     task_runner_and_events->task_runner->PostTask(
1505         FROM_HERE,
1506         BindOnce(
1507             &VerifyOrderAndTaskEnvironmentAndSignalEvent,
1508             TaskTraits{task_runner_and_events->updated_priority, thread_policy},
1509             test->GetUseResourceEfficientThreadGroup(),
1510             Unretained(task_runner_and_events->expected_previous_event.get()),
1511             Unretained(&task_runner_and_events->task_ran)));
1512   }
1513 
1514   // Update the priorities of the task runners that posted the tasks.
1515   for (auto& task_runner_and_events : task_runners_and_events) {
1516     task_runner_and_events->task_runner->UpdatePriority(
1517         task_runner_and_events->updated_priority);
1518   }
1519 
1520   // Allow tasks to run.
1521   test->thread_pool_->EndFence();
1522 
1523   for (auto& task_runner_and_events : task_runners_and_events)
1524     task_runner_and_events->task_ran.Wait();
1525 }
1526 
1527 // Update the priority of a sequence when it is scheduled, i.e. not currently
1528 // in a priority queue.
TestUpdatePrioritySequenceScheduled(ThreadPoolImplTest * test,ThreadPolicy thread_policy)1529 void TestUpdatePrioritySequenceScheduled(ThreadPoolImplTest* test,
1530                                          ThreadPolicy thread_policy) {
1531   test->StartThreadPool();
1532   auto task_runners_and_events =
1533       CreateTaskRunnersAndEvents(test, thread_policy);
1534 
1535   // Post blocking tasks to all task runners to prevent tasks from being
1536   // scheduled later in the test.
1537   for (auto& task_runner_and_events : task_runners_and_events) {
1538     task_runner_and_events->task_runner->PostTask(
1539         FROM_HERE, BindLambdaForTesting([&]() {
1540           task_runner_and_events->scheduled.Signal();
1541           task_runner_and_events->blocked.Wait();
1542         }));
1543 
1544     task_runner_and_events->scheduled.Wait();
1545   }
1546 
1547   // Update the priorities of the task runners while they are scheduled and
1548   // blocked.
1549   for (auto& task_runner_and_events : task_runners_and_events) {
1550     task_runner_and_events->task_runner->UpdatePriority(
1551         task_runner_and_events->updated_priority);
1552   }
1553 
1554   // Post an additional task to each task runner.
1555   for (auto& task_runner_and_events : task_runners_and_events) {
1556     task_runner_and_events->task_runner->PostTask(
1557         FROM_HERE,
1558         BindOnce(
1559             &VerifyOrderAndTaskEnvironmentAndSignalEvent,
1560             TaskTraits{task_runner_and_events->updated_priority, thread_policy},
1561             test->GetUseResourceEfficientThreadGroup(),
1562             Unretained(task_runner_and_events->expected_previous_event),
1563             Unretained(&task_runner_and_events->task_ran)));
1564   }
1565 
1566   // Unblock the task blocking each task runner, allowing the additional posted
1567   // tasks to run. Each posted task will verify that it has been posted with
1568   // updated priority when it runs.
1569   for (auto& task_runner_and_events : task_runners_and_events) {
1570     task_runner_and_events->blocked.Signal();
1571     task_runner_and_events->task_ran.Wait();
1572   }
1573 }
1574 
1575 }  // namespace
1576 
TEST_P(ThreadPoolImplTest,UpdatePrioritySequenceNotScheduled_PreferBackground)1577 TEST_P(ThreadPoolImplTest,
1578        UpdatePrioritySequenceNotScheduled_PreferBackground) {
1579   TestUpdatePrioritySequenceNotScheduled(this, ThreadPolicy::PREFER_BACKGROUND);
1580 }
1581 
TEST_P(ThreadPoolImplTest,UpdatePrioritySequenceNotScheduled_MustUseForeground)1582 TEST_P(ThreadPoolImplTest,
1583        UpdatePrioritySequenceNotScheduled_MustUseForeground) {
1584   TestUpdatePrioritySequenceNotScheduled(this,
1585                                          ThreadPolicy::MUST_USE_FOREGROUND);
1586 }
1587 
TEST_P(ThreadPoolImplTest,UpdatePrioritySequenceScheduled_PreferBackground)1588 TEST_P(ThreadPoolImplTest, UpdatePrioritySequenceScheduled_PreferBackground) {
1589   TestUpdatePrioritySequenceScheduled(this, ThreadPolicy::PREFER_BACKGROUND);
1590 }
1591 
TEST_P(ThreadPoolImplTest,UpdatePrioritySequenceScheduled_MustUseForeground)1592 TEST_P(ThreadPoolImplTest, UpdatePrioritySequenceScheduled_MustUseForeground) {
1593   TestUpdatePrioritySequenceScheduled(this, ThreadPolicy::MUST_USE_FOREGROUND);
1594 }
1595 
1596 // Verify that a ThreadPolicy has to be specified in TaskTraits to increase
1597 // TaskPriority from BEST_EFFORT.
TEST_P(ThreadPoolImplTest,UpdatePriorityFromBestEffortNoThreadPolicy)1598 TEST_P(ThreadPoolImplTest, UpdatePriorityFromBestEffortNoThreadPolicy) {
1599   GTEST_FLAG_SET(death_test_style, "threadsafe");
1600   StartThreadPool();
1601   {
1602     auto task_runner = thread_pool_->CreateUpdateableSequencedTaskRunner(
1603         {TaskPriority::BEST_EFFORT});
1604     EXPECT_DCHECK_DEATH(
1605         { task_runner->UpdatePriority(TaskPriority::USER_VISIBLE); });
1606   }
1607   {
1608     auto task_runner = thread_pool_->CreateUpdateableSequencedTaskRunner(
1609         {TaskPriority::BEST_EFFORT});
1610     EXPECT_DCHECK_DEATH(
1611         { task_runner->UpdatePriority(TaskPriority::USER_BLOCKING); });
1612   }
1613 }
1614 
1615 INSTANTIATE_TEST_SUITE_P(All, ThreadPoolImplTest, ::testing::Bool());
1616 
1617 INSTANTIATE_TEST_SUITE_P(
1618     All,
1619     ThreadPoolImplTest_CoverAllSchedulingOptions,
1620     ::testing::Combine(
1621         ::testing::Bool(),
1622         ::testing::ValuesIn(
1623             GetTraitsExecutionModePairsToCoverAllSchedulingOptions())));
1624 
1625 }  // namespace internal
1626 }  // namespace base
1627