/* test_kvmgr_reserve.c — job-array-single-wal-record task 7.1 (bug-1443) * * Unit tests for kvmgr_reserve() (kvmgr.c/kvmgr.h) -- the thin, kvmgr-level * forwarding wrapper around xzarray_reserve() (zarray.c, see * test_zarray_reserve.c for the rigorous capacity-growth proof at that * lower level). This file proves kvmgr_reserve() itself: * - correctly unwraps an xkvmgr_type instance and forwards to its * internal value store, allowing a subsequent bulk key_add() sequence * up to the reserved count to succeed; * - propagates a simulated allocation failure (via the SAME * xzarray_reserve_test_set_force_fail() seam kvmgr_reserve() forwards * into -- there is no separate kvmgr-level seam, deliberately, since * kvmgr_reserve() has no logic of its own beyond the forward); * - rejects a NULL kvmgr / negative n defensively. */ #include #include #include #include #include #include "kv.h" #include "kvmgr.h" #include "zarray.h" static var make_test_kvmgr(uint32_t nslots, uint32_t delta) { kvmgr_params_t params = { .key_type = KVMGR_KEY_INT, .nslots = nslots, .delta = delta, .datakiller = NULL }; return makeInstance(&xkvmgr_type, ¶ms); } /* ── kvmgr_reserve() allows a subsequent bulk key_add() sequence up to the * reserved count to succeed (functional forwarding proof) ──────────────── */ static void test_kvmgr_reserve_allows_subsequent_bulk_key_add(void) { const int n = 30; /* Tiny initial capacity/delta -- without reservation this would force * many incremental growth cycles across the loop below. */ var kvmgr = make_test_kvmgr(2, 1); TEST_ASSERT_NOT_NULL(kvmgr); lock(kvmgr, RTTI_LOCK_WRITE); int reserve_rc = kvmgr_reserve(kvmgr, n + 1); TEST_ASSERT_TRUE_MESSAGE(reserve_rc >= 0, "kvmgr_reserve must succeed for a valid kvmgr and count"); for (int i = 0; i < n; i++) { int idx = key_add(kvmgr, (void*)(long)(1000 + i), (void*)(long)i); TEST_ASSERT_TRUE_MESSAGE(idx >= 0, "every key_add within the reserved count must succeed"); } unlock(kvmgr); /* Spot-check a few entries resolve correctly. */ void* found = NULL; TEST_ASSERT_TRUE(key_find(kvmgr, (void*)(long)1000, &found) >= 0); TEST_ASSERT_EQUAL_INT(0, (int)(long)found); TEST_ASSERT_TRUE(key_find(kvmgr, (void*)(long)1029, &found) >= 0); TEST_ASSERT_EQUAL_INT(29, (int)(long)found); destroy(kvmgr); printf("test_kvmgr_reserve_allows_subsequent_bulk_key_add: PASS\n"); } /* ── Simulated allocation failure propagates through kvmgr_reserve() too -- * reusing the SAME xzarray_reserve()-level seam, since kvmgr_reserve() is a * pure forward with no logic of its own. ───────────────────────────────── */ static void test_kvmgr_reserve_propagates_simulated_allocation_failure(void) { var kvmgr = make_test_kvmgr(4, 4); TEST_ASSERT_NOT_NULL(kvmgr); xzarray_reserve_test_set_force_fail(); lock(kvmgr, RTTI_LOCK_WRITE); int rc = kvmgr_reserve(kvmgr, 10); unlock(kvmgr); TEST_ASSERT_EQUAL_INT_MESSAGE(-ENOMEM, rc, "a forced allocation failure must propagate as -ENOMEM through" " kvmgr_reserve()"); xzarray_reserve_test_clear_force_fail(); lock(kvmgr, RTTI_LOCK_WRITE); int rc2 = kvmgr_reserve(kvmgr, 10); unlock(kvmgr); TEST_ASSERT_TRUE_MESSAGE(rc2 >= 0, "clearing the force-fail seam must restore normal success"); destroy(kvmgr); printf("test_kvmgr_reserve_propagates_simulated_allocation_failure: " "PASS\n"); } /* ── Defensive / boundary ─────────────────────────────────────────────── */ static void test_kvmgr_reserve_rejects_null_kvmgr(void) { int rc = kvmgr_reserve(NULL, 5); TEST_ASSERT_TRUE(rc < 0); printf("test_kvmgr_reserve_rejects_null_kvmgr: PASS\n"); } static void test_kvmgr_reserve_rejects_negative_n(void) { var kvmgr = make_test_kvmgr(4, 4); TEST_ASSERT_NOT_NULL(kvmgr); lock(kvmgr, RTTI_LOCK_WRITE); int rc = kvmgr_reserve(kvmgr, -1); unlock(kvmgr); TEST_ASSERT_TRUE(rc < 0); destroy(kvmgr); printf("test_kvmgr_reserve_rejects_negative_n: PASS\n"); } /* ── Test group entry point ───────────────────────────────────────────── */ void test_kvmgr_reserve(void) { printf("\n>> kvmgr_reserve test\n"); RUN_TEST(test_kvmgr_reserve_allows_subsequent_bulk_key_add); RUN_TEST(test_kvmgr_reserve_propagates_simulated_allocation_failure); RUN_TEST(test_kvmgr_reserve_rejects_null_kvmgr); RUN_TEST(test_kvmgr_reserve_rejects_negative_n); }