From: Mike D. Lowis Date: Thu, 1 Oct 2015 16:41:20 +0000 (-0400) Subject: Added tests for delete and tweaked the API a bit X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=6ee9c4b0e6e161aee90467aa2bb94436e365fee6;p=archive%2Fcarl.git Added tests for delete and tweaked the API a bit --- diff --git a/build.ninja b/build.ninja index 306242d..9a98d49 100644 --- a/build.ninja +++ b/build.ninja @@ -1,9 +1,9 @@ CC = gcc DEPSUFFIX = .d CPPFLAGS = -Isource/ -Imodules/atf/source -CFLAGS = -g -O3 -Wall -Wextra --std=c99 --pedantic --coverage +CFLAGS = -g -O3 -Wall -Wextra --std=c99 --pedantic LD = gcc -LDFLAGS = --coverage +LDFLAGS = AR = ar ARFLAGS = rcs diff --git a/source/data/hash.c b/source/data/hash.c index 7d613fb..7fadd12 100644 --- a/source/data/hash.c +++ b/source/data/hash.c @@ -7,7 +7,7 @@ #include #include -#define NUM_PRIMES (sizeof(primes)/sizeof(unsigned int)) +#define NUM_PRIMES (sizeof(Primes)/sizeof(unsigned int)) static unsigned int Primes[] = { 5, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, @@ -33,22 +33,24 @@ static void find_entry(hash_t* hash, hash_entry_t** parent, hash_entry_t** curre static void rehash(hash_t* hash) { - unsigned int oldcount = hash->bkt_count++; - hash_entry_t** oldbuckets = hash->buckets; - hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count)); - hash->size = 0; - /* Iterate over all of the old buckets */ - for (unsigned int i = 0; i < num_buckets(oldcount); i++) { - hash_entry_t* node = oldbuckets[i]; - /* re-insert all entries in the bucket into the new bucket table */ - while (node != NULL) { - hash_entry_t* entry = node; - node = entry->next; - hash_set(hash, entry); + if ((hash->bkt_count+1) < NUM_PRIMES) { + unsigned int oldcount = hash->bkt_count++; + hash_entry_t** oldbuckets = hash->buckets; + hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count)); + hash->size = 0; + /* Iterate over all of the old buckets */ + for (unsigned int i = 0; i < num_buckets(oldcount); i++) { + hash_entry_t* node = oldbuckets[i]; + /* re-insert all entries in the bucket into the new bucket table */ + while (node != NULL) { + hash_entry_t* entry = node; + node = entry->next; + hash_set(hash, entry); + } } + /* Free the old bucket table */ + free(oldbuckets); } - /* Free the old bucket table */ - free(oldbuckets); } void hash_init(hash_t* hash, hash_hashfn_t hashfn, hash_cmpfn_t cmpfn, hash_freefn_t delfn) @@ -72,7 +74,7 @@ size_t hash_size(hash_t* hash) return hash->size; } -bool hash_set(hash_t* hash, hash_entry_t* entry) +void hash_set(hash_t* hash, hash_entry_t* entry) { if (hash->size >= num_buckets(hash->bkt_count)) rehash(hash); @@ -101,7 +103,6 @@ bool hash_set(hash_t* hash, hash_entry_t* entry) } if (deadite != NULL) hash->delfn(deadite); - return true; } hash_entry_t* hash_get(hash_t* hash, hash_entry_t* entry) @@ -132,24 +133,22 @@ bool hash_del(hash_t* hash, hash_entry_t* entry) hash->buckets[index] = node; hash->delfn(deadite); ret = true; + hash->size--; } return ret; } void hash_clr(hash_t* hash) { - /* Delete all the entries in the hash */ + /* Delete all the entries in the hash */ for (unsigned int i = 0; i < num_buckets(hash->bkt_count); i++) { hash_entry_t* node = hash->buckets[i]; + hash->buckets[i] = NULL; while (node != NULL) { hash_entry_t* deadite = node; node = node->next; hash->delfn(deadite); } } - /* Shrink the buckets array */ - free(hash->buckets); - hash->bkt_count = 0; - hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count)); } diff --git a/source/data/hash.h b/source/data/hash.h index 3a22bab..0c9f54f 100644 --- a/source/data/hash.h +++ b/source/data/hash.h @@ -34,7 +34,7 @@ void hash_deinit(hash_t* hash); size_t hash_size(hash_t* hash); -bool hash_set(hash_t* hash, hash_entry_t* entry); +void hash_set(hash_t* hash, hash_entry_t* entry); hash_entry_t* hash_get(hash_t* hash, hash_entry_t* entry); diff --git a/tests/data/hash.c b/tests/data/hash.c index fb0883e..e77a43f 100644 --- a/tests/data/hash.c +++ b/tests/data/hash.c @@ -1,4 +1,3 @@ - // Unit Test Framework Includes #include "atf.h" @@ -106,4 +105,74 @@ TEST_SUITE(Hash) { } hash_deinit(&hash); } + + TEST(Verify sequential inserts and deletions) + { + uint maxval = 1000000; + hash_t hash; + hash_init(&hash, hash_func, compare_func, delete_func); + for (uint i = 0; i < maxval; i++) + { + int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t)); + entry->val = i; + hash_set(&hash, &(entry->link)); + CHECK(i+1 == hash_size(&hash)); + CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); + } + for (uint i = 0; i < maxval; i++) + { + int_node_t search = { .val = i }; + CHECK(hash_del(&hash, &(search.link))); + CHECK((maxval - (i+1)) == hash_size(&hash)); + } + hash_deinit(&hash); + } + + TEST(Verify reverse inserts and deletions) + { + uint maxval = 1000000; + hash_t hash; + hash_init(&hash, hash_func, compare_func, delete_func); + for (uint i = 0; i < maxval; i++) + { + int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t)); + entry->val = maxval - i; + hash_set(&hash, &(entry->link)); + CHECK(i+1 == hash_size(&hash)); + CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); + } + for (uint i = 0; i < maxval; i++) + { + int_node_t search = { .val = i+1 }; + CHECK(hash_del(&hash, &(search.link))); + CHECK((maxval - (i+1)) == hash_size(&hash)); + } + hash_deinit(&hash); + } + + TEST(Verify ping pong hash inserts and deletions) + { + uint maxval = 1000000; + hash_t hash; + hash_init(&hash, hash_func, compare_func, delete_func); + for (uint i = 0; i < (maxval/2); i++) { + /* Insert the lower number */ + int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t)); + entry->val = i; + hash_set(&hash, &(entry->link)); + CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); + /* Insert the higher number */ + entry = (int_node_t*)malloc(sizeof(int_node_t)); + entry->val = maxval - i; + hash_set(&hash, &(entry->link)); + CHECK(&(entry->link) == hash_get(&hash, &(entry->link))); + } + for (uint i = 0; i < maxval; i++) + { + int_node_t search = { .val = i }; + if (hash_get(&hash, &(search.link))) + CHECK(hash_del(&hash, &(search.link))); + } + hash_deinit(&hash); + } }