Align the replay-window test with the reliable sequence domain
Separating the sequence domains gated duplicate suppression on packet.reliable in Rust, TypeScript and C# alike, so lossy datagrams are remembered nowhere and a replayed one is delivered again. That is the intended contract -- lossy traffic is fire-and-forget and its history is bounded by not existing -- but replay_history_is_bounded_and_idle_hub_sessions_expire still asserted the old behaviour with a lossy packet and had been left failing on the branch. The three tests the change added in each runtime cover ordered-requires- reliable, per-channel sequenced scope, and lossy gaps. None covers the bounded replay window, which was this test's real subject, so removing the assertion would have dropped the only coverage of a security property. The lossy assertion now states the new contract, and the reliable domain gets its own replay check: 4,100 acknowledged reliable sends, then the oldest replayed and rejected by the window. Rust 151, C# 148, TypeScript 48, Python 138 all pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
8d3025816d
commit
85bc4c71b5
1 changed files with 33 additions and 1 deletions
|
|
@ -453,10 +453,42 @@ fn replay_history_is_bounded_and_idle_hub_sessions_expire() -> Result<()> {
|
|||
}
|
||||
assert_eq!(receiver.receive(&packet, sequence)?.delivered.len(), 1);
|
||||
}
|
||||
assert!(
|
||||
// Separating the sequence domains moved duplicate suppression onto the
|
||||
// reliable domain, so a replayed lossy datagram is delivered again rather
|
||||
// than silently dropped. Lossy traffic is remembered nowhere, which is what
|
||||
// bounds its history.
|
||||
assert_eq!(
|
||||
receiver
|
||||
.receive(&oldest.expect("oldest packet"), 4_101)?
|
||||
.delivered
|
||||
.len(),
|
||||
1
|
||||
);
|
||||
|
||||
// The bounded replay window still guards the reliable domain, and nothing
|
||||
// else asserts it once the lossy path stopped being remembered.
|
||||
let mut oldest_reliable = None;
|
||||
for step in 0..4_100u64 {
|
||||
let packet = sender.send(
|
||||
"schema",
|
||||
vec![(step % 251) as u8],
|
||||
CultNetRudpSendOptions {
|
||||
reliable: true,
|
||||
ordered: false,
|
||||
sequenced: false,
|
||||
now_ms: step,
|
||||
},
|
||||
)?;
|
||||
if oldest_reliable.is_none() {
|
||||
oldest_reliable = Some(packet.clone());
|
||||
}
|
||||
assert_eq!(receiver.receive(&packet, step)?.delivered.len(), 1);
|
||||
sender.receive(&receiver.create_ack_for(packet.sequence), step)?;
|
||||
}
|
||||
assert!(
|
||||
receiver
|
||||
.receive(&oldest_reliable.expect("oldest reliable packet"), 4_101)?
|
||||
.delivered
|
||||
.is_empty()
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue