From b924fc2f66d46ee10aa3b800a6521d3940919f9f Mon Sep 17 00:00:00 2001 From: rsiddharth Date: Fri, 17 Apr 2020 21:02:35 -0400 Subject: nserver/ -> ./ --- tests/darray_algos_tests.c | 102 ++++++++++ tests/darray_tests.c | 361 +++++++++++++++++++++++++++++++++ tests/db_tests.c | 55 +++++ tests/hashmap_tests.c | 311 ++++++++++++++++++++++++++++ tests/minunit.h | 38 ++++ tests/ncmd_tests.c | 492 +++++++++++++++++++++++++++++++++++++++++++++ tests/protocol_tests.c | 202 +++++++++++++++++++ tests/runtests.sh | 19 ++ tests/stats_tests.c | 132 ++++++++++++ tests/tstree_tests.c | 132 ++++++++++++ 10 files changed, 1844 insertions(+) create mode 100644 tests/darray_algos_tests.c create mode 100644 tests/darray_tests.c create mode 100644 tests/db_tests.c create mode 100644 tests/hashmap_tests.c create mode 100644 tests/minunit.h create mode 100644 tests/ncmd_tests.c create mode 100644 tests/protocol_tests.c create mode 100644 tests/runtests.sh create mode 100644 tests/stats_tests.c create mode 100644 tests/tstree_tests.c (limited to 'tests') diff --git a/tests/darray_algos_tests.c b/tests/darray_algos_tests.c new file mode 100644 index 0000000..01ef471 --- /dev/null +++ b/tests/darray_algos_tests.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright © 2010, Zed A. Shaw. + * Copyright © 2020 rsiddharth + */ + +#include "minunit.h" +#include + +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/tests/darray_tests.c b/tests/darray_tests.c new file mode 100644 index 0000000..b33c460 --- /dev/null +++ b/tests/darray_tests.c @@ -0,0 +1,361 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright © 2010, Zed A. Shaw. + * Copyright © 2020 rsiddharth + */ + +#include "minunit.h" +#include + +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/tests/db_tests.c b/tests/db_tests.c new file mode 100644 index 0000000..dce3039 --- /dev/null +++ b/tests/db_tests.c @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright © 2020 rsiddharth + */ + +#include "minunit.h" +#include + +char *test_db_init() +{ + int rc = db_init(); + mu_assert(rc == 0, "db init failed"); + + return NULL; +} + +char *test_db_store() +{ + char *k = "hello"; + char *v = "kirk"; + + int rc = db_store(k, v); + mu_assert(rc == 0, "db store failed"); + + return NULL; +} + +char *test_db_load() +{ + char *k = "hello"; + char *expected_v = "kirk"; + + char *v = db_load(k); + mu_assert(v != NULL, "key not found"); + mu_assert(strncmp(v, expected_v, strlen(expected_v)) == 0, + "incorrect value for key"); + + // cleanup. + free(v); + + return NULL; +} + +char *all_tests() +{ + mu_suite_start(); + + mu_run_test(test_db_init); + mu_run_test(test_db_store); + mu_run_test(test_db_load); + + return NULL; +} + +RUN_TESTS(all_tests); 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 + */ + +#include "minunit.h" +#include +#include +#include + +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/tests/minunit.h b/tests/minunit.h new file mode 100644 index 0000000..4ddf265 --- /dev/null +++ b/tests/minunit.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright © 2010, Zed A. Shaw. + */ + +#undef NDEBUG +#ifndef _minunit_h +#define _minunit_h + +#include +#include +#include + +#define mu_suite_start() char *message = NULL + +#define mu_assert(test, message) if (!(test)) {\ + log_err(message); return message; } +#define mu_run_test(test) debug("\n-----%s", " " #test); \ + message = test(); tests_run++; if (message) return message; + +#define RUN_TESTS(name) int main(int argc, char *argv[]) {\ + argc = 1; \ + debug("----- RUNNING: %s", argv[0]); \ + printf("----\nRUNNING: %s\n", argv[0]);\ + char *result = name();\ + if (result != 0) {\ + printf("FAILED: %s\n", result); \ + }\ + else {\ + printf("ALL TESTS PASSED\n");\ + }\ + printf("Tests run: %d\n", tests_run);\ + exit(result != 0);\ + } + +int tests_run; + +#endif diff --git a/tests/ncmd_tests.c b/tests/ncmd_tests.c new file mode 100644 index 0000000..6174371 --- /dev/null +++ b/tests/ncmd_tests.c @@ -0,0 +1,492 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright © 2020 rsiddharth + */ + +#include "minunit.h" +#include + +char *test_sanitize() +{ + char *cmd = calloc(128, sizeof(char)); + mu_assert(cmd != NULL, "calloc failed"); + + char *c_cmd = "/create api/beef\n"; + size_t c_cmd_sz = strlen(c_cmd); + + strncpy(cmd, c_cmd, c_cmd_sz + 1); + mu_assert(strlen(cmd) == c_cmd_sz, "strncpy failed"); + + sanitize(cmd); + mu_assert(strlen(cmd) == c_cmd_sz - 1, "sanitize failed"); + mu_assert(strcmp(cmd, "/create api/beef") == 0, "sanitize failed"); + + + // Clear cmd. + memset(cmd, '\0', 128); + + + c_cmd = "/create api/ham\n\n\n"; + c_cmd_sz = strlen(c_cmd); + + strncpy(cmd, c_cmd, c_cmd_sz + 1); + mu_assert(strlen(cmd) == c_cmd_sz, "strncpy failed"); + + sanitize(cmd); + mu_assert(strlen(cmd) == c_cmd_sz - 3, "sanitize failed"); + mu_assert(strcmp(cmd, "/create api/ham") == 0, "sanitize failed"); + + + // Clear cmd. + memset(cmd, '\0', 128); + + + c_cmd = "/create api/bacon\n/create api/turkey\n"; + c_cmd_sz = strlen(c_cmd); + + strncpy(cmd, c_cmd, c_cmd_sz + 1); + mu_assert(strlen(cmd) == c_cmd_sz, "strncpy failed"); + + sanitize(cmd); + mu_assert(strlen(cmd) == c_cmd_sz - 20, "sanitize failed"); + mu_assert(strcmp(cmd, "/create api/bacon") == 0, "sanitize failed"); + + + // Cleanup. + free(cmd); + + return NULL; +} + +char *test_check_cmd() +{ + char *err = (char *) calloc(RSP_SIZE, sizeof(char)); + + char *cmd = (char *) calloc(128, sizeof(char)); + mu_assert(cmd != NULL, "calloc failed"); + + char *bacon = "/create api/bacon"; + strncpy(cmd, bacon, strlen(bacon)); + mu_assert(strlen(cmd) == strlen(bacon), "strncpy failed"); + + int rc = check_cmd(cmd, err); + mu_assert(rc == 0, "check_cmd failed"); + + memset(err, '\0', RSP_SIZE); + memset(cmd, '\0', 128); + + char *c = "/c"; + strncpy(cmd, c, strlen(c)); + mu_assert(strlen(cmd) == strlen(c), "strncpy failed"); + + rc = check_cmd(cmd, err); + mu_assert(rc < 0, "check_cmd failed"); + mu_assert(strcmp(err, "command size invalid\n") == 0, + "wrong err msg"); + + memset(err, '\0', RSP_SIZE); + memset(cmd, '\0', 128); + + + char *empty = "\n"; + strncpy(cmd, empty, strlen(empty)); + mu_assert(strlen(cmd) == strlen(empty), "strncpy failed"); + + rc = check_cmd(cmd, err); + mu_assert(rc < 0, "check_cmd failed"); + mu_assert(strcmp(err, "closing connection\n") == 0, + "wrong err msg"); + + + rc = check_cmd(NULL, err); + mu_assert(rc < 0, "check_cmd failed"); + mu_assert(strcmp(err, "internal error\n") == 0, + "wrong err msg"); + + + // Cleanup. + free(err); + free(cmd); + + return NULL; +} + +char *test_cmd_parts() +{ + struct bstrList *parts = NULL; + + bstring create = bfromcstr("/create"); + + char *bacon = "/create bacon"; + parts = cmd_parts(bacon); + mu_assert(parts != NULL, "cmd parts failed"); + mu_assert(parts->qty == 2, "qty check failed"); + mu_assert(bstricmp(parts->entry[0], create) == 0, + "equality check failed"); + + // Cleanup + bstrListDestroy(parts); + + char *ham = "/create ham"; + parts = cmd_parts(ham); + mu_assert(parts != NULL, "cmd parts failed"); + mu_assert(parts->qty == 2, "qty check failed"); + mu_assert(bstricmp(parts->entry[0], create) == 0, + "equality check failed"); + + + // Cleanup + bdestroy(create); + bstrListDestroy(parts); + + return NULL; +} + +char *test_find_function() +{ + struct bstrList *parts = NULL; + int funk = 0; + + char *bacon = "/create bacon"; + parts = cmd_parts(bacon); + mu_assert(parts != NULL, "cmd_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_CREATE, "find function create failed"); + + char *ham = "/create ham"; + parts = cmd_parts(ham); + mu_assert(parts != NULL, "cmd_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_CREATE, "find function create failed"); + + ham = "/CREate ham"; + parts = cmd_parts(ham); + mu_assert(parts != NULL, "cmd_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_CREATE, "find function create failed"); + + char *sample = "/sample bacon 42"; + parts = cmd_parts(sample); + mu_assert(parts != NULL, "cmd_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_SAMPLE, "find function sample failed"); + + sample = "/SAMPLE bacon 42"; + parts = cmd_parts(sample); + mu_assert(parts != NULL, "cmd_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_SAMPLE, "find function sample failed"); + + char *mean = "/mean bacon"; + parts = cmd_parts(mean); + mu_assert(parts != NULL, "cmd_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_MEAN, "find function mean failed"); + + char *dump = "/dump bacon"; + parts = cmd_parts(dump); + mu_assert(parts != NULL, "cmd_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_DUMP, "find function dump failed"); + + char *delete = "/delete bacon"; + parts = cmd_parts(delete); + mu_assert(parts != NULL, "cmd_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_DELETE, "find function delete failed"); + + char *list = "/list"; + parts = cmd_parts(list); + mu_assert(parts != NULL, "cmp_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_LIST, "find function list failed"); + + list = "/LIST"; + parts = cmd_parts(list); + mu_assert(parts != NULL, "cmp_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_LIST, "find function list failed"); + + char *store = "/store jowl"; + parts = cmd_parts(store); + mu_assert(parts != NULL, "cmp_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_STORE, "find function list failed"); + + store = "/STore jowl"; + parts = cmd_parts(store); + mu_assert(parts != NULL, "cmp_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_STORE, "find function list failed"); + + char *load = "/load jowl ears"; + parts = cmd_parts(load); + mu_assert(parts != NULL, "cmp_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_LOAD, "find function list failed"); + + load = "/LoAD jowl ears"; + parts = cmd_parts(load); + mu_assert(parts != NULL, "cmp_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_LOAD, "find function list failed"); + + char *nop = "/meant bacon"; + parts = cmd_parts(nop); + mu_assert(parts != NULL, "cmd_parts failed"); + funk = find_function(parts); + mu_assert(funk == NS_NOP, "find function mean failed"); + + return NULL; +} + +char *test_call_function() +{ + struct bstrList *parts = NULL; + + char *msg = (char *) calloc(RSP_SIZE + 1, sizeof(char)); + mu_assert(msg != NULL, "msg invalid"); + + char *bacon = "/create bacon"; + parts = cmd_parts(bacon); + mu_assert(parts != NULL, "cmd_parts failed"); + int rc = call_function(NS_CREATE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + char *ham = "/create ham"; + parts = cmd_parts(ham); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_CREATE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + char *beef = "/create beef"; + parts = cmd_parts(beef); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_CREATE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + char *bacon_sample = "/sample bacon 4.2"; + parts = cmd_parts(bacon_sample); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_SAMPLE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "Mean: 4.20\n") == 0, "call function failed"); + + bacon_sample = "/Sample bacon 6.9"; + parts = cmd_parts(bacon_sample); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_SAMPLE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "Mean: 5.55\n") == 0, "call function failed"); + + char *bacon_mean = "/mean bacon"; + parts = cmd_parts(bacon_mean); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_MEAN, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "Mean: 5.55\n") == 0, "call function failed"); + + char *bacon_dump = "/dump bacon"; + parts = cmd_parts(bacon_dump); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_DUMP, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "sum: 11.100000, sumsq: 65.250000, n: 2, min: 4.200000, max: 6.900000, mean: 5.550000, stddev: 1.909188\n") == 0, "call function failed"); + + char *bacon_delete = "/delete bacon"; + parts = cmd_parts(bacon_delete); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_DELETE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + char *list = "/list"; + parts = cmd_parts(list); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_LIST, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "ham\nbeef\n") == 0 + || strcmp(msg, "beef\nham\n") == 0, + "call function failed"); + + + char *ham_store = "/store ham"; + parts = cmd_parts(ham_store); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_STORE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + + char *beef_store = "/store beef"; + parts = cmd_parts(beef_store); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_STORE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + char *roastedham_load = "/load ham roastedham"; + parts = cmd_parts(roastedham_load); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_LOAD, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + char *grilledbeef_load = "/load beef grilledbeef"; + parts = cmd_parts(grilledbeef_load); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_LOAD, parts, msg); + printf("LOAD FIAAAL %d %s\n", rc, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + // delete ham, roastedham, beef, and roastedbeef. + char *ham_delete = "/delete ham"; + parts = cmd_parts(ham_delete); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_DELETE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + char *roastedham_delete = "/delete roastedham"; + parts = cmd_parts(roastedham_delete); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_DELETE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + char *beef_delete = "/delete beef"; + parts = cmd_parts(beef_delete); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_DELETE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + char *grilledbeef_delete = "/delete grilledbeef"; + parts = cmd_parts(grilledbeef_delete); + mu_assert(parts != NULL, "cmd_parts failed"); + rc = call_function(NS_DELETE, parts, msg); + mu_assert(rc == 0, "call function failed"); + mu_assert(strcmp(msg, "OK\n") == 0, "call function failed"); + + return NULL; +} + +char *test_process() +{ + char *out = (char *) calloc(RSP_SIZE + 1, sizeof(char)); + mu_assert(out != NULL, "out invalid"); + + char *bacon = "/create bacon"; + int rc = process(bacon, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "OK\n") == 0, "process failed"); + + char *ham = "/create ham"; + rc = process(ham, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "OK\n") == 0, "process failed"); + + char *beef = "/create beef"; + rc = process(beef, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "OK\n") == 0, "process failed"); + + char *ham_sample = "/sample ham 4.3"; + rc = process(ham_sample, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "Mean: 4.30\n") == 0, "process failed"); + + ham_sample = "/sample ham 6.0"; + rc = process(ham_sample, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "Mean: 5.15\n") == 0, "process failed"); + + char *bacon_sample = "/sample bacon 4.2"; + rc = process(bacon_sample, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "Mean: 4.20\n") == 0, "process failed"); + + bacon_sample = "/Sample bacon 6.9"; + rc = process(bacon_sample, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "Mean: 5.55\n") == 0, "process failed"); + + char *bacon_mean = "/mean bacon"; + rc = process(bacon_mean, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "Mean: 5.55\n") == 0, "process failed"); + + char *bacon_dump = "/dump bacon"; + rc = process(bacon_dump, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "sum: 11.100000, sumsq: 65.250000, n: 2, min: 4.200000, max: 6.900000, mean: 5.550000, stddev: 1.909188\n") == 0, "process failed"); + + char *bacon_delete = "/delete bacon"; + rc = process(bacon_delete, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "OK\n") == 0, "process failed"); + + char *list = "/list"; + rc = process(list, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "ham\nbeef\n") == 0 + || strcmp(out, "beef\nham\n") == 0, + "process failed"); + + char *ham_store = "/store ham"; + rc = process(ham_store, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "OK\n") == 0, "process failed"); + + char *beef_store = "/store beef"; + rc = process(beef_store, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "OK\n") == 0, "process failed"); + + char *bacon_store = "/store bacon"; + rc = process(bacon_store, out); + mu_assert(rc == -1, "process failed"); + mu_assert(strcmp(out, "error: store failed\n") == 0, "process failed"); + + char *roastedham_load = "/load ham roastedham"; + rc = process(roastedham_load, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "OK\n") == 0, "process failed"); + + char *roastedham_delete = "/delete roastedham"; + rc = process(roastedham_delete, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "OK\n") == 0, "process failed"); + + roastedham_load = "/load ham roastedham"; + rc = process(roastedham_load, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "OK\n") == 0, "process failed"); + + char *roastedham_dump = "/dump roastedham"; + rc = process(roastedham_dump, out); + mu_assert(rc == 0, "process failed"); + mu_assert(strcmp(out, "sum: 10.300000, sumsq: 54.490000, n: 2, min: 4.300000, max: 6.000000, mean: 5.150000, stddev: 1.202082\n") == 0, "process failed"); + + return NULL; +} + +char *all_tests() +{ + mu_suite_start(); + + mu_run_test(test_sanitize); + mu_run_test(test_check_cmd); + mu_run_test(test_cmd_parts); + mu_run_test(test_find_function); + mu_run_test(test_call_function); + mu_run_test(test_process); + + return NULL; +} + +RUN_TESTS(all_tests); diff --git a/tests/protocol_tests.c b/tests/protocol_tests.c new file mode 100644 index 0000000..62ebec3 --- /dev/null +++ b/tests/protocol_tests.c @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright © 2020 rsiddharth + */ + +#include "minunit.h" +#include + +char *test_sscreate() +{ + int rc = 0; + + rc = sscreate("/crimson"); + mu_assert(rc == 0, "sscreate failed 0"); + + rc = sscreate("/vermilion"); + mu_assert(rc == 0, "sscreate failed 1"); + + rc = sscreate("/crimson"); + mu_assert(rc == 1, "sscreate failed 2"); + + rc = sscreate("/crimson/sky"); + mu_assert(rc == 0, "sscreate failed 3"); + + // delete. check. + rc = ssdelete("/crimson/sky"); + mu_assert(rc == 0, "ssdelete failed 0"); + + rc = sscreate("/crimson/sky"); + mu_assert(rc == 2, "sscreate failed 4"); + + return NULL; +} + +char *test_sssample() +{ + double mean = 0; + + mean = sssample("/crimson", 3); + mu_assert(mean == 3.0, "sssample failed 0"); + + mean = sssample("/crimson", 9); + mu_assert(mean == 6.0, "sssample failed 1"); + + mean = sssample("/crimson", 12); + mu_assert(mean == 8.0, "sssample failed 2"); + + mean = sssample("/vermilion", 20); + mu_assert(mean == 20.0, "sssample failed 3"); + + mean = sssample("/vermilion", 27); + mu_assert(mean == 23.5, "sssample failed 4"); + + mean = sssample("/vermilion", 4); + mu_assert(mean == 17.0, "sssample failed 5"); + + mean = sssample("/ruby", 48); + mu_assert(mean == -1, "sssample failed 6"); + + mean = sssample("/crimson/sky", 42); + mu_assert(mean == 42.0, "sssample failed 7"); + + mean = sssample("/crimson", 10); + mu_assert(mean == 15.20, "sssample failed 8"); + + // delete check. + int rc = ssdelete("/crimson/sky"); + mu_assert(rc == 0, "ssdeleted failed 0"); + + mean = sssample("/crimson/sky", 71); + mu_assert(mean == -1, "sssample failed 9"); + + rc = sscreate("/crimson/sky"); + mu_assert(rc == 2, "sscreate failed 1"); + + mean = sssample("/crimson/sky", 71); + mu_assert(mean == 71.0, "sssample failed 9"); + + + + return NULL; +} + +char *test_ssmean() +{ + double m = 0; + + m = ssmean("/crimson"); + mu_assert(m == 24.50, "ssmean failed 0"); + + m = ssmean("/vermilion"); + mu_assert(m == 17, "ssmean failed 1"); + + m = ssmean("/ruby"); + mu_assert(m == -1, "ssmean failed 2"); + + m = ssmean("/crimson/sky"); + mu_assert(m == 71.0, "ssmean failed 3"); + + // delete check. + int rc = ssdelete("/crimson/sky"); + mu_assert(rc == 0, "ssdeleted failed 0"); + + m = ssmean("/crimson/sky"); + mu_assert(m == -1, "ssmean failed 4"); + + return NULL; +} + +char *test_ssdump() +{ + char *dstr = NULL; + + dstr = ssdump("/crimson"); + mu_assert(dstr != NULL, "ssdump failed 0"); + debug("DUMP: %s", dstr); + + // clean up. + free(dstr); + + dstr = ssdump("/vermilion"); + mu_assert(dstr != NULL, "ssdump failed 1"); + debug("DUMP: %s", dstr); + + // clean up. + free(dstr); + + dstr = ssdump("/ruby"); + mu_assert(dstr == NULL, "ssdump failed 2"); + debug("DUMP: %s", dstr); + + dstr = ssdump("/crimson/sky"); + mu_assert(dstr == NULL, "ssdump failed 2"); + + return NULL; +} + +char *test_sslist() +{ + char *ks = sslist(); + mu_assert(ks != NULL, "sslist failed"); + mu_assert(strlen(ks) == 20, "length check failed"); + + return NULL; +} + +char *test_ssstore() +{ + + int rc = ssstore("/crimson"); + mu_assert(rc == 0, "store /crimson failed"); + + rc = ssstore("/nonexistent"); + mu_assert(rc == -1, "store /nonexistent failed"); + + return NULL; +} + +char *test_ssload() +{ + int rc = ssload("/crimson", "/crimson"); + mu_assert(rc == -2, "ssload failed 0"); + + rc = ssload("/crimson", "/amaranth"); + mu_assert(rc == 0, "ssload failed 1"); + + return NULL; +} + +char *test_ssdelete() +{ + int rc = 0; + + rc = ssdelete("/crimson"); + mu_assert(rc == 0, "delete failed 0"); + + rc = ssdelete("/vermilion"); + mu_assert(rc == 0, "delete failed 1"); + + rc = ssdelete("/ruby"); + mu_assert(rc == 0, "delete failed 2"); + + return NULL; +} + +char *all_tests() +{ + mu_suite_start(); + + mu_run_test(test_sscreate); + mu_run_test(test_sssample); + mu_run_test(test_ssmean); + mu_run_test(test_ssdump); + mu_run_test(test_sslist); + mu_run_test(test_ssstore); + mu_run_test(test_ssload); + mu_run_test(test_ssdelete); + + return NULL; +} + +RUN_TESTS(all_tests); diff --git a/tests/runtests.sh b/tests/runtests.sh new file mode 100644 index 0000000..ff579a3 --- /dev/null +++ b/tests/runtests.sh @@ -0,0 +1,19 @@ +echo "Running unit tests:" + +for i in tests/*_tests +do + if test -f $i + then + if $VALGRIND ./$i 2>> tests/tests.log + then + echo $i PASS + else + echo "ERROR in test $i: here's tests/tests.log" + echo "------" + tail tests/tests.log + exit 1 + fi + fi +done + +echo "" diff --git a/tests/stats_tests.c b/tests/stats_tests.c new file mode 100644 index 0000000..72bee3f --- /dev/null +++ b/tests/stats_tests.c @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright © 2010, Zed A. Shaw. + * Copyright © 2020 rsiddharth + */ + +#include "minunit.h" +#include +#include +#include + +static char *st_str = NULL; + +const int NUM_SAMPLES = 10; +double samples[] = { + 6.1061334, 9.6783204, 1.2747090, 8.2395131, 0.3333483, + 6.9755066, 1.0626275, 7.6587523, 4.9382973, 9.5788115 +}; + +Stats expect = { + .sumsq = 425.1641, + .sum = 55.84602, + .min = 0.333, + .max = 9.678, + .n = 10 +}; + +double expect_mean = 5.584602; +double expect_stddev = 3.547868; + +#define EQ(X,Y,N) (round((X) * pow(10, N)) == round((Y) * pow(10, N))) + +char *test_operations() +{ + int i = 0; + Stats *st = Stats_create(); + mu_assert(st != NULL, "Fail to create stats."); + + for (i = 0; i < NUM_SAMPLES; i++) { + Stats_sample(st, samples[i]); + } + + Stats_dump(st); + + mu_assert(EQ(st->sumsq, expect.sumsq, 3), "sumsq not valid"); + mu_assert(EQ(st->sum, expect.sum, 3), "sum not valid"); + mu_assert(EQ(st->min, expect.min, 3), "min not valid"); + mu_assert(EQ(st->max, expect.max, 3), "max not valid"); + mu_assert(EQ(st->n, expect.n, 3), "n not valid"); + mu_assert(EQ(expect_mean, Stats_mean(st), 3), "mean not valid"); + mu_assert(EQ(expect_stddev, Stats_stddev(st), 3), + "stddev not valid"); + + return NULL; +} + +char *test_recreate() +{ + Stats *st = Stats_recreate( + expect.sum, expect.sumsq, expect.n, expect.min, expect.max); + + mu_assert(st->sum == expect.sum, "sum not equal"); + mu_assert(st->sumsq == expect.sumsq, "sumsq not equal"); + mu_assert(st->n == expect.n, "n not equal"); + mu_assert(st->min == expect.min, "min not equal"); + mu_assert(st->max == expect.max, "max not equal"); + mu_assert(EQ(expect_mean, Stats_mean(st), 3), "mean not valid"); + mu_assert(EQ(expect_stddev, Stats_stddev(st), 3), + "stddev not valid"); + + return NULL; +} + +char *test_stats_stringify() +{ + Stats *st = Stats_create(); + mu_assert(st != NULL, "stats create failed"); + + // fill with dummy data. + st->sum = 8238.33892; + st->sumsq = 4260238.8292; + st->n = 28; + st->min = 28.3921; + st->max = 238.27; + + st_str = Stats_stringify(st); + mu_assert(st_str != NULL, "stats stringify failed"); + + char *expected_st_str = "8238.34:4260238.83:28:28.39:238.27"; + mu_assert(strncmp(st_str, expected_st_str, strlen(expected_st_str)) == 0, + "stringified str invalid"); + + // cleanup + free(st); + + return NULL; +} + +char *test_stats_unstringify() +{ + mu_assert(st_str != NULL, "st_str not initialized"); + + Stats *st = Stats_unstringify(st_str); + mu_assert(st != NULL, "stats unstringify failed"); + + mu_assert(st->sum == 8238.34, "stats sum incorrect"); + mu_assert(st->sumsq == 4260238.83, "stats sumsq incorrect"); + mu_assert(st->n == 28, "stats n incorrect"); + mu_assert(st->min == 28.39, "stats min incorrect"); + mu_assert(st->max == 238.27, "stats max incorrect"); + + // clean up + free(st); + free(st_str); + + return NULL; +} + +char *all_tests() +{ + mu_suite_start(); + + mu_run_test(test_operations); + mu_run_test(test_recreate); + + mu_run_test(test_stats_stringify); + mu_run_test(test_stats_unstringify); + + return NULL; +} + +RUN_TESTS(all_tests); diff --git a/tests/tstree_tests.c b/tests/tstree_tests.c new file mode 100644 index 0000000..d8b5f9f --- /dev/null +++ b/tests/tstree_tests.c @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright © 2010, Zed A. Shaw. + * Copyright © 2020 rsiddharth + */ + +#include "minunit.h" +#include +#include +#include +#include + +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); -- cgit v1.2.3