blob: 06ef4b235b0081a63e122776f7f48868286d0743 [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
5#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
6
bnc463f2352019-10-10 04:49:34 -07007#include <utility>
8
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
10#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050011#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
12#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
13#include "net/third_party/quiche/src/quic/test_tools/simulator/alarm_factory.h"
14#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
15#include "net/third_party/quiche/src/quic/test_tools/simulator/packet_filter.h"
16#include "net/third_party/quiche/src/quic/test_tools/simulator/queue.h"
17#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
18#include "net/third_party/quiche/src/quic/test_tools/simulator/traffic_policer.h"
19
20using testing::_;
21using testing::Return;
22using testing::StrictMock;
23
24namespace quic {
25namespace simulator {
26
27// A simple counter that increments its value by 1 every specified period.
28class Counter : public Actor {
29 public:
vasilvvc48c8712019-03-11 13:38:16 -070030 Counter(Simulator* simulator, std::string name, QuicTime::Delta period)
QUICHE teama6ef0a62019-03-07 20:34:33 -050031 : Actor(simulator, name), value_(-1), period_(period) {
32 Schedule(clock_->Now());
33 }
34 ~Counter() override {}
35
36 inline int get_value() const { return value_; }
37
38 void Act() override {
39 ++value_;
40 QUIC_DVLOG(1) << name_ << " has value " << value_ << " at time "
41 << clock_->Now().ToDebuggingValue();
42 Schedule(clock_->Now() + period_);
43 }
44
45 private:
46 int value_;
47 QuicTime::Delta period_;
48};
49
50class SimulatorTest : public QuicTest {};
51
52// Test that the basic event handling works, and that Actors can be created and
53// destroyed mid-simulation.
54TEST_F(SimulatorTest, Counters) {
55 Simulator simulator;
56 for (int i = 0; i < 2; ++i) {
57 Counter fast_counter(&simulator, "fast_counter",
58 QuicTime::Delta::FromSeconds(3));
59 Counter slow_counter(&simulator, "slow_counter",
60 QuicTime::Delta::FromSeconds(10));
61
62 simulator.RunUntil(
63 [&slow_counter]() { return slow_counter.get_value() >= 10; });
64
65 EXPECT_EQ(10, slow_counter.get_value());
66 EXPECT_EQ(10 * 10 / 3, fast_counter.get_value());
67 }
68}
69
70// A port which counts the number of packets received on it, both total and
71// per-destination.
72class CounterPort : public UnconstrainedPortInterface {
73 public:
74 CounterPort() { Reset(); }
75 ~CounterPort() override {}
76
77 inline QuicByteCount bytes() const { return bytes_; }
78 inline QuicPacketCount packets() const { return packets_; }
79
80 void AcceptPacket(std::unique_ptr<Packet> packet) override {
81 bytes_ += packet->size;
82 packets_ += 1;
83
84 per_destination_packet_counter_[packet->destination] += 1;
85 }
86
87 void Reset() {
88 bytes_ = 0;
89 packets_ = 0;
90 per_destination_packet_counter_.clear();
91 }
92
vasilvvc48c8712019-03-11 13:38:16 -070093 QuicPacketCount CountPacketsForDestination(std::string destination) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -050094 auto result_it = per_destination_packet_counter_.find(destination);
95 if (result_it == per_destination_packet_counter_.cend()) {
96 return 0;
97 }
98 return result_it->second;
99 }
100
101 private:
102 QuicByteCount bytes_;
103 QuicPacketCount packets_;
104
vasilvvc48c8712019-03-11 13:38:16 -0700105 QuicUnorderedMap<std::string, QuicPacketCount>
106 per_destination_packet_counter_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500107};
108
109// Sends the packet to the specified destination at the uplink rate. Provides a
110// CounterPort as an Rx interface.
111class LinkSaturator : public Endpoint {
112 public:
113 LinkSaturator(Simulator* simulator,
vasilvvc48c8712019-03-11 13:38:16 -0700114 std::string name,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500115 QuicByteCount packet_size,
vasilvvc48c8712019-03-11 13:38:16 -0700116 std::string destination)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500117 : Endpoint(simulator, name),
118 packet_size_(packet_size),
119 destination_(std::move(destination)),
120 bytes_transmitted_(0),
121 packets_transmitted_(0) {
122 Schedule(clock_->Now());
123 }
124
125 void Act() override {
126 if (tx_port_->TimeUntilAvailable().IsZero()) {
vasilvv0fc587f2019-09-06 13:33:08 -0700127 auto packet = std::make_unique<Packet>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128 packet->source = name_;
129 packet->destination = destination_;
130 packet->tx_timestamp = clock_->Now();
131 packet->size = packet_size_;
132
133 tx_port_->AcceptPacket(std::move(packet));
134
135 bytes_transmitted_ += packet_size_;
136 packets_transmitted_ += 1;
137 }
138
139 Schedule(clock_->Now() + tx_port_->TimeUntilAvailable());
140 }
141
142 UnconstrainedPortInterface* GetRxPort() override {
143 return static_cast<UnconstrainedPortInterface*>(&rx_port_);
144 }
145
146 void SetTxPort(ConstrainedPortInterface* port) override { tx_port_ = port; }
147
148 CounterPort* counter() { return &rx_port_; }
149
150 inline QuicByteCount bytes_transmitted() const { return bytes_transmitted_; }
151 inline QuicPacketCount packets_transmitted() const {
152 return packets_transmitted_;
153 }
154
155 void Pause() { Unschedule(); }
156 void Resume() { Schedule(clock_->Now()); }
157
158 private:
159 QuicByteCount packet_size_;
vasilvvc48c8712019-03-11 13:38:16 -0700160 std::string destination_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500161
162 ConstrainedPortInterface* tx_port_;
163 CounterPort rx_port_;
164
165 QuicByteCount bytes_transmitted_;
166 QuicPacketCount packets_transmitted_;
167};
168
169// Saturate a symmetric link and verify that the number of packets sent and
170// received is correct.
171TEST_F(SimulatorTest, DirectLinkSaturation) {
172 Simulator simulator;
173 LinkSaturator saturator_a(&simulator, "Saturator A", 1000, "Saturator B");
174 LinkSaturator saturator_b(&simulator, "Saturator B", 100, "Saturator A");
175 SymmetricLink link(&saturator_a, &saturator_b,
176 QuicBandwidth::FromKBytesPerSecond(1000),
177 QuicTime::Delta::FromMilliseconds(100) +
178 QuicTime::Delta::FromMicroseconds(1));
179
180 const QuicTime start_time = simulator.GetClock()->Now();
181 const QuicTime after_first_50_ms =
182 start_time + QuicTime::Delta::FromMilliseconds(50);
183 simulator.RunUntil([&simulator, after_first_50_ms]() {
184 return simulator.GetClock()->Now() >= after_first_50_ms;
185 });
186 EXPECT_LE(1000u * 50u, saturator_a.bytes_transmitted());
187 EXPECT_GE(1000u * 51u, saturator_a.bytes_transmitted());
188 EXPECT_LE(1000u * 50u, saturator_b.bytes_transmitted());
189 EXPECT_GE(1000u * 51u, saturator_b.bytes_transmitted());
190 EXPECT_LE(50u, saturator_a.packets_transmitted());
191 EXPECT_GE(51u, saturator_a.packets_transmitted());
192 EXPECT_LE(500u, saturator_b.packets_transmitted());
193 EXPECT_GE(501u, saturator_b.packets_transmitted());
194 EXPECT_EQ(0u, saturator_a.counter()->bytes());
195 EXPECT_EQ(0u, saturator_b.counter()->bytes());
196
197 simulator.RunUntil([&saturator_a, &saturator_b]() {
198 if (saturator_a.counter()->packets() > 1000 ||
199 saturator_b.counter()->packets() > 100) {
200 ADD_FAILURE() << "The simulation did not arrive at the expected "
201 "termination contidition. Saturator A counter: "
202 << saturator_a.counter()->packets()
203 << ", saturator B counter: "
204 << saturator_b.counter()->packets();
205 return true;
206 }
207
208 return saturator_a.counter()->packets() == 1000 &&
209 saturator_b.counter()->packets() == 100;
210 });
211 EXPECT_EQ(201u, saturator_a.packets_transmitted());
212 EXPECT_EQ(2001u, saturator_b.packets_transmitted());
213 EXPECT_EQ(201u * 1000, saturator_a.bytes_transmitted());
214 EXPECT_EQ(2001u * 100, saturator_b.bytes_transmitted());
215
216 EXPECT_EQ(1000u,
217 saturator_a.counter()->CountPacketsForDestination("Saturator A"));
218 EXPECT_EQ(100u,
219 saturator_b.counter()->CountPacketsForDestination("Saturator B"));
220 EXPECT_EQ(0u,
221 saturator_a.counter()->CountPacketsForDestination("Saturator B"));
222 EXPECT_EQ(0u,
223 saturator_b.counter()->CountPacketsForDestination("Saturator A"));
224
225 const QuicTime end_time = simulator.GetClock()->Now();
226 const QuicBandwidth observed_bandwidth = QuicBandwidth::FromBytesAndTimeDelta(
227 saturator_a.bytes_transmitted(), end_time - start_time);
wub9343d702019-05-02 17:12:56 -0700228 EXPECT_APPROX_EQ(link.bandwidth(), observed_bandwidth, 0.01f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500229}
230
231// Accepts packets and stores them internally.
232class PacketAcceptor : public ConstrainedPortInterface {
233 public:
234 void AcceptPacket(std::unique_ptr<Packet> packet) override {
235 packets_.emplace_back(std::move(packet));
236 }
237
238 QuicTime::Delta TimeUntilAvailable() override {
239 return QuicTime::Delta::Zero();
240 }
241
242 std::vector<std::unique_ptr<Packet>>* packets() { return &packets_; }
243
244 private:
245 std::vector<std::unique_ptr<Packet>> packets_;
246};
247
248// Ensure the queue behaves correctly with accepting packets.
249TEST_F(SimulatorTest, Queue) {
250 Simulator simulator;
251 Queue queue(&simulator, "Queue", 1000);
252 PacketAcceptor acceptor;
253 queue.set_tx_port(&acceptor);
254
255 EXPECT_EQ(0u, queue.bytes_queued());
256 EXPECT_EQ(0u, queue.packets_queued());
257 EXPECT_EQ(0u, acceptor.packets()->size());
258
vasilvv0fc587f2019-09-06 13:33:08 -0700259 auto first_packet = std::make_unique<Packet>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500260 first_packet->size = 600;
261 queue.AcceptPacket(std::move(first_packet));
262 EXPECT_EQ(600u, queue.bytes_queued());
263 EXPECT_EQ(1u, queue.packets_queued());
264 EXPECT_EQ(0u, acceptor.packets()->size());
265
266 // The second packet does not fit and is dropped.
vasilvv0fc587f2019-09-06 13:33:08 -0700267 auto second_packet = std::make_unique<Packet>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268 second_packet->size = 500;
269 queue.AcceptPacket(std::move(second_packet));
270 EXPECT_EQ(600u, queue.bytes_queued());
271 EXPECT_EQ(1u, queue.packets_queued());
272 EXPECT_EQ(0u, acceptor.packets()->size());
273
vasilvv0fc587f2019-09-06 13:33:08 -0700274 auto third_packet = std::make_unique<Packet>();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500275 third_packet->size = 400;
276 queue.AcceptPacket(std::move(third_packet));
277 EXPECT_EQ(1000u, queue.bytes_queued());
278 EXPECT_EQ(2u, queue.packets_queued());
279 EXPECT_EQ(0u, acceptor.packets()->size());
280
281 // Run until there is nothing scheduled, so that the queue can deplete.
282 simulator.RunUntil([]() { return false; });
283 EXPECT_EQ(0u, queue.bytes_queued());
284 EXPECT_EQ(0u, queue.packets_queued());
285 ASSERT_EQ(2u, acceptor.packets()->size());
286 EXPECT_EQ(600u, acceptor.packets()->at(0)->size);
287 EXPECT_EQ(400u, acceptor.packets()->at(1)->size);
288}
289
290// Simulate a situation where the bottleneck link is 10 times slower than the
291// uplink, and they are separated by a queue.
292TEST_F(SimulatorTest, QueueBottleneck) {
293 const QuicBandwidth local_bandwidth =
294 QuicBandwidth::FromKBytesPerSecond(1000);
295 const QuicBandwidth bottleneck_bandwidth = 0.1f * local_bandwidth;
296 const QuicTime::Delta local_propagation_delay =
297 QuicTime::Delta::FromMilliseconds(1);
298 const QuicTime::Delta bottleneck_propagation_delay =
299 QuicTime::Delta::FromMilliseconds(20);
300 const QuicByteCount bdp =
301 bottleneck_bandwidth *
302 (local_propagation_delay + bottleneck_propagation_delay);
303
304 Simulator simulator;
305 LinkSaturator saturator(&simulator, "Saturator", 1000, "Counter");
306 ASSERT_GE(bdp, 1000u);
307 Queue queue(&simulator, "Queue", bdp);
308 CounterPort counter;
309
310 OneWayLink local_link(&simulator, "Local link", &queue, local_bandwidth,
311 local_propagation_delay);
312 OneWayLink bottleneck_link(&simulator, "Bottleneck link", &counter,
313 bottleneck_bandwidth,
314 bottleneck_propagation_delay);
315 saturator.SetTxPort(&local_link);
316 queue.set_tx_port(&bottleneck_link);
317
318 static const QuicPacketCount packets_received = 1000;
319 simulator.RunUntil(
320 [&counter]() { return counter.packets() == packets_received; });
321 const double loss_ratio = 1 - static_cast<double>(packets_received) /
322 saturator.packets_transmitted();
323 EXPECT_NEAR(loss_ratio, 0.9, 0.001);
324}
325
326// Verify that the queue of exactly one packet allows the transmission to
327// actually go through.
328TEST_F(SimulatorTest, OnePacketQueue) {
329 const QuicBandwidth local_bandwidth =
330 QuicBandwidth::FromKBytesPerSecond(1000);
331 const QuicBandwidth bottleneck_bandwidth = 0.1f * local_bandwidth;
332 const QuicTime::Delta local_propagation_delay =
333 QuicTime::Delta::FromMilliseconds(1);
334 const QuicTime::Delta bottleneck_propagation_delay =
335 QuicTime::Delta::FromMilliseconds(20);
336
337 Simulator simulator;
338 LinkSaturator saturator(&simulator, "Saturator", 1000, "Counter");
339 Queue queue(&simulator, "Queue", 1000);
340 CounterPort counter;
341
342 OneWayLink local_link(&simulator, "Local link", &queue, local_bandwidth,
343 local_propagation_delay);
344 OneWayLink bottleneck_link(&simulator, "Bottleneck link", &counter,
345 bottleneck_bandwidth,
346 bottleneck_propagation_delay);
347 saturator.SetTxPort(&local_link);
348 queue.set_tx_port(&bottleneck_link);
349
350 static const QuicPacketCount packets_received = 10;
351 // The deadline here is to prevent this tests from looping infinitely in case
352 // the packets never reach the receiver.
353 const QuicTime deadline =
354 simulator.GetClock()->Now() + QuicTime::Delta::FromSeconds(10);
355 simulator.RunUntil([&simulator, &counter, deadline]() {
356 return counter.packets() == packets_received ||
357 simulator.GetClock()->Now() > deadline;
358 });
359 ASSERT_EQ(packets_received, counter.packets());
360}
361
362// Simulate a network where three endpoints are connected to a switch and they
363// are sending traffic in circle (1 -> 2, 2 -> 3, 3 -> 1).
364TEST_F(SimulatorTest, SwitchedNetwork) {
365 const QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(10000);
366 const QuicTime::Delta base_propagation_delay =
367 QuicTime::Delta::FromMilliseconds(50);
368
369 Simulator simulator;
370 LinkSaturator saturator1(&simulator, "Saturator 1", 1000, "Saturator 2");
371 LinkSaturator saturator2(&simulator, "Saturator 2", 1000, "Saturator 3");
372 LinkSaturator saturator3(&simulator, "Saturator 3", 1000, "Saturator 1");
373 Switch network_switch(&simulator, "Switch", 8,
374 bandwidth * base_propagation_delay * 10);
375
376 // For determinicity, make it so that the first packet will arrive from
377 // Saturator 1, then from Saturator 2, and then from Saturator 3.
378 SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
379 base_propagation_delay);
380 SymmetricLink link2(&saturator2, network_switch.port(2), bandwidth,
381 base_propagation_delay * 2);
382 SymmetricLink link3(&saturator3, network_switch.port(3), bandwidth,
383 base_propagation_delay * 3);
384
385 const QuicTime start_time = simulator.GetClock()->Now();
386 static const QuicPacketCount bytes_received = 64 * 1000;
387 simulator.RunUntil([&saturator1]() {
388 return saturator1.counter()->bytes() >= bytes_received;
389 });
390 const QuicTime end_time = simulator.GetClock()->Now();
391
392 const QuicBandwidth observed_bandwidth = QuicBandwidth::FromBytesAndTimeDelta(
393 bytes_received, end_time - start_time);
394 const double bandwidth_ratio =
395 static_cast<double>(observed_bandwidth.ToBitsPerSecond()) /
396 bandwidth.ToBitsPerSecond();
397 EXPECT_NEAR(1, bandwidth_ratio, 0.1);
398
399 const double normalized_received_packets_for_saturator_2 =
400 static_cast<double>(saturator2.counter()->packets()) /
401 saturator1.counter()->packets();
402 const double normalized_received_packets_for_saturator_3 =
403 static_cast<double>(saturator3.counter()->packets()) /
404 saturator1.counter()->packets();
405 EXPECT_NEAR(1, normalized_received_packets_for_saturator_2, 0.1);
406 EXPECT_NEAR(1, normalized_received_packets_for_saturator_3, 0.1);
407
408 // Since Saturator 1 has its packet arrive first into the switch, switch will
409 // always know how to route traffic to it.
410 EXPECT_EQ(0u,
411 saturator2.counter()->CountPacketsForDestination("Saturator 1"));
412 EXPECT_EQ(0u,
413 saturator3.counter()->CountPacketsForDestination("Saturator 1"));
414
415 // Packets from the other saturators will be broadcast at least once.
416 EXPECT_EQ(1u,
417 saturator1.counter()->CountPacketsForDestination("Saturator 2"));
418 EXPECT_EQ(1u,
419 saturator3.counter()->CountPacketsForDestination("Saturator 2"));
420 EXPECT_EQ(1u,
421 saturator1.counter()->CountPacketsForDestination("Saturator 3"));
422 EXPECT_EQ(1u,
423 saturator2.counter()->CountPacketsForDestination("Saturator 3"));
424}
425
426// Toggle an alarm on and off at the specified interval. Assumes that alarm is
427// initially set and unsets it almost immediately after the object is
428// instantiated.
429class AlarmToggler : public Actor {
430 public:
431 AlarmToggler(Simulator* simulator,
vasilvvc48c8712019-03-11 13:38:16 -0700432 std::string name,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500433 QuicAlarm* alarm,
434 QuicTime::Delta interval)
435 : Actor(simulator, name),
436 alarm_(alarm),
437 interval_(interval),
438 deadline_(alarm->deadline()),
439 times_set_(0),
440 times_cancelled_(0) {
441 EXPECT_TRUE(alarm->IsSet());
442 EXPECT_GE(alarm->deadline(), clock_->Now());
443 Schedule(clock_->Now());
444 }
445
446 void Act() override {
447 if (deadline_ <= clock_->Now()) {
448 return;
449 }
450
451 if (alarm_->IsSet()) {
452 alarm_->Cancel();
453 times_cancelled_++;
454 } else {
455 alarm_->Set(deadline_);
456 times_set_++;
457 }
458
459 Schedule(clock_->Now() + interval_);
460 }
461
462 inline int times_set() { return times_set_; }
463 inline int times_cancelled() { return times_cancelled_; }
464
465 private:
466 QuicAlarm* alarm_;
467 QuicTime::Delta interval_;
468 QuicTime deadline_;
469
470 // Counts the number of times the alarm was set.
471 int times_set_;
472 // Counts the number of times the alarm was cancelled.
473 int times_cancelled_;
474};
475
476// Counts the number of times an alarm has fired.
477class CounterDelegate : public QuicAlarm::Delegate {
478 public:
479 explicit CounterDelegate(size_t* counter) : counter_(counter) {}
480
481 void OnAlarm() override { *counter_ += 1; }
482
483 private:
484 size_t* counter_;
485};
486
487// Verifies that the alarms work correctly, even when they are repeatedly
488// toggled.
489TEST_F(SimulatorTest, Alarms) {
490 Simulator simulator;
491 QuicAlarmFactory* alarm_factory = simulator.GetAlarmFactory();
492
493 size_t fast_alarm_counter = 0;
494 size_t slow_alarm_counter = 0;
495 std::unique_ptr<QuicAlarm> alarm_fast(
496 alarm_factory->CreateAlarm(new CounterDelegate(&fast_alarm_counter)));
497 std::unique_ptr<QuicAlarm> alarm_slow(
498 alarm_factory->CreateAlarm(new CounterDelegate(&slow_alarm_counter)));
499
500 const QuicTime start_time = simulator.GetClock()->Now();
501 alarm_fast->Set(start_time + QuicTime::Delta::FromMilliseconds(100));
502 alarm_slow->Set(start_time + QuicTime::Delta::FromMilliseconds(750));
503 AlarmToggler toggler(&simulator, "Toggler", alarm_slow.get(),
504 QuicTime::Delta::FromMilliseconds(100));
505
506 const QuicTime end_time =
507 start_time + QuicTime::Delta::FromMilliseconds(1000);
508 EXPECT_FALSE(simulator.RunUntil([&simulator, end_time]() {
509 return simulator.GetClock()->Now() >= end_time;
510 }));
511 EXPECT_EQ(1u, slow_alarm_counter);
512 EXPECT_EQ(1u, fast_alarm_counter);
513
514 EXPECT_EQ(4, toggler.times_set());
515 EXPECT_EQ(4, toggler.times_cancelled());
516}
517
518// Verifies that a cancelled alarm is never fired.
519TEST_F(SimulatorTest, AlarmCancelling) {
520 Simulator simulator;
521 QuicAlarmFactory* alarm_factory = simulator.GetAlarmFactory();
522
523 size_t alarm_counter = 0;
524 std::unique_ptr<QuicAlarm> alarm(
525 alarm_factory->CreateAlarm(new CounterDelegate(&alarm_counter)));
526
527 const QuicTime start_time = simulator.GetClock()->Now();
528 const QuicTime alarm_at = start_time + QuicTime::Delta::FromMilliseconds(300);
529 const QuicTime end_time = start_time + QuicTime::Delta::FromMilliseconds(400);
530
531 alarm->Set(alarm_at);
532 alarm->Cancel();
533 EXPECT_FALSE(alarm->IsSet());
534
535 EXPECT_FALSE(simulator.RunUntil([&simulator, end_time]() {
536 return simulator.GetClock()->Now() >= end_time;
537 }));
538
539 EXPECT_FALSE(alarm->IsSet());
540 EXPECT_EQ(0u, alarm_counter);
541}
542
543// Verifies that alarms can be scheduled into the past.
544TEST_F(SimulatorTest, AlarmInPast) {
545 Simulator simulator;
546 QuicAlarmFactory* alarm_factory = simulator.GetAlarmFactory();
547
548 size_t alarm_counter = 0;
549 std::unique_ptr<QuicAlarm> alarm(
550 alarm_factory->CreateAlarm(new CounterDelegate(&alarm_counter)));
551
552 const QuicTime start_time = simulator.GetClock()->Now();
553 simulator.RunFor(QuicTime::Delta::FromMilliseconds(400));
554
555 alarm->Set(start_time);
556 simulator.RunFor(QuicTime::Delta::FromMilliseconds(1));
557 EXPECT_FALSE(alarm->IsSet());
558 EXPECT_EQ(1u, alarm_counter);
559}
560
561// Tests Simulator::RunUntilOrTimeout() interface.
562TEST_F(SimulatorTest, RunUntilOrTimeout) {
563 Simulator simulator;
564 bool simulation_result;
565
566 // Count the number of seconds since the beginning of the simulation.
567 Counter counter(&simulator, "counter", QuicTime::Delta::FromSeconds(1));
568
569 // Ensure that the counter reaches the value of 10 given a 20 second deadline.
570 simulation_result = simulator.RunUntilOrTimeout(
571 [&counter]() { return counter.get_value() == 10; },
572 QuicTime::Delta::FromSeconds(20));
573 ASSERT_TRUE(simulation_result);
574
575 // Ensure that the counter will not reach the value of 100 given that the
576 // starting value is 10 and the deadline is 20 seconds.
577 simulation_result = simulator.RunUntilOrTimeout(
578 [&counter]() { return counter.get_value() == 100; },
579 QuicTime::Delta::FromSeconds(20));
580 ASSERT_FALSE(simulation_result);
581}
582
583// Tests Simulator::RunFor() interface.
584TEST_F(SimulatorTest, RunFor) {
585 Simulator simulator;
586
587 Counter counter(&simulator, "counter", QuicTime::Delta::FromSeconds(3));
588
589 simulator.RunFor(QuicTime::Delta::FromSeconds(100));
590
591 EXPECT_EQ(33, counter.get_value());
592}
593
594class MockPacketFilter : public PacketFilter {
595 public:
vasilvvc48c8712019-03-11 13:38:16 -0700596 MockPacketFilter(Simulator* simulator, std::string name, Endpoint* endpoint)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500597 : PacketFilter(simulator, name, endpoint) {}
598 MOCK_METHOD1(FilterPacket, bool(const Packet&));
599};
600
601// Set up two trivial packet filters, one allowing any packets, and one dropping
602// all of them.
603TEST_F(SimulatorTest, PacketFilter) {
604 const QuicBandwidth bandwidth =
605 QuicBandwidth::FromBytesPerSecond(1024 * 1024);
606 const QuicTime::Delta base_propagation_delay =
607 QuicTime::Delta::FromMilliseconds(5);
608
609 Simulator simulator;
610 LinkSaturator saturator_a(&simulator, "Saturator A", 1000, "Saturator B");
611 LinkSaturator saturator_b(&simulator, "Saturator B", 1000, "Saturator A");
612
613 // Attach packets to the switch to create a delay between the point at which
614 // the packet is generated and the point at which it is filtered. Note that
615 // if the saturators were connected directly, the link would be always
616 // available for the endpoint which has all of its packets dropped, resulting
617 // in saturator looping infinitely.
618 Switch network_switch(&simulator, "Switch", 8,
619 bandwidth * base_propagation_delay * 10);
620 StrictMock<MockPacketFilter> a_to_b_filter(&simulator, "A -> B filter",
621 network_switch.port(1));
622 StrictMock<MockPacketFilter> b_to_a_filter(&simulator, "B -> A filter",
623 network_switch.port(2));
624 SymmetricLink link_a(&a_to_b_filter, &saturator_b, bandwidth,
625 base_propagation_delay);
626 SymmetricLink link_b(&b_to_a_filter, &saturator_a, bandwidth,
627 base_propagation_delay);
628
629 // Allow packets from A to B, but not from B to A.
630 EXPECT_CALL(a_to_b_filter, FilterPacket(_)).WillRepeatedly(Return(true));
631 EXPECT_CALL(b_to_a_filter, FilterPacket(_)).WillRepeatedly(Return(false));
632
633 // Run the simulation for a while, and expect that only B will receive any
634 // packets.
635 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
636 EXPECT_GE(saturator_b.counter()->packets(), 1u);
637 EXPECT_EQ(saturator_a.counter()->packets(), 0u);
638}
639
640// Set up a traffic policer in one direction that throttles at 25% of link
641// bandwidth, and put two link saturators at each endpoint.
642TEST_F(SimulatorTest, TrafficPolicer) {
643 const QuicBandwidth bandwidth =
644 QuicBandwidth::FromBytesPerSecond(1024 * 1024);
645 const QuicTime::Delta base_propagation_delay =
646 QuicTime::Delta::FromMilliseconds(5);
647 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
648
649 Simulator simulator;
650 LinkSaturator saturator1(&simulator, "Saturator 1", 1000, "Saturator 2");
651 LinkSaturator saturator2(&simulator, "Saturator 2", 1000, "Saturator 1");
652 Switch network_switch(&simulator, "Switch", 8,
653 bandwidth * base_propagation_delay * 10);
654
655 static const QuicByteCount initial_burst = 1000 * 10;
656 static const QuicByteCount max_bucket_size = 1000 * 100;
657 static const QuicBandwidth target_bandwidth = bandwidth * 0.25;
658 TrafficPolicer policer(&simulator, "Policer", initial_burst, max_bucket_size,
659 target_bandwidth, network_switch.port(2));
660
661 SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
662 base_propagation_delay);
663 SymmetricLink link2(&saturator2, &policer, bandwidth, base_propagation_delay);
664
665 // Ensure the initial burst passes without being dropped at all.
666 bool simulator_result = simulator.RunUntilOrTimeout(
667 [&saturator1]() {
668 return saturator1.bytes_transmitted() == initial_burst;
669 },
670 timeout);
671 ASSERT_TRUE(simulator_result);
672 saturator1.Pause();
673 simulator_result = simulator.RunUntilOrTimeout(
674 [&saturator2]() {
675 return saturator2.counter()->bytes() == initial_burst;
676 },
677 timeout);
678 ASSERT_TRUE(simulator_result);
679 saturator1.Resume();
680
681 // Run for some time so that the initial burst is not visible.
682 const QuicTime::Delta simulation_time = QuicTime::Delta::FromSeconds(10);
683 simulator.RunFor(simulation_time);
684
685 // Ensure we've transmitted the amount of data we expected.
686 for (auto* saturator : {&saturator1, &saturator2}) {
wub9343d702019-05-02 17:12:56 -0700687 EXPECT_APPROX_EQ(bandwidth * simulation_time,
688 saturator->bytes_transmitted(), 0.01f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500689 }
690
691 // Check that only one direction is throttled.
wub9343d702019-05-02 17:12:56 -0700692 EXPECT_APPROX_EQ(saturator1.bytes_transmitted() / 4,
693 saturator2.counter()->bytes(), 0.1f);
694 EXPECT_APPROX_EQ(saturator2.bytes_transmitted(),
695 saturator1.counter()->bytes(), 0.1f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500696}
697
698// Ensure that a larger burst is allowed when the policed saturator exits
699// quiescence.
700TEST_F(SimulatorTest, TrafficPolicerBurst) {
701 const QuicBandwidth bandwidth =
702 QuicBandwidth::FromBytesPerSecond(1024 * 1024);
703 const QuicTime::Delta base_propagation_delay =
704 QuicTime::Delta::FromMilliseconds(5);
705 const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
706
707 Simulator simulator;
708 LinkSaturator saturator1(&simulator, "Saturator 1", 1000, "Saturator 2");
709 LinkSaturator saturator2(&simulator, "Saturator 2", 1000, "Saturator 1");
710 Switch network_switch(&simulator, "Switch", 8,
711 bandwidth * base_propagation_delay * 10);
712
713 const QuicByteCount initial_burst = 1000 * 10;
714 const QuicByteCount max_bucket_size = 1000 * 100;
715 const QuicBandwidth target_bandwidth = bandwidth * 0.25;
716 TrafficPolicer policer(&simulator, "Policer", initial_burst, max_bucket_size,
717 target_bandwidth, network_switch.port(2));
718
719 SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
720 base_propagation_delay);
721 SymmetricLink link2(&saturator2, &policer, bandwidth, base_propagation_delay);
722
723 // Ensure at least one packet is sent on each side.
724 bool simulator_result = simulator.RunUntilOrTimeout(
725 [&saturator1, &saturator2]() {
726 return saturator1.packets_transmitted() > 0 &&
727 saturator2.packets_transmitted() > 0;
728 },
729 timeout);
730 ASSERT_TRUE(simulator_result);
731
732 // Wait until the bucket fills up.
733 saturator1.Pause();
734 saturator2.Pause();
735 simulator.RunFor(1.5f * target_bandwidth.TransferTime(max_bucket_size));
736
737 // Send a burst.
738 saturator1.Resume();
739 simulator.RunFor(bandwidth.TransferTime(max_bucket_size));
740 saturator1.Pause();
741 simulator.RunFor(2 * base_propagation_delay);
742
743 // Expect the burst to pass without losses.
wub9343d702019-05-02 17:12:56 -0700744 EXPECT_APPROX_EQ(saturator1.bytes_transmitted(),
745 saturator2.counter()->bytes(), 0.1f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500746
747 // Expect subsequent traffic to be policed.
748 saturator1.Resume();
749 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
wub9343d702019-05-02 17:12:56 -0700750 EXPECT_APPROX_EQ(saturator1.bytes_transmitted() / 4,
751 saturator2.counter()->bytes(), 0.1f);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500752}
753
754// Test that the packet aggregation support in queues work.
755TEST_F(SimulatorTest, PacketAggregation) {
756 // Model network where the delays are dominated by transfer delay.
757 const QuicBandwidth bandwidth = QuicBandwidth::FromBytesPerSecond(1000);
758 const QuicTime::Delta base_propagation_delay =
759 QuicTime::Delta::FromMicroseconds(1);
760 const QuicByteCount aggregation_threshold = 1000;
761 const QuicTime::Delta aggregation_timeout = QuicTime::Delta::FromSeconds(30);
762
763 Simulator simulator;
764 LinkSaturator saturator1(&simulator, "Saturator 1", 10, "Saturator 2");
765 LinkSaturator saturator2(&simulator, "Saturator 2", 10, "Saturator 1");
766 Switch network_switch(&simulator, "Switch", 8, 10 * aggregation_threshold);
767
768 // Make links with asymmetric propagation delay so that Saturator 2 only
769 // receives packets addressed to it.
770 SymmetricLink link1(&saturator1, network_switch.port(1), bandwidth,
771 base_propagation_delay);
772 SymmetricLink link2(&saturator2, network_switch.port(2), bandwidth,
773 2 * base_propagation_delay);
774
775 // Enable aggregation in 1 -> 2 direction.
776 Queue* queue = network_switch.port_queue(2);
777 queue->EnableAggregation(aggregation_threshold, aggregation_timeout);
778
779 // Enable aggregation in 2 -> 1 direction in a way that all packets are larger
780 // than the threshold, so that aggregation is effectively a no-op.
781 network_switch.port_queue(1)->EnableAggregation(5, aggregation_timeout);
782
783 // Fill up the aggregation buffer up to 90% (900 bytes).
784 simulator.RunFor(0.9 * bandwidth.TransferTime(aggregation_threshold));
785 EXPECT_EQ(0u, saturator2.counter()->bytes());
786
787 // Stop sending, ensure that given a timespan much shorter than timeout, the
788 // packets remain in the queue.
789 saturator1.Pause();
790 saturator2.Pause();
791 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
792 EXPECT_EQ(0u, saturator2.counter()->bytes());
793 EXPECT_EQ(900u, queue->bytes_queued());
794
795 // Ensure that all packets have reached the saturator not affected by
796 // aggregation. Here, 10 extra bytes account for a misrouted packet in the
797 // beginning.
798 EXPECT_EQ(910u, saturator1.counter()->bytes());
799
800 // Send 500 more bytes. Since the aggregation threshold is 1000 bytes, and
801 // queue already has 900 bytes, 1000 bytes will be send and 400 will be in the
802 // queue.
803 saturator1.Resume();
804 simulator.RunFor(0.5 * bandwidth.TransferTime(aggregation_threshold));
805 saturator1.Pause();
806 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
807 EXPECT_EQ(1000u, saturator2.counter()->bytes());
808 EXPECT_EQ(400u, queue->bytes_queued());
809
810 // Actually time out, and cause all of the data to be received.
811 simulator.RunFor(aggregation_timeout);
812 EXPECT_EQ(1400u, saturator2.counter()->bytes());
813 EXPECT_EQ(0u, queue->bytes_queued());
814
815 // Run saturator for a longer time, to ensure that the logic to cancel and
816 // reset alarms works correctly.
817 saturator1.Resume();
818 simulator.RunFor(5.5 * bandwidth.TransferTime(aggregation_threshold));
819 saturator1.Pause();
820 simulator.RunFor(QuicTime::Delta::FromSeconds(10));
821 EXPECT_EQ(6400u, saturator2.counter()->bytes());
822 EXPECT_EQ(500u, queue->bytes_queued());
823
824 // Time out again.
825 simulator.RunFor(aggregation_timeout);
826 EXPECT_EQ(6900u, saturator2.counter()->bytes());
827 EXPECT_EQ(0u, queue->bytes_queued());
828}
829
830} // namespace simulator
831} // namespace quic