#include "base/task/thread_pool/pooled_single_thread_task_runner_manager.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/synchronization/atomic_flag.h"
#include "base/synchronization/lock.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool/can_run_policy_test.h"
#include "base/task/thread_pool/delayed_task_manager.h"
#include "base/task/thread_pool/environment_config.h"
#include "base/task/thread_pool/task_tracker.h"
#include "base/task/thread_pool/test_utils.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/simple_thread.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include "base/win/com_init_util.h"
#include "base/win/current_module.h"
#endif
namespace base {
namespace internal {
namespace {
class PooledSingleThreadTaskRunnerManagerTest : public testing::Test { … };
void CaptureThreadRef(PlatformThreadRef* thread_ref) { … }
void ShouldNotRun() { … }
}
TEST_F(PooledSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) { … }
TEST_F(PooledSingleThreadTaskRunnerManagerTest, SameThreadUsed) { … }
TEST_F(PooledSingleThreadTaskRunnerManagerTest, RunsTasksInCurrentSequence) { … }
TEST_F(PooledSingleThreadTaskRunnerManagerTest,
SharedWithBaseSyncPrimitivesDCHECKs) { … }
TEST_F(PooledSingleThreadTaskRunnerManagerTest,
ContinueOnShutdownDoesNotBlockBlockShutdown) { … }
namespace {
class PooledSingleThreadTaskRunnerManagerCommonTest
: public PooledSingleThreadTaskRunnerManagerTest,
public ::testing::WithParamInterface<
std::tuple<SingleThreadTaskRunnerThreadMode,
bool >> { … };
}
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, ThreadTypeSetCorrectly) { … }
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, ThreadNamesSet) { … }
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PostTaskAfterShutdown) { … }
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PostDelayedTask) { … }
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, PostTaskAfterDestroy) { … }
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, CanRunPolicyBasic) { … }
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest,
CanRunPolicyUpdatedBeforeRun) { … }
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, CanRunPolicyLoad) { … }
INSTANTIATE_TEST_SUITE_P(…);
namespace {
class CallJoinFromDifferentThread : public SimpleThread { … };
class PooledSingleThreadTaskRunnerManagerJoinTest
: public PooledSingleThreadTaskRunnerManagerTest { … };
}
TEST_F(PooledSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) { … }
TEST_F(PooledSingleThreadTaskRunnerManagerJoinTest,
ConcurrentJoinExtraSkippedTask) { … }
#if BUILDFLAG(IS_WIN)
TEST_P(PooledSingleThreadTaskRunnerManagerCommonTest, COMSTAInitialized) {
scoped_refptr<SingleThreadTaskRunner> com_task_runner =
single_thread_task_runner_manager_->CreateCOMSTATaskRunner(
{TaskShutdownBehavior::BLOCK_SHUTDOWN},
GetSingleThreadTaskRunnerThreadMode());
com_task_runner->PostTask(FROM_HERE, BindOnce(&win::AssertComApartmentType,
win::ComApartmentType::STA));
test::ShutdownTaskTracker(&task_tracker_);
}
TEST_F(PooledSingleThreadTaskRunnerManagerTest, COMSTASameThreadUsed) {
scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
single_thread_task_runner_manager_->CreateCOMSTATaskRunner(
{TaskShutdownBehavior::BLOCK_SHUTDOWN},
SingleThreadTaskRunnerThreadMode::SHARED);
scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
single_thread_task_runner_manager_->CreateCOMSTATaskRunner(
{TaskShutdownBehavior::BLOCK_SHUTDOWN},
SingleThreadTaskRunnerThreadMode::SHARED);
PlatformThreadRef thread_ref_1;
task_runner_1->PostTask(FROM_HERE,
BindOnce(&CaptureThreadRef, &thread_ref_1));
PlatformThreadRef thread_ref_2;
task_runner_2->PostTask(FROM_HERE,
BindOnce(&CaptureThreadRef, &thread_ref_2));
test::ShutdownTaskTracker(&task_tracker_);
ASSERT_FALSE(thread_ref_1.is_null());
ASSERT_FALSE(thread_ref_2.is_null());
EXPECT_EQ(thread_ref_1, thread_ref_2);
}
namespace {
const wchar_t* const kTestWindowClassName =
L"PooledSingleThreadTaskRunnerManagerTestWinMessageWindow";
class PooledSingleThreadTaskRunnerManagerTestWin
: public PooledSingleThreadTaskRunnerManagerTest {
public:
PooledSingleThreadTaskRunnerManagerTestWin() = default;
PooledSingleThreadTaskRunnerManagerTestWin(
const PooledSingleThreadTaskRunnerManagerTestWin&) = delete;
PooledSingleThreadTaskRunnerManagerTestWin& operator=(
const PooledSingleThreadTaskRunnerManagerTestWin&) = delete;
void SetUp() override {
PooledSingleThreadTaskRunnerManagerTest::SetUp();
register_class_succeeded_ = RegisterTestWindowClass();
ASSERT_TRUE(register_class_succeeded_);
}
void TearDown() override {
if (register_class_succeeded_)
::UnregisterClass(kTestWindowClassName, CURRENT_MODULE());
PooledSingleThreadTaskRunnerManagerTest::TearDown();
}
HWND CreateTestWindow() {
return CreateWindow(kTestWindowClassName, kTestWindowClassName, 0, 0, 0, 0,
0, HWND_MESSAGE, nullptr, CURRENT_MODULE(), nullptr);
}
private:
bool RegisterTestWindowClass() {
WNDCLASSEX window_class = {};
window_class.cbSize = sizeof(window_class);
window_class.lpfnWndProc = &::DefWindowProc;
window_class.hInstance = CURRENT_MODULE();
window_class.lpszClassName = kTestWindowClassName;
return !!::RegisterClassEx(&window_class);
}
bool register_class_succeeded_ = false;
};
}
TEST_F(PooledSingleThreadTaskRunnerManagerTestWin, PumpsMessages) {
scoped_refptr<SingleThreadTaskRunner> com_task_runner =
single_thread_task_runner_manager_->CreateCOMSTATaskRunner(
{TaskShutdownBehavior::BLOCK_SHUTDOWN},
SingleThreadTaskRunnerThreadMode::DEDICATED);
HWND hwnd = nullptr;
com_task_runner->PostTask(
FROM_HERE,
BindOnce([](PooledSingleThreadTaskRunnerManagerTestWin* test_harness,
HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); },
Unretained(this), &hwnd));
task_tracker_.FlushForTesting();
ASSERT_NE(hwnd, nullptr);
SendMessage(hwnd, WM_USER, 0, 0);
com_task_runner->PostTask(
FROM_HERE, BindOnce([](HWND hwnd) { ::DestroyWindow(hwnd); }, hwnd));
test::ShutdownTaskTracker(&task_tracker_);
}
#endif
namespace {
class PooledSingleThreadTaskRunnerManagerStartTest
: public PooledSingleThreadTaskRunnerManagerTest { … };
}
TEST_F(PooledSingleThreadTaskRunnerManagerStartTest, PostTaskBeforeStart) { … }
}
}