1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/task/sequence_manager/work_queue_sets.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10
11 #include "base/functional/bind.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/task/sequence_manager/enqueue_order.h"
14 #include "base/task/sequence_manager/fence.h"
15 #include "base/task/sequence_manager/task_order.h"
16 #include "base/task/sequence_manager/task_queue.h"
17 #include "base/task/sequence_manager/work_queue.h"
18 #include "base/time/time.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "third_party/abseil-cpp/absl/types/optional.h"
21
22 namespace base {
23 namespace sequence_manager {
24
25 class TimeDomain;
26
27 namespace internal {
28
29 namespace {
30
31 class MockObserver : public WorkQueueSets::Observer {
32 MOCK_METHOD1(WorkQueueSetBecameEmpty, void(size_t set_index));
33 MOCK_METHOD1(WorkQueueSetBecameNonEmpty, void(size_t set_index));
34 };
35
36 const TaskQueue::QueuePriority kHighestPriority = 0;
37 const TaskQueue::QueuePriority kDefaultPriority = 5;
38 const TaskQueue::QueuePriority kPriorityCount = 10;
39
40 } // namespace
41
42 class WorkQueueSetsTest : public testing::Test {
43 public:
SetUp()44 void SetUp() override {
45 work_queue_sets_ = std::make_unique<WorkQueueSets>(
46 "test", &mock_observer_,
47 SequenceManager::Settings::Builder()
48 .SetPrioritySettings(SequenceManager::PrioritySettings(
49 kPriorityCount, kDefaultPriority))
50 .Build());
51 }
52
TearDown()53 void TearDown() override {
54 for (std::unique_ptr<WorkQueue>& work_queue : work_queues_) {
55 if (work_queue->work_queue_sets())
56 work_queue_sets_->RemoveQueue(work_queue.get());
57 }
58 }
59
60 protected:
NewTaskQueue(const char * queue_name,WorkQueue::QueueType queue_type=WorkQueue::QueueType::kImmediate)61 WorkQueue* NewTaskQueue(
62 const char* queue_name,
63 WorkQueue::QueueType queue_type = WorkQueue::QueueType::kImmediate) {
64 WorkQueue* queue = new WorkQueue(nullptr, "test", queue_type);
65 work_queues_.push_back(WrapUnique(queue));
66 work_queue_sets_->AddQueue(queue, kHighestPriority);
67 return queue;
68 }
69
FakeTaskWithEnqueueOrder(int enqueue_order)70 Task FakeTaskWithEnqueueOrder(int enqueue_order) {
71 Task fake_task(PostedTask(nullptr, BindOnce([] {}), FROM_HERE),
72 EnqueueOrder(),
73 EnqueueOrder::FromIntForTesting(enqueue_order));
74 return fake_task;
75 }
76
FakeNonNestableTaskWithEnqueueOrder(int enqueue_order)77 Task FakeNonNestableTaskWithEnqueueOrder(int enqueue_order) {
78 Task fake_task(PostedTask(nullptr, BindOnce([] {}), FROM_HERE),
79 EnqueueOrder(),
80 EnqueueOrder::FromIntForTesting(enqueue_order));
81 fake_task.nestable = Nestable::kNonNestable;
82 return fake_task;
83 }
84
FakeTaskWithTaskOrder(TaskOrder task_order)85 Task FakeTaskWithTaskOrder(TaskOrder task_order) {
86 Task fake_task(PostedTask(nullptr, BindOnce([] {}), FROM_HERE,
87 task_order.delayed_run_time(),
88 subtle::DelayPolicy::kFlexibleNoSooner),
89 EnqueueOrder::FromIntForTesting(task_order.sequence_num()),
90 task_order.enqueue_order(), TimeTicks() + Milliseconds(1));
91 return fake_task;
92 }
93
GetOldestQueueInSet(int set) const94 WorkQueue* GetOldestQueueInSet(int set) const {
95 if (auto queue_and_task_order =
96 work_queue_sets_->GetOldestQueueAndTaskOrderInSet(set)) {
97 return queue_and_task_order->queue;
98 }
99 return nullptr;
100 }
101
102 MockObserver mock_observer_;
103 std::vector<std::unique_ptr<WorkQueue>> work_queues_;
104 std::unique_ptr<WorkQueueSets> work_queue_sets_;
105 };
106
TEST_F(WorkQueueSetsTest,ChangeSetIndex)107 TEST_F(WorkQueueSetsTest, ChangeSetIndex) {
108 WorkQueue* work_queue = NewTaskQueue("queue");
109 size_t set = kDefaultPriority;
110 work_queue_sets_->ChangeSetIndex(work_queue, set);
111 EXPECT_EQ(set, work_queue->work_queue_set_index());
112 }
113
TEST_F(WorkQueueSetsTest,GetOldestQueueAndTaskOrderInSet_QueueEmpty)114 TEST_F(WorkQueueSetsTest, GetOldestQueueAndTaskOrderInSet_QueueEmpty) {
115 WorkQueue* work_queue = NewTaskQueue("queue");
116 size_t set = kDefaultPriority;
117 work_queue_sets_->ChangeSetIndex(work_queue, set);
118 EXPECT_FALSE(work_queue_sets_->GetOldestQueueAndTaskOrderInSet(set));
119 }
120
TEST_F(WorkQueueSetsTest,OnTaskPushedToEmptyQueue)121 TEST_F(WorkQueueSetsTest, OnTaskPushedToEmptyQueue) {
122 WorkQueue* work_queue = NewTaskQueue("queue");
123 size_t set = kDefaultPriority;
124 work_queue_sets_->ChangeSetIndex(work_queue, set);
125 EXPECT_FALSE(work_queue_sets_->GetOldestQueueAndTaskOrderInSet(set));
126
127 // Calls OnTaskPushedToEmptyQueue.
128 work_queue->Push(FakeTaskWithEnqueueOrder(10));
129 EXPECT_EQ(work_queue, GetOldestQueueInSet(set));
130 }
131
TEST_F(WorkQueueSetsTest,GetOldestQueueAndTaskOrderInSet_SingleTaskInSet)132 TEST_F(WorkQueueSetsTest, GetOldestQueueAndTaskOrderInSet_SingleTaskInSet) {
133 WorkQueue* work_queue = NewTaskQueue("queue");
134 work_queue->Push(FakeTaskWithEnqueueOrder(10));
135 size_t set = 1;
136 work_queue_sets_->ChangeSetIndex(work_queue, set);
137 EXPECT_EQ(work_queue, GetOldestQueueInSet(set));
138 }
139
TEST_F(WorkQueueSetsTest,GetOldestQueueAndTaskOrderInSet_TaskOrder)140 TEST_F(WorkQueueSetsTest, GetOldestQueueAndTaskOrderInSet_TaskOrder) {
141 WorkQueue* work_queue = NewTaskQueue("queue");
142 work_queue->Push(FakeTaskWithEnqueueOrder(10));
143 size_t set = 1;
144 work_queue_sets_->ChangeSetIndex(work_queue, set);
145
146 absl::optional<WorkQueueAndTaskOrder> work_queue_and_task_order =
147 work_queue_sets_->GetOldestQueueAndTaskOrderInSet(set);
148 ASSERT_TRUE(work_queue_and_task_order);
149 EXPECT_EQ(work_queue, work_queue_and_task_order->queue);
150 EXPECT_EQ(10u, work_queue_and_task_order->order.enqueue_order());
151 }
152
TEST_F(WorkQueueSetsTest,GetOldestQueueAndTaskOrderInSet_MultipleAgesInSet)153 TEST_F(WorkQueueSetsTest, GetOldestQueueAndTaskOrderInSet_MultipleAgesInSet) {
154 WorkQueue* queue1 = NewTaskQueue("queue1");
155 WorkQueue* queue2 = NewTaskQueue("queue2");
156 WorkQueue* queue3 = NewTaskQueue("queue2");
157 queue1->Push(FakeTaskWithEnqueueOrder(6));
158 queue2->Push(FakeTaskWithEnqueueOrder(5));
159 queue3->Push(FakeTaskWithEnqueueOrder(4));
160 size_t set = 2;
161 work_queue_sets_->ChangeSetIndex(queue1, set);
162 work_queue_sets_->ChangeSetIndex(queue2, set);
163 work_queue_sets_->ChangeSetIndex(queue3, set);
164 absl::optional<WorkQueueAndTaskOrder> queue_and_order =
165 work_queue_sets_->GetOldestQueueAndTaskOrderInSet(set);
166 ASSERT_TRUE(queue_and_order);
167 EXPECT_EQ(queue3, queue_and_order->queue);
168 EXPECT_EQ(EnqueueOrder::FromIntForTesting(4),
169 queue_and_order->order.enqueue_order());
170 }
171
TEST_F(WorkQueueSetsTest,OnQueuesFrontTaskChanged)172 TEST_F(WorkQueueSetsTest, OnQueuesFrontTaskChanged) {
173 WorkQueue* queue1 = NewTaskQueue("queue1");
174 WorkQueue* queue2 = NewTaskQueue("queue2");
175 WorkQueue* queue3 = NewTaskQueue("queue3");
176 queue1->Push(FakeTaskWithEnqueueOrder(6));
177 queue2->Push(FakeTaskWithEnqueueOrder(5));
178 queue3->Push(FakeTaskWithEnqueueOrder(4));
179 size_t set = 4;
180 work_queue_sets_->ChangeSetIndex(queue1, set);
181 work_queue_sets_->ChangeSetIndex(queue2, set);
182 work_queue_sets_->ChangeSetIndex(queue3, set);
183 EXPECT_EQ(queue3, GetOldestQueueInSet(set));
184
185 // Make |queue1| now have a task with the lowest enqueue order.
186 *const_cast<Task*>(queue1->GetFrontTask()) = FakeTaskWithEnqueueOrder(1);
187 work_queue_sets_->OnQueuesFrontTaskChanged(queue1);
188 EXPECT_EQ(queue1, GetOldestQueueInSet(set));
189 }
190
TEST_F(WorkQueueSetsTest,OnQueuesFrontTaskChanged_OldestQueueBecomesEmpty)191 TEST_F(WorkQueueSetsTest, OnQueuesFrontTaskChanged_OldestQueueBecomesEmpty) {
192 WorkQueue* queue1 = NewTaskQueue("queue1");
193 WorkQueue* queue2 = NewTaskQueue("queue2");
194 WorkQueue* queue3 = NewTaskQueue("queue3");
195 queue1->Push(FakeTaskWithEnqueueOrder(6));
196 queue2->Push(FakeTaskWithEnqueueOrder(5));
197 queue3->Push(FakeTaskWithEnqueueOrder(4));
198 size_t set = 4;
199 work_queue_sets_->ChangeSetIndex(queue1, set);
200 work_queue_sets_->ChangeSetIndex(queue2, set);
201 work_queue_sets_->ChangeSetIndex(queue3, set);
202 EXPECT_EQ(queue3, GetOldestQueueInSet(set));
203
204 queue3->PopTaskForTesting();
205 work_queue_sets_->OnQueuesFrontTaskChanged(queue3);
206 EXPECT_EQ(queue2, GetOldestQueueInSet(set));
207 }
208
TEST_F(WorkQueueSetsTest,OnQueuesFrontTaskChanged_YoungestQueueBecomesEmpty)209 TEST_F(WorkQueueSetsTest, OnQueuesFrontTaskChanged_YoungestQueueBecomesEmpty) {
210 WorkQueue* queue1 = NewTaskQueue("queue1");
211 WorkQueue* queue2 = NewTaskQueue("queue2");
212 WorkQueue* queue3 = NewTaskQueue("queue3");
213 queue1->Push(FakeTaskWithEnqueueOrder(6));
214 queue2->Push(FakeTaskWithEnqueueOrder(5));
215 queue3->Push(FakeTaskWithEnqueueOrder(4));
216 size_t set = 4;
217 work_queue_sets_->ChangeSetIndex(queue1, set);
218 work_queue_sets_->ChangeSetIndex(queue2, set);
219 work_queue_sets_->ChangeSetIndex(queue3, set);
220 EXPECT_EQ(queue3, GetOldestQueueInSet(set));
221
222 queue1->PopTaskForTesting();
223 work_queue_sets_->OnQueuesFrontTaskChanged(queue1);
224 EXPECT_EQ(queue3, GetOldestQueueInSet(set));
225 }
226
TEST_F(WorkQueueSetsTest,OnPopMinQueueInSet)227 TEST_F(WorkQueueSetsTest, OnPopMinQueueInSet) {
228 WorkQueue* queue1 = NewTaskQueue("queue1");
229 WorkQueue* queue2 = NewTaskQueue("queue2");
230 WorkQueue* queue3 = NewTaskQueue("queue3");
231 queue1->Push(FakeTaskWithEnqueueOrder(6));
232 queue2->Push(FakeTaskWithEnqueueOrder(1));
233 queue2->Push(FakeTaskWithEnqueueOrder(3));
234 queue3->Push(FakeTaskWithEnqueueOrder(4));
235 size_t set = 3;
236 work_queue_sets_->ChangeSetIndex(queue1, set);
237 work_queue_sets_->ChangeSetIndex(queue2, set);
238 work_queue_sets_->ChangeSetIndex(queue3, set);
239 EXPECT_EQ(queue2, GetOldestQueueInSet(set));
240
241 queue2->PopTaskForTesting();
242 work_queue_sets_->OnPopMinQueueInSet(queue2);
243 EXPECT_EQ(queue2, GetOldestQueueInSet(set));
244 }
245
TEST_F(WorkQueueSetsTest,OnPopMinQueueInSet_QueueBecomesEmpty)246 TEST_F(WorkQueueSetsTest, OnPopMinQueueInSet_QueueBecomesEmpty) {
247 WorkQueue* queue1 = NewTaskQueue("queue1");
248 WorkQueue* queue2 = NewTaskQueue("queue2");
249 WorkQueue* queue3 = NewTaskQueue("queue3");
250 queue1->Push(FakeTaskWithEnqueueOrder(6));
251 queue2->Push(FakeTaskWithEnqueueOrder(5));
252 queue3->Push(FakeTaskWithEnqueueOrder(4));
253 size_t set = 4;
254 work_queue_sets_->ChangeSetIndex(queue1, set);
255 work_queue_sets_->ChangeSetIndex(queue2, set);
256 work_queue_sets_->ChangeSetIndex(queue3, set);
257 EXPECT_EQ(queue3, GetOldestQueueInSet(set));
258
259 queue3->PopTaskForTesting();
260 work_queue_sets_->OnPopMinQueueInSet(queue3);
261 EXPECT_EQ(queue2, GetOldestQueueInSet(set));
262 }
263
TEST_F(WorkQueueSetsTest,GetOldestQueueAndTaskOrderInSet_MultipleAgesInSetIntegerRollover)264 TEST_F(WorkQueueSetsTest,
265 GetOldestQueueAndTaskOrderInSet_MultipleAgesInSetIntegerRollover) {
266 WorkQueue* queue1 = NewTaskQueue("queue1");
267 WorkQueue* queue2 = NewTaskQueue("queue2");
268 WorkQueue* queue3 = NewTaskQueue("queue3");
269 queue1->Push(FakeTaskWithEnqueueOrder(0x7ffffff1));
270 queue2->Push(FakeTaskWithEnqueueOrder(0x7ffffff0));
271 queue3->Push(FakeTaskWithEnqueueOrder(-0x7ffffff1));
272 size_t set = 1;
273 work_queue_sets_->ChangeSetIndex(queue1, set);
274 work_queue_sets_->ChangeSetIndex(queue2, set);
275 work_queue_sets_->ChangeSetIndex(queue3, set);
276 EXPECT_EQ(queue2, GetOldestQueueInSet(set));
277 }
278
TEST_F(WorkQueueSetsTest,GetOldestQueueAndTaskOrderInSet_MultipleAgesInSet_RemoveQueue)279 TEST_F(WorkQueueSetsTest,
280 GetOldestQueueAndTaskOrderInSet_MultipleAgesInSet_RemoveQueue) {
281 WorkQueue* queue1 = NewTaskQueue("queue1");
282 WorkQueue* queue2 = NewTaskQueue("queue2");
283 WorkQueue* queue3 = NewTaskQueue("queue3");
284 queue1->Push(FakeTaskWithEnqueueOrder(6));
285 queue2->Push(FakeTaskWithEnqueueOrder(5));
286 queue3->Push(FakeTaskWithEnqueueOrder(4));
287 size_t set = 1;
288 work_queue_sets_->ChangeSetIndex(queue1, set);
289 work_queue_sets_->ChangeSetIndex(queue2, set);
290 work_queue_sets_->ChangeSetIndex(queue3, set);
291 work_queue_sets_->RemoveQueue(queue3);
292 EXPECT_EQ(queue2, GetOldestQueueInSet(set));
293 }
294
TEST_F(WorkQueueSetsTest,ChangeSetIndex_Complex)295 TEST_F(WorkQueueSetsTest, ChangeSetIndex_Complex) {
296 WorkQueue* queue1 = NewTaskQueue("queue1");
297 WorkQueue* queue2 = NewTaskQueue("queue2");
298 WorkQueue* queue3 = NewTaskQueue("queue3");
299 WorkQueue* queue4 = NewTaskQueue("queue4");
300 queue1->Push(FakeTaskWithEnqueueOrder(6));
301 queue2->Push(FakeTaskWithEnqueueOrder(5));
302 queue3->Push(FakeTaskWithEnqueueOrder(4));
303 queue4->Push(FakeTaskWithEnqueueOrder(3));
304 size_t set1 = 1;
305 size_t set2 = 2;
306 work_queue_sets_->ChangeSetIndex(queue1, set1);
307 work_queue_sets_->ChangeSetIndex(queue2, set1);
308 work_queue_sets_->ChangeSetIndex(queue3, set2);
309 work_queue_sets_->ChangeSetIndex(queue4, set2);
310 EXPECT_EQ(queue2, GetOldestQueueInSet(set1));
311 EXPECT_EQ(queue4, GetOldestQueueInSet(set2));
312
313 work_queue_sets_->ChangeSetIndex(queue4, set1);
314 EXPECT_EQ(queue4, GetOldestQueueInSet(set1));
315 EXPECT_EQ(queue3, GetOldestQueueInSet(set2));
316 }
317
TEST_F(WorkQueueSetsTest,IsSetEmpty_NoWork)318 TEST_F(WorkQueueSetsTest, IsSetEmpty_NoWork) {
319 size_t set = 2;
320 EXPECT_TRUE(work_queue_sets_->IsSetEmpty(set));
321
322 WorkQueue* work_queue = NewTaskQueue("queue");
323 work_queue_sets_->ChangeSetIndex(work_queue, set);
324 EXPECT_TRUE(work_queue_sets_->IsSetEmpty(set));
325 }
326
TEST_F(WorkQueueSetsTest,IsSetEmpty_Work)327 TEST_F(WorkQueueSetsTest, IsSetEmpty_Work) {
328 size_t set = 2;
329 EXPECT_TRUE(work_queue_sets_->IsSetEmpty(set));
330
331 WorkQueue* work_queue = NewTaskQueue("queue");
332 work_queue->Push(FakeTaskWithEnqueueOrder(1));
333 work_queue_sets_->ChangeSetIndex(work_queue, set);
334 EXPECT_FALSE(work_queue_sets_->IsSetEmpty(set));
335
336 work_queue->PopTaskForTesting();
337 work_queue_sets_->OnPopMinQueueInSet(work_queue);
338 EXPECT_TRUE(work_queue_sets_->IsSetEmpty(set));
339 }
340
TEST_F(WorkQueueSetsTest,BlockQueuesByFence)341 TEST_F(WorkQueueSetsTest, BlockQueuesByFence) {
342 WorkQueue* queue1 = NewTaskQueue("queue1");
343 WorkQueue* queue2 = NewTaskQueue("queue2");
344
345 queue1->Push(FakeTaskWithEnqueueOrder(6));
346 queue2->Push(FakeTaskWithEnqueueOrder(7));
347 queue1->Push(FakeTaskWithEnqueueOrder(8));
348 queue2->Push(FakeTaskWithEnqueueOrder(9));
349
350 size_t set = kHighestPriority;
351
352 EXPECT_EQ(queue1, GetOldestQueueInSet(set));
353
354 queue1->InsertFence(Fence::BlockingFence());
355 EXPECT_EQ(queue2, GetOldestQueueInSet(set));
356 }
357
TEST_F(WorkQueueSetsTest,PushNonNestableTaskToFront)358 TEST_F(WorkQueueSetsTest, PushNonNestableTaskToFront) {
359 WorkQueue* queue1 = NewTaskQueue("queue1");
360 WorkQueue* queue2 = NewTaskQueue("queue2");
361 WorkQueue* queue3 = NewTaskQueue("queue3");
362 queue1->Push(FakeTaskWithEnqueueOrder(6));
363 queue2->Push(FakeTaskWithEnqueueOrder(5));
364 queue3->Push(FakeTaskWithEnqueueOrder(4));
365 size_t set = 4;
366 work_queue_sets_->ChangeSetIndex(queue1, set);
367 work_queue_sets_->ChangeSetIndex(queue2, set);
368 work_queue_sets_->ChangeSetIndex(queue3, set);
369 EXPECT_EQ(queue3, GetOldestQueueInSet(set));
370
371 queue1->PushNonNestableTaskToFront(FakeNonNestableTaskWithEnqueueOrder(2));
372 EXPECT_EQ(queue1, GetOldestQueueInSet(set));
373 }
374
TEST_F(WorkQueueSetsTest,CollectSkippedOverLowerPriorityTasks)375 TEST_F(WorkQueueSetsTest, CollectSkippedOverLowerPriorityTasks) {
376 WorkQueue* queue1 = NewTaskQueue("queue1");
377 WorkQueue* queue2 = NewTaskQueue("queue2");
378 WorkQueue* queue3 = NewTaskQueue("queue3");
379
380 work_queue_sets_->ChangeSetIndex(queue1, 3);
381 work_queue_sets_->ChangeSetIndex(queue2, 2);
382 work_queue_sets_->ChangeSetIndex(queue3, 1);
383
384 queue1->Push(FakeTaskWithEnqueueOrder(1));
385 queue1->Push(FakeTaskWithEnqueueOrder(2));
386 queue2->Push(FakeTaskWithEnqueueOrder(3));
387 queue3->Push(FakeTaskWithEnqueueOrder(4));
388 queue3->Push(FakeTaskWithEnqueueOrder(5));
389 queue2->Push(FakeTaskWithEnqueueOrder(6));
390 queue1->Push(FakeTaskWithEnqueueOrder(7));
391
392 std::vector<const Task*> result;
393 work_queue_sets_->CollectSkippedOverLowerPriorityTasks(queue3, &result);
394
395 ASSERT_EQ(3u, result.size());
396 EXPECT_EQ(3u, result[0]->enqueue_order()); // The order here isn't important.
397 EXPECT_EQ(1u, result[1]->enqueue_order());
398 EXPECT_EQ(2u, result[2]->enqueue_order());
399 }
400
TEST_F(WorkQueueSetsTest,CompareDelayedTasksWithSameEnqueueOrder)401 TEST_F(WorkQueueSetsTest, CompareDelayedTasksWithSameEnqueueOrder) {
402 constexpr int kNumQueues = 3;
403
404 WorkQueue* queues[kNumQueues] = {
405 NewTaskQueue("queue0", WorkQueue::QueueType::kDelayed),
406 NewTaskQueue("queue1", WorkQueue::QueueType::kDelayed),
407 NewTaskQueue("queue2", WorkQueue::QueueType::kDelayed),
408 };
409
410 const EnqueueOrder kEnqueueOrder = EnqueueOrder::FromIntForTesting(5);
411 TaskOrder task_orders[kNumQueues] = {
412 TaskOrder::CreateForTesting(kEnqueueOrder, TimeTicks() + Seconds(1),
413 /*sequence_num=*/4),
414 TaskOrder::CreateForTesting(kEnqueueOrder, TimeTicks() + Seconds(2),
415 /*sequence_num=*/3),
416 TaskOrder::CreateForTesting(kEnqueueOrder, TimeTicks() + Seconds(3),
417 /*sequence_num=*/2),
418 };
419
420 constexpr size_t kSet = kDefaultPriority;
421
422 for (int i = 0; i < kNumQueues; i++) {
423 queues[i]->Push(FakeTaskWithTaskOrder(task_orders[i]));
424 work_queue_sets_->ChangeSetIndex(queues[i], kSet);
425 }
426
427 for (auto* queue : queues) {
428 EXPECT_EQ(queue, GetOldestQueueInSet(kSet));
429 queue->PopTaskForTesting();
430 work_queue_sets_->OnQueuesFrontTaskChanged(queue);
431 }
432 }
433
TEST_F(WorkQueueSetsTest,CompareDelayedTasksWithSameEnqueueOrderAndRunTime)434 TEST_F(WorkQueueSetsTest, CompareDelayedTasksWithSameEnqueueOrderAndRunTime) {
435 constexpr int kNumQueues = 3;
436
437 WorkQueue* queues[kNumQueues] = {
438 NewTaskQueue("queue0", WorkQueue::QueueType::kDelayed),
439 NewTaskQueue("queue1", WorkQueue::QueueType::kDelayed),
440 NewTaskQueue("queue2", WorkQueue::QueueType::kDelayed),
441 };
442
443 const EnqueueOrder kEnqueueOrder = EnqueueOrder::FromIntForTesting(5);
444 constexpr TimeTicks delayed_run_time = TimeTicks() + Seconds(1);
445 TaskOrder task_orders[kNumQueues] = {
446 TaskOrder::CreateForTesting(kEnqueueOrder, delayed_run_time,
447 /*sequence_num=*/2),
448 TaskOrder::CreateForTesting(kEnqueueOrder, delayed_run_time,
449 /*sequence_num=*/3),
450 TaskOrder::CreateForTesting(kEnqueueOrder, delayed_run_time,
451 /*sequence_num=*/4),
452 };
453
454 constexpr size_t kSet = kDefaultPriority;
455
456 for (int i = 0; i < kNumQueues; i++) {
457 queues[i]->Push(FakeTaskWithTaskOrder(task_orders[i]));
458 work_queue_sets_->ChangeSetIndex(queues[i], kSet);
459 }
460
461 for (auto* queue : queues) {
462 EXPECT_EQ(queue, GetOldestQueueInSet(kSet));
463 queue->PopTaskForTesting();
464 work_queue_sets_->OnQueuesFrontTaskChanged(queue);
465 }
466 }
467
TEST_F(WorkQueueSetsTest,CompareDelayedAndImmediateTasks)468 TEST_F(WorkQueueSetsTest, CompareDelayedAndImmediateTasks) {
469 constexpr int kNumQueues = 5;
470 WorkQueue* queues[kNumQueues] = {
471 NewTaskQueue("queue0", WorkQueue::QueueType::kImmediate),
472 NewTaskQueue("queue1", WorkQueue::QueueType::kDelayed),
473 NewTaskQueue("queue2", WorkQueue::QueueType::kDelayed),
474 NewTaskQueue("queue3", WorkQueue::QueueType::kDelayed),
475 NewTaskQueue("queue4", WorkQueue::QueueType::kImmediate),
476 };
477
478 // TaskOrders in increasing order.
479 TaskOrder task_orders[kNumQueues] = {
480 // Immediate.
481 TaskOrder::CreateForTesting(EnqueueOrder::FromIntForTesting(10),
482 TimeTicks(),
483 /*sequence_num=*/6),
484 // Delayed.
485 TaskOrder::CreateForTesting(EnqueueOrder::FromIntForTesting(11),
486 TimeTicks() + Seconds(1),
487 /*sequence_num=*/5),
488 // Delayed, with the same enqueue order as the previous task.
489 TaskOrder::CreateForTesting(EnqueueOrder::FromIntForTesting(11),
490 TimeTicks() + Seconds(2),
491 /*sequence_num=*/4),
492 // Delayed, with the same delayed run time as the previous task but queued
493 // in a subsequent wake-up.
494 TaskOrder::CreateForTesting(EnqueueOrder::FromIntForTesting(12),
495 TimeTicks() + Seconds(2),
496 /*sequence_num=*/3),
497 // Immediate.
498 TaskOrder::CreateForTesting(EnqueueOrder::FromIntForTesting(13),
499 TimeTicks(),
500 /*sequence_num=*/2),
501 };
502
503 constexpr size_t kSet = kDefaultPriority;
504
505 for (int i = kNumQueues - 1; i >= 0; i--) {
506 queues[i]->Push(FakeTaskWithTaskOrder(task_orders[i]));
507 work_queue_sets_->ChangeSetIndex(queues[i], kSet);
508 }
509
510 for (auto* queue : queues) {
511 EXPECT_EQ(queue, GetOldestQueueInSet(kSet));
512 queue->PopTaskForTesting();
513 work_queue_sets_->OnQueuesFrontTaskChanged(queue);
514 }
515 }
516
517 } // namespace internal
518 } // namespace sequence_manager
519 } // namespace base
520