use super::*;
use crate::{
event, path,
recovery::congestion_controller::PathPublisher,
time::{Clock, NoopClock},
};
#[test]
fn bandwidth() {
let result = Bandwidth::new(1000, Duration::from_secs(10));
assert_eq!(10_240_000_000, result.nanos_per_kibibyte);
}
#[test]
fn bandwidth_saturating() {
let result = Bandwidth::new(u64::MAX, Duration::from_secs(1));
assert_eq!(Bandwidth::INFINITY, result);
}
#[test]
fn bandwidth_zero_interval() {
let result = Bandwidth::new(500, Duration::ZERO);
assert_eq!(Bandwidth::ZERO, result);
}
#[test]
fn bandwidth_max_interval() {
let result = Bandwidth::new(1, Duration::from_nanos(1 << 53));
assert!(result > Bandwidth::ZERO);
}
#[test]
fn bandwidth_interval_too_long() {
let result = Bandwidth::new(1, Duration::from_nanos(1 << 54));
assert_eq!(Bandwidth::ZERO, result);
}
#[test]
fn bandwidth_mul_ratio() {
let bandwidth = Bandwidth::new(4000, Duration::from_secs(1));
let result = bandwidth * Ratio::new(3, 4);
assert_eq!(result, Bandwidth::new(3000, Duration::from_secs(1)));
}
#[test]
fn bandwidth_zero_mul_ratio() {
assert_eq!(Bandwidth::ZERO, Bandwidth::ZERO * Ratio::new(3, 7));
}
#[test]
fn bandwidth_mul_duration() {
let bandwidth = Bandwidth::new(7000, Duration::from_secs(2));
let result = bandwidth * Duration::from_secs(10);
assert_eq!(result, 35000);
}
#[test]
fn bandwidth_mul_duration_too_long() {
let bandwidth = Bandwidth::new(1, Duration::from_nanos(1));
let result = bandwidth * Duration::from_nanos(1 << 53);
assert!(result < u64::MAX);
let result = bandwidth * Duration::from_nanos(1 << 54);
assert_eq!(result, u64::MAX);
}
#[test]
fn bandwidth_mul_saturation() {
let bandwidth = Bandwidth::INFINITY;
let result = bandwidth * Duration::from_secs(10);
assert_eq!(result, u64::MAX);
}
#[test]
fn u64_div_bandwidth() {
let bandwidth = Bandwidth::new(10_000, Duration::from_secs(1));
let bytes = 200_000;
assert_eq!(bytes / bandwidth, Duration::from_secs(20));
let bandwidth = Bandwidth::new(10_000, Duration::from_secs(1));
let bytes = 2_000;
assert_eq!(bytes / bandwidth, Duration::from_millis(200));
}
#[test]
fn bandwidth_ordering() {
let low = Bandwidth::new(10_000, Duration::from_secs(1));
let high = Bandwidth::new(20_000, Duration::from_secs(1));
assert!(high > low);
assert_eq!(high, low.max(high));
}
#[test]
fn on_packet_sent_timestamp_initialization() {
let t0 = NoopClock.get_time();
let mut bw_estimator = Estimator::default();
let packet_info = bw_estimator.on_packet_sent(0, 0, None, t0);
assert_eq!(t0, packet_info.first_sent_time);
assert_eq!(t0, packet_info.delivered_time);
assert_eq!(Some(t0), bw_estimator.first_sent_time);
assert_eq!(Some(t0), bw_estimator.delivered_time);
let t1 = t0 + Duration::from_secs(1);
let packet_info = bw_estimator.on_packet_sent(1500, 0, None, t1);
assert_eq!(t0, packet_info.first_sent_time);
assert_eq!(t0, packet_info.delivered_time);
assert_eq!(Some(t0), bw_estimator.first_sent_time);
assert_eq!(Some(t0), bw_estimator.delivered_time);
let t2 = t0 + Duration::from_secs(2);
let packet_info = bw_estimator.on_packet_sent(0, 0, None, t2);
assert_eq!(t2, packet_info.first_sent_time);
assert_eq!(t2, packet_info.delivered_time);
assert_eq!(Some(t2), bw_estimator.first_sent_time);
assert_eq!(Some(t2), bw_estimator.delivered_time);
}
#[test]
fn on_packet_sent() {
let first_sent_time = NoopClock.get_time();
let delivered_time = first_sent_time + Duration::from_secs(1);
let mut bw_estimator = Estimator {
delivered_bytes: 15000,
delivered_time: Some(delivered_time),
lost_bytes: 100,
ecn_ce_count: 5,
first_sent_time: Some(first_sent_time),
app_limited_delivered_bytes: None,
rate_sample: Default::default(),
};
let packet_info = bw_estimator.on_packet_sent(500, 100, Some(true), first_sent_time);
assert_eq!(first_sent_time, packet_info.first_sent_time);
assert_eq!(delivered_time, packet_info.delivered_time);
assert_eq!(15000, packet_info.delivered_bytes);
assert_eq!(100, packet_info.lost_bytes);
assert_eq!(5, packet_info.ecn_ce_count);
assert!(packet_info.is_app_limited);
assert_eq!(500 + 100, packet_info.bytes_in_flight);
assert_eq!(
Some(500 + 15000 + 100),
bw_estimator.app_limited_delivered_bytes
);
}
#[test]
fn app_limited() {
let mut publisher = event::testing::Publisher::snapshot();
let mut publisher = PathPublisher::new(&mut publisher, path::Id::test_id());
let first_sent_time = NoopClock.get_time();
let delivered_time = first_sent_time + Duration::from_secs(1);
let mut bw_estimator = Estimator {
delivered_bytes: 15000,
delivered_time: Some(delivered_time),
lost_bytes: 100,
ecn_ce_count: 5,
first_sent_time: Some(first_sent_time),
app_limited_delivered_bytes: None,
rate_sample: Default::default(),
};
let packet_info = bw_estimator.on_packet_sent(1500, 100, Some(true), first_sent_time);
assert!(packet_info.is_app_limited);
assert_eq!(
Some(1500 + 15000 + 100),
bw_estimator.app_limited_delivered_bytes
);
let packet_info = bw_estimator.on_packet_sent(500, 100, Some(false), first_sent_time);
assert!(packet_info.is_app_limited);
assert_eq!(
Some(1500 + 15000 + 100),
bw_estimator.app_limited_delivered_bytes
);
let packet_info = bw_estimator.on_packet_sent(2500, 100, None, first_sent_time);
assert!(packet_info.is_app_limited);
assert_eq!(
Some(2500 + 15000 + 100),
bw_estimator.app_limited_delivered_bytes
);
let packet_info = PacketInfo {
delivered_bytes: bw_estimator.delivered_bytes,
delivered_time,
lost_bytes: 0,
ecn_ce_count: 0,
first_sent_time,
bytes_in_flight: 1500,
is_app_limited: false,
};
bw_estimator.on_ack(
2600,
delivered_time,
packet_info,
delivered_time,
&mut publisher,
);
assert_eq!(
Some(2500 + 100 + 15000),
bw_estimator.app_limited_delivered_bytes
);
bw_estimator.on_ack(
1,
delivered_time,
packet_info,
delivered_time,
&mut publisher,
);
assert_eq!(None, bw_estimator.app_limited_delivered_bytes);
}
#[test]
fn on_packet_ack_rate_sample() {
let mut publisher = event::testing::Publisher::snapshot();
let mut publisher = PathPublisher::new(&mut publisher, path::Id::test_id());
let t0 = NoopClock.get_time() + Duration::from_secs(60);
let t1 = t0 + Duration::from_secs(1);
let t2 = t0 + Duration::from_secs(2);
let mut bw_estimator = Estimator::default();
let packet_1 = bw_estimator.on_packet_sent(0, 100, Some(false), t0);
bw_estimator.delivered_bytes = 100000;
bw_estimator.lost_bytes = 100;
bw_estimator.ecn_ce_count = 5;
let packet_2 = bw_estimator.on_packet_sent(1500, 100, Some(true), t1);
bw_estimator.delivered_bytes = 200000;
bw_estimator.lost_bytes = 150;
bw_estimator.ecn_ce_count = 15;
let packet_3 = bw_estimator.on_packet_sent(3000, 100, Some(false), t2);
let now = t0 + Duration::from_secs(10);
let delivered_bytes = bw_estimator.delivered_bytes;
bw_estimator.on_ack(1500, t0, packet_1, now, &mut publisher);
assert_eq!(bw_estimator.delivered_bytes, delivered_bytes + 1500);
assert_eq!(bw_estimator.delivered_time, Some(now));
assert_eq!(
packet_1.delivered_bytes,
bw_estimator.rate_sample.prior_delivered_bytes
);
assert_eq!(
packet_1.lost_bytes,
bw_estimator.rate_sample.prior_lost_bytes
);
assert_eq!(
packet_1.is_app_limited,
bw_estimator.rate_sample.is_app_limited
);
assert_eq!(
packet_1.bytes_in_flight,
bw_estimator.rate_sample.bytes_in_flight
);
assert_eq!(Some(t0), bw_estimator.first_sent_time);
assert_eq!(now - t0, bw_estimator.rate_sample.interval);
assert_eq!(
bw_estimator.delivered_bytes,
bw_estimator.rate_sample.delivered_bytes
);
assert_eq!(bw_estimator.lost_bytes, bw_estimator.rate_sample.lost_bytes);
assert_eq!(
bw_estimator.ecn_ce_count,
bw_estimator.rate_sample.ecn_ce_count
);
let now = now + Duration::from_secs(1);
let delivered_bytes = bw_estimator.delivered_bytes;
bw_estimator.on_ack(1500, t2, packet_3, now, &mut publisher);
assert_eq!(bw_estimator.delivered_bytes, delivered_bytes + 1500);
assert_eq!(bw_estimator.delivered_time, Some(now));
assert!(packet_3.delivered_bytes > packet_1.delivered_bytes);
assert_eq!(
packet_3.delivered_bytes,
bw_estimator.rate_sample.prior_delivered_bytes
);
assert_eq!(
packet_3.lost_bytes,
bw_estimator.rate_sample.prior_lost_bytes
);
assert_eq!(
packet_3.is_app_limited,
bw_estimator.rate_sample.is_app_limited
);
assert_eq!(
packet_3.bytes_in_flight,
bw_estimator.rate_sample.bytes_in_flight
);
assert_eq!(Some(t2), bw_estimator.first_sent_time);
assert_eq!(now - t0, bw_estimator.rate_sample.interval);
assert_eq!(3000, bw_estimator.rate_sample.delivered_bytes);
assert_eq!(0, bw_estimator.rate_sample.lost_bytes);
assert_eq!(0, bw_estimator.rate_sample.ecn_ce_count);
let now = now + Duration::from_secs(1);
let delivered_bytes = bw_estimator.delivered_bytes;
bw_estimator.on_ack(1500, t1, packet_2, now, &mut publisher);
assert_eq!(bw_estimator.delivered_bytes, delivered_bytes + 1500);
assert_eq!(bw_estimator.delivered_time, Some(now));
assert_eq!(
packet_3.delivered_bytes,
bw_estimator.rate_sample.prior_delivered_bytes
);
assert_eq!(
packet_3.lost_bytes,
bw_estimator.rate_sample.prior_lost_bytes
);
assert_eq!(
packet_3.is_app_limited,
bw_estimator.rate_sample.is_app_limited
);
assert_eq!(
packet_3.bytes_in_flight,
bw_estimator.rate_sample.bytes_in_flight
);
assert_eq!(Some(t2), bw_estimator.first_sent_time);
assert_eq!(4500, bw_estimator.rate_sample.delivered_bytes);
assert_eq!(0, bw_estimator.rate_sample.lost_bytes);
assert_eq!(0, bw_estimator.rate_sample.ecn_ce_count);
}
#[test]
fn on_packet_ack_implausible_ack_rate() {
let mut publisher = event::testing::Publisher::snapshot();
let mut publisher = PathPublisher::new(&mut publisher, path::Id::test_id());
let t0 = NoopClock.get_time();
let mut bw_estimator = Estimator::default();
let packet_info = bw_estimator.on_packet_sent(0, 100, Some(false), t0);
let t4 = t0 + Duration::from_secs(4);
bw_estimator.on_ack(1500, t0, packet_info, t4, &mut publisher);
let t5 = t0 + Duration::from_secs(5);
let packet_info = bw_estimator.on_packet_sent(1500, 100, Some(false), t5);
let now = t0 + Duration::from_secs(6);
bw_estimator.on_ack(
1500,
t0 + Duration::from_secs(5),
packet_info,
now,
&mut publisher,
);
let send_elapsed = t5 - packet_info.first_sent_time;
let ack_elapsed = now - packet_info.delivered_time;
assert!(send_elapsed > ack_elapsed);
assert_eq!(send_elapsed, bw_estimator.rate_sample.interval);
}
#[test]
fn on_packet_loss() {
let mut bw_estimator = Estimator::default();
assert_eq!(0, bw_estimator.lost_bytes);
assert_eq!(0, bw_estimator.rate_sample.lost_bytes);
bw_estimator.on_loss(500);
assert_eq!(500, bw_estimator.lost_bytes);
assert_eq!(500, bw_estimator.rate_sample.lost_bytes);
bw_estimator.on_loss(250);
assert_eq!(750, bw_estimator.lost_bytes);
assert_eq!(750, bw_estimator.rate_sample.lost_bytes);
bw_estimator.on_app_limited(1000);
bw_estimator.on_loss(250);
assert_eq!(Some(750), bw_estimator.app_limited_delivered_bytes);
bw_estimator.on_loss(1000);
assert_eq!(Some(0), bw_estimator.app_limited_delivered_bytes);
}
#[test]
fn on_packet_discarded() {
let mut bw_estimator = Estimator::default();
bw_estimator.on_app_limited(1000);
bw_estimator.on_packet_discarded(250);
assert_eq!(Some(750), bw_estimator.app_limited_delivered_bytes);
bw_estimator.on_packet_discarded(1000);
assert_eq!(Some(0), bw_estimator.app_limited_delivered_bytes);
}
#[test]
fn on_explicit_congestion() {
let mut bw_estimator = Estimator::default();
assert_eq!(0, bw_estimator.ecn_ce_count);
assert_eq!(0, bw_estimator.rate_sample.ecn_ce_count);
bw_estimator.on_explicit_congestion(5);
assert_eq!(5, bw_estimator.ecn_ce_count);
assert_eq!(5, bw_estimator.rate_sample.ecn_ce_count);
bw_estimator.on_explicit_congestion(3);
assert_eq!(8, bw_estimator.ecn_ce_count);
assert_eq!(8, bw_estimator.rate_sample.ecn_ce_count);
}
#[test]
fn as_bytes_per_second() {
let bandwidth = Bandwidth::new(10_000, Duration::from_secs(1));
assert_eq!(10_000, bandwidth.as_bytes_per_second());
assert_eq!(0, Bandwidth::ZERO.as_bytes_per_second());
assert_eq!(u64::MAX, Bandwidth::INFINITY.as_bytes_per_second());
}