From bf19b9938508f70011395f4dc283ca758ec6a8d3 Mon Sep 17 00:00:00 2001 From: Ethan Werner Date: Sat, 19 Sep 2026 06:09:54 +0000 Subject: llm tooling --- tests/test_stack.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 tests/test_stack.c (limited to 'tests/test_stack.c') diff --git a/tests/test_stack.c b/tests/test_stack.c new file mode 100644 index 0000000..8fc19a3 --- /dev/null +++ b/tests/test_stack.c @@ -0,0 +1,234 @@ +// Tests for stack.h - stack push, pop, peek, and resizing operations +#include +#include + +typedef double stack_value_t; + +#define STACK_IMPLEMENTATION +#include "../include/stack.h" + +#define EPS 1e-9 + +#define ASSERT(cond, msg) \ + do { \ + if (!(cond)) { \ + fprintf(stderr, "FAIL: %s (test_stack.c:%d)\n", msg, __LINE__); \ + failures++; \ + } \ + } while (0) + +#define ASSERT_FLOAT_EQ(a, b, msg) \ + do { \ + if (fabs((a) - (b)) > EPS) { \ + fprintf(stderr, "FAIL: %s (got %f, expected %f) (test_stack.c:%d)\n", \ + msg, (double)(a), (double)(b), __LINE__); \ + failures++; \ + } \ + } while (0) + +static int failures = 0; + +void test_init_and_free() { + stack_t s = {.capacity = 10}; + stack_init(&s); + ASSERT(s.size == 0, "init size should be 0"); + ASSERT(s.capacity == 10, "init capacity should be 10"); + ASSERT(s.data != NULL, "init data should not be NULL"); + stack_free(&s); +} + +void test_default_capacity() { + stack_t s = {0}; + stack_init(&s); + ASSERT(s.capacity == 16, "default capacity should be 16"); + stack_free(&s); +} + +void test_push_pop() { + stack_t s = {0}; + stack_init(&s); + + for (int i = 0; i < 5; i++) { + stack_push(&s, (stack_value_t)(i * 10)); + } + + ASSERT(s.size == 5, "size after 5 pushes"); + ASSERT_FLOAT_EQ(stack_pop(&s), 40, "pop last pushed"); + ASSERT_FLOAT_EQ(stack_pop(&s), 30, "pop second last"); + ASSERT(s.size == 3, "size after 2 pops"); + + stack_free(&s); +} + +void test_peek() { + stack_t s = {0}; + stack_init(&s); + stack_push(&s, 42); + + ASSERT_FLOAT_EQ(stack_peek(&s), 42, "peek returns top"); + ASSERT(s.size == 1, "peek does not change size"); + + stack_free(&s); +} + +void test_peek_empty() { + stack_t s = {0}; + stack_init(&s); + ASSERT_FLOAT_EQ(stack_peek(&s), 0, "peek empty returns ZERO"); + stack_free(&s); +} + +void test_pop_empty() { + stack_t s = {0}; + stack_init(&s); + ASSERT_FLOAT_EQ(stack_pop(&s), 0, "pop empty returns ZERO"); + stack_free(&s); +} + +void test_grow() { + stack_t s = {.capacity = 2}; + stack_init(&s); + + for (int i = 0; i < 10; i++) { + stack_push(&s, (stack_value_t)i); + } + + ASSERT(s.size == 10, "size after growing"); + ASSERT(s.capacity >= 10, "capacity grew"); + + for (int i = 9; i >= 0; i--) { + ASSERT_FLOAT_EQ(stack_pop(&s), (stack_value_t)i, "values preserved after grow"); + } + + stack_free(&s); +} + +void test_clear() { + stack_t s = {0}; + stack_init(&s); + stack_push(&s, 1); + stack_push(&s, 2); + stack_push(&s, 3); + + stack_clear(&s); + ASSERT_FLOAT_EQ(s.data[0], 0, "clear zeroed data[0]"); + ASSERT_FLOAT_EQ(s.data[1], 0, "clear zeroed data[1]"); + ASSERT_FLOAT_EQ(s.data[2], 0, "clear zeroed data[2]"); + + stack_free(&s); +} + +void test_from_array() { + stack_value_t arr[] = {1, 2, 3, 4, 5}; + stack_t s = {0}; + stack_from_array(&s, arr, 5); + + ASSERT(s.size == 5, "from_array size"); + ASSERT(s.capacity == 5, "from_array capacity"); + + for (int i = 4; i >= 0; i--) { + ASSERT_FLOAT_EQ(stack_pop(&s), (stack_value_t)(i + 1), "from_array values"); + } + + stack_free(&s); +} + +void test_empty() { + stack_t s = {0}; + stack_init(&s); + ASSERT(stack_empty(&s) == 1, "empty stack returns true"); + stack_push(&s, 42); + ASSERT(stack_empty(&s) == 0, "non-empty stack returns false"); + stack_free(&s); +} + +void test_from_array_single() { + stack_value_t arr[] = {42}; + stack_t s = {0}; + stack_from_array(&s, arr, 1); + + ASSERT(s.size == 1, "from_array single size"); + ASSERT(s.capacity == 1, "from_array single capacity"); + ASSERT_FLOAT_EQ(stack_pop(&s), 42, "from_array single value"); + + stack_free(&s); +} + +void test_multiple_free() { + stack_t s = {0}; + stack_init(&s); + stack_free(&s); + ASSERT(s.data == NULL, "data is NULL after free"); + ASSERT(s.size == 0, "size is 0 after free"); + ASSERT(s.capacity == 0, "capacity is 0 after free"); + stack_free(&s); + ASSERT(s.data == NULL, "second free is safe"); +} + +void test_pop_ok() { + stack_t s = {0}; + stack_init(&s); + + stack_value_t out = 0; + ASSERT(!stack_pop_ok(&s, &out), "pop_ok on empty returns 0"); + + stack_push(&s, 42); + ASSERT(stack_pop_ok(&s, &out), "pop_ok on non-empty returns 1"); + ASSERT_FLOAT_EQ(out, 42, "pop_ok value"); + ASSERT(s.size == 0, "pop_ok decrements size"); + + stack_free(&s); +} + +void test_peek_ok() { + stack_t s = {0}; + stack_init(&s); + + stack_value_t out = 0; + ASSERT(!stack_peek_ok(&s, &out), "peek_ok on empty returns 0"); + + stack_push(&s, 99); + ASSERT(stack_peek_ok(&s, &out), "peek_ok on non-empty returns 1"); + ASSERT_FLOAT_EQ(out, 99, "peek_ok value"); + ASSERT(s.size == 1, "peek_ok does not change size"); + + stack_free(&s); +} + +void test_pop_ok_null_out() { + stack_t s = {0}; + stack_init(&s); + stack_push(&s, 1); + ASSERT(!stack_pop_ok(&s, NULL), "pop_ok with NULL out returns 0"); + stack_free(&s); +} + +void test_peek_ok_null_out() { + stack_t s = {0}; + stack_init(&s); + stack_push(&s, 1); + ASSERT(!stack_peek_ok(&s, NULL), "peek_ok with NULL out returns 0"); + stack_free(&s); +} + +int main() { + test_init_and_free(); + test_default_capacity(); + test_push_pop(); + test_peek(); + test_peek_empty(); + test_pop_empty(); + test_pop_ok(); + test_peek_ok(); + test_pop_ok_null_out(); + test_peek_ok_null_out(); + test_grow(); + test_clear(); + test_from_array(); + test_from_array_single(); + test_empty(); + test_multiple_free(); + + printf("test_stack: %d failures\n", failures); + return failures; +} -- cgit v1.3.1