#include #include #include #include #include "zarray.h" /* xzarray_type is defined in zarray.c */ extern typeinfo_t xzarray_type; /* Helper: create an xzarray instance */ static meta_obj_t* make_test_xzarray(void) { xzarray_params_t params = { .delta = 4, .datakiller = NULL }; return (meta_obj_t*)makeInstance(&xzarray_type, ¶ms); } static void test_freeze_thaw_slots_exist(void) { /* After P0-2, vfreeze and vthaw must be wired (non-NULL). */ const intf_varray_t* iface = (const intf_varray_t*)xzarray_type.interfaces.varray; TEST_ASSERT_NOT_NULL(iface); /* Access slots without crash — verifies struct layout has them */ (void)iface->vfreeze; (void)iface->vthaw; /* Slots must be non-NULL after P0-2 wires the real implementations */ TEST_ASSERT_NOT_NULL(iface->vfreeze); TEST_ASSERT_NOT_NULL(iface->vthaw); printf("test_freeze_thaw_slots_exist: PASS\n"); } static void test_freeze_creates_shadow(void) { meta_obj_t* arr = make_test_xzarray(); TEST_ASSERT_NOT_NULL(arr); /* Store 3 items */ char* items[3] = { "alpha", "beta", "gamma" }; for (int i = 0; i < 3; i++) { int idx = vstore(arr, items[i]); TEST_ASSERT_TRUE(idx >= 0); } /* Freeze should succeed */ TEST_ASSERT_EQUAL_INT(0, vfreeze(arr)); /* After freeze, vget must still return stored values (COW mode active) */ void* out = NULL; TEST_ASSERT_EQUAL_INT(0, vget(arr, 0, &out)); TEST_ASSERT_NOT_NULL(out); /* Thaw to clean up */ vthaw(arr, NULL, NULL); destroy(arr); } static void test_freeze_thaw_preserves_all_entries(void) { meta_obj_t* arr = make_test_xzarray(); TEST_ASSERT_NOT_NULL(arr); int N = 5; char* items[5] = { "a", "b", "c", "d", "e" }; int idxs[5]; for (int i = 0; i < N; i++) { idxs[i] = vstore(arr, items[i]); TEST_ASSERT_TRUE(idxs[i] >= 0); } TEST_ASSERT_EQUAL_INT(0, vfreeze(arr)); TEST_ASSERT_EQUAL_INT(0, vthaw(arr, NULL, NULL)); /* All 5 entries must be reachable after thaw */ for (int i = 0; i < N; i++) { void* out = NULL; TEST_ASSERT_EQUAL_INT(0, vget(arr, idxs[i], &out)); TEST_ASSERT_EQUAL_PTR(items[i], out); } destroy(arr); } static void test_mutation_during_cow_visible_after_thaw(void) { meta_obj_t* arr = make_test_xzarray(); TEST_ASSERT_NOT_NULL(arr); char* original = "original"; char* updated = "updated"; int idx = vstore(arr, original); TEST_ASSERT_TRUE(idx >= 0); TEST_ASSERT_EQUAL_INT(0, vfreeze(arr)); /* Overwrite index during COW — write to new active array */ int put_idxs[1] = { idx }; void* put_data[1] = { updated }; vput_vec(arr, 1, put_idxs, put_data); TEST_ASSERT_EQUAL_INT(0, vthaw(arr, NULL, NULL)); /* After thaw, the updated value must win over the shadow value */ void* out = NULL; TEST_ASSERT_EQUAL_INT(0, vget(arr, idx, &out)); TEST_ASSERT_EQUAL_PTR(updated, out); destroy(arr); } static void test_double_freeze_fails(void) { meta_obj_t* arr = make_test_xzarray(); TEST_ASSERT_NOT_NULL(arr); TEST_ASSERT_EQUAL_INT(0, vfreeze(arr)); /* Second freeze must fail (already in COW mode) */ TEST_ASSERT_TRUE(vfreeze(arr) != 0); vthaw(arr, NULL, NULL); destroy(arr); } void test_zarray_cow(void) { printf("\n>> zarray COW interface slot test\n\n"); RUN_TEST(test_freeze_thaw_slots_exist); RUN_TEST(test_freeze_creates_shadow); RUN_TEST(test_freeze_thaw_preserves_all_entries); RUN_TEST(test_mutation_during_cow_visible_after_thaw); RUN_TEST(test_double_freeze_fails); }