test: update tests to use new API

generic-data-trie
Jef Roosens 2022-12-07 12:56:31 +01:00
parent 50ebf86589
commit a153c4e22d
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
4 changed files with 124 additions and 75 deletions

View File

@ -26,9 +26,17 @@ TrieExitCode trie_init(Trie **trie_ptr, const char *file_path) {
// Allocate & initialize trie // Allocate & initialize trie
Trie *trie = calloc(1, sizeof(Trie)); Trie *trie = calloc(1, sizeof(Trie));
trie->root = tnode_init(); trie->root = tnode_init();
trie->file_path = strdup(file_path);
pthread_rwlock_init(&trie->lock, NULL); pthread_rwlock_init(&trie->lock, NULL);
*trie_ptr = trie;
if (file_path == NULL) {
trie->file_path = NULL;
return Ok;
}
trie->file_path = strdup(file_path);
// Populate trie with data from file // Populate trie with data from file
FILE *fp = fopen(file_path, "r"); FILE *fp = fopen(file_path, "r");
@ -75,8 +83,6 @@ TrieExitCode trie_init(Trie **trie_ptr, const char *file_path) {
fclose(fp); fclose(fp);
*trie_ptr = trie;
return Ok; return Ok;
} }
@ -265,6 +271,7 @@ TrieExitCode trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
} }
TrieExitCode trie_add(Trie *trie, const char *key, Entry *entry) { TrieExitCode trie_add(Trie *trie, const char *key, Entry *entry) {
if (trie->file_path != NULL) {
// Easiest way to make sure we don't add duplicate entries // Easiest way to make sure we don't add duplicate entries
// We use an internal function that doesn't require a read lock, as we're // We use an internal function that doesn't require a read lock, as we're
// already inside a write lock // already inside a write lock
@ -286,6 +293,7 @@ TrieExitCode trie_add(Trie *trie, const char *key, Entry *entry) {
fputs("\n", fp); fputs("\n", fp);
fclose(fp); fclose(fp);
}
// This function *should* always return Ok. Otherwise, the function would've // This function *should* always return Ok. Otherwise, the function would've
// exited because the string was found in the trie. // exited because the string was found in the trie.

View File

@ -5,6 +5,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "trie.h"
typedef struct fuzzyconfig { typedef struct fuzzyconfig {
int seed; int seed;
@ -74,7 +75,7 @@ char** init_string_matrix(int count, int len) {
* @param size_func function to get the size of the given trie * @param size_func function to get the size of the given trie
* @return exit code describing failures, if any * @return exit code describing failures, if any
*/ */
int fuzzy_test_trie_seed(FuzzyConfig conf, void* (*init_func) (), void (*free_func) (void*), bool (*add_func) (void*, char*, void*), bool (*remove_func) (void*, char*), size_t (*size_func) (void*)) { int fuzzy_test_trie_seed(FuzzyConfig conf) {
srand(conf.seed); srand(conf.seed);
char** matrix = init_string_matrix(conf.word_count, conf.word_length); char** matrix = init_string_matrix(conf.word_count, conf.word_length);
@ -100,9 +101,11 @@ int fuzzy_test_trie_seed(FuzzyConfig conf, void* (*init_func) (), void (*free_fu
// also correct // also correct
size_t size = 0; size_t size = 0;
void* ct = init_func(); Trie *ct;
trie_init(&ct, NULL);
bool changed; bool changed;
TrieExitCode status;
// 0: success // 0: success
// 1: invalid add // 1: invalid add
@ -113,13 +116,13 @@ int fuzzy_test_trie_seed(FuzzyConfig conf, void* (*init_func) (), void (*free_fu
// Add all strings to trie, checking for duplicates // Add all strings to trie, checking for duplicates
for (int i = 0; i < conf.word_count; i++) { for (int i = 0; i < conf.word_count; i++) {
changed = add_func(ct, matrix[i], NULL); status = trie_add(ct, matrix[i], NULL);
// if changed is false, *contains_dedupped[i] should be true, as changed // if changed is false, *contains_dedupped[i] should be true, as changed
// can only be false if the string is already contained in the trie. if // can only be false if the string is already contained in the trie. if
// changed is true, *contains_dedupped[i] should be false, as the string // changed is true, *contains_dedupped[i] should be false, as the string
// cannot be in the trie yet. // cannot be in the trie yet.
if (changed == *contains_dedupped[i]) { if (status == Ok && *contains_dedupped[i]) {
exit_code = 1; exit_code = 1;
goto END; goto END;
} }
@ -131,8 +134,8 @@ int fuzzy_test_trie_seed(FuzzyConfig conf, void* (*init_func) (), void (*free_fu
} }
// Ensure size is correct // Ensure size is correct
if (size_func(ct) != size) { if (trie_size(ct) != size) {
printf("%i %i\n", size_func(ct), size); printf("%i %i\n", trie_size(ct), size);
exit_code = 3; exit_code = 3;
goto END; goto END;
} }
@ -160,7 +163,7 @@ int fuzzy_test_trie_seed(FuzzyConfig conf, void* (*init_func) (), void (*free_fu
/* } */ /* } */
END: END:
free_func(ct); trie_free(ct);
// Even testing functions should properly free memory // Even testing functions should properly free memory
free(contains); free(contains);

View File

@ -5,62 +5,104 @@
#define TEST_SIZE(ct, size) \ #define TEST_SIZE(ct, size) \
TEST_CHECK(trie_size(ct) == size); \ TEST_CHECK(trie_size(ct) == size); \
TEST_MSG("Size: %zu", trie_size(ct)) TEST_MSG("Size: %zu", trie_size(ct))
\
# define TRIE_INIT() \
Trie *ct; \
trie_init(&ct, NULL); \
TEST_CHECK(ct != NULL)
void test_init() { void test_init() {
Trie* ct = trie_init(); TRIE_INIT();
TEST_CHECK(ct != NULL);
TEST_SIZE(ct, 0); TEST_SIZE(ct, 0);
trie_free(ct); trie_free(ct);
} }
void test_add_one() { void test_add_one() {
Trie* ct = trie_init(); TRIE_INIT();
TEST_CHECK(ct != NULL);
Entry *entry = entry_new(Redirect, ""); Entry *entry = entry_new(Redirect, "");
const char* string = "this is a test"; const char* string = "this is a test";
TEST_CHECK(trie_add(ct, string, entry)); TEST_CHECK(trie_add(ct, string, entry) == Ok);
TEST_CHECK(trie_search(ct, string) == entry); Entry *entry2;
TEST_CHECK(trie_search(ct, &entry2, string) == Ok);
TEST_CHECK(entry == entry2);
TEST_SIZE(ct, 1); TEST_SIZE(ct, 1);
trie_free(ct); trie_free(ct);
} }
void test_search_not_present() { void test_add_prefix() {
Trie* ct = trie_init(); TRIE_INIT();
TEST_CHECK(ct != NULL);
const char *s1 = "halloween-2022";
const char *s2 = "halloween-202";
Entry *entry1 = entry_new(Redirect, "");
Entry *entry2 = entry_new(Redirect, "");
TEST_CHECK(trie_add(ct, s1, entry1) == Ok);
TEST_CHECK(trie_add(ct, s2, entry2) == Ok);
Entry *entry3;
TEST_CHECK(trie_search(ct, &entry3, s1) == Ok);
TEST_CHECK(entry3 == entry1);
entry2 = NULL;
TEST_CHECK(trie_search(ct, &entry3, s2) == Ok);
TEST_CHECK(entry3 == entry2);
trie_free(ct);
}
void test_search_not_present() {
TRIE_INIT();
TEST_CHECK(trie_add(ct, "this string exists", NULL) == Ok);
Entry *entry;
TEST_CHECK(trie_search(ct, &entry, "this string does not exist") == NotFound);
TEST_CHECK(trie_add(ct, "this string exists", NULL));
TEST_CHECK(trie_search(ct, "this string does not exist") == NULL);
trie_free(ct); trie_free(ct);
} }
void test_add_more() { void test_add_more() {
Trie* ct = trie_init(); TRIE_INIT();
TEST_CHECK(ct != NULL);
const char* one = "one"; const char* one = "one";
const char* two = "two"; const char* two = "two";
const char* twenty = "twenty"; const char* twenty = "twenty";
const char* twentytwo = "twentytwo"; const char* twentytwo = "twentytwo";
Entry *entry = entry_new(Redirect, ""); Entry *entry = entry_new(Redirect, "");
TEST_CHECK(trie_add(ct, one, entry)); TEST_CHECK(trie_add(ct, one, entry) == Ok);
TEST_CHECK(trie_add(ct, two, entry)); TEST_CHECK(trie_add(ct, two, entry) == Ok);
TEST_CHECK(trie_add(ct, twenty, entry)); TEST_CHECK(trie_add(ct, twenty, entry) == Ok);
TEST_CHECK(trie_add(ct, twentytwo, entry)); TEST_CHECK(trie_add(ct, twentytwo, entry) == Ok);
TEST_SIZE(ct, 4); TEST_SIZE(ct, 4);
TEST_CHECK(trie_search(ct, one) == entry); Entry *entry2;
TEST_CHECK(trie_search(ct, two) == entry); TEST_CHECK(trie_search(ct, &entry2, one) == Ok);
TEST_CHECK(trie_search(ct, twenty) == entry); TEST_CHECK(entry2 == entry);
TEST_CHECK(trie_search(ct, twentytwo) == entry); entry2 = NULL;
TEST_CHECK(!trie_add(ct, one, NULL)); TEST_CHECK(trie_search(ct, &entry2, two) == Ok);
TEST_CHECK(!trie_add(ct, two, NULL)); TEST_CHECK(entry2 == entry);
TEST_CHECK(!trie_add(ct, twenty, NULL)); entry2 = NULL;
TEST_CHECK(!trie_add(ct, twentytwo, NULL));
TEST_CHECK(trie_search(ct, &entry2, twenty) == Ok);
TEST_CHECK(entry2 == entry);
entry2 = NULL;
TEST_CHECK(trie_search(ct, &entry2, twentytwo) == Ok);
TEST_CHECK(entry2 == entry);
entry2 = NULL;
TEST_CHECK(trie_add(ct, one, NULL) == AlreadyPresent);
TEST_CHECK(trie_add(ct, two, NULL) == AlreadyPresent);
TEST_CHECK(trie_add(ct, twenty, NULL) == AlreadyPresent);
TEST_CHECK(trie_add(ct, twentytwo, NULL) == AlreadyPresent);
trie_free(ct); trie_free(ct);
} }
@ -127,9 +169,7 @@ void test_fuzzy_set() {
int res; int res;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
res = fuzzy_test_trie_seed(configs[i], trie_init, res = fuzzy_test_trie_seed(configs[i]);
trie_free, trie_add_no_lock,
NULL, trie_size);
TEST_CHECK_(res == 0, TEST_CHECK_(res == 0,
"Failed config, seed = %i, len = %i, count = %i, code=%i", configs[i].seed, configs[i].word_length, configs[i].word_count, res); "Failed config, seed = %i, len = %i, count = %i, code=%i", configs[i].seed, configs[i].word_length, configs[i].word_count, res);
} }

View File

@ -19,9 +19,7 @@ void test_fuzzy() {
config.word_length = len; config.word_length = len;
config.word_count = count; config.word_count = count;
res = fuzzy_test_trie_seed(config, trie_init, res = fuzzy_test_trie_seed(config);
trie_free, trie_add_no_lock,
NULL, trie_size);
TEST_CHECK_(res == 0, TEST_CHECK_(res == 0,
"Failed config, seed = %i, len = %i, count = %i, code = %i", config.seed, config.word_length, config.word_count, res); "Failed config, seed = %i, len = %i, count = %i, code = %i", config.seed, config.word_length, config.word_count, res);
} }