1 // Copyright 2012 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 "net/quic/test_task_runner.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/time/time.h"
11 #include "net/third_party/quiche/src/quiche/quic/test_tools/mock_clock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace net::test {
15
16 namespace {
17
NowInTicks(const quic::MockClock & clock)18 base::TimeTicks NowInTicks(const quic::MockClock& clock) {
19 base::TimeTicks ticks;
20 return ticks + base::Microseconds(
21 (clock.Now() - quic::QuicTime::Zero()).ToMicroseconds());
22 }
23
24 } // namespace
25
TestTaskRunner(quic::MockClock * clock)26 TestTaskRunner::TestTaskRunner(quic::MockClock* clock) : clock_(clock) {}
27
28 TestTaskRunner::~TestTaskRunner() = default;
29
PostDelayedTask(const base::Location & from_here,base::OnceClosure task,base::TimeDelta delay)30 bool TestTaskRunner::PostDelayedTask(const base::Location& from_here,
31 base::OnceClosure task,
32 base::TimeDelta delay) {
33 EXPECT_GE(delay, base::TimeDelta());
34 tasks_.emplace_back(from_here, std::move(task), NowInTicks(*clock_), delay,
35 base::TestPendingTask::NESTABLE);
36 return true;
37 }
38
PostNonNestableDelayedTask(const base::Location & from_here,base::OnceClosure task,base::TimeDelta delay)39 bool TestTaskRunner::PostNonNestableDelayedTask(const base::Location& from_here,
40 base::OnceClosure task,
41 base::TimeDelta delay) {
42 return PostDelayedTask(from_here, std::move(task), delay);
43 }
44
RunsTasksInCurrentSequence() const45 bool TestTaskRunner::RunsTasksInCurrentSequence() const {
46 return true;
47 }
48
GetPostedTasks() const49 const std::vector<PostedTask>& TestTaskRunner::GetPostedTasks() const {
50 return tasks_;
51 }
52
NextPendingTaskDelay()53 quic::QuicTime::Delta TestTaskRunner::NextPendingTaskDelay() {
54 if (tasks_.empty())
55 return quic::QuicTime::Delta::Infinite();
56
57 auto next = FindNextTask();
58 return quic::QuicTime::Delta::FromMicroseconds(
59 (next->GetTimeToRun() - NowInTicks(*clock_)).InMicroseconds());
60 }
61
RunNextTask()62 void TestTaskRunner::RunNextTask() {
63 auto next = FindNextTask();
64 DCHECK(next != tasks_.end());
65 clock_->AdvanceTime(quic::QuicTime::Delta::FromMicroseconds(
66 (next->GetTimeToRun() - NowInTicks(*clock_)).InMicroseconds()));
67 PostedTask task = std::move(*next);
68 tasks_.erase(next);
69 std::move(task.task).Run();
70 }
71
FastForwardBy(quic::QuicTime::Delta delta)72 void TestTaskRunner::FastForwardBy(quic::QuicTime::Delta delta) {
73 DCHECK_GE(delta, quic::QuicTime::Delta::Zero());
74
75 quic::QuicTime end_timestamp = clock_->Now() + delta;
76
77 while (NextPendingTaskDelay() <= end_timestamp - clock_->Now()) {
78 RunNextTask();
79 }
80
81 if (clock_->Now() != end_timestamp)
82 clock_->AdvanceTime(end_timestamp - clock_->Now());
83
84 while (NextPendingTaskDelay() <= quic::QuicTime::Delta::Zero()) {
85 RunNextTask();
86 }
87 return;
88 }
89
RunUntilIdle()90 void TestTaskRunner::RunUntilIdle() {
91 while (!tasks_.empty())
92 RunNextTask();
93 }
94 namespace {
95
96 struct ShouldRunBeforeLessThan {
operator ()net::test::__anonf98dfd770211::ShouldRunBeforeLessThan97 bool operator()(const PostedTask& task1, const PostedTask& task2) const {
98 return task1.ShouldRunBefore(task2);
99 }
100 };
101
102 } // namespace
103
FindNextTask()104 std::vector<PostedTask>::iterator TestTaskRunner::FindNextTask() {
105 return std::min_element(tasks_.begin(), tasks_.end(),
106 ShouldRunBeforeLessThan());
107 }
108
109 } // namespace net::test
110