#include <stic.h> #include <stddef.h> /* NULL */ #include <stdlib.h> /* free() malloc() */ #include <string.h> /* memset() strdup() */ #include "../../src/utils/trie.h" static char * make_large_key(char filler, int len); TEST(freeing_new_trie_is_ok) { trie_t *const trie = trie_create(/*free_func=*/NULL); assert_non_null(trie); trie_free(trie); } TEST(freeing_null_trie_is_ok) { trie_free(NULL); } TEST(put_returns_zero_for_new_string) { trie_t *const trie = trie_create(/*free_func=*/NULL); assert_int_equal(0, trie_put(trie, "str")); trie_free(trie); } TEST(put_returns_positive_number_for_existing_string) { trie_t *const trie = trie_create(/*free_func=*/NULL); assert_int_equal(0, trie_put(trie, "str")); assert_true(trie_put(trie, "str") > 0); trie_free(trie); } TEST(multiple_puts) { trie_t *const trie = trie_create(/*free_func=*/NULL); assert_int_equal(0, trie_put(trie, "str")); assert_int_equal(0, trie_put(trie, "astr")); assert_int_equal(0, trie_put(trie, "string")); assert_int_equal(0, trie_put(trie, "strong")); assert_int_equal(0, trie_put(trie, "xxx")); assert_true(trie_put(trie, "str") > 0); assert_int_equal(0, trie_put(trie, "st")); assert_int_equal(0, trie_put(trie, "s")); assert_true(trie_put(trie, "astr") > 0); assert_int_equal(0, trie_put(trie, "ast")); assert_int_equal(0, trie_put(trie, "as")); assert_int_equal(0, trie_put(trie, "a")); assert_true(trie_put(trie, "string") > 0); assert_int_equal(0, trie_put(trie, "strin")); assert_int_equal(0, trie_put(trie, "stri")); assert_true(trie_put(trie, "strong") > 0); assert_int_equal(0, trie_put(trie, "stron")); assert_int_equal(0, trie_put(trie, "stro")); assert_true(trie_put(trie, "xxx") > 0); assert_int_equal(0, trie_put(trie, "xx")); assert_int_equal(0, trie_put(trie, "x")); trie_free(trie); } TEST(empty_string_cannot_be_added) { trie_t *const trie = trie_create(/*free_func=*/NULL); assert_int_equal(-1, trie_put(trie, "")); trie_free(trie); } TEST(utf8) { trie_t *const trie = trie_create(/*free_func=*/NULL); assert_int_equal(0, trie_put(trie, "строка")); assert_int_equal(0, trie_put(trie, "string")); assert_true(trie_put(trie, "строка") > 0); assert_true(trie_put(trie, "string") > 0); trie_free(trie); } TEST(put_sets_data_to_null) { trie_t *const trie = trie_create(/*free_func=*/NULL); void *data = trie; assert_int_equal(0, trie_put(trie, "str")); assert_success(trie_get(trie, "str", &data)); assert_null(data); trie_free(trie); } TEST(get_returns_previously_set_data) { trie_t *const trie = trie_create(/*free_func=*/NULL); void *data; assert_int_equal(0, trie_set(trie, "str", trie)); assert_success(trie_get(trie, "str", &data)); assert_true(data == trie); trie_free(trie); } TEST(set_overwrites_previous_data) { trie_t *const trie = trie_create(/*free_func=*/NULL); void *data = NULL; assert_int_equal(0, trie_set(trie, "str", trie)); assert_true(trie_set(trie, "str", &data) > 0); assert_success(trie_get(trie, "str", &data)); assert_true(data == &data); trie_free(trie); } TEST(free_with_data_removes_data) { /* The check is implicit, external tool should check that no memory leak is * created. */ trie_t *const trie = trie_create(&free); assert_true(trie_set(trie, "str", strdup("str")) == 0); assert_true(trie_set(trie, "something", strdup("something")) == 0); trie_free(trie); } TEST(cloning_null_trie_is_ok) { assert_true(trie_clone(NULL) == NULL); } TEST(trie_cloning_works) { trie_t *const trie = trie_create(/*free_func=*/NULL); trie_t *clone; assert_int_equal(0, trie_put(trie, "str")); clone = trie_clone(trie); assert_true(trie_put(clone, "str") > 0); assert_int_equal(0, trie_put(clone, "string")); assert_int_equal(0, trie_put(trie, "string")); trie_free(clone); trie_free(trie); } TEST(assign_to_existing_prefix) { trie_t *const trie = trie_create(/*free_func=*/NULL); void *data = NULL; assert_success(trie_put(trie, "bcd")); assert_success(trie_get(trie, "bcd", &data)); assert_success(trie_put(trie, "bd")); assert_success(trie_get(trie, "bd", &data)); assert_success(trie_get(trie, "bcd", &data)); trie_free(trie); } TEST(huge_keys) { char *a_key = make_large_key('a', 32768); char *b_key = make_large_key('b', 12345); trie_t *const trie = trie_create(/*free_func=*/NULL); void *data = NULL; /* One large key works. */ assert_success(trie_put(trie, a_key)); assert_success(trie_get(trie, a_key, &data)); /* Use a small key. */ assert_success(trie_put(trie, "small")); assert_success(trie_get(trie, "small", &data)); /* Another large key works. */ assert_success(trie_put(trie, b_key)); assert_success(trie_get(trie, b_key, &data)); /* Small one again. */ assert_success(trie_put(trie, "short")); assert_success(trie_get(trie, "short", &data)); /* The first one is still there. */ assert_success(trie_get(trie, a_key, &data)); trie_free(trie); free(a_key); free(b_key); } static char * make_large_key(char filler, int len) { char *key = malloc(len + 1); /* assert_non_null() weirdly causes `'key' may be used uninitialized` (is it * about data not being initialized?). */ assert_true(key != NULL); memset(key, filler, len); key[len] = '\0'; return key; } /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set cinoptions+=t0 filetype=c : */