Skip to content

Commit a0bfa9d

Browse files
committed
Add test to demonstrate sender side interleaving.
1 parent 45a3337 commit a0bfa9d

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

quiche/src/tests.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10411,3 +10411,83 @@ fn configuration_values_are_limited_to_max_varint() {
1041110411
// do not panic because of too large values that we try to encode via varint.
1041210412
assert_eq!(pipe.handshake(), Err(Error::InvalidTransportParam));
1041310413
}
10414+
10415+
/// Tests that incremental streams are scheduled round-robin when sending.
10416+
///
10417+
/// When multiple incremental streams have data queued, each call to send()
10418+
/// should emit data from the next stream in rotation, not always from the
10419+
/// same stream.
10420+
#[test]
10421+
fn incremental_stream_round_robin() {
10422+
let mut config = Config::new(PROTOCOL_VERSION).unwrap();
10423+
config
10424+
.load_cert_chain_from_pem_file("examples/cert.crt")
10425+
.unwrap();
10426+
config
10427+
.load_priv_key_from_pem_file("examples/cert.key")
10428+
.unwrap();
10429+
config
10430+
.set_application_protos(&[b"proto1", b"proto2"])
10431+
.unwrap();
10432+
// Set high limits so we can send data on multiple streams
10433+
config.set_initial_max_data(100000);
10434+
config.set_initial_max_stream_data_bidi_local(10000);
10435+
config.set_initial_max_stream_data_bidi_remote(10000);
10436+
config.set_initial_max_streams_bidi(10);
10437+
config.verify_peer(false);
10438+
10439+
let mut pipe = test_utils::Pipe::with_config(&mut config).unwrap();
10440+
assert_eq!(pipe.handshake(), Ok(()));
10441+
10442+
// Queue data on three streams. All streams are incremental by default.
10443+
// Use 2500 bytes so each stream needs ~2 packets to send all data.
10444+
let data = vec![0u8; 2500];
10445+
assert_eq!(pipe.client.stream_send(4, &data, false), Ok(2500));
10446+
assert_eq!(pipe.client.stream_send(8, &data, false), Ok(2500));
10447+
assert_eq!(pipe.client.stream_send(12, &data, false), Ok(2500));
10448+
10449+
// Track which streams get data sent in each packet
10450+
let mut send_order = Vec::new();
10451+
10452+
// Send packets one at a time
10453+
let mut buf = [0; 1350];
10454+
let mut recv_buf = [0; 1350];
10455+
10456+
// Send multiple packets and track which stream's data is sent
10457+
for _ in 0..10 {
10458+
let result = pipe.client.send(&mut buf);
10459+
if result.is_err() {
10460+
break;
10461+
}
10462+
let (len, _) = result.unwrap();
10463+
if len == 0 {
10464+
break;
10465+
}
10466+
10467+
// Process packet on server
10468+
let info = RecvInfo {
10469+
to: test_utils::Pipe::server_addr(),
10470+
from: test_utils::Pipe::client_addr(),
10471+
};
10472+
pipe.server.recv(&mut buf[..len], info).unwrap();
10473+
10474+
// Check which streams received data in THIS packet by consuming data.
10475+
// This ensures readable() only shows streams with new data next time.
10476+
for stream_id in pipe.server.readable() {
10477+
send_order.push(stream_id);
10478+
// Drain the data so the stream is no longer readable
10479+
while pipe.server.stream_recv(stream_id, &mut recv_buf).is_ok() {}
10480+
}
10481+
}
10482+
10483+
// With round-robin, streams are cycled after sending:
10484+
// - Stream 4 sends (lowest sequence), cycled to back -> queue: [8, 12, 4]
10485+
// - Stream 8 sends, cycled to back -> queue: [12, 4, 8]
10486+
// - Stream 12 sends, cycled to back -> queue: [4, 8, 12]
10487+
// Pattern repeats until all data is sent (3 rounds for 2500 bytes each).
10488+
assert_eq!(
10489+
send_order,
10490+
vec![4, 8, 12, 4, 8, 12, 4, 8, 12],
10491+
"Expected round-robin ordering: streams interleave across packets"
10492+
);
10493+
}

0 commit comments

Comments
 (0)