From f8217d240d598f39f70047f7a623dd46312542c6 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 4 Dec 2021 16:01:12 -0800 Subject: Initial commit. --- listpool/test/listpool_test.c | 166 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 listpool/test/listpool_test.c (limited to 'listpool/test/listpool_test.c') diff --git a/listpool/test/listpool_test.c b/listpool/test/listpool_test.c new file mode 100644 index 0000000..cb54d00 --- /dev/null +++ b/listpool/test/listpool_test.c @@ -0,0 +1,166 @@ +#include "listpool.h" + +#include "test.h" + +#define NUM_BLOCKS 10 + +DEF_LISTPOOL(test_pool, int, NUM_BLOCKS); + +static int count(test_pool* pool) { + int count = 0; + listpool_foreach(pool, n, { count++; }); + return count; +} + +static int sum(test_pool* pool) { + int sum = 0; + listpool_foreach(pool, n, { sum += *n; }); + return sum; +} + +// Create a pool. +TEST_CASE(listpool_create) { + test_pool pool; + listpool_make(&pool); +} + +// Allocate all N blocks. +TEST_CASE(listpool_fully_allocate) { + test_pool pool; + listpool_make(&pool); + + for (int i = 0; i < NUM_BLOCKS; ++i) { + const int* block = listpool_alloc(&pool); + TEST_TRUE(block != 0); + } +} + +// Allocate all N blocks, then free them. +TEST_CASE(listpool_fill_then_free) { + test_pool pool; + listpool_make(&pool); + + int* blocks[NUM_BLOCKS] = {0}; + for (int i = 0; i < NUM_BLOCKS; i++) { + blocks[i] = listpool_alloc(&pool); + TEST_TRUE(blocks[i] != 0); + } + + for (int i = 0; i < NUM_BLOCKS; i++) { + listpool_free(&pool, &blocks[i]); + TEST_EQUAL(blocks[i], 0); // Pointer should be set to 0 on free. + } + + TEST_EQUAL(count(&pool), 0); +} + +// Attempt to allocate blocks past the maximum pool size. +// The pool should handle the failed allocations gracefully. +TEST_CASE(listpool_allocate_beyond_max_size) { + test_pool pool; + listpool_make(&pool); + + // Fully allocate the pool. + for (int i = 0; i < NUM_BLOCKS; ++i) { + TEST_TRUE(listpool_alloc(&pool) != 0); + } + + // Past the end. + for (int i = 0; i < NUM_BLOCKS; ++i) { + TEST_EQUAL(listpool_alloc(&pool), 0); + } +} + +// Free blocks should always remain zeroed out. +// This tests the invariant right after creating the pool. +TEST_CASE(listpool_zero_free_blocks_after_creation) { + test_pool pool; + listpool_make(&pool); + + const int zero = 0; + for (int i = 0; i < NUM_BLOCKS; ++i) { + const int* block = (const int*)(pool.blocks) + i; + TEST_EQUAL(memcmp(block, &zero, sizeof(int)), 0); + } +} + +// Free blocks should always remain zeroed out. +// This tests the invariant after freeing a block. +TEST_CASE(listpool_zero_free_block_after_free) { + test_pool pool; + listpool_make(&pool); + + int* val = listpool_alloc(&pool); + TEST_TRUE(val != 0); + *val = 177; + + int* old_val = val; + listpool_free(&pool, &val); // val pointer is set to 0. + TEST_EQUAL(*old_val, 0); // Block is zeroed out after free. +} + +// Traverse an empty pool. +TEST_CASE(listpool_traverse_empty) { + test_pool pool; + listpool_make(&pool); + + TEST_EQUAL(count(&pool), 0); +} + +// Traverse a partially full pool. +TEST_CASE(listpool_traverse_partially_full) { + const int N = NUM_BLOCKS / 2; + + test_pool pool; + listpool_make(&pool); + + for (int i = 0; i < N; ++i) { + int* val = listpool_alloc(&pool); + TEST_TRUE(val != 0); + *val = i + 1; + } + + TEST_EQUAL(sum(&pool), (N) * (N + 1) / 2); +} + +// Traverse a full pool. +TEST_CASE(listpool_traverse_full) { + test_pool pool; + listpool_make(&pool); + + for (int i = 0; i < NUM_BLOCKS; ++i) { + int* val = listpool_alloc(&pool); + TEST_TRUE(val != 0); + *val = i + 1; + } + + TEST_EQUAL(sum(&pool), (NUM_BLOCKS) * (NUM_BLOCKS + 1) / 2); +} + +// Remove a value from the list. +TEST_CASE(listpool_remove_value) { + test_pool pool; + listpool_make(&pool); + + int* x = listpool_alloc(&pool); + int* y = listpool_alloc(&pool); + TEST_TRUE(x != 0); + TEST_TRUE(y != 0); + + *x = 155; + *y = 177; + + listpool_remove(&pool, 155); // x + + TEST_EQUAL(count(&pool), 1); + TEST_EQUAL(sum(&pool), *y); +} + +// Stress test. +// +// 1. Allocate the pool, either fully or partially. If fully, attempt to +// allocate some items past the end. +// +// 2. Free all allocated items in some random order. + +int main() { return 0; } -- cgit v1.2.3