tests: rework the actually useful tests to live in the integration crate
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 34s
Rust CI / cargo clippy (push) Successful in 35s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 10s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m14s
Rust CI / cargo doc (push) Successful in 23s
Fuzz Smoke / cargo fuzz smoke (push) Failing after 29s
Supply chain / cargo-deny advisories (push) Successful in 9s
Supply chain / cargo-deny bans licenses sources (push) Successful in 5s
Supply chain / actionlint (push) Successful in 3s
Netem Interop / netem interop (push) Successful in 1m11s
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 34s
Rust CI / cargo clippy (push) Successful in 35s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Failing after 8s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Failing after 10s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m14s
Rust CI / cargo doc (push) Successful in 23s
Fuzz Smoke / cargo fuzz smoke (push) Failing after 29s
Supply chain / cargo-deny advisories (push) Successful in 9s
Supply chain / cargo-deny bans licenses sources (push) Successful in 5s
Supply chain / actionlint (push) Successful in 3s
Netem Interop / netem interop (push) Successful in 1m11s
This commit is contained in:
101 files changed
+3636
-15159
No files matched your search
@@ -0,0 +1,264 @@
|
||||
use std::{
|
||||
net::{SocketAddr, SocketAddrV6},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use irtt_proto::{decode_echo_reply, decode_open_reply, encode_request, Params, RequestToEncode};
|
||||
use irtt_server::{ServerConfig, ServerCore};
|
||||
|
||||
// Admission, authentication, endpoint ownership and capacity are checked through
|
||||
// the public packet interface, with actual OS-generated session tokens.
|
||||
#[test]
|
||||
fn authenticated_sessions_are_bounded_and_owned_by_the_opening_endpoint() {
|
||||
let key = b"session-behavior";
|
||||
let peer: SocketAddr = "127.0.0.1:40000".parse().unwrap();
|
||||
let other: SocketAddr = "127.0.0.1:40001".parse().unwrap();
|
||||
let mut server = ServerCore::new(
|
||||
ServerConfig::default()
|
||||
.with_hmac_key(key)
|
||||
.with_max_sessions(1)
|
||||
.with_min_send_interval(Duration::ZERO),
|
||||
);
|
||||
let params = Params {
|
||||
received_stats: irtt_proto::ReceivedStats::Both,
|
||||
..Params::with_protocol_defaults()
|
||||
};
|
||||
let open = encode_request(
|
||||
RequestToEncode::Open {
|
||||
params: ¶ms,
|
||||
no_test: false,
|
||||
},
|
||||
Some(key),
|
||||
)
|
||||
.unwrap();
|
||||
let mut unkeyed = ServerCore::new(ServerConfig::default());
|
||||
assert!(unkeyed.handle_datagram(peer, &open).unwrap().is_none());
|
||||
assert_eq!(unkeyed.session_count(), 0);
|
||||
let unauthenticated = encode_request(
|
||||
RequestToEncode::Open {
|
||||
params: ¶ms,
|
||||
no_test: false,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
for packet in [
|
||||
&[][..],
|
||||
&[0; 16][..],
|
||||
&open[..open.len() - 1],
|
||||
&unauthenticated,
|
||||
] {
|
||||
assert!(server.handle_datagram(peer, packet).unwrap().is_none());
|
||||
assert_eq!(server.session_count(), 0);
|
||||
}
|
||||
let reply = server.handle_datagram(peer, &open).unwrap().unwrap();
|
||||
let opened = decode_open_reply(reply.bytes(), Some(key)).unwrap();
|
||||
assert_ne!(opened.token, 0);
|
||||
assert!(server.handle_datagram(other, &open).unwrap().is_none());
|
||||
assert_eq!(server.session_count(), 1);
|
||||
let echo = encode_request(
|
||||
RequestToEncode::Echo {
|
||||
token: opened.token,
|
||||
sequence: 0,
|
||||
params: &opened.params,
|
||||
payload: &[],
|
||||
},
|
||||
Some(key),
|
||||
)
|
||||
.unwrap();
|
||||
let close = encode_request(
|
||||
RequestToEncode::Close {
|
||||
token: opened.token,
|
||||
},
|
||||
Some(key),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(server.handle_datagram(other, &echo).unwrap().is_none());
|
||||
assert!(server.handle_datagram(other, &close).unwrap().is_none());
|
||||
let mut corrupted = echo.clone();
|
||||
corrupted[4] ^= 1;
|
||||
assert!(server.handle_datagram(peer, &corrupted).unwrap().is_none());
|
||||
let reply = server.handle_datagram(peer, &echo).unwrap().unwrap();
|
||||
let echoed = decode_echo_reply(reply.bytes(), &opened.params, Some(key)).unwrap();
|
||||
assert_eq!(echoed.sequence, 0);
|
||||
assert_eq!(echoed.recv_count, Some(1));
|
||||
assert!(server.handle_datagram(peer, &close).unwrap().is_none());
|
||||
assert_eq!(server.session_count(), 0);
|
||||
assert!(server.handle_datagram(peer, &echo).unwrap().is_none());
|
||||
assert!(server.handle_datagram(other, &open).unwrap().is_some());
|
||||
}
|
||||
|
||||
// Zero allowance and zero idle lifetime expose the boundary behavior directly,
|
||||
// without scripting clock reads or inspecting session/rate representations.
|
||||
#[test]
|
||||
fn zero_burst_and_zero_idle_timeout_silently_refuse_echoes() {
|
||||
let peer: SocketAddr = "127.0.0.1:40000".parse().unwrap();
|
||||
for config in [
|
||||
ServerConfig::default().with_burst_allowance(0),
|
||||
ServerConfig::default().with_idle_timeout(Duration::ZERO),
|
||||
] {
|
||||
let mut server = ServerCore::new(config);
|
||||
let params = Params::with_protocol_defaults();
|
||||
let open = encode_request(
|
||||
RequestToEncode::Open {
|
||||
params: ¶ms,
|
||||
no_test: false,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
let reply = server.handle_datagram(peer, &open).unwrap().unwrap();
|
||||
let opened = decode_open_reply(reply.bytes(), None).unwrap();
|
||||
let echo = encode_request(
|
||||
RequestToEncode::Echo {
|
||||
token: opened.token,
|
||||
sequence: 0,
|
||||
params: &opened.params,
|
||||
payload: &[],
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(server.handle_datagram(peer, &echo).unwrap().is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ipv6_flow_labels_share_a_session_but_zones_do_not() {
|
||||
let endpoint = |flow, scope| {
|
||||
SocketAddr::V6(SocketAddrV6::new(
|
||||
"fe80::1234".parse().unwrap(),
|
||||
40000,
|
||||
flow,
|
||||
scope,
|
||||
))
|
||||
};
|
||||
let mut server =
|
||||
ServerCore::new(ServerConfig::default().with_min_send_interval(Duration::ZERO));
|
||||
let params = Params {
|
||||
received_stats: irtt_proto::ReceivedStats::Both,
|
||||
..Params::with_protocol_defaults()
|
||||
};
|
||||
let packet = encode_request(
|
||||
RequestToEncode::Open {
|
||||
params: ¶ms,
|
||||
no_test: false,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
let reply = server
|
||||
.handle_datagram(endpoint(1, 2), &packet)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let opened = decode_open_reply(reply.bytes(), None).unwrap();
|
||||
let echo = encode_request(
|
||||
RequestToEncode::Echo {
|
||||
token: opened.token,
|
||||
sequence: 0,
|
||||
params: &opened.params,
|
||||
payload: &[],
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
let close = encode_request(
|
||||
RequestToEncode::Close {
|
||||
token: opened.token,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(server
|
||||
.handle_datagram(endpoint(1, 3), &echo)
|
||||
.unwrap()
|
||||
.is_none());
|
||||
assert!(server
|
||||
.handle_datagram(endpoint(1, 3), &close)
|
||||
.unwrap()
|
||||
.is_none());
|
||||
assert_eq!(server.session_count(), 1);
|
||||
let reply = server
|
||||
.handle_datagram(endpoint(99, 2), &echo)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
decode_echo_reply(reply.bytes(), &opened.params, None)
|
||||
.unwrap()
|
||||
.recv_count,
|
||||
Some(1)
|
||||
);
|
||||
assert!(server
|
||||
.handle_datagram(endpoint(99, 2), &close)
|
||||
.unwrap()
|
||||
.is_none());
|
||||
assert_eq!(server.session_count(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn oversized_authenticated_echo_does_not_advance_session_state() {
|
||||
let key = b"oversized-echo-test";
|
||||
let peer = "127.0.0.1:40000".parse().unwrap();
|
||||
let mut server = ServerCore::new(
|
||||
ServerConfig::default()
|
||||
.with_hmac_key(key)
|
||||
.with_max_packet_length(96)
|
||||
.with_burst_allowance(1)
|
||||
.with_min_send_interval(Duration::from_secs(60))
|
||||
.with_max_test_duration(Duration::from_millis(1))
|
||||
.with_idle_timeout(Duration::MAX),
|
||||
);
|
||||
let params = Params {
|
||||
length: 96,
|
||||
received_stats: irtt_proto::ReceivedStats::Both,
|
||||
..Params::with_protocol_defaults()
|
||||
};
|
||||
let open = encode_request(
|
||||
RequestToEncode::Open {
|
||||
params: ¶ms,
|
||||
no_test: false,
|
||||
},
|
||||
Some(key),
|
||||
)
|
||||
.unwrap();
|
||||
let reply = server.handle_datagram(peer, &open).unwrap().unwrap();
|
||||
let opened = decode_open_reply(reply.bytes(), Some(key)).unwrap();
|
||||
let oversized_params = Params {
|
||||
length: 128,
|
||||
..opened.params.clone()
|
||||
};
|
||||
let oversized = encode_request(
|
||||
RequestToEncode::Echo {
|
||||
token: opened.token,
|
||||
sequence: 63,
|
||||
params: &oversized_params,
|
||||
payload: &[],
|
||||
},
|
||||
Some(key),
|
||||
)
|
||||
.unwrap();
|
||||
assert!(oversized.len() > 96);
|
||||
assert!(server.handle_datagram(peer, &oversized).unwrap().is_none());
|
||||
// If the oversized request started maximum duration, the first valid
|
||||
// echo would now close. Oversleep preserves this distinction.
|
||||
std::thread::sleep(Duration::from_millis(2001));
|
||||
let valid = encode_request(
|
||||
RequestToEncode::Echo {
|
||||
token: opened.token,
|
||||
sequence: 0,
|
||||
params: &opened.params,
|
||||
payload: &[],
|
||||
},
|
||||
Some(key),
|
||||
)
|
||||
.unwrap();
|
||||
let reply = server
|
||||
.handle_datagram(peer, &valid)
|
||||
.unwrap()
|
||||
.expect("oversized request must not consume allowance");
|
||||
let reply = decode_echo_reply(reply.bytes(), &opened.params, Some(key)).unwrap();
|
||||
assert_eq!(reply.flags & irtt_proto::FLAG_CLOSE, 0);
|
||||
assert_eq!(reply.recv_count, Some(1));
|
||||
assert_eq!(reply.recv_window, Some(1));
|
||||
assert_eq!(server.session_count(), 1);
|
||||
}
|
||||
Reference in new issue
Block a user