tests: clean up more tests across the project
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 33s
Rust CI / cargo clippy (push) Successful in 34s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Failing after 33s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 9s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo doc (push) Successful in 22s
Fuzz Smoke / cargo fuzz smoke (push) Failing after 27s
Supply chain / cargo-deny advisories (push) Successful in 7s
Supply chain / cargo-deny bans licenses sources (push) Successful in 6s
Supply chain / actionlint (push) Successful in 3s
Netem Interop / netem interop (push) Successful in 1m3s

This commit is contained in:
Nils Andreas Svee committed 2026-10-02 12:47:27 +07:00
1 parent dc5b19059e
commit 74e7532965
17 files changed
+28 -1435

No files matched your search

-90
View File
@@ -228,75 +228,6 @@ pub(crate) fn echo_payload_len(hmac: bool, params: &Params) -> usize {
mod tests {
use super::*;
#[test]
fn recognized_descriptors_parse_to_their_mode() {
for (descriptor, expected) in [
("none", FillMode::None),
("rand", FillMode::Random),
("pattern:00", FillMode::Pattern(vec![0x00])),
("pattern:ff00", FillMode::Pattern(vec![0xff, 0x00])),
// Only the hexadecimal body is case-insensitive.
("pattern:AaBb", FillMode::Pattern(vec![0xaa, 0xbb])),
(
"pattern:69727474",
FillMode::Pattern(DEFAULT_FILL_PATTERN.to_vec()),
),
] {
assert_eq!(FillMode::parse(descriptor), Some(expected), "{descriptor}");
}
}
#[test]
fn unrecognized_and_malformed_descriptors_parse_to_nothing() {
for descriptor in [
"",
"bogus",
// The mode names themselves are case-sensitive.
"RAND",
"None",
"Pattern:aabb",
"rand ",
"pattern:",
"pattern:f",
"pattern:abc",
"pattern:zz",
"pattern:0g",
// A multi-byte character is not two hexadecimal digits, whatever
// its byte length.
"pattern:é",
] {
assert_eq!(FillMode::parse(descriptor), None, "{descriptor:?}");
}
}
#[test]
fn the_default_descriptor_and_the_default_pattern_agree() {
// The two constants are held separately so nothing has to parse a
// string per open; this is what keeps them from drifting.
assert_eq!(
FillMode::parse(DEFAULT_FILL_DESCRIPTOR),
Some(FillMode::default_fill())
);
}
#[test]
fn a_pattern_repeats_from_its_first_byte_and_stops_at_the_region() {
let mode = FillMode::Pattern(vec![0xaa, 0xbb]);
assert_eq!(mode.payload(0), Vec::<u8>::new());
assert_eq!(mode.payload(1), vec![0xaa]);
assert_eq!(
mode.payload(7),
vec![0xaa, 0xbb, 0xaa, 0xbb, 0xaa, 0xbb, 0xaa]
);
}
#[test]
fn no_fill_leaves_the_region_to_the_encoder() {
// Not a length-sized run of zeroes: the encoder has already zeroed the
// region, and copying zeroes over zeroes would only cost an allocation.
assert!(FillMode::None.payload(16).is_empty());
}
#[test]
fn a_failed_random_draw_yields_zeroes() {
// The real source cannot be made to fail without a production hook, and
@@ -309,25 +240,4 @@ mod tests {
};
assert_eq!(random_payload(6, scribble), vec![0; 6]);
}
#[test]
fn a_successful_random_draw_is_propagated_whole() {
// Deterministic on purpose. Nothing here asserts that real random bytes
// are nonzero, distinct or well distributed; those are properties of
// the operating system's source, and testing them would be a coin flip
// dressed up as an assertion.
let drawn = [1, 2, 3, 4, 5];
let source = |buffer: &mut [u8]| -> Result<(), ()> {
assert_eq!(buffer.len(), drawn.len(), "the whole region is offered");
buffer.copy_from_slice(&drawn);
Ok(())
};
assert_eq!(random_payload(drawn.len(), source), drawn);
}
#[test]
fn an_empty_region_never_reaches_the_random_source() {
let source = |_: &mut [u8]| -> Result<(), ()> { panic!("no bytes were needed") };
assert!(random_payload(0, source).is_empty());
}
}
-77
View File
@@ -393,83 +393,6 @@ mod tests {
use super::*;
use crate::{token::TokenSource, ServerCore, ServerError};
/// Which listener of a requested set has to be bound IPv6-only.
///
/// The interesting rows are the mapped ones. `[::ffff:0.0.0.0]` is an IPv4
/// wildcard bind wearing an IPv6 address, so it is neither a candidate for
/// `IPV6_V6ONLY` — which would refuse the traffic it exists to serve — nor
/// the IPv6 half of a same-port pair. A genuine IPv6 address paired with it
/// still is.
#[test]
fn only_a_genuine_ipv6_listener_sharing_an_explicit_port_is_bound_ipv6_only() {
for (addr, requested, ipv6_only, why) in [
(
"[::]:2112",
vec!["0.0.0.0:2112", "[::]:2112"],
true,
"the wildcard pair is the reason this exists",
),
(
"[::1]:2112",
vec!["127.0.0.1:2112", "[::1]:2112"],
true,
"and so is the explicit loopback pair",
),
(
"0.0.0.0:2112",
vec!["0.0.0.0:2112", "[::]:2112"],
false,
"the IPv4 half is bound exactly as it always was",
),
(
"[::]:2112",
vec!["[::]:2112"],
false,
"an IPv6 listener alone keeps ordinary bind semantics",
),
(
"[::]:2112",
vec!["0.0.0.0:2113", "[::]:2112"],
false,
"different ports cannot collide",
),
(
"[::]:0",
vec!["0.0.0.0:0", "[::]:0"],
false,
"two ephemeral requests resolve independently",
),
(
"[::ffff:0.0.0.0]:2112",
vec!["0.0.0.0:2112", "[::ffff:0.0.0.0]:2112"],
false,
"a mapped wildcard is an IPv4 listener, not an IPv6 one",
),
(
"[::]:2112",
vec!["[::ffff:0.0.0.0]:2112", "[::]:2112"],
true,
"and it is the IPv4 half a genuine IPv6 listener must avoid",
),
(
"[::ffff:127.0.0.1]:2112",
vec!["[::ffff:127.0.0.1]:2112", "[::1]:2112"],
false,
"a mapped host address is explicit IPv4 too",
),
] {
let requested: Vec<SocketAddr> = requested
.iter()
.map(|addr| addr.parse().expect("a test address must parse"))
.collect();
assert_eq!(
needs_ipv6_only(addr.parse().unwrap(), &requested),
ipv6_only,
"{addr} among {requested:?}: {why}"
);
}
}
#[tokio::test(flavor = "current_thread")]
async fn a_set_serving_nothing_is_refused() {
assert!(matches!(
+10 -54
View File
@@ -1,12 +1,9 @@
//! Server fill: what an open reply reports, what the session will fill with,
//! and the bytes an echo reply actually carries.
//!
//! The first two are deliberately different questions. A client that expressed
//! no preference keeps its absent or empty descriptor in the negotiated
//! parameters while the session uses this server's default fill, and only a
//! descriptor the server could not honor is rewritten. Asserting the reply alone
//! would not separate those, so the negotiation tests read the session's
//! effective mode too, and the payload tests then pin the bytes on the wire.
//! A client that expressed no preference keeps its absent or empty descriptor
//! in the negotiated parameters. Payload tests assert the effective fill from
//! reply bytes, without inspecting the session's internal representation.
//!
//! Payload lengths here are derived from `irtt-proto`'s own layout rather than
//! written as offsets, and are deliberately not multiples of the pattern length.
@@ -18,7 +15,6 @@ use super::support::{
expect_no_test_reply, expect_normal_open_reply, no_test_request, open_negotiated, open_request,
other_peer, peer, unthrottled, ScriptedTokens, KEY,
};
use crate::{core::ServerCore, fill::FillMode};
const TOKEN_A: u64 = 0x0102_0304_0506_0708;
const TOKEN_B: u64 = 0x1112_1314_1516_1718;
@@ -38,8 +34,8 @@ fn requesting(descriptor: Option<&str>) -> Params {
}
/// Opens a session requesting `descriptor` and returns the descriptor the reply
/// carried together with the fill the session actually holds.
fn negotiated(descriptor: Option<&str>) -> (Option<String>, FillMode) {
/// carried.
fn negotiated(descriptor: Option<&str>) -> Option<String> {
let mut core = core_with_tokens(unthrottled(), ScriptedTokens::new([TOKEN_A]));
let packet = core
.handle_datagram(peer(), &open_request(&requesting(descriptor), None))
@@ -47,16 +43,7 @@ fn negotiated(descriptor: Option<&str>) -> (Option<String>, FillMode) {
.expect("the open must be answered");
let reply = expect_normal_open_reply(&packet, None);
let fill = effective_fill(&core, reply.token);
(reply.params.server_fill.map(|fill| fill.value), fill)
}
/// The effective fill of the session `token` names.
fn effective_fill(core: &ServerCore, token: u64) -> FillMode {
core.session(token)
.expect("the open must have created a session")
.fill()
.clone()
reply.params.server_fill.map(|fill| fill.value)
}
/// The descriptor a no-test open reports for `descriptor`, which creates no
@@ -75,17 +62,6 @@ fn no_test_negotiated(descriptor: Option<&str>) -> Option<String> {
reply.params.server_fill.map(|fill| fill.value)
}
#[test]
fn no_preference_keeps_an_absent_descriptor_and_uses_the_default_fill() {
// The important half is the first: a client that asked for nothing must be
// answered with nothing, or a strict client rejects a restriction the
// server never actually imposed. The server's own default is an internal
// choice and stays internal.
let (returned, fill) = negotiated(None);
assert_eq!(returned, None, "an absent request stays absent");
assert_eq!(fill, FillMode::default_fill());
}
#[test]
fn an_explicitly_empty_descriptor_is_preserved_and_uses_the_default_fill() {
// A low-level peer can send this even though `ClientConfig` rejects an
@@ -93,31 +69,12 @@ fn an_explicitly_empty_descriptor_is_preserved_and_uses_the_default_fill() {
// with absent as "no preference", so it is neither refused nor rewritten:
// the requested wire value comes back exactly, and the server picks its own
// behavior behind it.
let (returned, fill) = negotiated(Some(""));
let returned = negotiated(Some(""));
assert_eq!(
returned.as_deref(),
Some(""),
"an empty request stays empty"
);
assert_eq!(fill, FillMode::default_fill());
}
#[test]
fn a_valid_descriptor_is_returned_exactly_as_requested() {
for (descriptor, expected) in [
("none", FillMode::None),
("rand", FillMode::Random),
("pattern:00", FillMode::Pattern(vec![0x00])),
("pattern:ff00", FillMode::Pattern(vec![0xff, 0x00])),
// Returned with its own hexadecimal case, not normalized to the bytes
// it decodes to: rewriting it would report a restriction that did not
// happen, and a strict client would reject the session for it.
("pattern:AaBb", FillMode::Pattern(vec![0xaa, 0xbb])),
] {
let (returned, fill) = negotiated(Some(descriptor));
assert_eq!(returned.as_deref(), Some(descriptor), "{descriptor}");
assert_eq!(fill, expected, "{descriptor}");
}
}
#[test]
@@ -137,13 +94,12 @@ fn an_unknown_or_malformed_descriptor_is_replaced_by_the_default() {
"pattern:0g",
"0123456789abcdef0123456789abcdef",
] {
let (returned, fill) = negotiated(Some(descriptor));
let returned = negotiated(Some(descriptor));
assert_eq!(
returned.as_deref(),
Some(crate::fill::DEFAULT_FILL_DESCRIPTOR),
"{descriptor}"
);
assert_eq!(fill, FillMode::default_fill(), "{descriptor}");
}
}
@@ -229,8 +185,8 @@ fn repeated(pattern: &[u8], len: usize) -> Vec<u8> {
#[test]
fn no_preference_fills_with_the_default_pattern() {
// The wire consequence of the negotiation test above: absent descriptor,
// default bytes. 7 is not a multiple of 4, so the last repeat is partial.
// An absent descriptor uses default bytes. 7 is not a multiple of 4, so
// the last repeat is partial.
assert_eq!(echo_payload(None, 7), b"irttirt".to_vec());
}