#include "unittest.h"
static int custom_allocs;
static int custom_alloc_calls;
static void *
malloc_custom(size_t size)
{
++custom_alloc_calls;
++custom_allocs;
return malloc(size);
}
static void
free_custom(void *ptr)
{
++custom_alloc_calls;
--custom_allocs;
free(ptr);
}
static void *
realloc_custom(void *ptr, size_t size)
{
++custom_alloc_calls;
return realloc(ptr, size);
}
static char *
strdup_custom(const char *s)
{
++custom_alloc_calls;
++custom_allocs;
return strdup(s);
}
int
main(int argc, char *argv[])
{
char *dir = NULL;
VMEM *vmp;
int *ptr;
int test_case = -1;
int expect_custom_alloc = 0;
START(argc, argv, "vmem_valgrind");
if (argc >= 2 && argc <= 3) {
test_case = atoi(argv[1]);
if (test_case > 9)
test_case = -1;
if (argc > 2)
dir = argv[2];
}
if (test_case < 0)
UT_FATAL("usage: %s <test-number from 0 to 9> [directory]",
argv[0]);
if (test_case < 5) {
UT_OUT("use default allocator");
expect_custom_alloc = 0;
} else {
UT_OUT("use custom alloc functions");
test_case -= 5;
expect_custom_alloc = 1;
vmem_set_funcs(malloc_custom, free_custom,
realloc_custom, strdup_custom, NULL);
}
if (dir == NULL) {
void *mem_pool = MMAP_ANON_ALIGNED(VMEM_MIN_POOL, 4 << 20);
vmp = vmem_create_in_region(mem_pool, VMEM_MIN_POOL);
if (vmp == NULL)
UT_FATAL("!vmem_create_in_region");
} else {
vmp = vmem_create(dir, VMEM_MIN_POOL);
if (vmp == NULL)
UT_FATAL("!vmem_create");
}
switch (test_case) {
case 0: {
UT_OUT("remove all allocations and delete pool");
ptr = vmem_malloc(vmp, sizeof(int));
if (ptr == NULL)
UT_FATAL("!vmem_malloc");
vmem_free(vmp, ptr);
vmem_delete(vmp);
break;
}
case 1: {
UT_OUT("only remove allocations");
ptr = vmem_malloc(vmp, sizeof(int));
if (ptr == NULL)
UT_FATAL("!vmem_malloc");
vmem_free(vmp, ptr);
break;
}
case 2: {
UT_OUT("only delete pool");
ptr = vmem_malloc(vmp, sizeof(int));
if (ptr == NULL)
UT_FATAL("!vmem_malloc");
vmem_delete(vmp);
ptr = NULL;
break;
}
case 3: {
UT_OUT("memory leaks");
ptr = vmem_malloc(vmp, sizeof(int));
if (ptr == NULL)
UT_FATAL("!vmem_malloc");
ptr = NULL;
vmem_delete(vmp);
break;
}
case 4: {
UT_OUT("heap block overrun");
ptr = vmem_malloc(vmp, 12 * sizeof(int));
if (ptr == NULL)
UT_FATAL("!vmem_malloc");
ptr[12] = 7;
vmem_free(vmp, ptr);
vmem_delete(vmp);
break;
}
default: {
UT_FATAL("!unknown test-number");
}
}
UT_ASSERTeq(custom_allocs, 0);
if (expect_custom_alloc == 0) {
UT_ASSERTeq(custom_alloc_calls, 0);
} else {
UT_ASSERTne(custom_alloc_calls, 0);
}
DONE(NULL);
}