#include "c_Array.h" #include #include #include "c_Test.h" /* ========================================================================== */ /* TEST CASES */ /* ========================================================================== */ C_TEST_FRAME_INIT(); // 1. Stack Initialization and Destruction Loop void test_array_stack_init_destroy(void) { c_Array_t arr; c_err_t err = c_Array_Init(&arr, 5, sizeof(int)); C_ASSERT_EQ_INT(C_SUCCESS, err); C_ASSERT_EQ_INT(5, c_Array_Length(&arr)); C_ASSERT_EQ_INT(sizeof(int), c_Array_Size(&arr)); C_ASSERT_PTR_NOT_NULL(arr.array); c_Array_Destroy(&arr); } // 2. Heap Dynamic Allocation Lifecycles void test_array_heap_new_delete(void) { c_Array_t* arr = c_Array_New(10, sizeof(double)); C_ASSERT_PTR_NOT_NULL(arr); C_ASSERT_EQ_INT(10, c_Array_Length(arr)); C_ASSERT_EQ_INT(sizeof(double), c_Array_Size(arr)); c_Array_Delete(&arr); C_ASSERT_PTR_NULL(arr); // Ensure pointer is zeroed out by reference parameter modification } // 3. Put and Get Data Element Scenarios void test_array_put_and_get(void) { c_Array_t* arr = c_Array_New(3, sizeof(int)); C_ASSERT_PTR_NOT_NULL(arr); C_ASSERT_EQ_INT(3, arr->length); int val1 = 100, val2 = 200, val3 = 300; // Put elements inside length limits C_ASSERT_EQ_INT(C_SUCCESS, c_Array_Put(arr, 0, &val1)); C_ASSERT_EQ_INT(C_SUCCESS, c_Array_Put(arr, 1, &val2)); C_ASSERT_EQ_INT(C_SUCCESS, c_Array_Put(arr, 2, &val3)); // Out of bounds checks int val_bad = 999; C_ASSERT_EQ_INT(C_ERR_PARAM, c_Array_Put(arr, 3, &val_bad)); // Get verification void* fetch_ptr = NULL; C_ASSERT_EQ_INT(C_SUCCESS, c_Array_Get(arr, 1, &fetch_ptr)); C_ASSERT_PTR_NOT_NULL(fetch_ptr); C_ASSERT_EQ_INT(200, *(int*)fetch_ptr); // Out of bounds get verification C_ASSERT_EQ_INT(C_ERR_PARAM, c_Array_Get(arr, 5, &fetch_ptr)); c_Array_Delete(&arr); } // 4. Memory Resizing Limits Verification void test_array_resize(void) { c_Array_t* arr = c_Array_New(2, sizeof(int)); int val0 = 42, val1 = 84; c_Array_Put(arr, 0, &val0); c_Array_Put(arr, 1, &val1); // Resize up to 4 elements C_ASSERT_EQ_INT(C_SUCCESS, c_Array_Resize(arr, 4)); C_ASSERT_EQ_INT(4, c_Array_Length(arr)); // Verify older elements remain structurally untouched void* res_ptr = NULL; C_ASSERT_EQ_INT(C_SUCCESS, c_Array_Get(arr, 1, &res_ptr)); C_ASSERT_EQ_INT(84, *(int*)res_ptr); // Resize down to 1 element C_ASSERT_EQ_INT(C_SUCCESS, c_Array_Resize(arr, 1)); C_ASSERT_EQ_INT(1, c_Array_Length(arr)); // Index 1 should now be unreachable / out of bounds C_ASSERT_EQ_INT(C_ERR_PARAM, c_Array_Get(arr, 1, &res_ptr)); c_Array_Delete(&arr); } // 5. Deep Copy Execution Verification void test_array_copy_and_copy_to(void) { c_Array_t* source = c_Array_New(3, sizeof(int)); int a = 11, b = 22, c = 33; c_Array_Put(source, 0, &a); c_Array_Put(source, 1, &b); c_Array_Put(source, 2, &c); // Test c_Array_Copy (creates a new array object on the heap) c_Array_t* copied_arr = c_Array_Copy(source, 2); // copy only first 2 items C_ASSERT_PTR_NOT_NULL(copied_arr); C_ASSERT_EQ_INT(2, c_Array_Length(copied_arr)); void* data_ptr = NULL; c_Array_Get(copied_arr, 1, &data_ptr); C_ASSERT_EQ_INT(22, *(int*)data_ptr); // Test c_Array_CopyTo (copies into an already initialized destination) c_Array_t dest; c_Array_Init(&dest, 3, sizeof(int)); C_ASSERT_EQ_INT(C_SUCCESS, c_Array_CopyTo(source, &dest)); c_Array_Get(&dest, 2, &data_ptr); C_ASSERT_EQ_INT(33, *(int*)data_ptr); // Clean up all resources c_Array_Delete(&copied_arr); c_Array_Destroy(&dest); c_Array_Delete(&source); } /* ========================================================================== */ /* SUITE BINDINGS & ENTRY MAIN */ /* ========================================================================== */ static void array_data_structure_suite(void) { C_TEST_CASE_RUN(test_array_stack_init_destroy); C_TEST_CASE_RUN(test_array_heap_new_delete); C_TEST_CASE_RUN(test_array_put_and_get); C_TEST_CASE_RUN(test_array_resize); C_TEST_CASE_RUN(test_array_copy_and_copy_to); } int main(void) { C_TEST_SUITE_RUN(array_data_structure_suite); C_TEST_FRAME_REPORT(); return (g_test_ctx.tests_passed == g_test_ctx.tests_run) ? 0 : 1; }