200 lines
7.6 KiB
C++
200 lines
7.6 KiB
C++
// Copyright 2017 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/task_scheduler/lazy_task_runner.h"
|
|
|
|
#include "base/bind.h"
|
|
#include "base/bind_helpers.h"
|
|
#include "base/sequence_checker_impl.h"
|
|
#include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h"
|
|
#include "base/test/scoped_task_environment.h"
|
|
#include "base/threading/thread_checker_impl.h"
|
|
#include "build/build_config.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
#if defined(OS_WIN)
|
|
#include "base/win/com_init_util.h"
|
|
#endif
|
|
|
|
namespace base {
|
|
|
|
namespace {
|
|
|
|
LazySequencedTaskRunner g_sequenced_task_runner_user_visible =
|
|
LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({TaskPriority::USER_VISIBLE});
|
|
LazySequencedTaskRunner g_sequenced_task_runner_user_blocking =
|
|
LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({TaskPriority::USER_BLOCKING});
|
|
|
|
LazySingleThreadTaskRunner g_single_thread_task_runner_user_visible =
|
|
LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(
|
|
{TaskPriority::USER_VISIBLE},
|
|
SingleThreadTaskRunnerThreadMode::SHARED);
|
|
LazySingleThreadTaskRunner g_single_thread_task_runner_user_blocking =
|
|
LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(
|
|
{TaskPriority::USER_BLOCKING},
|
|
SingleThreadTaskRunnerThreadMode::SHARED);
|
|
|
|
#if defined(OS_WIN)
|
|
LazyCOMSTATaskRunner g_com_sta_task_runner_user_visible =
|
|
LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
|
|
{TaskPriority::USER_VISIBLE},
|
|
SingleThreadTaskRunnerThreadMode::SHARED);
|
|
LazyCOMSTATaskRunner g_com_sta_task_runner_user_blocking =
|
|
LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
|
|
{TaskPriority::USER_BLOCKING},
|
|
SingleThreadTaskRunnerThreadMode::SHARED);
|
|
#endif // defined(OS_WIN)
|
|
|
|
void InitCheckers(SequenceCheckerImpl* sequence_checker,
|
|
ThreadCheckerImpl* thread_checker) {
|
|
sequence_checker->DetachFromSequence();
|
|
EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
|
|
thread_checker->DetachFromThread();
|
|
EXPECT_TRUE(thread_checker->CalledOnValidThread());
|
|
}
|
|
|
|
void ExpectSequencedEnvironment(SequenceCheckerImpl* sequence_checker,
|
|
ThreadCheckerImpl* thread_checker,
|
|
TaskPriority expected_priority) {
|
|
EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
|
|
EXPECT_FALSE(thread_checker->CalledOnValidThread());
|
|
EXPECT_EQ(expected_priority, internal::GetTaskPriorityForCurrentThread());
|
|
}
|
|
|
|
void ExpectSingleThreadEnvironment(SequenceCheckerImpl* sequence_checker,
|
|
ThreadCheckerImpl* thread_checker,
|
|
TaskPriority expected_priority
|
|
#if defined(OS_WIN)
|
|
,
|
|
bool expect_com_sta = false
|
|
#endif
|
|
) {
|
|
EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
|
|
EXPECT_TRUE(thread_checker->CalledOnValidThread());
|
|
EXPECT_EQ(expected_priority, internal::GetTaskPriorityForCurrentThread());
|
|
|
|
#if defined(OS_WIN)
|
|
if (expect_com_sta)
|
|
win::AssertComApartmentType(win::ComApartmentType::STA);
|
|
#endif
|
|
}
|
|
|
|
class TaskSchedulerLazyTaskRunnerEnvironmentTest : public testing::Test {
|
|
protected:
|
|
TaskSchedulerLazyTaskRunnerEnvironmentTest() = default;
|
|
|
|
void TestTaskRunnerEnvironment(scoped_refptr<SequencedTaskRunner> task_runner,
|
|
bool expect_single_thread,
|
|
TaskPriority expected_priority
|
|
#if defined(OS_WIN)
|
|
,
|
|
bool expect_com_sta = false
|
|
#endif
|
|
) {
|
|
SequenceCheckerImpl sequence_checker;
|
|
ThreadCheckerImpl thread_checker;
|
|
task_runner->PostTask(FROM_HERE,
|
|
BindOnce(&InitCheckers, Unretained(&sequence_checker),
|
|
Unretained(&thread_checker)));
|
|
scoped_task_environment_.RunUntilIdle();
|
|
|
|
OnceClosure task =
|
|
expect_single_thread
|
|
? BindOnce(&ExpectSingleThreadEnvironment,
|
|
Unretained(&sequence_checker),
|
|
Unretained(&thread_checker), expected_priority
|
|
#if defined(OS_WIN)
|
|
,
|
|
expect_com_sta
|
|
#endif
|
|
)
|
|
: BindOnce(&ExpectSequencedEnvironment,
|
|
Unretained(&sequence_checker),
|
|
Unretained(&thread_checker), expected_priority);
|
|
task_runner->PostTask(FROM_HERE, std::move(task));
|
|
scoped_task_environment_.RunUntilIdle();
|
|
}
|
|
|
|
test::ScopedTaskEnvironment scoped_task_environment_;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(TaskSchedulerLazyTaskRunnerEnvironmentTest);
|
|
};
|
|
|
|
} // namespace
|
|
|
|
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
|
|
LazySequencedTaskRunnerUserVisible) {
|
|
TestTaskRunnerEnvironment(g_sequenced_task_runner_user_visible.Get(), false,
|
|
TaskPriority::USER_VISIBLE);
|
|
}
|
|
|
|
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
|
|
LazySequencedTaskRunnerUserBlocking) {
|
|
TestTaskRunnerEnvironment(g_sequenced_task_runner_user_blocking.Get(), false,
|
|
TaskPriority::USER_BLOCKING);
|
|
}
|
|
|
|
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
|
|
LazySingleThreadTaskRunnerUserVisible) {
|
|
TestTaskRunnerEnvironment(g_single_thread_task_runner_user_visible.Get(),
|
|
true, TaskPriority::USER_VISIBLE);
|
|
}
|
|
|
|
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
|
|
LazySingleThreadTaskRunnerUserBlocking) {
|
|
TestTaskRunnerEnvironment(g_single_thread_task_runner_user_blocking.Get(),
|
|
true, TaskPriority::USER_BLOCKING);
|
|
}
|
|
|
|
#if defined(OS_WIN)
|
|
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
|
|
LazyCOMSTATaskRunnerUserVisible) {
|
|
TestTaskRunnerEnvironment(g_com_sta_task_runner_user_visible.Get(), true,
|
|
TaskPriority::USER_VISIBLE, true);
|
|
}
|
|
|
|
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
|
|
LazyCOMSTATaskRunnerUserBlocking) {
|
|
TestTaskRunnerEnvironment(g_com_sta_task_runner_user_blocking.Get(), true,
|
|
TaskPriority::USER_BLOCKING, true);
|
|
}
|
|
#endif // defined(OS_WIN)
|
|
|
|
TEST(TaskSchdulerLazyTaskRunnerTest, LazySequencedTaskRunnerReset) {
|
|
for (int i = 0; i < 2; ++i) {
|
|
test::ScopedTaskEnvironment scoped_task_environment;
|
|
// If the TaskRunner isn't released when the test::ScopedTaskEnvironment
|
|
// goes out of scope, the second invocation of the line below will access a
|
|
// deleted TaskScheduler and crash.
|
|
g_sequenced_task_runner_user_visible.Get()->PostTask(FROM_HERE,
|
|
DoNothing());
|
|
}
|
|
}
|
|
|
|
TEST(TaskSchdulerLazyTaskRunnerTest, LazySingleThreadTaskRunnerReset) {
|
|
for (int i = 0; i < 2; ++i) {
|
|
test::ScopedTaskEnvironment scoped_task_environment;
|
|
// If the TaskRunner isn't released when the test::ScopedTaskEnvironment
|
|
// goes out of scope, the second invocation of the line below will access a
|
|
// deleted TaskScheduler and crash.
|
|
g_single_thread_task_runner_user_visible.Get()->PostTask(FROM_HERE,
|
|
DoNothing());
|
|
}
|
|
}
|
|
|
|
#if defined(OS_WIN)
|
|
TEST(TaskSchdulerLazyTaskRunnerTest, LazyCOMSTATaskRunnerReset) {
|
|
for (int i = 0; i < 2; ++i) {
|
|
test::ScopedTaskEnvironment scoped_task_environment;
|
|
// If the TaskRunner isn't released when the test::ScopedTaskEnvironment
|
|
// goes out of scope, the second invocation of the line below will access a
|
|
// deleted TaskScheduler and crash.
|
|
g_com_sta_task_runner_user_visible.Get()->PostTask(FROM_HERE, DoNothing());
|
|
}
|
|
}
|
|
#endif // defined(OS_WIN)
|
|
|
|
} // namespace base
|