summaryrefslogtreecommitdiffstats
path: root/chromium/base/task/thread_pool/job_task_source_unittest.cc
diff options
context:
space:
mode:
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.cc119
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