// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/task/thread_pool/sequence.h"

#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/test/gtest_util.h"
#include "base/time/time.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace base {
namespace internal {

namespace {

class MockTask {
 public:
  MOCK_METHOD0(Run, void());
};

Task CreateTask(MockTask* mock_task, TimeTicks now = TimeTicks::Now()) {
  return Task(FROM_HERE, BindOnce(&MockTask::Run, Unretained(mock_task)), now,
              TimeDelta());
}

Task CreateDelayedTask(MockTask* mock_task,
                       TimeDelta delay,
                       TimeTicks now = TimeTicks::Now()) {
  return Task(FROM_HERE, BindOnce(&MockTask::Run, Unretained(mock_task)), now,
              delay);
}

void ExpectMockTask(MockTask* mock_task, Task* task) {
  EXPECT_CALL(*mock_task, Run());
  std::move(task->task).Run();
  testing::Mock::VerifyAndClear(mock_task);
}

}  // namespace

TEST(ThreadPoolSequenceTest, PushTakeRemove) {
  testing::StrictMock<MockTask> mock_task_a;
  testing::StrictMock<MockTask> mock_task_b;
  testing::StrictMock<MockTask> mock_task_c;
  testing::StrictMock<MockTask> mock_task_d;
  testing::StrictMock<MockTask> mock_task_e;

  scoped_refptr<Sequence> sequence =
      MakeRefCounted<Sequence>(TaskTraits(TaskPriority::BEST_EFFORT), nullptr,
                               TaskSourceExecutionMode::kParallel);
  Sequence::Transaction sequence_transaction(sequence->BeginTransaction());

  // Push task A in the sequence. PushImmediateTask() should return true since
  // it's the first task.
  EXPECT_TRUE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(CreateTask(&mock_task_a));

  // Push task B, C and D in the sequence. PushImmediateTask() should return
  // false since there is already a task in a sequence.
  EXPECT_FALSE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(CreateTask(&mock_task_b));
  EXPECT_FALSE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(CreateTask(&mock_task_c));
  EXPECT_FALSE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(CreateTask(&mock_task_d));

  // Take the task in front of the sequence. It should be task A.
  auto registered_task_source =
      RegisteredTaskSource::CreateForTesting(sequence);
  registered_task_source.WillRunTask();
  absl::optional<Task> task =
      registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_a, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Task B should now be in front.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));
  EXPECT_TRUE(registered_task_source.WillReEnqueue(TimeTicks::Now(),
                                                   &sequence_transaction));

  registered_task_source.WillRunTask();
  EXPECT_TRUE(sequence->has_worker_for_testing());
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_b, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Task C should now be in front.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));
  EXPECT_TRUE(registered_task_source.WillReEnqueue(TimeTicks::Now(),
                                                   &sequence_transaction));

  registered_task_source.WillRunTask();
  EXPECT_TRUE(sequence->has_worker_for_testing());
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_c, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));
  EXPECT_TRUE(registered_task_source.WillReEnqueue(TimeTicks::Now(),
                                                   &sequence_transaction));
  EXPECT_FALSE(sequence->has_worker_for_testing());

  // Push task E in the sequence.
  EXPECT_FALSE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(CreateTask(&mock_task_e));

  // Task D should be in front.
  registered_task_source.WillRunTask();
  EXPECT_TRUE(sequence->has_worker_for_testing());
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_d, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Task E should now be in front.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));
  EXPECT_TRUE(registered_task_source.WillReEnqueue(TimeTicks::Now(),
                                                   &sequence_transaction));
  registered_task_source.WillRunTask();
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_e, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. The sequence should now be empty.
  EXPECT_FALSE(registered_task_source.DidProcessTask(&sequence_transaction));

  // Sequence is empty and it won't be returned to the priority queue.
  EXPECT_FALSE(sequence->has_worker_for_testing());
  EXPECT_FALSE(sequence->is_immediate_for_testing());
  EXPECT_TRUE(sequence->IsEmptyForTesting());
}

// Verifies the sort key of a BEST_EFFORT sequence that contains one task.
TEST(ThreadPoolSequenceTest, GetSortKeyBestEffort) {
  // Create a BEST_EFFORT sequence with a task.
  Task best_effort_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
  scoped_refptr<Sequence> best_effort_sequence =
      MakeRefCounted<Sequence>(TaskTraits(TaskPriority::BEST_EFFORT), nullptr,
                               TaskSourceExecutionMode::kParallel);
  Sequence::Transaction best_effort_sequence_transaction(
      best_effort_sequence->BeginTransaction());
  best_effort_sequence_transaction.WillPushImmediateTask();
  best_effort_sequence_transaction.PushImmediateTask(
      std::move(best_effort_task));

  // Get the sort key.
  const TaskSourceSortKey best_effort_sort_key =
      best_effort_sequence->GetSortKey();

  // Take the task from the sequence, so that its sequenced time is available
  // for the check below.
  auto best_effort_registered_task_source =
      RegisteredTaskSource::CreateForTesting(best_effort_sequence);
  best_effort_registered_task_source.WillRunTask();
  auto take_best_effort_task = best_effort_registered_task_source.TakeTask(
      &best_effort_sequence_transaction);

  // Verify the sort key.
  EXPECT_EQ(TaskPriority::BEST_EFFORT, best_effort_sort_key.priority());
  EXPECT_EQ(take_best_effort_task.queue_time,
            best_effort_sort_key.ready_time());

  // DidProcessTask for correctness.
  best_effort_registered_task_source.DidProcessTask(
      &best_effort_sequence_transaction);
}

// Same as ThreadPoolSequenceTest.GetSortKeyBestEffort, but with a
// USER_VISIBLE sequence.
TEST(ThreadPoolSequenceTest, GetSortKeyForeground) {
  // Create a USER_VISIBLE sequence with a task.
  Task foreground_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
  scoped_refptr<Sequence> foreground_sequence =
      MakeRefCounted<Sequence>(TaskTraits(TaskPriority::USER_VISIBLE), nullptr,
                               TaskSourceExecutionMode::kParallel);
  Sequence::Transaction foreground_sequence_transaction(
      foreground_sequence->BeginTransaction());
  foreground_sequence_transaction.WillPushImmediateTask();
  foreground_sequence_transaction.PushImmediateTask(std::move(foreground_task));

  // Get the sort key.
  const TaskSourceSortKey foreground_sort_key =
      foreground_sequence->GetSortKey();

  // Take the task from the sequence, so that its sequenced time is available
  // for the check below.
  auto foreground_registered_task_source =
      RegisteredTaskSource::CreateForTesting(foreground_sequence);
  foreground_registered_task_source.WillRunTask();
  auto take_foreground_task = foreground_registered_task_source.TakeTask(
      &foreground_sequence_transaction);

  // Verify the sort key.
  EXPECT_EQ(TaskPriority::USER_VISIBLE, foreground_sort_key.priority());
  EXPECT_EQ(take_foreground_task.queue_time, foreground_sort_key.ready_time());

  // DidProcessTask for correctness.
  foreground_registered_task_source.DidProcessTask(
      &foreground_sequence_transaction);
}

// Verify that a DCHECK fires if DidProcessTask() is called on a sequence which
// didn't return a Task.
TEST(ThreadPoolSequenceTest, DidProcessTaskWithoutWillRunTask) {
  scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(
      TaskTraits(), nullptr, TaskSourceExecutionMode::kParallel);
  Sequence::Transaction sequence_transaction(sequence->BeginTransaction());
  EXPECT_TRUE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(
      Task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()));

  auto registered_task_source =
      RegisteredTaskSource::CreateForTesting(sequence);
  EXPECT_DCHECK_DEATH({
    registered_task_source.DidProcessTask(&sequence_transaction);
  });
}

// Verify that a DCHECK fires if TakeTask() is called on a sequence whose front
// slot is empty.
TEST(ThreadPoolSequenceTest, TakeEmptyFrontSlot) {
  scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(
      TaskTraits(), nullptr, TaskSourceExecutionMode::kParallel);
  Sequence::Transaction sequence_transaction(sequence->BeginTransaction());
  sequence_transaction.WillPushImmediateTask();
  sequence_transaction.PushImmediateTask(
      Task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()));

  auto registered_task_source =
      RegisteredTaskSource::CreateForTesting(sequence);
  {
    registered_task_source.WillRunTask();
    IgnoreResult(registered_task_source.TakeTask(&sequence_transaction));
    registered_task_source.DidProcessTask(&sequence_transaction);
  }
  EXPECT_DCHECK_DEATH({
    registered_task_source.WillRunTask();
    auto task = registered_task_source.TakeTask(&sequence_transaction);
  });
}

// Verify that a DCHECK fires if TakeTask() is called on an empty sequence.
TEST(ThreadPoolSequenceTest, TakeEmptySequence) {
  scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(
      TaskTraits(), nullptr, TaskSourceExecutionMode::kParallel);
  auto registered_task_source =
      RegisteredTaskSource::CreateForTesting(sequence);
  EXPECT_DCHECK_DEATH({
    registered_task_source.WillRunTask();
    auto task = registered_task_source.TakeTask();
  });
}

// Verify that the sequence stays in worker when new tasks are being pushed
// while it's being processed.
TEST(ThreadPoolSequenceTest, SequenceHasWorker) {
  testing::StrictMock<MockTask> mock_task_a;
  testing::StrictMock<MockTask> mock_task_b;

  scoped_refptr<Sequence> sequence =
      MakeRefCounted<Sequence>(TaskTraits(TaskPriority::BEST_EFFORT), nullptr,
                               TaskSourceExecutionMode::kParallel);

  Sequence::Transaction sequence_transaction(sequence->BeginTransaction());

  // Push task A in the sequence. WillPushImmediateTask() should return
  // true since sequence is empty.
  EXPECT_TRUE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(CreateTask(&mock_task_a));

  auto registered_task_source =
      RegisteredTaskSource::CreateForTesting(sequence);

  registered_task_source.WillRunTask();

  // WillRunTask indicates that a worker has called GetWork() and is ready to
  // run a task.
  EXPECT_TRUE(sequence->has_worker_for_testing());

  // The next task we get when we call Sequence::TakeTask should be Task A.
  absl::optional<Task> task_a =
      registered_task_source.TakeTask(&sequence_transaction);

  // Push task B into the sequence. WillPushImmediateTask() should return false.
  EXPECT_FALSE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(CreateTask(&mock_task_b));

  // Sequence is still being processed by a worker so pushing a new task
  // shouldn't change its location. We should expect it to still be in worker.
  EXPECT_TRUE(sequence->has_worker_for_testing());

  // Remove the empty slot. Sequence still has task B. This should return true.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));
  // Sequence can run immediately.
  EXPECT_TRUE(registered_task_source.WillReEnqueue(TimeTicks::Now(),
                                                   &sequence_transaction));

  // Sequence is not empty so it will be returned to the priority queue.
  EXPECT_FALSE(sequence->has_worker_for_testing());

  registered_task_source.WillRunTask();

  // The next task we get when we call Sequence::TakeTask should be Task B.
  absl::optional<Task> task_b =
      registered_task_source.TakeTask(&sequence_transaction);

  // Remove the empty slot. Sequence is be empty. This should return false.
  EXPECT_FALSE(registered_task_source.DidProcessTask(&sequence_transaction));

  // Sequence is empty and it won't be returned to the priority queue.
  EXPECT_FALSE(sequence->has_worker_for_testing());
  EXPECT_FALSE(sequence->is_immediate_for_testing());
  EXPECT_TRUE(sequence->IsEmptyForTesting());
}

// Verify that the sequence handle delayed tasks.
TEST(ThreadPoolSequenceTest, PushTakeRemoveDelayedTasks) {
  TimeTicks now = TimeTicks::Now();

  testing::StrictMock<MockTask> mock_task_a;
  testing::StrictMock<MockTask> mock_task_b;
  testing::StrictMock<MockTask> mock_task_c;
  testing::StrictMock<MockTask> mock_task_d;

  scoped_refptr<Sequence> sequence =
      MakeRefCounted<Sequence>(TaskTraits(TaskPriority::BEST_EFFORT), nullptr,
                               TaskSourceExecutionMode::kParallel);

  Sequence::Transaction sequence_transaction(sequence->BeginTransaction());

  // Push task A in the sequence.
  auto delayed_task_a = CreateDelayedTask(&mock_task_a, Milliseconds(20), now);
  // PushDelayedTask(delayed_task_a, now) should return true since sequence is
  // empty.
  EXPECT_TRUE(sequence_transaction.PushDelayedTask(std::move(delayed_task_a)));

  // Push task B into the sequence.
  auto delayed_task_b = CreateDelayedTask(&mock_task_b, Milliseconds(10), now);
  // PushDelayedTask(...) should return true since task b runtime is earlier
  // than task a's.
  EXPECT_TRUE(sequence_transaction.PushDelayedTask(std::move(delayed_task_b)));

  // Sequence doesn't have immediate tasks.
  EXPECT_FALSE(sequence->is_immediate_for_testing());

  // Time advances by 15s.
  now += Milliseconds(15);

  // Set sequence to ready
  EXPECT_TRUE(sequence->OnBecomeReady());

  // Sequence is about to be run.
  EXPECT_TRUE(sequence->is_immediate_for_testing());

  auto registered_task_source =
      RegisteredTaskSource::CreateForTesting(sequence);
  registered_task_source.WillRunTask();

  // Take the task in front of the sequence. It should be task B.
  absl::optional<Task> task =
      registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_b, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Task A should now be in front. Sequence is not empty
  // so this should return true.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));

  // Task A is still not ready so this should return false.
  EXPECT_FALSE(
      registered_task_source.WillReEnqueue(now, &sequence_transaction));
  EXPECT_FALSE(sequence->is_immediate_for_testing());

  // Push task C into the sequence.
  auto delayed_task_c = CreateDelayedTask(&mock_task_c, Milliseconds(1), now);
  // PushDelayedTask(...) should return true since task c runtime is
  // earlier than task a's.
  EXPECT_TRUE(sequence_transaction.PushDelayedTask(std::move(delayed_task_c)));

  // Push task D into the sequence.
  auto delayed_task_d = CreateDelayedTask(&mock_task_d, Milliseconds(1), now);
  // PushDelayedTask(...) should return false since task d queue time
  // is later than task c's.
  EXPECT_FALSE(sequence_transaction.PushDelayedTask(std::move(delayed_task_d)));

  // Time advances by 2ms.
  now += Milliseconds(2);
  // Set sequence to ready
  EXPECT_TRUE(registered_task_source->OnBecomeReady());

  registered_task_source.WillRunTask();

  // This should return task C
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_c, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Task D should now be in front.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));

  // Task D is ready so this should return true.
  EXPECT_TRUE(registered_task_source.WillReEnqueue(now, &sequence_transaction));
  EXPECT_TRUE(sequence->is_immediate_for_testing());

  registered_task_source.WillRunTask();

  // This should return task D
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_d, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Task A should now be in front.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));

  // Time advances by 10ms.
  now += Milliseconds(10);

  // Task A is ready so this should return true.
  EXPECT_TRUE(registered_task_source.WillReEnqueue(now, &sequence_transaction));
  EXPECT_TRUE(sequence->is_immediate_for_testing());

  registered_task_source.WillRunTask();

  // This should return task A since it's ripe
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_a, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Sequence should be empty now.
  EXPECT_FALSE(registered_task_source.DidProcessTask(&sequence_transaction));

  // Sequence is empty and it won't be returned to the priority queue.
  EXPECT_FALSE(sequence->has_worker_for_testing());
  EXPECT_FALSE(sequence->is_immediate_for_testing());
  EXPECT_TRUE(sequence->IsEmptyForTesting());
}

// Verify that the sequence handle delayed and immediate tasks.
TEST(ThreadPoolSequenceTest, PushTakeRemoveMixedTasks) {
  TimeTicks now = TimeTicks::Now();

  testing::StrictMock<MockTask> mock_task_a;
  testing::StrictMock<MockTask> mock_task_b;
  testing::StrictMock<MockTask> mock_task_c;
  testing::StrictMock<MockTask> mock_task_d;

  scoped_refptr<Sequence> sequence =
      MakeRefCounted<Sequence>(TaskTraits(TaskPriority::BEST_EFFORT), nullptr,
                               TaskSourceExecutionMode::kParallel);

  Sequence::Transaction sequence_transaction(sequence->BeginTransaction());

  // Starting with a delayed task
  // Push task A in the sequence.
  auto delayed_task_a = CreateDelayedTask(&mock_task_a, Milliseconds(20), now);
  // PushDelayedTask(delayed_task_a) should return
  // true since sequence is empty.
  EXPECT_TRUE(sequence_transaction.PushDelayedTask(std::move(delayed_task_a)));
  // Sequence doesn't have immediate tasks.
  EXPECT_FALSE(sequence->is_immediate_for_testing());

  // Push an immediate task while a delayed task is already sitting in the
  // delayed queue. This should prompt a move to the immediate queue.
  // Push task B in the sequence.
  auto task_b = CreateTask(&mock_task_b, now);
  // WillPushImmediateTask() should return true since sequence is in delayed
  // queue.
  EXPECT_TRUE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(std::move(task_b));
  // Sequence now has an immediate tasks.
  EXPECT_TRUE(sequence->is_immediate_for_testing());

  auto registered_task_source =
      RegisteredTaskSource::CreateForTesting(sequence);

  // Prepare to run a task.
  registered_task_source.WillRunTask();
  EXPECT_TRUE(sequence->has_worker_for_testing());

  // Take the task in front of the sequence. It should be task B.
  absl::optional<Task> task =
      registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_b, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Task A should now be in front. Sequence is not empty
  // so this should return true.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));

  // Time advances by 21ms.
  now += Milliseconds(21);

  // Task A is ready so this should return true.
  EXPECT_TRUE(registered_task_source.WillReEnqueue(now, &sequence_transaction));
  EXPECT_TRUE(sequence->is_immediate_for_testing());

  registered_task_source.WillRunTask();
  EXPECT_TRUE(sequence->has_worker_for_testing());

  // Push a delayed task while sequence is being run by a worker. Push task C in
  // the sequence.
  auto delayed_task_c = CreateDelayedTask(&mock_task_c, Milliseconds(5), now);
  // PushDelayedTask(delayed_task_c) should return false since sequence is in
  // worker.
  EXPECT_FALSE(sequence_transaction.PushDelayedTask(std::move(delayed_task_c)));
  // Sequence is still in worker.
  EXPECT_TRUE(sequence->has_worker_for_testing());

  // This should return task A
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_a, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Task C should now be in front.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));

  // Time advances by 2ms.
  now += Milliseconds(2);

  // Task C is not ready so this should return false.
  EXPECT_FALSE(
      registered_task_source.WillReEnqueue(now, &sequence_transaction));
  EXPECT_FALSE(sequence->is_immediate_for_testing());

  // Time advances by 4ms. Task C becomes ready.
  now += Milliseconds(4);

  // Set sequence to ready
  EXPECT_TRUE(registered_task_source->OnBecomeReady());
  EXPECT_TRUE(sequence->is_immediate_for_testing());

  // Push task D in the sequence while sequence is ready.
  auto task_d = CreateTask(&mock_task_d, now);
  // WillPushImmediateTask() should return false since sequence is already in
  // immediate queue.
  EXPECT_FALSE(sequence_transaction.WillPushImmediateTask());
  sequence_transaction.PushImmediateTask(std::move(task_d));
  EXPECT_TRUE(sequence->is_immediate_for_testing());

  registered_task_source.WillRunTask();
  EXPECT_TRUE(sequence->has_worker_for_testing());

  // This should return task C since was ready before Task D was posted.
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_c, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Task D should now be in front.
  EXPECT_TRUE(registered_task_source.DidProcessTask(&sequence_transaction));

  // Task D should be run so this should return true.
  EXPECT_TRUE(registered_task_source.WillReEnqueue(now, &sequence_transaction));
  EXPECT_TRUE(sequence->is_immediate_for_testing());

  registered_task_source.WillRunTask();

  // This should return task D since it's immediate.
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_d, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Remove the empty slot. Sequence should be empty.
  EXPECT_FALSE(registered_task_source.DidProcessTask(&sequence_transaction));
  EXPECT_FALSE(sequence->has_worker_for_testing());
  EXPECT_FALSE(sequence->is_immediate_for_testing());
}

// Test that PushDelayedTask method is used only for delayed tasks
TEST(ThreadPoolSequenceTest, TestPushDelayedTaskMethodUsage) {
  testing::StrictMock<MockTask> mock_task_a;

  scoped_refptr<Sequence> sequence =
      MakeRefCounted<Sequence>(TaskTraits(TaskPriority::BEST_EFFORT), nullptr,
                               TaskSourceExecutionMode::kParallel);

  Sequence::Transaction sequence_transaction(sequence->BeginTransaction());

  // Push task B in the sequence.
  auto task_a = CreateTask(&mock_task_a);
  EXPECT_DCHECK_DEATH(
      { sequence_transaction.PushDelayedTask(std::move(task_a)); });
}

// Verifies the delayed sort key of a sequence that contains one delayed task.
// We will also test for the case where we push a delayed task with a runtime
// earlier than the queue_time of an already pushed immediate task.
TEST(ThreadPoolSequenceTest, GetDelayedSortKeyMixedtasks) {
  TimeTicks now = TimeTicks::Now();

  testing::StrictMock<MockTask> mock_task_a;
  testing::StrictMock<MockTask> mock_task_b;

  scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(
      TaskTraits(), nullptr, TaskSourceExecutionMode::kParallel);
  Sequence::Transaction sequence_transaction(sequence->BeginTransaction());

  // Create a first delayed task.
  EXPECT_TRUE(sequence_transaction.PushDelayedTask(
      CreateDelayedTask(&mock_task_a, Milliseconds(10), now)));

  // Get the delayed sort key (first time).
  const TimeTicks sort_key_1 = sequence->GetDelayedSortKey();

  // Time advances by 11ms.
  now += Milliseconds(11);

  // Push an immediate task that should run after the delayed task.
  auto immediate_task = CreateTask(&mock_task_b, now);
  sequence_transaction.WillPushImmediateTask();
  sequence_transaction.PushImmediateTask(std::move(immediate_task));

  // Get the delayed sort key (second time).
  const TimeTicks sort_key_2 = sequence->GetDelayedSortKey();

  // Take the delayed task from the sequence, so that its next delayed runtime
  // is available for the check below.
  auto registered_task_source =
      RegisteredTaskSource::CreateForTesting(sequence);
  registered_task_source.WillRunTask();
  absl::optional<Task> take_delayed_task =
      registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_a, &take_delayed_task.value());
  EXPECT_FALSE(take_delayed_task->queue_time.is_null());

  // For correctness.
  registered_task_source.DidProcessTask(&sequence_transaction);
  registered_task_source.WillReEnqueue(now, &sequence_transaction);

  // Verify that sort_key_1 is equal to the delayed task latest run time.
  EXPECT_EQ(take_delayed_task->latest_delayed_run_time(), sort_key_1);

  // Verify that the sort key didn't change after pushing the immediate task.
  EXPECT_EQ(sort_key_1, sort_key_2);

  // Get the delayed sort key (third time).
  const TimeTicks sort_key_3 = sequence->GetDelayedSortKey();

  // Take the immediate task from the sequence, so that its queue time
  // is available for the check below.
  registered_task_source.WillRunTask();
  absl::optional<Task> take_immediate_task =
      registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_b, &take_immediate_task.value());
  EXPECT_FALSE(take_immediate_task->queue_time.is_null());

  // Verify that sort_key_1 is equal to the immediate task queue time.
  EXPECT_EQ(take_immediate_task->queue_time, sort_key_3);

  // DidProcessTask for correctness.
  registered_task_source.DidProcessTask(&sequence_transaction);
}

// Test for the case where we push a delayed task to run earlier than the
// already posted delayed task.
TEST(ThreadPoolSequenceTest, GetDelayedSortKeyDelayedtasks) {
  TimeTicks now = TimeTicks::Now();

  testing::StrictMock<MockTask> mock_task_a;
  testing::StrictMock<MockTask> mock_task_b;

  scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(
      TaskTraits(), nullptr, TaskSourceExecutionMode::kParallel);
  Sequence::Transaction sequence_transaction(sequence->BeginTransaction());

  // Create a first delayed task.
  sequence_transaction.PushDelayedTask(
      CreateDelayedTask(&mock_task_a, Milliseconds(15), now));

  // Get the delayed sort key (first time).
  const TimeTicks sort_key_1 = sequence->GetDelayedSortKey();

  // Create a first delayed task.
  sequence_transaction.PushDelayedTask(
      CreateDelayedTask(&mock_task_b, Milliseconds(10), now));

  // Get the delayed sort key (second time).
  const TimeTicks sort_key_2 = sequence->GetDelayedSortKey();

  // Time advances by 11ms
  now += Milliseconds(11);

  sequence->OnBecomeReady();
  auto registered_task_source =
      RegisteredTaskSource::CreateForTesting(sequence);
  registered_task_source.WillRunTask();
  absl::optional<Task> task =
      registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_b, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Verify that sort_key_2 is equal to the last posted task latest delayed run
  // time.
  EXPECT_EQ(task->latest_delayed_run_time(), sort_key_2);

  // Time advances by 5ms
  now += Milliseconds(5);

  // For correctness.
  registered_task_source.DidProcessTask(&sequence_transaction);
  registered_task_source.WillReEnqueue(now, &sequence_transaction);

  registered_task_source.WillRunTask();
  task = registered_task_source.TakeTask(&sequence_transaction);
  ExpectMockTask(&mock_task_a, &task.value());
  EXPECT_FALSE(task->queue_time.is_null());

  // Verify that sort_key_1 is equal to the first posted task latest delayed run
  // time.
  EXPECT_EQ(task->latest_delayed_run_time(), sort_key_1);

  // DidProcessTask for correctness.
  registered_task_source.DidProcessTask(&sequence_transaction);
}

}  // namespace internal
}  // namespace base
