test: protect durable behavior identified in review
This commit is contained in:
7 files changed
+528
-6
No files matched your search
@@ -155,3 +155,109 @@ async fn wildcard_construction_is_refused_without_reply_source_selection() {
|
||||
Err(ServerRuntimeError::WildcardSourceSelectionUnsupported { .. })
|
||||
));
|
||||
}
|
||||
|
||||
// A current-thread runtime cannot receive while this test holds its thread.
|
||||
// Queue real packets before delaying the server: no synthetic ancillary data or
|
||||
// transport hooks. A short queue delay selects kernel wall time; a delay beyond
|
||||
// the documented one-second sanity bound falls back to userspace. Monotonic and
|
||||
// midpoint timestamps must always remain at the later userspace observation.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn queued_echoes_select_kernel_receive_wall_only_when_plausible() {
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
let ns = || {
|
||||
i64::try_from(
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos(),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
for (placement, delay, kernel_expected) in [
|
||||
(StampAt::Both, Duration::from_millis(100), true),
|
||||
(StampAt::Both, Duration::from_millis(1100), false),
|
||||
(StampAt::Midpoint, Duration::from_millis(100), false),
|
||||
] {
|
||||
let mut server = Server::bind("127.0.0.1:0".parse().unwrap(), unthrottled())
|
||||
.await
|
||||
.unwrap();
|
||||
let addr = server.local_addr().unwrap();
|
||||
let client = UdpSocket::bind("127.0.0.1:0").await.unwrap();
|
||||
client.connect(addr).await.unwrap();
|
||||
let (stop_tx, stop_rx) = oneshot::channel();
|
||||
let run = tokio::spawn(async move {
|
||||
server
|
||||
.run(async {
|
||||
let _ = stop_rx.await;
|
||||
})
|
||||
.await
|
||||
});
|
||||
let params = Params {
|
||||
stamp_at: placement,
|
||||
clock: Clock::Both,
|
||||
received_stats: ReceivedStats::Both,
|
||||
..Params::with_protocol_defaults()
|
||||
};
|
||||
let open = encode_request(
|
||||
RequestToEncode::Open {
|
||||
params: ¶ms,
|
||||
no_test: false,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
client.send(&open).await.unwrap();
|
||||
let mut buffer = [0; 2048];
|
||||
let len = timeout(Duration::from_secs(2), client.recv(&mut buffer))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let opened = decode_open_reply(&buffer[..len], None).unwrap();
|
||||
let echo = encode_request(
|
||||
RequestToEncode::Echo {
|
||||
token: opened.token,
|
||||
sequence: 0,
|
||||
params: &opened.params,
|
||||
payload: &[],
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
client.writable().await.unwrap();
|
||||
let before_send = ns();
|
||||
client.try_send(&echo).unwrap(); // No await from submission through resume marker.
|
||||
let queued_by = ns();
|
||||
std::thread::sleep(delay);
|
||||
let resumed_at = ns();
|
||||
let len = timeout(Duration::from_secs(2), client.recv(&mut buffer))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let reply = decode_echo_reply(&buffer[..len], &opened.params, None).unwrap();
|
||||
assert_eq!(reply.recv_count, Some(1));
|
||||
assert_eq!(reply.recv_window, Some(1));
|
||||
let timestamps = reply.timestamps;
|
||||
if kernel_expected {
|
||||
let receive = timestamps.recv_wall.unwrap();
|
||||
assert!(
|
||||
receive >= before_send && receive <= queued_by,
|
||||
"receive wall must identify the kernel arrival before the queue delay"
|
||||
);
|
||||
let wall_elapsed = timestamps.send_wall.unwrap() - receive;
|
||||
let mono_elapsed = timestamps.send_mono.unwrap() - timestamps.recv_mono.unwrap();
|
||||
assert!(
|
||||
wall_elapsed - mono_elapsed >= 50_000_000,
|
||||
"queue delay must not move the monotonic endpoint"
|
||||
);
|
||||
} else {
|
||||
let receive = timestamps.recv_wall.or(timestamps.midpoint_wall).unwrap();
|
||||
assert!(
|
||||
receive >= resumed_at,
|
||||
"fallback and midpoint must use userspace time"
|
||||
);
|
||||
}
|
||||
stop_tx.send(()).unwrap();
|
||||
run.await.unwrap().unwrap();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user