// 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/work_queue.h" #include #include #include #include "base/functional/bind.h" #include "base/task/common/lazy_now.h" #include "base/task/sequence_manager/enqueue_order.h" #include "base/task/sequence_manager/fence.h" #include "base/task/sequence_manager/sequence_manager.h" #include "base/task/sequence_manager/task_order.h" #include "base/task/sequence_manager/task_queue_impl.h" #include "base/task/sequence_manager/work_queue_sets.h" #include "base/time/time.h" #include "testing/gmock/include/gmock/gmock.h" namespace base { namespace sequence_manager { namespace internal { namespace { class MockObserver : public WorkQueueSets::Observer { MOCK_METHOD1(WorkQueueSetBecameEmpty, void(size_t set_index)); MOCK_METHOD1(WorkQueueSetBecameNonEmpty, void(size_t set_index)); }; void NopTask() {} struct Cancelable { Cancelable() = default; void NopTask() {} WeakPtrFactory weak_ptr_factory{this}; }; } // namespace class WorkQueueTest : public testing::Test { public: WorkQueueTest() : WorkQueueTest(WorkQueue::QueueType::kImmediate) {} explicit WorkQueueTest(WorkQueue::QueueType queue_type) : queue_type_(queue_type) {} void SetUp() override { task_queue_ = std::make_unique( /*sequence_manager=*/nullptr, /*wake_up_queue=*/nullptr, TaskQueue::Spec(QueueName::TEST_TQ)); work_queue_ = std::make_unique(task_queue_.get(), "test", queue_type_); mock_observer_ = std::make_unique(); work_queue_sets_ = std::make_unique( "test", mock_observer_.get(), SequenceManager::Settings()); work_queue_sets_->AddQueue(work_queue_.get(), 0); } void TearDown() override { work_queue_sets_->RemoveQueue(work_queue_.get()); task_queue_->UnregisterTaskQueue(); } protected: Task FakeCancelableTaskWithEnqueueOrder(int enqueue_order, WeakPtr weak_ptr) { Task fake_task(PostedTask(nullptr, BindOnce(&Cancelable::NopTask, weak_ptr), FROM_HERE), EnqueueOrder(), EnqueueOrder::FromIntForTesting(enqueue_order)); return fake_task; } Task FakeTaskWithEnqueueOrder(int enqueue_order) { Task fake_task(PostedTask(nullptr, BindOnce(&NopTask), FROM_HERE), EnqueueOrder(), EnqueueOrder::FromIntForTesting(enqueue_order)); return fake_task; } Task FakeNonNestableTaskWithEnqueueOrder(int enqueue_order) { Task fake_task(PostedTask(nullptr, BindOnce(&NopTask), FROM_HERE), EnqueueOrder(), EnqueueOrder::FromIntForTesting(enqueue_order)); fake_task.nestable = Nestable::kNonNestable; return fake_task; } Task FakeTaskWithTaskOrder(TaskOrder task_order) { Task fake_task(PostedTask(nullptr, BindOnce(&NopTask), FROM_HERE, task_order.delayed_run_time(), subtle::DelayPolicy::kFlexibleNoSooner), EnqueueOrder::FromIntForTesting(task_order.sequence_num()), task_order.enqueue_order(), TimeTicks() + Milliseconds(1)); return fake_task; } Fence CreateFenceWithEnqueueOrder(int enqueue_order) { return Fence(TaskOrder::CreateForTesting( EnqueueOrder::FromIntForTesting(enqueue_order))); } WorkQueue* GetOldestQueueInSet(int set) { if (auto queue_and_task_order = work_queue_sets_->GetOldestQueueAndTaskOrderInSet(set)) { return queue_and_task_order->queue; } return nullptr; } std::unique_ptr mock_observer_; std::unique_ptr task_queue_; std::unique_ptr work_queue_; std::unique_ptr work_queue_sets_; std::unique_ptr incoming_queue_; private: const WorkQueue::QueueType queue_type_; }; class DelayedWorkQueueTest : public WorkQueueTest { public: DelayedWorkQueueTest() : WorkQueueTest(WorkQueue::QueueType::kDelayed) {} }; TEST_F(WorkQueueTest, Empty) { EXPECT_TRUE(work_queue_->Empty()); work_queue_->Push(FakeTaskWithEnqueueOrder(1)); EXPECT_FALSE(work_queue_->Empty()); } TEST_F(WorkQueueTest, Empty_IgnoresFences) { work_queue_->Push(FakeTaskWithEnqueueOrder(1)); work_queue_->InsertFence(Fence::BlockingFence()); EXPECT_FALSE(work_queue_->Empty()); } TEST_F(WorkQueueTest, GetFrontTaskOrderQueueEmpty) { EXPECT_FALSE(work_queue_->GetFrontTaskOrder()); } TEST_F(WorkQueueTest, GetFrontTaskOrder) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); std::optional task_order = work_queue_->GetFrontTaskOrder(); EXPECT_TRUE(task_order); EXPECT_EQ(2ull, task_order->enqueue_order()); } TEST_F(WorkQueueTest, GetFrontTaskQueueEmpty) { EXPECT_EQ(nullptr, work_queue_->GetFrontTask()); } TEST_F(WorkQueueTest, GetFrontTask) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); ASSERT_NE(nullptr, work_queue_->GetFrontTask()); EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order()); } TEST_F(WorkQueueTest, GetBackTask_Empty) { EXPECT_EQ(nullptr, work_queue_->GetBackTask()); } TEST_F(WorkQueueTest, GetBackTask) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); ASSERT_NE(nullptr, work_queue_->GetBackTask()); EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order()); } TEST_F(WorkQueueTest, Push) { EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); work_queue_->Push(FakeTaskWithEnqueueOrder(2)); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); } TEST_F(WorkQueueTest, PushMultiple) { EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order()); EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order()); } TEST_F(WorkQueueTest, PushAfterFenceHit) { work_queue_->InsertFence(Fence::BlockingFence()); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); work_queue_->Push(FakeTaskWithEnqueueOrder(2)); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); } TEST_F(WorkQueueTest, CreateTaskPusherNothingPushed) { EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); { WorkQueue::TaskPusher task_pusher(work_queue_->CreateTaskPusher()); } EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); } TEST_F(WorkQueueTest, CreateTaskPusherOneTask) { EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); { WorkQueue::TaskPusher task_pusher(work_queue_->CreateTaskPusher()); Task task = FakeTaskWithEnqueueOrder(2); task_pusher.Push(std::move(task)); } EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); } TEST_F(WorkQueueTest, CreateTaskPusherThreeTasks) { EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); { WorkQueue::TaskPusher task_pusher(work_queue_->CreateTaskPusher()); task_pusher.Push(FakeTaskWithEnqueueOrder(2)); task_pusher.Push(FakeTaskWithEnqueueOrder(3)); task_pusher.Push(FakeTaskWithEnqueueOrder(4)); } EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order()); EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order()); } TEST_F(WorkQueueTest, CreateTaskPusherAfterFenceHit) { work_queue_->InsertFence(Fence::BlockingFence()); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); { WorkQueue::TaskPusher task_pusher(work_queue_->CreateTaskPusher()); task_pusher.Push(FakeTaskWithEnqueueOrder(2)); task_pusher.Push(FakeTaskWithEnqueueOrder(3)); task_pusher.Push(FakeTaskWithEnqueueOrder(4)); } EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); } TEST_F(WorkQueueTest, PushNonNestableTaskToFront) { EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); work_queue_->PushNonNestableTaskToFront( FakeNonNestableTaskWithEnqueueOrder(3)); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); work_queue_->PushNonNestableTaskToFront( FakeNonNestableTaskWithEnqueueOrder(2)); EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order()); EXPECT_EQ(3ull, work_queue_->GetBackTask()->enqueue_order()); } TEST_F(WorkQueueTest, PushNonNestableTaskToFrontAfterFenceHit) { work_queue_->InsertFence(Fence::BlockingFence()); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); work_queue_->PushNonNestableTaskToFront( FakeNonNestableTaskWithEnqueueOrder(2)); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); } TEST_F(WorkQueueTest, PushNonNestableTaskToFrontBeforeFenceHit) { work_queue_->InsertFence(CreateFenceWithEnqueueOrder(3)); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); work_queue_->PushNonNestableTaskToFront( FakeNonNestableTaskWithEnqueueOrder(2)); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); } TEST_F(WorkQueueTest, TakeImmediateIncomingQueueTasks) { task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(2)); task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(3)); task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(4)); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); EXPECT_TRUE(work_queue_->Empty()); work_queue_->TakeImmediateIncomingQueueTasks(); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); ASSERT_NE(nullptr, work_queue_->GetFrontTask()); EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order()); ASSERT_NE(nullptr, work_queue_->GetBackTask()); EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order()); } TEST_F(WorkQueueTest, TakeImmediateIncomingQueueTasksAfterFenceHit) { work_queue_->InsertFence(Fence::BlockingFence()); task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(2)); task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(3)); task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(4)); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); EXPECT_TRUE(work_queue_->Empty()); work_queue_->TakeImmediateIncomingQueueTasks(); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); ASSERT_NE(nullptr, work_queue_->GetFrontTask()); EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order()); ASSERT_NE(nullptr, work_queue_->GetBackTask()); EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order()); } TEST_F(WorkQueueTest, TakeTaskFromWorkQueue) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_EQ(3ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_EQ(4ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); EXPECT_TRUE(work_queue_->Empty()); } TEST_F(WorkQueueTest, TakeTaskFromWorkQueue_HitFence) { work_queue_->InsertFence(CreateFenceWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); EXPECT_TRUE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, InsertFenceBeforeEnqueueing) { EXPECT_FALSE(work_queue_->InsertFence(Fence::BlockingFence())); EXPECT_TRUE(work_queue_->BlockedByFence()); work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); EXPECT_FALSE(work_queue_->GetFrontTaskOrder()); } TEST_F(WorkQueueTest, InsertFenceAfterEnqueueingNonBlocking) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); EXPECT_FALSE(work_queue_->InsertFence(CreateFenceWithEnqueueOrder(5))); EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_TRUE(work_queue_->GetFrontTaskOrder()); EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); } TEST_F(WorkQueueTest, InsertFenceAfterEnqueueing) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); // NB in reality a fence will always be greater than any currently enqueued // tasks. EXPECT_FALSE(work_queue_->InsertFence(Fence::BlockingFence())); EXPECT_TRUE(work_queue_->BlockedByFence()); EXPECT_FALSE(work_queue_->GetFrontTaskOrder()); } TEST_F(WorkQueueTest, InsertNewFence) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); work_queue_->Push(FakeTaskWithEnqueueOrder(5)); EXPECT_FALSE(work_queue_->InsertFence(CreateFenceWithEnqueueOrder(3))); EXPECT_FALSE(work_queue_->BlockedByFence()); // Note until TakeTaskFromWorkQueue() is called we don't hit the fence. std::optional task_order = work_queue_->GetFrontTaskOrder(); EXPECT_TRUE(task_order); EXPECT_EQ(2ull, task_order->enqueue_order()); EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_FALSE(work_queue_->GetFrontTaskOrder()); EXPECT_TRUE(work_queue_->BlockedByFence()); // Inserting the new fence should temporarily unblock the queue until the new // one is hit. EXPECT_TRUE(work_queue_->InsertFence(CreateFenceWithEnqueueOrder(6))); EXPECT_FALSE(work_queue_->BlockedByFence()); task_order = work_queue_->GetFrontTaskOrder(); EXPECT_TRUE(task_order); EXPECT_EQ(4ull, task_order->enqueue_order()); EXPECT_EQ(4ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_TRUE(work_queue_->GetFrontTaskOrder()); EXPECT_FALSE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, PushWithNonEmptyQueueDoesNotHitFence) { work_queue_->Push(FakeTaskWithEnqueueOrder(1)); EXPECT_FALSE(work_queue_->InsertFence(CreateFenceWithEnqueueOrder(2))); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); EXPECT_FALSE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, RemoveFence) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); work_queue_->Push(FakeTaskWithEnqueueOrder(5)); work_queue_->InsertFence(CreateFenceWithEnqueueOrder(3)); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); EXPECT_TRUE(work_queue_->BlockedByFence()); EXPECT_TRUE(work_queue_->RemoveFence()); EXPECT_EQ(4ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, RemoveFenceButNoFence) { EXPECT_FALSE(work_queue_->RemoveFence()); } TEST_F(WorkQueueTest, RemoveFenceNothingUnblocked) { EXPECT_FALSE(work_queue_->InsertFence(Fence::BlockingFence())); EXPECT_TRUE(work_queue_->BlockedByFence()); EXPECT_FALSE(work_queue_->RemoveFence()); EXPECT_FALSE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, BlockedByFence) { EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_FALSE(work_queue_->InsertFence(Fence::BlockingFence())); EXPECT_TRUE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, BlockedByFencePopBecomesEmpty) { work_queue_->Push(FakeTaskWithEnqueueOrder(1)); EXPECT_FALSE(work_queue_->InsertFence(CreateFenceWithEnqueueOrder(2))); EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_EQ(1ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_TRUE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, BlockedByFencePop) { work_queue_->Push(FakeTaskWithEnqueueOrder(1)); EXPECT_FALSE(work_queue_->InsertFence(CreateFenceWithEnqueueOrder(2))); EXPECT_FALSE(work_queue_->BlockedByFence()); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_EQ(1ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_TRUE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, InitiallyEmptyBlockedByFenceNewFenceUnblocks) { EXPECT_FALSE(work_queue_->InsertFence(Fence::BlockingFence())); EXPECT_TRUE(work_queue_->BlockedByFence()); work_queue_->Push(FakeTaskWithEnqueueOrder(2)); EXPECT_TRUE(work_queue_->InsertFence(CreateFenceWithEnqueueOrder(3))); EXPECT_FALSE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, BlockedByFenceNewFenceUnblocks) { work_queue_->Push(FakeTaskWithEnqueueOrder(1)); EXPECT_FALSE(work_queue_->InsertFence(CreateFenceWithEnqueueOrder(2))); EXPECT_FALSE(work_queue_->BlockedByFence()); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_EQ(1ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order()); EXPECT_TRUE(work_queue_->BlockedByFence()); EXPECT_TRUE(work_queue_->InsertFence(CreateFenceWithEnqueueOrder(4))); EXPECT_FALSE(work_queue_->BlockedByFence()); } TEST_F(WorkQueueTest, InsertFenceAfterEnqueuing) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_FALSE(work_queue_->InsertFence(Fence::BlockingFence())); EXPECT_TRUE(work_queue_->BlockedByFence()); EXPECT_FALSE(work_queue_->GetFrontTaskOrder()); } TEST_F(WorkQueueTest, RemoveAllCanceledTasksFromFront) { { Cancelable cancelable; work_queue_->Push(FakeCancelableTaskWithEnqueueOrder( 2, cancelable.weak_ptr_factory.GetWeakPtr())); work_queue_->Push(FakeCancelableTaskWithEnqueueOrder( 3, cancelable.weak_ptr_factory.GetWeakPtr())); work_queue_->Push(FakeCancelableTaskWithEnqueueOrder( 4, cancelable.weak_ptr_factory.GetWeakPtr())); work_queue_->Push(FakeTaskWithEnqueueOrder(5)); } EXPECT_TRUE(work_queue_->RemoveAllCanceledTasksFromFront()); std::optional task_order = work_queue_->GetFrontTaskOrder(); EXPECT_TRUE(task_order); EXPECT_EQ(5ull, task_order->enqueue_order()); } TEST_F(WorkQueueTest, RemoveAllCanceledTasksFromFrontTasksNotCanceled) { { Cancelable cancelable; work_queue_->Push(FakeCancelableTaskWithEnqueueOrder( 2, cancelable.weak_ptr_factory.GetWeakPtr())); work_queue_->Push(FakeCancelableTaskWithEnqueueOrder( 3, cancelable.weak_ptr_factory.GetWeakPtr())); work_queue_->Push(FakeCancelableTaskWithEnqueueOrder( 4, cancelable.weak_ptr_factory.GetWeakPtr())); work_queue_->Push(FakeTaskWithEnqueueOrder(5)); EXPECT_FALSE(work_queue_->RemoveAllCanceledTasksFromFront()); std::optional task_order = work_queue_->GetFrontTaskOrder(); EXPECT_TRUE(task_order); EXPECT_EQ(2ull, task_order->enqueue_order()); } } TEST_F(WorkQueueTest, RemoveAllCanceledTasksFromFrontQueueBlockedByFence) { { Cancelable cancelable; work_queue_->Push(FakeCancelableTaskWithEnqueueOrder( 2, cancelable.weak_ptr_factory.GetWeakPtr())); work_queue_->Push(FakeCancelableTaskWithEnqueueOrder( 3, cancelable.weak_ptr_factory.GetWeakPtr())); work_queue_->Push(FakeCancelableTaskWithEnqueueOrder( 4, cancelable.weak_ptr_factory.GetWeakPtr())); work_queue_->Push(FakeTaskWithEnqueueOrder(5)); } EXPECT_FALSE(work_queue_->InsertFence(Fence::BlockingFence())); EXPECT_TRUE(work_queue_->BlockedByFence()); EXPECT_TRUE(work_queue_->RemoveAllCanceledTasksFromFront()); EXPECT_FALSE(work_queue_->GetFrontTaskOrder()); } TEST_F(WorkQueueTest, CollectTasksOlderThan) { work_queue_->Push(FakeTaskWithEnqueueOrder(2)); work_queue_->Push(FakeTaskWithEnqueueOrder(3)); work_queue_->Push(FakeTaskWithEnqueueOrder(4)); std::vector result; work_queue_->CollectTasksOlderThan( TaskOrder::CreateForTesting(EnqueueOrder::FromIntForTesting(4), TimeTicks(), 0), &result); ASSERT_EQ(2u, result.size()); EXPECT_EQ(2u, result[0]->enqueue_order()); EXPECT_EQ(3u, result[1]->enqueue_order()); } TEST_F(DelayedWorkQueueTest, PushMultipleWithSameEnqueueOrder) { const EnqueueOrder kEnqueueOrder = EnqueueOrder::FromIntForTesting(5); TaskOrder task_orders[3] = { TaskOrder::CreateForTesting(kEnqueueOrder, TimeTicks() + Seconds(1), /*sequence_num=*/4), TaskOrder::CreateForTesting(kEnqueueOrder, TimeTicks() + Seconds(2), /*sequence_num=*/3), TaskOrder::CreateForTesting(kEnqueueOrder, TimeTicks() + Seconds(3), /*sequence_num=*/2), }; EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); for (auto& task_order : task_orders) { work_queue_->Push(FakeTaskWithTaskOrder(task_order)); } EXPECT_TRUE(task_orders[0] == work_queue_->GetFrontTaskOrder()); EXPECT_TRUE(task_orders[0] == work_queue_->GetFrontTask()->task_order()); EXPECT_TRUE(task_orders[2] == work_queue_->GetBackTask()->task_order()); } TEST_F(DelayedWorkQueueTest, DelayedFenceInDelayedTaskGroup) { const EnqueueOrder kEnqueueOrder = EnqueueOrder::FromIntForTesting(5); TaskOrder task_orders[3] = { TaskOrder::CreateForTesting(kEnqueueOrder, TimeTicks() + Seconds(1), /*sequence_num=*/4), TaskOrder::CreateForTesting(kEnqueueOrder, TimeTicks() + Seconds(2), /*sequence_num=*/3), TaskOrder::CreateForTesting(kEnqueueOrder, TimeTicks() + Seconds(3), /*sequence_num=*/2), }; EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); for (auto& task_order : task_orders) { work_queue_->Push(FakeTaskWithTaskOrder(task_order)); } work_queue_->InsertFence(Fence(task_orders[2])); EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); EXPECT_TRUE(task_orders[0] == work_queue_->TakeTaskFromWorkQueue().task_order()); EXPECT_FALSE(work_queue_->BlockedByFence()); EXPECT_EQ(work_queue_.get(), GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); EXPECT_TRUE(task_orders[1] == work_queue_->TakeTaskFromWorkQueue().task_order()); EXPECT_TRUE(work_queue_->BlockedByFence()); EXPECT_EQ(nullptr, GetOldestQueueInSet(0)); EXPECT_FALSE(work_queue_->Empty()); } } // namespace internal } // namespace sequence_manager } // namespace base