summaryrefslogtreecommitdiffstats
path: root/tests/hashmap_tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/hashmap_tests.c')
-rw-r--r--tests/hashmap_tests.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/tests/hashmap_tests.c b/tests/hashmap_tests.c
new file mode 100644
index 0000000..d4835dc
--- /dev/null
+++ b/tests/hashmap_tests.c
@@ -0,0 +1,311 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright © 2010, Zed A. Shaw.
+ * Copyright © 2020 rsiddharth <s@ricketyspace.net>
+ */
+
+#include "minunit.h"
+#include <hashmap.h>
+#include <assert.h>
+#include <bstrlib.h>
+
+Hashmap *map = NULL;
+Hashmap *map_alt = NULL;
+static int traverse_called = 0;
+static int traverse_duplicates = 0;
+struct tagbstring test0 = bsStatic("test data 0");
+struct tagbstring test1 = bsStatic("test data 1");
+struct tagbstring test2 = bsStatic("test data 2");
+struct tagbstring test3 = bsStatic("xest data 3");
+struct tagbstring expect0 = bsStatic("THE VALUE 0");
+struct tagbstring expect1 = bsStatic("THE VALUE 1");
+struct tagbstring expect2 = bsStatic("THE VALUE 2");
+struct tagbstring expect3 = bsStatic("THE VALUE 3");
+
+static int traverse_good_cb(HashmapNode *node)
+{
+ debug("KEY: %s", bdata((bstring) node->key));
+ traverse_called++;
+ return 0;
+}
+
+static int traverse_fail_cb(HashmapNode *node)
+{
+ debug("KEY %s", bdata((bstring) node->key));
+ traverse_called++;
+
+ if (traverse_called == 2) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int traverse_duplicates_cb(HashmapNode *node)
+{
+ if ((bstring) node->data == &expect1) {
+ ++traverse_duplicates;
+ }
+
+ return 0;
+}
+
+int non_empty_buckets(Hashmap *map)
+{
+ int i = 0, non_empty = 0;
+
+ for (i = 0; i < DArray_count(map->buckets); i++) {
+ DArray *bucket = DArray_get(map->buckets, i);
+ if (bucket) {
+ non_empty += 1;
+ }
+ }
+
+ return non_empty;
+}
+
+char *test_create()
+{
+ map = Hashmap_create(NULL, NULL);
+ mu_assert(map != NULL, "Failed to create map.");
+
+ map_alt = Hashmap_create(NULL, (Hashmap_hash) fnv_hash);
+ mu_assert(map != NULL, "Failde to create map_alt.");
+
+ return NULL;
+}
+
+char *test_destroy()
+{
+ Hashmap_destroy(map);
+ Hashmap_destroy(map_alt);
+ return NULL;
+}
+
+char *test_get_test()
+{
+ int rc = Hashmap_set(map, &test1, &expect1);
+ mu_assert(rc == 0, "Failed to set &test1");
+ bstring result = Hashmap_get(map, &test1);
+ mu_assert(result == &expect1, "Wron value for test1.");
+
+ rc = Hashmap_set(map, &test2, &expect2);
+ mu_assert(rc == 0, "Failed to test test2");
+ result = Hashmap_get(map, &test2);
+ mu_assert(result == &expect2, "Wrong value for test2.");
+
+ rc = Hashmap_set(map, &test3, &expect3);
+ mu_assert(rc == 0, "Failed to set test3");
+ result = Hashmap_get(map, &test3);
+ mu_assert(result == &expect3, "Wrong value for test3");
+
+ return NULL;
+}
+
+char *test_traverse()
+{
+ int rc = Hashmap_traverse(map, traverse_good_cb);
+ mu_assert(rc == 0, "Failed to traverse");
+ mu_assert(traverse_called == 3, "Wrong count traverse");
+
+ traverse_called = 0;
+ rc = Hashmap_traverse(map, traverse_fail_cb);
+ mu_assert(rc == 1, "Failed to traverse.");
+ mu_assert(traverse_called == 2, "Wrong count traverse for fail.");
+
+ return NULL;
+}
+
+char *test_keys()
+{
+ DArray *keys = Hashmap_keys(map);
+ mu_assert(keys != NULL, "Unable to get hashmap's keys");
+ mu_assert(DArray_count(keys) == 3, "Expected three keys");
+
+ for (int i = 0; i < DArray_count(keys); i++) {
+ char *k = bdata((bstring) DArray_get(keys, i));
+
+ debug("KEY: %s", k);
+ }
+
+ // clean up.
+ DArray_destroy(keys);
+
+ return NULL;
+}
+
+char *test_delete()
+{
+ bstring deleted = (bstring) Hashmap_delete(map, &test1);
+ mu_assert(deleted != NULL, "Got NULL on delete");
+ mu_assert(deleted == &expect1, "Should get test1");
+ bstring result = Hashmap_get(map, &test1);
+ mu_assert(result == NULL, "Should delete");
+
+ deleted = (bstring) Hashmap_delete(map, &test2);
+ mu_assert(deleted != NULL, "Got NULL on delete");
+ mu_assert(deleted == &expect2, "Should get test2");
+ result = Hashmap_get(map, &test2);
+ mu_assert(result == NULL, "Should delete");
+
+ deleted = (bstring) Hashmap_delete(map, &test3);
+ mu_assert(deleted != NULL, "Got NULL on delete.");
+ mu_assert(deleted == &expect3, "Should get test3");
+ result = Hashmap_get(map, &test3);
+ mu_assert(result == NULL, "Should delete.");
+
+ return NULL;
+}
+
+char *test_bucket_destruction()
+{
+ int rc = 0, non_empty = 0;
+ bstring deleted = NULL;
+
+ // Insert some elements.
+ rc = Hashmap_set(map, &test1, &expect1);
+ mu_assert(rc == 0, "Failed to set &test1 0");
+ rc = Hashmap_set(map, &test2, &expect2);
+ mu_assert(rc == 0, "Failed to test test2");
+
+ // Non-empty buckets test.
+ non_empty = non_empty_buckets(map);
+ mu_assert(non_empty == 2, "Expected two non-empty buckets");
+
+ // Remove test1
+ deleted = Hashmap_delete(map, &test1);
+ mu_assert(deleted != NULL, "Error deleting test1");
+
+ // Non-empty buckets test.
+ non_empty = non_empty_buckets(map);
+ mu_assert(non_empty == 1, "Expected one non-empty buckets");
+
+ // Remove test2
+ deleted = Hashmap_delete(map, &test2);
+ mu_assert(deleted != NULL, "Error deleting test2");
+
+ // Non-empty buckets test.
+ non_empty = non_empty_buckets(map);
+ mu_assert(non_empty == 0, "Expected one non-empty buckets");
+
+ return NULL;
+}
+
+char *test_set_duplicates()
+{
+ int rc = 0;
+
+ // Insert test1 two times.
+ rc = Hashmap_set(map, &test1, &expect1);
+ mu_assert(rc == 0, "Failed to set &test1 0");
+ rc = Hashmap_set(map, &test1, &expect1);
+ mu_assert(rc == 0, "Failed to set &test1 1");
+
+ // Insert test2 one time.
+ rc = Hashmap_set(map, &test2, &expect2);
+ mu_assert(rc == 0, "Failed to test test2");
+
+ // Insert test3 one time.
+ rc = Hashmap_set(map, &test3, &expect3);
+ mu_assert(rc == 0, "Failed to set test3");
+
+ // Test there are two test1 nodes.
+ traverse_duplicates = 0;
+ rc = Hashmap_traverse(map, traverse_duplicates_cb);
+ mu_assert(traverse_duplicates == 2,
+ "traverse_duplicates must be 2");
+
+ // Cleanup
+ bstring deleted = NULL;
+ deleted = Hashmap_delete(map, &test1);
+ mu_assert(deleted != NULL, "Error deleting test1 0");
+ deleted = Hashmap_delete(map, &test1);
+ mu_assert(deleted != NULL, "Error deleting test1 1");
+ deleted = Hashmap_delete(map, &test2);
+ mu_assert(deleted != NULL, "Error deleting test2");
+ deleted = Hashmap_delete(map, &test3);
+ mu_assert(deleted != NULL, "Error deleting test3");
+
+ return NULL;
+}
+
+char *test_set_fucked()
+{
+ int rc = 0;
+
+ // Insert test1 three times.
+ rc = Hashmap_set_fucked(map, &test1, &expect1);
+ mu_assert(rc == 1, "Failed to set fuck &test1 0");
+ rc = Hashmap_set_fucked(map, &test1, &expect1);
+ mu_assert(rc == 0, "Failed to set fuck &test1 1");
+ rc = Hashmap_set_fucked(map, &test1, &expect1);
+ mu_assert(rc == 0, "Failed to set fuck &test1 2");
+
+ // Insert test2 one time.
+ rc = Hashmap_set_fucked(map, &test2, &expect2);
+ mu_assert(rc == 1, "Failed to test test2");
+
+ // Insert test3 one time.
+ rc = Hashmap_set_fucked(map, &test3, &expect3);
+ mu_assert(rc == 1, "Failed to set test3");
+
+ // Test there are two test1 nodes.
+ traverse_duplicates = 0;
+ rc = Hashmap_traverse(map, traverse_duplicates_cb);
+ mu_assert(traverse_duplicates == 1,
+ "traverse_duplicates must be 1");
+
+ // Cleanup
+ bstring deleted = NULL;
+ deleted = Hashmap_delete(map, &test1);
+ mu_assert(deleted != NULL, "Error deleting test1");
+ deleted = Hashmap_delete(map, &test1);
+ mu_assert(deleted == NULL, "Error test1 must be already deleted");
+ deleted = Hashmap_delete(map, &test2);
+ mu_assert(deleted != NULL, "Error deleting test2");
+ deleted = Hashmap_delete(map, &test3);
+ mu_assert(deleted != NULL, "Error deleting test3");
+
+ return NULL;
+}
+
+char *test_fnv_hash()
+{
+ uint32_t hash[3];
+
+ hash[0] = fnv_hash(&test0);
+ mu_assert(hash[0] > 0, "hash not set correctly for key test0");
+
+ hash[1] = fnv_hash(&test1);
+ mu_assert(hash[1] > 0, "hash not set correctly for key test1");
+
+ hash[2] = fnv_hash(&test2);
+ mu_assert(hash[2] > 0, "hash not set correctly for key test2");
+
+ // Check all three hashes are different.
+ mu_assert(hash[0] != hash[1], "hash for test0 = hash for test1");
+ mu_assert(hash[0] != hash[2], "hash for test0 = hash for test2");
+ mu_assert(hash[1] != hash[2], "hash for test1 = hash for test2");
+
+ return NULL;
+}
+
+char *all_tests()
+{
+ mu_suite_start();
+
+ mu_run_test(test_create);
+ mu_run_test(test_get_test);
+ mu_run_test(test_traverse);
+ mu_run_test(test_keys);
+ mu_run_test(test_delete);
+ mu_run_test(test_bucket_destruction);
+ mu_run_test(test_set_duplicates);
+ mu_run_test(test_set_fucked);
+ mu_run_test(test_fnv_hash);
+ mu_run_test(test_destroy);
+
+ return NULL;
+}
+
+RUN_TESTS(all_tests);