@@ -232,6 +232,75 @@ is_lingering_stream_test() ->
232232 {ok , _Preface , State } = hackney_http2_machine :init (client , ? TEST_OPTS ),
233233 ? assertEqual (false , hackney_http2_machine :is_lingering_stream (1 , State )).
234234
235+ % %====================================================================
236+ % % Window Update Send Tests
237+ % %====================================================================
238+
239+ setup_stream_with_headers (ServerSettings ) ->
240+ {ok , _Preface , S0 } = hackney_http2_machine :init (client , ? TEST_OPTS ),
241+ {ok , S1 } = hackney_http2_machine :frame ({settings , ServerSettings }, S0 ),
242+ {ok , S2 } = hackney_http2_machine :frame (settings_ack , S1 ),
243+ {ok , StreamID , S3 } = hackney_http2_machine :init_stream (<<" POST" >>, S2 ),
244+ PseudoHeaders = #{
245+ method => <<" POST" >>,
246+ scheme => <<" https" >>,
247+ authority => <<" example.com" >>,
248+ path => <<" /upload" >>
249+ },
250+ Headers = [{<<" content-type" >>, <<" application/octet-stream" >>}],
251+ {ok , nofin , _HeaderBlock , S4 } = hackney_http2_machine :prepare_headers (
252+ StreamID , S3 , nofin , PseudoHeaders , Headers ),
253+ {StreamID , S4 }.
254+
255+ conn_window_update_sends_queued_data_test () ->
256+ {StreamID , S0 } = setup_stream_with_headers (#{initial_window_size => 200000 }),
257+ FillData = {data , binary :copy (<<0 >>, 65535 )},
258+ {send , _ , S1 } = hackney_http2_machine :send_or_queue_data (StreamID , S0 , nofin , FillData ),
259+ QueuedData = {data , binary :copy (<<1 >>, 10000 )},
260+ {ok , S2 } = hackney_http2_machine :send_or_queue_data (StreamID , S1 , fin , QueuedData ),
261+ BufferSize = hackney_http2_machine :get_connection_local_buffer_size (S2 ),
262+ ? assert (BufferSize > 0 ),
263+ {send , SendList , _S3 } = hackney_http2_machine :frame ({window_update , 50000 }, S2 ),
264+ ? assert (is_list (SendList )),
265+ ? assert (length (SendList ) > 0 ).
266+
267+ stream_window_update_sends_queued_data_test () ->
268+ {StreamID , S0 } = setup_stream_with_headers (#{initial_window_size => 100 }),
269+ FillData = {data , binary :copy (<<0 >>, 100 )},
270+ {send , _ , S1 } = hackney_http2_machine :send_or_queue_data (StreamID , S0 , nofin , FillData ),
271+ QueuedData = {data , binary :copy (<<1 >>, 500 )},
272+ {ok , S2 } = hackney_http2_machine :send_or_queue_data (StreamID , S1 , fin , QueuedData ),
273+ {send , SendList , _S3 } = hackney_http2_machine :frame (
274+ {window_update , StreamID , 10000 }, S2 ),
275+ ? assert (is_list (SendList )),
276+ ? assert (length (SendList ) > 0 ),
277+ [{SentStreamID , _ , _ } | _ ] = SendList ,
278+ ? assertEqual (StreamID , SentStreamID ).
279+
280+ conn_window_update_no_queued_data_test () ->
281+ {ok , _Preface , S0 } = hackney_http2_machine :init (client , ? TEST_OPTS ),
282+ {ok , S1 } = hackney_http2_machine :frame ({settings , #{}}, S0 ),
283+ {ok , S2 } = hackney_http2_machine :frame (settings_ack , S1 ),
284+ {ok , S3 } = hackney_http2_machine :frame ({window_update , 1000 }, S2 ),
285+ ? assert (is_tuple (S3 )).
286+
287+ stream_window_update_no_queued_data_test () ->
288+ {StreamID , S0 } = setup_stream_with_headers (#{}),
289+ {ok , S1 } = hackney_http2_machine :frame ({window_update , StreamID , 1000 }, S0 ),
290+ ? assert (is_tuple (S1 )).
291+
292+ conn_window_update_overflow_test () ->
293+ {ok , _Preface , S0 } = hackney_http2_machine :init (client , ? TEST_OPTS ),
294+ {ok , S1 } = hackney_http2_machine :frame ({settings , #{}}, S0 ),
295+ {ok , S2 } = hackney_http2_machine :frame (settings_ack , S1 ),
296+ {error , {connection_error , flow_control_error , _ }, _S3 } =
297+ hackney_http2_machine :frame ({window_update , 16#7fffffff }, S2 ).
298+
299+ stream_window_update_overflow_test () ->
300+ {StreamID , S0 } = setup_stream_with_headers (#{}),
301+ Result = hackney_http2_machine :frame ({window_update , StreamID , 16#7fffffff }, S0 ),
302+ ? assertMatch ({error , {stream_error , StreamID , flow_control_error , _ }, _ }, Result ).
303+
235304% %====================================================================
236305% % Test Suites
237306% %====================================================================
@@ -274,3 +343,19 @@ stream_state_test_() ->
274343 {" Last streamid" , fun last_streamid_test /0 },
275344 {" Is lingering stream" , fun is_lingering_stream_test /0 }
276345 ].
346+
347+ window_update_send_test_ () ->
348+ [
349+ {" Conn window_update sends queued data" ,
350+ fun conn_window_update_sends_queued_data_test /0 },
351+ {" Stream window_update sends queued data" ,
352+ fun stream_window_update_sends_queued_data_test /0 },
353+ {" Conn window_update with no queued data" ,
354+ fun conn_window_update_no_queued_data_test /0 },
355+ {" Stream window_update with no queued data" ,
356+ fun stream_window_update_no_queued_data_test /0 },
357+ {" Conn window_update overflow error" ,
358+ fun conn_window_update_overflow_test /0 },
359+ {" Stream window_update overflow error" ,
360+ fun stream_window_update_overflow_test /0 }
361+ ].
0 commit comments