| Index: base/task_scheduler/scheduler_single_thread_worker_pool_manager_unittest.cc
|
| diff --git a/base/task_scheduler/scheduler_single_thread_worker_pool_manager_unittest.cc b/base/task_scheduler/scheduler_single_thread_worker_pool_manager_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..891777847bcb683170b04ba1426e8e6d6454b42f
|
| --- /dev/null
|
| +++ b/base/task_scheduler/scheduler_single_thread_worker_pool_manager_unittest.cc
|
| @@ -0,0 +1,178 @@
|
| +// 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/scheduler_single_thread_worker_pool_manager.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/synchronization/lock.h"
|
| +#include "base/task_scheduler/delayed_task_manager.h"
|
| +#include "base/task_scheduler/scheduler_worker_pool_params.h"
|
| +#include "base/task_scheduler/task_tracker.h"
|
| +#include "base/task_scheduler/task_traits.h"
|
| +#include "base/threading/thread.h"
|
| +#include "base/threading/thread_local_storage.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace base {
|
| +namespace internal {
|
| +
|
| +namespace {
|
| +
|
| +constexpr size_t kMagicTlsValue = 42;
|
| +
|
| +enum WorkerPoolType {
|
| + BACKGROUND_WORKER_POOL = 0,
|
| + FOREGROUND_WORKER_POOL,
|
| +};
|
| +
|
| +static size_t GetThreadPoolIndexForTraits(const TaskTraits& traits) {
|
| + return traits.priority() == TaskPriority::BACKGROUND ? BACKGROUND_WORKER_POOL
|
| + : FOREGROUND_WORKER_POOL;
|
| +}
|
| +
|
| +class TaskSchedulerSingleThreadWorkerPoolManagerTest : public testing::Test {
|
| + public:
|
| + TaskSchedulerSingleThreadWorkerPoolManagerTest()
|
| + : service_thread_("TaskSchedulerServiceThread") {}
|
| +
|
| + void SetUp() override {
|
| + ASSERT_FALSE(delayed_task_manager_);
|
| + service_thread_.Start();
|
| +
|
| + using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy;
|
| +
|
| + std::vector<SchedulerWorkerPoolParams> params_vector;
|
| +
|
| + ASSERT_EQ(BACKGROUND_WORKER_POOL, params_vector.size());
|
| + params_vector.emplace_back("Background", ThreadPriority::BACKGROUND,
|
| + StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max());
|
| +
|
| + ASSERT_EQ(FOREGROUND_WORKER_POOL, params_vector.size());
|
| + params_vector.emplace_back("Foreground", ThreadPriority::NORMAL,
|
| + StandbyThreadPolicy::LAZY, 1U, TimeDelta::Max());
|
| +
|
| + delayed_task_manager_ =
|
| + MakeUnique<DelayedTaskManager>(service_thread_.task_runner());
|
| + single_thread_worker_pool_manager_ =
|
| + MakeUnique<SchedulerSingleThreadWorkerPoolManager>(
|
| + params_vector, Bind(&GetThreadPoolIndexForTraits), &task_tracker_,
|
| + delayed_task_manager_.get());
|
| + }
|
| +
|
| + void TearDown() override {
|
| + single_thread_worker_pool_manager_->JoinForTesting();
|
| + single_thread_worker_pool_manager_.reset();
|
| + delayed_task_manager_.reset();
|
| + service_thread_.Stop();
|
| + }
|
| +
|
| + protected:
|
| + std::unique_ptr<SchedulerSingleThreadWorkerPoolManager>
|
| + single_thread_worker_pool_manager_;
|
| +
|
| + private:
|
| + TaskTracker task_tracker_;
|
| + Thread service_thread_;
|
| + std::unique_ptr<DelayedTaskManager> delayed_task_manager_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadWorkerPoolManagerTest);
|
| +};
|
| +
|
| +void CaptureThreadId(PlatformThreadId* thread_id) {
|
| + ASSERT_TRUE(thread_id);
|
| + *thread_id = PlatformThread::CurrentId();
|
| +}
|
| +
|
| +void CaptureThreadPriority(ThreadPriority* thread_priority) {
|
| + ASSERT_TRUE(thread_priority);
|
| + *thread_priority = PlatformThread::GetCurrentThreadPriority();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +TEST_F(TaskSchedulerSingleThreadWorkerPoolManagerTest, DifferentThreadsUsed) {
|
| + scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
|
| + single_thread_worker_pool_manager_
|
| + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits());
|
| + scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
|
| + single_thread_worker_pool_manager_
|
| + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits());
|
| +
|
| + PlatformThreadId thread_id_1 = kInvalidThreadId;
|
| + task_runner_1->PostTask(FROM_HERE, Bind(&CaptureThreadId, &thread_id_1));
|
| + PlatformThreadId thread_id_2 = kInvalidThreadId;
|
| + task_runner_2->PostTask(FROM_HERE, Bind(&CaptureThreadId, &thread_id_2));
|
| + single_thread_worker_pool_manager_->WaitForAllWorkersIdleForTesting();
|
| +
|
| + ASSERT_NE(kInvalidThreadId, thread_id_1);
|
| + ASSERT_NE(kInvalidThreadId, thread_id_2);
|
| + EXPECT_NE(thread_id_1, thread_id_2);
|
| +}
|
| +
|
| +TEST_F(TaskSchedulerSingleThreadWorkerPoolManagerTest, PrioritySetCorrectly) {
|
| + scoped_refptr<SingleThreadTaskRunner> task_runner_background =
|
| + single_thread_worker_pool_manager_
|
| + ->CreateSingleThreadTaskRunnerWithTraits(
|
| + TaskTraits().WithPriority(TaskPriority::BACKGROUND));
|
| + scoped_refptr<SingleThreadTaskRunner> task_runner_user_visible =
|
| + single_thread_worker_pool_manager_
|
| + ->CreateSingleThreadTaskRunnerWithTraits(
|
| + TaskTraits().WithPriority(TaskPriority::USER_VISIBLE));
|
| + scoped_refptr<SingleThreadTaskRunner> task_runner_user_blocking =
|
| + single_thread_worker_pool_manager_
|
| + ->CreateSingleThreadTaskRunnerWithTraits(
|
| + TaskTraits().WithPriority(TaskPriority::USER_BLOCKING));
|
| +
|
| + ThreadPriority thread_priority_background;
|
| + task_runner_background->PostTask(
|
| + FROM_HERE, Bind(&CaptureThreadPriority, &thread_priority_background));
|
| + ThreadPriority thread_priority_user_visible;
|
| + task_runner_user_visible->PostTask(
|
| + FROM_HERE, Bind(&CaptureThreadPriority, &thread_priority_user_visible));
|
| + ThreadPriority thread_priority_user_blocking;
|
| + task_runner_user_blocking->PostTask(
|
| + FROM_HERE, Bind(&CaptureThreadPriority, &thread_priority_user_blocking));
|
| + single_thread_worker_pool_manager_->WaitForAllWorkersIdleForTesting();
|
| +
|
| + if (Lock::HandlesMultipleThreadPriorities())
|
| + EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background);
|
| + else
|
| + EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background);
|
| + EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_visible);
|
| + EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_blocking);
|
| +}
|
| +
|
| +TEST_F(TaskSchedulerSingleThreadWorkerPoolManagerTest, ThreadsReused) {
|
| + scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
|
| + single_thread_worker_pool_manager_
|
| + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits());
|
| + ThreadLocalStorage::Slot slot;
|
| + task_runner_1->PostTask(
|
| + FROM_HERE, Bind(
|
| + [](ThreadLocalStorage::Slot* slot) {
|
| + slot->Set(reinterpret_cast<void*>(kMagicTlsValue));
|
| + },
|
| + base::Unretained(&slot)));
|
| + single_thread_worker_pool_manager_->WaitForAllWorkersIdleForTesting();
|
| + task_runner_1 = nullptr;
|
| +
|
| + scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
|
| + single_thread_worker_pool_manager_
|
| + ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits());
|
| + size_t tls_value = 0;
|
| + task_runner_2->PostTask(
|
| + FROM_HERE, Bind(
|
| + [](ThreadLocalStorage::Slot* slot, size_t* tls_value) {
|
| + *tls_value = reinterpret_cast<size_t>(slot->Get());
|
| + },
|
| + Unretained(&slot), Unretained(&tls_value)));
|
| +
|
| + single_thread_worker_pool_manager_->WaitForAllWorkersIdleForTesting();
|
| +
|
| + EXPECT_EQ(42U, tls_value);
|
| +}
|
| +
|
| +} // namespace internal
|
| +} // namespace base
|
|
|