/** * @file symtab.c * @brief Tests the fixed-capacity open-addressed symbol table. */ #include #include #include #include "testutil.h" static akbasic_SymbolTable TABLE; int main(void) { void *value = NULL; int64_t ivalue = 0; char key[32]; int marker_a = 1; int marker_b = 2; int i = 0; TEST_REQUIRE_OK(akbasic_error_register()); TEST_REQUIRE_OK(akbasic_symtab_init(&TABLE, 16)); /* Round-trip both payloads. */ TEST_REQUIRE_OK(akbasic_symtab_set(&TABLE, "A#", &marker_a, 42)); TEST_REQUIRE_OK(akbasic_symtab_get(&TABLE, "A#", &value, &ivalue)); TEST_REQUIRE(value == &marker_a, "wrong pointer payload"); TEST_REQUIRE_INT(ivalue, 42); /* Replacing an existing key must not grow the table. */ TEST_REQUIRE_OK(akbasic_symtab_set(&TABLE, "A#", &marker_b, 43)); TEST_REQUIRE_OK(akbasic_symtab_get(&TABLE, "A#", &value, &ivalue)); TEST_REQUIRE(value == &marker_b, "replacement did not take"); TEST_REQUIRE_INT(ivalue, 43); TEST_REQUIRE_INT(TABLE.count, 1); /* A miss is AKERR_KEY, not a crash and not a silent NULL. */ TEST_REQUIRE_STATUS(akbasic_symtab_get(&TABLE, "B$", &value, &ivalue), AKERR_KEY); /* * Collisions. Sixteen distinct keys in a sixteen-slot table guarantees the * probe sequence is exercised, and the last insert has exactly one slot to * find. */ TEST_REQUIRE_OK(akbasic_symtab_clear(&TABLE)); for ( i = 0; i < 16; i++ ) { snprintf(key, sizeof(key), "V%d#", i); TEST_REQUIRE_OK(akbasic_symtab_set(&TABLE, key, NULL, i)); } for ( i = 0; i < 16; i++ ) { snprintf(key, sizeof(key), "V%d#", i); TEST_REQUIRE_OK(akbasic_symtab_get(&TABLE, key, NULL, &ivalue)); TEST_REQUIRE_INT(ivalue, i); } /* Seventeenth key into a sixteen-slot table: full, and it says so. */ TEST_REQUIRE_STATUS(akbasic_symtab_set(&TABLE, "OVERFLOW#", NULL, 0), AKBASIC_ERR_BOUNDS); /* Clear keeps the capacity but drops the contents. */ TEST_REQUIRE_OK(akbasic_symtab_clear(&TABLE)); TEST_REQUIRE_INT(TABLE.count, 0); TEST_REQUIRE_INT(TABLE.capacity, 16); TEST_REQUIRE_STATUS(akbasic_symtab_get(&TABLE, "V0#", NULL, NULL), AKERR_KEY); /* Argument validation. */ TEST_REQUIRE_STATUS(akbasic_symtab_init(NULL, 16), AKERR_NULLPOINTER); TEST_REQUIRE_STATUS(akbasic_symtab_init(&TABLE, 0), AKBASIC_ERR_BOUNDS); TEST_REQUIRE_STATUS(akbasic_symtab_init(&TABLE, AKBASIC_SYMTAB_MAX_SLOTS + 1), AKBASIC_ERR_BOUNDS); return akbasic_test_failures; }