| Index: base/task_scheduler/scheduler_worker_thread_unittest.cc
|
| diff --git a/base/task_scheduler/scheduler_worker_thread_unittest.cc b/base/task_scheduler/scheduler_worker_thread_unittest.cc
|
| index 0131dcf0d7b07f9989ebf46d7247fd9b247fb29c..fb4be984c04e95dd20f4f534c1865c73c6d0c587 100644
|
| --- a/base/task_scheduler/scheduler_worker_thread_unittest.cc
|
| +++ b/base/task_scheduler/scheduler_worker_thread_unittest.cc
|
| @@ -14,6 +14,8 @@
|
| #include "base/macros.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/synchronization/condition_variable.h"
|
| +#include "base/task_scheduler/delayed_task_manager.h"
|
| +#include "base/task_scheduler/priority_queue.h"
|
| #include "base/task_scheduler/scheduler_lock.h"
|
| #include "base/task_scheduler/sequence.h"
|
| #include "base/task_scheduler/task.h"
|
| @@ -24,19 +26,22 @@ namespace base {
|
| namespace internal {
|
| namespace {
|
|
|
| -const size_t kNumSequencesPerTest = 150;
|
| +constexpr size_t kNumTasksPerTest = 150;
|
|
|
| // The test parameter is the number of Tasks per Sequence returned by GetWork().
|
| -class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>,
|
| - public SchedulerWorkerThread::Delegate {
|
| +class TaskSchedulerWorkerThreadDelegateWorkTest
|
| + : public testing::TestWithParam<size_t>,
|
| + public SchedulerWorkerThread::Delegate {
|
| protected:
|
| - TaskSchedulerWorkerThreadTest()
|
| - : main_entry_called_(true, false),
|
| + TaskSchedulerWorkerThreadDelegateWorkTest()
|
| + : delayed_task_manager_(Bind(&DoNothing)),
|
| + main_entry_called_(true, false),
|
| num_get_work_cv_(lock_.CreateConditionVariable()) {}
|
|
|
| void SetUp() override {
|
| worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread(
|
| - ThreadPriority::NORMAL, this, &task_tracker_);
|
| + ThreadPriority::NORMAL, this, &task_tracker_, &delayed_task_manager_,
|
| + &dummy_priority_queue_);
|
| ASSERT_TRUE(worker_thread_);
|
| main_entry_called_.Wait();
|
| }
|
| @@ -93,7 +98,9 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>,
|
| }
|
|
|
| scoped_refptr<Sequence> GetWork(
|
| - SchedulerWorkerThread* worker_thread) override {
|
| + SchedulerWorkerThread* worker_thread,
|
| + PriorityQueue* alternate_priority_queue,
|
| + bool* alternate_priority_queue_used) override {
|
| EXPECT_EQ(worker_thread_.get(), worker_thread);
|
|
|
| {
|
| @@ -116,8 +123,9 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>,
|
| scoped_refptr<Sequence> sequence(new Sequence);
|
| for (size_t i = 0; i < TasksPerSequence(); ++i) {
|
| std::unique_ptr<Task> task(new Task(
|
| - FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback,
|
| - Unretained(this)),
|
| + FROM_HERE,
|
| + Bind(&TaskSchedulerWorkerThreadDelegateWorkTest::RunTaskCallback,
|
| + Unretained(this)),
|
| TaskTraits(), TimeTicks()));
|
| EXPECT_TRUE(task_tracker_.WillPostTask(task.get()));
|
| sequence->PushTask(std::move(task));
|
| @@ -159,6 +167,8 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>,
|
| }
|
|
|
| TaskTracker task_tracker_;
|
| + DelayedTaskManager delayed_task_manager_;
|
| + PriorityQueue dummy_priority_queue_;
|
|
|
| // Synchronizes access to all members below.
|
| mutable SchedulerLock lock_;
|
| @@ -188,19 +198,19 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>,
|
| // Number of times that RunTaskCallback() has been called.
|
| size_t num_run_tasks_ = 0;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadTest);
|
| + DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadDelegateWorkTest);
|
| };
|
|
|
| // Verify that when GetWork() continuously returns Sequences, all Tasks in these
|
| // Sequences run successfully. The test wakes up the SchedulerWorkerThread once.
|
| -TEST_P(TaskSchedulerWorkerThreadTest, ContinuousWork) {
|
| - // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to
|
| +TEST_P(TaskSchedulerWorkerThreadDelegateWorkTest, ContinuousWork) {
|
| + // Set GetWork() to return |kNumTasksPerTest| Sequences before starting to
|
| // return nullptr.
|
| - SetNumSequencesToCreate(kNumSequencesPerTest);
|
| + SetNumSequencesToCreate(kNumTasksPerTest);
|
|
|
| - // Expect |kNumSequencesPerTest| calls to GetWork() in which it returns a
|
| + // Expect |kNumTasksPerTest| calls to GetWork() in which it returns a
|
| // Sequence and one call in which its returns nullptr.
|
| - const size_t kExpectedNumGetWork = kNumSequencesPerTest + 1;
|
| + constexpr size_t kExpectedNumGetWork = kNumTasksPerTest + 1;
|
| SetMaxGetWork(kExpectedNumGetWork);
|
|
|
| // Wake up |worker_thread_| and wait until GetWork() has been invoked the
|
| @@ -209,7 +219,7 @@ TEST_P(TaskSchedulerWorkerThreadTest, ContinuousWork) {
|
| WaitForNumGetWork(kExpectedNumGetWork);
|
|
|
| // All tasks should have run.
|
| - EXPECT_EQ(kNumSequencesPerTest, NumRunTasks());
|
| + EXPECT_EQ(kNumTasksPerTest, NumRunTasks());
|
|
|
| // If Sequences returned by GetWork() contain more than one Task, they aren't
|
| // empty after the worker thread pops Tasks from them and thus should be
|
| @@ -223,8 +233,8 @@ TEST_P(TaskSchedulerWorkerThreadTest, ContinuousWork) {
|
| // Verify that when GetWork() alternates between returning a Sequence and
|
| // returning nullptr, all Tasks in the returned Sequences run successfully. The
|
| // test wakes up the SchedulerWorkerThread once for each Sequence.
|
| -TEST_P(TaskSchedulerWorkerThreadTest, IntermittentWork) {
|
| - for (size_t i = 0; i < kNumSequencesPerTest; ++i) {
|
| +TEST_P(TaskSchedulerWorkerThreadDelegateWorkTest, IntermittentWork) {
|
| + for (size_t i = 0; i < kNumTasksPerTest; ++i) {
|
| // Set GetWork() to return 1 Sequence before starting to return
|
| // nullptr.
|
| SetNumSequencesToCreate(1);
|
| @@ -253,12 +263,128 @@ TEST_P(TaskSchedulerWorkerThreadTest, IntermittentWork) {
|
| }
|
|
|
| INSTANTIATE_TEST_CASE_P(OneTaskPerSequence,
|
| - TaskSchedulerWorkerThreadTest,
|
| + TaskSchedulerWorkerThreadDelegateWorkTest,
|
| ::testing::Values(1));
|
| INSTANTIATE_TEST_CASE_P(TwoTasksPerSequence,
|
| - TaskSchedulerWorkerThreadTest,
|
| + TaskSchedulerWorkerThreadDelegateWorkTest,
|
| ::testing::Values(2));
|
|
|
| +class TaskSchedulerWorkerThreadSingleThreadedWorkTest
|
| + : public testing::Test,
|
| + public SchedulerWorkerThread::Delegate {
|
| + protected:
|
| + TaskSchedulerWorkerThreadSingleThreadedWorkTest()
|
| + : delayed_task_manager_(Bind(&DoNothing)),
|
| + num_run_tasks_cv_(lock_.CreateConditionVariable()) {}
|
| +
|
| + void SetUp() override {
|
| + worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread(
|
| + ThreadPriority::NORMAL, this, &task_tracker_, &delayed_task_manager_,
|
| + &dummy_priority_queue_);
|
| + ASSERT_TRUE(worker_thread_);
|
| + }
|
| +
|
| + void TearDown() override { worker_thread_->JoinForTesting(); }
|
| +
|
| + void PostTestTask(scoped_refptr<TaskRunner> task_runner) {
|
| + size_t task_index;
|
| + {
|
| + AutoSchedulerLock auto_lock(lock_);
|
| + task_index = num_posted_tasks_++;
|
| + }
|
| + task_runner->PostTask(
|
| + FROM_HERE,
|
| + Bind(&TaskSchedulerWorkerThreadSingleThreadedWorkTest::RunTaskCallback,
|
| + Unretained(this), task_index, task_runner));
|
| + }
|
| +
|
| + void WaitForAllTasksToRun() {
|
| + AutoSchedulerLock auto_lock(lock_);
|
| + while (num_run_tasks_ < num_posted_tasks_)
|
| + num_run_tasks_cv_->Wait();
|
| + }
|
| +
|
| + std::unique_ptr<SchedulerWorkerThread> worker_thread_;
|
| +
|
| + private:
|
| + // SchedulerWorkerThread::Delegate:
|
| + void OnMainEntry() override {}
|
| +
|
| + scoped_refptr<Sequence> GetWork(
|
| + SchedulerWorkerThread* worker_thread,
|
| + PriorityQueue* alternate_priority_queue,
|
| + bool* alternate_priority_queue_used) override {
|
| + EXPECT_EQ(worker_thread_.get(), worker_thread);
|
| +
|
| + // Return a Sequence from |alternate_priority_queue| or nullptr if it is
|
| + // empty.
|
| + auto transaction = alternate_priority_queue->BeginTransaction();
|
| + auto sequence = transaction->Peek().sequence;
|
| + if (!sequence)
|
| + return nullptr;
|
| + *alternate_priority_queue_used = true;
|
| + transaction->Pop();
|
| + return sequence;
|
| + }
|
| +
|
| + void EnqueueSequence(scoped_refptr<Sequence> sequence) override {
|
| + ADD_FAILURE() << "EnqueueSequence shouldn't be called in a test that only "
|
| + "posts single-threaded Tasks.";
|
| + }
|
| +
|
| + void RunTaskCallback(size_t index, scoped_refptr<TaskRunner> task_runner) {
|
| + AutoSchedulerLock auto_lock(lock_);
|
| +
|
| + EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread());
|
| +
|
| + // Verify that tasks run in posting order.
|
| + EXPECT_EQ(num_run_tasks_, index);
|
| +
|
| + // Verify that we don't run more tasks than posted.
|
| + ++num_run_tasks_;
|
| + EXPECT_LE(num_run_tasks_, num_posted_tasks_);
|
| +
|
| + num_run_tasks_cv_->Signal();
|
| + }
|
| +
|
| + TaskTracker task_tracker_;
|
| + DelayedTaskManager delayed_task_manager_;
|
| + PriorityQueue dummy_priority_queue_;
|
| +
|
| + // Synchronizes access to all members below.
|
| + mutable SchedulerLock lock_;
|
| +
|
| + // Number of tasks posted by PostTestTask().
|
| + size_t num_posted_tasks_ = 0;
|
| +
|
| + // Number of times that RunTaskCallback() has been called.
|
| + size_t num_run_tasks_ = 0;
|
| +
|
| + // Condition variable signaled when |num_run_tasks_| is incremented.
|
| + std::unique_ptr<ConditionVariable> num_run_tasks_cv_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadSingleThreadedWorkTest);
|
| +};
|
| +
|
| +TEST_F(TaskSchedulerWorkerThreadSingleThreadedWorkTest, ContinuousWork) {
|
| + auto task_runner = worker_thread_->CreateTaskRunnerWithTraits(TaskTraits());
|
| + EXPECT_FALSE(task_runner->RunsTasksOnCurrentThread());
|
| +
|
| + for (size_t i = 0; i < kNumTasksPerTest; ++i)
|
| + PostTestTask(task_runner);
|
| + WaitForAllTasksToRun();
|
| +}
|
| +
|
| +TEST_F(TaskSchedulerWorkerThreadSingleThreadedWorkTest, IntermittentWork) {
|
| + auto task_runner = worker_thread_->CreateTaskRunnerWithTraits(TaskTraits());
|
| + EXPECT_FALSE(task_runner->RunsTasksOnCurrentThread());
|
| +
|
| + for (size_t i = 0; i < kNumTasksPerTest; ++i) {
|
| + PostTestTask(task_runner);
|
| + WaitForAllTasksToRun();
|
| + }
|
| +}
|
| +
|
| } // namespace
|
| } // namespace internal
|
| } // namespace base
|
|
|