summaryrefslogtreecommitdiff
path: root/chromium/net/quic/test_task_runner.cc
blob: b35e7b7184fc7eda66b8a1b2b46b33f94f5e56e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/quic/test_task_runner.h"

#include <algorithm>
#include <utility>

#include "base/time/time.h"
#include "net/third_party/quiche/src/quiche/quic/test_tools/mock_clock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net::test {

namespace {

base::TimeTicks NowInTicks(const quic::MockClock& clock) {
  base::TimeTicks ticks;
  return ticks + base::Microseconds(
                     (clock.Now() - quic::QuicTime::Zero()).ToMicroseconds());
}

}  // namespace

TestTaskRunner::TestTaskRunner(quic::MockClock* clock) : clock_(clock) {}

TestTaskRunner::~TestTaskRunner() = default;

bool TestTaskRunner::PostDelayedTask(const base::Location& from_here,
                                     base::OnceClosure task,
                                     base::TimeDelta delay) {
  EXPECT_GE(delay, base::TimeDelta());
  tasks_.emplace_back(from_here, std::move(task), NowInTicks(*clock_), delay,
                      base::TestPendingTask::NESTABLE);
  return true;
}

bool TestTaskRunner::PostNonNestableDelayedTask(const base::Location& from_here,
                                                base::OnceClosure task,
                                                base::TimeDelta delay) {
  return PostDelayedTask(from_here, std::move(task), delay);
}

bool TestTaskRunner::RunsTasksInCurrentSequence() const {
  return true;
}

const std::vector<PostedTask>& TestTaskRunner::GetPostedTasks() const {
  return tasks_;
}

quic::QuicTime::Delta TestTaskRunner::NextPendingTaskDelay() {
  if (tasks_.empty())
    return quic::QuicTime::Delta::Infinite();

  auto next = FindNextTask();
  return quic::QuicTime::Delta::FromMicroseconds(
      (next->GetTimeToRun() - NowInTicks(*clock_)).InMicroseconds());
}

void TestTaskRunner::RunNextTask() {
  auto next = FindNextTask();
  DCHECK(next != tasks_.end());
  clock_->AdvanceTime(quic::QuicTime::Delta::FromMicroseconds(
      (next->GetTimeToRun() - NowInTicks(*clock_)).InMicroseconds()));
  PostedTask task = std::move(*next);
  tasks_.erase(next);
  std::move(task.task).Run();
}

void TestTaskRunner::FastForwardBy(quic::QuicTime::Delta delta) {
  DCHECK_GE(delta, quic::QuicTime::Delta::Zero());

  quic::QuicTime end_timestamp = clock_->Now() + delta;

  while (NextPendingTaskDelay() <= end_timestamp - clock_->Now()) {
    RunNextTask();
  }

  if (clock_->Now() != end_timestamp)
    clock_->AdvanceTime(end_timestamp - clock_->Now());

  while (NextPendingTaskDelay() <= quic::QuicTime::Delta::Zero()) {
    RunNextTask();
  }
  return;
}

void TestTaskRunner::RunUntilIdle() {
  while (!tasks_.empty())
    RunNextTask();
}
namespace {

struct ShouldRunBeforeLessThan {
  bool operator()(const PostedTask& task1, const PostedTask& task2) const {
    return task1.ShouldRunBefore(task2);
  }
};

}  // namespace

std::vector<PostedTask>::iterator TestTaskRunner::FindNextTask() {
  return std::min_element(tasks_.begin(), tasks_.end(),
                          ShouldRunBeforeLessThan());
}

}  // namespace net::test