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 "s3_tester.h"
8 #include <aws/io/channel_bootstrap.h>
9 #include <aws/testing/aws_test_harness.h>
10
s_test_s3_endpoint_ref_zero_ref_callback(struct aws_s3_endpoint * endpoint)11 static bool s_test_s3_endpoint_ref_zero_ref_callback(struct aws_s3_endpoint *endpoint) {
12 struct aws_s3_tester *tester = endpoint->user_data;
13
14 if (aws_s3_tester_inc_counter1(tester) == 1) {
15 return false;
16 }
17
18 return true;
19 }
20
s_test_s3_endpoint_ref_shutdown(void * user_data)21 static void s_test_s3_endpoint_ref_shutdown(void *user_data) {
22 struct aws_s3_tester *tester = user_data;
23
24 aws_s3_tester_inc_counter1(tester);
25 }
26
AWS_TEST_CASE(test_s3_endpoint_ref,s_test_s3_endpoint_ref)27 AWS_TEST_CASE(test_s3_endpoint_ref, s_test_s3_endpoint_ref)
28 static int s_test_s3_endpoint_ref(struct aws_allocator *allocator, void *ctx) {
29 (void)ctx;
30
31 struct aws_s3_tester tester;
32 ASSERT_SUCCESS(aws_s3_tester_init(allocator, &tester));
33 aws_s3_tester_set_counter1_desired(&tester, 3);
34
35 struct aws_string *host_name =
36 aws_s3_tester_build_endpoint_string(allocator, &g_test_public_bucket_name, &g_test_s3_region);
37
38 struct aws_s3_endpoint_options endpoint_options = {
39 .host_name = host_name,
40 .ref_count_zero_callback = s_test_s3_endpoint_ref_zero_ref_callback,
41 .shutdown_callback = s_test_s3_endpoint_ref_shutdown,
42 .client_bootstrap = tester.client_bootstrap,
43 .tls_connection_options = NULL,
44 .dns_host_address_ttl_seconds = 1,
45 .user_data = &tester,
46 .max_connections = 4,
47 };
48
49 struct aws_s3_endpoint *endpoint = aws_s3_endpoint_new(allocator, &endpoint_options);
50
51 ASSERT_TRUE(endpoint->http_connection_manager != NULL);
52
53 /* During the first release, s_test_s3_endpoint_ref_zero_ref_callback will return false, which will mean it does not
54 * get cleaned up. */
55 aws_s3_endpoint_release(endpoint);
56 ASSERT_TRUE(aws_atomic_load_int(&endpoint->ref_count.ref_count) == 0);
57
58 /* Perform an acquire, bumping the ref count to 1. */
59 aws_s3_endpoint_acquire(endpoint);
60 ASSERT_TRUE(aws_atomic_load_int(&endpoint->ref_count.ref_count) == 1);
61
62 /* During the secnod release, s_test_s3_endpoint_ref_zero_ref_callback will return true, causing clean up to
63 * occur.*/
64 aws_s3_endpoint_release(endpoint);
65
66 /* Wait for shutdown callback to increment the counter, hitting 3. */
67 aws_s3_tester_wait_for_counters(&tester);
68
69 aws_string_destroy(host_name);
70 aws_s3_tester_clean_up(&tester);
71
72 return 0;
73 }
74
s_test_s3_endpoint_resurrect_endpoint_ref_count_zero(struct aws_s3_endpoint * endpoint)75 static bool s_test_s3_endpoint_resurrect_endpoint_ref_count_zero(struct aws_s3_endpoint *endpoint) {
76 struct aws_s3_client *client = endpoint->user_data;
77 struct aws_s3_tester *tester = client->shutdown_callback_user_data;
78
79 bool acquire_and_release_endpoint = false;
80
81 if (aws_s3_tester_inc_counter1(tester) == 1) {
82 acquire_and_release_endpoint = true;
83 aws_s3_endpoint_acquire(endpoint);
84 }
85
86 struct aws_s3_client_vtable *original_client_vtable =
87 aws_s3_tester_get_client_vtable_patch(tester, 0)->original_vtable;
88
89 bool result = original_client_vtable->endpoint_ref_count_zero(endpoint);
90
91 if (acquire_and_release_endpoint) {
92 aws_s3_endpoint_release(endpoint);
93 }
94
95 return result;
96 }
97
AWS_TEST_CASE(test_s3_endpoint_resurrect,s_test_s3_endpoint_resurrect)98 AWS_TEST_CASE(test_s3_endpoint_resurrect, s_test_s3_endpoint_resurrect)
99 static int s_test_s3_endpoint_resurrect(struct aws_allocator *allocator, void *ctx) {
100 (void)ctx;
101
102 struct aws_s3_tester tester;
103 ASSERT_SUCCESS(aws_s3_tester_init(allocator, &tester));
104
105 struct aws_s3_tester_client_options client_options;
106 AWS_ZERO_STRUCT(client_options);
107
108 struct aws_s3_client *client = NULL;
109 ASSERT_SUCCESS(aws_s3_tester_client_new(&tester, &client_options, &client));
110
111 struct aws_s3_client_vtable *patched_client_vtable = aws_s3_tester_patch_client_vtable(&tester, client, NULL);
112 patched_client_vtable->endpoint_ref_count_zero = s_test_s3_endpoint_resurrect_endpoint_ref_count_zero;
113
114 struct aws_s3_tester_meta_request_options options = {
115 .allocator = allocator,
116 .client = client,
117 .meta_request_type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT,
118 .validate_type = AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_SUCCESS,
119 .get_options =
120 {
121 .object_path = g_pre_existing_object_1MB,
122 },
123 };
124
125 ASSERT_SUCCESS(aws_s3_tester_send_meta_request_with_options(&tester, &options, NULL));
126
127 aws_s3_client_release(client);
128 aws_s3_tester_clean_up(&tester);
129
130 return 0;
131 }
132
AWS_TEST_CASE(test_s3_different_endpoints,s_test_s3_different_endpoints)133 AWS_TEST_CASE(test_s3_different_endpoints, s_test_s3_different_endpoints)
134 static int s_test_s3_different_endpoints(struct aws_allocator *allocator, void *ctx) {
135 (void)ctx;
136
137 struct aws_s3_tester tester;
138 ASSERT_SUCCESS(aws_s3_tester_init(allocator, &tester));
139
140 struct aws_s3_client *client = NULL;
141 struct aws_s3_tester_client_options client_options;
142 AWS_ZERO_STRUCT(client_options);
143
144 ASSERT_SUCCESS(aws_s3_tester_client_new(&tester, &client_options, &client));
145
146 {
147 struct aws_s3_meta_request_test_results meta_request_test_results;
148 AWS_ZERO_STRUCT(meta_request_test_results);
149
150 struct aws_s3_tester_meta_request_options options = {
151 .allocator = allocator,
152 .client = client,
153 .meta_request_type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT,
154 .validate_type = AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_SUCCESS,
155 .get_options =
156 {
157 .object_path = g_s3_path_get_object_test_1MB,
158 },
159 };
160
161 ASSERT_SUCCESS(aws_s3_tester_send_meta_request_with_options(&tester, &options, &meta_request_test_results));
162 aws_s3_meta_request_test_results_clean_up(&meta_request_test_results);
163 }
164
165 {
166 struct aws_s3_meta_request_test_results meta_request_test_results;
167 AWS_ZERO_STRUCT(meta_request_test_results);
168
169 struct aws_s3_tester_meta_request_options options = {
170 .allocator = allocator,
171 .client = client,
172 .meta_request_type = AWS_S3_META_REQUEST_TYPE_GET_OBJECT,
173 .validate_type = AWS_S3_TESTER_VALIDATE_TYPE_EXPECT_SUCCESS,
174 .bucket_name = &g_test_public_bucket_name,
175 .get_options =
176 {
177 .object_path = g_s3_path_get_object_test_1MB,
178 },
179 };
180
181 ASSERT_SUCCESS(aws_s3_tester_send_meta_request_with_options(&tester, &options, &meta_request_test_results));
182 aws_s3_meta_request_test_results_clean_up(&meta_request_test_results);
183 }
184
185 aws_s3_client_release(client);
186
187 aws_s3_tester_clean_up(&tester);
188
189 return 0;
190 }
191