• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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