// Tests for pool.h - memory pool allocation and free-list operations #define POOL_IMPLEMENTATION #include "../include/pool.h" #include #include #include #define ASSERT(cond, msg) \ do { \ if (!(cond)) { \ fprintf(stderr, "FAIL: %s (test_pool.c:%d)\n", msg, __LINE__); \ failures++; \ } \ } while (0) static int failures = 0; void test_init_and_fini() { pool_t *p = pool_init(32, 10); ASSERT(p != NULL, "pool_init returns non-NULL"); if (!p) return; ASSERT(p->block_s == 32, "block size"); ASSERT(p->block_n == 10, "block count"); pool_fini(&p); } void test_malloc_and_free() { pool_t *p = pool_init(64, 5); void *b1 = pool_malloc(p); void *b2 = pool_malloc(p); void *b3 = pool_malloc(p); ASSERT(b1 != NULL, "malloc 1"); ASSERT(b2 != NULL, "malloc 2"); ASSERT(b3 != NULL, "malloc 3"); ASSERT(b1 != b2, "malloc returns different blocks"); ASSERT(pool_size(p) == 3, "size after 3 mallocs"); pool_free(p, b2); ASSERT(pool_size(p) == 2, "size after 1 free"); pool_free(p, b1); pool_free(p, b3); ASSERT(pool_size(p) == 0, "size after all frees"); pool_fini(&p); } void test_reuse_freed_block() { pool_t *p = pool_init(32, 3); void *b1 = pool_malloc(p); void *b2 = pool_malloc(p); pool_free(p, b1); void *b3 = pool_malloc(p); ASSERT(b3 == b1, "reuses freed block"); pool_free(p, b2); pool_free(p, b3); pool_fini(&p); } void test_capacity_and_size() { pool_t *p = pool_init(16, 20); ASSERT(pool_capacity(p) == 20, "capacity"); ASSERT(pool_size(p) == 0, "initial size is 0"); pool_malloc(p); pool_malloc(p); ASSERT(pool_size(p) == 2, "size after 2 mallocs"); pool_fini(&p); } void test_exhaust_pool() { pool_t *p = pool_init(16, 2); pool_malloc(p); pool_malloc(p); void *overflow = pool_malloc(p); ASSERT(overflow == NULL, "returns NULL when exhausted"); pool_fini(&p); } void test_write_and_read_block() { pool_t *p = pool_init(32, 1); int32_t *block = pool_malloc(p); ASSERT(block != NULL, "pool_malloc returns non-NULL"); if (!block) { pool_fini(&p); return; } *block = 42; ASSERT(*block == 42, "can write and read block data"); pool_fini(&p); } void test_multiple_free_fini() { pool_t *p = pool_init(16, 1); pool_fini(&p); pool_fini(&p); pool_fini(NULL); } void test_free_invalid_pointer() { pool_t *p = pool_init(32, 3); void *b1 = pool_malloc(p); ASSERT(pool_size(p) == 1, "size before invalid free"); int stack_var; pool_free(p, &stack_var); ASSERT(pool_size(p) == 1, "invalid free rejected (stack ptr)"); pool_free(p, (void *)0x12345678); ASSERT(pool_size(p) == 1, "invalid free rejected (random ptr)"); pool_free(p, NULL); ASSERT(pool_size(p) == 1, "invalid free rejected (NULL)"); pool_free(NULL, b1); ASSERT(pool_size(p) == 1, "invalid free rejected (NULL pool)"); pool_free(p, b1); ASSERT(pool_size(p) == 0, "valid free accepted"); pool_fini(&p); } void test_init_invalid_block_size() { pool_t *p = pool_init(3, 10); ASSERT(p == NULL, "block size < sizeof(void*) returns NULL"); p = pool_init(7, 10); ASSERT(p == NULL, "block size not multiple of sizeof(void*) returns NULL"); } int main() { test_init_and_fini(); test_malloc_and_free(); test_reuse_freed_block(); test_capacity_and_size(); test_exhaust_pool(); test_write_and_read_block(); test_multiple_free_fini(); test_free_invalid_pointer(); test_init_invalid_block_size(); printf("test_pool: %d failures\n", failures); return failures; }