#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "base/task/thread_pool/thread_pool_impl.h"
#include <stddef.h>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "base/base_switches.h"
#include "base/cfi_buildflags.h"
#include "base/containers/span.h"
#include "base/debug/stack_trace.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/message_loop/message_pump_type.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/system/sys_info.h"
#include "base/task/task_features.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool/environment_config.h"
#include "base/task/thread_pool/test_task_factory.h"
#include "base/task/thread_pool/test_utils.h"
#include "base/task/thread_pool/worker_thread_observer.h"
#include "base/task/updateable_sequenced_task_runner.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "base/test/test_waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_POSIX)
#include <unistd.h>
#include "base/debug/leak_annotations.h"
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/files/file_util.h"
#include "base/posix/eintr_wrapper.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/com_init_util.h"
#endif
namespace base {
namespace internal {
namespace {
constexpr size_t kMaxNumForegroundThreads = …;
constexpr size_t kMaxNumUtilityThreads = …;
struct TraitsExecutionModePair { … };
bool TraitsSupportBackgroundThreadType(const TaskTraits& traits) { … }
bool TraitsSupportUtilityThreadType(const TaskTraits& traits) { … }
void VerifyTaskEnvironment(const TaskTraits& traits,
bool use_resource_efficient_group) { … }
void VerifyTaskEnvironmentAndSignalEvent(const TaskTraits& traits,
bool use_resource_efficient_group,
TestWaitableEvent* event) { … }
void VerifyTimeAndTaskEnvironmentAndSignalEvent(
const TaskTraits& traits,
bool use_resource_efficient_group,
TimeTicks expected_time,
TestWaitableEvent* event) { … }
void VerifyOrderAndTaskEnvironmentAndSignalEvent(
const TaskTraits& traits,
bool use_resource_efficient_group,
TestWaitableEvent* expected_previous_event,
TestWaitableEvent* event) { … }
scoped_refptr<TaskRunner> CreateTaskRunnerAndExecutionMode(
ThreadPoolImpl* thread_pool,
const TaskTraits& traits,
TaskSourceExecutionMode execution_mode,
SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode =
SingleThreadTaskRunnerThreadMode::SHARED) { … }
class ThreadPostingTasks : public SimpleThread { … };
std::vector<TraitsExecutionModePair> GetTraitsExecutionModePairs() { … }
std::vector<TraitsExecutionModePair>
GetTraitsExecutionModePairsToCoverAllSchedulingOptions() { … }
class ThreadPoolImplTestBase : public testing::Test { … };
class ThreadPoolImplTest : public ThreadPoolImplTestBase,
public testing::WithParamInterface<
bool > { … };
class ThreadPoolImplTest_CoverAllSchedulingOptions
: public ThreadPoolImplTestBase,
public testing::WithParamInterface<
std::tuple<bool ,
TraitsExecutionModePair>> { … };
}
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostDelayedTaskNoDelay) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostDelayedTaskWithDelay) { … }
namespace {
scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerAndExecutionMode(
ThreadPoolImpl* thread_pool,
const TaskTraits& traits,
TaskSourceExecutionMode execution_mode,
SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode =
SingleThreadTaskRunnerThreadMode::SHARED) { … }
}
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
PostDelayedTaskAtViaTaskRunner) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostTasksViaTaskRunner) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
PostDelayedTaskNoDelayBeforeStart) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
PostDelayedTaskWithDelayBeforeStart) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
PostTaskViaTaskRunnerBeforeStart) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostTaskAfterDestroy) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
FlushAsyncForTestingSimple) { … }
TEST(ThreadPoolImplTest_Switch, DisableBestEffortTasksSwitch) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, Fence) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, MultipleFences) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, FenceBeforeStart) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, BestEffortFence) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, MultipleBestEffortFences) { … }
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
BestEffortFenceBeforeStart) { … }
TEST_P(ThreadPoolImplTest, MultipleTraitsExecutionModePair) { … }
TEST_P(ThreadPoolImplTest,
GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated) { … }
TEST_P(ThreadPoolImplTest, SequencedRunsTasksInCurrentSequence) { … }
TEST_P(ThreadPoolImplTest, SingleThreadRunsTasksInCurrentSequence) { … }
#if BUILDFLAG(IS_WIN)
TEST_P(ThreadPoolImplTest, COMSTATaskRunnersRunWithCOMSTA) {
StartThreadPool();
auto com_sta_task_runner = thread_pool_->CreateCOMSTATaskRunner(
{}, SingleThreadTaskRunnerThreadMode::SHARED);
TestWaitableEvent task_ran;
com_sta_task_runner->PostTask(
FROM_HERE, BindOnce(
[](TestWaitableEvent* task_ran) {
win::AssertComApartmentType(win::ComApartmentType::STA);
task_ran->Signal();
},
Unretained(&task_ran)));
task_ran.Wait();
}
#endif
TEST_P(ThreadPoolImplTest, DelayedTasksNotRunAfterShutdown) { … }
#if BUILDFLAG(IS_POSIX)
TEST_P(ThreadPoolImplTest, FileDescriptorWatcherNoOpsAfterShutdown) { … }
#endif
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, FileDescriptorWatcher) { … }
#endif
TEST_P(ThreadPoolImplTest, SequenceLocalStorage) { … }
TEST_P(ThreadPoolImplTest, FlushAsyncNoTasks) { … }
namespace {
void VerifyHasStringsOnStack(const std::string& pool_str,
const std::string& shutdown_behavior_str) { … }
}
#if BUILDFLAG(IS_POSIX)
#define MAYBE_IdentifiableStacks …
#elif BUILDFLAG(IS_WIN) && \
(defined(ADDRESS_SANITIZER) || BUILDFLAG(CFI_CAST_CHECK))
#define MAYBE_IdentifiableStacks …
#else
#define MAYBE_IdentifiableStacks …
#endif
TEST_P(ThreadPoolImplTest, MAYBE_IdentifiableStacks) { … }
TEST_P(ThreadPoolImplTest, WorkerThreadObserver) { … }
TEST_P(ThreadPoolImplTest, ScheduleJobTaskSource) { … }
TEST_P(ThreadPoolImplTest, ThreadGroupChangeShouldYield) { … }
namespace {
class MustBeDestroyed { … };
}
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
NoLeakWhenPostingNestedTask) { … }
namespace {
struct TaskRunnerAndEvents { … };
std::vector<std::unique_ptr<TaskRunnerAndEvents>> CreateTaskRunnersAndEvents(
ThreadPoolImplTest* test,
ThreadPolicy thread_policy) { … }
void TestUpdatePrioritySequenceNotScheduled(ThreadPoolImplTest* test,
ThreadPolicy thread_policy) { … }
void TestUpdatePrioritySequenceScheduled(ThreadPoolImplTest* test,
ThreadPolicy thread_policy) { … }
}
TEST_P(ThreadPoolImplTest,
UpdatePrioritySequenceNotScheduled_PreferBackground) { … }
TEST_P(ThreadPoolImplTest,
UpdatePrioritySequenceNotScheduled_MustUseForeground) { … }
TEST_P(ThreadPoolImplTest, UpdatePrioritySequenceScheduled_PreferBackground) { … }
TEST_P(ThreadPoolImplTest, UpdatePrioritySequenceScheduled_MustUseForeground) { … }
TEST_P(ThreadPoolImplTest, UpdatePriorityFromBestEffortNoThreadPolicy) { … }
INSTANTIATE_TEST_SUITE_P(…);
INSTANTIATE_TEST_SUITE_P(…);
}
}