diff options
Diffstat (limited to 'chromium/base/task/thread_pool/job_task_source_unittest.cc')
-rw-r--r-- | chromium/base/task/thread_pool/job_task_source_unittest.cc | 119 |
1 files changed, 111 insertions, 8 deletions
diff --git a/chromium/base/task/thread_pool/job_task_source_unittest.cc b/chromium/base/task/thread_pool/job_task_source_unittest.cc index 789cf5ab7a0..413771f2235 100644 --- a/chromium/base/task/thread_pool/job_task_source_unittest.cc +++ b/chromium/base/task/thread_pool/job_task_source_unittest.cc @@ -29,6 +29,8 @@ class MockPooledTaskRunnerDelegate : public PooledTaskRunnerDelegate { MOCK_CONST_METHOD1(ShouldYield, bool(const TaskSource* task_source)); MOCK_METHOD1(EnqueueJobTaskSource, bool(scoped_refptr<JobTaskSource> task_source)); + MOCK_METHOD1(RemoveJobTaskSource, + void(scoped_refptr<JobTaskSource> task_source)); MOCK_CONST_METHOD1(IsRunningPoolWithTraits, bool(const TaskTraits& traits)); MOCK_METHOD2(UpdatePriority, void(scoped_refptr<TaskSource> task_source, @@ -108,13 +110,17 @@ TEST_F(ThreadPoolJobTaskSourceTest, Clear) { EXPECT_EQ(registered_task_source_d.WillRunTask(), TaskSource::RunStatus::kAllowedNotSaturated); + EXPECT_FALSE(task_source->ShouldYield()); + { EXPECT_EQ(1U, task_source->GetRemainingConcurrency()); auto task = registered_task_source_c.Clear(); std::move(task->task).Run(); + registered_task_source_c.DidProcessTask(); EXPECT_EQ(0U, task_source->GetRemainingConcurrency()); } // The task source shouldn't allow any further tasks after Clear. + EXPECT_TRUE(task_source->ShouldYield()); EXPECT_EQ(RegisteredTaskSource::CreateForTesting(task_source).WillRunTask(), TaskSource::RunStatus::kDisallowed); @@ -122,6 +128,7 @@ TEST_F(ThreadPoolJobTaskSourceTest, Clear) { { auto task = registered_task_source_d.Clear(); std::move(task->task).Run(); + registered_task_source_d.DidProcessTask(); EXPECT_EQ(0U, task_source->GetRemainingConcurrency()); } @@ -129,15 +136,53 @@ TEST_F(ThreadPoolJobTaskSourceTest, Clear) { std::move(task_a->task).Run(); registered_task_source_a.DidProcessTask(); - // A valid outstanding RunStatus can also take & run a task. + // A valid outstanding RunStatus can also take and run a task. { auto task = registered_task_source_b.TakeTask(); std::move(task->task).Run(); registered_task_source_b.DidProcessTask(); } - // Sanity check. +} + +// Verifies that a job task source doesn't return an "allowed" RunStatus after +// Cancel() is called. +TEST_F(ThreadPoolJobTaskSourceTest, Cancel) { + auto job_task = base::MakeRefCounted<test::MockJobTask>( + DoNothing(), /* num_tasks_to_run */ 3); + scoped_refptr<JobTaskSource> task_source = job_task->GetJobTaskSource( + FROM_HERE, {ThreadPool(), TaskPriority::BEST_EFFORT}, + &pooled_task_runner_delegate_); + + auto registered_task_source_a = + RegisteredTaskSource::CreateForTesting(task_source); + EXPECT_EQ(registered_task_source_a.WillRunTask(), + TaskSource::RunStatus::kAllowedNotSaturated); + auto task_a = registered_task_source_a.TakeTask(); + + auto registered_task_source_b = + RegisteredTaskSource::CreateForTesting(task_source); + EXPECT_EQ(registered_task_source_b.WillRunTask(), + TaskSource::RunStatus::kAllowedNotSaturated); + + EXPECT_FALSE(task_source->ShouldYield()); + + task_source->Cancel(); + EXPECT_TRUE(task_source->ShouldYield()); + + // The task source shouldn't allow any further tasks after Cancel. EXPECT_EQ(RegisteredTaskSource::CreateForTesting(task_source).WillRunTask(), TaskSource::RunStatus::kDisallowed); + + // A task that was already acquired can still run. + std::move(task_a->task).Run(); + registered_task_source_a.DidProcessTask(); + + // A RegisteredTaskSource that's ready can also take and run a task. + { + auto task = registered_task_source_b.TakeTask(); + std::move(task->task).Run(); + registered_task_source_b.DidProcessTask(); + } } // Verifies that multiple tasks can run in parallel up to |max_concurrency|. @@ -183,6 +228,68 @@ TEST_F(ThreadPoolJobTaskSourceTest, RunTasksInParallel) { EXPECT_FALSE(registered_task_source_c.DidProcessTask()); } +// Verifies the normal flow of running the join task until completion. +TEST_F(ThreadPoolJobTaskSourceTest, RunJoinTask) { + auto job_task = base::MakeRefCounted<test::MockJobTask>( + DoNothing(), /* num_tasks_to_run */ 2); + scoped_refptr<JobTaskSource> task_source = job_task->GetJobTaskSource( + FROM_HERE, ThreadPool(), &pooled_task_runner_delegate_); + + EXPECT_TRUE(task_source->WillJoin()); + // Intentionally run |worker_task| twice to make sure RunJoinTask() calls + // it again. This can happen in production if the joining thread spuriously + // return and needs to run again. + EXPECT_TRUE(task_source->RunJoinTask()); + EXPECT_FALSE(task_source->RunJoinTask()); +} + +// Verifies that WillJoin() doesn't allow a joining thread to contribute +// after Cancel() is called. +TEST_F(ThreadPoolJobTaskSourceTest, CancelJoinTask) { + auto job_task = base::MakeRefCounted<test::MockJobTask>( + DoNothing(), /* num_tasks_to_run */ 2); + scoped_refptr<JobTaskSource> task_source = job_task->GetJobTaskSource( + FROM_HERE, ThreadPool(), &pooled_task_runner_delegate_); + + task_source->Cancel(); + EXPECT_FALSE(task_source->WillJoin()); +} + +// Verifies that RunJoinTask() doesn't allow a joining thread to contribute +// after Cancel() is called. +TEST_F(ThreadPoolJobTaskSourceTest, JoinCancelTask) { + auto job_task = base::MakeRefCounted<test::MockJobTask>( + DoNothing(), /* num_tasks_to_run */ 2); + scoped_refptr<JobTaskSource> task_source = job_task->GetJobTaskSource( + FROM_HERE, ThreadPool(), &pooled_task_runner_delegate_); + + EXPECT_TRUE(task_source->WillJoin()); + task_source->Cancel(); + EXPECT_FALSE(task_source->RunJoinTask()); +} + +// Verifies that the join task can run in parallel with worker tasks up to +// |max_concurrency|. +TEST_F(ThreadPoolJobTaskSourceTest, RunJoinTaskInParallel) { + auto job_task = base::MakeRefCounted<test::MockJobTask>( + DoNothing(), /* num_tasks_to_run */ 2); + scoped_refptr<JobTaskSource> task_source = job_task->GetJobTaskSource( + FROM_HERE, ThreadPool(), &pooled_task_runner_delegate_); + + auto registered_task_source = + RegisteredTaskSource::CreateForTesting(task_source); + EXPECT_EQ(registered_task_source.WillRunTask(), + TaskSource::RunStatus::kAllowedNotSaturated); + auto worker_task = registered_task_source.TakeTask(); + + EXPECT_TRUE(task_source->WillJoin()); + + std::move(worker_task->task).Run(); + EXPECT_FALSE(registered_task_source.DidProcessTask()); + + EXPECT_FALSE(task_source->RunJoinTask()); +} + // Verifies that a call to NotifyConcurrencyIncrease() calls the delegate // and allows to run additional tasks. TEST_F(ThreadPoolJobTaskSourceTest, NotifyConcurrencyIncrease) { @@ -342,13 +449,9 @@ TEST_F(ThreadPoolJobTaskSourceTest, InvalidDidProcessTask) { auto registered_task_source = RegisteredTaskSource::CreateForTesting(task_source); - EXPECT_EQ(registered_task_source.WillRunTask(), - TaskSource::RunStatus::kAllowedSaturated); - // Can not be called before TakeTask(). - EXPECT_DCHECK_DEATH(registered_task_source.DidProcessTask()); - auto task = registered_task_source.TakeTask(); - registered_task_source.DidProcessTask(); + // Can not be called before WillRunTask(). + EXPECT_DCHECK_DEATH(registered_task_source.DidProcessTask()); } } // namespace internal |