Skip to content

Commit 642c68b

Browse files
committed
Updating signature to include versioning and versions, and added test
1 parent 2383bfd commit 642c68b

File tree

8 files changed

+212
-18
lines changed

8 files changed

+212
-18
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ project(libds3)
33

44
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/modules/")
55

6-
set (DS3SDK_VERSION_MAJOR 4)
7-
set (DS3SDK_VERSION_MINOR 1)
6+
set (DS3SDK_VERSION_MAJOR 5)
7+
set (DS3SDK_VERSION_MINOR 0)
88
set (DS3SDK_VERSION_PATCH 0)
99

1010
add_subdirectory(src)

src/ds3.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,16 @@ static void get_file_size_posix(const char* file_path, uint64_t* file_size) {
295295
}
296296
}
297297

298+
uint64_t get_file_size(const char* file_path) {
299+
uint64_t size = 0;
300+
#ifdef _WIN32
301+
get_file_size_windows(file_path, &size);
302+
#else
303+
get_file_size_posix(file_path, &size);
304+
#endif
305+
return size;
306+
}
307+
298308
static ds3_bulk_object_response* _ds3_bulk_object_from_file(const char* file_name, const char* base_path) {
299309
struct stat file_info;
300310
int result;

src/ds3.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5075,6 +5075,11 @@ LIBRARY_API ds3_bulk_object_list_response* ds3_init_bulk_object_list();
50755075
*/
50765076
LIBRARY_API ds3_bulk_object_list_response* ds3_init_bulk_object_list_with_size(size_t num_objects);
50775077

5078+
/**
5079+
* Retrieves the size of the specified file. If the file does not exist, 0 is returned.
5080+
*/
5081+
LIBRARY_API uint64_t get_file_size(const char* file_path);
5082+
50785083
#ifdef __cplusplus
50795084
}
50805085
#endif

src/ds3_net.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,48 @@ static char* _canonicalize_amz_headers(GHashTable* headers) {
287287
}
288288

289289
static char* _canonicalized_resource(ds3_str* path, GHashTable* query_params) {
290+
gchar* versioning_query = NULL;
291+
292+
gchar* path_copy = g_strdup(path->value);
293+
gchar* canonicalized_query;
294+
gchar** query_strings;
295+
GPtrArray* array = g_ptr_array_new();
296+
297+
// Canonicalize required query parameters in alpha numberic order
290298
if (g_hash_table_contains(query_params, "delete")) {
291-
return g_strconcat(path->value, "?delete", NULL);
292-
} else {
293-
return g_strdup(path->value);
299+
g_ptr_array_add(array, "delete");
300+
}
301+
302+
if (g_hash_table_contains(query_params, "versioning")) {
303+
gchar* version_level = g_hash_table_lookup(query_params, "versioning");
304+
versioning_query = g_strdup_printf("versioning=%s", version_level);
305+
g_ptr_array_add(array, versioning_query);
306+
}
307+
308+
if (g_hash_table_contains(query_params, "versions")) {
309+
g_ptr_array_add(array, "versions");
310+
}
311+
312+
// Finish the array with a terminating NULL
313+
g_ptr_array_add(array, NULL);
314+
query_strings = (gchar**)g_ptr_array_free(array, FALSE);
315+
316+
canonicalized_query = g_strjoinv("&", query_strings);
317+
318+
// Free individual dynamically allocated query strings
319+
if (versioning_query != NULL) {
320+
g_free(versioning_query);
321+
}
322+
g_free(query_strings);
323+
324+
if (strlen(canonicalized_query) > 0) {
325+
gchar* canonicalized_path = g_strjoin("?", path_copy, canonicalized_query, NULL);
326+
g_free(canonicalized_query);
327+
g_free(path_copy);
328+
return canonicalized_path;
294329
}
330+
g_free(canonicalized_query);
331+
return path_copy;
295332
}
296333

297334
static size_t _process_header_line(void* buffer, size_t size, size_t nmemb, void* user_data) {

test/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,17 @@ add_executable(ds3_c_tests
6868
bulk_get.cpp
6969
bulk_put.cpp
7070
checksum.cpp
71+
connection_tests.cpp
7172
deletes_test.cpp
73+
get_object.cpp
7274
get_physical_placement.cpp
7375
job_tests.cpp
7476
metadata_tests.cpp
7577
multimap_tests.cpp
7678
negative_tests.cpp
79+
put_directory.cpp
7780
search_tests.cpp
7881
service_tests.cpp
79-
connection_tests.cpp
80-
put_directory.cpp
8182
test.cpp)
8283

8384
add_test(regression_tests ds3_c_tests)

test/get_object.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,155 @@ BOOST_AUTO_TEST_CASE( get_object ) {
8282
free_client(client);
8383
}
8484

85+
void put_test_file(ds3_client* client, const char* file_name, const char* object_name, const char* bucket_name) {
86+
ds3_request* request = NULL;
87+
ds3_error* error = NULL;
88+
FILE* file = fopen(file_name, "r");
89+
90+
// Get file size
91+
uint64_t size = get_file_size(file_name);
92+
93+
// Perform naked put object
94+
request = ds3_init_put_object_request(bucket_name, object_name, size);
95+
error = ds3_put_object_request(client, request, file, ds3_read_from_file);
96+
ds3_request_free(request);
97+
fclose(file);
98+
handle_error(error);
99+
}
100+
101+
size_t test_write_buff_counter(void* buffer, size_t size, size_t nmemb, void* user_byte_count) {
102+
int cur_byte_count = size * nmemb;
103+
104+
int* total_byte_count = (int*)user_byte_count;
105+
*total_byte_count += cur_byte_count;
106+
return cur_byte_count;
107+
}
108+
109+
BOOST_AUTO_TEST_CASE( get_objects_with_versioning ) {
110+
printf("-----Testing GET object with versioning-------\n");
111+
const char* dp_name = "c_test_dp_with_versioning";
112+
const char* bucket_name = "test_get_object_bucket";
113+
const char* file_name1 = "resources/sherlock_holmes.txt";
114+
const char* file_name2 = "resources/beowulf.txt";
115+
const char* object_name = "sherlock_holmes_versioned.txt";
116+
ds3_request* request = NULL;
117+
ds3_error* error = NULL;
118+
ds3_data_policy_response* put_dp_response = NULL;
119+
ds3_list_bucket_result_response* get_bucket_response = NULL;
120+
ds3_bulk_object_list_response* bulk_objects_response = NULL;
121+
ds3_master_object_list_response* bulk_get_response = NULL;
122+
123+
ds3_client* client = get_client();
124+
125+
// Create data policy with versioning turned on
126+
request = ds3_init_put_data_policy_spectra_s3_request(dp_name);
127+
ds3_request_set_versioning_ds3_versioning_level(request, DS3_VERSIONING_LEVEL_KEEP_MULTIPLE_VERSIONS);
128+
error = ds3_put_data_policy_spectra_s3_request(client, request, &put_dp_response);
129+
handle_error(error);
130+
131+
BOOST_CHECK(put_dp_response != NULL);
132+
ds3_str* data_policy_id = ds3_str_init(put_dp_response->id->value);
133+
134+
ds3_request_free(request);
135+
ds3_data_policy_response_free(put_dp_response);
136+
137+
// Create data persistence rule
138+
ds3_data_persistence_rule_response* put_data_persistence_rule_response = NULL;
139+
request = ds3_init_put_data_persistence_rule_spectra_s3_request(
140+
data_policy_id->value,
141+
DS3_DATA_ISOLATION_LEVEL_STANDARD,
142+
TEST_SD_NAME,
143+
DS3_DATA_PERSISTENCE_RULE_TYPE_PERMANENT);
144+
error = ds3_put_data_persistence_rule_spectra_s3_request(client, request, &put_data_persistence_rule_response);
145+
handle_error(error);
146+
ds3_str* data_persistence_rule_id = ds3_str_init(put_data_persistence_rule_response->id->value);
147+
148+
ds3_request_free(request);
149+
ds3_data_persistence_rule_response_free(put_data_persistence_rule_response);
150+
151+
// Create bucket with data policy
152+
error = create_bucket_with_data_policy(client, bucket_name, data_policy_id->value);
153+
handle_error(error);
154+
155+
// Put object twice
156+
put_test_file(client, file_name1, object_name, bucket_name);
157+
put_test_file(client, file_name2, object_name, bucket_name);
158+
159+
// Get version of an object TODO
160+
request = ds3_init_get_bucket_request(bucket_name);
161+
ds3_request_set_versions(request, True);
162+
error = ds3_get_bucket_request(client, request, &get_bucket_response);
163+
handle_error(error);
164+
165+
BOOST_CHECK_EQUAL(get_bucket_response->num_objects, 0);
166+
BOOST_CHECK_EQUAL(get_bucket_response->num_versioned_objects, 2);
167+
168+
ds3_request_free(request);
169+
170+
171+
// Perform bulk get with both versioned objects
172+
//TODO start
173+
bulk_objects_response = ds3_convert_object_list((const ds3_contents_response**)get_bucket_response->versioned_objects, get_bucket_response->num_versioned_objects);
174+
ds3_list_bucket_result_response_free(get_bucket_response);
175+
176+
request = ds3_init_get_bulk_job_spectra_s3_request(bucket_name, bulk_objects_response);
177+
178+
error = ds3_get_bulk_job_spectra_s3_request(client, request, &bulk_get_response);
179+
ds3_request_free(request);
180+
ds3_bulk_object_list_response_free(bulk_objects_response);
181+
handle_error(error);
182+
183+
/* TODO uncomment once related bug is fixed
184+
ds3_master_object_list_response* chunk_response = NULL;
185+
chunk_response = ensure_available_chunks(client, bulk_get_response->job_id);
186+
187+
188+
for (uint64_t chunk_index = 0; chunk_index < chunk_response->num_objects; chunk_index++) {
189+
ds3_objects_response* chunk_object_list = chunk_response->objects[chunk_index];
190+
for (uint64_t chunk_object_index = 0; chunk_object_index < chunk_object_list->num_objects; chunk_object_index++) {
191+
ds3_bulk_object_response* current_obj = chunk_object_list->objects[chunk_object_index];
192+
193+
const uint64_t length = current_obj->length;
194+
const uint64_t offset = current_obj->offset;
195+
196+
request = ds3_init_get_object_request(chunk_response->bucket_name->value, current_obj->name->value, length);
197+
ds3_request_set_job(request, chunk_response->job_id->value);
198+
ds3_request_set_offset(request, offset);
199+
ds3_request_set_version_id(request, current_obj->id->value);
200+
201+
int byte_count = 0;
202+
error = ds3_get_object_request(client, request, &byte_count, test_write_buff_counter);
203+
ds3_request_free(request);
204+
handle_error(error);
205+
206+
BOOST_CHECK(byte_count > 0); //todo update to check for expected length for this version
207+
}
208+
}
209+
210+
ds3_master_object_list_response_free(chunk_response);
211+
*/
212+
ds3_master_object_list_response_free(bulk_get_response);
213+
214+
// Delete bucket with force i.e. with objects
215+
request = ds3_init_delete_bucket_spectra_s3_request(bucket_name);
216+
ds3_request_set_force(request, True);
217+
error = ds3_delete_bucket_spectra_s3_request(client, request);
218+
handle_error(error);
219+
ds3_request_free(request);
220+
221+
// Delete data persistence rule
222+
ds3_request* delete_data_persistence_rule_request = ds3_init_delete_data_persistence_rule_spectra_s3_request(data_persistence_rule_id->value);
223+
error = ds3_delete_data_persistence_rule_spectra_s3_request(client, delete_data_persistence_rule_request);
224+
handle_error(error);
225+
ds3_request_free(delete_data_persistence_rule_request);
226+
ds3_str_free(data_persistence_rule_id);
227+
228+
// Delete DataPolicy
229+
ds3_request* delete_data_policy_request = ds3_init_delete_data_policy_spectra_s3_request(dp_name);
230+
error = ds3_delete_data_policy_spectra_s3_request(client, delete_data_policy_request);
231+
handle_error(error);
232+
ds3_request_free(delete_data_policy_request);
233+
ds3_str_free(data_policy_id);
234+
235+
free_client(client);
236+
}

test/negative_tests.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ BOOST_AUTO_TEST_CASE(put_duplicate_bucket) {
5555
error = create_bucket_with_data_policy(client, bucket_name, ids.data_policy_id->value);
5656
BOOST_CHECK(error!=NULL);
5757
BOOST_CHECK(error->error->http_error_code == 409);
58-
BOOST_CHECK(strcmp(error->error->code->value ,"Conflict")==0);
5958
ds3_error_free(error);
6059

6160
//Deleting Created Bucket
@@ -81,7 +80,6 @@ BOOST_AUTO_TEST_CASE(delete_non_existing_bucket){
8180

8281
BOOST_CHECK(error != NULL);
8382
BOOST_CHECK(error->error->http_error_code == 404);
84-
BOOST_CHECK(strcmp(error->error->code->value ,"Not Found")==0);
8583
ds3_error_free(error);
8684
free_client(client);
8785
}
@@ -100,7 +98,6 @@ BOOST_AUTO_TEST_CASE(get_bucket_with_empty_bucket_name){
10098
ds3_list_bucket_result_response_free(response);
10199
free_client(client);
102100

103-
//printf("error->error->code[%s]\n", error->error->code->value);
104101
BOOST_REQUIRE(error != NULL);
105102
BOOST_CHECK(g_str_has_prefix(error->message->value, "The bucket name parameter is required") == (gboolean)TRUE);
106103
BOOST_CHECK(error->code == DS3_ERROR_MISSING_ARGS);
@@ -185,7 +182,6 @@ BOOST_AUTO_TEST_CASE(head_bucket_non_existing_bucket){
185182

186183
BOOST_CHECK(error != NULL);
187184
BOOST_CHECK(error->error->http_error_code == 404);
188-
BOOST_CHECK(strcmp(error->error->code->value ,"Not Found")==0);
189185
ds3_error_free(error);
190186
free_client(client);
191187
}
@@ -231,7 +227,6 @@ BOOST_AUTO_TEST_CASE(delete_non_existing_object) {
231227

232228
BOOST_REQUIRE(error != NULL);
233229
BOOST_CHECK(error->error->http_error_code == 404);
234-
BOOST_CHECK(strcmp(error->error->code->value ,"Not Found") == 0);
235230
ds3_error_free(error);
236231
}
237232

@@ -245,7 +240,6 @@ BOOST_AUTO_TEST_CASE(bad_bucket_name) {
245240

246241
BOOST_REQUIRE(error != NULL);
247242
BOOST_CHECK(error->error->http_error_code == 400);
248-
BOOST_CHECK(strcmp(error->error->code->value ,"Bad Request") == 0);
249243
ds3_error_free(error);
250244

251245
free_client(client);
@@ -261,7 +255,6 @@ BOOST_AUTO_TEST_CASE( put_bucket_bucket_name_with_trailing_slash){
261255
BOOST_CHECK(put_bucket_error != NULL);
262256
BOOST_CHECK(put_bucket_error->code == DS3_ERROR_BAD_STATUS_CODE);
263257
BOOST_CHECK(put_bucket_error->error->http_error_code == 400);
264-
BOOST_CHECK(strcmp(put_bucket_error->error->code->value, "Bad Request") == 0);
265258

266259
ds3_error_free(put_bucket_error);
267260
clear_bucket(client, bucket_name);
@@ -293,7 +286,6 @@ BOOST_AUTO_TEST_CASE(put_duplicate_object_list){
293286

294287
BOOST_REQUIRE(error != NULL);
295288
BOOST_CHECK(error->error->http_error_code == 400);
296-
BOOST_CHECK(strcmp(error->error->code->value ,"Bad Request") == 0);
297289
ds3_error_free(error);
298290
}
299291

@@ -344,7 +336,6 @@ BOOST_AUTO_TEST_CASE(delete_multiple_job) {
344336

345337
BOOST_REQUIRE(error != NULL);
346338
BOOST_CHECK(error->error->http_error_code == 404);
347-
BOOST_CHECK(strcmp(error->error->code->value ,"Not Found") == 0);
348339
ds3_error_free(error);
349340
}
350341

@@ -363,7 +354,6 @@ BOOST_AUTO_TEST_CASE(get_non_existing_job) {
363354

364355
BOOST_REQUIRE(error != NULL);
365356
BOOST_CHECK(error->error->http_error_code == 404);
366-
BOOST_CHECK(strcmp(error->error->code->value, "Not Found") == 0);
367357
ds3_error_free(error);
368358
}
369359

test/search_tests.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,6 @@ BOOST_AUTO_TEST_CASE( get_incorrect_bucket_name ) {
253253
ds3_error* error = ds3_get_objects_details_spectra_s3_request(client, request, &response);
254254
BOOST_CHECK(error!=NULL);
255255
BOOST_CHECK(error->error->http_error_code == 404);
256-
BOOST_CHECK(strcmp(error->error->code->value ,"Not Found") == 0);
257256

258257
ds3_request_free(request);
259258
ds3_error_free(error);

0 commit comments

Comments
 (0)