mod support;
use std::{
sync::{
Arc,
atomic::{AtomicUsize, Ordering},
},
time::Duration,
};
use moq_net::{Hop, Version, bandwidth::Rate, origin};
use support::harness::{MockConnectOptions, MockPair, connect_mock};
use support::mock::MockStats;
const VERSIONS: [&str; 2] = ["moq-lite-06", "moq-lite-07-wip"];
const IDLE: Duration = Duration::from_secs(60);
const PROBE_MAX_AGE: Duration = Duration::from_secs(10);
const STATS: MockStats = MockStats {
estimated_send_rate: Some(1_000_000),
rtt: Some(Duration::from_millis(40)),
};
async fn viewer(
version: &str,
origin: &origin::Producer,
polls: Option<Arc<AtomicUsize>>,
) -> (MockPair, moq_net::bandwidth::Consumer) {
let mut options = MockConnectOptions::new(version.parse::<Version>().unwrap());
options.server_publish = Some(origin.consume());
options.client_subscribe = Some(origin::Producer::new(origin::Config::new(Hop::new(2).unwrap())).0);
options.stats = STATS;
options.server_polls = polls;
let pair = connect_mock(options).await;
let mut probe = pair.client.recv_bandwidth().expect("lite carries PROBE");
assert_eq!(probe.changed().await.unwrap(), Some(Rate::from_bps(1_000_000)));
tokio::time::sleep(Duration::from_secs(1)).await;
(pair, probe)
}
fn origin() -> origin::Producer {
let (origin, driver) = origin::Producer::new(origin::Config::new(Hop::new(1).unwrap()));
tokio::spawn(support::harness::run(driver));
origin
}
#[tokio::test(start_paused = true)]
async fn idle_viewer_does_not_wake_the_server() {
for version in VERSIONS {
let origin = origin();
let polls = Arc::new(AtomicUsize::new(0));
let (pair, _probe) = viewer(version, &origin, Some(polls.clone())).await;
let reads = &pair.server_transport;
let (start_polls, start_reads) = (polls.load(Ordering::Relaxed), reads.stats_reads());
assert!(start_polls > 0, "the requested poll counter must observe the handshake");
tokio::time::sleep(IDLE).await;
let polls = polls.load(Ordering::Relaxed) - start_polls;
let reads = reads.stats_reads() - start_reads;
let refreshes = (IDLE.as_secs() / PROBE_MAX_AGE.as_secs()) as usize;
assert!(reads <= refreshes, "{version}: {reads} stats reads over {IDLE:?}");
assert!(polls <= 2 * refreshes, "{version}: {polls} driver polls over {IDLE:?}");
}
}
#[tokio::test(start_paused = true)]
async fn busy_viewer_sees_the_estimate_move() {
for version in VERSIONS {
let origin = origin();
let (pair, mut probe) = viewer(version, &origin, None).await;
pair.server_transport.set_stats(MockStats {
estimated_send_rate: Some(2_000_000),
..STATS
});
let broadcast = origin.create_broadcast("live").unwrap();
broadcast.announce(Default::default()).unwrap();
let moved = tokio::time::timeout(Duration::from_millis(1), probe.changed()).await;
assert_eq!(
moved.expect("reported with the work").unwrap(),
Some(Rate::from_bps(2_000_000)),
"{version}"
);
}
}