1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 
6 #include "s3_tester.h"
7 #include "aws/s3/private/s3_auto_ranged_get.h"
8 #include "aws/s3/private/s3_client_impl.h"
9 #include "aws/s3/private/s3_meta_request_impl.h"
10 #include "aws/s3/private/s3_util.h"
11 #include <aws/auth/credentials.h>
12 #include <aws/common/system_info.h>
13 #include <aws/http/request_response.h>
14 #include <aws/io/channel_bootstrap.h>
15 #include <aws/io/event_loop.h>
16 #include <aws/io/host_resolver.h>
17 #include <aws/io/stream.h>
18 #include <aws/io/tls_channel_handler.h>
19 #include <aws/testing/aws_test_harness.h>
20 #include <inttypes.h>
21 #include <stdlib.h>
22 #include <time.h>
23 
24 #if _MSC_VER
25 #    pragma warning(disable : 4232) /* function pointer to dll symbol */
26 #endif
27 
28 const struct aws_byte_cursor g_test_body_content_type = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("text/plain");
29 const struct aws_byte_cursor g_test_s3_region = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("us-west-2");
30 const struct aws_byte_cursor g_test_bucket_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("aws-crt-canary-bucket");
31 const struct aws_byte_cursor g_test_public_bucket_name =
32     AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("aws-crt-test-stuff-us-west-2");
33 const struct aws_byte_cursor g_s3_path_get_object_test_1MB =
34     AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/get_object_test_1MB.txt");
35 const struct aws_byte_cursor g_s3_sse_header = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption");
36 
37 /* TODO populate these at the beginning of running tests with names that are unique to the test run. */
38 const struct aws_byte_cursor g_pre_existing_object_1MB =
39     AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/pre-existing_object_1MB.txt");
40 const struct aws_byte_cursor g_pre_existing_object_kms_10MB =
41     AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/pre-existing_object_kms_10MB.txt");
42 const struct aws_byte_cursor g_pre_existing_object_aes256_10MB =
43     AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/pre-existing_object_aes256_10MB.txt");
44 const struct aws_byte_cursor g_pre_existing_empty_object =
45     AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/pre-existing_object_empty.txt");
46 
47 #ifdef BYO_CRYPTO
48 /* Under BYO_CRYPTO, this function currently needs to be defined by the user. Defining a null implementation here so
49  * that tests build, but it is not currently meant to be used by any tests. */
aws_tls_handler_protocol(struct aws_channel_handler * handler)50 struct aws_byte_buf aws_tls_handler_protocol(struct aws_channel_handler *handler) {
51     (void)handler;
52     AWS_FATAL_ASSERT(false);
53     struct aws_byte_buf byte_buf;
54     AWS_ZERO_STRUCT(byte_buf);
55     return byte_buf;
56 }
57 #endif
58 
s_s3_test_meta_request_header_callback(struct aws_s3_meta_request * meta_request,const struct aws_http_headers * headers,int response_status,void * user_data)59 static int s_s3_test_meta_request_header_callback(
60     struct aws_s3_meta_request *meta_request,
61     const struct aws_http_headers *headers,
62     int response_status,
63     void *user_data) {
64     (void)meta_request;
65 
66     struct aws_s3_meta_request_test_results *meta_request_test_results =
67         (struct aws_s3_meta_request_test_results *)user_data;
68 
69     aws_http_headers_release(meta_request_test_results->response_headers);
70 
71     meta_request_test_results->response_headers = (struct aws_http_headers *)headers;
72     aws_http_headers_acquire(meta_request_test_results->response_headers);
73 
74     meta_request_test_results->headers_response_status = response_status;
75 
76     if (meta_request_test_results->headers_callback != NULL) {
77         return meta_request_test_results->headers_callback(meta_request, headers, response_status, user_data);
78     }
79 
80     return AWS_OP_SUCCESS;
81 }
82 
s_s3_test_meta_request_body_callback(struct aws_s3_meta_request * meta_request,const struct aws_byte_cursor * body,uint64_t range_start,void * user_data)83 static int s_s3_test_meta_request_body_callback(
84     struct aws_s3_meta_request *meta_request,
85     const struct aws_byte_cursor *body,
86     uint64_t range_start,
87     void *user_data) {
88     (void)meta_request;
89     (void)body;
90     AWS_PRECONDITION(meta_request);
91     AWS_PRECONDITION(body);
92 
93     struct aws_s3_meta_request_test_results *meta_request_test_results = user_data;
94     meta_request_test_results->received_body_size += body->len;
95 
96     AWS_LOGF_DEBUG(
97         AWS_LS_S3_GENERAL,
98         "Received range %" PRIu64 "-%" PRIu64 ". Expected range start: %" PRIu64,
99         range_start,
100         range_start + body->len - 1,
101         meta_request_test_results->expected_range_start);
102 
103     uint64_t object_range_start = 0;
104 
105     /* If this is an auto-ranged-get meta request, then grab the object range start so that the expected_range_start can
106      * be properly offset.*/
107     if (meta_request->type == AWS_S3_META_REQUEST_TYPE_GET_OBJECT) {
108 
109         aws_s3_meta_request_lock_synced_data(meta_request);
110 
111         struct aws_s3_auto_ranged_get *auto_ranged_get = meta_request->impl;
112         AWS_PRECONDITION(auto_ranged_get);
113 
114         bool object_range_known = auto_ranged_get->synced_data.object_range_known != 0;
115         object_range_start = auto_ranged_get->synced_data.object_range_start;
116 
117         aws_s3_meta_request_unlock_synced_data(meta_request);
118 
119         ASSERT_TRUE(object_range_known);
120     }
121 
122     ASSERT_TRUE((object_range_start + meta_request_test_results->expected_range_start) == range_start);
123     meta_request_test_results->expected_range_start += body->len;
124 
125     if (meta_request_test_results->body_callback != NULL) {
126         return meta_request_test_results->body_callback(meta_request, body, range_start, user_data);
127     }
128 
129     return AWS_OP_SUCCESS;
130 }
131 
s_s3_test_meta_request_finish(struct aws_s3_meta_request * meta_request,const struct aws_s3_meta_request_result * result,void * user_data)132 static void s_s3_test_meta_request_finish(
133     struct aws_s3_meta_request *meta_request,
134     const struct aws_s3_meta_request_result *result,
135     void *user_data) {
136     (void)meta_request;
137 
138     struct aws_s3_meta_request_test_results *meta_request_test_results = user_data;
139     struct aws_s3_tester *tester = meta_request_test_results->tester;
140 
141     meta_request_test_results->error_response_headers = result->error_response_headers;
142 
143     if (result->error_response_headers != NULL) {
144         aws_http_headers_acquire(result->error_response_headers);
145     }
146 
147     if (result->error_response_body != NULL) {
148         aws_byte_buf_init_copy(
149             &meta_request_test_results->error_response_body, tester->allocator, result->error_response_body);
150     }
151 
152     meta_request_test_results->finished_response_status = result->response_status;
153     meta_request_test_results->finished_error_code = result->error_code;
154 
155     aws_s3_tester_notify_meta_request_finished(tester, result);
156 }
157 
s_s3_test_meta_request_shutdown(void * user_data)158 static void s_s3_test_meta_request_shutdown(void *user_data) {
159     struct aws_s3_meta_request_test_results *meta_request_test_results = user_data;
160     struct aws_s3_tester *tester = meta_request_test_results->tester;
161 
162     aws_s3_tester_notify_meta_request_shutdown(tester);
163 }
164 
165 /* Wait for the cleanup notification.  This, and the s_s3_test_client_shutdown function are meant to be used for
166  * sequential clean up only, and should not overlap with the "finish" callback.  (Both currently use the same
167  * mutex/signal.) */
168 static void s_s3_tester_wait_for_client_shutdown(struct aws_s3_tester *tester);
169 
170 /* Notify the tester that a particular clean up step has finished. */
171 static void s_s3_test_client_shutdown(void *user_data);
172 
173 static bool s_s3_tester_have_meta_requests_finished(void *user_data);
174 
175 static bool s_s3_tester_has_client_shutdown(void *user_data);
176 
aws_s3_tester_build_endpoint_string(struct aws_allocator * allocator,const struct aws_byte_cursor * bucket_name,const struct aws_byte_cursor * region)177 struct aws_string *aws_s3_tester_build_endpoint_string(
178     struct aws_allocator *allocator,
179     const struct aws_byte_cursor *bucket_name,
180     const struct aws_byte_cursor *region) {
181 
182     struct aws_byte_cursor endpoint_url_part0 = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(".s3.");
183     struct aws_byte_cursor endpoint_url_part1 = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL(".amazonaws.com");
184 
185     struct aws_byte_buf endpoint_buffer;
186     aws_byte_buf_init(&endpoint_buffer, allocator, 128);
187 
188     aws_byte_buf_append_dynamic(&endpoint_buffer, bucket_name);
189     aws_byte_buf_append_dynamic(&endpoint_buffer, &endpoint_url_part0);
190     aws_byte_buf_append_dynamic(&endpoint_buffer, region);
191     aws_byte_buf_append_dynamic(&endpoint_buffer, &endpoint_url_part1);
192 
193     struct aws_string *endpoint_string = aws_string_new_from_buf(allocator, &endpoint_buffer);
194 
195     aws_byte_buf_clean_up(&endpoint_buffer);
196 
197     return endpoint_string;
198 }
199 
aws_s3_tester_init(struct aws_allocator * allocator,struct aws_s3_tester * tester)200 int aws_s3_tester_init(struct aws_allocator *allocator, struct aws_s3_tester *tester) {
201 
202     AWS_PRECONDITION(allocator);
203     AWS_PRECONDITION(tester);
204 
205     (void)allocator;
206 
207     AWS_ZERO_STRUCT(*tester);
208 
209     tester->allocator = allocator;
210 
211     aws_s3_library_init(allocator);
212 
213     if (aws_mutex_init(&tester->synced_data.lock)) {
214         return AWS_OP_ERR;
215     }
216 
217     if (aws_condition_variable_init(&tester->signal)) {
218         goto condition_variable_failed;
219     }
220 
221     ASSERT_SUCCESS(aws_array_list_init_dynamic(
222         &tester->client_vtable_patches, tester->allocator, 4, sizeof(struct aws_s3_client_vtable_patch)));
223 
224     ASSERT_SUCCESS(aws_array_list_init_dynamic(
225         &tester->meta_request_vtable_patches, tester->allocator, 4, sizeof(struct aws_s3_meta_request_vtable_patch)));
226 
227     /* Setup an event loop group and host resolver. */
228     tester->el_group = aws_event_loop_group_new_default(allocator, 0, NULL);
229     ASSERT_TRUE(tester->el_group != NULL);
230 
231     struct aws_host_resolver_default_options resolver_options = {
232         .max_entries = 10,
233         .el_group = tester->el_group,
234     };
235     tester->host_resolver = aws_host_resolver_new_default(allocator, &resolver_options);
236     ASSERT_TRUE(tester->host_resolver != NULL);
237 
238     /* Setup the client boot strap. */
239     {
240         struct aws_client_bootstrap_options bootstrap_options;
241         AWS_ZERO_STRUCT(bootstrap_options);
242         bootstrap_options.event_loop_group = tester->el_group;
243         bootstrap_options.host_resolver = tester->host_resolver;
244         bootstrap_options.user_data = tester;
245 
246         tester->client_bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
247     }
248 
249 #ifndef BYO_CRYPTO
250     /* Setup the credentials provider */
251     {
252         struct aws_credentials_provider_chain_default_options credentials_config;
253         AWS_ZERO_STRUCT(credentials_config);
254         credentials_config.bootstrap = tester->client_bootstrap;
255         tester->credentials_provider = aws_credentials_provider_new_chain_default(allocator, &credentials_config);
256     }
257 #endif
258 
259     aws_s3_init_default_signing_config(&tester->default_signing_config, g_test_s3_region, tester->credentials_provider);
260 
261     return AWS_OP_SUCCESS;
262 
263 condition_variable_failed:
264 
265     aws_mutex_clean_up(&tester->synced_data.lock);
266 
267     return AWS_OP_ERR;
268 }
269 
aws_s3_tester_bind_client(struct aws_s3_tester * tester,struct aws_s3_client_config * config,uint32_t flags)270 int aws_s3_tester_bind_client(struct aws_s3_tester *tester, struct aws_s3_client_config *config, uint32_t flags) {
271     AWS_PRECONDITION(tester);
272     AWS_PRECONDITION(config);
273 
274     ASSERT_TRUE(!tester->bound_to_client);
275     tester->bound_to_client = true;
276 
277     ASSERT_TRUE(config->client_bootstrap == NULL);
278     config->client_bootstrap = tester->client_bootstrap;
279 
280     if (flags & AWS_S3_TESTER_BIND_CLIENT_REGION) {
281         ASSERT_TRUE(config->region.len == 0);
282         config->region = g_test_s3_region;
283     }
284 
285     if (flags & AWS_S3_TESTER_BIND_CLIENT_SIGNING) {
286         ASSERT_TRUE(config->signing_config == NULL);
287         config->signing_config = &tester->default_signing_config;
288     }
289 
290     ASSERT_TRUE(config->shutdown_callback == NULL);
291     config->shutdown_callback = s_s3_test_client_shutdown;
292 
293     ASSERT_TRUE(config->shutdown_callback_user_data == NULL);
294     config->shutdown_callback_user_data = tester;
295 
296     return AWS_OP_SUCCESS;
297 }
298 
aws_s3_tester_bind_meta_request(struct aws_s3_tester * tester,struct aws_s3_meta_request_options * options,struct aws_s3_meta_request_test_results * meta_request_test_results)299 int aws_s3_tester_bind_meta_request(
300     struct aws_s3_tester *tester,
301     struct aws_s3_meta_request_options *options,
302     struct aws_s3_meta_request_test_results *meta_request_test_results) {
303 
304     meta_request_test_results->tester = tester;
305 
306     aws_s3_tester_lock_synced_data(tester);
307     ++tester->synced_data.desired_meta_request_finish_count;
308     ++tester->synced_data.desired_meta_request_shutdown_count;
309     aws_s3_tester_unlock_synced_data(tester);
310 
311     ASSERT_TRUE(options->headers_callback == NULL);
312     options->headers_callback = s_s3_test_meta_request_header_callback;
313 
314     ASSERT_TRUE(options->body_callback == NULL);
315     options->body_callback = s_s3_test_meta_request_body_callback;
316 
317     ASSERT_TRUE(options->finish_callback == NULL);
318     options->finish_callback = s_s3_test_meta_request_finish;
319 
320     ASSERT_TRUE(options->shutdown_callback == NULL);
321     options->shutdown_callback = s_s3_test_meta_request_shutdown;
322 
323     ASSERT_TRUE(options->user_data == NULL);
324     options->user_data = meta_request_test_results;
325 
326     return AWS_OP_SUCCESS;
327 }
328 
aws_s3_meta_request_test_results_clean_up(struct aws_s3_meta_request_test_results * test_meta_request)329 void aws_s3_meta_request_test_results_clean_up(struct aws_s3_meta_request_test_results *test_meta_request) {
330     if (test_meta_request == NULL) {
331         return;
332     }
333 
334     aws_http_headers_release(test_meta_request->error_response_headers);
335     aws_byte_buf_clean_up(&test_meta_request->error_response_body);
336     aws_http_headers_release(test_meta_request->response_headers);
337 
338     AWS_ZERO_STRUCT(*test_meta_request);
339 }
340 
aws_s3_tester_notify_meta_request_finished(struct aws_s3_tester * tester,const struct aws_s3_meta_request_result * result)341 void aws_s3_tester_notify_meta_request_finished(
342     struct aws_s3_tester *tester,
343     const struct aws_s3_meta_request_result *result) {
344     AWS_PRECONDITION(tester);
345 
346     bool notify = false;
347 
348     aws_s3_tester_lock_synced_data(tester);
349     ++tester->synced_data.meta_request_finish_count;
350 
351     int error_code = AWS_ERROR_SUCCESS;
352 
353     if (result != NULL) {
354         error_code = result->error_code;
355     }
356 
357     if (tester->synced_data.desired_meta_request_finish_count == 0 ||
358         tester->synced_data.meta_request_finish_count == tester->synced_data.desired_meta_request_finish_count ||
359         (error_code != AWS_ERROR_SUCCESS)) {
360 
361         tester->synced_data.meta_requests_finished = true;
362         tester->synced_data.finish_error_code = error_code;
363 
364         notify = true;
365     }
366 
367     aws_s3_tester_unlock_synced_data(tester);
368 
369     if (notify) {
370         aws_condition_variable_notify_all(&tester->signal);
371     }
372 }
373 
s_s3_tester_have_meta_requests_finished(void * user_data)374 static bool s_s3_tester_have_meta_requests_finished(void *user_data) {
375     AWS_PRECONDITION(user_data);
376     struct aws_s3_tester *tester = (struct aws_s3_tester *)user_data;
377 
378     return tester->synced_data.meta_requests_finished > 0;
379 }
380 
aws_s3_tester_wait_for_meta_request_finish(struct aws_s3_tester * tester)381 void aws_s3_tester_wait_for_meta_request_finish(struct aws_s3_tester *tester) {
382     AWS_PRECONDITION(tester);
383 
384     aws_s3_tester_lock_synced_data(tester);
385     aws_condition_variable_wait_pred(
386         &tester->signal, &tester->synced_data.lock, s_s3_tester_have_meta_requests_finished, tester);
387 
388     tester->synced_data.meta_requests_finished = false;
389     aws_s3_tester_unlock_synced_data(tester);
390 }
391 
aws_s3_tester_notify_meta_request_shutdown(struct aws_s3_tester * tester)392 void aws_s3_tester_notify_meta_request_shutdown(struct aws_s3_tester *tester) {
393     bool notify = false;
394 
395     aws_s3_tester_lock_synced_data(tester);
396     ++tester->synced_data.meta_request_shutdown_count;
397 
398     if (tester->synced_data.desired_meta_request_shutdown_count == 0 ||
399         tester->synced_data.meta_request_shutdown_count == tester->synced_data.desired_meta_request_shutdown_count) {
400 
401         tester->synced_data.meta_requests_shutdown = true;
402         notify = true;
403     }
404 
405     aws_s3_tester_unlock_synced_data(tester);
406 
407     if (notify) {
408         aws_condition_variable_notify_all(&tester->signal);
409     }
410 }
411 
s_s3_tester_have_meta_requests_shutdown(void * user_data)412 static bool s_s3_tester_have_meta_requests_shutdown(void *user_data) {
413     AWS_PRECONDITION(user_data);
414     struct aws_s3_tester *tester = (struct aws_s3_tester *)user_data;
415 
416     return tester->synced_data.meta_requests_shutdown > 0;
417 }
418 
aws_s3_tester_wait_for_meta_request_shutdown(struct aws_s3_tester * tester)419 void aws_s3_tester_wait_for_meta_request_shutdown(struct aws_s3_tester *tester) {
420     AWS_PRECONDITION(tester);
421 
422     aws_s3_tester_lock_synced_data(tester);
423     aws_condition_variable_wait_pred(
424         &tester->signal, &tester->synced_data.lock, s_s3_tester_have_meta_requests_shutdown, tester);
425 
426     tester->synced_data.meta_requests_shutdown = false;
427     aws_s3_tester_unlock_synced_data(tester);
428 }
429 
s_s3_tester_counters_equal_desired(void * user_data)430 static bool s_s3_tester_counters_equal_desired(void *user_data) {
431     AWS_PRECONDITION(user_data);
432     struct aws_s3_tester *tester = (struct aws_s3_tester *)user_data;
433 
434     return tester->synced_data.counter1 == tester->synced_data.desired_counter1 &&
435            tester->synced_data.counter2 == tester->synced_data.desired_counter2;
436 }
437 
aws_s3_tester_wait_for_signal(struct aws_s3_tester * tester)438 void aws_s3_tester_wait_for_signal(struct aws_s3_tester *tester) {
439     aws_s3_tester_lock_synced_data(tester);
440     aws_condition_variable_wait(&tester->signal, &tester->synced_data.lock);
441     aws_s3_tester_unlock_synced_data(tester);
442 }
443 
aws_s3_tester_notify_signal(struct aws_s3_tester * tester)444 void aws_s3_tester_notify_signal(struct aws_s3_tester *tester) {
445     aws_condition_variable_notify_all(&tester->signal);
446 }
447 
aws_s3_tester_wait_for_counters(struct aws_s3_tester * tester)448 void aws_s3_tester_wait_for_counters(struct aws_s3_tester *tester) {
449     aws_s3_tester_lock_synced_data(tester);
450     aws_condition_variable_wait_pred(
451         &tester->signal, &tester->synced_data.lock, s_s3_tester_counters_equal_desired, tester);
452     aws_s3_tester_unlock_synced_data(tester);
453 }
454 
aws_s3_tester_inc_counter1(struct aws_s3_tester * tester)455 size_t aws_s3_tester_inc_counter1(struct aws_s3_tester *tester) {
456     aws_s3_tester_lock_synced_data(tester);
457     size_t result = ++tester->synced_data.counter1;
458     aws_s3_tester_unlock_synced_data(tester);
459 
460     aws_condition_variable_notify_all(&tester->signal);
461 
462     return result;
463 }
464 
aws_s3_tester_inc_counter2(struct aws_s3_tester * tester)465 size_t aws_s3_tester_inc_counter2(struct aws_s3_tester *tester) {
466     aws_s3_tester_lock_synced_data(tester);
467     size_t result = ++tester->synced_data.counter2;
468     aws_s3_tester_unlock_synced_data(tester);
469 
470     aws_condition_variable_notify_all(&tester->signal);
471 
472     return result;
473 }
474 
aws_s3_tester_reset_counter1(struct aws_s3_tester * tester)475 void aws_s3_tester_reset_counter1(struct aws_s3_tester *tester) {
476     aws_s3_tester_lock_synced_data(tester);
477     tester->synced_data.counter1 = 0;
478     aws_s3_tester_unlock_synced_data(tester);
479 }
480 
aws_s3_tester_reset_counter2(struct aws_s3_tester * tester)481 void aws_s3_tester_reset_counter2(struct aws_s3_tester *tester) {
482     aws_s3_tester_lock_synced_data(tester);
483     tester->synced_data.counter2 = 0;
484     aws_s3_tester_unlock_synced_data(tester);
485 }
486 
aws_s3_tester_set_counter1_desired(struct aws_s3_tester * tester,size_t value)487 void aws_s3_tester_set_counter1_desired(struct aws_s3_tester *tester, size_t value) {
488     aws_s3_tester_lock_synced_data(tester);
489     tester->synced_data.desired_counter1 = value;
490     aws_s3_tester_unlock_synced_data(tester);
491 }
492 
aws_s3_tester_set_counter2_desired(struct aws_s3_tester * tester,size_t value)493 void aws_s3_tester_set_counter2_desired(struct aws_s3_tester *tester, size_t value) {
494     aws_s3_tester_lock_synced_data(tester);
495     tester->synced_data.desired_counter2 = value;
496     aws_s3_tester_unlock_synced_data(tester);
497 }
498 
aws_s3_tester_clean_up(struct aws_s3_tester * tester)499 void aws_s3_tester_clean_up(struct aws_s3_tester *tester) {
500     AWS_PRECONDITION(tester);
501 
502     if (tester->bound_to_client) {
503         s_s3_tester_wait_for_client_shutdown(tester);
504         tester->bound_to_client = false;
505     }
506 
507     aws_array_list_clean_up(&tester->client_vtable_patches);
508     aws_array_list_clean_up(&tester->meta_request_vtable_patches);
509 
510     aws_client_bootstrap_release(tester->client_bootstrap);
511     tester->client_bootstrap = NULL;
512 
513     aws_credentials_provider_release(tester->credentials_provider);
514     tester->credentials_provider = NULL;
515 
516     aws_host_resolver_release(tester->host_resolver);
517     tester->host_resolver = NULL;
518 
519     aws_event_loop_group_release(tester->el_group);
520     tester->el_group = NULL;
521 
522     aws_s3_library_clean_up();
523 
524     aws_condition_variable_clean_up(&tester->signal);
525     aws_mutex_clean_up(&tester->synced_data.lock);
526 }
527 
aws_s3_tester_lock_synced_data(struct aws_s3_tester * tester)528 void aws_s3_tester_lock_synced_data(struct aws_s3_tester *tester) {
529     AWS_PRECONDITION(tester);
530     aws_mutex_lock(&tester->synced_data.lock);
531 }
532 
aws_s3_tester_unlock_synced_data(struct aws_s3_tester * tester)533 void aws_s3_tester_unlock_synced_data(struct aws_s3_tester *tester) {
534     AWS_PRECONDITION(tester);
535 
536     aws_mutex_unlock(&tester->synced_data.lock);
537 }
538 
s_s3_client_meta_request_factory_empty(struct aws_s3_client * client,const struct aws_s3_meta_request_options * options)539 struct aws_s3_meta_request *s_s3_client_meta_request_factory_empty(
540     struct aws_s3_client *client,
541     const struct aws_s3_meta_request_options *options) {
542     AWS_PRECONDITION(client);
543     AWS_PRECONDITION(options);
544 
545     (void)client;
546     (void)options;
547 
548     return NULL;
549 }
550 
s_s3_client_create_connection_for_request_empty(struct aws_s3_client * client,struct aws_s3_request * request)551 void s_s3_client_create_connection_for_request_empty(struct aws_s3_client *client, struct aws_s3_request *request) {
552     AWS_PRECONDITION(client);
553     AWS_PRECONDITION(request);
554 
555     (void)client;
556     (void)request;
557 }
558 
s_s3_client_acquire_http_connection_empty(struct aws_http_connection_manager * conn_manager,aws_http_connection_manager_on_connection_setup_fn * on_connection_acquired_callback,void * user_data)559 static void s_s3_client_acquire_http_connection_empty(
560     struct aws_http_connection_manager *conn_manager,
561     aws_http_connection_manager_on_connection_setup_fn *on_connection_acquired_callback,
562     void *user_data) {
563     (void)conn_manager;
564     (void)on_connection_acquired_callback;
565     (void)user_data;
566 }
567 
s_s3_client_get_host_address_count_empty(struct aws_host_resolver * host_resolver,const struct aws_string * host_name,uint32_t flags)568 size_t s_s3_client_get_host_address_count_empty(
569     struct aws_host_resolver *host_resolver,
570     const struct aws_string *host_name,
571     uint32_t flags) {
572     (void)host_resolver;
573     (void)host_name;
574     (void)flags;
575     return 0;
576 }
577 
s_s3_client_schedule_process_work_synced_empty(struct aws_s3_client * client)578 static void s_s3_client_schedule_process_work_synced_empty(struct aws_s3_client *client) {
579     (void)client;
580 }
581 
s_s3_client_process_work_empty(struct aws_s3_client * client)582 static void s_s3_client_process_work_empty(struct aws_s3_client *client) {
583     AWS_PRECONDITION(client);
584     (void)client;
585 }
586 
s_s3_client_endpoint_ref_count_zero_empty(struct aws_s3_endpoint * endpoint)587 static bool s_s3_client_endpoint_ref_count_zero_empty(struct aws_s3_endpoint *endpoint) {
588     AWS_PRECONDITION(endpoint);
589     (void)endpoint;
590     return true;
591 }
592 
s_s3_client_endpoint_shutdown_callback_empty(void * user_data)593 static void s_s3_client_endpoint_shutdown_callback_empty(void *user_data) {
594     AWS_PRECONDITION(user_data);
595     (void)user_data;
596 }
597 
s_s3_client_finish_destroy_empty(struct aws_s3_client * client)598 static void s_s3_client_finish_destroy_empty(struct aws_s3_client *client) {
599     AWS_PRECONDITION(client);
600     (void)client;
601 }
602 
603 struct aws_s3_client_vtable g_aws_s3_client_mock_vtable = {
604     .meta_request_factory = s_s3_client_meta_request_factory_empty,
605     .create_connection_for_request = s_s3_client_create_connection_for_request_empty,
606     .acquire_http_connection = s_s3_client_acquire_http_connection_empty,
607     .get_host_address_count = s_s3_client_get_host_address_count_empty,
608     .schedule_process_work_synced = s_s3_client_schedule_process_work_synced_empty,
609     .process_work = s_s3_client_process_work_empty,
610     .endpoint_ref_count_zero = s_s3_client_endpoint_ref_count_zero_empty,
611     .endpoint_shutdown_callback = s_s3_client_endpoint_shutdown_callback_empty,
612     .finish_destroy = s_s3_client_finish_destroy_empty,
613 };
614 
s_s3_mock_client_start_destroy(void * user_data)615 static void s_s3_mock_client_start_destroy(void *user_data) {
616     struct aws_s3_client *client = user_data;
617     AWS_ASSERT(client);
618 
619     aws_mem_release(client->allocator, client);
620 }
621 
aws_s3_tester_mock_client_new(struct aws_s3_tester * tester)622 struct aws_s3_client *aws_s3_tester_mock_client_new(struct aws_s3_tester *tester) {
623     struct aws_allocator *allocator = tester->allocator;
624     struct aws_s3_client *mock_client = aws_mem_calloc(allocator, 1, sizeof(struct aws_s3_client));
625 
626     mock_client->allocator = allocator;
627     mock_client->vtable = &g_aws_s3_client_mock_vtable;
628 
629     aws_ref_count_init(
630         &mock_client->ref_count, mock_client, (aws_simple_completion_callback *)s_s3_mock_client_start_destroy);
631 
632     aws_mutex_init(&mock_client->synced_data.lock);
633 
634     aws_atomic_init_int(&mock_client->stats.num_requests_in_flight, 0);
635 
636     for (uint32_t i = 0; i < (uint32_t)AWS_S3_META_REQUEST_TYPE_MAX; ++i) {
637         aws_atomic_init_int(&mock_client->stats.num_requests_network_io[i], 0);
638     }
639 
640     aws_atomic_init_int(&mock_client->stats.num_requests_stream_queued_waiting, 0);
641     aws_atomic_init_int(&mock_client->stats.num_requests_streaming, 0);
642 
643     return mock_client;
644 }
645 
aws_s3_tester_dummy_http_request_new(struct aws_s3_tester * tester)646 struct aws_http_message *aws_s3_tester_dummy_http_request_new(struct aws_s3_tester *tester) {
647     AWS_PRECONDITION(tester);
648 
649     struct aws_http_message *message = aws_http_message_new_request(tester->allocator);
650 
651     struct aws_http_header host_header = {
652         .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Host"),
653         .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("dummy_host"),
654     };
655 
656     aws_http_message_add_header(message, host_header);
657 
658     return message;
659 }
660 
s_s3_meta_request_update_empty(struct aws_s3_meta_request * meta_request,uint32_t flags,struct aws_s3_request ** out_request)661 static bool s_s3_meta_request_update_empty(
662     struct aws_s3_meta_request *meta_request,
663     uint32_t flags,
664     struct aws_s3_request **out_request) {
665     (void)meta_request;
666     (void)flags;
667     (void)out_request;
668     return false;
669 }
670 
s_s3_meta_request_send_request_finish_empty(struct aws_s3_connection * connection,struct aws_http_stream * stream,int error_code)671 void s_s3_meta_request_send_request_finish_empty(
672     struct aws_s3_connection *connection,
673     struct aws_http_stream *stream,
674     int error_code) {
675     (void)connection;
676     (void)stream;
677     (void)error_code;
678 }
679 
s_s3_meta_request_finished_request_empty(struct aws_s3_meta_request * meta_request,struct aws_s3_request * request,int error_code)680 static void s_s3_meta_request_finished_request_empty(
681     struct aws_s3_meta_request *meta_request,
682     struct aws_s3_request *request,
683     int error_code) {
684     (void)meta_request;
685     (void)request;
686     (void)error_code;
687 }
688 
s_s3_meta_request_schedule_prepare_request_empty(struct aws_s3_meta_request * meta_request,struct aws_s3_request * request,aws_s3_meta_request_prepare_request_callback_fn * callback,void * user_data)689 static void s_s3_meta_request_schedule_prepare_request_empty(
690     struct aws_s3_meta_request *meta_request,
691     struct aws_s3_request *request,
692     aws_s3_meta_request_prepare_request_callback_fn *callback,
693     void *user_data) {
694     (void)meta_request;
695     (void)request;
696     (void)callback;
697     (void)user_data;
698 }
699 
s_s3_meta_request_prepare_request_empty(struct aws_s3_meta_request * meta_request,struct aws_s3_request * request)700 static int s_s3_meta_request_prepare_request_empty(
701     struct aws_s3_meta_request *meta_request,
702     struct aws_s3_request *request) {
703     (void)meta_request;
704     (void)request;
705     return AWS_OP_ERR;
706 }
707 
s_s3_meta_request_init_signing_date_time_empty(struct aws_s3_meta_request * meta_request,struct aws_date_time * date_time)708 static void s_s3_meta_request_init_signing_date_time_empty(
709     struct aws_s3_meta_request *meta_request,
710     struct aws_date_time *date_time) {
711     (void)meta_request;
712     (void)date_time;
713 }
714 
s_s3_meta_request_sign_request_empty(struct aws_s3_meta_request * meta_request,struct aws_s3_request * request,aws_signing_complete_fn * on_signing_complete,void * user_data)715 static void s_s3_meta_request_sign_request_empty(
716     struct aws_s3_meta_request *meta_request,
717     struct aws_s3_request *request,
718     aws_signing_complete_fn *on_signing_complete,
719     void *user_data) {
720     (void)meta_request;
721     (void)request;
722     (void)on_signing_complete;
723     (void)user_data;
724 }
725 
s_s3_mock_meta_request_destroy(struct aws_s3_meta_request * meta_request)726 static void s_s3_mock_meta_request_destroy(struct aws_s3_meta_request *meta_request) {
727     AWS_PRECONDITION(meta_request);
728 
729     aws_mem_release(meta_request->allocator, meta_request->impl);
730 }
731 
732 static struct aws_s3_meta_request_vtable s_s3_mock_meta_request_vtable = {
733     .update = s_s3_meta_request_update_empty,
734     .send_request_finish = s_s3_meta_request_send_request_finish_empty,
735     .schedule_prepare_request = s_s3_meta_request_schedule_prepare_request_empty,
736     .prepare_request = s_s3_meta_request_prepare_request_empty,
737     .finished_request = s_s3_meta_request_finished_request_empty,
738     .init_signing_date_time = s_s3_meta_request_init_signing_date_time_empty,
739     .sign_request = s_s3_meta_request_sign_request_empty,
740     .destroy = s_s3_mock_meta_request_destroy,
741 };
742 
743 struct aws_s3_empty_meta_request {
744     struct aws_s3_meta_request base;
745 };
746 
s_s3_mock_endpoint_zero_ref(void * user_data)747 static void s_s3_mock_endpoint_zero_ref(void *user_data) {
748     struct aws_s3_endpoint *endpoint = user_data;
749 
750     aws_string_destroy(endpoint->host_name);
751     aws_mem_release(endpoint->allocator, endpoint);
752 }
753 
aws_s3_tester_mock_endpoint_new(struct aws_s3_tester * tester)754 struct aws_s3_endpoint *aws_s3_tester_mock_endpoint_new(struct aws_s3_tester *tester) {
755     struct aws_s3_endpoint *endpoint = aws_mem_calloc(tester->allocator, 1, sizeof(struct aws_s3_endpoint));
756     endpoint->allocator = tester->allocator;
757     aws_ref_count_init(&endpoint->ref_count, endpoint, s_s3_mock_endpoint_zero_ref);
758 
759     struct aws_byte_cursor empty_cursor = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("");
760     endpoint->host_name = aws_string_new_from_cursor(tester->allocator, &empty_cursor);
761 
762     return endpoint;
763 }
764 
aws_s3_tester_mock_meta_request_new(struct aws_s3_tester * tester)765 struct aws_s3_meta_request *aws_s3_tester_mock_meta_request_new(struct aws_s3_tester *tester) {
766     AWS_PRECONDITION(tester);
767 
768     struct aws_s3_empty_meta_request *empty_meta_request =
769         aws_mem_calloc(tester->allocator, 1, sizeof(struct aws_s3_empty_meta_request));
770 
771     struct aws_http_message *dummy_http_message = aws_s3_tester_dummy_http_request_new(tester);
772 
773     struct aws_s3_meta_request_options options = {
774         .message = dummy_http_message,
775     };
776 
777     aws_s3_meta_request_init_base(
778         tester->allocator,
779         NULL,
780         0,
781         false,
782         &options,
783         empty_meta_request,
784         &s_s3_mock_meta_request_vtable,
785         &empty_meta_request->base);
786 
787     aws_http_message_release(dummy_http_message);
788 
789     return &empty_meta_request->base;
790 }
791 
aws_s3_create_test_buffer(struct aws_allocator * allocator,size_t buffer_size,struct aws_byte_buf * out_buf)792 void aws_s3_create_test_buffer(struct aws_allocator *allocator, size_t buffer_size, struct aws_byte_buf *out_buf) {
793     AWS_PRECONDITION(allocator);
794     AWS_PRECONDITION(out_buf);
795 
796     struct aws_byte_cursor test_string = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("This is an S3 test.");
797 
798     aws_byte_buf_init(out_buf, allocator, buffer_size);
799 
800     for (size_t buffer_pos = 0; buffer_pos < buffer_size; buffer_pos += test_string.len) {
801         size_t buffer_size_remaining = buffer_size - buffer_pos;
802         size_t string_copy_size = test_string.len;
803 
804         if (buffer_size_remaining < string_copy_size) {
805             string_copy_size = buffer_size_remaining;
806         }
807 
808         struct aws_byte_cursor from_byte_cursor = {.len = string_copy_size, .ptr = test_string.ptr};
809 
810         aws_byte_buf_append(out_buf, &from_byte_cursor);
811     }
812 }
813 
s_s3_test_client_shutdown(void * user_data)814 static void s_s3_test_client_shutdown(void *user_data) {
815     AWS_PRECONDITION(user_data);
816 
817     struct aws_s3_tester *tester = (struct aws_s3_tester *)user_data;
818 
819     aws_s3_tester_lock_synced_data(tester);
820     tester->synced_data.client_shutdown = true;
821     aws_s3_tester_unlock_synced_data(tester);
822 
823     aws_condition_variable_notify_all(&tester->signal);
824 }
825 
s_s3_tester_has_client_shutdown(void * user_data)826 static bool s_s3_tester_has_client_shutdown(void *user_data) {
827     AWS_PRECONDITION(user_data);
828     struct aws_s3_tester *tester = (struct aws_s3_tester *)user_data;
829 
830     return tester->synced_data.client_shutdown > 0;
831 }
832 
s_s3_tester_wait_for_client_shutdown(struct aws_s3_tester * tester)833 static void s_s3_tester_wait_for_client_shutdown(struct aws_s3_tester *tester) {
834     AWS_PRECONDITION(tester);
835 
836     aws_s3_tester_lock_synced_data(tester);
837     aws_condition_variable_wait_pred(
838         &tester->signal, &tester->synced_data.lock, s_s3_tester_has_client_shutdown, tester);
839 
840     tester->synced_data.client_shutdown = false;
841     aws_s3_tester_unlock_synced_data(tester);
842 }
843 
aws_s3_test_get_object_request_new(struct aws_allocator * allocator,struct aws_byte_cursor host,struct aws_byte_cursor key)844 struct aws_http_message *aws_s3_test_get_object_request_new(
845     struct aws_allocator *allocator,
846     struct aws_byte_cursor host,
847     struct aws_byte_cursor key) {
848 
849     struct aws_http_message *message = aws_http_message_new_request(allocator);
850 
851     if (message == NULL) {
852         return NULL;
853     }
854 
855     struct aws_http_header host_header = {.name = g_host_header_name, .value = host};
856 
857     if (aws_http_message_add_header(message, host_header)) {
858         goto error_clean_up_message;
859     }
860 
861     if (aws_http_message_set_request_method(message, aws_http_method_get)) {
862         goto error_clean_up_message;
863     }
864 
865     if (aws_http_message_set_request_path(message, key)) {
866         goto error_clean_up_message;
867     }
868 
869     return message;
870 
871 error_clean_up_message:
872 
873     if (message != NULL) {
874         aws_http_message_release(message);
875         message = NULL;
876     }
877 
878     return NULL;
879 }
880 
aws_s3_tester_patch_client_vtable(struct aws_s3_tester * tester,struct aws_s3_client * client,size_t * out_index)881 struct aws_s3_client_vtable *aws_s3_tester_patch_client_vtable(
882     struct aws_s3_tester *tester,
883     struct aws_s3_client *client,
884     size_t *out_index) {
885 
886     struct aws_s3_client_vtable_patch patch;
887     AWS_ZERO_STRUCT(patch);
888 
889     /* Push a new vtable patch into the array. */
890     aws_array_list_push_back(&tester->client_vtable_patches, (void *)&patch);
891 
892     /* Get a pointer to the new vtable patch. */
893     size_t index = aws_array_list_length(&tester->client_vtable_patches) - 1;
894     struct aws_s3_client_vtable_patch *patch_array_ptr = aws_s3_tester_get_client_vtable_patch(tester, index);
895 
896     /* Cache a pointer to the original vtable. */
897     patch_array_ptr->original_vtable = client->vtable;
898 
899     /* Copy the original vtable contents into the patched vtable. */
900     memcpy(&patch_array_ptr->patched_vtable, patch_array_ptr->original_vtable, sizeof(struct aws_s3_client_vtable));
901 
902     /* Point the client at the new vtable. */
903     client->vtable = &patch_array_ptr->patched_vtable;
904 
905     if (out_index) {
906         *out_index = index;
907     }
908 
909     return &patch_array_ptr->patched_vtable;
910 }
911 
aws_s3_tester_get_client_vtable_patch(struct aws_s3_tester * tester,size_t index)912 struct aws_s3_client_vtable_patch *aws_s3_tester_get_client_vtable_patch(struct aws_s3_tester *tester, size_t index) {
913     struct aws_s3_client_vtable_patch *patch = NULL;
914     aws_array_list_get_at_ptr(&tester->client_vtable_patches, (void **)&patch, index);
915     return patch;
916 }
917 
aws_s3_tester_patch_meta_request_vtable(struct aws_s3_tester * tester,struct aws_s3_meta_request * meta_request,size_t * out_index)918 struct aws_s3_meta_request_vtable *aws_s3_tester_patch_meta_request_vtable(
919     struct aws_s3_tester *tester,
920     struct aws_s3_meta_request *meta_request,
921     size_t *out_index) {
922 
923     struct aws_s3_meta_request_vtable_patch patch;
924     AWS_ZERO_STRUCT(patch);
925 
926     /* Push a new vtable patch into the array. */
927     aws_array_list_push_back(&tester->meta_request_vtable_patches, (void *)&patch);
928 
929     /* Get a pointer to the new vtable patch. */
930     size_t index = aws_array_list_length(&tester->meta_request_vtable_patches) - 1;
931     struct aws_s3_meta_request_vtable_patch *patch_array_ptr =
932         aws_s3_tester_get_meta_request_vtable_patch(tester, index);
933 
934     /* Cache a pointer to the original vtable. */
935     patch_array_ptr->original_vtable = meta_request->vtable;
936 
937     /* Copy the original vtable contents into the patched vtable. */
938     memcpy(
939         &patch_array_ptr->patched_vtable, patch_array_ptr->original_vtable, sizeof(struct aws_s3_meta_request_vtable));
940 
941     /* Point the meta request at the new vtable. */
942     meta_request->vtable = &patch_array_ptr->patched_vtable;
943 
944     if (out_index) {
945         *out_index = index;
946     }
947 
948     return &patch_array_ptr->patched_vtable;
949 }
950 
aws_s3_tester_get_meta_request_vtable_patch(struct aws_s3_tester * tester,size_t index)951 struct aws_s3_meta_request_vtable_patch *aws_s3_tester_get_meta_request_vtable_patch(
952     struct aws_s3_tester *tester,
953     size_t index) {
954     struct aws_s3_meta_request_vtable_patch *patch = NULL;
955     aws_array_list_get_at_ptr(&tester->meta_request_vtable_patches, (void **)&patch, index);
956     return patch;
957 }
958 
aws_s3_test_put_object_request_new(struct aws_allocator * allocator,struct aws_byte_cursor host,struct aws_byte_cursor key,struct aws_byte_cursor content_type,struct aws_input_stream * body_stream,uint32_t flags)959 struct aws_http_message *aws_s3_test_put_object_request_new(
960     struct aws_allocator *allocator,
961     struct aws_byte_cursor host,
962     struct aws_byte_cursor key,
963     struct aws_byte_cursor content_type,
964     struct aws_input_stream *body_stream,
965     uint32_t flags) {
966 
967     AWS_PRECONDITION(allocator);
968     AWS_PRECONDITION(body_stream);
969 
970     int64_t body_stream_length = 0;
971 
972     if (aws_input_stream_get_length(body_stream, &body_stream_length)) {
973         return NULL;
974     }
975 
976     struct aws_http_message *message = aws_http_message_new_request(allocator);
977 
978     if (message == NULL) {
979         return NULL;
980     }
981 
982     struct aws_http_header host_header = {.name = g_host_header_name, .value = host};
983 
984     struct aws_http_header content_type_header = {.name = g_content_type_header_name, .value = content_type};
985 
986     char content_length_buffer[64] = "";
987     snprintf(content_length_buffer, sizeof(content_length_buffer), "%" PRId64 "", body_stream_length);
988 
989     struct aws_http_header content_length_header = {
990         .name = g_content_length_header_name,
991         .value = aws_byte_cursor_from_c_str(content_length_buffer),
992     };
993 
994     struct aws_http_header sse_kms_header = {.name = g_s3_sse_header, .value = aws_byte_cursor_from_c_str("aws:kms")};
995     struct aws_http_header sse_aes256_header = {.name = g_s3_sse_header, .value = aws_byte_cursor_from_c_str("AES256")};
996     struct aws_http_header acl_public_read_header = {
997         .name = g_acl_header_name,
998         .value = aws_byte_cursor_from_c_str("bucket-owner-read"),
999     };
1000 
1001     if (aws_http_message_add_header(message, host_header)) {
1002         goto error_clean_up_message;
1003     }
1004 
1005     if (aws_http_message_add_header(message, content_type_header)) {
1006         goto error_clean_up_message;
1007     }
1008 
1009     if (aws_http_message_add_header(message, content_length_header)) {
1010         goto error_clean_up_message;
1011     }
1012 
1013     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_SSE_KMS) {
1014         if (aws_http_message_add_header(message, sse_kms_header)) {
1015             goto error_clean_up_message;
1016         }
1017     }
1018 
1019     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_SSE_AES256) {
1020         if (aws_http_message_add_header(message, sse_aes256_header)) {
1021             goto error_clean_up_message;
1022         }
1023     }
1024 
1025     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_PUT_ACL) {
1026         if (aws_http_message_add_header(message, acl_public_read_header)) {
1027             goto error_clean_up_message;
1028         }
1029     }
1030 
1031     if (aws_http_message_set_request_method(message, aws_http_method_put)) {
1032         goto error_clean_up_message;
1033     }
1034 
1035     if (aws_http_message_set_request_path(message, key)) {
1036         goto error_clean_up_message;
1037     }
1038 
1039     aws_http_message_set_body_stream(message, body_stream);
1040 
1041     return message;
1042 
1043 error_clean_up_message:
1044 
1045     if (message != NULL) {
1046         aws_http_message_release(message);
1047         message = NULL;
1048     }
1049 
1050     return NULL;
1051 }
1052 
aws_s3_tester_client_new(struct aws_s3_tester * tester,struct aws_s3_tester_client_options * options,struct aws_s3_client ** out_client)1053 int aws_s3_tester_client_new(
1054     struct aws_s3_tester *tester,
1055     struct aws_s3_tester_client_options *options,
1056     struct aws_s3_client **out_client) {
1057     ASSERT_TRUE(tester != NULL);
1058     ASSERT_TRUE(options != NULL);
1059     ASSERT_TRUE(out_client != NULL);
1060 
1061     struct aws_s3_client_config client_config = {
1062         .part_size = options->part_size,
1063         .max_part_size = options->max_part_size,
1064     };
1065 
1066     struct aws_tls_connection_options tls_connection_options;
1067     AWS_ZERO_STRUCT(tls_connection_options);
1068 
1069 #ifndef BYO_CRYPTO
1070     struct aws_tls_ctx_options tls_context_options;
1071     aws_tls_ctx_options_init_default_client(&tls_context_options, tester->allocator);
1072 
1073     struct aws_tls_ctx *context = aws_tls_client_ctx_new(tester->allocator, &tls_context_options);
1074     aws_tls_connection_options_init_from_ctx(&tls_connection_options, context);
1075 #endif
1076 
1077     struct aws_string *endpoint =
1078         aws_s3_tester_build_endpoint_string(tester->allocator, &g_test_bucket_name, &g_test_s3_region);
1079     struct aws_byte_cursor endpoint_cursor = aws_byte_cursor_from_string(endpoint);
1080 
1081     tls_connection_options.server_name = aws_string_new_from_cursor(tester->allocator, &endpoint_cursor);
1082 
1083     switch (options->tls_usage) {
1084         case AWS_S3_TLS_ENABLED:
1085             client_config.tls_mode = AWS_MR_TLS_ENABLED;
1086             client_config.tls_connection_options = &tls_connection_options;
1087             break;
1088         case AWS_S3_TLS_DISABLED:
1089             client_config.tls_mode = AWS_MR_TLS_DISABLED;
1090             break;
1091         default:
1092             break;
1093     }
1094 
1095     ASSERT_SUCCESS(aws_s3_tester_bind_client(
1096         tester, &client_config, AWS_S3_TESTER_BIND_CLIENT_REGION | AWS_S3_TESTER_BIND_CLIENT_SIGNING));
1097 
1098     *out_client = aws_s3_client_new(tester->allocator, &client_config);
1099 
1100     aws_string_destroy(endpoint);
1101 
1102 #ifndef BYO_CRYPTO
1103     aws_tls_ctx_release(context);
1104     aws_tls_connection_options_clean_up(&tls_connection_options);
1105     aws_tls_ctx_options_clean_up(&tls_context_options);
1106 #endif
1107 
1108     return AWS_OP_SUCCESS;
1109 }
1110 
aws_s3_tester_send_meta_request_with_options(struct aws_s3_tester * tester,struct aws_s3_tester_meta_request_options * options,struct aws_s3_meta_request_test_results * out_results)1111 int aws_s3_tester_send_meta_request_with_options(
1112     struct aws_s3_tester *tester,
1113     struct aws_s3_tester_meta_request_options *options,
1114     struct aws_s3_meta_request_test_results *out_results) {
1115     ASSERT_TRUE(options != NULL);
1116 
1117     struct aws_allocator *allocator = options->allocator;
1118 
1119     struct aws_s3_tester local_tester;
1120     AWS_ZERO_STRUCT(local_tester);
1121     bool clean_up_local_tester = false;
1122 
1123     if (tester == NULL) {
1124         ASSERT_TRUE(options->allocator);
1125         ASSERT_SUCCESS(aws_s3_tester_init(options->allocator, &local_tester));
1126         tester = &local_tester;
1127         clean_up_local_tester = true;
1128     } else if (allocator == NULL) {
1129         allocator = tester->allocator;
1130     }
1131 
1132     struct aws_s3_client *client = options->client;
1133 
1134     if (client == NULL) {
1135 
1136         if (options->client_options != NULL) {
1137             ASSERT_SUCCESS(aws_s3_tester_client_new(tester, options->client_options, &client));
1138         } else {
1139             struct aws_s3_tester_client_options client_options;
1140             AWS_ZERO_STRUCT(client_options);
1141             ASSERT_SUCCESS(aws_s3_tester_client_new(tester, &client_options, &client));
1142         }
1143 
1144     } else {
1145         aws_s3_client_acquire(client);
1146     }
1147 
1148     struct aws_s3_meta_request_options meta_request_options = {
1149         .type = options->meta_request_type,
1150         .message = options->message,
1151     };
1152 
1153     struct aws_byte_buf input_stream_buffer;
1154     AWS_ZERO_STRUCT(input_stream_buffer);
1155 
1156     struct aws_input_stream *input_stream = NULL;
1157 
1158     if (meta_request_options.message == NULL) {
1159         const struct aws_byte_cursor *bucket_name = options->bucket_name;
1160 
1161         if (bucket_name == NULL) {
1162             bucket_name = &g_test_bucket_name;
1163         }
1164 
1165         struct aws_string *host_name = aws_s3_tester_build_endpoint_string(allocator, bucket_name, &g_test_s3_region);
1166 
1167         if (meta_request_options.type == AWS_S3_META_REQUEST_TYPE_GET_OBJECT ||
1168             (meta_request_options.type == AWS_S3_META_REQUEST_TYPE_DEFAULT &&
1169              options->default_type_options.mode == AWS_S3_TESTER_DEFAULT_TYPE_MODE_GET)) {
1170 
1171             struct aws_http_message *message = aws_s3_test_get_object_request_new(
1172                 allocator, aws_byte_cursor_from_string(host_name), options->get_options.object_path);
1173 
1174             if (options->get_options.object_range.ptr != NULL) {
1175                 struct aws_http_header range_header = {
1176                     .name = g_range_header_name,
1177                     .value = options->get_options.object_range,
1178                 };
1179 
1180                 aws_http_message_add_header(message, range_header);
1181             }
1182 
1183             meta_request_options.message = message;
1184 
1185         } else if (
1186             meta_request_options.type == AWS_S3_META_REQUEST_TYPE_PUT_OBJECT ||
1187             (meta_request_options.type == AWS_S3_META_REQUEST_TYPE_DEFAULT &&
1188              options->default_type_options.mode == AWS_S3_TESTER_DEFAULT_TYPE_MODE_PUT)) {
1189 
1190             uint32_t object_size_mb = options->put_options.object_size_mb;
1191             size_t object_size_bytes = (size_t)object_size_mb * 1024ULL * 1024ULL;
1192 
1193             if (options->put_options.ensure_multipart) {
1194                 if (object_size_bytes == 0) {
1195                     object_size_bytes = client->part_size * 2;
1196                     object_size_mb = (uint32_t)(object_size_bytes / 1024 / 1024);
1197                 }
1198 
1199                 ASSERT_TRUE(object_size_bytes > client->part_size);
1200             }
1201 
1202             if (options->put_options.invalid_input_stream) {
1203                 input_stream = aws_s3_bad_input_stream_new(allocator, object_size_bytes);
1204             } else {
1205                 input_stream = aws_s3_test_input_stream_new(allocator, object_size_bytes);
1206             }
1207 
1208             struct aws_byte_buf object_path_buffer;
1209             aws_byte_buf_init(&object_path_buffer, allocator, 128);
1210 
1211             if (options->put_options.object_path_override.ptr != NULL) {
1212                 aws_byte_buf_append_dynamic(&object_path_buffer, &options->put_options.object_path_override);
1213             } else {
1214                 char object_path_sprintf_buffer[128] = "";
1215 
1216                 switch (options->sse_type) {
1217                     case AWS_S3_TESTER_SSE_NONE:
1218                         snprintf(
1219                             object_path_sprintf_buffer,
1220                             sizeof(object_path_sprintf_buffer),
1221                             "/put_object_test_%uMB.txt",
1222                             object_size_mb);
1223                         break;
1224                     case AWS_S3_TESTER_SSE_KMS:
1225                         snprintf(
1226                             object_path_sprintf_buffer,
1227                             sizeof(object_path_sprintf_buffer),
1228                             "/put_object_test_kms_%uMB.txt",
1229                             object_size_mb);
1230                         break;
1231                     case AWS_S3_TESTER_SSE_AES256:
1232                         snprintf(
1233                             object_path_sprintf_buffer,
1234                             sizeof(object_path_sprintf_buffer),
1235                             "/put_object_test_aes256_%uMB.txt",
1236                             object_size_mb);
1237                         break;
1238 
1239                     default:
1240                         break;
1241                 }
1242 
1243                 struct aws_byte_cursor sprintf_buffer_cursor = aws_byte_cursor_from_c_str(object_path_sprintf_buffer);
1244                 aws_byte_buf_append_dynamic(&object_path_buffer, &sprintf_buffer_cursor);
1245             }
1246 
1247             struct aws_byte_cursor test_object_path = aws_byte_cursor_from_buf(&object_path_buffer);
1248 
1249             /* Put together a simple S3 Put Object request. */
1250             struct aws_http_message *message = aws_s3_test_put_object_request_new(
1251                 allocator,
1252                 aws_byte_cursor_from_string(host_name),
1253                 test_object_path,
1254                 g_test_body_content_type,
1255                 input_stream,
1256                 options->sse_type);
1257 
1258             aws_byte_buf_clean_up(&object_path_buffer);
1259 
1260             if (options->put_options.content_length) {
1261                 /* make a invalid request */
1262                 char content_length_buffer[64] = "";
1263                 snprintf(
1264                     content_length_buffer, sizeof(content_length_buffer), "%zu", options->put_options.content_length);
1265 
1266                 struct aws_http_headers *headers = aws_http_message_get_headers(message);
1267                 aws_http_headers_set(
1268                     headers, g_content_length_header_name, aws_byte_cursor_from_c_str(content_length_buffer));
1269             }
1270 
1271             if (options->put_options.invalid_request) {
1272                 /* make a invalid request */
1273                 aws_http_message_set_request_path(message, aws_byte_cursor_from_c_str("invalid_path"));
1274             }
1275 
1276             meta_request_options.message = message;
1277         }
1278 
1279         ASSERT_TRUE(meta_request_options.message != NULL);
1280 
1281         aws_string_destroy(host_name);
1282     } else {
1283         aws_http_message_acquire(meta_request_options.message);
1284     }
1285 
1286     struct aws_s3_meta_request_test_results meta_request_test_results;
1287     AWS_ZERO_STRUCT(meta_request_test_results);
1288 
1289     if (out_results == NULL) {
1290         out_results = &meta_request_test_results;
1291     }
1292 
1293     out_results->headers_callback = options->headers_callback;
1294     out_results->body_callback = options->body_callback;
1295 
1296     ASSERT_SUCCESS(aws_s3_tester_bind_meta_request(tester, &meta_request_options, out_results));
1297 
1298     struct aws_s3_meta_request *meta_request = aws_s3_client_make_meta_request(client, &meta_request_options);
1299 
1300     if (meta_request == NULL) {
1301         out_results->finished_error_code = aws_last_error();
1302     }
1303 
1304     aws_http_message_release(meta_request_options.message);
1305     meta_request_options.message = NULL;
1306 
1307     if (meta_request != NULL) {
1308         /* Wait for the request to finish. */
1309         aws_s3_tester_wait_for_meta_request_finish(tester);
1310         ASSERT_TRUE(aws_s3_meta_request_is_finished(meta_request));
1311     }
1312 
1313     aws_s3_tester_lock_synced_data(tester);
1314 
1315     switch (options->validate_type) {
1316         case AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_SUCCESS:
1317             ASSERT_TRUE(out_results->finished_error_code == AWS_ERROR_SUCCESS);
1318 
1319             if (meta_request_options.type == AWS_S3_META_REQUEST_TYPE_GET_OBJECT) {
1320                 ASSERT_SUCCESS(aws_s3_tester_validate_get_object_results(out_results, options->sse_type));
1321             } else if (meta_request_options.type == AWS_S3_META_REQUEST_TYPE_PUT_OBJECT) {
1322                 ASSERT_SUCCESS(aws_s3_tester_validate_put_object_results(out_results, options->sse_type));
1323             }
1324             break;
1325         case AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_FAILURE:
1326             ASSERT_FALSE(out_results->finished_error_code == AWS_ERROR_SUCCESS);
1327             break;
1328 
1329         default:
1330             ASSERT_TRUE(false);
1331             break;
1332     }
1333 
1334     aws_s3_tester_unlock_synced_data(tester);
1335 
1336     if (meta_request != NULL) {
1337         out_results->part_size = meta_request->part_size;
1338         aws_s3_meta_request_release(meta_request);
1339         meta_request = NULL;
1340 
1341         if (!options->dont_wait_for_shutdown) {
1342             aws_s3_tester_wait_for_meta_request_shutdown(tester);
1343         }
1344     }
1345 
1346     aws_s3_meta_request_test_results_clean_up(&meta_request_test_results);
1347 
1348     aws_s3_client_release(client);
1349 
1350     aws_input_stream_destroy(input_stream);
1351     input_stream = NULL;
1352 
1353     aws_byte_buf_clean_up(&input_stream_buffer);
1354 
1355     if (clean_up_local_tester) {
1356         aws_s3_tester_clean_up(&local_tester);
1357     }
1358 
1359     return AWS_OP_SUCCESS;
1360 }
1361 
aws_s3_tester_send_meta_request(struct aws_s3_tester * tester,struct aws_s3_client * client,struct aws_s3_meta_request_options * options,struct aws_s3_meta_request_test_results * test_results,uint32_t flags)1362 int aws_s3_tester_send_meta_request(
1363     struct aws_s3_tester *tester,
1364     struct aws_s3_client *client,
1365     struct aws_s3_meta_request_options *options,
1366     struct aws_s3_meta_request_test_results *test_results,
1367     uint32_t flags) {
1368 
1369     ASSERT_SUCCESS(aws_s3_tester_bind_meta_request(tester, options, test_results));
1370 
1371     struct aws_s3_meta_request *meta_request = aws_s3_client_make_meta_request(client, options);
1372 
1373     ASSERT_TRUE(meta_request != NULL);
1374 
1375     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_CANCEL) {
1376         /* take a random sleep from 0-1 ms. */
1377         srand((uint32_t)time(NULL));
1378         aws_thread_current_sleep(rand() % 1000000);
1379         aws_s3_meta_request_cancel(meta_request);
1380     }
1381 
1382     /* Wait for the request to finish. */
1383     aws_s3_tester_wait_for_meta_request_finish(tester);
1384 
1385     ASSERT_TRUE(aws_s3_meta_request_is_finished(meta_request));
1386 
1387     aws_s3_tester_lock_synced_data(tester);
1388 
1389     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_EXPECT_SUCCESS) {
1390         ASSERT_TRUE(tester->synced_data.finish_error_code == AWS_ERROR_SUCCESS);
1391     } else if (flags & AWS_S3_TESTER_SEND_META_REQUEST_CANCEL) {
1392         ASSERT_TRUE(tester->synced_data.finish_error_code == AWS_ERROR_S3_CANCELED);
1393     } else {
1394         ASSERT_FALSE(tester->synced_data.finish_error_code == AWS_ERROR_SUCCESS);
1395     }
1396 
1397     aws_s3_tester_unlock_synced_data(tester);
1398 
1399     test_results->part_size = meta_request->part_size;
1400 
1401     aws_s3_meta_request_release(meta_request);
1402 
1403     if ((flags & AWS_S3_TESTER_SEND_META_REQUEST_DONT_WAIT_FOR_SHUTDOWN) == 0) {
1404         aws_s3_tester_wait_for_meta_request_shutdown(tester);
1405     }
1406 
1407     return AWS_OP_SUCCESS;
1408 }
1409 
aws_s3_tester_send_get_object_meta_request(struct aws_s3_tester * tester,struct aws_s3_client * client,struct aws_byte_cursor s3_path,uint32_t flags,struct aws_s3_meta_request_test_results * out_results)1410 int aws_s3_tester_send_get_object_meta_request(
1411     struct aws_s3_tester *tester,
1412     struct aws_s3_client *client,
1413     struct aws_byte_cursor s3_path,
1414     uint32_t flags,
1415     struct aws_s3_meta_request_test_results *out_results) {
1416 
1417     struct aws_string *host_name =
1418         aws_s3_tester_build_endpoint_string(tester->allocator, &g_test_bucket_name, &g_test_s3_region);
1419 
1420     /* Put together a simple S3 Get Object request. */
1421     struct aws_http_message *message =
1422         aws_s3_test_get_object_request_new(tester->allocator, aws_byte_cursor_from_string(host_name), s3_path);
1423 
1424     struct aws_s3_meta_request_options options;
1425     AWS_ZERO_STRUCT(options);
1426     options.type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT;
1427     options.message = message;
1428 
1429     /* Trigger accelerating of our Get Object request. */
1430     struct aws_s3_meta_request_test_results meta_request_test_results;
1431     AWS_ZERO_STRUCT(meta_request_test_results);
1432 
1433     if (out_results == NULL) {
1434         out_results = &meta_request_test_results;
1435     }
1436 
1437     ASSERT_SUCCESS(aws_s3_tester_send_meta_request(tester, client, &options, out_results, flags));
1438 
1439     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_EXPECT_SUCCESS) {
1440         ASSERT_SUCCESS(aws_s3_tester_validate_get_object_results(out_results, flags));
1441     }
1442 
1443     aws_s3_meta_request_test_results_clean_up(&meta_request_test_results);
1444 
1445     aws_http_message_release(message);
1446     aws_string_destroy(host_name);
1447 
1448     return AWS_OP_SUCCESS;
1449 }
1450 
aws_s3_tester_validate_get_object_results(struct aws_s3_meta_request_test_results * meta_request_test_results,uint32_t flags)1451 int aws_s3_tester_validate_get_object_results(
1452     struct aws_s3_meta_request_test_results *meta_request_test_results,
1453     uint32_t flags) {
1454     AWS_PRECONDITION(meta_request_test_results);
1455     AWS_PRECONDITION(meta_request_test_results->tester);
1456 
1457     ASSERT_TRUE(meta_request_test_results->response_headers != NULL);
1458 
1459     if (aws_http_headers_has(
1460             meta_request_test_results->response_headers, aws_byte_cursor_from_c_str("Content-Range"))) {
1461         ASSERT_TRUE(meta_request_test_results->finished_response_status == 206);
1462     } else {
1463         ASSERT_TRUE(meta_request_test_results->finished_response_status == 200);
1464     }
1465 
1466     ASSERT_TRUE(
1467         meta_request_test_results->finished_response_status == meta_request_test_results->headers_response_status);
1468     ASSERT_TRUE(meta_request_test_results->finished_error_code == AWS_ERROR_SUCCESS);
1469 
1470     ASSERT_TRUE(meta_request_test_results->error_response_headers == NULL);
1471     ASSERT_TRUE(meta_request_test_results->error_response_body.len == 0);
1472 
1473     struct aws_s3_tester *tester = meta_request_test_results->tester;
1474 
1475     struct aws_byte_cursor content_length_cursor;
1476     AWS_ZERO_STRUCT(content_length_cursor);
1477     ASSERT_SUCCESS(aws_http_headers_get(
1478         meta_request_test_results->response_headers,
1479         aws_byte_cursor_from_c_str("Content-Length"),
1480         &content_length_cursor));
1481 
1482     struct aws_byte_cursor sse_byte_cursor;
1483 
1484     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_SSE_KMS) {
1485         ASSERT_SUCCESS(
1486             aws_http_headers_get(meta_request_test_results->response_headers, g_s3_sse_header, &sse_byte_cursor));
1487         ASSERT_TRUE(aws_byte_cursor_eq_c_str(&sse_byte_cursor, "aws:kms"));
1488     }
1489 
1490     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_SSE_AES256) {
1491         ASSERT_SUCCESS(
1492             aws_http_headers_get(meta_request_test_results->response_headers, g_s3_sse_header, &sse_byte_cursor));
1493         ASSERT_TRUE(aws_byte_cursor_eq_c_str(&sse_byte_cursor, "AES256"));
1494     }
1495 
1496     struct aws_string *content_length_str = aws_string_new_from_cursor(tester->allocator, &content_length_cursor);
1497 
1498     char *content_length_str_end = NULL;
1499     uint64_t content_length = strtoull((const char *)content_length_str->bytes, &content_length_str_end, 10);
1500 
1501     aws_string_destroy(content_length_str);
1502 
1503     AWS_LOGF_DEBUG(
1504         AWS_LS_S3_GENERAL,
1505         "Content length in header is %" PRIu64 " and received body size is %" PRIu64,
1506         content_length,
1507         meta_request_test_results->received_body_size);
1508 
1509     ASSERT_TRUE(content_length == meta_request_test_results->received_body_size);
1510 
1511     return AWS_OP_SUCCESS;
1512 }
1513 
aws_s3_tester_send_put_object_meta_request(struct aws_s3_tester * tester,struct aws_s3_client * client,uint32_t file_size_mb,uint32_t flags,struct aws_s3_meta_request_test_results * out_results)1514 int aws_s3_tester_send_put_object_meta_request(
1515     struct aws_s3_tester *tester,
1516     struct aws_s3_client *client,
1517     uint32_t file_size_mb,
1518     uint32_t flags,
1519     struct aws_s3_meta_request_test_results *out_results) {
1520     ASSERT_TRUE(tester != NULL);
1521     ASSERT_TRUE(client != NULL);
1522 
1523     struct aws_allocator *allocator = tester->allocator;
1524 
1525     struct aws_byte_buf test_buffer;
1526     aws_s3_create_test_buffer(allocator, (size_t)file_size_mb * 1024ULL * 1024ULL, &test_buffer);
1527 
1528     struct aws_byte_cursor test_body_cursor = aws_byte_cursor_from_buf(&test_buffer);
1529     struct aws_input_stream *input_stream = aws_input_stream_new_from_cursor(allocator, &test_body_cursor);
1530 
1531     struct aws_string *host_name =
1532         aws_s3_tester_build_endpoint_string(allocator, &g_test_bucket_name, &g_test_s3_region);
1533 
1534     char object_path_buffer[128] = "";
1535 
1536     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_SSE_KMS) {
1537         snprintf(object_path_buffer, sizeof(object_path_buffer), "/get_object_test_kms_%uMB.txt", file_size_mb);
1538     } else if (flags & AWS_S3_TESTER_SEND_META_REQUEST_SSE_KMS) {
1539         snprintf(object_path_buffer, sizeof(object_path_buffer), "/get_object_test_aes256_%uMB.txt", file_size_mb);
1540     } else if (flags & AWS_S3_TESTER_SEND_META_REQUEST_PUT_ACL) {
1541         snprintf(
1542             object_path_buffer, sizeof(object_path_buffer), "/get_object_test_acl_public_read_%uMB.txt", file_size_mb);
1543     } else {
1544         snprintf(object_path_buffer, sizeof(object_path_buffer), "/get_object_test_%uMB.txt", file_size_mb);
1545     }
1546     struct aws_byte_cursor test_object_path = aws_byte_cursor_from_c_str(object_path_buffer);
1547 
1548     /* Put together a simple S3 Put Object request. */
1549     struct aws_http_message *message = aws_s3_test_put_object_request_new(
1550         allocator,
1551         aws_byte_cursor_from_string(host_name),
1552         test_object_path,
1553         g_test_body_content_type,
1554         input_stream,
1555         flags);
1556 
1557     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_WITH_CORRECT_CONTENT_MD5) {
1558         ASSERT_SUCCESS(aws_s3_message_util_add_content_md5_header(allocator, &test_buffer, message));
1559     } else if (flags & AWS_S3_TESTER_SEND_META_REQUEST_WITH_INCORRECT_CONTENT_MD5) {
1560         struct aws_http_header content_md5_header = {
1561             .name = g_content_md5_header_name,
1562             .value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("dummy_content_md5"),
1563         };
1564         ASSERT_SUCCESS(aws_http_message_add_header(message, content_md5_header));
1565     }
1566 
1567     struct aws_s3_meta_request_options options;
1568     AWS_ZERO_STRUCT(options);
1569     options.type = AWS_S3_META_REQUEST_TYPE_PUT_OBJECT;
1570     options.message = message;
1571 
1572     struct aws_s3_meta_request_test_results meta_request_test_results;
1573     AWS_ZERO_STRUCT(meta_request_test_results);
1574 
1575     if (out_results == NULL) {
1576         out_results = &meta_request_test_results;
1577     }
1578 
1579     ASSERT_SUCCESS(aws_s3_tester_send_meta_request(tester, client, &options, out_results, flags));
1580 
1581     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_EXPECT_SUCCESS) {
1582         ASSERT_SUCCESS(aws_s3_tester_validate_put_object_results(out_results, flags));
1583     }
1584 
1585     aws_s3_meta_request_test_results_clean_up(&meta_request_test_results);
1586 
1587     aws_http_message_release(message);
1588     message = NULL;
1589 
1590     aws_string_destroy(host_name);
1591     host_name = NULL;
1592 
1593     aws_input_stream_destroy(input_stream);
1594     input_stream = NULL;
1595 
1596     aws_byte_buf_clean_up(&test_buffer);
1597 
1598     return AWS_OP_SUCCESS;
1599 }
1600 
aws_s3_tester_validate_put_object_results(struct aws_s3_meta_request_test_results * meta_request_test_results,uint32_t flags)1601 int aws_s3_tester_validate_put_object_results(
1602     struct aws_s3_meta_request_test_results *meta_request_test_results,
1603     uint32_t flags) {
1604     ASSERT_TRUE(meta_request_test_results->finished_response_status == 200);
1605     ASSERT_TRUE(
1606         meta_request_test_results->finished_response_status == meta_request_test_results->headers_response_status);
1607     ASSERT_TRUE(meta_request_test_results->finished_error_code == AWS_ERROR_SUCCESS);
1608 
1609     ASSERT_TRUE(meta_request_test_results->error_response_headers == NULL);
1610     ASSERT_TRUE(meta_request_test_results->error_response_body.len == 0);
1611 
1612     struct aws_byte_cursor etag_byte_cursor;
1613     AWS_ZERO_STRUCT(etag_byte_cursor);
1614     ASSERT_SUCCESS(
1615         aws_http_headers_get(meta_request_test_results->response_headers, g_etag_header_name, &etag_byte_cursor));
1616     struct aws_byte_cursor sse_byte_cursor;
1617     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_SSE_KMS) {
1618         ASSERT_SUCCESS(
1619             aws_http_headers_get(meta_request_test_results->response_headers, g_s3_sse_header, &sse_byte_cursor));
1620         ASSERT_TRUE(aws_byte_cursor_eq_c_str(&sse_byte_cursor, "aws:kms"));
1621     }
1622     if (flags & AWS_S3_TESTER_SEND_META_REQUEST_SSE_AES256) {
1623         ASSERT_SUCCESS(
1624             aws_http_headers_get(meta_request_test_results->response_headers, g_s3_sse_header, &sse_byte_cursor));
1625         ASSERT_TRUE(aws_byte_cursor_eq_c_str(&sse_byte_cursor, "AES256"));
1626     }
1627     ASSERT_TRUE(etag_byte_cursor.len > 0);
1628 
1629     struct aws_byte_cursor quote_entity = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("&quot;");
1630 
1631     if (etag_byte_cursor.len >= quote_entity.len) {
1632         for (size_t i = 0; i < (etag_byte_cursor.len - quote_entity.len + 1); ++i) {
1633             ASSERT_TRUE(
1634                 strncmp((const char *)&etag_byte_cursor.ptr[i], (const char *)quote_entity.ptr, quote_entity.len) != 0);
1635         }
1636     }
1637 
1638     return AWS_OP_SUCCESS;
1639 }
1640