blob: a9835e85d0a51c68e5c92bba569f826f4233b17a [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "quic/test_tools/simulator/simulator.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
QUICHE team5be974e2020-12-29 18:35:24 -05007#include "quic/core/crypto/quic_random.h"
8#include "quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05009
10namespace quic {
11namespace simulator {
12
wub76139a52019-12-17 10:55:13 -080013Simulator::Simulator() : Simulator(nullptr) {}
14
15Simulator::Simulator(QuicRandom* random_generator)
16 : random_generator_(random_generator),
QUICHE teama6ef0a62019-03-07 20:34:33 -050017 alarm_factory_(this, "Default Alarm Manager"),
18 run_for_should_stop_(false),
19 enable_random_delays_(false) {
20 run_for_alarm_.reset(
21 alarm_factory_.CreateAlarm(new RunForDelegate(&run_for_should_stop_)));
22}
23
24Simulator::~Simulator() {
25 // Ensure that Actor under run_for_alarm_ is removed before Simulator data
26 // structures are destructed.
27 run_for_alarm_.reset();
28}
29
30Simulator::Clock::Clock() : now_(kStartTime) {}
31
32QuicTime Simulator::Clock::ApproximateNow() const {
33 return now_;
34}
35
36QuicTime Simulator::Clock::Now() const {
37 return now_;
38}
39
40QuicWallTime Simulator::Clock::WallNow() const {
41 return QuicWallTime::FromUNIXMicroseconds(
42 (now_ - QuicTime::Zero()).ToMicroseconds());
43}
44
45void Simulator::AddActor(Actor* actor) {
46 auto emplace_times_result =
47 scheduled_times_.insert(std::make_pair(actor, QuicTime::Infinite()));
48 auto emplace_names_result = actor_names_.insert(actor->name());
49
50 // Ensure that the object was actually placed into the map.
vasilvvf8035162021-02-01 14:49:14 -080051 QUICHE_DCHECK(emplace_times_result.second);
52 QUICHE_DCHECK(emplace_names_result.second);
QUICHE teama6ef0a62019-03-07 20:34:33 -050053}
54
55void Simulator::RemoveActor(Actor* actor) {
56 auto scheduled_time_it = scheduled_times_.find(actor);
57 auto actor_names_it = actor_names_.find(actor->name());
vasilvvf8035162021-02-01 14:49:14 -080058 QUICHE_DCHECK(scheduled_time_it != scheduled_times_.end());
59 QUICHE_DCHECK(actor_names_it != actor_names_.end());
QUICHE teama6ef0a62019-03-07 20:34:33 -050060
61 QuicTime scheduled_time = scheduled_time_it->second;
62 if (scheduled_time != QuicTime::Infinite()) {
63 Unschedule(actor);
64 }
65
66 scheduled_times_.erase(scheduled_time_it);
67 actor_names_.erase(actor_names_it);
68}
69
70void Simulator::Schedule(Actor* actor, QuicTime new_time) {
71 auto scheduled_time_it = scheduled_times_.find(actor);
vasilvvf8035162021-02-01 14:49:14 -080072 QUICHE_DCHECK(scheduled_time_it != scheduled_times_.end());
QUICHE teama6ef0a62019-03-07 20:34:33 -050073 QuicTime scheduled_time = scheduled_time_it->second;
74
75 if (scheduled_time <= new_time) {
76 return;
77 }
78
79 if (scheduled_time != QuicTime::Infinite()) {
80 Unschedule(actor);
81 }
82
83 scheduled_time_it->second = new_time;
84 schedule_.insert(std::make_pair(new_time, actor));
85}
86
87void Simulator::Unschedule(Actor* actor) {
88 auto scheduled_time_it = scheduled_times_.find(actor);
vasilvvf8035162021-02-01 14:49:14 -080089 QUICHE_DCHECK(scheduled_time_it != scheduled_times_.end());
QUICHE teama6ef0a62019-03-07 20:34:33 -050090 QuicTime scheduled_time = scheduled_time_it->second;
91
vasilvvf8035162021-02-01 14:49:14 -080092 QUICHE_DCHECK(scheduled_time != QuicTime::Infinite());
QUICHE teama6ef0a62019-03-07 20:34:33 -050093 auto range = schedule_.equal_range(scheduled_time);
94 for (auto it = range.first; it != range.second; ++it) {
95 if (it->second == actor) {
96 schedule_.erase(it);
97 scheduled_time_it->second = QuicTime::Infinite();
98 return;
99 }
100 }
vasilvvf8035162021-02-01 14:49:14 -0800101 QUICHE_DCHECK(false);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500102}
103
104const QuicClock* Simulator::GetClock() const {
105 return &clock_;
106}
107
108QuicRandom* Simulator::GetRandomGenerator() {
109 if (random_generator_ == nullptr) {
110 random_generator_ = QuicRandom::GetInstance();
111 }
112
113 return random_generator_;
114}
115
116QuicBufferAllocator* Simulator::GetStreamSendBufferAllocator() {
117 return &buffer_allocator_;
118}
119
120QuicAlarmFactory* Simulator::GetAlarmFactory() {
121 return &alarm_factory_;
122}
123
124Simulator::RunForDelegate::RunForDelegate(bool* run_for_should_stop)
125 : run_for_should_stop_(run_for_should_stop) {}
126
127void Simulator::RunForDelegate::OnAlarm() {
128 *run_for_should_stop_ = true;
129}
130
131void Simulator::RunFor(QuicTime::Delta time_span) {
vasilvvf8035162021-02-01 14:49:14 -0800132 QUICHE_DCHECK(!run_for_alarm_->IsSet());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500133
134 // RunFor() ensures that the simulation stops at the exact time specified by
135 // scheduling an alarm at that point and using that alarm to abort the
136 // simulation. An alarm is necessary because otherwise it is possible that
137 // nothing is scheduled at |end_time|, so the simulation will either go
138 // further than requested or stop before reaching |end_time|.
139 const QuicTime end_time = clock_.Now() + time_span;
140 run_for_alarm_->Set(end_time);
141 run_for_should_stop_ = false;
142 bool simulation_result = RunUntil([this]() { return run_for_should_stop_; });
143
vasilvvf8035162021-02-01 14:49:14 -0800144 QUICHE_DCHECK(simulation_result);
145 QUICHE_DCHECK(clock_.Now() == end_time);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500146}
147
148void Simulator::HandleNextScheduledActor() {
149 const auto current_event_it = schedule_.begin();
150 QuicTime event_time = current_event_it->first;
151 Actor* actor = current_event_it->second;
152 QUIC_DVLOG(3) << "At t = " << event_time.ToDebuggingValue() << ", calling "
153 << actor->name();
154
155 Unschedule(actor);
156
157 if (clock_.Now() > event_time) {
QUICHE team407e1c72021-03-16 14:46:23 -0700158 QUIC_BUG(quic_bug_10150_1)
QUICHE teama541a9b2021-03-08 10:43:00 -0800159 << "Error: event registered by [" << actor->name()
160 << "] requires travelling back in time. Current time: "
161 << clock_.Now().ToDebuggingValue()
162 << ", scheduled time: " << event_time.ToDebuggingValue();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500163 }
164 clock_.now_ = event_time;
165
166 actor->Act();
167}
168
169} // namespace simulator
170} // namespace quic