diff --git a/CuteDNS.files b/CuteDNS.files index 83df21712cb75f6227ddad0c9c9c843bc425d966..cb99e3cb68f708e8b23544778f184b35cfd15c5f 100644 --- a/CuteDNS.files +++ b/CuteDNS.files @@ -37,6 +37,7 @@ src/tests/tests.h src/tests/cuckoo-test.c src/tests/cuckoo-test.h src/tests/server_tests.c +src/tests/skiplist_tests.c src/tests/tap_unit.h src/tests/template_tests.c src/other/log.h diff --git a/src/tests/main.c b/src/tests/main.c index 24ed2ddd87b35d3db83fade1fab8b53a6505dd36..ca535dbd6b2227a5166e626566c2958e38bd6d24 100644 --- a/src/tests/main.c +++ b/src/tests/main.c @@ -3,13 +3,15 @@ // Units to test #include "server_tests.c" +#include "skiplist_tests.c" // Run all loaded units int main(int argc, char * argv[]) { // Build test set unit_api* tests[] = { - &server_tests_api, //! Server unit + &server_tests_api, //! Server unit + &skiplist_tests_api, //! Skip list unit NULL }; @@ -17,6 +19,7 @@ int main(int argc, char * argv[]) int id = 0; int test_count = 0; while(tests[id] != NULL) { + fprintf(stderr, "#test %s : %d tests\n", tests[id]->name, tests[id]->count(argc, argv)); test_count += tests[id]->count(argc, argv); ++id; } diff --git a/src/tests/skiplist_tests.c b/src/tests/skiplist_tests.c new file mode 100644 index 0000000000000000000000000000000000000000..f2f7785bb8dda3c81accdb757d2c95edfbdd42ea --- /dev/null +++ b/src/tests/skiplist_tests.c @@ -0,0 +1,167 @@ +#include "tap_unit.h" +#include "skip-list.h" + +static int skiplist_tests_count(int argc, char * argv[]); +static int skiplist_tests_run(int argc, char * argv[]); + +/* + * Unit API. + */ +unit_api skiplist_tests_api = { + "Skip list", + &skiplist_tests_count, + &skiplist_tests_run +}; + +/* + * Unit implementation. + */ + +static const int SKIPLIST_TEST_COUNT = 5; + +static int skiplist_tests_count(int argc, char *argv[]) +{ + return SKIPLIST_TEST_COUNT; +} + +/* Comparing and merging limited to int keys used in test. + */ +int test_skip_compare_keys( void *key1, void *key2 ) +{ + return ((long)key1 < (long)key2) ? -1 : (((long)key1 > (long)key2) ? 1 : 0); +} + +int test_skip_merge_values( void **lvalue, void **rvalue ) +{ + (*lvalue) = (void *)((long)(*lvalue) + (long)(*rvalue)); + return 0; +} + +int test_skiplist_create(skip_list** list) +{ + *list = skip_create_list(test_skip_compare_keys); + return *list != NULL; +} + +int test_skiplist_fill(skip_list* list, long* uitems, int loops) +{ + int uitem_count = 0; + for (int i = 0; i < loops; ++i) { + long key = rand() % 100 + 1; + long value = rand() % 100 + 1; + int res = skip_insert(list, (void *)key, (void *)value, + test_skip_merge_values); + switch (res) { + case -2: + diag("skiplist: merging failed"); + return 0; + break; + case -1: + diag("skiplist: insert failed"); + return 0; + break; + case 0: + uitems[uitem_count++] = key; + break; + default: + break; + } + } + + return uitem_count; +} + +int test_skiplist_lookup_seq(skip_list* list, long* uitems, int uitems_count) +{ + int errors = 0; + + // Sequential lookup + for(int i = 0; i < uitems_count; ++i) { + void *found = skip_find(list, (void*) uitems[i]); + if(found == NULL) { + diag("skiplist: sequential lookup failed, key: %d", uitems[i]); + ++errors; + } + } + + if(errors) { + diag("skiplist: sequential lookup: %d found %d missed, %.2f%% success rate", + uitems_count - errors, errors, (uitems_count-errors)/(float) uitems_count*100.0); + } + + return errors == 0; +} + +int test_skiplist_lookup_rand(skip_list* list, long* uitems, int uitems_count) +{ + int errors = 0; + srand((unsigned)time(NULL)); + + // Random lookup + for(int i = 0; i < uitems_count; ++i) { + long key = rand() % uitems_count + 1; + void *found = skip_find(list, (void*) key); + if(found == NULL) { + diag("skiplist: random lookup failed, key: %d", uitems[i]); + ++errors; + } + } + + if(errors) { + diag("skiplist: sequential lookup: %d found %d missed, %.2f%% success rate", + uitems_count - errors, errors, (uitems_count-errors)/(float) uitems_count*100.0); + } + return errors == 0; +} + + +int test_skiplist_remove(skip_list* list, long* uitems, int uitems_count) +{ + int errors = 0; + + // delete items + for (int i = 0; i < uitems_count; ++i) { + int res = skip_remove(list, (void *) uitems[i], NULL, NULL); + switch (res) { + case 0: + break; + default: + ++errors; + break; + } + } + + if(errors) { + diag("skiplist: sequential lookup: %d found %d missed, %.2f%% success rate", + uitems_count - errors, errors, (uitems_count-errors)/(float) uitems_count*100.0); + } + return errors == 0; +} + +static int skiplist_tests_run(int argc, char *argv[]) +{ + const int loops = 100; + int uitems_count = 0; + long* uitems = malloc(loops * sizeof(long)); + skip_list* list = 0; + + // Test 1: create + ok(test_skiplist_create(&list), "skiplist: create"); + + // Test 2: fill + ok(uitems_count = test_skiplist_fill(list, uitems, loops), "skiplist: fill"); + + // Test 3: sequential lookup + ok(test_skiplist_lookup_seq(list, uitems, uitems_count), "skiplist: sequential lookup"); + + // Test 4: sequential lookup + ok(test_skiplist_lookup_seq(list, uitems, uitems_count), "skiplist: random lookup lookup"); + + // Test 5: remove items + ok(test_skiplist_remove(list, uitems, uitems_count), "skiplist: random lookup lookup"); + + // Cleanup + skip_destroy_list(&list, NULL, NULL); + free(uitems); + return 0; +}