in quic/s2n-quic-transport/src/stream/manager/tests.rs [1997:2165]
fn max_data_causes_on_connection_window_available_to_be_called_on_streams() {
fn assert_connection_window_state(
manager: &mut AbstractStreamManager<MockStream>,
stream_id: StreamId,
expected_on_connection_window_available_call_count: usize,
expected_on_connection_window_available_retrieve_window: u64,
) {
manager.with_asserted_stream(stream_id, |stream| {
assert_eq!(
expected_on_connection_window_available_call_count,
stream.on_connection_window_available_count
);
assert_eq!(
expected_on_connection_window_available_retrieve_window,
stream.on_connection_window_available_retrieve_window
);
});
}
let mut manager = create_stream_manager(endpoint::Type::Server);
// Consume all window
let mut current_window =
manager.with_outgoing_connection_flow_controller(|ctrl| ctrl.total_window());
assert_eq!(
current_window,
manager
.with_outgoing_connection_flow_controller(|ctrl| ctrl.acquire_window(current_window))
);
// Create some open Streams with interests
let stream_1 = try_open(&mut manager, StreamType::Bidirectional).unwrap();
let stream_2 = try_open(&mut manager, StreamType::Unidirectional).unwrap();
let stream_3 = try_open(&mut manager, StreamType::Bidirectional).unwrap();
let stream_4 = try_open(&mut manager, StreamType::Unidirectional).unwrap();
manager.with_asserted_stream(stream_1, |stream| {
stream.on_connection_window_available_retrieve_window = 1;
});
manager.with_asserted_stream(stream_3, |stream| {
stream.on_connection_window_available_retrieve_window = 1;
});
manager.with_asserted_stream(stream_4, |stream| {
stream.on_connection_window_available_retrieve_window = 1;
});
assert_eq!(
[stream_1, stream_3, stream_4],
*manager.streams_waiting_for_connection_flow_control_credits()
);
current_window += 100;
assert!(manager
.on_max_data(MaxData {
maximum_data: current_window,
})
.is_ok());
assert_eq!(
current_window,
manager.with_outgoing_connection_flow_controller(|ctrl| ctrl.total_window())
);
assert_eq!(
VarInt::from_u32(97),
manager.with_outgoing_connection_flow_controller(|ctrl| ctrl.available_window())
);
for stream_id in &[stream_1, stream_3, stream_4] {
assert_connection_window_state(&mut manager, *stream_id, 1, 0);
}
assert_connection_window_state(&mut manager, stream_2, 0, 0);
assert!(manager
.streams_waiting_for_connection_flow_control_credits()
.is_empty());
// Let stream_3 grab more of the connection window than it requires
manager.with_asserted_stream(stream_3, |stream| {
stream.on_connection_window_available_retrieve_window = 120
});
manager.with_asserted_stream(stream_4, |stream| {
stream.on_connection_window_available_retrieve_window = 220
});
//= https://www.rfc-editor.org/rfc/rfc9000#section-4.1
//= type=test
//# A sender MUST ignore any MAX_STREAM_DATA or MAX_DATA frames that do
//# not increase flow control limits.
assert!(manager
.on_max_data(MaxData {
maximum_data: current_window,
})
.is_ok());
assert_eq!(
VarInt::from_u32(0),
manager.with_outgoing_connection_flow_controller(|ctrl| ctrl.available_window())
);
assert_connection_window_state(&mut manager, stream_3, 2, 23);
assert_connection_window_state(&mut manager, stream_4, 1, 220);
// Stream 3 and 4 are still waiting
assert_eq!(
[stream_3, stream_4],
*manager.streams_waiting_for_connection_flow_control_credits()
);
current_window += 23;
assert!(manager
.on_max_data(MaxData {
maximum_data: current_window,
})
.is_ok());
assert_connection_window_state(&mut manager, stream_3, 3, 0);
assert_connection_window_state(&mut manager, stream_4, 1, 220);
// Stream 4 is still waiting
assert_eq!(
[stream_4],
*manager.streams_waiting_for_connection_flow_control_credits()
);
// Setup Stream 1 again
manager.with_asserted_stream(stream_1, |stream| {
stream.on_connection_window_available_retrieve_window = 200;
});
assert_eq!(
[stream_4, stream_1],
*manager.streams_waiting_for_connection_flow_control_credits()
);
current_window += 230;
assert!(manager
.on_max_data(MaxData {
maximum_data: current_window,
})
.is_ok());
assert_connection_window_state(&mut manager, stream_1, 2, 190);
// Stream 1 is still waiting
assert_eq!(
[stream_1],
*manager.streams_waiting_for_connection_flow_control_credits()
);
// Do not increase the window, but still query `on_max_data`:
assert!(manager
.on_max_data(MaxData {
maximum_data: current_window,
})
.is_ok());
assert_eq!(
[stream_1],
*manager.streams_waiting_for_connection_flow_control_credits()
);
current_window += 200;
assert!(manager
.on_max_data(MaxData {
maximum_data: current_window,
})
.is_ok());
assert_connection_window_state(&mut manager, stream_1, 3, 0);
// All done
assert!(manager
.streams_waiting_for_connection_flow_control_credits()
.is_empty());
}