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/wake_up_queue.h"
6
7 #include <memory>
8 #include <optional>
9
10 #include "base/memory/ptr_util.h"
11 #include "base/message_loop/message_pump.h"
12 #include "base/message_loop/message_pump_type.h"
13 #include "base/task/sequence_manager/enqueue_order.h"
14 #include "base/task/sequence_manager/sequence_manager_impl.h"
15 #include "base/task/sequence_manager/task_queue_impl.h"
16 #include "base/test/mock_callback.h"
17 #include "base/test/simple_test_tick_clock.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19
20 using testing::_;
21 using testing::AnyNumber;
22 using testing::Mock;
23
24 namespace base {
25 namespace sequence_manager {
26 namespace internal {
27
28 class TaskQueueImplForTest : public internal::TaskQueueImpl {
29 public:
TaskQueueImplForTest(internal::SequenceManagerImpl * sequence_manager,WakeUpQueue * wake_up_queue,const TaskQueue::Spec & spec)30 TaskQueueImplForTest(internal::SequenceManagerImpl* sequence_manager,
31 WakeUpQueue* wake_up_queue,
32 const TaskQueue::Spec& spec)
33 : TaskQueueImpl(sequence_manager, wake_up_queue, spec) {}
34 ~TaskQueueImplForTest() override = default;
35
36 using TaskQueueImpl::SetNextWakeUp;
37 };
38
39 class MockWakeUpQueue : public WakeUpQueue {
40 public:
MockWakeUpQueue()41 MockWakeUpQueue()
42 : WakeUpQueue(internal::AssociatedThreadId::CreateBound()) {}
43
44 MockWakeUpQueue(const MockWakeUpQueue&) = delete;
45 MockWakeUpQueue& operator=(const MockWakeUpQueue&) = delete;
46 ~MockWakeUpQueue() override = default;
47
48 using WakeUpQueue::MoveReadyDelayedTasksToWorkQueues;
49 using WakeUpQueue::SetNextWakeUpForQueue;
50 using WakeUpQueue::UnregisterQueue;
51
OnNextWakeUpChanged(LazyNow * lazy_now,std::optional<WakeUp> wake_up)52 void OnNextWakeUpChanged(LazyNow* lazy_now,
53 std::optional<WakeUp> wake_up) override {
54 TimeTicks time = wake_up ? wake_up->time : TimeTicks::Max();
55 OnNextWakeUpChanged_TimeTicks(time);
56 }
GetName() const57 const char* GetName() const override { return "Test"; }
UnregisterQueue(internal::TaskQueueImpl * queue)58 void UnregisterQueue(internal::TaskQueueImpl* queue) override {
59 SetNextWakeUpForQueue(queue, nullptr, std::nullopt);
60 }
61
NextScheduledTaskQueue() const62 internal::TaskQueueImpl* NextScheduledTaskQueue() const {
63 if (wake_up_queue_.empty())
64 return nullptr;
65 return wake_up_queue_.top().queue;
66 }
67
NextScheduledRunTime() const68 TimeTicks NextScheduledRunTime() const {
69 if (wake_up_queue_.empty())
70 return TimeTicks::Max();
71 return wake_up_queue_.top().wake_up.time;
72 }
73
74 MOCK_METHOD1(OnNextWakeUpChanged_TimeTicks, void(TimeTicks time));
75 };
76
77 class WakeUpQueueTest : public testing::Test {
78 public:
SetUp()79 void SetUp() final {
80 // A null clock triggers some assertions.
81 tick_clock_.Advance(Milliseconds(1));
82 wake_up_queue_ = std::make_unique<MockWakeUpQueue>();
83 task_queue_ = std::make_unique<TaskQueueImplForTest>(
84 nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
85 }
86
TearDown()87 void TearDown() final {
88 if (task_queue_)
89 task_queue_->UnregisterTaskQueue();
90 }
91
92 std::unique_ptr<MockWakeUpQueue> wake_up_queue_;
93 std::unique_ptr<TaskQueueImplForTest> task_queue_;
94 SimpleTestTickClock tick_clock_;
95 };
96
TEST_F(WakeUpQueueTest,ScheduleWakeUpForQueue)97 TEST_F(WakeUpQueueTest, ScheduleWakeUpForQueue) {
98 TimeTicks now = tick_clock_.NowTicks();
99 TimeDelta delay = Milliseconds(10);
100 TimeTicks delayed_runtime = now + delay;
101 EXPECT_TRUE(wake_up_queue_->empty());
102 EXPECT_CALL(*wake_up_queue_.get(),
103 OnNextWakeUpChanged_TimeTicks(delayed_runtime));
104 LazyNow lazy_now(now);
105 task_queue_->SetNextWakeUp(&lazy_now, WakeUp{delayed_runtime});
106
107 EXPECT_FALSE(wake_up_queue_->empty());
108 EXPECT_EQ(delayed_runtime, wake_up_queue_->NextScheduledRunTime());
109
110 EXPECT_EQ(task_queue_.get(), wake_up_queue_->NextScheduledTaskQueue());
111 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
112
113 EXPECT_CALL(*wake_up_queue_.get(),
114 OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
115 .Times(AnyNumber());
116 }
117
TEST_F(WakeUpQueueTest,ScheduleWakeUpForQueueSupersedesPreviousWakeUp)118 TEST_F(WakeUpQueueTest, ScheduleWakeUpForQueueSupersedesPreviousWakeUp) {
119 TimeTicks now = tick_clock_.NowTicks();
120 TimeDelta delay1 = Milliseconds(10);
121 TimeDelta delay2 = Milliseconds(100);
122 TimeTicks delayed_runtime1 = now + delay1;
123 TimeTicks delayed_runtime2 = now + delay2;
124 EXPECT_CALL(*wake_up_queue_.get(),
125 OnNextWakeUpChanged_TimeTicks(delayed_runtime1));
126 LazyNow lazy_now(now);
127 task_queue_->SetNextWakeUp(&lazy_now, WakeUp{delayed_runtime1});
128
129 EXPECT_EQ(delayed_runtime1, wake_up_queue_->NextScheduledRunTime());
130
131 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
132
133 // Now schedule a later wake_up, which should replace the previously
134 // requested one.
135 EXPECT_CALL(*wake_up_queue_.get(),
136 OnNextWakeUpChanged_TimeTicks(delayed_runtime2));
137 task_queue_->SetNextWakeUp(&lazy_now, WakeUp{delayed_runtime2});
138
139 EXPECT_EQ(delayed_runtime2, wake_up_queue_->NextScheduledRunTime());
140 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
141
142 EXPECT_CALL(*wake_up_queue_.get(),
143 OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
144 .Times(AnyNumber());
145 }
146
TEST_F(WakeUpQueueTest,ScheduleFlexibleNoSoonerWakeUpForQueueSupersedesPreviousWakeUpWithLeeway)147 TEST_F(
148 WakeUpQueueTest,
149 ScheduleFlexibleNoSoonerWakeUpForQueueSupersedesPreviousWakeUpWithLeeway) {
150 TimeTicks now = tick_clock_.NowTicks();
151 TimeDelta delay1 = Milliseconds(10);
152 TimeDelta delay2 = Milliseconds(15);
153 TimeTicks delayed_runtime1 = now + delay1;
154 TimeTicks delayed_runtime2 = now + delay2;
155 EXPECT_CALL(*wake_up_queue_.get(),
156 OnNextWakeUpChanged_TimeTicks(delayed_runtime1));
157 LazyNow lazy_now(now);
158 task_queue_->SetNextWakeUp(
159 &lazy_now,
160 WakeUp{delayed_runtime1, Milliseconds(10), WakeUpResolution::kLow,
161 subtle::DelayPolicy::kFlexibleNoSooner});
162
163 EXPECT_EQ((WakeUp{delayed_runtime1, Milliseconds(10), WakeUpResolution::kLow,
164 subtle::DelayPolicy::kFlexibleNoSooner}),
165 wake_up_queue_->GetNextDelayedWakeUp());
166
167 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
168
169 // Now schedule a later wake_up, which should replace the previously
170 // requested one.
171 EXPECT_CALL(*wake_up_queue_.get(),
172 OnNextWakeUpChanged_TimeTicks(delayed_runtime2));
173 task_queue_->SetNextWakeUp(
174 &lazy_now, WakeUp{delayed_runtime2, TimeDelta(), WakeUpResolution::kLow,
175 subtle::DelayPolicy::kPrecise});
176
177 EXPECT_EQ((WakeUp{delayed_runtime2, TimeDelta(), WakeUpResolution::kLow,
178 subtle::DelayPolicy::kPrecise}),
179 wake_up_queue_->GetNextDelayedWakeUp());
180 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
181
182 EXPECT_CALL(*wake_up_queue_.get(),
183 OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
184 .Times(AnyNumber());
185 }
186
TEST_F(WakeUpQueueTest,ScheduleFlexiblePreferEarlyWakeUpForQueueSupersedesPreviousWakeUp)187 TEST_F(WakeUpQueueTest,
188 ScheduleFlexiblePreferEarlyWakeUpForQueueSupersedesPreviousWakeUp) {
189 TimeTicks now = tick_clock_.NowTicks();
190 TimeDelta delay1 = Milliseconds(10);
191 TimeDelta delay2 = Milliseconds(15);
192 TimeTicks delayed_runtime1 = now + delay1;
193 TimeTicks delayed_runtime2 = now + delay2;
194 EXPECT_CALL(*wake_up_queue_.get(),
195 OnNextWakeUpChanged_TimeTicks(delayed_runtime1));
196 LazyNow lazy_now(now);
197 task_queue_->SetNextWakeUp(
198 &lazy_now, WakeUp{delayed_runtime1, TimeDelta(), WakeUpResolution::kLow,
199 subtle::DelayPolicy::kPrecise});
200
201 EXPECT_EQ((WakeUp{delayed_runtime1, TimeDelta(), WakeUpResolution::kLow,
202 subtle::DelayPolicy::kPrecise}),
203 wake_up_queue_->GetNextDelayedWakeUp());
204
205 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
206
207 // Now schedule a later wake_up, which should replace the previously
208 // requested one.
209 EXPECT_CALL(*wake_up_queue_.get(),
210 OnNextWakeUpChanged_TimeTicks(delayed_runtime2));
211 task_queue_->SetNextWakeUp(
212 &lazy_now,
213 WakeUp{delayed_runtime2, Milliseconds(10), WakeUpResolution::kLow,
214 subtle::DelayPolicy::kFlexiblePreferEarly});
215
216 EXPECT_EQ((WakeUp{delayed_runtime2, Milliseconds(10), WakeUpResolution::kLow,
217 subtle::DelayPolicy::kFlexiblePreferEarly}),
218 wake_up_queue_->GetNextDelayedWakeUp());
219 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
220
221 EXPECT_CALL(*wake_up_queue_.get(),
222 OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
223 .Times(AnyNumber());
224 }
225
TEST_F(WakeUpQueueTest,SetNextDelayedDoWork_OnlyCalledForEarlierTasks)226 TEST_F(WakeUpQueueTest, SetNextDelayedDoWork_OnlyCalledForEarlierTasks) {
227 std::unique_ptr<TaskQueueImplForTest> task_queue2 =
228 std::make_unique<TaskQueueImplForTest>(
229 nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
230
231 std::unique_ptr<TaskQueueImplForTest> task_queue3 =
232 std::make_unique<TaskQueueImplForTest>(
233 nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
234
235 std::unique_ptr<TaskQueueImplForTest> task_queue4 =
236 std::make_unique<TaskQueueImplForTest>(
237 nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
238
239 TimeDelta delay1 = Milliseconds(10);
240 TimeDelta delay2 = Milliseconds(20);
241 TimeDelta delay3 = Milliseconds(30);
242 TimeDelta delay4 = Milliseconds(1);
243
244 // SetNextDelayedDoWork should always be called if there are no other
245 // wake-ups.
246 TimeTicks now = tick_clock_.NowTicks();
247 LazyNow lazy_now(now);
248 EXPECT_CALL(*wake_up_queue_.get(),
249 OnNextWakeUpChanged_TimeTicks(now + delay1));
250 task_queue_->SetNextWakeUp(&lazy_now, WakeUp{now + delay1});
251
252 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
253
254 // SetNextDelayedDoWork should not be called when scheduling later tasks.
255 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_)).Times(0);
256 task_queue2->SetNextWakeUp(&lazy_now, WakeUp{now + delay2});
257 task_queue3->SetNextWakeUp(&lazy_now, WakeUp{now + delay3});
258
259 // SetNextDelayedDoWork should be called when scheduling earlier tasks.
260 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
261 EXPECT_CALL(*wake_up_queue_.get(),
262 OnNextWakeUpChanged_TimeTicks(now + delay4));
263 task_queue4->SetNextWakeUp(&lazy_now, WakeUp{now + delay4});
264
265 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
266
267 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_)).Times(2);
268 task_queue2->UnregisterTaskQueue();
269 task_queue3->UnregisterTaskQueue();
270 task_queue4->UnregisterTaskQueue();
271 }
272
TEST_F(WakeUpQueueTest,UnregisterQueue)273 TEST_F(WakeUpQueueTest, UnregisterQueue) {
274 std::unique_ptr<TaskQueueImplForTest> task_queue2 =
275 std::make_unique<TaskQueueImplForTest>(
276 nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
277 EXPECT_TRUE(wake_up_queue_->empty());
278
279 TimeTicks now = tick_clock_.NowTicks();
280 LazyNow lazy_now(now);
281 TimeTicks wake_up1 = now + Milliseconds(10);
282 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(wake_up1))
283 .Times(1);
284 task_queue_->SetNextWakeUp(&lazy_now, WakeUp{wake_up1});
285 TimeTicks wake_up2 = now + Milliseconds(100);
286 task_queue2->SetNextWakeUp(&lazy_now, WakeUp{wake_up2});
287 EXPECT_FALSE(wake_up_queue_->empty());
288
289 EXPECT_EQ(task_queue_.get(), wake_up_queue_->NextScheduledTaskQueue());
290
291 testing::Mock::VerifyAndClearExpectations(wake_up_queue_.get());
292
293 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(wake_up2))
294 .Times(1);
295
296 wake_up_queue_->UnregisterQueue(task_queue_.get());
297 EXPECT_EQ(task_queue2.get(), wake_up_queue_->NextScheduledTaskQueue());
298
299 task_queue_->UnregisterTaskQueue();
300 task_queue_ = nullptr;
301
302 EXPECT_FALSE(wake_up_queue_->empty());
303 testing::Mock::VerifyAndClearExpectations(wake_up_queue_.get());
304
305 EXPECT_CALL(*wake_up_queue_.get(),
306 OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()))
307 .Times(1);
308
309 wake_up_queue_->UnregisterQueue(task_queue2.get());
310 EXPECT_FALSE(wake_up_queue_->NextScheduledTaskQueue());
311
312 task_queue2->UnregisterTaskQueue();
313 task_queue2 = nullptr;
314 EXPECT_TRUE(wake_up_queue_->empty());
315 }
316
TEST_F(WakeUpQueueTest,MoveReadyDelayedTasksToWorkQueues)317 TEST_F(WakeUpQueueTest, MoveReadyDelayedTasksToWorkQueues) {
318 TimeDelta delay = Milliseconds(50);
319 TimeTicks now = tick_clock_.NowTicks();
320 LazyNow lazy_now_1(now);
321 TimeTicks delayed_runtime = now + delay;
322 EXPECT_CALL(*wake_up_queue_.get(),
323 OnNextWakeUpChanged_TimeTicks(delayed_runtime));
324 task_queue_->SetNextWakeUp(&lazy_now_1, WakeUp{delayed_runtime});
325
326 EXPECT_EQ(delayed_runtime, wake_up_queue_->NextScheduledRunTime());
327
328 wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_1,
329 EnqueueOrder());
330 EXPECT_EQ(delayed_runtime, wake_up_queue_->NextScheduledRunTime());
331
332 EXPECT_CALL(*wake_up_queue_.get(),
333 OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()));
334 tick_clock_.SetNowTicks(delayed_runtime);
335 LazyNow lazy_now_2(&tick_clock_);
336 wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_2,
337 EnqueueOrder());
338 ASSERT_TRUE(wake_up_queue_->NextScheduledRunTime().is_max());
339 }
340
TEST_F(WakeUpQueueTest,MoveReadyDelayedTasksToWorkQueuesWithLeeway)341 TEST_F(WakeUpQueueTest, MoveReadyDelayedTasksToWorkQueuesWithLeeway) {
342 std::unique_ptr<TaskQueueImplForTest> task_queue2 =
343 std::make_unique<TaskQueueImplForTest>(
344 nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
345
346 TimeTicks now = tick_clock_.NowTicks();
347 LazyNow lazy_now_1(now);
348
349 EXPECT_CALL(*wake_up_queue_.get(),
350 OnNextWakeUpChanged_TimeTicks(now + Milliseconds(10)));
351 task_queue2->SetNextWakeUp(&lazy_now_1,
352 WakeUp{now + Milliseconds(10), Milliseconds(4)});
353 EXPECT_CALL(*wake_up_queue_.get(),
354 OnNextWakeUpChanged_TimeTicks(now + Milliseconds(11)));
355 task_queue_->SetNextWakeUp(&lazy_now_1,
356 WakeUp{now + Milliseconds(11), TimeDelta()});
357
358 EXPECT_EQ(now + Milliseconds(11), wake_up_queue_->NextScheduledRunTime());
359
360 wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_1,
361 EnqueueOrder());
362 EXPECT_EQ(now + Milliseconds(11), wake_up_queue_->NextScheduledRunTime());
363
364 tick_clock_.SetNowTicks(now + Milliseconds(10));
365 LazyNow lazy_now_2(&tick_clock_);
366 wake_up_queue_->MoveReadyDelayedTasksToWorkQueues(&lazy_now_2,
367 EnqueueOrder());
368 EXPECT_EQ(now + Milliseconds(11), wake_up_queue_->NextScheduledRunTime());
369
370 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
371 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_))
372 .Times(AnyNumber());
373 // Tidy up.
374 task_queue2->UnregisterTaskQueue();
375 }
376
TEST_F(WakeUpQueueTest,CancelDelayedWork)377 TEST_F(WakeUpQueueTest, CancelDelayedWork) {
378 TimeTicks now = tick_clock_.NowTicks();
379 LazyNow lazy_now(now);
380 TimeTicks run_time = now + Milliseconds(20);
381
382 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(run_time));
383 task_queue_->SetNextWakeUp(&lazy_now, WakeUp{run_time});
384
385 EXPECT_EQ(task_queue_.get(), wake_up_queue_->NextScheduledTaskQueue());
386
387 EXPECT_CALL(*wake_up_queue_.get(),
388 OnNextWakeUpChanged_TimeTicks(TimeTicks::Max()));
389 task_queue_->SetNextWakeUp(&lazy_now, std::nullopt);
390 EXPECT_FALSE(wake_up_queue_->NextScheduledTaskQueue());
391 }
392
TEST_F(WakeUpQueueTest,CancelDelayedWork_TwoQueues)393 TEST_F(WakeUpQueueTest, CancelDelayedWork_TwoQueues) {
394 std::unique_ptr<TaskQueueImplForTest> task_queue2 =
395 std::make_unique<TaskQueueImplForTest>(
396 nullptr, wake_up_queue_.get(), TaskQueue::Spec(QueueName::TEST_TQ));
397
398 TimeTicks now = tick_clock_.NowTicks();
399 LazyNow lazy_now(now);
400 TimeTicks run_time1 = now + Milliseconds(20);
401 TimeTicks run_time2 = now + Milliseconds(40);
402 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(run_time1));
403 task_queue_->SetNextWakeUp(&lazy_now, WakeUp{run_time1});
404 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
405
406 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_)).Times(0);
407 task_queue2->SetNextWakeUp(&lazy_now, WakeUp{run_time2});
408 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
409
410 EXPECT_EQ(task_queue_.get(), wake_up_queue_->NextScheduledTaskQueue());
411
412 EXPECT_EQ(run_time1, wake_up_queue_->NextScheduledRunTime());
413
414 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(run_time2));
415 task_queue_->SetNextWakeUp(&lazy_now, std::nullopt);
416 EXPECT_EQ(task_queue2.get(), wake_up_queue_->NextScheduledTaskQueue());
417
418 EXPECT_EQ(run_time2, wake_up_queue_->NextScheduledRunTime());
419
420 Mock::VerifyAndClearExpectations(wake_up_queue_.get());
421 EXPECT_CALL(*wake_up_queue_.get(), OnNextWakeUpChanged_TimeTicks(_))
422 .Times(AnyNumber());
423
424 // Tidy up.
425 task_queue2->UnregisterTaskQueue();
426 }
427
TEST_F(WakeUpQueueTest,HighResolutionWakeUps)428 TEST_F(WakeUpQueueTest, HighResolutionWakeUps) {
429 TimeTicks now = tick_clock_.NowTicks();
430 LazyNow lazy_now(now);
431 TimeTicks run_time1 = now + Milliseconds(20);
432 TimeTicks run_time2 = now + Milliseconds(40);
433 TaskQueueImplForTest q1(nullptr, wake_up_queue_.get(),
434 TaskQueue::Spec(QueueName::TEST_TQ));
435 TaskQueueImplForTest q2(nullptr, wake_up_queue_.get(),
436 TaskQueue::Spec(QueueName::TEST_TQ));
437
438 // Add two high resolution wake-ups.
439 EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
440 wake_up_queue_->SetNextWakeUpForQueue(
441 &q1, &lazy_now, WakeUp{run_time1, TimeDelta(), WakeUpResolution::kHigh});
442 EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
443 wake_up_queue_->SetNextWakeUpForQueue(
444 &q2, &lazy_now, WakeUp{run_time2, TimeDelta(), WakeUpResolution::kHigh});
445 EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
446
447 // Remove one of the wake-ups.
448 wake_up_queue_->SetNextWakeUpForQueue(&q1, &lazy_now, std::nullopt);
449 EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
450
451 // Remove the second one too.
452 wake_up_queue_->SetNextWakeUpForQueue(&q2, &lazy_now, std::nullopt);
453 EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
454
455 // Change a low resolution wake-up to a high resolution one.
456 wake_up_queue_->SetNextWakeUpForQueue(
457 &q1, &lazy_now, WakeUp{run_time1, TimeDelta(), WakeUpResolution::kLow});
458 EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
459 wake_up_queue_->SetNextWakeUpForQueue(
460 &q1, &lazy_now, WakeUp{run_time1, TimeDelta(), WakeUpResolution::kHigh});
461 EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
462
463 // Move a high resolution wake-up in time.
464 wake_up_queue_->SetNextWakeUpForQueue(
465 &q1, &lazy_now, WakeUp{run_time2, TimeDelta(), WakeUpResolution::kHigh});
466 EXPECT_TRUE(wake_up_queue_->has_pending_high_resolution_tasks());
467
468 // Cancel the wake-up twice.
469 wake_up_queue_->SetNextWakeUpForQueue(&q1, &lazy_now, std::nullopt);
470 wake_up_queue_->SetNextWakeUpForQueue(&q1, &lazy_now, std::nullopt);
471 EXPECT_FALSE(wake_up_queue_->has_pending_high_resolution_tasks());
472
473 // Tidy up.
474 q1.UnregisterTaskQueue();
475 q2.UnregisterTaskQueue();
476 }
477
TEST_F(WakeUpQueueTest,SetNextWakeUpForQueueInThePast)478 TEST_F(WakeUpQueueTest, SetNextWakeUpForQueueInThePast) {
479 constexpr auto kType = MessagePumpType::DEFAULT;
480 constexpr auto kDelay = Milliseconds(20);
481 constexpr TaskQueue::QueuePriority kHighestPriority = 0;
482 constexpr TaskQueue::QueuePriority kDefaultPriority = 1;
483 constexpr TaskQueue::QueuePriority kLowestPriority = 2;
484 constexpr TaskQueue::QueuePriority kPriorityCount = 3;
485 auto sequence_manager = sequence_manager::CreateUnboundSequenceManager(
486 SequenceManager::Settings::Builder()
487 .SetMessagePumpType(kType)
488 .SetTickClock(&tick_clock_)
489 .SetPrioritySettings(SequenceManager::PrioritySettings(
490 kPriorityCount, kDefaultPriority))
491 .Build());
492 sequence_manager->BindToMessagePump(MessagePump::Create(kType));
493 auto high_prio_queue =
494 sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST_TQ));
495 high_prio_queue->SetQueuePriority(kHighestPriority);
496 auto high_prio_runner = high_prio_queue->CreateTaskRunner(kTaskTypeNone);
497 auto low_prio_queue =
498 sequence_manager->CreateTaskQueue(TaskQueue::Spec(QueueName::TEST2_TQ));
499 low_prio_queue->SetQueuePriority(kLowestPriority);
500 auto low_prio_runner = low_prio_queue->CreateTaskRunner(kTaskTypeNone);
501 sequence_manager->SetDefaultTaskRunner(high_prio_runner);
502 base::MockCallback<base::OnceCallback<void()>> task_1, task_2;
503
504 testing::Sequence s;
505 // Expect task_2 to run after task_1
506 EXPECT_CALL(task_1, Run);
507 EXPECT_CALL(task_2, Run);
508 // Schedule high and low priority tasks in such a way that clock.Now() will be
509 // way into the future by the time the low prio task run time is used to setup
510 // a wake up.
511 low_prio_runner->PostDelayedTask(FROM_HERE, task_2.Get(), kDelay);
512 high_prio_runner->PostDelayedTask(FROM_HERE, task_1.Get(), kDelay * 2);
513 high_prio_runner->PostTask(
514 FROM_HERE, BindOnce([](SimpleTestTickClock* clock,
515 TimeDelta delay) { clock->Advance(delay); },
516 base::Unretained(&tick_clock_), kDelay * 2));
517 RunLoop().RunUntilIdle();
518 }
519
520 } // namespace internal
521 } // namespace sequence_manager
522 } // namespace base
523