@@ -5336,6 +5336,116 @@ TEST_CASE(h2_client_manual_data_write) {
53365336 return s_tester_clean_up ();
53375337}
53385338
5339+ TEST_CASE (h2_client_manual_data_write_with_body ) {
5340+
5341+ ASSERT_SUCCESS (s_tester_init (allocator , ctx ));
5342+ /* get connection preface and acks out of the way */
5343+ ASSERT_SUCCESS (h2_fake_peer_send_connection_preface_default_settings (& s_tester .peer ));
5344+ ASSERT_SUCCESS (h2_fake_peer_decode_messages_from_testing_channel (& s_tester .peer ));
5345+ size_t frame_count = h2_decode_tester_frame_count (& s_tester .peer .decode );
5346+
5347+ struct aws_http_message * request = aws_http2_message_new_request (allocator );
5348+ ASSERT_NOT_NULL (request );
5349+
5350+ struct aws_http_header request_headers_src [] = {
5351+ DEFINE_HEADER (":method" , "GET" ),
5352+ DEFINE_HEADER (":scheme" , "https" ),
5353+ DEFINE_HEADER (":path" , "/" ),
5354+ };
5355+ aws_http_message_add_header_array (request , request_headers_src , AWS_ARRAY_SIZE (request_headers_src ));
5356+ struct aws_http_make_request_options request_options = {
5357+ .self_size = sizeof (request_options ),
5358+ .request = request ,
5359+ .http2_use_manual_data_writes = true,
5360+ };
5361+ size_t total_length = 0 ;
5362+
5363+ /* set request body */
5364+ const char * body_src = "hello" ;
5365+ struct aws_byte_cursor body_cursor = aws_byte_cursor_from_c_str (body_src );
5366+ struct aws_input_stream * request_body = aws_input_stream_new_from_cursor (allocator , & body_cursor );
5367+ aws_http_message_set_body_stream (request , request_body );
5368+ int64_t body_length = 0 ;
5369+ ASSERT_SUCCESS (aws_input_stream_get_length (request_body , & body_length ));
5370+ total_length += (size_t )body_length ;
5371+ aws_input_stream_release (request_body );
5372+
5373+ struct aws_http_stream * stream = aws_http_connection_make_request (s_tester .connection , & request_options );
5374+ ASSERT_NOT_NULL (stream );
5375+
5376+ aws_http_stream_activate (stream );
5377+ testing_channel_drain_queued_tasks (& s_tester .testing_channel );
5378+ uint32_t stream_id = aws_http_stream_get_id (stream );
5379+
5380+ struct aws_byte_buf payload ;
5381+ aws_byte_buf_init (& payload , allocator , 1024 );
5382+
5383+ struct h2_client_manual_data_write_ctx test_ctx = {
5384+ .allocator = allocator ,
5385+ .data = payload ,
5386+ };
5387+
5388+ /* Simulate writes coming in over time */
5389+ for (int idx = 0 ; idx < 1000 ; ++ idx ) {
5390+ struct aws_input_stream * data_stream = s_h2_client_manual_data_write_generate_data (& test_ctx );
5391+ int64_t stream_length = 0 ;
5392+ ASSERT_SUCCESS (aws_input_stream_get_length (data_stream , & stream_length ));
5393+ total_length += (size_t )stream_length ;
5394+ struct aws_http2_stream_write_data_options write = {
5395+ .data = data_stream ,
5396+ .on_complete = NULL ,
5397+ .user_data = NULL ,
5398+ };
5399+ ASSERT_SUCCESS (aws_http2_stream_write_data (stream , & write ));
5400+ /* fake peer sends WINDOW_UPDATE */
5401+ struct aws_h2_frame * peer_frame = aws_h2_frame_new_window_update (allocator , stream_id , (uint32_t )stream_length );
5402+ ASSERT_SUCCESS (h2_fake_peer_send_frame (& s_tester .peer , peer_frame ));
5403+ /* Connection level window update */
5404+ peer_frame = aws_h2_frame_new_window_update (allocator , 0 , (uint32_t )stream_length );
5405+ ASSERT_SUCCESS (h2_fake_peer_send_frame (& s_tester .peer , peer_frame ));
5406+ if (idx % 10 == 0 ) {
5407+ testing_channel_drain_queued_tasks (& s_tester .testing_channel );
5408+ ASSERT_SUCCESS (h2_fake_peer_decode_messages_from_testing_channel (& s_tester .peer ));
5409+ }
5410+ aws_input_stream_release (data_stream );
5411+ }
5412+ struct aws_http2_stream_write_data_options last_write = {.end_stream = true};
5413+
5414+ ASSERT_SUCCESS (aws_http2_stream_write_data (stream , & last_write ));
5415+
5416+ testing_channel_drain_queued_tasks (& s_tester .testing_channel );
5417+ ASSERT_SUCCESS (h2_fake_peer_decode_messages_from_testing_channel (& s_tester .peer ));
5418+ size_t frame_count2 = h2_decode_tester_frame_count (& s_tester .peer .decode );
5419+ /* Peer should received header frame without end_stream and mutiple data frames and combined payload length should
5420+ * be the same as total length sent. */
5421+ struct h2_decoded_frame * header_frame = h2_decode_tester_get_frame (& s_tester .peer .decode , frame_count );
5422+ ASSERT_UINT_EQUALS (AWS_H2_FRAME_T_HEADERS , header_frame -> type );
5423+ ASSERT_FALSE (header_frame -> end_stream );
5424+ size_t received_length = 0 ;
5425+ for (size_t i = frame_count + 1 ; i < frame_count2 ; i ++ ) {
5426+ struct h2_decoded_frame * data_frame = h2_decode_tester_get_frame (& s_tester .peer .decode , i );
5427+ ASSERT_UINT_EQUALS (AWS_H2_FRAME_T_DATA , data_frame -> type );
5428+ received_length += data_frame -> data_payload_len ;
5429+ if (i == frame_count2 - 1 ) {
5430+ ASSERT_TRUE (data_frame -> end_stream );
5431+ } else {
5432+ ASSERT_FALSE (data_frame -> end_stream );
5433+ }
5434+ }
5435+ ASSERT_UINT_EQUALS (received_length , total_length );
5436+
5437+ aws_http_message_release (request );
5438+ aws_http_stream_release (stream );
5439+
5440+ /* close the connection */
5441+ aws_http_connection_close (s_tester .connection );
5442+
5443+ aws_byte_buf_clean_up (& test_ctx .data );
5444+
5445+ /* clean up */
5446+ return s_tester_clean_up ();
5447+ }
5448+
53395449TEST_CASE (h2_client_manual_data_write_no_data ) {
53405450
53415451 ASSERT_SUCCESS (s_tester_init (allocator , ctx ));
0 commit comments