summaryrefslogtreecommitdiffstats
path: root/tests/test_pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_pool.c')
-rw-r--r--tests/test_pool.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/tests/test_pool.c b/tests/test_pool.c
new file mode 100644
index 0000000..2c75688
--- /dev/null
+++ b/tests/test_pool.c
@@ -0,0 +1,150 @@
+// Tests for pool.h - memory pool allocation and free-list operations
+#define POOL_IMPLEMENTATION
+#include "../include/pool.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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;
+}