Skip to content

Commit 2f07551

Browse files
authored
correct the doc about unactivated stream and add test (#460)
1 parent 18352c8 commit 2f07551

File tree

4 files changed

+56
-14
lines changed

4 files changed

+56
-14
lines changed

include/aws/http/request_response.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,16 @@ typedef int(
186186
typedef int(aws_http_on_incoming_request_done_fn)(struct aws_http_stream *stream, void *user_data);
187187

188188
/**
189-
* Invoked when request/response stream is completely destroyed.
190-
* This may be invoked synchronously when aws_http_stream_release() is called.
191-
* This is invoked even if the stream is never activated.
189+
* Invoked when a request/response stream is complete, whether successful or unsuccessful
190+
* This is always invoked on the HTTP connection's event-loop thread.
191+
* This will not be invoked if the stream is never activated.
192192
*/
193193
typedef void(aws_http_on_stream_complete_fn)(struct aws_http_stream *stream, int error_code, void *user_data);
194194

195195
/**
196196
* Invoked when request/response stream destroy completely.
197197
* This can be invoked within the same thead who release the refcount on http stream.
198+
* This is invoked even if the stream is never activated.
198199
*/
199200
typedef void(aws_http_on_stream_destroy_fn)(void *user_data);
200201

source/h2_connection.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1531,7 +1531,7 @@ static struct aws_h2err s_decoder_on_settings_ack(void *userdata) {
15311531
}
15321532
connection->thread_data.settings_self[settings_array[i].id] = settings_array[i].value;
15331533
}
1534-
/* invoke the change settings compeleted user callback */
1534+
/* invoke the change settings completed user callback */
15351535
if (pending_settings->on_completed) {
15361536
pending_settings->on_completed(&connection->base, AWS_ERROR_SUCCESS, pending_settings->user_data);
15371537
}

tests/test_h1_client.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3647,36 +3647,52 @@ H1_CLIENT_TEST_CASE(h1_client_close_from_on_thread_makes_not_open) {
36473647
return AWS_OP_SUCCESS;
36483648
}
36493649

3650+
struct s_callback_invoked {
3651+
bool destroy_invoked;
3652+
bool complete_invoked;
3653+
};
3654+
36503655
static void s_unactivated_stream_cleans_up_on_destroy(void *data) {
3651-
bool *destroyed = data;
3652-
*destroyed = true;
3656+
struct s_callback_invoked *callback_data = data;
3657+
callback_data->destroy_invoked = true;
3658+
}
3659+
3660+
static void s_unactivated_stream_complete(struct aws_http_stream *stream, int error_code, void *data) {
3661+
(void)stream;
3662+
(void)error_code;
3663+
struct s_callback_invoked *callback_data = data;
3664+
callback_data->complete_invoked = true;
36533665
}
36543666

36553667
H1_CLIENT_TEST_CASE(h1_client_unactivated_stream_cleans_up) {
36563668
(void)ctx;
36573669
struct tester tester;
36583670
ASSERT_SUCCESS(s_tester_init(&tester, allocator));
36593671
ASSERT_TRUE(aws_http_connection_is_open(tester.connection));
3660-
bool destroyed = false;
36613672

36623673
struct aws_http_message *request = aws_http_message_new_request(allocator);
36633674
ASSERT_SUCCESS(aws_http_message_set_request_method(request, aws_byte_cursor_from_c_str("GET")));
36643675
ASSERT_SUCCESS(aws_http_message_set_request_path(request, aws_byte_cursor_from_c_str("/")));
3676+
struct s_callback_invoked callback_data = {0};
36653677

36663678
struct aws_http_make_request_options options = {
36673679
.self_size = sizeof(struct aws_http_make_request_options),
36683680
.request = request,
36693681
.on_destroy = s_unactivated_stream_cleans_up_on_destroy,
3670-
.user_data = &destroyed,
3682+
.on_complete = s_unactivated_stream_complete,
3683+
.user_data = &callback_data,
36713684
};
36723685

36733686
struct aws_http_stream *stream = aws_http_connection_make_request(tester.connection, &options);
36743687
aws_http_message_release(request);
36753688
ASSERT_NOT_NULL(stream);
36763689
/* we do not activate, that is the test. */
3677-
ASSERT_FALSE(destroyed);
3690+
ASSERT_FALSE(callback_data.destroy_invoked);
3691+
ASSERT_FALSE(callback_data.complete_invoked);
36783692
aws_http_stream_release(stream);
3679-
ASSERT_TRUE(destroyed);
3693+
/* Only destroy invoked, the complete was not invoked */
3694+
ASSERT_TRUE(callback_data.destroy_invoked);
3695+
ASSERT_FALSE(callback_data.complete_invoked);
36803696
aws_http_connection_close(tester.connection);
36813697
ASSERT_SUCCESS(s_tester_clean_up(&tester));
36823698
return AWS_OP_SUCCESS;

tests/test_h2_client.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,23 @@ TEST_CASE(h2_client_stream_release_after_complete) {
230230
return s_tester_clean_up();
231231
}
232232

233+
struct s_callback_invoked {
234+
bool destroy_invoked;
235+
bool complete_invoked;
236+
};
237+
238+
static void s_unactivated_stream_cleans_up_on_destroy(void *data) {
239+
struct s_callback_invoked *callback_data = data;
240+
callback_data->destroy_invoked = true;
241+
}
242+
243+
static void s_unactivated_stream_complete(struct aws_http_stream *stream, int error_code, void *data) {
244+
(void)stream;
245+
(void)error_code;
246+
struct s_callback_invoked *callback_data = data;
247+
callback_data->complete_invoked = true;
248+
}
249+
233250
TEST_CASE(h2_client_unactivated_stream_cleans_up) {
234251
ASSERT_SUCCESS(s_tester_init(allocator, ctx));
235252

@@ -243,22 +260,30 @@ TEST_CASE(h2_client_unactivated_stream_cleans_up) {
243260
DEFINE_HEADER(":path", "/"),
244261
};
245262
ASSERT_SUCCESS(aws_http_message_add_header_array(request, headers, AWS_ARRAY_SIZE(headers)));
246-
263+
struct s_callback_invoked callback_data = {0};
247264
struct aws_http_make_request_options options = {
248265
.self_size = sizeof(options),
249266
.request = request,
267+
.on_destroy = s_unactivated_stream_cleans_up_on_destroy,
268+
.on_complete = s_unactivated_stream_complete,
269+
.user_data = &callback_data,
250270
};
251271

252272
struct aws_http_stream *stream = aws_http_connection_make_request(s_tester.connection, &options);
253273
ASSERT_NOT_NULL(stream);
254274
/* do not activate the stream, that's the test. */
255275

276+
ASSERT_FALSE(callback_data.destroy_invoked);
277+
ASSERT_FALSE(callback_data.complete_invoked);
256278
/* shutdown channel so request can be released */
257279
aws_channel_shutdown(s_tester.testing_channel.channel, AWS_ERROR_SUCCESS);
258280
testing_channel_drain_queued_tasks(&s_tester.testing_channel);
259281
ASSERT_TRUE(testing_channel_is_shutdown_completed(&s_tester.testing_channel));
260282

261283
aws_http_stream_release(stream);
284+
ASSERT_TRUE(callback_data.destroy_invoked);
285+
ASSERT_FALSE(callback_data.complete_invoked);
286+
262287
aws_http_message_release(request);
263288

264289
return s_tester_clean_up();
@@ -1074,7 +1099,7 @@ TEST_CASE(h2_client_stream_err_receive_info_headers_after_main) {
10741099
ASSERT_SUCCESS(h2_fake_peer_send_frame(&s_tester.peer, peer_frame));
10751100

10761101
testing_channel_drain_queued_tasks(&s_tester.testing_channel);
1077-
/* validate the stream compeleted with error */
1102+
/* validate the stream completed with error */
10781103
ASSERT_TRUE(stream_tester.complete);
10791104
ASSERT_INT_EQUALS(AWS_ERROR_HTTP_PROTOCOL_ERROR, stream_tester.on_complete_error_code);
10801105
/* validate the connection is not affected */
@@ -1196,7 +1221,7 @@ TEST_CASE(h2_client_stream_err_receive_trailing_before_main) {
11961221
ASSERT_SUCCESS(h2_fake_peer_send_frame(&s_tester.peer, peer_frame));
11971222

11981223
testing_channel_drain_queued_tasks(&s_tester.testing_channel);
1199-
/* validate the stream compeleted with error */
1224+
/* validate the stream completed with error */
12001225
ASSERT_TRUE(stream_tester.complete);
12011226
ASSERT_INT_EQUALS(AWS_ERROR_HTTP_PROTOCOL_ERROR, stream_tester.on_complete_error_code);
12021227
/* validate the connection is not affected */
@@ -1321,7 +1346,7 @@ TEST_CASE(h2_client_stream_err_stream_frames_received_soon_after_rst_stream_rece
13211346
peer_frame = aws_h2_frame_new_headers(allocator, stream_id, response_headers, true /*end_stream*/, 0, NULL);
13221347
ASSERT_SUCCESS(h2_fake_peer_send_frame(&s_tester.peer, peer_frame));
13231348
testing_channel_drain_queued_tasks(&s_tester.testing_channel);
1324-
/* validate the stream compeleted with error */
1349+
/* validate the stream completed with error */
13251350
ASSERT_TRUE(stream_tester.complete);
13261351
ASSERT_INT_EQUALS(AWS_ERROR_HTTP_RST_STREAM_RECEIVED, stream_tester.on_complete_error_code);
13271352
/* We treat this as a stream error. So, validate the connection is still open and a rst stream is sent by

0 commit comments

Comments
 (0)