blob: f0f0caaf37c3936363b697583c9e6aceeb056f54 [file] [log] [blame]
// Copyright 2015 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/sequence_manager/wake_up_queue.h"
#include <memory>
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_pump.h"
#include "base/message_loop/message_pump_type.h"
#include "base/task/sequence_manager/enqueue_order.h"
#include "base/task/sequence_manager/sequence_manager_impl.h"
#include "base/task/sequence_manager/task_queue_impl.h"
#include "base/test/mock_callback.h"
#include "base/test/simple_test_tick_clock.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
using testing::_;
using testing::AnyNumber;
using testing::Mock;
namespace base {
namespace sequence_manager {
namespace internal {
class TaskQueueImplForTest : public internal::TaskQueueImpl {
public:
TaskQueueImplForTest(internal::SequenceManagerImpl* sequence_manager,
WakeUpQueue* wake_up_queue,
const TaskQueue::Spec& spec)
: TaskQueueImpl(sequence_manager, wake_up_queue, spec) {}
~TaskQueueImplForTest() = default;
using TaskQueueImpl::SetNextWakeUp;
};
class MockWakeUpQueue : public WakeUpQueue {
public:
MockWakeUpQueue()
: WakeUpQueue(internal::AssociatedThreadId::CreateBound()) {}
MockWakeUpQueue(const MockWakeUpQueue&) = delete;
MockWakeUpQueue& operator=(const MockWakeUpQueue&) = delete;
~MockWakeUpQueue() override = default;
using WakeUpQueue::MoveReadyDelayedTasksToWorkQueues;
using WakeUpQueue::SetNextWakeUpForQueue;
using WakeUpQueue::UnregisterQueue;
void OnNextWakeUpChanged(LazyNow* lazy_now,
absl::optional<WakeUp> wake_up) override {
TimeTicks time = wake_up ? wake_up->time : TimeTicks::Max();
OnNextWakeUpChanged_TimeTicks(time);
}
const char* GetName() const override { return "Test"; }
void UnregisterQueue(internal::TaskQueueImpl* queue) override {
SetNextWakeUpForQueue(queue, nullptr, absl::nullopt);
}
internal::TaskQueueImpl* NextScheduledTaskQueue() const {
if (wake_up_queue_.empty())
return nullptr;
return wake_up_queue_.top().queue;
}
TimeTicks NextScheduledRunTime() const {
if (wake_up_queue_.empty())
return TimeTicks::Max();
return wake_up_queue_.top().wake_up.time;
}
MOCK_METHOD1(OnNextWakeUpChanged_TimeTicks, void(TimeTicks time));
};
class WakeUpQueueTest : public testing::Test {
public:
void SetUp() final {
// A null clock triggers some assertions.
tick_clock_.Advance(Milliseconds(1));
wake_up_queue_ = std::make_unique<MockWakeUpQueue>();
task_queue_ = std::make_unique<TaskQueueImplForTest>(
nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
}
void TearDown() final {
if (task_queue_)
task_queue_->UnregisterTaskQueue();
}
std::unique_ptr<MockWakeUpQueue> wake_up_queue_;
std::unique_ptr<TaskQueueImplForTest> task_queue_;
SimpleTestTickClock tick_clock_;
};
TEST_F(WakeUpQueueTest, ScheduleWakeUpForQueue) {
TimeTicks now = tick_clock_.NowTicks();
TimeDelta delay = Milliseconds(10);
TimeTicks delayed_runtime = now + delay;
EXPECT_TRUE(wake_up_queue_->empty());
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(delayed_runtime));
LazyNow lazy_now(now);
task_queue_->SetNextWakeUp(&lazy_now, WakeUp{delayed_runtime});
EXPECT_FALSE(wake_up_queue_->empty());
EXPECT_EQ(delayed_runtime, wake_up_queue_->NextScheduledRunTime());
EXPECT_EQ(task_queue_.get(), wake_up_queue_->NextScheduledTaskQueue());
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
.Times(AnyNumber());
}
TEST_F(WakeUpQueueTest, ScheduleWakeUpForQueueSupersedesPreviousWakeUp) {
TimeTicks now = tick_clock_.NowTicks();
TimeDelta delay1 = Milliseconds(10);
TimeDelta delay2 = Milliseconds(100);
TimeTicks delayed_runtime1 = now + delay1;
TimeTicks delayed_runtime2 = now + delay2;
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(delayed_runtime1));
LazyNow lazy_now(now);
task_queue_->SetNextWakeUp(&lazy_now, WakeUp{delayed_runtime1});
EXPECT_EQ(delayed_runtime1, wake_up_queue_->NextScheduledRunTime());
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
// Now schedule a later wake_up, which should replace the previously
// requested one.
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(delayed_runtime2));
task_queue_->SetNextWakeUp(&lazy_now, WakeUp{delayed_runtime2});
EXPECT_EQ(delayed_runtime2, wake_up_queue_->NextScheduledRunTime());
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
.Times(AnyNumber());
}
TEST_F(
WakeUpQueueTest,
ScheduleFlexibleNoSoonerWakeUpForQueueSupersedesPreviousWakeUpWithLeeway) {
TimeTicks now = tick_clock_.NowTicks();
TimeDelta delay1 = Milliseconds(10);
TimeDelta delay2 = Milliseconds(15);
TimeTicks delayed_runtime1 = now + delay1;
TimeTicks delayed_runtime2 = now + delay2;
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(delayed_runtime1));
LazyNow lazy_now(now);
task_queue_->SetNextWakeUp(
&lazy_now,
WakeUp{delayed_runtime1, Milliseconds(10), WakeUpResolution::kLow,
subtle::DelayPolicy::kFlexibleNoSooner});
EXPECT_EQ((WakeUp{delayed_runtime1, Milliseconds(10), WakeUpResolution::kLow,
subtle::DelayPolicy::kFlexibleNoSooner}),
wake_up_queue_->GetNextDelayedWakeUp());
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
// Now schedule a later wake_up, which should replace the previously
// requested one.
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(delayed_runtime2));
task_queue_->SetNextWakeUp(
&lazy_now, WakeUp{delayed_runtime2, TimeDelta(), WakeUpResolution::kLow,
subtle::DelayPolicy::kPrecise});
EXPECT_EQ((WakeUp{delayed_runtime2, TimeDelta(), WakeUpResolution::kLow,
subtle::DelayPolicy::kPrecise}),
wake_up_queue_->GetNextDelayedWakeUp());
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
.Times(AnyNumber());
}
TEST_F(WakeUpQueueTest,
ScheduleFlexiblePreferEarlyWakeUpForQueueSupersedesPreviousWakeUp) {
TimeTicks now = tick_clock_.NowTicks();
TimeDelta delay1 = Milliseconds(10);
TimeDelta delay2 = Milliseconds(15);
TimeTicks delayed_runtime1 = now + delay1;
TimeTicks delayed_runtime2 = now + delay2;
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(delayed_runtime1));
LazyNow lazy_now(now);
task_queue_->SetNextWakeUp(
&lazy_now, WakeUp{delayed_runtime1, TimeDelta(), WakeUpResolution::kLow,
subtle::DelayPolicy::kPrecise});
EXPECT_EQ((WakeUp{delayed_runtime1, TimeDelta(), WakeUpResolution::kLow,
subtle::DelayPolicy::kPrecise}),
wake_up_queue_->GetNextDelayedWakeUp());
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
// Now schedule a later wake_up, which should replace the previously
// requested one.
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(delayed_runtime2));
task_queue_->SetNextWakeUp(
&lazy_now,
WakeUp{delayed_runtime2, Milliseconds(10), WakeUpResolution::kLow,
subtle::DelayPolicy::kFlexiblePreferEarly});
EXPECT_EQ((WakeUp{delayed_runtime2, Milliseconds(10), WakeUpResolution::kLow,
subtle::DelayPolicy::kFlexiblePreferEarly}),
wake_up_queue_->GetNextDelayedWakeUp());
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
.Times(AnyNumber());
}
TEST_F(WakeUpQueueTest, SetNextDelayedDoWork_OnlyCalledForEarlierTasks) {
std::unique_ptr<TaskQueueImplForTest> task_queue2 =
std::make_unique<TaskQueueImplForTest>(
nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
std::unique_ptr<TaskQueueImplForTest> task_queue3 =
std::make_unique<TaskQueueImplForTest>(
nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
std::unique_ptr<TaskQueueImplForTest> task_queue4 =
std::make_unique<TaskQueueImplForTest>(
nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
TimeDelta delay1 = Milliseconds(10);
TimeDelta delay2 = Milliseconds(20);
TimeDelta delay3 = Milliseconds(30);
TimeDelta delay4 = Milliseconds(1);
// SetNextDelayedDoWork should always be called if there are no other
// wake-ups.
TimeTicks now = tick_clock_.NowTicks();
LazyNow lazy_now(now);
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(now + delay1));
task_queue_->SetNextWakeUp(&lazy_now, WakeUp{now + delay1});
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
// SetNextDelayedDoWork should not be called when scheduling later tasks.
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_)).Times(0);
task_queue2->SetNextWakeUp(&lazy_now, WakeUp{now + delay2});
task_queue3->SetNextWakeUp(&lazy_now, WakeUp{now + delay3});
// SetNextDelayedDoWork should be called when scheduling earlier tasks.
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(now + delay4));
task_queue4->SetNextWakeUp(&lazy_now, WakeUp{now + delay4});
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_)).Times(2);
task_queue2->UnregisterTaskQueue();
task_queue3->UnregisterTaskQueue();
task_queue4->UnregisterTaskQueue();
}
TEST_F(WakeUpQueueTest, UnregisterQueue) {
std::unique_ptr<TaskQueueImplForTest> task_queue2 =
std::make_unique<TaskQueueImplForTest>(
nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
EXPECT_TRUE(wake_up_queue_->empty());
TimeTicks now = tick_clock_.NowTicks();
LazyNow lazy_now(now);
TimeTicks wake_up1 = now + Milliseconds(10);
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(wake_up1))
.Times(1);
task_queue_->SetNextWakeUp(&lazy_now, WakeUp{wake_up1});
TimeTicks wake_up2 = now + Milliseconds(100);
task_queue2->SetNextWakeUp(&lazy_now, WakeUp{wake_up2});
EXPECT_FALSE(wake_up_queue_->empty());
EXPECT_EQ(task_queue_.get(), wake_up_queue_->NextScheduledTaskQueue());
testing::Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(wake_up2))
.Times(1);
wake_up_queue_->UnregisterQueue(task_queue_.get());
EXPECT_EQ(task_queue2.get(), wake_up_queue_->NextScheduledTaskQueue());
task_queue_->UnregisterTaskQueue();
task_queue_ = nullptr;
EXPECT_FALSE(wake_up_queue_->empty());
testing::Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
.Times(1);
wake_up_queue_->UnregisterQueue(task_queue2.get());
EXPECT_FALSE(wake_up_queue_->NextScheduledTaskQueue());
task_queue2->UnregisterTaskQueue();
task_queue2 = nullptr;
EXPECT_TRUE(wake_up_queue_->empty());
}
TEST_F(WakeUpQueueTest, MoveReadyDelayedTasksToWorkQueues) {
TimeDelta delay = Milliseconds(50);
TimeTicks now = tick_clock_.NowTicks();
LazyNow lazy_now_1(now);
TimeTicks delayed_runtime = now + delay;
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(delayed_runtime));
task_queue_->SetNextWakeUp(&lazy_now_1, WakeUp{delayed_runtime});
EXPECT_EQ(delayed_runtime, wake_up_queue_->NextScheduledRunTime());
wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_1,
EnqueueOrder());
EXPECT_EQ(delayed_runtime, wake_up_queue_->NextScheduledRunTime());
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()));
tick_clock_.SetNowTicks(delayed_runtime);
LazyNow lazy_now_2(&tick_clock_);
wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_2,
EnqueueOrder());
ASSERT_TRUE(wake_up_queue_->NextScheduledRunTime().is_max());
}
TEST_F(WakeUpQueueTest, MoveReadyDelayedTasksToWorkQueuesWithLeeway) {
std::unique_ptr<TaskQueueImplForTest> task_queue2 =
std::make_unique<TaskQueueImplForTest>(
nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
TimeTicks now = tick_clock_.NowTicks();
LazyNow lazy_now_1(now);
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(now + Milliseconds(10)));
task_queue2->SetNextWakeUp(&lazy_now_1,
WakeUp{now + Milliseconds(10), Milliseconds(4)});
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(now + Milliseconds(11)));
task_queue_->SetNextWakeUp(&lazy_now_1,
WakeUp{now + Milliseconds(11), TimeDelta()});
EXPECT_EQ(now + Milliseconds(11), wake_up_queue_->NextScheduledRunTime());
wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_1,
EnqueueOrder());
EXPECT_EQ(now + Milliseconds(11), wake_up_queue_->NextScheduledRunTime());
tick_clock_.SetNowTicks(now + Milliseconds(10));
LazyNow lazy_now_2(&tick_clock_);
wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_2,
EnqueueOrder());
EXPECT_EQ(now + Milliseconds(11), wake_up_queue_->NextScheduledRunTime());
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_))
.Times(AnyNumber());
// Tidy up.
task_queue2->UnregisterTaskQueue();
}
TEST_F(WakeUpQueueTest, CancelDelayedWork) {
TimeTicks now = tick_clock_.NowTicks();
LazyNow lazy_now(now);
TimeTicks run_time = now + Milliseconds(20);
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(run_time));
task_queue_->SetNextWakeUp(&lazy_now, WakeUp{run_time});
EXPECT_EQ(task_queue_.get(), wake_up_queue_->NextScheduledTaskQueue());
EXPECT_CALL(*wake_up_queue_.get(),
OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()));
task_queue_->SetNextWakeUp(&lazy_now, absl::nullopt);
EXPECT_FALSE(wake_up_queue_->NextScheduledTaskQueue());
}
TEST_F(WakeUpQueueTest, CancelDelayedWork_TwoQueues) {
std::unique_ptr<TaskQueueImplForTest> task_queue2 =
std::make_unique<TaskQueueImplForTest>(
nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
TimeTicks now = tick_clock_.NowTicks();
LazyNow lazy_now(now);
TimeTicks run_time1 = now + Milliseconds(20);
TimeTicks run_time2 = now + Milliseconds(40);
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(run_time1));
task_queue_->SetNextWakeUp(&lazy_now, WakeUp{run_time1});
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_)).Times(0);
task_queue2->SetNextWakeUp(&lazy_now, WakeUp{run_time2});
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_EQ(task_queue_.get(), wake_up_queue_->NextScheduledTaskQueue());
EXPECT_EQ(run_time1, wake_up_queue_->NextScheduledRunTime());
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(run_time2));
task_queue_->SetNextWakeUp(&lazy_now, absl::nullopt);
EXPECT_EQ(task_queue2.get(), wake_up_queue_->NextScheduledTaskQueue());
EXPECT_EQ(run_time2, wake_up_queue_->NextScheduledRunTime());
Mock::VerifyAndClearExpectations(wake_up_queue_.get());
EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_))
.Times(AnyNumber());
// Tidy up.
task_queue2->UnregisterTaskQueue();
}
TEST_F(WakeUpQueueTest, HighResolutionWakeUps) {
TimeTicks now = tick_clock_.NowTicks();
LazyNow lazy_now(now);
TimeTicks run_time1 = now + Milliseconds(20);
TimeTicks run_time2 = now + Milliseconds(40);
TaskQueueImplForTest q1(nullptr, wake_up_queue_.get(),
TaskQueue::Spec(QueueName::TEST_TQ));
TaskQueueImplForTest q2(nullptr, wake_up_queue_.get(),
TaskQueue::Spec(QueueName::TEST_TQ));
// Add two high resolution wake-ups.
EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
wake_up_queue_->SetNextWakeUpForQueue(
&q1, &lazy_now, WakeUp{run_time1, TimeDelta(), WakeUpResolution::kHigh});
EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
wake_up_queue_->SetNextWakeUpForQueue(
&q2, &lazy_now, WakeUp{run_time2, TimeDelta(), WakeUpResolution::kHigh});
EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
// Remove one of the wake-ups.
wake_up_queue_->SetNextWakeUpForQueue(&q1, &lazy_now, absl::nullopt);
EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
// Remove the second one too.
wake_up_queue_->SetNextWakeUpForQueue(&q2, &lazy_now, absl::nullopt);
EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
// Change a low resolution wake-up to a high resolution one.
wake_up_queue_->SetNextWakeUpForQueue(
&q1, &lazy_now, WakeUp{run_time1, TimeDelta(), WakeUpResolution::kLow});
EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
wake_up_queue_->SetNextWakeUpForQueue(
&q1, &lazy_now, WakeUp{run_time1, TimeDelta(), WakeUpResolution::kHigh});
EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
// Move a high resolution wake-up in time.
wake_up_queue_->SetNextWakeUpForQueue(
&q1, &lazy_now, WakeUp{run_time2, TimeDelta(), WakeUpResolution::kHigh});
EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
// Cancel the wake-up twice.
wake_up_queue_->SetNextWakeUpForQueue(&q1, &lazy_now, absl::nullopt);
wake_up_queue_->SetNextWakeUpForQueue(&q1, &lazy_now, absl::nullopt);
EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
// Tidy up.
q1.UnregisterTaskQueue();
q2.UnregisterTaskQueue();
}
TEST_F(WakeUpQueueTest, SetNextWakeUpForQueueInThePast) {
constexpr auto kType = MessagePumpType::DEFAULT;
constexpr auto kDelay = Milliseconds(20);
constexpr TaskQueue::QueuePriority kHighestPriority = 0;
constexpr TaskQueue::QueuePriority kDefaultPriority = 1;
constexpr TaskQueue::QueuePriority kLowestPriority = 2;
constexpr TaskQueue::QueuePriority kPriorityCount = 3;
auto sequence_manager = sequence_manager::CreateUnboundSequenceManager(
SequenceManager::Settings::Builder()
.SetMessagePumpType(kType)
.SetTickClock(&tick_clock_)
.SetPrioritySettings(SequenceManager::PrioritySettings(
kPriorityCount, kDefaultPriority))
.Build());
sequence_manager->BindToMessagePump(MessagePump::Create(kType));
auto high_prio_queue =
sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST_TQ));
high_prio_queue->SetQueuePriority(kHighestPriority);
auto high_prio_runner = high_prio_queue->CreateTaskRunner(kTaskTypeNone);
auto low_prio_queue =
sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST2_TQ));
low_prio_queue->SetQueuePriority(kLowestPriority);
auto low_prio_runner = low_prio_queue->CreateTaskRunner(kTaskTypeNone);
sequence_manager->SetDefaultTaskRunner(high_prio_runner);
base::MockCallback<base::OnceCallback<void()>> task_1, task_2;
testing::Sequence s;
// Expect task_2 to run after task_1
EXPECT_CALL(task_1, Run);
EXPECT_CALL(task_2, Run);
// Schedule high and low priority tasks in such a way that clock.Now() will be
// way into the future by the time the low prio task run time is used to setup
// a wake up.
low_prio_runner->PostDelayedTask(FROM_HERE, task_2.Get(), kDelay);
high_prio_runner->PostDelayedTask(FROM_HERE, task_1.Get(), kDelay * 2);
high_prio_runner->PostTask(
FROM_HERE, BindOnce([](SimpleTestTickClock* clock,
TimeDelta delay) { clock->Advance(delay); },
base::Unretained(&tick_clock_), kDelay * 2));
RunLoop().RunUntilIdle();
}
} // namespace internal
} // namespace sequence_manager
} // namespace base