fn max_data_causes_on_connection_window_available_to_be_called_on_streams()

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());
}