1313#include <aws/testing/aws_test_harness.h>
1414
1515enum s3_update_cancel_type {
16+ S3_UPDATE_CANCEL_TYPE_NO_CANCEL ,
17+
1618 S3_UPDATE_CANCEL_TYPE_MPU_CREATE_NOT_SENT ,
1719 S3_UPDATE_CANCEL_TYPE_MPU_CREATE_COMPLETED ,
1820 S3_UPDATE_CANCEL_TYPE_MPU_ONE_PART_COMPLETED ,
1921 S3_UPDATE_CANCEL_TYPE_MPU_ALL_PARTS_COMPLETED ,
22+ S3_UPDATE_CANCEL_TYPE_MPU_ONGOING_HTTP_REQUESTS ,
2023 S3_UPDATE_CANCEL_TYPE_NUM_MPU_CANCEL_TYPES ,
2124
2225 S3_UPDATE_CANCEL_TYPE_MPD_NOTHING_SENT ,
@@ -31,6 +34,8 @@ enum s3_update_cancel_type {
3134
3235struct s3_cancel_test_user_data {
3336 enum s3_update_cancel_type type ;
37+ bool pause ;
38+ struct aws_s3_meta_request_resume_token * resume_token ;
3439 bool abort_successful ;
3540};
3641
@@ -48,74 +53,84 @@ static bool s_s3_meta_request_update_cancel_test(
4853 struct aws_s3_auto_ranged_put * auto_ranged_put = meta_request -> impl ;
4954 struct aws_s3_auto_ranged_get * auto_ranged_get = meta_request -> impl ;
5055
51- bool call_cancel = false;
56+ bool call_cancel_or_pause = false;
5257 bool block_update = false;
5358
5459 aws_s3_meta_request_lock_synced_data (meta_request );
5560
5661 switch (cancel_test_user_data -> type ) {
62+ case S3_UPDATE_CANCEL_TYPE_NO_CANCEL :
63+ break ;
64+
5765 case S3_UPDATE_CANCEL_TYPE_MPU_CREATE_NOT_SENT :
58- call_cancel = auto_ranged_put -> synced_data .create_multipart_upload_sent != 0 ;
66+ call_cancel_or_pause = auto_ranged_put -> synced_data .create_multipart_upload_sent != 0 ;
5967 break ;
6068 case S3_UPDATE_CANCEL_TYPE_MPU_CREATE_COMPLETED :
61- call_cancel = auto_ranged_put -> synced_data .create_multipart_upload_completed != 0 ;
69+ call_cancel_or_pause = auto_ranged_put -> synced_data .create_multipart_upload_completed != 0 ;
6270 break ;
6371 case S3_UPDATE_CANCEL_TYPE_MPU_ONE_PART_COMPLETED :
64- call_cancel = auto_ranged_put -> synced_data .num_parts_completed == 1 ;
65- block_update = !call_cancel && auto_ranged_put -> synced_data .num_parts_started == 1 ;
72+ call_cancel_or_pause = auto_ranged_put -> synced_data .num_parts_completed == 1 ;
73+ block_update = !call_cancel_or_pause && auto_ranged_put -> synced_data .num_parts_started == 1 ;
6674 break ;
6775 case S3_UPDATE_CANCEL_TYPE_MPU_ALL_PARTS_COMPLETED :
68- call_cancel = auto_ranged_put -> synced_data .num_parts_completed ==
69- auto_ranged_put -> total_num_parts_from_content_length ;
76+ call_cancel_or_pause = auto_ranged_put -> synced_data .num_parts_completed ==
77+ auto_ranged_put -> total_num_parts_from_content_length ;
78+ break ;
79+
80+ case S3_UPDATE_CANCEL_TYPE_MPU_ONGOING_HTTP_REQUESTS :
81+ call_cancel_or_pause = !aws_linked_list_empty (& meta_request -> synced_data .ongoing_http_requests_list );
7082 break ;
7183
7284 case S3_UPDATE_CANCEL_TYPE_NUM_MPU_CANCEL_TYPES :
7385 AWS_ASSERT (false);
7486 break ;
7587
7688 case S3_UPDATE_CANCEL_TYPE_MPD_NOTHING_SENT :
77- call_cancel = auto_ranged_get -> synced_data .num_parts_requested == 0 ;
89+ call_cancel_or_pause = auto_ranged_get -> synced_data .num_parts_requested == 0 ;
7890 break ;
7991
8092 case S3_UPDATE_CANCEL_TYPE_MPD_HEAD_OBJECT_SENT :
81- call_cancel = auto_ranged_get -> synced_data .head_object_sent != 0 ;
93+ call_cancel_or_pause = auto_ranged_get -> synced_data .head_object_sent != 0 ;
8294 break ;
8395
8496 case S3_UPDATE_CANCEL_TYPE_MPD_HEAD_OBJECT_COMPLETED :
85- call_cancel = auto_ranged_get -> synced_data .head_object_completed != 0 ;
97+ call_cancel_or_pause = auto_ranged_get -> synced_data .head_object_completed != 0 ;
8698 break ;
8799
88100 case S3_UPDATE_CANCEL_TYPE_MPD_GET_WITHOUT_RANGE_SENT :
89- call_cancel = auto_ranged_get -> synced_data .get_without_range_sent != 0 ;
101+ call_cancel_or_pause = auto_ranged_get -> synced_data .get_without_range_sent != 0 ;
90102 break ;
91103
92104 case S3_UPDATE_CANCEL_TYPE_MPD_GET_WITHOUT_RANGE_COMPLETED :
93- call_cancel = auto_ranged_get -> synced_data .get_without_range_completed != 0 ;
105+ call_cancel_or_pause = auto_ranged_get -> synced_data .get_without_range_completed != 0 ;
94106 break ;
95107
96108 case S3_UPDATE_CANCEL_TYPE_MPD_ONE_PART_SENT :
97- call_cancel = auto_ranged_get -> synced_data .num_parts_requested == 1 ;
109+ call_cancel_or_pause = auto_ranged_get -> synced_data .num_parts_requested == 1 ;
98110 break ;
99111
100112 case S3_UPDATE_CANCEL_TYPE_MPD_ONE_PART_COMPLETED :
101- call_cancel = auto_ranged_get -> synced_data .num_parts_completed == 1 ;
113+ call_cancel_or_pause = auto_ranged_get -> synced_data .num_parts_completed == 1 ;
102114
103115 /* Prevent other parts from being queued while we wait for this one to complete. */
104- block_update = !call_cancel && auto_ranged_get -> synced_data .num_parts_requested == 1 ;
116+ block_update = !call_cancel_or_pause && auto_ranged_get -> synced_data .num_parts_requested == 1 ;
105117 break ;
106118
107119 case S3_UPDATE_CANCEL_TYPE_MPD_TWO_PARTS_COMPLETED :
108- call_cancel = auto_ranged_get -> synced_data .num_parts_completed == 2 ;
120+ call_cancel_or_pause = auto_ranged_get -> synced_data .num_parts_completed == 2 ;
109121
110122 /* Prevent other parts from being queued while we wait for these two to complete. */
111- block_update = !call_cancel && auto_ranged_get -> synced_data .num_parts_requested == 2 ;
123+ block_update = !call_cancel_or_pause && auto_ranged_get -> synced_data .num_parts_requested == 2 ;
112124 break ;
113125 }
114126
115127 aws_s3_meta_request_unlock_synced_data (meta_request );
116-
117- if (call_cancel ) {
118- aws_s3_meta_request_cancel (meta_request );
128+ if (call_cancel_or_pause ) {
129+ if (cancel_test_user_data -> pause ) {
130+ aws_s3_meta_request_pause (meta_request , & cancel_test_user_data -> resume_token );
131+ } else {
132+ aws_s3_meta_request_cancel (meta_request );
133+ }
119134 }
120135
121136 if (block_update ) {
@@ -175,7 +190,8 @@ static struct aws_s3_meta_request *s_meta_request_factory_patch_update_cancel_te
175190static int s3_cancel_test_helper_ex (
176191 struct aws_allocator * allocator ,
177192 enum s3_update_cancel_type cancel_type ,
178- bool async_input_stream ) {
193+ bool async_input_stream ,
194+ bool pause ) {
179195
180196 AWS_ASSERT (allocator );
181197
@@ -184,6 +200,7 @@ static int s3_cancel_test_helper_ex(
184200
185201 struct s3_cancel_test_user_data test_user_data = {
186202 .type = cancel_type ,
203+ .pause = pause ,
187204 };
188205
189206 tester .user_data = & test_user_data ;
@@ -221,13 +238,49 @@ static int s3_cancel_test_helper_ex(
221238 };
222239
223240 ASSERT_SUCCESS (aws_s3_tester_send_meta_request_with_options (& tester , & options , & meta_request_test_results ));
224- ASSERT_INT_EQUALS (AWS_ERROR_S3_CANCELED , meta_request_test_results .finished_error_code );
241+ int expected_error_code = pause ? AWS_ERROR_S3_PAUSED : AWS_ERROR_S3_CANCELED ;
242+ ASSERT_INT_EQUALS (expected_error_code , meta_request_test_results .finished_error_code );
243+
244+ if (cancel_type == S3_UPDATE_CANCEL_TYPE_MPU_ONGOING_HTTP_REQUESTS ) {
245+ /* Check the metric and see we have at least a request completed with AWS_ERROR_S3_CANCELED */
246+ /* The meta request completed, we can access the synced data now. */
247+ struct aws_array_list * metrics_list = & meta_request_test_results .synced_data .metrics ;
248+ bool cancelled_successfully = false;
249+ for (size_t i = 0 ; i < aws_array_list_length (metrics_list ); ++ i ) {
250+ struct aws_s3_request_metrics * metrics = NULL ;
251+ aws_array_list_get_at (metrics_list , (void * * )& metrics , i );
252+ if (metrics -> crt_info_metrics .error_code == expected_error_code ) {
253+ cancelled_successfully = true;
254+ break ;
255+ }
256+ }
257+ ASSERT_TRUE (cancelled_successfully );
258+ }
225259
226260 aws_s3_meta_request_test_results_clean_up (& meta_request_test_results );
227-
228- if (cancel_type != S3_UPDATE_CANCEL_TYPE_MPU_CREATE_NOT_SENT ) {
261+ if (cancel_type != S3_UPDATE_CANCEL_TYPE_MPU_CREATE_NOT_SENT && !pause ) {
229262 ASSERT_TRUE (test_user_data .abort_successful );
230263 }
264+ if (pause ) {
265+ /* Resume the paused request. */
266+ ASSERT_NOT_NULL (test_user_data .resume_token );
267+ test_user_data .type = S3_UPDATE_CANCEL_TYPE_NO_CANCEL ;
268+ struct aws_s3_tester_meta_request_options resume_options = {
269+ .allocator = allocator ,
270+ .client = client ,
271+ .meta_request_type = AWS_S3_META_REQUEST_TYPE_PUT_OBJECT ,
272+ .validate_type = AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_SUCCESS ,
273+ .put_options =
274+ {
275+ .ensure_multipart = true,
276+ .async_input_stream = async_input_stream ,
277+ .resume_token = test_user_data .resume_token ,
278+ },
279+ };
280+
281+ ASSERT_SUCCESS (aws_s3_tester_send_meta_request_with_options (& tester , & resume_options , NULL ));
282+ aws_s3_meta_request_resume_token_release (test_user_data .resume_token );
283+ }
231284
232285 /* TODO: perform additional verification with list-multipart-uploads */
233286
@@ -284,7 +337,7 @@ static int s3_cancel_test_helper_ex(
284337}
285338
286339static int s3_cancel_test_helper (struct aws_allocator * allocator , enum s3_update_cancel_type cancel_type ) {
287- return s3_cancel_test_helper_ex (allocator , cancel_type , false /*async_input_stream*/ );
340+ return s3_cancel_test_helper_ex (allocator , cancel_type , false /*async_input_stream*/ , false /*pause*/ );
288341}
289342
290343static int s3_cancel_test_helper_fc (
@@ -459,8 +512,8 @@ AWS_TEST_CASE(test_s3_cancel_mpu_one_part_completed_async, s_test_s3_cancel_mpu_
459512static int s_test_s3_cancel_mpu_one_part_completed_async (struct aws_allocator * allocator , void * ctx ) {
460513 (void )ctx ;
461514
462- ASSERT_SUCCESS (
463- s3_cancel_test_helper_ex ( allocator , S3_UPDATE_CANCEL_TYPE_MPU_ONE_PART_COMPLETED , true /*async_input_stream*/ ));
515+ ASSERT_SUCCESS (s3_cancel_test_helper_ex (
516+ allocator , S3_UPDATE_CANCEL_TYPE_MPU_ONE_PART_COMPLETED , true /*async_input_stream*/ , false /*pause */ ));
464517
465518 return 0 ;
466519}
@@ -474,6 +527,25 @@ static int s_test_s3_cancel_mpu_all_parts_completed(struct aws_allocator *alloca
474527 return 0 ;
475528}
476529
530+ AWS_TEST_CASE (test_s3_cancel_mpu_ongoing_http_requests , s_test_s3_cancel_mpu_ongoing_http_requests )
531+ static int s_test_s3_cancel_mpu_ongoing_http_requests (struct aws_allocator * allocator , void * ctx ) {
532+ (void )ctx ;
533+
534+ ASSERT_SUCCESS (s3_cancel_test_helper (allocator , S3_UPDATE_CANCEL_TYPE_MPU_ONGOING_HTTP_REQUESTS ));
535+
536+ return 0 ;
537+ }
538+
539+ AWS_TEST_CASE (test_s3_pause_mpu_ongoing_http_requests , s_test_s3_pause_mpu_ongoing_http_requests )
540+ static int s_test_s3_pause_mpu_ongoing_http_requests (struct aws_allocator * allocator , void * ctx ) {
541+ (void )ctx ;
542+
543+ ASSERT_SUCCESS (s3_cancel_test_helper_ex (
544+ allocator , S3_UPDATE_CANCEL_TYPE_MPU_ONGOING_HTTP_REQUESTS , false /*async_input_stream*/ , true /*pause*/ ));
545+
546+ return 0 ;
547+ }
548+
477549AWS_TEST_CASE (test_s3_cancel_mpd_nothing_sent , s_test_s3_cancel_mpd_nothing_sent )
478550static int s_test_s3_cancel_mpd_nothing_sent (struct aws_allocator * allocator , void * ctx ) {
479551 (void )ctx ;
0 commit comments