All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #13 PR #13
341 lines
15 KiB
C
341 lines
15 KiB
C
/**
|
|
* @file test_hashtable.c
|
|
* @author rick
|
|
* @date 27.07.22
|
|
* @brief Test for the HashTable implementation
|
|
*/
|
|
|
|
#include "waitui/hashtable_generic.h"
|
|
#include "waitui/hashtable_generic_impl.h"
|
|
|
|
#include "../../bdd-for-c-ext.h"
|
|
|
|
typedef struct value {
|
|
int count;
|
|
int i;
|
|
} value;
|
|
|
|
static value *value_new(int i) {
|
|
value *this = calloc(1, sizeof(*this));
|
|
if (!this) { return NULL; }
|
|
this->i = i;
|
|
return this;
|
|
}
|
|
|
|
static void value_destroy(value **this) {
|
|
if (!this || !(*this)) { return; }
|
|
free(*this);
|
|
*this = NULL;
|
|
}
|
|
|
|
static int value_check_counter(value *this, int *count) {
|
|
if (!this) { return 0; }
|
|
return this->count == *count;
|
|
}
|
|
|
|
CREATE_HASHTABLE_TYPE(INTERFACE, value)
|
|
CREATE_HASHTABLE_TYPE(IMPLEMENTATION, value)
|
|
|
|
spec("hashtable") {
|
|
context("use as a normal hashtable with no forced collisions") {
|
|
static value_hashtable *hashtable = NULL;
|
|
|
|
before_each() {
|
|
hashtable = value_hashtable_new(42);
|
|
check(hashtable != NULL, "hashtable should not be NULL");
|
|
}
|
|
|
|
after_each() {
|
|
value_hashtable_destroy(&hashtable);
|
|
check(hashtable == NULL, "hashtable should be NULL");
|
|
}
|
|
|
|
describe("value_hashtable_insert()") {
|
|
for_it(
|
|
"should add values to the end of the list and it should be there",
|
|
params_format(2, "start: %d", "elements: %d"),
|
|
format_args(test_param.start, test_param.count),
|
|
{
|
|
int start;
|
|
int count;
|
|
},
|
|
test_params(
|
|
{0, 0},
|
|
{0, 1},
|
|
{1, 1},
|
|
{4, 20},
|
|
)
|
|
) {
|
|
for (int i = test_param.start; i < test_param.start + test_param.count; ++i) {
|
|
str key = STR_NULL_INIT;
|
|
value *value = NULL;
|
|
|
|
STR_SNPRINTF(&key, "key-%d", i);
|
|
check(key.s != NULL, "key.s should be not NULL");
|
|
|
|
check(value_hashtable_has(hashtable, key) == 0, "hashtable should not have the key already");
|
|
check(value_hashtable_insert(hashtable, key, value_new(i)) == 1);
|
|
check(value_hashtable_has(hashtable, key) == 1, "hashtable should have the key");
|
|
value = value_hashtable_lookup(hashtable, key);
|
|
check(value != NULL, "value should not be NULL");
|
|
check(value->i == i, "value should be %d but is %d", i, value->i);
|
|
|
|
STR_FREE(&key);
|
|
}
|
|
|
|
for (int i = test_param.start + test_param.count - 1; i >= test_param.start; --i) {
|
|
str key = STR_NULL_INIT;
|
|
value *value = NULL;
|
|
|
|
STR_SNPRINTF(&key, "key-%d", i);
|
|
check(key.s != NULL, "key.s should be not NULL");
|
|
|
|
value = value_hashtable_lookup(hashtable, key);
|
|
check(value != NULL, "value should not be NULL");
|
|
check(value->i == i, "value should be %d but is %d", i, value->i);
|
|
|
|
STR_FREE(&key);
|
|
}
|
|
}
|
|
for_it_end();
|
|
|
|
it("should work with the empty str") {
|
|
str key = STR_STATIC_INIT("");
|
|
|
|
check(value_hashtable_has(hashtable, key) == 0, "hashtable should not have the key already");
|
|
check(value_hashtable_insert(hashtable, key, value_new(1337)) == 1);
|
|
check(value_hashtable_has(hashtable, key) == 1, "hashtable should have the key");
|
|
}
|
|
|
|
it("should not work with the str having NULL as string") {
|
|
str key = STR_NULL_INIT;
|
|
value *value = value_new(1337);
|
|
check(value_hashtable_insert(hashtable, key, value) == 0);
|
|
check(value != NULL, "value should not be NULL");
|
|
value_destroy(&value);
|
|
}
|
|
|
|
it("should return 0 with NULL as this param") {
|
|
str key = STR_STATIC_INIT("leet");
|
|
value *value = value_new(1);
|
|
check(value_hashtable_insert(NULL, key, value) == 0, "return should be 0");
|
|
check(value != NULL, "value should not be NULL");
|
|
value_destroy(&value);
|
|
}
|
|
|
|
it("should not allow double entry") {
|
|
str key = STR_STATIC_INIT("42");
|
|
|
|
check(value_hashtable_has(hashtable, key) == 0, "hashtable should not have the key already");
|
|
check(value_hashtable_insert(hashtable, key, value_new(1337)) == 1);
|
|
check(value_hashtable_has(hashtable, key) == 1, "hashtable should have the key");
|
|
|
|
value *value = value_new(1337);
|
|
check(value_hashtable_insert(hashtable, key, value) == 0, "return should be 0");
|
|
check(value != NULL, "value should not be NULL");
|
|
value_destroy(&value);
|
|
}
|
|
}
|
|
|
|
describe("value_hashtable_insertCheck()") {
|
|
it("should allow a double insert when check test the value and returns true") {
|
|
int counter;
|
|
str key = STR_STATIC_INIT("foo");
|
|
|
|
value *value1 = value_new(1337);
|
|
value1->count = 0;
|
|
|
|
value *value2 = value_new(7331);
|
|
value2->count = 1;
|
|
|
|
value *resultValue = NULL;
|
|
|
|
counter = 0;
|
|
|
|
check(value_hashtable_insertCheck(hashtable, key, value1, (value_hashtable_value_check_fn) value_check_counter, &counter) == 1);
|
|
check(value_hashtable_hasCheck(hashtable, key, (value_hashtable_value_check_fn) value_check_counter, &counter) == 1);
|
|
check(value_hashtable_insertCheck(hashtable, key, value1, (value_hashtable_value_check_fn) value_check_counter, &counter) == 0);
|
|
|
|
counter = 1;
|
|
|
|
check(value_hashtable_insertCheck(hashtable, key, value2, (value_hashtable_value_check_fn) value_check_counter, &counter) == 1);
|
|
check(value_hashtable_hasCheck(hashtable, key, (value_hashtable_value_check_fn) value_check_counter, &counter) == 1);
|
|
check(value_hashtable_insertCheck(hashtable, key, value2, (value_hashtable_value_check_fn) value_check_counter, &counter) == 0);
|
|
|
|
counter = 0;
|
|
resultValue = value_hashtable_lookupCheck(hashtable, key, (value_hashtable_value_check_fn) value_check_counter, &counter);
|
|
check(resultValue != NULL, "resultValue should not be NULL");
|
|
check(resultValue->i == 1337, "resultValue->i should be %d", 1337);
|
|
check(resultValue->count == 0, "resultValue->count should be %d", 0);
|
|
|
|
counter = 1;
|
|
resultValue = value_hashtable_lookupCheck(hashtable, key, (value_hashtable_value_check_fn) value_check_counter, &counter);
|
|
check(resultValue != NULL, "resultValue should not be NULL");
|
|
check(resultValue->i == 7331, "resultValue->i should be %d", 7331);
|
|
check(resultValue->count == 1, "resultValue->count should be %d", 1);
|
|
check(value_hashtable_markStolenCheck(hashtable, key, (value_hashtable_value_check_fn) value_check_counter, &counter) == 1);
|
|
check(value_hashtable_isStolenCheck(hashtable, key, (value_hashtable_value_check_fn) value_check_counter, &counter) == 1);
|
|
value_destroy(&resultValue);
|
|
}
|
|
}
|
|
|
|
describe("value_hashtable_destroy()") {
|
|
it("should work with NULL as this param") {
|
|
value_hashtable_destroy(NULL);
|
|
}
|
|
|
|
it("should work with a pointer to NULL as this param") {
|
|
static value_hashtable *empty = NULL;
|
|
value_hashtable_destroy(&empty);
|
|
check(empty == NULL, "empty should be NULL");
|
|
}
|
|
}
|
|
|
|
describe("value_hashtable_lookup()") {
|
|
it("should work with the empty str") {
|
|
str key = STR_STATIC_INIT("");
|
|
value *value = value_hashtable_lookup(hashtable, key);
|
|
check(value == NULL, "value should be NULL");
|
|
}
|
|
|
|
it("should not work with the str having NULL as string") {
|
|
str key = STR_NULL_INIT;
|
|
value *value = value_hashtable_lookup(hashtable, key);
|
|
check(value == NULL, "value should be NULL");
|
|
}
|
|
|
|
it("should return NULL with NULL as this param") {
|
|
str key = STR_STATIC_INIT("leet");
|
|
value *value = value_hashtable_lookup(NULL, key);
|
|
check(value == NULL, "value should be NULL");
|
|
}
|
|
}
|
|
|
|
describe("value_hashtable_markStolen()") {
|
|
it("should mark the value for the given key as stolen") {
|
|
str key = STR_STATIC_INIT("leet");
|
|
value *value = NULL;
|
|
check(value_hashtable_has(hashtable, key) == 0,"hashtable should not have the key already");
|
|
check(value_hashtable_insert(hashtable, key, value_new(1337)) == 1);
|
|
check(value_hashtable_has(hashtable, key) == 1, "hashtable should have the key");
|
|
value = value_hashtable_lookup(hashtable, key);
|
|
check(value != NULL, "value should not be NULL");
|
|
check(value_hashtable_markStolen(hashtable, key) == 1, "hashtable should mark the value for the key as stolen");
|
|
check(value_hashtable_isStolen(hashtable, key) == 1, "hashtable should have the value for the key marked as stolen");
|
|
value_destroy(&value);
|
|
}
|
|
|
|
it("should return 0 the given key that is not existing") {
|
|
str keyExists = STR_STATIC_INIT("other");
|
|
check(value_hashtable_insert(hashtable, keyExists, value_new(1337)) == 1);
|
|
str key = STR_STATIC_INIT("leet");
|
|
check(value_hashtable_has(hashtable, key) == 0,"hashtable should not have the key already");
|
|
check(value_hashtable_markStolen(hashtable, key) == 0, "hashtable should mark the value for the key as stolen");
|
|
}
|
|
|
|
it("should work with the empty str") {
|
|
str key = STR_STATIC_INIT("");
|
|
value *value = NULL;
|
|
check(value_hashtable_insert(hashtable, key, value_new(1337)) == 1);
|
|
value = value_hashtable_lookup(hashtable, key);
|
|
check(value != NULL, "value should not be NULL");
|
|
check(value_hashtable_markStolen(hashtable, key) == 1, "return should be 1");
|
|
value_destroy(&value);
|
|
}
|
|
|
|
it("should not work with the str having NULL as string") {
|
|
str key = STR_NULL_INIT;
|
|
check(value_hashtable_markStolen(hashtable, key) == 0, "return should be 0");
|
|
}
|
|
|
|
it("should return 0 with NULL as this param") {
|
|
str key = STR_STATIC_INIT("leet");
|
|
check(value_hashtable_markStolen(NULL, key) == 0, "return should be 0");
|
|
}
|
|
}
|
|
|
|
describe("value_hashtable_has()") {
|
|
it("should work with the empty str") {
|
|
str key = STR_STATIC_INIT("");
|
|
check(value_hashtable_insert(hashtable, key, value_new(1337)) == 1);
|
|
check(value_hashtable_has(hashtable, key) == 1, "return should be 1");
|
|
}
|
|
|
|
it("should not work with the str having NULL as string") {
|
|
str key = STR_NULL_INIT;
|
|
check(value_hashtable_has(hashtable, key) == 0, "return should be 0");
|
|
}
|
|
|
|
it("should return NULL with NULL as this param") {
|
|
str key = STR_STATIC_INIT("leet");
|
|
check(value_hashtable_has(NULL, key) == 0, "return should be 0");
|
|
}
|
|
}
|
|
|
|
describe("value_hashtable_isStolen()") {
|
|
it("should work with the empty str") {
|
|
str key = STR_STATIC_INIT("");
|
|
check(value_hashtable_insert(hashtable, key, value_new(1337)) == 1);
|
|
check(value_hashtable_isStolen(hashtable, key) == 0, "return should be 0");
|
|
}
|
|
|
|
it("should not work with the str having NULL as string") {
|
|
str key = STR_NULL_INIT;
|
|
check(value_hashtable_isStolen(hashtable, key) == 0, "return should be 0");
|
|
}
|
|
|
|
it("should return NULL with NULL as this param") {
|
|
str key = STR_STATIC_INIT("leet");
|
|
check(value_hashtable_isStolen(NULL, key) == 0, "return should be 0");
|
|
}
|
|
|
|
it("should return 0 with a not stolen value") {
|
|
str key = STR_STATIC_INIT("test");
|
|
str otherKey1 = STR_STATIC_INIT("otherKey1");
|
|
check(value_hashtable_insert(hashtable, otherKey1, value_new(1337)) == 1);
|
|
check(value_hashtable_isStolen(hashtable, key) == 0, "return should be 0");
|
|
}
|
|
}
|
|
}
|
|
|
|
context("use as a normal hashtable with forced collisions") {
|
|
static value_hashtable *hashtable = NULL;
|
|
|
|
before_each() {
|
|
hashtable = value_hashtable_new(2);
|
|
check(hashtable != NULL, "hashtable should not be NULL");
|
|
}
|
|
|
|
after_each() {
|
|
value_hashtable_destroy(&hashtable);
|
|
check(hashtable == NULL, "hashtable should be NULL");
|
|
}
|
|
|
|
describe("value_hashtable_markStolen()") {
|
|
it("should mark the value for the given key as stolen") {
|
|
str key = STR_STATIC_INIT("leet");
|
|
str otherKey1 = STR_STATIC_INIT("otherKey1");
|
|
str otherKey2 = STR_STATIC_INIT("otherKey2");
|
|
str otherKey3 = STR_STATIC_INIT("otherKey3");
|
|
str otherKey4 = STR_STATIC_INIT("otherKey4");
|
|
value *value = NULL;
|
|
|
|
check(value_hashtable_has(hashtable, key) == 0,"hashtable should not have the key already");
|
|
check(value_hashtable_insert(hashtable, key, value_new(1337)) == 1);
|
|
check(value_hashtable_has(hashtable, key) == 1, "hashtable should have the key");
|
|
|
|
check(value_hashtable_insert(hashtable, otherKey1, value_new(1337)) == 1);
|
|
check(value_hashtable_insert(hashtable, otherKey2, value_new(1337)) == 1);
|
|
check(value_hashtable_insert(hashtable, otherKey3, value_new(1337)) == 1);
|
|
check(value_hashtable_insert(hashtable, otherKey4, value_new(1337)) == 1);
|
|
|
|
value = value_hashtable_lookup(hashtable, key);
|
|
check(value != NULL, "value should not be NULL");
|
|
check(value_hashtable_markStolen(hashtable, key) == 1, "hashtable should mark the value for the key as stolen");
|
|
check(value_hashtable_isStolen(hashtable, key) == 1, "hashtable should have the value for the key marked as stolen");
|
|
value_destroy(&value);
|
|
}
|
|
}
|
|
}
|
|
}
|