aboutsummaryrefslogtreecommitdiffstats
path: root/tests/strmap_tests.c
diff options
context:
space:
mode:
authorDouglas B. Rumbaugh <doug@douglasrumbaugh.com>2025-11-01 13:31:38 -0400
committerDouglas B. Rumbaugh <doug@douglasrumbaugh.com>2025-11-01 13:31:38 -0400
commit6338ac827b15787a0d83136eac9d681588f07f9a (patch)
treef808100cd52e54c632b31b8a42f3bdb703f3d31a /tests/strmap_tests.c
downloadlibmap-6338ac827b15787a0d83136eac9d681588f07f9a.tar.gz
Initial commit
Diffstat (limited to 'tests/strmap_tests.c')
-rwxr-xr-xtests/strmap_tests.c228
1 files changed, 228 insertions, 0 deletions
diff --git a/tests/strmap_tests.c b/tests/strmap_tests.c
new file mode 100755
index 0000000..7f3c34f
--- /dev/null
+++ b/tests/strmap_tests.c
@@ -0,0 +1,228 @@
+/*
+ * strmap_test.c
+ *
+ * Unit tests for strmap implementation
+ */
+
+#include "hashfuncs.h"
+#include "strmap.h"
+
+#include <check.h>
+#include <stdlib.h>
+#include <string.h>
+
+START_TEST(test_create_destroy) {
+ strmap *map = strmap_create(hash_key);
+ ck_assert_ptr_nonnull(map);
+ ck_assert_uint_eq(strmap_size(map), 0);
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_put_get_basic) {
+ strmap *map = strmap_create(hash_key);
+ const char *value;
+
+ ck_assert_int_eq(strmap_put(map, "key1", "value1"), STRMAP_OK);
+ ck_assert_uint_eq(strmap_size(map), 1);
+
+ ck_assert_int_eq(strmap_get(map, "key1", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "value1");
+
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_put_update) {
+ strmap *map = strmap_create(hash_key);
+ const char *value;
+
+ ck_assert_int_eq(strmap_put(map, "key1", "value1"), STRMAP_OK);
+ ck_assert_int_eq(strmap_put(map, "key1", "value2"), STRMAP_OK);
+ ck_assert_uint_eq(strmap_size(map), 1);
+
+ ck_assert_int_eq(strmap_get(map, "key1", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "value2");
+
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_get_nonexistent) {
+ strmap *map = strmap_create(hash_key);
+ const char *value;
+
+ ck_assert_int_eq(strmap_get(map, "nonexistent", &value), STRMAP_NOTFOUND);
+
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_delete_basic) {
+ strmap *map = strmap_create(hash_key);
+ const char *value;
+
+ ck_assert_int_eq(strmap_put(map, "key1", "value1"), STRMAP_OK);
+ ck_assert_int_eq(strmap_delete(map, "key1"), STRMAP_OK);
+ ck_assert_uint_eq(strmap_size(map), 0);
+
+ ck_assert_int_eq(strmap_get(map, "key1", &value), STRMAP_NOTFOUND);
+
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_delete_nonexistent) {
+ strmap *map = strmap_create(hash_key);
+
+ ck_assert_int_eq(strmap_delete(map, "nonexistent"), STRMAP_NOTFOUND);
+
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_delete_multiple) {
+ strmap *map = strmap_create(hash_key);
+ const char *value;
+
+ // Add multiple items
+ ck_assert_int_eq(strmap_put(map, "key1", "value1"), STRMAP_OK);
+ ck_assert_int_eq(strmap_put(map, "key2", "value2"), STRMAP_OK);
+ ck_assert_int_eq(strmap_put(map, "key3", "value3"), STRMAP_OK);
+ ck_assert_uint_eq(strmap_size(map), 3);
+
+ // Delete middle item
+ ck_assert_int_eq(strmap_delete(map, "key2"), STRMAP_OK);
+ ck_assert_uint_eq(strmap_size(map), 2);
+ ck_assert_int_eq(strmap_get(map, "key2", &value), STRMAP_NOTFOUND);
+
+ // Verify remaining items
+ ck_assert_int_eq(strmap_get(map, "key1", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "value1");
+ ck_assert_int_eq(strmap_get(map, "key3", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "value3");
+
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_delete_head) {
+ strmap *map = strmap_create(hash_key);
+ const char *value;
+
+ // Add items that will likely hash to same bucket
+ ck_assert_int_eq(strmap_put(map, "a", "first"), STRMAP_OK);
+ ck_assert_int_eq(strmap_put(map, "b", "second"), STRMAP_OK);
+ ck_assert_int_eq(strmap_put(map, "c", "third"), STRMAP_OK);
+
+ // Delete head item
+ ck_assert_int_eq(strmap_delete(map, "c"), STRMAP_OK);
+ ck_assert_uint_eq(strmap_size(map), 2);
+ ck_assert_int_eq(strmap_get(map, "c", &value), STRMAP_NOTFOUND);
+
+ // Verify remaining items
+ ck_assert_int_eq(strmap_get(map, "a", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "first");
+ ck_assert_int_eq(strmap_get(map, "b", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "second");
+
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_collision_handling) {
+ strmap *map = strmap_create(test_hash);
+ const char *value;
+
+ /* all keys with the same initial letter should map to the same bucket */
+ ck_assert_int_eq(strmap_put(map, "key1", "value1"), STRMAP_OK);
+ ck_assert_int_eq(strmap_put(map, "key2", "value2"), STRMAP_OK);
+ ck_assert_int_eq(strmap_put(map, "key3", "value3"), STRMAP_OK);
+ ck_assert_uint_eq(strmap_size(map), 3);
+
+ // Retrieve all values
+ ck_assert_int_eq(strmap_get(map, "key1", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "value1");
+ ck_assert_int_eq(strmap_get(map, "key2", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "value2");
+ ck_assert_int_eq(strmap_get(map, "key3", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "value3");
+
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_empty_key_value) {
+ strmap *map = strmap_create(hash_key);
+ const char *value;
+
+ // Test empty string key
+ ck_assert_int_eq(strmap_put(map, "", "empty_key_value"), STRMAP_OK);
+ ck_assert_int_eq(strmap_get(map, "", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "empty_key_value");
+
+ // Test empty string value
+ ck_assert_int_eq(strmap_put(map, "empty_value_key", ""), STRMAP_OK);
+ ck_assert_int_eq(strmap_get(map, "empty_value_key", &value), STRMAP_OK);
+ ck_assert_str_eq(value, "");
+
+ strmap_destroy(map);
+}
+END_TEST
+
+START_TEST(test_put_null_key) {
+ strmap *map = strmap_create(hash_key);
+
+ // This should ideally be handled gracefully
+ // Behavior depends on your strdup implementation with NULL
+ // For now, we'll assume it fails gracefully
+ ck_assert_int_eq(strmap_put(map, NULL, "value"), STRMAP_ERR);
+
+ strmap_destroy(map);
+}
+END_TEST
+
+Suite *strmap_suite(void) {
+ Suite *s;
+ TCase *tc_core;
+ TCase *tc_edge;
+
+ s = suite_create("Strmap");
+
+ /* Core test case */
+ tc_core = tcase_create("Core");
+ tcase_add_test(tc_core, test_create_destroy);
+ tcase_add_test(tc_core, test_put_get_basic);
+ tcase_add_test(tc_core, test_put_update);
+ tcase_add_test(tc_core, test_get_nonexistent);
+ tcase_add_test(tc_core, test_delete_basic);
+ tcase_add_test(tc_core, test_delete_nonexistent);
+ tcase_add_test(tc_core, test_delete_multiple);
+ tcase_add_test(tc_core, test_delete_head);
+ tcase_add_test(tc_core, test_collision_handling);
+
+ /* Edge cases */
+ tc_edge = tcase_create("Edge");
+ tcase_add_test(tc_edge, test_empty_key_value);
+ tcase_add_test(tc_edge, test_put_null_key);
+
+ suite_add_tcase(s, tc_core);
+ suite_add_tcase(s, tc_edge);
+
+ return s;
+}
+
+int main(void) {
+ int number_failed;
+ Suite *s;
+ SRunner *sr;
+
+ s = strmap_suite();
+ sr = srunner_create(s);
+
+ srunner_run_all(sr, CK_NORMAL);
+ number_failed = srunner_ntests_failed(sr);
+ srunner_free(sr);
+
+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}