Coverage Report

Created: 2026-04-01 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/neqo/test-fixture/src/sim/drop.rs
Line
Count
Source
1
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4
// option. This file may not be copied, modified, or distributed
5
// except according to those terms.
6
7
#![expect(clippy::unwrap_used, reason = "This is test code.")]
8
9
use std::{
10
    fmt::{self, Debug},
11
    time::Instant,
12
};
13
14
use neqo_common::{Datagram, qtrace};
15
use neqo_transport::Output;
16
17
use super::{Node, Rng};
18
19
/// A random dropper.
20
pub struct Drop {
21
    threshold: u64,
22
    max: u64,
23
    rng: Option<Rng>,
24
}
25
26
impl Drop {
27
    /// Make a new random drop generator.  Each `drop` is called, this generates a
28
    /// random value between 0 and `max` (exclusive).  If this value is less than
29
    /// `threshold` a value of `true` is returned.
30
    #[must_use]
31
0
    pub const fn new(threshold: u64, max: u64) -> Self {
32
0
        Self {
33
0
            threshold,
34
0
            max,
35
0
            rng: None,
36
0
        }
37
0
    }
38
39
    /// Generate random drops with the given percentage.
40
    #[must_use]
41
0
    pub fn percentage(pct: u8) -> Self {
42
        // Multiply by 10 so that the random number generator works more efficiently.
43
0
        Self::new(u64::from(pct) * 10, 1000)
44
0
    }
45
46
    /// Determine whether or not to drop a packet.
47
    /// # Panics
48
    /// When this is invoked after test configuration has been torn down,
49
    /// such that the RNG is no longer available.
50
    #[must_use]
51
0
    pub fn drop(&self) -> bool {
52
0
        let mut rng = self.rng.as_ref().unwrap().borrow_mut();
53
0
        let r = rng.random_from(0..self.max);
54
0
        r < self.threshold
55
0
    }
56
}
57
58
impl Node for Drop {
59
0
    fn init(&mut self, rng: Rng, _now: Instant) {
60
0
        self.rng = Some(rng);
61
0
    }
62
63
    // Pass any datagram provided directly out, but drop some of them.
64
0
    fn process(&mut self, d: Option<Datagram>, _now: Instant) -> Output {
65
0
        d.map_or(Output::None, |dgram| {
66
0
            if self.drop() {
67
0
                qtrace!("drop {}", dgram.len());
68
0
                Output::None
69
            } else {
70
0
                Output::Datagram(dgram)
71
            }
72
0
        })
73
0
    }
74
}
75
76
impl Debug for Drop {
77
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78
0
        f.write_str("drop")
79
0
    }
80
}