summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrsiddharth <s@ricketyspace.net>2020-04-17 20:34:16 -0400
committerrsiddharth <s@ricketyspace.net>2020-04-17 20:56:37 -0400
commit65fdd3c928ed0f0607e604dbef1ce7673b621b56 (patch)
tree8c80e68d33d8bec8940657b3872a5cddfce9b3bb
parentebe9b4e02b7d86e0a7b31dd9b129d20814072cca (diff)
nserver: Add tests from liblcthw.
Some tests were modified.
-rw-r--r--nserver/tests/darray_algos_tests.c102
-rw-r--r--nserver/tests/darray_tests.c361
-rw-r--r--nserver/tests/hashmap_tests.c311
-rw-r--r--nserver/tests/tstree_tests.c132
4 files changed, 906 insertions, 0 deletions
diff --git a/nserver/tests/darray_algos_tests.c b/nserver/tests/darray_algos_tests.c
new file mode 100644
index 0000000..01ef471
--- /dev/null
+++ b/nserver/tests/darray_algos_tests.c
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright © 2010, Zed A. Shaw.
+ * Copyright © 2020 rsiddharth <s@ricketyspace.net>
+ */
+
+#include "minunit.h"
+#include <darray_algos.h>
+
+int testcmp(char **a, char **b)
+{
+ return strcmp(*a, *b);
+}
+
+DArray *create_words()
+{
+ DArray *result = DArray_create(0, 5);
+ char *words[] = { "asdfasfd",
+ "werwar", "13234", "asdfasfd", "oioj" };
+ int i = 0;
+
+ for (i = 0; i < 5; i++) {
+ DArray_push(result, words[i]);
+ }
+
+ return result;
+}
+
+int is_sorted(DArray *array)
+{
+ int i = 0;
+
+ for (i = 0; i < DArray_count(array) -1; i++) {
+ if (strcmp(DArray_get(array, i), DArray_get(array, i + 1)) > 0) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+char *run_sort_test(int (*func) (DArray *, DArray_compare),
+ const char *name)
+{
+ DArray *words = create_words();
+ mu_assert(!is_sorted(words), "Words should start not sorted.");
+
+ debug("--- Testing %s sorting algorithm", name);
+ int rc = func(words, (DArray_compare) testcmp);
+ mu_assert(rc == 0, "sort failed");
+ mu_assert(is_sorted(words), "didn't sort it");
+
+ DArray_destroy(words);
+
+ return NULL;
+}
+
+char *test_qsort()
+{
+ return run_sort_test(DArray_qsort, "qsort");
+}
+
+char *test_fucked_qsort()
+{
+ return run_sort_test(DArray_fucked_qsort, "fucked qsort");
+}
+
+char *test_heapsort()
+{
+ return run_sort_test(DArray_heapsort, "heapsort");
+}
+
+char *test_fucked_heapsort()
+{
+ return run_sort_test(DArray_fucked_heapsort, "fucked heapsort");
+}
+
+char *test_mergesort()
+{
+ return run_sort_test(DArray_mergesort, "mergesort");
+}
+
+char *test_fucked_mergesort()
+{
+ return run_sort_test(DArray_fucked_mergesort, "fucked mergesort");
+}
+
+char *all_tests()
+{
+ mu_suite_start();
+
+ mu_run_test(test_qsort);
+ mu_run_test(test_fucked_qsort);
+ mu_run_test(test_heapsort);
+ mu_run_test(test_fucked_heapsort);
+ mu_run_test(test_mergesort);
+ mu_run_test(test_fucked_mergesort);
+
+ return NULL;
+}
+
+RUN_TESTS(all_tests);
diff --git a/nserver/tests/darray_tests.c b/nserver/tests/darray_tests.c
new file mode 100644
index 0000000..b33c460
--- /dev/null
+++ b/nserver/tests/darray_tests.c
@@ -0,0 +1,361 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright © 2010, Zed A. Shaw.
+ * Copyright © 2020 rsiddharth <s@ricketyspace.net>
+ */
+
+#include "minunit.h"
+#include <darray.h>
+
+static DArray *array = NULL;
+static int *val1 = NULL;
+static int *val2 = NULL;
+
+int testcmp(int **a, int **b)
+{
+ int x = **a, y = **b;
+
+ if (x == y) {
+ return 0;
+ } else if (x < y) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+char *test_create()
+{
+ // Test fail.
+ array = DArray_create(0, 0);
+ mu_assert(array == NULL, "array must be NULL.");
+
+ // Test success.
+ array = DArray_create(sizeof(int), 100);
+ mu_assert(array != NULL, "DArray_create failed.");
+ mu_assert(array->contents != NULL, "contents are wrong in array.");
+ mu_assert(array->end == 0, "end isn't at the right spot");
+ mu_assert(array->element_size == sizeof(int),
+ "element size is wrong.");
+ mu_assert(array->max == 100, "wrong max length on initial size");
+
+ return NULL;
+}
+
+char *test_destroy()
+{
+ DArray_destroy(array);
+
+ return NULL;
+}
+
+char *test_new()
+{
+ // Test fail.
+ val1 = DArray_new(NULL);
+ mu_assert(val1 == NULL, "val1 must be NULL");
+
+ // Test success
+ val1 = DArray_new(array);
+ mu_assert(val1 != NULL, "failed to make a new element");
+
+ val2 = DArray_new(array);
+ mu_assert(val2 != NULL, "failed to make a new element");
+
+ return NULL;
+}
+
+char *test_set()
+{
+ int rc = 0;
+
+ // Test fail.
+
+ // case where array is NULL
+ rc = DArray_set(NULL, 0, val1);
+ mu_assert(rc == -1, "rc must be -1");
+
+ // case where i < 0
+ rc = DArray_set(array, -1, val1);
+ mu_assert(rc == -1, "rc must be -1");
+
+ // case where i > array->max
+ rc = DArray_set(array, array->max + 1, val1);
+ mu_assert(rc == -1, "rc must be -1");
+
+ // Test success.
+
+ // must set val1 at index 0
+ rc = DArray_set(array, 0, val1);
+ mu_assert(rc == 0, "rc must be 0");
+
+ // must set val2 at index 1
+ rc = DArray_set(array, 1, val2);
+ mu_assert(rc == 1, "rc must be 1");
+
+ return NULL;
+}
+
+char *test_get()
+{
+ void *rc = NULL;
+
+ // Test fail.
+
+ // case where array is NULL
+ rc = DArray_get(NULL, 0);
+ mu_assert(rc == NULL, "rc must be NULL");
+
+ // case where i < 0
+ rc = DArray_get(array, -2);
+ mu_assert(rc == NULL, "rc must be NULL");
+
+ // case where i > array->max
+ rc = DArray_get(array, array->max + 1);
+ mu_assert(rc == NULL, "rc must be NULL");
+
+ // Test succcess.
+ mu_assert(DArray_get(array, 0) == val1, "Wrong first value");
+ mu_assert(DArray_get(array, 1) == val2, "Wrong second value");
+
+ return NULL;
+}
+
+char *test_remove()
+{
+ int *val_check = NULL;
+
+ // Test fail.
+
+ // case where array is NULL.
+ val_check = DArray_remove(NULL, 0);
+ mu_assert(val_check == NULL, "val_check must be NULL");
+ mu_assert(array->contents[0] != NULL,
+ "array->contents[0] must not be NULL");
+
+ // case where i < 0
+ val_check = DArray_remove(array, -1);
+ mu_assert(val_check == NULL, "val_check must be NULL");
+
+ // case where i > array->max
+ val_check = DArray_remove(array, array->max + 1);
+ mu_assert(val_check == NULL, "val_check must be NULL");
+
+ // Test success.
+ val_check = DArray_remove(array, 0);
+ mu_assert(val_check !=NULL, "Should not get NULL");
+ mu_assert(*val_check == *val1, "Should get the first value.");
+ mu_assert(DArray_get(array, 0) == NULL, "Should be gone.");
+ DArray_free(val_check);
+
+ val_check = DArray_remove(array, 1);
+ mu_assert(val_check != NULL, "Should not get NULL.");
+ mu_assert(*val_check == *val2, "Should get second value.");
+ mu_assert(DArray_get(array, 1) == NULL, "Should be gone");
+ DArray_free(val_check);
+
+ return NULL;
+}
+
+char *test_expand_contract()
+{
+ int old_max = array->max;
+ DArray_expand(array);
+ mu_assert((unsigned int) array->max == old_max + array->expand_rate,
+ "Wrong size after expand.");
+
+ // Check if newly allocated space is all set to 0.
+ int i = 0;
+ for (i = old_max; i < array->max; i++) {
+ mu_assert(array->contents[i] == 0, "contents must be 0");
+ }
+
+ int rc = 0;
+ rc = DArray_contract(array);
+ mu_assert(rc == 0, "rc must be 0");
+ mu_assert((unsigned int) array->max == array->expand_rate + 1,
+ "Should stay at the expand_rate at least.");
+
+ rc = DArray_contract(array);
+ mu_assert(rc == 0, "rc must be 0");
+ mu_assert((unsigned int) array->max == array->expand_rate + 1,
+ "Should stay at the expand_rate at least");
+
+ return NULL;
+}
+
+char *test_push_pop()
+{
+ int i = 0, rc = 0;
+ for (i = 0; i < 1000; i++) {
+ int *val = DArray_new(array);
+ *val = i * 333;
+ rc = DArray_push(array, val);
+ mu_assert(rc == 0, "Darray_push failed");
+ }
+
+ mu_assert(array->max == 1201, "Wrong max size.");
+
+ for (i = 999; i >= 0; i--) {
+ int *val = DArray_pop(array);
+ mu_assert(val != NULL, "Shouldn't get a NULL");
+ mu_assert(*val == i * 333, "Wrong value.");
+
+ if ((DArray_end(array) > (int) array->expand_rate) &&
+ (DArray_end(array) % array->expand_rate)) {
+ mu_assert(array->max == DArray_end(array) + 1,
+ "DArray pop contract error");
+ }
+
+ DArray_free(val);
+ }
+
+ return NULL;
+}
+
+int is_sorted(DArray *array)
+{
+ int i = 0;
+
+ for (i = 0; i < DArray_count(array) -1; i++) {
+ if (*((int *) DArray_get(array, i)) > *((int *) DArray_get(array, i + 1))) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+char *test_shallow_copy()
+{
+ // First populate array.
+ array = DArray_create(sizeof(int), 100);
+ int i = 0, rc = 0;
+ int *val = NULL;
+ for (i = 0; i < 1000; i++) {
+ val = DArray_new(array);
+ *val = i * 333;
+ rc = DArray_push(array, val);
+ mu_assert(rc == 0, "Darray_push failed");
+ }
+ mu_assert(array->max == 1300, "Wrong max size.");
+
+ // Set at 1100
+ val = DArray_new(array);
+ *val = 42;
+ rc = DArray_set(array, 1100, val);
+ mu_assert(rc == 1100, "Error setting value at 1100");
+
+ // Set at 1110
+ val = DArray_new(array);
+ *val = 4242;
+ rc = DArray_set(array, 1110, val);
+ mu_assert(rc == 1110, "Error setting value at 1110");
+
+ // Test shallow copy
+ DArray *copy = DArray_shallow_copy(array);
+ mu_assert(copy != NULL, "Shallow copy failed");
+
+ int expected = 0;
+ for (i = 0; i < 1000; i++) {
+ expected = i * 333;
+ val = DArray_get(copy, i);
+ mu_assert(*val == expected, "Unexpected element in copy.");
+ }
+
+ expected = 42;
+ val = DArray_get(copy, 1100);
+ mu_assert(*val == expected, "Unexpected element at in copy.");
+
+ expected = 4242;
+ val = DArray_get(copy, 1110);
+ mu_assert(*val == expected, "Unexpected element at in copy.");
+
+ // Destroy copy.
+ DArray_destroy(copy);
+
+ // Destroy array.
+ DArray_clear_destroy(array);
+ return NULL;
+}
+
+char *test_sort_add()
+{
+ array = DArray_create(sizeof(int), 100);
+ mu_assert(array != NULL, "Error initializing array");
+
+ int i = 0, rc = 0;
+ int *val = NULL;
+ for (i = 0; i < 2000; i++) {
+ val = DArray_new(array);
+ mu_assert(val != NULL, "Error creating new element");
+ *val = rand();
+
+ rc = DArray_sort_add(array, val, (DArray_compare) testcmp);
+ mu_assert(rc == 0, "Error adding element.");
+ mu_assert(is_sorted(array) == 1, "array not sorted.");
+ }
+
+ DArray_clear_destroy(array);
+ return NULL;
+}
+
+char *test_find()
+{
+ array = DArray_create(sizeof(int), 100);
+ mu_assert(array != NULL, "Error initializing array");
+
+ // test setup.
+ int i = 0, rc = 0;
+ int *val = NULL;
+ for (i = 0; i < 2000; i++) {
+ val = DArray_new(array);
+ mu_assert(val != NULL, "Error creating new element");
+ *val = i;
+
+ rc = DArray_sort_add(array, val, (DArray_compare) testcmp);
+ mu_assert(rc == 0, "Error adding element");
+ mu_assert(is_sorted(array) == 1, "array not sorted");
+ }
+
+ // tests.
+ val = DArray_new(array);
+ mu_assert(val != NULL, "Error creating new element");
+
+ for (i = 0; i < 2000; i++) {
+ *val = i;
+
+ rc = DArray_find(array, val, (DArray_compare) testcmp);
+ mu_assert(rc == i, "val not found in array");
+ }
+
+ *val = 3000;
+ rc = DArray_find(array, val, (DArray_compare) testcmp);
+ mu_assert(rc == -1, "rc must be -1");
+
+ // test teardown.
+ DArray_clear_destroy(array);
+ free(val);
+ return NULL;
+}
+
+char *all_tests()
+{
+ mu_suite_start();
+
+ mu_run_test(test_create);
+ mu_run_test(test_new);
+ mu_run_test(test_set);
+ mu_run_test(test_get);
+ mu_run_test(test_remove);
+ mu_run_test(test_expand_contract);
+ mu_run_test(test_push_pop);
+ mu_run_test(test_destroy);
+ mu_run_test(test_shallow_copy);
+ mu_run_test(test_sort_add);
+ mu_run_test(test_find);
+
+ return NULL;
+}
+
+RUN_TESTS(all_tests);
diff --git a/nserver/tests/hashmap_tests.c b/nserver/tests/hashmap_tests.c
new file mode 100644
index 0000000..d4835dc
--- /dev/null
+++ b/nserver/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);
diff --git a/nserver/tests/tstree_tests.c b/nserver/tests/tstree_tests.c
new file mode 100644
index 0000000..d8b5f9f
--- /dev/null
+++ b/nserver/tests/tstree_tests.c
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright © 2010, Zed A. Shaw.
+ * Copyright © 2020 rsiddharth <s@ricketyspace.net>
+ */
+
+#include "minunit.h"
+#include <tstree.h>
+#include <string.h>
+#include <assert.h>
+#include <bstrlib.h>
+
+TSTree *node = NULL;
+char *valueA = "VALUEA";
+char *valueB = "VALUEB";
+char *value2 = "VALUE2";
+char *value4 = "VALUE4";
+char *reverse = "VALUER";
+int traverse_count = 0;
+
+struct tagbstring test1 = bsStatic("TEST");
+struct tagbstring test2 = bsStatic("TEST2");
+struct tagbstring test3 = bsStatic("TSET");
+struct tagbstring test4 = bsStatic("T");
+
+char *test_insert()
+{
+ node = TSTree_insert(node, bdata(&test1), blength(&test1), valueA);
+ mu_assert(node != NULL, "Failed to insert into tst.");
+
+ node = TSTree_insert(node, bdata(&test2), blength(&test2), value2);
+ mu_assert(node != NULL,
+ "Failed to insert into tst with second name.");
+
+ node = TSTree_insert(node, bdata(&test3), blength(&test3), reverse);
+ mu_assert(node != NULL,
+ "Failed to insert into tst with reverse name");
+
+ node = TSTree_insert(node, bdata(&test4), blength(&test4), value4);
+ mu_assert(node != NULL,
+ "Failed to insert into tst with second name.");
+
+ return NULL;
+}
+
+char *test_search_exact()
+{
+ // tst returns the last one inserted
+ void *res = TSTree_search(node, bdata(&test1), blength(&test1));
+ mu_assert(res == valueA,
+ "Got the wrong value back, should get A not B.");
+
+ // tst does not find if not exact
+ res = TSTree_search(node, "TESTNO", strlen("TESTNO"));
+ mu_assert(res == NULL, "Should not find anything.");
+
+ return NULL;
+}
+
+char *test_search_prefix()
+{
+ void *res = TSTree_search_prefix(
+ node, bdata(&test2), blength(&test2));
+ debug("result: %p, expected: %p", res, valueA);
+ mu_assert(res == valueA, "Got wrong valueA by prefix.");
+
+
+ res = TSTree_search_prefix(node, bdata(&test3), blength(&test3));
+ debug("result: %p, expected: %p", res, valueA);
+ mu_assert(res == value4, "Got wrong value4 for prefix of 1.");
+
+ res = TSTree_search_prefix(node, "TE", strlen("TE"));
+ mu_assert(res == value4, "Should find for short prefix");
+
+ res = TSTree_search_prefix(node, "TE--", strlen("TE--"));
+ mu_assert(res == value4, "Should find for partial prefix.");
+
+ return NULL;
+}
+
+char *test_collect()
+{
+ DArray *arr = TSTree_collect(node, "TE", strlen("TE"));
+ mu_assert(DArray_count(arr) == 2, "Must collect TEST & TEST2");
+ DArray_destroy(arr);
+
+ arr = TSTree_collect(node, "T", strlen("T"));
+ mu_assert(DArray_count(arr) == 4, "Must collect all keys");
+ DArray_destroy(arr);
+
+ return NULL;
+}
+
+void TSTree_traverse_test_cb(void *value, void *data)
+{
+ assert(value != NULL && "Should not get NULL value.");
+ assert(data == valueA && "Expecting valueA as the data.");
+ traverse_count++;
+}
+
+char *test_traverse()
+{
+ traverse_count = 0;
+ TSTree_traverse(node, TSTree_traverse_test_cb, valueA);
+ debug("traverse count is: %d", traverse_count);
+ mu_assert(traverse_count == 4, "Didn't find 4 keys.");
+
+ return NULL;
+}
+
+char *test_destroy()
+{
+ TSTree_destroy(node);
+
+ return NULL;
+}
+
+char *all_tests()
+{
+ mu_suite_start();
+
+ mu_run_test(test_insert);
+ mu_run_test(test_search_exact);
+ mu_run_test(test_search_prefix);
+ mu_run_test(test_collect);
+ mu_run_test(test_traverse);
+ mu_run_test(test_destroy);
+
+ return NULL;
+}
+
+RUN_TESTS(all_tests);