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,133 @@
|
||||
//! Observe the emitted IP byte, independently of protocol negotiation.
|
||||
#![cfg(target_os = "linux")]
|
||||
|
||||
use std::{io::IoSliceMut, net::UdpSocket as StdSocket, os::fd::AsRawFd, time::Duration};
|
||||
|
||||
use irtt_proto::{
|
||||
decode_echo_reply, decode_open_reply, encode_request, OpenReply, Params, RequestToEncode,
|
||||
FLAG_CLOSE,
|
||||
};
|
||||
use irtt_server::{Server, ServerConfig};
|
||||
use nix::sys::socket::{recvmsg, ControlMessageOwned, MsgFlags};
|
||||
use tokio::{net::UdpSocket, sync::oneshot, time::timeout};
|
||||
|
||||
async fn exchange(client: &UdpSocket, request: &[u8], expected: u8) -> Vec<u8> {
|
||||
client.send(request).await.unwrap();
|
||||
loop {
|
||||
client.readable().await.unwrap();
|
||||
let packet = client.try_io(tokio::io::Interest::READABLE, || {
|
||||
let mut bytes = [0; 2048];
|
||||
let mut control = nix::cmsg_space!(u8);
|
||||
let mut iov = [IoSliceMut::new(&mut bytes)];
|
||||
let msg = recvmsg::<()>(
|
||||
client.as_raw_fd(),
|
||||
&mut iov,
|
||||
Some(&mut control),
|
||||
MsgFlags::MSG_DONTWAIT,
|
||||
)?;
|
||||
let size = msg.bytes;
|
||||
let class = msg.cmsgs().unwrap().find_map(|message| match message {
|
||||
ControlMessageOwned::Ipv4Tos(class) => Some(class),
|
||||
_ => None,
|
||||
});
|
||||
assert_eq!(class, Some(expected));
|
||||
Ok(bytes[..size].to_vec())
|
||||
});
|
||||
match packet {
|
||||
Ok(packet) => return packet,
|
||||
Err(error) if error.kind() == std::io::ErrorKind::WouldBlock => {}
|
||||
Err(error) => panic!("receive failed: {error}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn echo(opened: &OpenReply, sequence: u32) -> Vec<u8> {
|
||||
encode_request(
|
||||
RequestToEncode::Echo {
|
||||
token: opened.token,
|
||||
sequence,
|
||||
params: &opened.params,
|
||||
payload: &[],
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn every_open_echo_and_server_close_applies_its_own_raw_traffic_class() {
|
||||
timeout(Duration::from_secs(8), async {
|
||||
let maximum = Duration::from_millis(1);
|
||||
let mut server = Server::bind(
|
||||
"127.0.0.1:0".parse().unwrap(),
|
||||
ServerConfig::default()
|
||||
.with_min_send_interval(Duration::ZERO)
|
||||
.with_idle_timeout(Duration::MAX)
|
||||
.with_max_test_duration(maximum),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let addr = server.local_addr().unwrap();
|
||||
let (shutdown, stopped) = oneshot::channel();
|
||||
let task = tokio::spawn(async move {
|
||||
server
|
||||
.run(async {
|
||||
let _ = stopped.await;
|
||||
})
|
||||
.await
|
||||
});
|
||||
let socket = StdSocket::bind("127.0.0.1:0").unwrap();
|
||||
socket2::SockRef::from(&socket)
|
||||
.set_recv_tos_v4(true)
|
||||
.unwrap();
|
||||
socket.set_nonblocking(true).unwrap();
|
||||
let client = UdpSocket::from_std(socket).unwrap();
|
||||
client.connect(addr).await.unwrap();
|
||||
let mut sessions = Vec::new();
|
||||
// Each new OPEN follows a prior ECHO. The first raw byte also includes
|
||||
// ECN bits: neither a codepoint shift nor masking would preserve it.
|
||||
for (requested, class) in [(185, 185), (32, 32), (0, 0), (256, 0), (-1, 0)] {
|
||||
let params = Params {
|
||||
dscp: requested,
|
||||
..Params::with_protocol_defaults()
|
||||
};
|
||||
let request = encode_request(
|
||||
RequestToEncode::Open {
|
||||
params: ¶ms,
|
||||
no_test: false,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
let packet = exchange(&client, &request, 0).await;
|
||||
let opened = decode_open_reply(&packet, None).unwrap();
|
||||
assert_eq!(opened.params.dscp, requested);
|
||||
let packet = exchange(&client, &echo(&opened, 0), class).await;
|
||||
assert_eq!(
|
||||
decode_echo_reply(&packet, &opened.params, None)
|
||||
.unwrap()
|
||||
.flags
|
||||
& FLAG_CLOSE,
|
||||
0
|
||||
);
|
||||
sessions.push((opened, class));
|
||||
}
|
||||
// Every session has now served its first echo. Waiting past all duration
|
||||
// deadlines is safe under oversleep; idle expiry cannot intervene.
|
||||
tokio::time::sleep(maximum + Duration::from_secs(2)).await;
|
||||
for (opened, class) in sessions {
|
||||
let packet = exchange(&client, &echo(&opened, 1), class).await;
|
||||
assert_ne!(
|
||||
decode_echo_reply(&packet, &opened.params, None)
|
||||
.unwrap()
|
||||
.flags
|
||||
& FLAG_CLOSE,
|
||||
0
|
||||
);
|
||||
}
|
||||
shutdown.send(()).unwrap();
|
||||
task.await.unwrap().unwrap();
|
||||
})
|
||||
.await
|
||||
.expect("marked runtime exchanges did not complete");
|
||||
}
|
||||
Reference in new issue
Block a user