#include <errno.h>
#include "unittest.h"
#include "cuckoo.h"
#include "util.h"
#include "libpmemobj.h"
#define TEST_INSERTS 100
#define TEST_VAL(x) ((void *)((uintptr_t)(x)))
static int Rcounter_malloc;
static void *
__wrap_malloc(size_t size)
{
switch (util_fetch_and_add32(&Rcounter_malloc, 1)) {
case 1:
default:
return malloc(size);
case 2:
case 0:
return NULL;
}
}
static void
test_cuckoo_new_delete(void)
{
struct cuckoo *c = NULL;
c = cuckoo_new();
UT_ASSERT(c == NULL);
c = cuckoo_new();
UT_ASSERT(c == NULL);
c = cuckoo_new();
UT_ASSERT(c != NULL);
cuckoo_delete(c);
}
static void
test_insert_get_remove(void)
{
struct cuckoo *c = cuckoo_new();
UT_ASSERT(c != NULL);
for (int i = 0; i < TEST_INSERTS; ++i)
UT_ASSERT(cuckoo_insert(c, i, TEST_VAL(i)) == 0);
for (int i = 0; i < TEST_INSERTS; ++i)
UT_ASSERT(cuckoo_get(c, i) == TEST_VAL(i));
for (int i = 0; i < TEST_INSERTS; ++i)
UT_ASSERT(cuckoo_remove(c, i) == TEST_VAL(i));
for (int i = 0; i < TEST_INSERTS; ++i)
UT_ASSERT(cuckoo_remove(c, i) == NULL);
for (int i = 0; i < TEST_INSERTS; ++i)
UT_ASSERT(cuckoo_get(c, i) == NULL);
cuckoo_delete(c);
}
static uint64_t
rand64(void)
{
return (((uint64_t)rand()) << 32) | rand();
}
#define NVALUES (100000)
#define TEST_VALUE ((void *)0x1)
#define INITIAL_SEED 54321
static void
test_load_factor(void)
{
struct cuckoo *c = cuckoo_new();
UT_ASSERT(c != NULL);
srand(INITIAL_SEED);
float avg_load = 0.f;
rand64();
int inserted = 0;
for (int i = 0; ; ++i) {
if (cuckoo_insert(c, rand64() % NVALUES, TEST_VALUE) == 0) {
inserted++;
avg_load += (float)inserted / cuckoo_get_size(c);
if (inserted == NVALUES)
break;
}
}
avg_load /= inserted;
UT_ASSERT(avg_load >= 0.4f);
cuckoo_delete(c);
}
int
main(int argc, char *argv[])
{
START(argc, argv, "obj_cuckoo");
Malloc = __wrap_malloc;
test_cuckoo_new_delete();
test_insert_get_remove();
test_load_factor();
DONE(NULL);
}