#include #include #include #include #include "scufcont/DArray.h" #include "scufcont/scufcont.h" #define SCDARRAY_CHARP_ALLOC(arrptr) SCDArray_charp_alloc((arrptr), darray_charp_destroyer, darray_charp_copyer) SCDARRAY_HEADER(char *, charp); SCDARRAY_IMPL(char *, charp) void darray_charp_destroyer(char **elem) { if (elem != NULL && *elem != NULL) { free(*elem); *elem = NULL; } } void darray_charp_copyer(char **dst, char **src) { if (dst != NULL && src != NULL && *src != NULL) { *dst = (char *) malloc(sizeof(char) * (strlen(*src) + 1)); strncpy(*dst, *src, strlen(*src) + 1); } } void test_DArray_alloc(void **state) { (void) state; SCDArray_charp arr; assert_true(SCDARRAY_CHARP_ALLOC(&arr) == SCUFCONT_SUCCESS); assert_non_null(arr.data); assert_uint_equal(arr.len, 0u); assert_uint_equal(arr.capacity, 1u); SCDArray_charp_free(&arr); } void test_DArray_alloc_copy(void **state) { (void) state; srand(time(NULL)); SCDArray_charp arr; assert_true(SCDARRAY_CHARP_ALLOC(&arr) == SCUFCONT_SUCCESS); const size_t elems_n = rand() % 100; for (size_t i = 0; i < elems_n; i++) { const int n = rand(); char buf[100]; snprintf(buf, 100, "%d", n); char *bufptr = buf; assert_true(SCDArray_charp_push_back(&arr, &bufptr) == SCUFCONT_SUCCESS); } SCDArray_charp copied; assert_true(SCDArray_charp_alloc_copy(&copied, &arr) == SCUFCONT_SUCCESS); assert_non_null(copied.data); assert_uint_equal(copied.capacity, arr.capacity); assert_uint_equal(copied.len, arr.len); for (size_t i = 0; i < arr.len; i++) { char **orig_elem = SCDArray_charp_at(&arr, i); assert_non_null(orig_elem); assert_non_null(*orig_elem); char **copied_elem = SCDArray_charp_at(&copied, i); assert_non_null(copied_elem); assert_non_null(*copied_elem); assert_string_equal(*orig_elem, *copied_elem); } const size_t arr_data_len = arr.len; char **arr_data = (char **) malloc(sizeof(char *) * arr.len); assert_non_null(arr_data); for (size_t i = 0; i < arr.len; i++) { char **src = SCDArray_charp_at(&arr, i); assert_non_null(src); assert_non_null(*src); arr.elem_copy(arr_data + i, src); } SCDArray_charp_free(&arr); // Freeing the first array shouldn't affect the data in the copied array. assert_uint_equal(arr_data_len, copied.len); for (size_t i = 0; i < arr_data_len; i++) { assert_string_equal(arr_data[i], *SCDArray_charp_at(&copied, i)); } SCDArray_charp_free(&copied); for (size_t i = 0; i < arr_data_len; i++) { free(arr_data[i]); } free(arr_data); } void test_DArray_push_back(void **state) { (void) state; SCDArray_charp arr; SCDARRAY_CHARP_ALLOC(&arr); const char *str1_lit = "Hello"; const size_t str1_len = strlen(str1_lit); char *str1 = malloc(sizeof(char) * (str1_len + 1)); strncpy(str1, str1_lit, str1_len + 1); char *str2 = "World"; assert_true(SCDArray_charp_push_back(&arr, &(char *) { str1 }) == SCUFCONT_SUCCESS); assert_string_equal(*SCDArray_charp_at(&arr, 0), str1); assert_true(SCDArray_charp_push_back(&arr, &(char *) { str2 }) == SCUFCONT_SUCCESS); assert_string_equal(*SCDArray_charp_at(&arr, 0), str1); assert_string_equal(*SCDArray_charp_at(&arr, 1), str2); // Freeing the original memory should not affect the array element. free(str1); assert_string_equal(*SCDArray_charp_at(&arr, 0), str1_lit); SCDArray_charp_free(&arr); } void test_DArray_at(void **state) { (void) state; SCDArray_charp arr; SCDARRAY_CHARP_ALLOC(&arr); assert_true(SCDArray_charp_push_back(&arr, &(char *) { "Hello" }) == SCUFCONT_SUCCESS); assert_string_equal(*SCDArray_charp_at(&arr, 0), "Hello"); assert_true(SCDArray_charp_push_back(&arr, &(char *) { "World" }) == SCUFCONT_SUCCESS); assert_string_equal(*SCDArray_charp_at(&arr, 0), "Hello"); assert_string_equal(*SCDArray_charp_at(&arr, 1), "World"); SCDArray_charp_free(&arr); } void test_DArray_push_back_multiple(void **state) { (void) state; SCDArray_charp arr; SCDARRAY_CHARP_ALLOC(&arr); char *nums[] = { "1", "2", "3", "4", "5" }; const size_t nums_len = sizeof(nums) / sizeof(nums[0]); assert_true(SCDArray_charp_push_back_multiple(&arr, nums, nums_len) == SCUFCONT_SUCCESS); for (size_t i = 0; i < arr.len; i++) { assert_string_equal(*SCDArray_charp_at(&arr, i), nums[i]); } const size_t nums2_len = 3; char **nums2 = (char **) malloc(sizeof(char *) * nums2_len); nums2[0] = "6"; nums2[1] = "7"; nums2[2] = "8"; assert_true(SCDArray_charp_push_back_multiple(&arr, nums2, nums2_len) == SCUFCONT_SUCCESS); for (size_t i = 0; i < nums_len; i++) { assert_string_equal(*SCDArray_charp_at(&arr, i), nums[i]); } for (size_t i = 0; i < nums2_len; i++) { assert_string_equal(*SCDArray_charp_at(&arr, i + nums_len), nums2[i]); } SCDArray_charp_free(&arr); // Freeing the array should not affect the original memory. assert_string_equal(nums2[0], "6"); assert_string_equal(nums2[1], "7"); assert_string_equal(nums2[2], "8"); free(nums2); } void test_DArray_remove(void **state) { (void) state; SCDArray_charp arr; SCDARRAY_CHARP_ALLOC(&arr); char *nums[5]; nums[0] = (char *) malloc(2); strncpy(nums[0], "1", 2); nums[1] = (char *) malloc(2); strncpy(nums[1], "2", 2); nums[2] = (char *) malloc(2); strncpy(nums[2], "3", 2); nums[3] = (char *) malloc(2); strncpy(nums[3], "4", 2); nums[4] = (char *) malloc(2); strncpy(nums[4], "5", 2); const size_t nums_len = 5; SCDArray_charp_push_back_multiple(&arr, nums, nums_len); for (size_t i = 0; i < arr.len; i++) { assert_string_equal(*SCDArray_charp_at(&arr, i), nums[i]); } // Remove last { const size_t old_len = arr.len; SCDArray_charp_remove(&arr, arr.len - 1); assert_uint_equal(arr.len, old_len - 1); char *new_nums[] = { "1", "2", "3", "4" }; assert_uint_equal(arr.len, sizeof(new_nums) / sizeof(new_nums[0])); for (size_t i = 0; i < arr.len; i++) { char **elem = SCDArray_charp_at(&arr, i); assert_string_equal(*elem, new_nums[i]); } assert_non_null(nums[nums_len - 1]); assert_string_equal(nums[nums_len - 1], "5"); } // Remove from middle { const size_t old_len = arr.len; SCDArray_charp_remove(&arr, 1); assert_uint_equal(arr.len, old_len - 1); char *new_nums[] = { "1", "3", "4" }; assert_uint_equal(arr.len, sizeof(new_nums) / sizeof(new_nums[0])); for (size_t i = 0; i < arr.len; i++) { assert_string_equal(*SCDArray_charp_at(&arr, i), new_nums[i]); } assert_non_null(nums[1]); assert_string_equal(nums[1], "2"); } // Remove first { const size_t old_len = arr.len; SCDArray_charp_remove(&arr, 0); assert_uint_equal(arr.len, old_len - 1); char *new_nums[] = { "3", "4" }; assert_uint_equal(arr.len, sizeof(new_nums) / sizeof(new_nums[0])); for (size_t i = 0; i < arr.len; i++) { assert_string_equal(*SCDArray_charp_at(&arr, i), new_nums[i]); } assert_non_null(nums[0]); assert_string_equal(nums[0], "1"); } SCDArray_charp_free(&arr); for (size_t i = 0; i < nums_len; i++) { free(nums[i]); } } void test_DArray_clear(void **state) { (void) state; SCDArray_charp arr; SCDARRAY_CHARP_ALLOC(&arr); char *words[] = { "Hello", "World", "!", "Foo", "bar" }; const size_t words_len = sizeof(words) / sizeof(words[0]); for (size_t i = 0; i < words_len; i++) { SCDArray_charp_push_back(&arr, words + i); } assert_uint_equal(arr.len, words_len); for (size_t i = 0; i < words_len; i++) { char **w = SCDArray_charp_at(&arr, i); assert_string_equal(*w, words[i]); } SCDArray_charp_clear(&arr); assert_uint_equal(arr.len, 0); } int DArray_tests_run(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_DArray_alloc), cmocka_unit_test(test_DArray_alloc_copy), cmocka_unit_test(test_DArray_push_back), cmocka_unit_test(test_DArray_at), cmocka_unit_test(test_DArray_push_back_multiple), cmocka_unit_test(test_DArray_remove), cmocka_unit_test(test_DArray_clear) }; return cmocka_run_group_tests_name("DArray", tests, NULL, NULL); }