| // 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 "net/third_party/quic/test_tools/mock_clock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace net { |
| namespace test { |
| |
| namespace { |
| |
| base::TimeTicks NowInTicks(const quic::MockClock& clock) { |
| base::TimeTicks ticks; |
| return ticks + base::TimeDelta::FromMicroseconds( |
| (clock.Now() - quic::QuicTime::Zero()).ToMicroseconds()); |
| } |
| |
| } // namespace |
| |
| TestTaskRunner::TestTaskRunner(quic::MockClock* clock) : clock_(clock) {} |
| |
| TestTaskRunner::~TestTaskRunner() {} |
| |
| bool TestTaskRunner::PostDelayedTask(const base::Location& from_here, |
| base::OnceClosure task, |
| base::TimeDelta delay) { |
| EXPECT_GE(delay, base::TimeDelta()); |
| tasks_.push_back(PostedTask(from_here, std::move(task), NowInTicks(*clock_), |
| delay, base::TestPendingTask::NESTABLE)); |
| return false; |
| } |
| |
| 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 test |
| } // namespace net |