#include #include #include #include #include #include #include #if defined(__has_feature) #if __has_feature(address_sanitizer) const char* __asan_default_options(void) { return "allocator_may_return_null=1"; } #endif #endif /* ========================================================================= * 1. BASIC LIFECYCLE & NULL GUARDS * ========================================================================= */ static void test_push_back_single(void) { printf("[1] Testing push_back with a single character...\n"); _VecCharInternal vec = VEC_INIT; err_t err = ERR_T_INIT; _vec_char_push_back(&vec, 'A', &err); assert(err.flags == 0); assert(vec._internal_size == 1); assert(vec._internal_arr[0] == 'A'); _vec_char_delete(&vec, &err); printf("Passed\n"); } static void test_null_guards(void) { printf("[2] Testing null pointer checks in __null_check...\n"); _VecCharInternal vec = VEC_INIT; err_t err = ERR_T_INIT; size_t res1 = __null_check(&vec, nullptr); assert(res1 == ERR_ERR_T_NULL); size_t res2 = __null_check((const _VecCharInternal*)nullptr, &err); assert(res2 == ERR_VEC_NULL); assert((err.flags & ERR_VEC_NULL) != 0); err = (err_t)ERR_T_INIT; size_t res3 = __null_check(&vec, &err); assert(res3 == ERR_BUF_NULL); assert((err.flags & ERR_BUF_NULL) != 0); err = (err_t)ERR_T_INIT; size_t res4 = __null_check(vec._internal_arr, &err); assert(res4 == ERR_BUF_NULL); assert((err.flags & ERR_BUF_NULL) != 0); err = (err_t)ERR_T_INIT; size_t res5 = __null_check((const char*)nullptr, nullptr); assert(res5 == ERR_ERR_T_NULL); printf("Passed\n"); } static void test_origin_override(void) { printf("[3] Testing __origin_override...\n"); err_t err = ERR_T_INIT; size_t res_null_status = __origin_override(nullptr, "TEST"); assert(res_null_status == ERR_ERR_T_NULL); size_t res = __origin_override(&err, nullptr); assert(res == ERR_STR_NULL); assert((err.flags & ERR_STR_NULL) != 0); err = (err_t)ERR_T_INIT; __origin_override(&err, "INITIAL"); assert(strcmp(err.origin, "INITIAL") == 0); // Override existing origin -> ERR_ORIGIN_UNALTERABLE __origin_override(&err, "REPLACED"); assert((err.flags & ERR_ORIGIN_UNALTERABLE) != 0); assert(strcmp(err.origin, "INITIAL") == 0); printf("Passed\n"); } /* ========================================================================= * 2. PRINT & COPY * ========================================================================= */ static void test_print_vec(void) { _VecCharInternal vec = VEC_INIT; err_t err = ERR_T_INIT; printf("[4] Testing print_vec with null vector\n"); _vec_char_print_vec(nullptr, &err); assert((err.flags & ERR_VEC_NULL) != 0); printf("Passed\n"); printf("[5] Testing print_vec with null array\n"); err = (err_t)ERR_T_INIT; _vec_char_print_vec(&vec, &err); assert((err.flags & ERR_BUF_NULL) != 0); printf("Passed\n"); printf("[6] Testing print_vec with null err\n"); _vec_char_print_vec(&vec, nullptr); printf("Passed\n"); printf("[7] Testing print_vec with valid parameters\n"); err = (err_t)ERR_T_INIT; _vec_char_push_back(&vec, 'a', &err); _vec_char_push_back(&vec, 'b', &err); _vec_char_print_vec(&vec, &err); _vec_char_delete(&vec, &err); printf("Passed\n"); } static void test_cpy(void) { char arr[3] = { 'a', 'b', 'c' }; _VecCharInternal blank = VEC_INIT; printf("[8] Testing _vec_char_cpy with null source arr\n"); err_t err1 = ERR_T_INIT; _VecCharInternal tmp = _vec_char_cpy(nullptr, 3, &err1); assert(blank._internal_arr == tmp._internal_arr && blank._internal_capacity == tmp._internal_capacity && blank._internal_size == tmp._internal_size && blank._internal_max_size == tmp._internal_max_size); assert((err1.flags & ERR_BUF_NULL) != 0); printf("Passed\n"); printf("[9] Testing _vec_char_cpy with null err\n"); _VecCharInternal res2 = _vec_char_cpy(arr, 3, nullptr); assert(blank._internal_arr == res2._internal_arr && blank._internal_capacity == res2._internal_capacity && blank._internal_size == res2._internal_size && blank._internal_max_size == res2._internal_max_size); printf("Passed\n"); printf("[10] Testing _vec_char_cpy with size 0\n"); err_t err3 = ERR_T_INIT; _VecCharInternal res3 = _vec_char_cpy(arr, 0, &err3); assert(blank._internal_arr == res3._internal_arr && blank._internal_capacity == res3._internal_capacity && blank._internal_size == res3._internal_size && blank._internal_max_size == res3._internal_max_size); assert((err3.flags & ERR_SIZE_ZERO) != 0); printf("Passed\n"); printf("[11] Testing _vec_char_cpy with size exceeding max_size\n"); err_t err4 = ERR_T_INIT; _VecCharInternal res4 = _vec_char_cpy(arr, res3._internal_max_size + 1, &err4); assert(blank._internal_arr == res4._internal_arr && blank._internal_capacity == res4._internal_capacity && blank._internal_size == res4._internal_size && blank._internal_max_size == res4._internal_max_size); assert((err4.flags & ERR_SIZE_OVERFLOW) != 0); printf("Passed\n"); printf("[12] Testing _vec_char_cpy allocation failure\n"); err_t err5 = ERR_T_INIT; size_t huge_size = ((size_t)1 << 40); _VecCharInternal res5 = _vec_char_cpy(arr, huge_size, &err5); assert((err5.flags & ERR_ALLOC_FAIL) != 0); printf("Passed\n"); printf("[13] Testing _vec_char_cpy with valid inputs\n"); err_t err = ERR_T_INIT; char res[4] = { 'a', 'b', 'c', 'd' }; _VecCharInternal vec = _vec_char_cpy(res, 4, &err); assert(err.flags == 0); assert(vec._internal_size == 4); assert(vec._internal_capacity == 4); assert(memcmp(vec._internal_arr, res, 4) == 0); _vec_char_delete(&vec, &err); printf("Passed\n"); } /* ========================================================================= * 3. PUSH, POP, CAPACITY & SIZING * ========================================================================= */ static void test_push_back(void) { printf("[14] Testing _vec_char_push_back null vec\n"); err_t err = ERR_T_INIT; _vec_char_push_back(nullptr, 'a', &err); assert((err.flags & ERR_VEC_NULL) != 0); printf("Passed\n"); printf("[15] Testing _vec_char_push_back null err\n"); _VecCharInternal vec1 = VEC_INIT; _vec_char_push_back(&vec1, 'a', nullptr); assert(vec1._internal_size == 1); _vec_char_delete(&vec1, &err); printf("Passed\n"); printf("[16] Testing _vec_char_push_back size overflow\n"); _VecCharInternal vec2 = VEC_INIT; err_t err2 = ERR_T_INIT; vec2._internal_size = vec2._internal_max_size; _vec_char_push_back(&vec2, 'a', &err2); assert((err2.flags & ERR_SIZE_OVERFLOW) != 0); printf("Passed\n"); printf("[17] Testing push_back capacity growth realloc\n"); err_t err3 = ERR_T_INIT; _VecCharInternal vec3 = VEC_INIT; for (char c = '0'; c <= '9'; c++) { _vec_char_push_back(&vec3, c, &err3); assert(err3.flags == 0); } assert(vec3._internal_size == 10); assert(vec3._internal_capacity >= 10); _vec_char_delete(&vec3, &err3); printf("Passed\n"); } static void test_pop_back(void) { _VecCharInternal vec = VEC_INIT; err_t err = ERR_T_INIT; printf("[18] Testing _vec_char_pop_back null vector\n"); _vec_char_pop_back(nullptr, &err); assert((err.flags & ERR_VEC_NULL) != 0); printf("Passed\n"); printf("[19] Testing _vec_char_pop_back size 0\n"); err = (err_t)ERR_T_INIT; _vec_char_push_back(&vec, 'x', &err); _vec_char_pop_back(&vec, &err); // size is now 0, but buffer is allocated err = (err_t)ERR_T_INIT; _vec_char_pop_back(&vec, &err); assert((err.flags & ERR_SIZE_ZERO) != 0); printf("Passed\n"); printf("[20] Testing _vec_char_pop_back valid pop\n"); err = (err_t)ERR_T_INIT; _vec_char_push_back(&vec, 'a', &err); _vec_char_push_back(&vec, 'b', &err); assert(vec._internal_size == 2); _vec_char_pop_back(&vec, &err); assert(vec._internal_size == 1); assert(vec._internal_arr[0] == 'a'); assert(vec._internal_arr[1] == 0); _vec_char_delete(&vec, &err); printf("Passed\n"); } static void test_reserve(void) { _VecCharInternal vec = VEC_INIT; err_t err = ERR_T_INIT; printf("[21] Testing _vec_char_reserve null vector\n"); _vec_char_reserve(nullptr, 1, &err); assert((err.flags & ERR_VEC_NULL) != 0); printf("Passed\n"); printf("[22] Testing _vec_char_reserve capacity 0\n"); err = (err_t)ERR_T_INIT; _vec_char_reserve(&vec, 0, &err); assert((err.flags & ERR_SIZE_ZERO) != 0); printf("Passed\n"); printf("[23] Testing _vec_char_reserve calloc on unallocated buffer\n"); err = (err_t)ERR_T_INIT; _vec_char_reserve(&vec, 32, &err); assert(err.flags == 0); assert(vec._internal_capacity == 32); assert(vec._internal_arr != nullptr); printf("Passed\n"); printf("[24] Testing _vec_char_reserve realloc to larger capacity\n"); _vec_char_reserve(&vec, 64, &err); assert(err.flags == 0); assert(vec._internal_capacity == 64); printf("Passed\n"); printf("[25] Testing _vec_char_reserve truncating size\n"); vec._internal_size = 50; _vec_char_reserve(&vec, 20, &err); assert(vec._internal_size == 20); assert(vec._internal_capacity == 20); _vec_char_delete(&vec, &err); printf("Passed\n"); } static void test_shrink_to_fit(void) { _VecCharInternal vec = VEC_INIT; err_t err = ERR_T_INIT; printf("[26] Testing _vec_char_shrink_to_fit null vector\n"); _vec_char_shrink_to_fit(nullptr, &err); assert((err.flags & ERR_VEC_NULL) != 0); printf("Passed\n"); printf( "[27] Testing _vec_char_shrink_to_fit size 0 with allocated " "buffer\n"); err = (err_t)ERR_T_INIT; _vec_char_push_back(&vec, 'a', &err); _vec_char_pop_back(&vec, &err); err = (err_t)ERR_T_INIT; _vec_char_shrink_to_fit(&vec, &err); assert((err.flags & ERR_SIZE_ZERO) != 0); printf("Passed\n"); printf("[28] Testing _vec_char_shrink_to_fit normal shrinkage\n"); _vec_char_reserve(&vec, 128, &err); for (char c = '0'; c < '5'; c++) { _vec_char_push_back(&vec, c, &err); } assert(vec._internal_capacity == 128); assert(vec._internal_size == 5); err = (err_t)ERR_T_INIT; _vec_char_shrink_to_fit(&vec, &err); assert(err.flags == 0); assert(vec._internal_capacity == 5); assert(vec._internal_size == 5); _vec_char_delete(&vec, &err); printf("Passed\n"); } /* ========================================================================= * 4. GETTERS, ELEMENT ACCESS & CLEAR * ========================================================================= */ static void test_getters_and_access(void) { printf("[29] Testing getters, clear, and boundary element access...\n"); _VecCharInternal vec = VEC_INIT; err_t err = ERR_T_INIT; // 1. Null pointer check assert(_vec_char_data(nullptr, &err) == nullptr); assert((err.flags & ERR_VEC_NULL) != 0); err = (err_t)ERR_T_INIT; assert(_vec_char_size(nullptr, &err) == 0); assert((err.flags & ERR_VEC_NULL) != 0); err = (err_t)ERR_T_INIT; assert(_vec_char_capacity(nullptr, &err) == 0); assert((err.flags & ERR_VEC_NULL) != 0); err = (err_t)ERR_T_INIT; assert(_vec_char_max_size(nullptr, &err) == 0); assert((err.flags & ERR_VEC_NULL) != 0); // 2. Unallocated buffer check for empty() err = (err_t)ERR_T_INIT; size_t unalloc_empty = _vec_char_empty(&vec, &err); assert((err.flags & ERR_BUF_NULL) != 0); assert(unalloc_empty != 0); // 3. Allocate the buffer and pop so size is 0 with valid arr err = (err_t)ERR_T_INIT; _vec_char_push_back(&vec, 'x', &err); _vec_char_pop_back(&vec, &err); err = (err_t)ERR_T_INIT; // Now _internal_arr is non-null and size is 0: assert(_vec_char_empty(&vec, &err) == 0); // Boundary element access on size 0 err = (err_t)ERR_T_INIT; assert(_vec_char_front(&vec, &err) == 0 || (err.flags & ERR_OUT_OF_BOUNDS) != 0); err = (err_t)ERR_T_INIT; assert(_vec_char_back(&vec, &err) == 0 || (err.flags & ERR_OUT_OF_BOUNDS) != 0); // 4. Populate container err = (err_t)ERR_T_INIT; _vec_char_push_back(&vec, 'x', &err); _vec_char_push_back(&vec, 'y', &err); _vec_char_push_back(&vec, 'z', &err); assert(_vec_char_size(&vec, &err) == 3); assert(_vec_char_capacity(&vec, &err) >= 3); assert(_vec_char_data(&vec, &err) == vec._internal_arr); assert(_vec_char_front(&vec, &err) == 'x'); assert(_vec_char_back(&vec, &err) == 'z'); assert(_vec_char_begin(&vec, &err) == 0); assert(_vec_char_end(&vec, &err) == 2); // Out of bounds at() err = (err_t)ERR_T_INIT; assert(_vec_char_at(&vec, 10, &err) == nullptr); assert((err.flags & ERR_OUT_OF_BOUNDS) != 0); // Clear container err = (err_t)ERR_T_INIT; _vec_char_clear(&vec, &err); assert(vec._internal_size == 0); assert(vec._internal_arr[0] == 0); _vec_char_delete(&vec, &err); assert(vec._internal_arr == nullptr); assert(vec._internal_size == 0); assert(vec._internal_capacity == 0); printf("Passed\n"); } /* ========================================================================= * 5. SWAP, ERASE, RESIZE, ASSIGN & INSERT * ========================================================================= */ static void test_swap(void) { printf("[30] Testing _vec_char_swap...\n"); _VecCharInternal a = VEC_INIT; _VecCharInternal b = VEC_INIT; err_t err = ERR_T_INIT; // Null vector checks _vec_char_swap(nullptr, &b, &err); assert((err.flags & ERR_VEC_NULL) != 0); err = (err_t)ERR_T_INIT; _vec_char_swap(&a, nullptr, &err); assert((err.flags & ERR_VEC_NULL) != 0); // Normal swap err = (err_t)ERR_T_INIT; _vec_char_push_back(&a, 'A', &err); _vec_char_push_back(&b, 'B', &err); _vec_char_push_back(&b, 'C', &err); _vec_char_swap(&a, &b, &err); assert(a._internal_size == 2); assert(a._internal_arr[0] == 'B'); assert(b._internal_size == 1); assert(b._internal_arr[0] == 'A'); _vec_char_delete(&a, &err); _vec_char_delete(&b, &err); printf("Passed\n"); } static void test_erase_variants(void) { printf("[31] Testing _vec_char_erase single & range overloads...\n"); _VecCharInternal vec = VEC_INIT; err_t err = ERR_T_INIT; for (char c = '0'; c <= '5'; c++) { _vec_char_push_back(&vec, c, &err); } // "012345" // Single element erase out of bounds (noop) _vec_char_erase(&vec, 10, &err); assert(vec._internal_size == 6); // Erase index 2 ('2') -> "01345" _vec_char_erase(&vec, 2, &err); assert(vec._internal_size == 5); assert(vec._internal_arr[2] == '3'); // Range erase invalid bounds err = (err_t)ERR_T_INIT; _vec_char_erase(&vec, 4, 2, &err); // iter_end <= iter_start assert((err.flags & ERR_OUT_OF_BOUNDS) != 0); err = (err_t)ERR_T_INIT; _vec_char_erase(&vec, 0, 10, &err); // iter_end > size assert((err.flags & ERR_OUT_OF_BOUNDS) != 0); // Range erase middle: index 1 through 3 ("0[13]45" -> "045") err = (err_t)ERR_T_INIT; _vec_char_erase(&vec, 1, 3, &err); assert(vec._internal_size == 3); assert(vec._internal_arr[0] == '0'); assert(vec._internal_arr[1] == '4'); assert(vec._internal_arr[2] == '5'); _vec_char_delete(&vec, &err); printf("Passed\n"); } static void test_resize(void) { printf("[32] Testing _vec_char_resize (zero-fill & value-fill)...\n"); _VecCharInternal vec = VEC_INIT; err_t err = ERR_T_INIT; // Null vector _vec_char_resize((_VecCharInternal*)nullptr, 10, &err); assert((err.flags & ERR_VEC_NULL) != 0); // Resize unallocated buffer to size 5 err = (err_t)ERR_T_INIT; _vec_char_resize(&vec, 5, &err); assert(err.flags == 0); assert(vec._internal_size == 5); assert(vec._internal_arr[0] == 0); // Same size requested err = (err_t)ERR_T_INIT; _vec_char_resize(&vec, 5, &err); assert((err.flags & ERR_OUT_OF_BOUNDS) != 0); // Exceeds max size err = (err_t)ERR_T_INIT; _vec_char_resize(&vec, vec._internal_max_size + 1, &err); assert((err.flags & ERR_SIZE_OVERFLOW) != 0); // Grow with value fill err = (err_t)ERR_T_INIT; _vec_char_resize(&vec, 8, 'Z', &err); assert(vec._internal_size == 8); assert(vec._internal_arr[5] == 'Z'); assert(vec._internal_arr[7] == 'Z'); // Shrink with value fill err = (err_t)ERR_T_INIT; _vec_char_resize(&vec, 3, 'A', &err); assert(vec._internal_size == 3); _vec_char_delete(&vec, &err); printf("Passed\n"); } static void test_assign(void) { printf("[33] Testing _vec_char_assign overloads...\n"); _VecCharInternal dst = VEC_INIT; _VecCharInternal src = VEC_INIT; err_t err = ERR_T_INIT; // Populate src: 'A', 'B', 'C', 'D', 'E' for (char c = 'A'; c <= 'E'; c++) { _vec_char_push_back(&src, c, &err); } // Allocate dst buffer first so it is not unallocated _vec_char_push_back(&dst, 'z', &err); err = (err_t)ERR_T_INIT; // 1. Fill assign: 4 'X's _vec_char_assign(&dst, 4, 'X', &err); assert(err.flags == 0); assert(dst._internal_size == 4); assert(dst._internal_arr[0] == 'X'); assert(dst._internal_arr[3] == 'X'); // 2. Fill assign with 0 amount err = (err_t)ERR_T_INIT; _vec_char_assign(&dst, 0, 'Y', &err); assert((err.flags & ERR_SIZE_ZERO) != 0); // 3. Range assign self-buffer check err = (err_t)ERR_T_INIT; _vec_char_assign(&dst, &dst, 0, 2, &err); assert((err.flags & ERR_DOUBLE_BUF) != 0); // 4. Range assign invalid sub-range (start >= end) err = (err_t)ERR_T_INIT; _vec_char_assign(&dst, &src, 3, 2, &err); assert((err.flags & ERR_OUT_OF_BOUNDS) != 0); // 5. Range assign out of bounds end err = (err_t)ERR_T_INIT; _vec_char_assign(&dst, &src, 0, 10, &err); assert((err.flags & ERR_OUT_OF_BOUNDS) != 0); _vec_char_delete(&dst, &err); _vec_char_delete(&src, &err); printf("Passed\n"); } static void test_insert(void) { printf("[34] Testing _vec_char_insert overloads...\n"); _VecCharInternal vec = VEC_INIT; _VecCharInternal other = VEC_INIT; err_t err = ERR_T_INIT; // Single insert on unallocated buffer _vec_char_insert(&vec, 0, 'M', &err); assert(vec._internal_size == 1); assert(vec._internal_arr[0] == 'M'); // Single insert out of bounds err = (err_t)ERR_T_INIT; _vec_char_insert(&vec, 5, 'O', &err); assert((err.flags & ERR_OUT_OF_BOUNDS) != 0); // Single insert at middle: index 0 ('A', then 'M' shifts to 1) err = (err_t)ERR_T_INIT; _vec_char_insert(&vec, 0, 'A', &err); assert(vec._internal_size == 2); assert(vec._internal_arr[0] == 'A'); assert(vec._internal_arr[1] == 'M'); // Repeated insert: insert 3 'B's at index 1 -> 'A', 'B', 'B', 'B', 'M' _vec_char_insert(&vec, 1, 3, 'B', &err); assert(vec._internal_size == 5); assert(vec._internal_arr[1] == 'B'); assert(vec._internal_arr[3] == 'B'); assert(vec._internal_arr[4] == 'M'); // Repeated insert amount 0 err = (err_t)ERR_T_INIT; _vec_char_insert(&vec, 0, 0, 'Z', &err); assert((err.flags & ERR_SIZE_ZERO) != 0); // Vector-from-vector range insert _vec_char_push_back(&other, '1', &err); _vec_char_push_back(&other, '2', &err); // Double buffer check err = (err_t)ERR_T_INIT; _vec_char_insert(&vec, &vec, 0, 0, 1, &err); assert((err.flags & ERR_DOUBLE_BUF) != 0); _vec_char_delete(&vec, &err); _vec_char_delete(&other, &err); printf("Passed\n"); } /* ========================================================================= * MAIN TEST RUNNER * ========================================================================= */ int main(void) { printf("=========================================\n"); printf(" Starting Complete libvec Unit Test Suite\n"); printf("=========================================\n"); test_push_back_single(); test_null_guards(); test_origin_override(); test_print_vec(); test_cpy(); test_push_back(); test_pop_back(); test_reserve(); test_shrink_to_fit(); test_getters_and_access(); test_swap(); test_erase_variants(); test_resize(); test_assign(); test_insert(); printf("=========================================\n"); printf(" All 34 Test Suites Executed Successfully!\n"); printf("=========================================\n"); return 0; }