1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 
6 #include "aws/s3/private/s3_client_impl.h"
7 #include "aws/s3/private/s3_meta_request_impl.h"
8 #include "aws/s3/private/s3_request_messages.h"
9 #include "aws/s3/private/s3_util.h"
10 #include "s3_tester.h"
11 #include <aws/common/atomics.h>
12 #include <aws/common/byte_buf.h>
13 #include <aws/common/clock.h>
14 #include <aws/common/common.h>
15 #include <aws/common/ref_count.h>
16 #include <aws/common/xml_parser.h>
17 #include <aws/http/request_response.h>
18 #include <aws/io/stream.h>
19 #include <aws/io/tls_channel_handler.h>
20 #include <aws/testing/aws_test_harness.h>
21 #include <inttypes.h>
22 
23 static const struct aws_http_header get_object_test_headers[] = {
24     {
25         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Host"),
26         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("HostValue"),
27     },
28     {
29         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("If-Match"),
30         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("If-MatchValue"),
31     },
32     {
33         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("If-Modified-Since"),
34         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("If-Modified-SinceValue"),
35     },
36     {
37         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("If-None-Match"),
38         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("If-None-MatchValue"),
39     },
40     {
41         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Range"),
42         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("RangeValue"),
43     },
44     {
45         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-customer-algorithm"),
46         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-customer-algorithmValue"),
47     },
48     {
49         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-customer-key"),
50         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-customer-keyValue"),
51     },
52     {
53         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-customer-key-MD5"),
54         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-customer-key-MD5Value"),
55     },
56     {
57         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-request-payer"),
58         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-request-payerValue"),
59     },
60     {
61         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-expected-bucket-owner"),
62         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-expected-bucket-ownerValue"),
63     },
64 };
65 
66 static const struct aws_http_header s_put_object_test_headers[] = {
67     {
68         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-acl"),
69         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ACLValue"),
70     },
71     {
72         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Cache-Control"),
73         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("CacheControlValue"),
74     },
75     {
76         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-Disposition"),
77         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ContentDispositionValue"),
78     },
79     {
80         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-Encoding"),
81         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ContentEncodingValue"),
82     },
83     {
84         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-Language"),
85         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ContentLanguageValue"),
86     },
87     {
88         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-Length"),
89         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ContentLengthValue"),
90     },
91     {
92         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-MD5"),
93         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ContentMD5Value"),
94     },
95     {
96         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-Type"),
97         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ContentTypeValue"),
98     },
99     {
100         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Expires"),
101         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ExpiresValue"),
102     },
103     {
104         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-grant-full-control"),
105         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GrantFullControlValue"),
106     },
107     {
108         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-grant-read"),
109         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GrantReadValue"),
110     },
111     {
112         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-grant-read-acp"),
113         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GrantReadACPValue"),
114     },
115     {
116         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-grant-write-acp"),
117         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("GrantWriteACPValue"),
118     },
119     {
120         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption"),
121         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ServerSideEncryptionValue"),
122     },
123     {
124         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-storage-class"),
125         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("StorageClassValue"),
126     },
127     {
128         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-website-redirect-location"),
129         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("WebsiteRedirectLocationValue"),
130     },
131     {
132         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-customer-algorithm"),
133         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("SSECustomerAlgorithmValue"),
134     },
135     {
136         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-customer-key"),
137         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("SSECustomerKeyValue"),
138     },
139     {
140         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-customer-key-MD5"),
141         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("SSECustomerKeyMD5Value"),
142     },
143     {
144         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-aws-kms-key-id"),
145         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("SSEKMSKeyIdValue"),
146     },
147     {
148         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-context"),
149         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("SSEKMSEncryptionContextValue"),
150     },
151     {
152         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-bucket-key-enabled"),
153         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("BucketKeyEnabledValue"),
154     },
155     {
156         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-request-payer"),
157         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("RequestPayerValue"),
158     },
159     {
160         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-tagging"),
161         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("TaggingValue"),
162     },
163     {
164         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-object-lock-mode"),
165         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ObjectLockModeValue"),
166     },
167     {
168         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-object-lock-retain-until-date"),
169         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ObjectLockRetainUntilDateValue"),
170     },
171     {
172         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-object-lock-legal-hold"),
173         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ObjectLockLegalHoldStatusValue"),
174     },
175     {
176         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-expected-bucket-owner"),
177         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ExpectedBucketOwnerValue"),
178     },
179 };
180 
s_fill_byte_buf(struct aws_byte_buf * buffer,struct aws_allocator * allocator,size_t buffer_size)181 static int s_fill_byte_buf(struct aws_byte_buf *buffer, struct aws_allocator *allocator, size_t buffer_size) {
182     ASSERT_TRUE(buffer != NULL);
183     ASSERT_TRUE(allocator != NULL);
184     ASSERT_TRUE(buffer_size > 0);
185 
186     ASSERT_SUCCESS(aws_byte_buf_init(buffer, allocator, buffer_size));
187 
188     srand(0);
189 
190     for (size_t i = 0; i < buffer_size; ++i) {
191         const char single_char = (char)(rand() % (int)('z' - 'a') + (int)'a');
192 
193         struct aws_byte_cursor single_char_cursor = {
194             .ptr = (uint8_t *)&single_char,
195             .len = 1,
196         };
197 
198         ASSERT_SUCCESS(aws_byte_buf_append(buffer, &single_char_cursor));
199     }
200 
201     return AWS_OP_SUCCESS;
202 }
203 
s_test_http_headers_match(struct aws_allocator * allocator,struct aws_http_message * message0,struct aws_http_message * message1,const struct aws_byte_cursor * excluded_message0_headers,size_t excluded_message0_headers_count,const struct aws_byte_cursor * message1_header_exceptions,size_t message1_header_exceptions_count)204 static int s_test_http_headers_match(
205     struct aws_allocator *allocator,
206     struct aws_http_message *message0,
207     struct aws_http_message *message1,
208 
209     /* Headers that we know are in message0, but should NOT be in message1 */
210     const struct aws_byte_cursor *excluded_message0_headers,
211     size_t excluded_message0_headers_count,
212 
213     /* Headers in message1 that are okay to be in message1 even if they are in the excluded list or are not in
214        message0.*/
215     const struct aws_byte_cursor *message1_header_exceptions,
216     size_t message1_header_exceptions_count) {
217     ASSERT_TRUE(message0 != NULL);
218     ASSERT_TRUE(message1 != NULL);
219     ASSERT_TRUE(excluded_message0_headers != NULL || excluded_message0_headers_count == 0);
220     ASSERT_TRUE(message1_header_exceptions != NULL || message1_header_exceptions_count == 0);
221 
222     struct aws_http_headers *message0_headers = aws_http_message_get_headers(message0);
223     ASSERT_TRUE(message0_headers != NULL);
224 
225     struct aws_http_headers *message1_headers = aws_http_message_get_headers(message1);
226     ASSERT_TRUE(message1_headers != NULL);
227 
228     struct aws_http_headers *expected_message0_headers = aws_http_headers_new(allocator);
229 
230     /* Copy message1 headers to expected_message0_headers. With upcoming adds/removes, it should transform back into
231      * message0.
232      */
233     for (size_t i = 0; i < aws_http_headers_count(message1_headers); ++i) {
234         struct aws_http_header message1_header;
235         AWS_ZERO_STRUCT(message1_header);
236         ASSERT_SUCCESS(aws_http_headers_get_index(message1_headers, i, &message1_header));
237         ASSERT_SUCCESS(aws_http_headers_add(expected_message0_headers, message1_header.name, message1_header.value));
238     }
239 
240     /* Go through all of the headers that were originally removed from message1 after it was copied from message0. */
241     for (size_t i = 0; i < excluded_message0_headers_count; ++i) {
242         const struct aws_byte_cursor *excluded_header_name = &excluded_message0_headers[i];
243 
244         bool header_existance_is_valid = false;
245 
246         /* If the heaer is in the exception list, it's okay for message1 to have. (It may have been re-added.) */
247         for (size_t j = 0; j < message1_header_exceptions_count; ++j) {
248             if (aws_byte_cursor_eq(excluded_header_name, &message1_header_exceptions[j])) {
249                 header_existance_is_valid = true;
250                 break;
251             }
252         }
253 
254         /* Try to get the header from message1. */
255         struct aws_byte_cursor message1_header_value;
256         AWS_ZERO_STRUCT(message1_header_value);
257         int result = aws_http_headers_get(message1_headers, *excluded_header_name, &message1_header_value);
258 
259         if (header_existance_is_valid) {
260 
261             /* If this header is allowed to exist in message1, then we don't need to assert on its existance or
262              * non-existance.  But we do want to erase it from the expected_message0_headers, since its value may be
263              * different from that in message0. */
264             if (result == AWS_OP_SUCCESS) {
265                 ASSERT_SUCCESS(aws_http_headers_erase(expected_message0_headers, *excluded_header_name));
266             }
267 
268         } else {
269             /* In this case, message1 should not have the header. */
270             ASSERT_TRUE(result == AWS_OP_ERR && aws_last_error() == AWS_ERROR_HTTP_HEADER_NOT_FOUND);
271         }
272 
273         /* At this point, expected_message0_headers should not have the excluded header in it. Add a copy of the header
274          * from message0 to expected_message0_headers to further transform it toward being a copy of message0 headers.
275          */
276         struct aws_byte_cursor message0_header_value;
277         AWS_ZERO_STRUCT(message0_header_value);
278         if (aws_http_headers_get(message0_headers, *excluded_header_name, &message0_header_value) == AWS_OP_SUCCESS) {
279             ASSERT_SUCCESS(
280                 aws_http_headers_add(expected_message0_headers, *excluded_header_name, message0_header_value));
281         }
282     }
283 
284     /* message0_headers should now match expected_message0_headers */
285     {
286         ASSERT_TRUE(aws_http_headers_count(message0_headers) == aws_http_headers_count(expected_message0_headers));
287 
288         for (size_t i = 0; i < aws_http_headers_count(message0_headers); ++i) {
289             struct aws_http_header message0_header;
290             AWS_ZERO_STRUCT(message0_header);
291             ASSERT_SUCCESS(aws_http_headers_get_index(message0_headers, i, &message0_header));
292 
293             struct aws_byte_cursor expected_message0_header_value;
294             AWS_ZERO_STRUCT(expected_message0_header_value);
295             ASSERT_SUCCESS(
296                 aws_http_headers_get(expected_message0_headers, message0_header.name, &expected_message0_header_value));
297 
298             ASSERT_TRUE(aws_byte_cursor_eq(&message0_header.value, &expected_message0_header_value));
299         }
300     }
301 
302     aws_http_headers_release(expected_message0_headers);
303 
304     return AWS_OP_SUCCESS;
305 }
306 
s_test_http_messages_match(struct aws_allocator * allocator,struct aws_http_message * message0,struct aws_http_message * message1,const struct aws_byte_cursor * excluded_headers,size_t excluded_headers_count)307 static int s_test_http_messages_match(
308     struct aws_allocator *allocator,
309     struct aws_http_message *message0,
310     struct aws_http_message *message1,
311     const struct aws_byte_cursor *excluded_headers,
312     size_t excluded_headers_count) {
313     ASSERT_TRUE(message0 != NULL);
314     ASSERT_TRUE(message1 != NULL);
315     ASSERT_TRUE(excluded_headers != NULL || excluded_headers_count == 0);
316 
317     struct aws_byte_cursor request_path;
318     AWS_ZERO_STRUCT(request_path);
319     ASSERT_SUCCESS(aws_http_message_get_request_path(message0, &request_path));
320 
321     struct aws_byte_cursor copied_request_path;
322     AWS_ZERO_STRUCT(copied_request_path);
323     ASSERT_SUCCESS(aws_http_message_get_request_path(message1, &copied_request_path));
324 
325     ASSERT_TRUE(aws_byte_cursor_eq(&request_path, &copied_request_path));
326 
327     struct aws_byte_cursor request_method;
328     AWS_ZERO_STRUCT(request_method);
329     ASSERT_SUCCESS(aws_http_message_get_request_method(message0, &request_method));
330 
331     struct aws_byte_cursor copied_request_method;
332     AWS_ZERO_STRUCT(copied_request_method);
333     ASSERT_SUCCESS(aws_http_message_get_request_method(message1, &copied_request_method));
334 
335     ASSERT_TRUE(aws_byte_cursor_eq(&request_method, &copied_request_method));
336 
337     ASSERT_SUCCESS(
338         s_test_http_headers_match(allocator, message0, message1, excluded_headers, excluded_headers_count, NULL, 0));
339 
340     return AWS_OP_SUCCESS;
341 }
342 
s_test_http_message_request_path(struct aws_http_message * message,const struct aws_byte_cursor * request_path)343 static int s_test_http_message_request_path(
344     struct aws_http_message *message,
345     const struct aws_byte_cursor *request_path) {
346 
347     struct aws_byte_cursor message_request_path;
348     AWS_ZERO_STRUCT(message_request_path);
349     ASSERT_SUCCESS(aws_http_message_get_request_path(message, &message_request_path));
350 
351     ASSERT_TRUE(aws_byte_cursor_eq(&message_request_path, request_path));
352 
353     return AWS_OP_SUCCESS;
354 }
355 
s_test_http_message_request_method(struct aws_http_message * message,const char * method)356 static int s_test_http_message_request_method(struct aws_http_message *message, const char *method) {
357 
358     struct aws_byte_cursor message_request_method;
359     AWS_ZERO_STRUCT(message_request_method);
360     ASSERT_SUCCESS(aws_http_message_get_request_method(message, &message_request_method));
361 
362     struct aws_byte_cursor method_cursor = aws_byte_cursor_from_c_str(method);
363 
364     ASSERT_TRUE(aws_byte_cursor_eq(&message_request_method, &method_cursor));
365 
366     return AWS_OP_SUCCESS;
367 }
368 
s_test_http_message_body_stream(struct aws_allocator * allocator,struct aws_http_message * derived_message,struct aws_byte_buf * expected_stream_contents)369 static int s_test_http_message_body_stream(
370     struct aws_allocator *allocator,
371     struct aws_http_message *derived_message,
372     struct aws_byte_buf *expected_stream_contents) {
373     ASSERT_TRUE(derived_message != NULL);
374     ASSERT_TRUE(expected_stream_contents != NULL);
375 
376     struct aws_http_headers *headers = aws_http_message_get_headers(derived_message);
377     ASSERT_TRUE(headers != NULL);
378 
379     struct aws_input_stream *body_stream = aws_http_message_get_body_stream(derived_message);
380     ASSERT_TRUE(body_stream != NULL);
381 
382     /* Check for the content length header. */
383     struct aws_byte_cursor content_length_header_value;
384     AWS_ZERO_STRUCT(content_length_header_value);
385     ASSERT_SUCCESS(aws_http_headers_get(headers, g_content_length_header_name, &content_length_header_value));
386 
387     struct aws_string *content_length_header_str = aws_string_new_from_cursor(allocator, &content_length_header_value);
388     uint32_t content_length = (uint32_t)atoi((const char *)content_length_header_str->bytes);
389     ASSERT_TRUE(content_length == (uint32_t)expected_stream_contents->len);
390     aws_string_destroy(content_length_header_str);
391 
392     /* Check that the stream data is equal to the original buffer data. */
393     struct aws_byte_buf stream_read_buffer;
394     ASSERT_SUCCESS(aws_byte_buf_init(&stream_read_buffer, allocator, expected_stream_contents->len));
395     ASSERT_SUCCESS(aws_input_stream_read(body_stream, &stream_read_buffer));
396     ASSERT_TRUE(aws_byte_buf_eq(expected_stream_contents, &stream_read_buffer));
397     aws_byte_buf_clean_up(&stream_read_buffer);
398 
399     /* There should be no data left in the stream. */
400     struct aws_byte_buf stream_overread_buffer;
401     ASSERT_SUCCESS(aws_byte_buf_init(&stream_overread_buffer, allocator, expected_stream_contents->len));
402     ASSERT_SUCCESS(aws_input_stream_read(body_stream, &stream_overread_buffer));
403     ASSERT_TRUE(stream_overread_buffer.len == 0);
404     aws_byte_buf_clean_up(&stream_overread_buffer);
405 
406     return AWS_OP_SUCCESS;
407 }
408 
s_create_get_object_message(struct aws_allocator * allocator,const struct aws_byte_cursor * path,struct aws_http_message ** out_message)409 int s_create_get_object_message(
410     struct aws_allocator *allocator,
411     const struct aws_byte_cursor *path,
412     struct aws_http_message **out_message) {
413     ASSERT_TRUE(out_message != NULL);
414     ASSERT_TRUE(*out_message == NULL);
415 
416     struct aws_http_message *message = aws_http_message_new_request(allocator);
417     ASSERT_TRUE(message != NULL);
418 
419     ASSERT_SUCCESS(aws_http_message_set_request_path(message, *path));
420     ASSERT_SUCCESS(aws_http_message_set_request_method(message, aws_byte_cursor_from_c_str("GET")));
421 
422     for (size_t i = 0; i < AWS_ARRAY_SIZE(get_object_test_headers); ++i) {
423         ASSERT_SUCCESS(aws_http_message_add_header(message, get_object_test_headers[i]));
424     }
425 
426     *out_message = message;
427 
428     return AWS_OP_SUCCESS;
429 }
430 
s_create_put_object_message(struct aws_allocator * allocator,const struct aws_byte_cursor * path,struct aws_http_message ** out_message)431 int s_create_put_object_message(
432     struct aws_allocator *allocator,
433     const struct aws_byte_cursor *path,
434     struct aws_http_message **out_message) {
435     ASSERT_TRUE(out_message != NULL);
436     ASSERT_TRUE(*out_message == NULL);
437 
438     struct aws_http_message *message = aws_http_message_new_request(allocator);
439     ASSERT_TRUE(message != NULL);
440 
441     ASSERT_SUCCESS(aws_http_message_set_request_path(message, *path));
442     ASSERT_SUCCESS(aws_http_message_set_request_method(message, aws_byte_cursor_from_c_str("PUT")));
443 
444     for (size_t i = 0; i < AWS_ARRAY_SIZE(s_put_object_test_headers); ++i) {
445         ASSERT_SUCCESS(aws_http_message_add_header(message, s_put_object_test_headers[i]));
446     }
447 
448     *out_message = message;
449 
450     return AWS_OP_SUCCESS;
451     ;
452 }
453 
AWS_TEST_CASE(test_s3_copy_http_message,s_test_s3_copy_http_message)454 AWS_TEST_CASE(test_s3_copy_http_message, s_test_s3_copy_http_message)
455 static int s_test_s3_copy_http_message(struct aws_allocator *allocator, void *ctx) {
456     (void)ctx;
457 
458     const struct aws_byte_cursor request_method = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("RequestMethod");
459     const struct aws_byte_cursor request_path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("RequestPath");
460 
461     const struct aws_http_header included_header = {
462         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("IncludedHeader"),
463         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("IncludedHeaderValue"),
464     };
465 
466     const struct aws_http_header excluded_header = {
467         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ExcludedHeader"),
468         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ExcludedHeaderValue"),
469     };
470 
471     struct aws_http_message *message = aws_http_message_new_request(allocator);
472     ASSERT_TRUE(message != NULL);
473     ASSERT_SUCCESS(aws_http_message_set_request_method(message, request_method));
474     ASSERT_SUCCESS(aws_http_message_set_request_path(message, request_path));
475 
476     struct aws_http_headers *message_headers = aws_http_message_get_headers(message);
477     ASSERT_TRUE(message != NULL);
478     ASSERT_SUCCESS(aws_http_headers_add(message_headers, included_header.name, included_header.value));
479     ASSERT_SUCCESS(aws_http_headers_add(message_headers, excluded_header.name, excluded_header.value));
480 
481     struct aws_http_message *copied_message =
482         aws_s3_message_util_copy_http_message(allocator, message, &excluded_header.name, 1);
483     ASSERT_TRUE(copied_message != NULL);
484 
485     ASSERT_SUCCESS(s_test_http_messages_match(allocator, message, copied_message, &excluded_header.name, 1));
486 
487     aws_http_message_release(copied_message);
488     aws_http_message_release(message);
489 
490     return 0;
491 }
492 
AWS_TEST_CASE(test_s3_message_util_assign_body,s_test_s3_message_util_assign_body)493 AWS_TEST_CASE(test_s3_message_util_assign_body, s_test_s3_message_util_assign_body)
494 static int s_test_s3_message_util_assign_body(struct aws_allocator *allocator, void *ctx) {
495     (void)ctx;
496 
497     struct aws_http_message *message = aws_http_message_new_request(allocator);
498 
499     const size_t test_buffer_size = 42;
500     struct aws_byte_buf test_buffer;
501     ASSERT_SUCCESS(s_fill_byte_buf(&test_buffer, allocator, test_buffer_size));
502 
503     struct aws_input_stream *input_stream = aws_s3_message_util_assign_body(allocator, &test_buffer, message);
504     ASSERT_TRUE(input_stream != NULL);
505 
506     ASSERT_TRUE(aws_http_message_get_body_stream(message) == input_stream);
507     ASSERT_SUCCESS(s_test_http_message_body_stream(allocator, message, &test_buffer));
508 
509     aws_input_stream_destroy(input_stream);
510     aws_byte_buf_clean_up(&test_buffer);
511     aws_http_message_release(message);
512 
513     return 0;
514 }
515 
AWS_TEST_CASE(test_s3_ranged_get_object_message_new,s_test_s3_ranged_get_object_message_new)516 AWS_TEST_CASE(test_s3_ranged_get_object_message_new, s_test_s3_ranged_get_object_message_new)
517 static int s_test_s3_ranged_get_object_message_new(struct aws_allocator *allocator, void *ctx) {
518     (void)ctx;
519 
520     const struct aws_byte_cursor test_path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath");
521 
522     struct aws_http_message *original_message = NULL;
523     ASSERT_SUCCESS(s_create_get_object_message(allocator, &test_path, &original_message));
524     ASSERT_TRUE(original_message != NULL);
525 
526     {
527         char expected_range_value_buffer[128] = "bytes=42-83";
528         struct aws_byte_cursor expected_range_value_cursor = aws_byte_cursor_from_c_str(expected_range_value_buffer);
529 
530         struct aws_http_message *get_object_message =
531             aws_s3_ranged_get_object_message_new(allocator, original_message, 42, 83);
532         ASSERT_TRUE(get_object_message != NULL);
533 
534         struct aws_http_headers *headers = aws_http_message_get_headers(get_object_message);
535         ASSERT_TRUE(headers != NULL);
536 
537         struct aws_byte_cursor range_header_value;
538         AWS_ZERO_STRUCT(range_header_value);
539         ASSERT_SUCCESS(aws_http_headers_get(headers, g_range_header_name, &range_header_value));
540 
541         ASSERT_TRUE(aws_byte_cursor_eq(&range_header_value, &expected_range_value_cursor));
542 
543         s_test_http_message_request_method(get_object_message, "GET");
544 
545         aws_http_message_release(get_object_message);
546     }
547 
548     aws_http_message_release(original_message);
549 
550     return 0;
551 }
552 
AWS_TEST_CASE(test_s3_set_multipart_request_path,s_test_s3_set_multipart_request_path)553 AWS_TEST_CASE(test_s3_set_multipart_request_path, s_test_s3_set_multipart_request_path)
554 static int s_test_s3_set_multipart_request_path(struct aws_allocator *allocator, void *ctx) {
555     (void)ctx;
556 
557 #define TEST_PATH "/TestPath"
558 #define TEST_PATH_WITH_PARAMS "/TestPath?arg=value"
559 #define UPLOAD_ID "test_upload_id"
560 #define UPLOAD_ID_PARAM "uploadId=test_upload_id"
561 #define PART_NUMBER 4
562 #define UPLOADS_PARAM "uploads"
563 
564     const struct aws_byte_cursor test_path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(TEST_PATH);
565     const struct aws_byte_cursor test_path_with_params = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(TEST_PATH_WITH_PARAMS);
566 
567     struct aws_byte_cursor test_path_permutations[] = {
568         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath"),
569         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?uploads"),
570         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?partNumber=4"),
571         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?partNumber=4&uploads"),
572         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?uploadId=test_upload_id"),
573         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?uploadId=test_upload_id&uploads"),
574         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?partNumber=4&uploadId=test_upload_id"),
575         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?partNumber=4&uploadId=test_upload_id&uploads"),
576     };
577 
578     struct aws_byte_cursor test_path_with_params_permutations[] = {
579         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?arg=value"),
580         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?arg=value&uploads"),
581         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?arg=value&partNumber=4"),
582         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?arg=value&partNumber=4&uploads"),
583         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?arg=value&uploadId=test_upload_id"),
584         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?arg=value&uploadId=test_upload_id&uploads"),
585         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?arg=value&partNumber=4&uploadId=test_upload_id"),
586         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?arg=value&partNumber=4&uploadId=test_upload_id&uploads"),
587     };
588 
589     const uint32_t num_permutations = 8;
590 
591     for (uint32_t i = 0; i < num_permutations; ++i) {
592         struct aws_string *upload_id = NULL;
593         uint32_t part_number = 0;
594         bool uploads_param = false;
595 
596         if (i & 0x4) {
597             upload_id = aws_string_new_from_c_str(allocator, UPLOAD_ID);
598         }
599 
600         if (i & 0x2) {
601             part_number = PART_NUMBER;
602         }
603 
604         if (i & 0x1) {
605             uploads_param = true;
606         }
607 
608         {
609             struct aws_http_message *message = NULL;
610             ASSERT_SUCCESS(s_create_put_object_message(allocator, &test_path, &message));
611 
612             ASSERT_SUCCESS(aws_s3_message_util_set_multipart_request_path(
613                 allocator, upload_id, part_number, uploads_param, message));
614 
615             ASSERT_SUCCESS(s_test_http_message_request_path(message, &test_path_permutations[i]));
616 
617             aws_http_message_release(message);
618         }
619 
620         {
621             struct aws_http_message *message_with_params = NULL;
622             ASSERT_SUCCESS(s_create_put_object_message(allocator, &test_path_with_params, &message_with_params));
623 
624             ASSERT_SUCCESS(aws_s3_message_util_set_multipart_request_path(
625                 allocator, upload_id, part_number, uploads_param, message_with_params));
626 
627             ASSERT_SUCCESS(
628                 s_test_http_message_request_path(message_with_params, &test_path_with_params_permutations[i]));
629 
630             aws_http_message_release(message_with_params);
631         }
632 
633         aws_string_destroy(upload_id);
634     }
635 
636 #undef TEST_PATH
637 #undef TEST_PATH_WITH_PARAMS
638 #undef UPLOAD_ID
639 #undef UPLOAD_ID_PARAM
640 #undef PART_NUMBER
641 #undef UPLOADS_PARAM
642 
643     return 0;
644 }
645 
AWS_TEST_CASE(test_s3_create_multipart_upload_message_new,s_test_s3_create_multipart_upload_message_new)646 AWS_TEST_CASE(test_s3_create_multipart_upload_message_new, s_test_s3_create_multipart_upload_message_new)
647 static int s_test_s3_create_multipart_upload_message_new(struct aws_allocator *allocator, void *ctx) {
648     (void)ctx;
649 
650     struct aws_byte_cursor path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath");
651     struct aws_byte_cursor expected_create_path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/TestPath?uploads");
652 
653     struct aws_http_message *original_message = NULL;
654     ASSERT_SUCCESS(s_create_put_object_message(allocator, &path, &original_message));
655     ASSERT_TRUE(original_message != NULL);
656 
657     struct aws_http_message *create_multipart_upload_message =
658         aws_s3_create_multipart_upload_message_new(allocator, original_message);
659     ASSERT_TRUE(create_multipart_upload_message != NULL);
660 
661     ASSERT_SUCCESS(s_test_http_message_request_method(create_multipart_upload_message, "POST"));
662     ASSERT_SUCCESS(s_test_http_message_request_path(create_multipart_upload_message, &expected_create_path));
663     ASSERT_SUCCESS(s_test_http_headers_match(
664         allocator,
665         original_message,
666         create_multipart_upload_message,
667         g_s3_create_multipart_upload_excluded_headers,
668         g_s3_create_multipart_upload_excluded_headers_count,
669         NULL,
670         0));
671 
672     aws_http_message_release(create_multipart_upload_message);
673     aws_http_message_release(original_message);
674 
675     return 0;
676 }
677 
AWS_TEST_CASE(test_s3_upload_part_message_new,s_test_s3_upload_part_message_new)678 AWS_TEST_CASE(test_s3_upload_part_message_new, s_test_s3_upload_part_message_new)
679 static int s_test_s3_upload_part_message_new(struct aws_allocator *allocator, void *ctx) {
680     (void)ctx;
681 
682 #define STRINGIFY_HELPER(x) #x
683 #define STRINGIFY(x) STRINGIFY_HELPER(x)
684 #define TEST_PATH "/TestPath"
685 #define UPLOAD_ID "test_upload_id"
686 #define PART_NUMBER 4
687 #define PART_NUMBER_STR "?partNumber=" STRINGIFY(PART_NUMBER)
688 #define EXPECTED_UPLOAD_PART_PATH TEST_PATH PART_NUMBER_STR "&uploadId=" UPLOAD_ID
689 
690     const struct aws_byte_cursor header_exclude_exceptions[] = {
691         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-Length"),
692     };
693 
694     struct aws_byte_cursor path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(TEST_PATH);
695     struct aws_byte_cursor expected_create_path = aws_byte_cursor_from_c_str(EXPECTED_UPLOAD_PART_PATH);
696 
697     struct aws_http_message *original_message = NULL;
698     ASSERT_SUCCESS(s_create_put_object_message(allocator, &path, &original_message));
699     ASSERT_TRUE(original_message != NULL);
700 
701     const size_t part_buffer_size = 42;
702     struct aws_byte_buf part_buffer;
703     AWS_ZERO_STRUCT(part_buffer);
704     s_fill_byte_buf(&part_buffer, allocator, part_buffer_size);
705 
706     struct aws_string *upload_id = aws_string_new_from_c_str(allocator, UPLOAD_ID);
707 
708     struct aws_http_message *upload_part_message =
709         aws_s3_upload_part_message_new(allocator, original_message, &part_buffer, PART_NUMBER, upload_id, false);
710     ASSERT_TRUE(upload_part_message != NULL);
711 
712     ASSERT_SUCCESS(s_test_http_message_request_method(upload_part_message, "PUT"));
713     ASSERT_SUCCESS(s_test_http_message_request_path(upload_part_message, &expected_create_path));
714     ASSERT_SUCCESS(s_test_http_headers_match(
715         allocator,
716         original_message,
717         upload_part_message,
718         g_s3_upload_part_excluded_headers,
719         g_s3_upload_part_excluded_headers_count,
720         header_exclude_exceptions,
721         AWS_ARRAY_SIZE(header_exclude_exceptions)));
722 
723     ASSERT_SUCCESS(s_test_http_message_body_stream(allocator, upload_part_message, &part_buffer));
724 
725     aws_string_destroy(upload_id);
726     aws_byte_buf_clean_up(&part_buffer);
727 
728     aws_input_stream_destroy(aws_http_message_get_body_stream(upload_part_message));
729     aws_http_message_release(upload_part_message);
730     aws_http_message_release(original_message);
731 
732 #undef STRINGIFY_HELPER
733 #undef STRINGIFY
734 #undef TEST_PATH
735 #undef UPLOAD_ID
736 #undef PART_NUMBER
737 #undef PART_NUMBER_STR
738 #undef EXPECTED_UPLOAD_PART_PATH
739 
740     return 0;
741 }
742 
743 struct complete_multipart_upload_xml_test_data {
744     struct aws_byte_cursor etag_value;
745     struct aws_byte_cursor part_number_value;
746     bool found_etag;
747     bool found_part_number;
748 };
749 
s_complete_multipart_upload_traverse_xml_node(struct aws_xml_parser * parser,struct aws_xml_node * node,void * user_data)750 static bool s_complete_multipart_upload_traverse_xml_node(
751     struct aws_xml_parser *parser,
752     struct aws_xml_node *node,
753     void *user_data) {
754 
755     const struct aws_byte_cursor complete_multipar_upload_tag_name =
756         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("CompleteMultipartUpload");
757     const struct aws_byte_cursor part_tag_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Part");
758     const struct aws_byte_cursor etag_tag_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ETag");
759     const struct aws_byte_cursor part_number_tag_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("PartNumber");
760 
761     struct aws_byte_cursor node_name;
762     AWS_ZERO_STRUCT(node_name);
763 
764     bool keep_traversing = false;
765     struct complete_multipart_upload_xml_test_data *test_data = user_data;
766 
767     /* If we can't get the name of the node, stop traversing. */
768     if (aws_xml_node_get_name(node, &node_name)) {
769         /* Couldn't get the tag name, so nothing to do but stop traversing. */
770     } else if (aws_byte_cursor_eq(&node_name, &complete_multipar_upload_tag_name)) {
771         aws_xml_node_traverse(parser, node, s_complete_multipart_upload_traverse_xml_node, user_data);
772     } else if (aws_byte_cursor_eq(&node_name, &part_tag_name)) {
773         aws_xml_node_traverse(parser, node, s_complete_multipart_upload_traverse_xml_node, user_data);
774     } else if (aws_byte_cursor_eq(&node_name, &etag_tag_name)) {
775 
776         struct aws_byte_cursor node_body;
777         AWS_ZERO_STRUCT(node_body);
778         if (aws_xml_node_as_body(parser, node, &node_body)) {
779             goto finish;
780         }
781 
782         test_data->found_etag = aws_byte_cursor_eq(&node_body, &test_data->etag_value);
783         keep_traversing = true;
784     } else if (aws_byte_cursor_eq(&node_name, &part_number_tag_name)) {
785 
786         struct aws_byte_cursor node_body;
787         AWS_ZERO_STRUCT(node_body);
788         aws_xml_node_as_body(parser, node, &node_body);
789 
790         test_data->found_part_number = aws_byte_cursor_eq(&node_body, &test_data->part_number_value);
791         keep_traversing = true;
792     }
793 
794 finish:
795     return keep_traversing;
796 }
797 
AWS_TEST_CASE(test_s3_complete_multipart_message_new,s_test_s3_complete_multipart_message_new)798 AWS_TEST_CASE(test_s3_complete_multipart_message_new, s_test_s3_complete_multipart_message_new)
799 static int s_test_s3_complete_multipart_message_new(struct aws_allocator *allocator, void *ctx) {
800     (void)ctx;
801 
802 #define TEST_PATH "/TestPath"
803 #define UPLOAD_ID "test_upload_id"
804 #define EXPECTED_UPLOAD_PART_PATH TEST_PATH "?uploadId=" UPLOAD_ID
805 #define ETAG_VALUE "etag_value"
806 
807     struct aws_array_list etags;
808     ASSERT_SUCCESS(aws_array_list_init_dynamic(&etags, allocator, 1, sizeof(struct aws_string *)));
809     struct aws_string *etag = aws_string_new_from_c_str(allocator, ETAG_VALUE);
810     ASSERT_SUCCESS(aws_array_list_push_back(&etags, &etag));
811 
812     const struct aws_byte_cursor header_exclude_exceptions[] = {
813         AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Content-Length"),
814     };
815 
816     struct aws_byte_cursor path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(TEST_PATH);
817     struct aws_byte_cursor expected_create_path = aws_byte_cursor_from_c_str(EXPECTED_UPLOAD_PART_PATH);
818 
819     struct aws_http_message *original_message = NULL;
820     ASSERT_SUCCESS(s_create_put_object_message(allocator, &path, &original_message));
821     ASSERT_TRUE(original_message != NULL);
822 
823     struct aws_string *upload_id = aws_string_new_from_c_str(allocator, UPLOAD_ID);
824 
825     struct aws_byte_buf body_buffer;
826     aws_byte_buf_init(&body_buffer, allocator, 64);
827 
828     struct aws_http_message *complete_multipart_message =
829         aws_s3_complete_multipart_message_new(allocator, original_message, &body_buffer, upload_id, &etags);
830 
831     ASSERT_SUCCESS(s_test_http_message_request_method(complete_multipart_message, "POST"));
832     ASSERT_SUCCESS(s_test_http_message_request_path(complete_multipart_message, &expected_create_path));
833     ASSERT_SUCCESS(s_test_http_headers_match(
834         allocator,
835         original_message,
836         complete_multipart_message,
837         g_s3_complete_multipart_upload_excluded_headers,
838         g_s3_complete_multipart_upload_excluded_headers_count,
839         header_exclude_exceptions,
840         AWS_ARRAY_SIZE(header_exclude_exceptions)));
841 
842     {
843         struct aws_xml_parser_options parser_options = {
844             .doc = aws_byte_cursor_from_buf(&body_buffer),
845         };
846 
847         struct aws_xml_parser *parser = aws_xml_parser_new(allocator, &parser_options);
848 
849         struct complete_multipart_upload_xml_test_data xml_user_data = {
850             .etag_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(ETAG_VALUE),
851             .part_number_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("1"),
852             .found_etag = false,
853             .found_part_number = false,
854         };
855 
856         ASSERT_SUCCESS(
857             aws_xml_parser_parse(parser, s_complete_multipart_upload_traverse_xml_node, (void *)&xml_user_data));
858         aws_xml_parser_destroy(parser);
859 
860         ASSERT_TRUE(xml_user_data.found_etag);
861         ASSERT_TRUE(xml_user_data.found_part_number);
862     }
863 
864     aws_byte_buf_clean_up(&body_buffer);
865     aws_string_destroy(upload_id);
866 
867     aws_input_stream_destroy(aws_http_message_get_body_stream(complete_multipart_message));
868     aws_http_message_release(complete_multipart_message);
869     aws_http_message_release(original_message);
870 
871     aws_string_destroy(etag);
872     aws_array_list_clean_up(&etags);
873 
874 #undef TEST_PATH
875 #undef UPLOAD_ID
876 #undef EXPECTED_UPLOAD_PART_PATH
877 #undef ETAG_VALUE
878 
879     return 0;
880 }
881 
AWS_TEST_CASE(test_s3_abort_multipart_upload_message_new,s_test_s3_abort_multipart_upload_message_newt)882 AWS_TEST_CASE(test_s3_abort_multipart_upload_message_new, s_test_s3_abort_multipart_upload_message_newt)
883 static int s_test_s3_abort_multipart_upload_message_newt(struct aws_allocator *allocator, void *ctx) {
884     (void)ctx;
885 
886 #define TEST_PATH "/TestPath"
887 #define UPLOAD_ID "test_upload_id"
888 #define EXPECTED_UPLOAD_PART_PATH TEST_PATH "?uploadId=" UPLOAD_ID
889 
890     struct aws_byte_cursor path = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(TEST_PATH);
891     struct aws_byte_cursor expected_create_path = aws_byte_cursor_from_c_str(EXPECTED_UPLOAD_PART_PATH);
892 
893     struct aws_http_message *original_message = NULL;
894     ASSERT_SUCCESS(s_create_put_object_message(allocator, &path, &original_message));
895     ASSERT_TRUE(original_message != NULL);
896 
897     struct aws_string *upload_id = aws_string_new_from_c_str(allocator, UPLOAD_ID);
898 
899     struct aws_http_message *abort_upload_message =
900         aws_s3_abort_multipart_upload_message_new(allocator, original_message, upload_id);
901     ASSERT_TRUE(abort_upload_message != NULL);
902 
903     ASSERT_SUCCESS(s_test_http_message_request_method(abort_upload_message, "DELETE"));
904     ASSERT_SUCCESS(s_test_http_message_request_path(abort_upload_message, &expected_create_path));
905     ASSERT_SUCCESS(s_test_http_headers_match(
906         allocator,
907         original_message,
908         abort_upload_message,
909         g_s3_abort_multipart_upload_excluded_headers,
910         g_s3_abort_multipart_upload_excluded_headers_count,
911         NULL,
912         0));
913 
914     aws_string_destroy(upload_id);
915 
916     aws_http_message_release(abort_upload_message);
917     aws_http_message_release(original_message);
918 
919 #undef TEST_PATH
920 #undef UPLOAD_ID
921 #undef EXPECTED_UPLOAD_PART_PATH
922 
923     return 0;
924 }
925