#include "cx/test.h"
#include "util_allocator.h"
#include "cx/mempool.h"
#include <errno.h>
static unsigned test_mempool_destructor_called;
static void test_mempool_destructor(cx_attr_unused
void *mem) {
test_mempool_destructor_called++;
}
static void test_mempool_destructor2(
void *data, cx_attr_unused
void *mem) {
int *ctr = data;
*ctr = *ctr +
1;
}
CX_TEST(test_mempool_create) {
CxMempool *pool = cxMempoolCreateSimple(
16);
CX_TEST_DO {
CX_TEST_ASSERT(pool->destr ==
NULL);
CX_TEST_ASSERT(pool->destr2 ==
NULL);
CX_TEST_ASSERT(pool->destr2_data ==
NULL);
CX_TEST_ASSERT(pool->allocator !=
NULL);
CX_TEST_ASSERT(pool->allocator->cl !=
NULL);
CX_TEST_ASSERT(pool->allocator->data == pool);
CX_TEST_ASSERT(pool->allocator->cl->malloc !=
NULL);
CX_TEST_ASSERT(pool->allocator->cl->calloc !=
NULL);
CX_TEST_ASSERT(pool->allocator->cl->realloc !=
NULL);
CX_TEST_ASSERT(pool->allocator->cl->free !=
NULL);
CX_TEST_ASSERT(pool->capacity ==
16);
CX_TEST_ASSERT(pool->size ==
0);
CX_TEST_ASSERT(pool->data !=
NULL);
}
cxMempoolFree(pool);
}
static CX_TEST_SUBROUTINE(test_mempool_malloc_verify, CxMempool *pool) {
CX_TEST_ASSERT(cxMalloc(pool->allocator,
sizeof(
int)) !=
NULL);
CX_TEST_ASSERT(cxMalloc(pool->allocator,
sizeof(
int)) !=
NULL);
CX_TEST_ASSERT(pool->size ==
2);
CX_TEST_ASSERT(pool->capacity ==
4);
CX_TEST_ASSERT(cxMalloc(pool->allocator,
sizeof(
int)) !=
NULL);
CX_TEST_ASSERT(cxMalloc(pool->allocator,
sizeof(
int)) !=
NULL);
CX_TEST_ASSERT(pool->size ==
4);
CX_TEST_ASSERT(pool->capacity ==
4);
CX_TEST_ASSERT(cxMalloc(pool->allocator,
sizeof(
int)) !=
NULL);
int *i = cxMalloc(pool->allocator,
sizeof(
int));
CX_TEST_ASSERT(i !=
NULL);
*i =
4083914;
CX_TEST_ASSERT(pool->size ==
6);
CX_TEST_ASSERT(pool->capacity >=
6);
}
CX_TEST(test_mempool_malloc0) {
CxMempool *pool = cxMempoolCreatePure(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_malloc_verify, pool);
}
cxMempoolFree(pool);
}
CX_TEST(test_mempool_malloc) {
CxMempool *pool = cxMempoolCreateSimple(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_malloc_verify, pool);
}
cxMempoolFree(pool);
}
CX_TEST(test_mempool_malloc2) {
CxMempool *pool = cxMempoolCreateAdvanced(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_malloc_verify, pool);
}
cxMempoolFree(pool);
}
static CX_TEST_SUBROUTINE(test_mempool_calloc_verify, CxMempool *pool) {
int *test = cxCalloc(pool->allocator,
2,
sizeof(
int));
CX_TEST_ASSERT(test !=
NULL);
CX_TEST_ASSERT(test[
0] ==
0);
CX_TEST_ASSERT(test[
1] ==
0);
#if __GNUC__ >
11
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored
"-Walloc-size-larger-than="
#endif
errno =
0;
CX_TEST_ASSERT(
NULL == cxCalloc(pool->allocator,
SIZE_MAX /
2,
sizeof(
int)));
CX_TEST_ASSERT(errno ==
EOVERFLOW);
#if __GNUC__ >
11
#pragma GCC diagnostic pop
#endif
}
CX_TEST(test_mempool_calloc0) {
CxMempool *pool = cxMempoolCreatePure(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_calloc_verify, pool);
}
cxMempoolFree(pool);
}
CX_TEST(test_mempool_calloc) {
CxMempool *pool = cxMempoolCreateSimple(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_calloc_verify, pool);
}
cxMempoolFree(pool);
}
CX_TEST(test_mempool_calloc2) {
CxMempool *pool = cxMempoolCreateAdvanced(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_calloc_verify, pool);
}
cxMempoolFree(pool);
}
static CX_TEST_SUBROUTINE(test_mempool_realloc_verify, CxMempool *pool,
enum cx_mempool_type type) {
int *data = cxRealloc(pool->allocator,
NULL,
2*
sizeof(
int));
if (type ==
CX_MEMPOOL_TYPE_SIMPLE) {
cxMempoolSetDestructor(data, test_mempool_destructor);
}
else if (type ==
CX_MEMPOOL_TYPE_ADVANCED) {
cxMempoolSetDestructor2(data, test_mempool_destructor2, &test_mempool_destructor_called);
}
*data =
13;
data = cxRealloc(pool->allocator, data,
sizeof(
int));
CX_TEST_ASSERT(*data ==
13);
data = cxRealloc(pool->allocator, data,
sizeof(
int));
CX_TEST_ASSERT(*data ==
13);
int *rdata = data;
unsigned n =
1;
while (rdata == data) {
n <<=
1;
CX_TEST_ASSERTM(n <
65536,
"Reallocation attempt failed - test not executable");
rdata = cxRealloc(pool->allocator, data, n *
sizeof(
intptr_t));
}
CX_TEST_ASSERT(*rdata ==
13);
if (type !=
CX_MEMPOOL_TYPE_PURE) {
test_mempool_destructor_called =
0;
cxFree(pool->allocator, rdata);
CX_TEST_ASSERT(test_mempool_destructor_called ==
1);
}
}
CX_TEST(test_mempool_realloc0) {
CxMempool *pool = cxMempoolCreatePure(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_realloc_verify, pool,
CX_MEMPOOL_TYPE_PURE);
}
cxMempoolFree(pool);
}
CX_TEST(test_mempool_realloc) {
CxMempool *pool = cxMempoolCreateSimple(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_realloc_verify, pool,
CX_MEMPOOL_TYPE_SIMPLE);
}
cxMempoolFree(pool);
}
CX_TEST(test_mempool_realloc2) {
CxMempool *pool = cxMempoolCreateAdvanced(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_realloc_verify, pool,
CX_MEMPOOL_TYPE_ADVANCED);
}
cxMempoolFree(pool);
}
static CX_TEST_SUBROUTINE(test_mempool_free_verify, CxMempool *pool) {
void *mem1, *mem2;
mem1 = cxMalloc(pool->allocator,
16);
cxFree(pool->allocator, mem1);
CX_TEST_ASSERT(pool->size ==
0);
mem1 = cxMalloc(pool->allocator,
16);
mem1 = cxMalloc(pool->allocator,
16);
mem1 = cxMalloc(pool->allocator,
16);
mem2 = cxMalloc(pool->allocator,
16);
mem2 = cxMalloc(pool->allocator,
16);
CX_TEST_ASSERT(pool->size ==
5);
void *freed = cxRealloc(pool->allocator, mem1,
0);
CX_TEST_ASSERT(freed ==
NULL);
CX_TEST_ASSERT(pool->size ==
4);
cxFree(pool->allocator, mem2);
CX_TEST_ASSERT(pool->size ==
3);
}
CX_TEST(test_mempool_free0) {
CxMempool *pool = cxMempoolCreatePure(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_free_verify, pool);
}
cxMempoolFree(pool);
}
CX_TEST(test_mempool_free) {
CxMempool *pool = cxMempoolCreateSimple(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_free_verify, pool);
}
cxMempoolFree(pool);
}
CX_TEST(test_mempool_free2) {
CxMempool *pool = cxMempoolCreateAdvanced(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_free_verify, pool);
}
cxMempoolFree(pool);
}
CX_TEST(test_mempool_destroy) {
CxMempool *pool = cxMempoolCreateSimple(
4);
CX_TEST_DO {
int *data = cxMalloc(pool->allocator,
sizeof(
int));
*data =
13;
cxMempoolSetDestructor(data, test_mempool_destructor);
CX_TEST_ASSERT(*data ==
13);
test_mempool_destructor_called =
0;
cxFree(pool->allocator, data);
CX_TEST_ASSERT(test_mempool_destructor_called ==
1);
data = cxMalloc(pool->allocator,
sizeof(
int));
cxMempoolSetDestructor(data, test_mempool_destructor);
cxMempoolFree(pool);
CX_TEST_ASSERT(test_mempool_destructor_called ==
2);
}
}
CX_TEST(test_mempool_destroy2) {
CxMempool *pool = cxMempoolCreateAdvanced(
4);
CX_TEST_DO {
int *data = cxMalloc(pool->allocator,
sizeof(
int));
int ctr =
0;
*data =
47;
cxMempoolSetDestructor2(data, test_mempool_destructor2, &ctr);
CX_TEST_ASSERT(*data ==
47);
cxFree(pool->allocator, data);
CX_TEST_ASSERT(ctr ==
1);
data = cxMalloc(pool->allocator,
sizeof(
int));
cxMempoolSetDestructor2(data, test_mempool_destructor2, &ctr);
cxMempoolFree(pool);
CX_TEST_ASSERT(ctr ==
2);
}
}
CX_TEST(test_mempool_remove_destructor) {
CxMempool *pool = cxMempoolCreateSimple(
4);
CX_TEST_DO {
int *data = cxMalloc(pool->allocator,
sizeof(
int));
*data =
13;
cxMempoolSetDestructor(data, test_mempool_destructor);
CX_TEST_ASSERT(*data ==
13);
cxMempoolRemoveDestructor(data);
CX_TEST_ASSERT(*data ==
13);
test_mempool_destructor_called =
0;
cxFree(pool->allocator, data);
CX_TEST_ASSERT(test_mempool_destructor_called ==
0);
data = cxMalloc(pool->allocator,
sizeof(
int));
*data =
99;
cxMempoolSetDestructor(data, test_mempool_destructor);
cxMempoolRemoveDestructor(data);
CX_TEST_ASSERT(*data ==
99);
cxMempoolFree(pool);
CX_TEST_ASSERT(test_mempool_destructor_called ==
0);
}
}
CX_TEST(test_mempool_remove_destructor2) {
CxMempool *pool = cxMempoolCreateAdvanced(
4);
CX_TEST_DO {
int *data = cxMalloc(pool->allocator,
sizeof(
int));
int ctr =
0;
*data =
47;
cxMempoolSetDestructor2(data, test_mempool_destructor2, &ctr);
CX_TEST_ASSERT(*data ==
47);
cxMempoolRemoveDestructor2(data);
CX_TEST_ASSERT(*data ==
47);
cxFree(pool->allocator, data);
CX_TEST_ASSERT(ctr ==
0);
data = cxMalloc(pool->allocator,
sizeof(
int));
*data =
99;
cxMempoolSetDestructor2(data, test_mempool_destructor2, &ctr);
cxMempoolRemoveDestructor2(data);
CX_TEST_ASSERT(*data ==
99);
cxMempoolFree(pool);
CX_TEST_ASSERT(ctr ==
0);
}
}
static CX_TEST_SUBROUTINE(test_mempool_global_destructors_verify, CxMempool *pool) {
int *data = cxMalloc(pool->allocator,
sizeof(
int));
int ctr =
0;
cxMempoolGlobalDestructor(pool, test_mempool_destructor);
cxMempoolGlobalDestructor2(pool, test_mempool_destructor2, &ctr);
test_mempool_destructor_called =
0;
cxFree(pool->allocator, data);
CX_TEST_ASSERT(ctr ==
1);
CX_TEST_ASSERT(test_mempool_destructor_called ==
1);
data = cxMalloc(pool->allocator,
sizeof(
int));
cxMempoolFree(pool);
CX_TEST_ASSERT(ctr ==
2);
CX_TEST_ASSERT(test_mempool_destructor_called ==
2);
}
CX_TEST(test_mempool_global_destructors0) {
CxMempool *pool = cxMempoolCreatePure(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_global_destructors_verify, pool);
}
}
CX_TEST(test_mempool_global_destructors) {
CxMempool *pool = cxMempoolCreateSimple(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_global_destructors_verify, pool);
}
}
CX_TEST(test_mempool_global_destructors2) {
CxMempool *pool = cxMempoolCreateAdvanced(
4);
CX_TEST_DO {
CX_TEST_CALL_SUBROUTINE(test_mempool_global_destructors_verify, pool);
}
}
CX_TEST(test_mempool_register) {
CxMempool *pool = cxMempoolCreateAdvanced(
4);
CX_TEST_DO {
int *data = cxMalloc(pool->allocator,
sizeof(
int));
test_mempool_destructor_called =
0;
cxMempoolSetDestructor2(data, test_mempool_destructor2, &test_mempool_destructor_called);
int donotfree =
0;
cxMempoolRegister(pool, &donotfree, test_mempool_destructor);
cxMempoolFree(pool);
CX_TEST_ASSERT(test_mempool_destructor_called ==
2);
}
}
CX_TEST(test_mempool_register2) {
CxMempool *pool = cxMempoolCreateSimple(
4);
CX_TEST_DO {
int *data = cxMalloc(pool->allocator,
sizeof(
int));
test_mempool_destructor_called =
0;
cxMempoolSetDestructor(data, test_mempool_destructor);
int donotfree =
0;
cxMempoolRegister2(pool, &donotfree, test_mempool_destructor2, &test_mempool_destructor_called);
cxMempoolFree(pool);
CX_TEST_ASSERT(test_mempool_destructor_called ==
2);
}
}
CX_TEST(test_mempool_transfer) {
CxMempool *src = cxMempoolCreateSimple(
4);
CxMempool *dest = cxMempoolCreateSimple(
4);
CX_TEST_DO {
int *c = cxMalloc(src->allocator,
sizeof(
int));
cxMempoolSetDestructor(c, test_mempool_destructor);
c = cxMalloc(src->allocator,
sizeof(
int));
cxMempoolSetDestructor(c, test_mempool_destructor);
CX_TEST_ASSERT(src->size ==
2);
CX_TEST_ASSERT(src->registered_size ==
0);
const CxAllocator *old_allocator = src->allocator;
CX_TEST_ASSERT(old_allocator->data == src);
int result = cxMempoolTransfer(src, dest);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(src->size ==
0);
CX_TEST_ASSERT(dest->size ==
2);
CX_TEST_ASSERT(src->registered_size ==
0);
CX_TEST_ASSERT(dest->registered_size ==
1);
CX_TEST_ASSERT(src->allocator != old_allocator);
CX_TEST_ASSERT(old_allocator->data == dest);
test_mempool_destructor_called =
0;
cxMempoolFree(src);
CX_TEST_ASSERT(test_mempool_destructor_called ==
0);
result = cxMempoolTransfer(dest, dest);
CX_TEST_ASSERT(result !=
0);
cxMempoolFree(dest);
CX_TEST_ASSERT(test_mempool_destructor_called ==
2);
}
}
CX_TEST(test_mempool_transfer_with_foreign_memory) {
CxMempool *src = cxMempoolCreateSimple(
4);
CxMempool *dest = cxMempoolCreateSimple(
4);
CX_TEST_DO {
int *c = cxMalloc(src->allocator,
sizeof(
int));
c = cxMalloc(src->allocator,
sizeof(
int));
cxMempoolSetDestructor(c, test_mempool_destructor);
c = malloc(
sizeof(
int));
cxMempoolRegister(src, c, test_mempool_destructor);
CX_TEST_ASSERT(src->size ==
2);
CX_TEST_ASSERT(src->registered_size ==
1);
const CxAllocator *old_allocator = src->allocator;
CX_TEST_ASSERT(old_allocator->data == src);
int result = cxMempoolTransfer(src, dest);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(src->size ==
0);
CX_TEST_ASSERT(dest->size ==
2);
CX_TEST_ASSERT(src->registered_size ==
0);
CX_TEST_ASSERT(dest->registered_size ==
2);
CX_TEST_ASSERT(src->allocator != old_allocator);
CX_TEST_ASSERT(old_allocator->data == dest);
test_mempool_destructor_called =
0;
cxMempoolFree(src);
CX_TEST_ASSERT(test_mempool_destructor_called ==
0);
cxMempoolFree(dest);
CX_TEST_ASSERT(test_mempool_destructor_called ==
2);
free(c);
}
}
CX_TEST(test_mempool_transfer_foreign_memory_only) {
CxMempool *src = cxMempoolCreateSimple(
4);
CxMempool *dest = cxMempoolCreateSimple(
4);
int *a = malloc(
sizeof(
int));
int *b = malloc(
sizeof(
int));
CX_TEST_DO {
cxMempoolRegister(src, a, test_mempool_destructor);
cxMempoolRegister(src, b, test_mempool_destructor);
CX_TEST_ASSERT(src->size ==
0);
CX_TEST_ASSERT(src->registered_size ==
2);
const CxAllocator *old_allocator = src->allocator;
CX_TEST_ASSERT(old_allocator->data == src);
int result = cxMempoolTransfer(src, dest);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(src->size ==
0);
CX_TEST_ASSERT(dest->size ==
0);
CX_TEST_ASSERT(src->registered_size ==
0);
CX_TEST_ASSERT(dest->registered_size ==
3);
CX_TEST_ASSERT(src->allocator != old_allocator);
CX_TEST_ASSERT(old_allocator->data == dest);
test_mempool_destructor_called =
0;
cxMempoolFree(src);
CX_TEST_ASSERT(test_mempool_destructor_called ==
0);
cxMempoolFree(dest);
CX_TEST_ASSERT(test_mempool_destructor_called ==
2);
}
free(a);
free(b);
}
CX_TEST(test_mempool_transfer_object) {
CxMempool *src = cxMempoolCreateSimple(
4);
CxMempool *dest = cxMempoolCreateSimple(
4);
CX_TEST_DO {
int *a = cxMalloc(src->allocator,
sizeof(
int));
int *b = cxMalloc(src->allocator,
sizeof(
int));
int *c = malloc(
sizeof(
int));
cxMempoolRegister(src, c, free);
int *d = malloc(
sizeof(
int));
cxMempoolRegister(src, d, free);
CX_TEST_ASSERT(src->size ==
2);
CX_TEST_ASSERT(src->registered_size ==
2);
int result = cxMempoolTransferObject(src, dest, a);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(src->size ==
1);
CX_TEST_ASSERT(src->registered_size ==
2);
CX_TEST_ASSERT(dest->size ==
1);
CX_TEST_ASSERT(dest->registered_size ==
0);
result = cxMempoolTransferObject(src, dest, a);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(src->size ==
1);
CX_TEST_ASSERT(src->registered_size ==
2);
CX_TEST_ASSERT(dest->size ==
1);
CX_TEST_ASSERT(dest->registered_size ==
0);
result = cxMempoolTransferObject(src, dest, c);
CX_TEST_ASSERT(result ==
0);
CX_TEST_ASSERT(src->size ==
1);
CX_TEST_ASSERT(src->registered_size ==
1);
CX_TEST_ASSERT(dest->size ==
1);
CX_TEST_ASSERT(dest->registered_size ==
1);
result = cxMempoolTransferObject(dest, dest, b);
CX_TEST_ASSERT(result !=
0);
CX_TEST_ASSERT(src->size ==
1);
CX_TEST_ASSERT(dest->size ==
1);
cxFree(src->allocator, b);
}
cxMempoolFree(src);
cxMempoolFree(dest);
}
CxTestSuite *cx_test_suite_mempool(
void) {
CxTestSuite *suite = cx_test_suite_new(
"mempool");
cx_test_register(suite, test_mempool_create);
cx_test_register(suite, test_mempool_malloc0);
cx_test_register(suite, test_mempool_calloc0);
cx_test_register(suite, test_mempool_realloc0);
cx_test_register(suite, test_mempool_free0);
cx_test_register(suite, test_mempool_malloc);
cx_test_register(suite, test_mempool_calloc);
cx_test_register(suite, test_mempool_realloc);
cx_test_register(suite, test_mempool_free);
cx_test_register(suite, test_mempool_destroy);
cx_test_register(suite, test_mempool_malloc2);
cx_test_register(suite, test_mempool_calloc2);
cx_test_register(suite, test_mempool_realloc2);
cx_test_register(suite, test_mempool_free2);
cx_test_register(suite, test_mempool_destroy2);
cx_test_register(suite, test_mempool_remove_destructor);
cx_test_register(suite, test_mempool_remove_destructor2);
cx_test_register(suite, test_mempool_global_destructors0);
cx_test_register(suite, test_mempool_global_destructors);
cx_test_register(suite, test_mempool_global_destructors2);
cx_test_register(suite, test_mempool_register);
cx_test_register(suite, test_mempool_register2);
cx_test_register(suite, test_mempool_transfer);
cx_test_register(suite, test_mempool_transfer_with_foreign_memory);
cx_test_register(suite, test_mempool_transfer_foreign_memory_only);
cx_test_register(suite, test_mempool_transfer_object);
return suite;
}