Skip to content

Commit c95ad5c

Browse files
authored
More S3 client test (#255)
1 parent 2433461 commit c95ad5c

File tree

11 files changed

+283
-92
lines changed

11 files changed

+283
-92
lines changed

.builder/actions/mock_server_setup.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def run(self, env):
2222
python_path = sys.executable
2323
# install dependency for mock server
2424
self.env.shell.exec(python_path,
25-
'-m', 'pip', 'install', 'h11', 'trio', check=True)
25+
'-m', 'pip', 'install', 'h11', 'trio', 'proxy.py', check=True)
2626
# check the deps can be import correctly
2727
self.env.shell.exec(python_path,
2828
'-c', 'import h11, trio', check=True)
@@ -34,8 +34,16 @@ def run(self, env):
3434
base_dir = os.path.dirname(os.path.realpath(__file__))
3535
dir = os.path.join(base_dir, "..", "..", "tests", "mock_s3_server")
3636

37-
p = subprocess.Popen([python_path, "mock_s3_server.py"], cwd=dir)
37+
p1 = subprocess.Popen([python_path, "mock_s3_server.py"], cwd=dir)
38+
try:
39+
p2 = subprocess.Popen("proxy", cwd=dir)
40+
except Exception as e:
41+
# Okay for proxy to fail starting up as it may not be in the path
42+
print(e)
43+
p2 = None
3844

3945
@atexit.register
4046
def close_mock_server():
41-
p.terminate()
47+
p1.terminate()
48+
if p2 != None:
49+
p2.terminate()

include/aws/s3/private/s3_request_messages.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct aws_http_message *aws_s3_message_util_copy_http_message_no_body_filter_he
4040
/* Copy headers from one message to the other and exclude specific headers.
4141
* exclude_x_amz_meta controls whether S3 user metadata headers (prefixed with "x-amz-meta) are excluded.*/
4242
AWS_S3_API
43-
int aws_s3_message_util_copy_headers(
43+
void aws_s3_message_util_copy_headers(
4444
struct aws_http_message *source_message,
4545
struct aws_http_message *dest_message,
4646
const struct aws_byte_cursor *excluded_headers_arrays,

source/s3_client.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -668,13 +668,7 @@ int s_apply_endpoint_override(
668668
}
669669

670670
struct aws_byte_cursor host_value;
671-
if (aws_http_headers_get(message_headers, g_host_header_name, &host_value)) {
672-
AWS_LOGF_ERROR(
673-
AWS_LS_S3_CLIENT,
674-
"id=%p Cannot create meta s3 request; message provided in options does not have a 'Host' header.",
675-
(void *)client);
676-
return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
677-
}
671+
AWS_FATAL_ASSERT(aws_http_headers_get(message_headers, g_host_header_name, &host_value) == AWS_OP_SUCCESS);
678672

679673
if (endpoint_authority != NULL && !aws_byte_cursor_eq(&host_value, endpoint_authority)) {
680674
AWS_LOGF_ERROR(

source/s3_request_messages.c

Lines changed: 22 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ struct aws_http_message *aws_s3_create_multipart_upload_message_new(
266266
false /*exclude_x_amz_meta*/);
267267

268268
if (message == NULL) {
269-
goto error_clean_up;
269+
return NULL;
270270
}
271271

272272
if (aws_s3_message_util_set_multipart_request_path(allocator, NULL, 0, true, message)) {
@@ -299,12 +299,7 @@ struct aws_http_message *aws_s3_create_multipart_upload_message_new(
299299
return message;
300300

301301
error_clean_up:
302-
303-
if (message != NULL) {
304-
aws_http_message_release(message);
305-
message = NULL;
306-
}
307-
302+
aws_http_message_release(message);
308303
return NULL;
309304
}
310305

@@ -322,6 +317,7 @@ struct aws_http_message *aws_s3_upload_part_message_new(
322317
AWS_PRECONDITION(allocator);
323318
AWS_PRECONDITION(base_message);
324319
AWS_PRECONDITION(part_number > 0);
320+
AWS_PRECONDITION(buffer);
325321

326322
struct aws_http_message *message = aws_s3_message_util_copy_http_message_no_body_filter_headers(
327323
allocator,
@@ -331,40 +327,30 @@ struct aws_http_message *aws_s3_upload_part_message_new(
331327
true /*exclude_x_amz_meta*/);
332328

333329
if (message == NULL) {
334-
goto error_clean_up;
330+
return NULL;
335331
}
336332

337333
if (aws_s3_message_util_set_multipart_request_path(allocator, upload_id, part_number, false, message)) {
338334
goto error_clean_up;
339335
}
340336

341-
if (buffer != NULL) {
337+
if (aws_s3_message_util_assign_body(allocator, buffer, message, checksum_config, encoded_checksum_output) == NULL) {
338+
goto error_clean_up;
339+
}
342340

343-
if (aws_s3_message_util_assign_body(allocator, buffer, message, checksum_config, encoded_checksum_output) ==
344-
NULL) {
345-
goto error_clean_up;
346-
}
347-
if (should_compute_content_md5) {
348-
if (!checksum_config || checksum_config->location == AWS_SCL_NONE) {
349-
/* MD5 will be skiped if flexible checksum used */
350-
if (aws_s3_message_util_add_content_md5_header(allocator, buffer, message)) {
351-
goto error_clean_up;
352-
}
341+
if (should_compute_content_md5) {
342+
if (!checksum_config || checksum_config->location == AWS_SCL_NONE) {
343+
/* MD5 will be skiped if flexible checksum used */
344+
if (aws_s3_message_util_add_content_md5_header(allocator, buffer, message)) {
345+
goto error_clean_up;
353346
}
354347
}
355-
} else {
356-
goto error_clean_up;
357348
}
358349

359350
return message;
360351

361352
error_clean_up:
362-
363-
if (message != NULL) {
364-
aws_http_message_release(message);
365-
message = NULL;
366-
}
367-
353+
aws_http_message_release(message);
368354
return NULL;
369355
}
370356

@@ -900,10 +886,7 @@ struct aws_http_message *aws_s3_message_util_copy_http_message_no_body_filter_he
900886
AWS_PRECONDITION(base_message);
901887

902888
struct aws_http_message *message = aws_http_message_new_request(allocator);
903-
904-
if (message == NULL) {
905-
return NULL;
906-
}
889+
AWS_ASSERT(message);
907890

908891
struct aws_byte_cursor request_method;
909892
if (aws_http_message_get_request_method(base_message, &request_method)) {
@@ -925,24 +908,17 @@ struct aws_http_message *aws_s3_message_util_copy_http_message_no_body_filter_he
925908
goto error_clean_up;
926909
}
927910

928-
if (aws_s3_message_util_copy_headers(
929-
base_message, message, excluded_header_array, excluded_header_array_size, exclude_x_amz_meta)) {
930-
goto error_clean_up;
931-
}
911+
aws_s3_message_util_copy_headers(
912+
base_message, message, excluded_header_array, excluded_header_array_size, exclude_x_amz_meta);
932913

933914
return message;
934915

935916
error_clean_up:
936-
937-
if (message != NULL) {
938-
aws_http_message_release(message);
939-
message = NULL;
940-
}
941-
917+
aws_http_message_release(message);
942918
return NULL;
943919
}
944920

945-
int aws_s3_message_util_copy_headers(
921+
void aws_s3_message_util_copy_headers(
946922
struct aws_http_message *source_message,
947923
struct aws_http_message *dest_message,
948924
const struct aws_byte_cursor *excluded_header_array,
@@ -954,9 +930,7 @@ int aws_s3_message_util_copy_headers(
954930
for (size_t header_index = 0; header_index < num_headers; ++header_index) {
955931
struct aws_http_header header;
956932

957-
if (aws_http_message_get_header(source_message, &header, header_index)) {
958-
return AWS_OP_ERR;
959-
}
933+
int error = aws_http_message_get_header(source_message, &header, header_index);
960934

961935
if (excluded_header_array && excluded_header_array_size > 0) {
962936
bool exclude_header = false;
@@ -979,12 +953,10 @@ int aws_s3_message_util_copy_headers(
979953
}
980954
}
981955

982-
if (aws_http_message_add_header(dest_message, header)) {
983-
return AWS_OP_ERR;
984-
}
956+
error |= aws_http_message_add_header(dest_message, header);
957+
(void)error;
958+
AWS_ASSERT(!error);
985959
}
986-
987-
return AWS_OP_SUCCESS;
988960
}
989961

990962
/* Add a range header.*/

tests/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ add_test_case(test_s3_ranged_get_object_message_new)
2020
add_test_case(test_s3_set_multipart_request_path)
2121
add_test_case(test_s3_create_multipart_upload_message_new)
2222
add_test_case(test_s3_upload_part_message_new)
23+
add_test_case(test_s3_upload_part_message_fail)
2324
add_test_case(test_s3_complete_multipart_message_new)
2425
add_test_case(test_s3_abort_multipart_upload_message_new)
2526

2627
add_net_test_case(test_s3_client_create_destroy)
28+
add_net_test_case(test_s3_client_create_error)
2729
add_net_test_case(test_s3_client_monitoring_options_override)
2830
add_net_test_case(test_s3_client_proxy_ev_settings_override)
2931
add_net_test_case(test_s3_client_tcp_keep_alive_options_override)
@@ -235,11 +237,14 @@ if(ENABLE_MOCK_SERVER_TESTS)
235237
add_net_test_case(resume_mutli_page_list_parts_mock_server)
236238
add_net_test_case(resume_list_parts_failed_mock_server)
237239
add_net_test_case(resume_after_finished_mock_server)
240+
add_net_test_case(multipart_upload_proxy_mock_server)
241+
add_net_test_case(endpoint_override_mock_server)
238242
endif()
239243

240244
add_net_test_case(meta_request_auto_ranged_get_new_error_handling)
241245
add_net_test_case(meta_request_auto_ranged_put_new_error_handling)
242246
add_net_test_case(bad_request_error_handling)
247+
add_net_test_case(make_meta_request_error_handling)
243248

244249
set(TEST_BINARY_NAME ${PROJECT_NAME}-tests)
245250
generate_test_driver(${TEST_BINARY_NAME})

tests/s3_data_plane_tests.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,31 @@ static int s_test_s3_client_create_destroy(struct aws_allocator *allocator, void
5050
return 0;
5151
}
5252

53+
AWS_TEST_CASE(test_s3_client_create_error, s_test_s3_client_create_error)
54+
static int s_test_s3_client_create_error(struct aws_allocator *allocator, void *ctx) {
55+
(void)ctx;
56+
57+
struct aws_s3_tester tester;
58+
AWS_ZERO_STRUCT(tester);
59+
ASSERT_SUCCESS(aws_s3_tester_init(allocator, &tester));
60+
61+
struct aws_s3_client_config client_config;
62+
AWS_ZERO_STRUCT(client_config);
63+
struct aws_http_proxy_options proxy_options = {
64+
.connection_type = AWS_HPCT_HTTP_LEGACY,
65+
.host = aws_byte_cursor_from_c_str("localhost"),
66+
.port = 8899,
67+
};
68+
client_config.proxy_options = &proxy_options;
69+
struct aws_s3_client *client = aws_s3_client_new(allocator, &client_config);
70+
71+
ASSERT_TRUE(client == NULL);
72+
73+
aws_s3_tester_clean_up(&tester);
74+
75+
return 0;
76+
}
77+
5378
AWS_TEST_CASE(test_s3_client_monitoring_options_override, s_test_s3_client_monitoring_options_override)
5479
static int s_test_s3_client_monitoring_options_override(struct aws_allocator *allocator, void *ctx) {
5580
(void)ctx;
@@ -1713,13 +1738,9 @@ static int s_test_s3_put_object_multiple(struct aws_allocator *allocator, void *
17131738
struct aws_byte_cursor test_body_cursor = aws_byte_cursor_from_buf(&input_stream_buffers[i]);
17141739
input_streams[i] = aws_input_stream_new_from_cursor(allocator, &test_body_cursor);
17151740
struct aws_byte_cursor test_object_path = aws_byte_cursor_from_c_str(object_path_buffer);
1741+
struct aws_byte_cursor host_cur = aws_byte_cursor_from_string(host_name);
17161742
messages[i] = aws_s3_test_put_object_request_new(
1717-
allocator,
1718-
aws_byte_cursor_from_string(host_name),
1719-
test_object_path,
1720-
g_test_body_content_type,
1721-
input_streams[i],
1722-
0);
1743+
allocator, &host_cur, test_object_path, g_test_body_content_type, input_streams[i], 0);
17231744
struct aws_s3_meta_request_options options;
17241745
AWS_ZERO_STRUCT(options);
17251746
options.type = AWS_S3_META_REQUEST_TYPE_PUT_OBJECT;
@@ -2293,7 +2314,7 @@ static int s_test_s3_upload_part_message_helper(struct aws_allocator *allocator,
22932314

22942315
/* Put together a simple S3 Put Object request. */
22952316
struct aws_http_message *base_message = aws_s3_test_put_object_request_new(
2296-
allocator, host_name, test_object_path, g_test_body_content_type, input_stream, AWS_S3_TESTER_SSE_NONE);
2317+
allocator, &host_name, test_object_path, g_test_body_content_type, input_stream, AWS_S3_TESTER_SSE_NONE);
22972318

22982319
uint32_t part_number = 1;
22992320
struct aws_string *upload_id = aws_string_new_from_c_str(allocator, "dummy_upload_id");
@@ -2366,7 +2387,7 @@ static int s_test_s3_create_multipart_upload_message_with_content_md5(struct aws
23662387

23672388
/* Put together a simple S3 Put Object request. */
23682389
struct aws_http_message *base_message = aws_s3_test_put_object_request_new(
2369-
allocator, host_name, test_object_path, g_test_body_content_type, input_stream, AWS_S3_TESTER_SSE_NONE);
2390+
allocator, &host_name, test_object_path, g_test_body_content_type, input_stream, AWS_S3_TESTER_SSE_NONE);
23702391

23712392
struct aws_http_header content_md5_header = {
23722393
.name = g_content_md5_header_name,
@@ -2415,7 +2436,7 @@ static int s_test_s3_complete_multipart_message_with_content_md5(struct aws_allo
24152436

24162437
/* Put together a simple S3 Put Object request. */
24172438
struct aws_http_message *base_message = aws_s3_test_put_object_request_new(
2418-
allocator, host_name, test_object_path, g_test_body_content_type, input_stream, AWS_S3_TESTER_SSE_NONE);
2439+
allocator, &host_name, test_object_path, g_test_body_content_type, input_stream, AWS_S3_TESTER_SSE_NONE);
24192440

24202441
struct aws_http_header content_md5_header = {
24212442
.name = g_content_md5_header_name,

tests/s3_meta_request_test.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,59 @@ TEST_CASE(bad_request_error_handling) {
153153

154154
return 0;
155155
}
156+
157+
TEST_CASE(make_meta_request_error_handling) {
158+
/* The original request without method and path. */
159+
(void)ctx;
160+
struct aws_http_message *message = aws_http_message_new_request(allocator);
161+
ASSERT_SUCCESS(aws_http_message_set_request_method(message, aws_http_method_get));
162+
ASSERT_SUCCESS(aws_http_message_set_request_path(message, aws_byte_cursor_from_c_str("/")));
163+
struct aws_s3_tester tester;
164+
AWS_ZERO_STRUCT(tester);
165+
ASSERT_SUCCESS(aws_s3_tester_init(allocator, &tester));
166+
struct aws_s3_client *client = NULL;
167+
struct aws_s3_tester_client_options client_options = {
168+
.part_size = 5 * 1024 * 1024,
169+
};
170+
171+
ASSERT_SUCCESS(aws_s3_tester_client_new(&tester, &client_options, &client));
172+
173+
/* 1. Bad options type */
174+
struct aws_s3_meta_request_options options;
175+
AWS_ZERO_STRUCT(options);
176+
options.type = AWS_S3_META_REQUEST_TYPE_MAX;
177+
178+
struct aws_s3_meta_request *meta_request = aws_s3_client_make_meta_request(client, &options);
179+
ASSERT_NULL(meta_request);
180+
/* 2. No message */
181+
options.type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT;
182+
183+
meta_request = aws_s3_client_make_meta_request(client, &options);
184+
ASSERT_NULL(meta_request);
185+
186+
/* 3. No message header */
187+
options.type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT;
188+
options.message = message;
189+
190+
meta_request = aws_s3_client_make_meta_request(client, &options);
191+
ASSERT_NULL(meta_request);
192+
193+
/* 4. Bad host name */
194+
struct aws_http_header host_header = {
195+
.name = g_host_header_name,
196+
.value = aws_byte_cursor_from_c_str("invalid:/s3.us-east-1.amazonaws.com"),
197+
};
198+
ASSERT_SUCCESS(aws_http_message_add_header(message, host_header));
199+
200+
options.type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT;
201+
options.message = message;
202+
203+
meta_request = aws_s3_client_make_meta_request(client, &options);
204+
ASSERT_NULL(meta_request);
205+
206+
aws_http_message_release(message);
207+
aws_s3_client_release(client);
208+
aws_s3_tester_clean_up(&tester);
209+
210+
return 0;
211+
}

0 commit comments

Comments
 (0)