Skip to content
File

Blob: firmware/vendor/str0m/tests/bwe/loss.rs

rust120 lines
1//! Loss-based bandwidth estimation tests.
2 
3use std::time::Duration;
4 
5use netem::{DataSize, NetemConfig, Probability, RandomLoss};
6use str0m::RtcError;
7use str0m::bwe::Bitrate;
8 
9use crate::common::{BweTestContext, Step, connect_with_bwe, init_crypto_default, init_log};
10 
11#[test]
12fn loss_caps_estimate_below_delay_based() -> Result<(), RtcError> {
13 init_log();
14 init_crypto_default();
15 
16 let plan = vec![
17 Step::Conditions {
18 description: "Network with moderate loss",
19 config: NetemConfig::new()
20 .latency(Duration::from_millis(20))
21 .jitter(Duration::from_millis(5))
22 .loss(RandomLoss::new(Probability::new(0.10))) // 10% loss
23 .link(Bitrate::mbps(5), DataSize::kbytes(100))
24 .seed(42),
25 },
26 Step::Media {
27 description: "Send at 2 Mbps",
28 desired_bitrate: Bitrate::mbps(5),
29 media_send_rate: Bitrate::mbps(2),
30 },
31 // Past startup phase (2 seconds) so loss controller activates
32 Step::Run {
33 description: "Wait past startup phase",
34 duration: Duration::from_secs(3),
35 },
36 Step::Run {
37 description: "Let loss controller observe and cap",
38 duration: Duration::from_secs(5),
39 },
40 Step::Check {
41 description: "Estimate capped by loss (safety net)",
42 at_least: Bitrate::mbps(1),
43 },
44 ];
45 
46 let (mut l, mut r) = connect_with_bwe(Bitrate::mbps(2), Bitrate::mbps(5));
47 let mut ctx = BweTestContext::new(&mut l, &mut r);
48 ctx.run_plan(&mut l, &mut r, &plan)?;
49 
50 Ok(())
51}
52 
53#[test]
54fn loss_controller_only_reduces_never_increases() -> Result<(), RtcError> {
55 init_log();
56 init_crypto_default();
57 
58 let plan = vec![
59 // Start with clean network to establish high estimate
60 Step::Conditions {
61 description: "Clean network initially",
62 config: NetemConfig::new()
63 .latency(Duration::from_millis(10))
64 .link(Bitrate::mbps(5), DataSize::kbytes(150))
65 .seed(42),
66 },
67 Step::Media {
68 description: "Send at 2 Mbps",
69 desired_bitrate: Bitrate::mbps(5),
70 media_send_rate: Bitrate::mbps(2),
71 },
72 Step::Run {
73 description: "Build up estimate",
74 duration: Duration::from_secs(5),
75 },
76 Step::Check {
77 description: "Estimate should be healthy",
78 at_least: Bitrate::mbps(2),
79 },
80 // Introduce loss
81 Step::Conditions {
82 description: "Add significant loss",
83 config: NetemConfig::new()
84 .latency(Duration::from_millis(10))
85 .loss(RandomLoss::new(Probability::new(0.15))) // 15% loss
86 .link(Bitrate::mbps(5), DataSize::kbytes(150))
87 .seed(42),
88 },
89 Step::Run {
90 description: "Loss controller reduces estimate",
91 duration: Duration::from_secs(5),
92 },
93 Step::Check {
94 description: "Estimate reduced by loss controller",
95 at_least: Bitrate::mbps(1),
96 },
97 // Remove loss - estimate should NOT increase from loss controller
98 // (only delay-based increases)
99 Step::Conditions {
100 description: "Remove loss",
101 config: NetemConfig::new()
102 .latency(Duration::from_millis(10))
103 .link(Bitrate::mbps(5), DataSize::kbytes(150))
104 .seed(42),
105 },
106 Step::Run {
107 description: "Delay-based can recover, not loss-based",
108 duration: Duration::from_secs(5),
109 },
110 // We just verify the test completes without checking specific value
111 // The point is loss controller acts as safety net, not growth driver
112 ];
113 
114 let (mut l, mut r) = connect_with_bwe(Bitrate::mbps(2), Bitrate::mbps(5));
115 let mut ctx = BweTestContext::new(&mut l, &mut r);
116 ctx.run_plan(&mut l, &mut r, &plan)?;
117 
118 Ok(())
119}