Files
cKit/Foundation/c_ArrayStack.t.c
T
2026-08-29 11:39:28 +08:00

153 lines
5.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "c_ArrayStack.h"
#include <stdlib.h>
#include <stdio.h>
#include <c_Test.h>
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
static c_ArrayStack_t g_stack;
// 启动环境:初始化一个初始容量为 2 的 int 类型栈
static void setup_stack() {
c_err_t err = c_ArrayStack_Init(&g_stack, sizeof(int), 2);
if (err != C_ERR_OK) {
printf(" " COLOR_RED "[ERROR] Stack Setup failed!" COLOR_RESET "\n");
}
}
// 清理环境:安全销毁栈,杜绝内存泄漏
static void teardown_stack() {
c_ArrayStack_Destroy(&g_stack);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
// 用例 1:测试 LIFO(后进先出)核心逻辑、IsEmpty 状态及 Peek 观察
static void test_stack_push_pop_lifo() {
// 初始状态应该为空
ASSERT_MSG(c_ArrayStack_IsEmpty(&g_stack) == true, "Stack should be empty initially");
int v1 = 111, v2 = 222;
ASSERT_INT_EQ_MSG(C_ERR_OK, c_ArrayStack_Push(&g_stack, &v1), "Push 111 failed");
ASSERT_INT_EQ_MSG(C_ERR_OK, c_ArrayStack_Push(&g_stack, &v2), "Push 222 failed");
// 此时不应该为空,大小应为 2
ASSERT_MSG(c_ArrayStack_IsEmpty(&g_stack) == false, "Stack should not be empty");
ASSERT_INT_EQ_MSG(2, g_stack.size, "Stack size should be 2");
// 测试 Peek:应该看到最后压入的 222,且栈大小不变
int* top_ptr = (int*)c_ArrayStack_Peek(&g_stack);
ASSERT_MSG(top_ptr != NULL, "Peek should not return NULL");
ASSERT_INT_EQ_MSG(222, *top_ptr, "Peek value should be 222");
ASSERT_INT_EQ_MSG(2, g_stack.size, "Size must remain 2 after peek");
// 测试 Pop:验证 LIFO 顺序
int out_val = 0;
ASSERT_INT_EQ_MSG(C_ERR_OK, c_ArrayStack_Pop(&g_stack, &out_val), "First pop failed");
ASSERT_INT_EQ_MSG(222, out_val, "First popped value should be 222 (LIFO)");
ASSERT_INT_EQ_MSG(C_ERR_OK, c_ArrayStack_Pop(&g_stack, &out_val), "Second pop failed");
ASSERT_INT_EQ_MSG(111, out_val, "Second popped value should be 111");
// 最终应该重新变为空栈
ASSERT_MSG(c_ArrayStack_IsEmpty(&g_stack) == true, "Stack should be empty after popping all elements");
}
// 用例 2:测试空栈(Empty)的边界防御表现
static void test_stack_empty_bounds() {
int dummy = 999;
// 空栈执行 Pop 应该安全报错(例如返回 C_ERR_EMPTY 或非 OK 状态)
c_err_t err = c_ArrayStack_Pop(&g_stack, &dummy);
ASSERT_MSG(err != C_ERR_OK, "Pop on empty stack should return an error code");
ASSERT_INT_EQ_MSG(999, dummy, "Output buffer should remain unchanged on failure");
// 空栈执行 Peek 应该安全返回 NULL
ASSERT_MSG(c_ArrayStack_Peek(&g_stack) == NULL, "Peek on empty stack must return NULL");
}
// 用例 3:动态自动扩容测试
static void test_stack_auto_expansion() {
// 初始容量设为了 2,连续压入 4 个数据触发自动扩容
for (int i = 1; i <= 4; i++) {
int val = i * 10;
c_err_t err = c_ArrayStack_Push(&g_stack, &val);
char msg[64];
sprintf(msg, "Pushing element %d failed", val);
ASSERT_INT_EQ_MSG(C_ERR_OK, err, msg);
}
// 校验容量是否增长
ASSERT_MSG(g_stack.capacity > 2, "Stack capacity should have grown");
ASSERT_INT_EQ_MSG(4, g_stack.size, "Stack size should be 4");
// 倒序弹出校验,确保扩容重构内存后历史数据未损坏
int out_val = 0;
int expected_vals[] = {40, 30, 20, 10};
for (int i = 0; i < 4; i++) {
c_ArrayStack_Pop(&g_stack, &out_val);
char msg[64];
sprintf(msg, "Mismatched LIFO element at step %d", i);
ASSERT_INT_EQ_MSG(expected_vals[i], out_val, msg);
}
}
// 用例 4:测试从任意指定索引删除元素(c_ArrayStack_Remove
static void test_stack_remove_by_index() {
// 压入底 -> 顶:10, 20, 30, 40
// 索引映射:index 0 -> 10, index 1 -> 20, index 2 -> 30, index 3 -> 40
for (int i = 1; i <= 4; i++) {
int val = i * 10;
c_ArrayStack_Push(&g_stack, &val);
}
// 1. 测试越界删除防御(有效索引为 0~3)
c_err_t err_invalid = c_ArrayStack_Remove(&g_stack, 4);
ASSERT_MSG(err_invalid != C_ERR_OK, "Remove out of bounds should fail");
// 2. 删除中间的元素:索引 1 (对应数字 20)
c_err_t err_ok = c_ArrayStack_Remove(&g_stack, 1);
ASSERT_INT_EQ_MSG(C_ERR_OK, err_ok, "Remove middle element failed");
ASSERT_INT_EQ_MSG(3, g_stack.size, "Size should drop to 3 after remove");
// 3. 验证删除后的整体结构。由于移除了 20,剩下的数组结构应为:10, 30, 40
// 按照栈的 LIFO 弹出顺序,依次拿到的应该是 40 -> 30 -> 10
int out_val = 0;
c_ArrayStack_Pop(&g_stack, &out_val);
ASSERT_INT_EQ_MSG(40, out_val, "Top should still be 40");
c_ArrayStack_Pop(&g_stack, &out_val);
ASSERT_INT_EQ_MSG(30, out_val, "Next should be 30 (since 20 was removed)");
c_ArrayStack_Pop(&g_stack, &out_val);
ASSERT_INT_EQ_MSG(10, out_val, "Bottom element should be 10");
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
int main(int argc, char** argv){
TEST_START(Starting Unit Tests);
// 运行需要内存环境的用例
RUN_TEST_FIXTURE(test_stack_push_pop_lifo, setup_stack, teardown_stack);
RUN_TEST_FIXTURE(test_stack_empty_bounds, setup_stack, teardown_stack);
RUN_TEST_FIXTURE(test_stack_auto_expansion, setup_stack, teardown_stack);
RUN_TEST_FIXTURE(test_stack_remove_by_index, setup_stack, teardown_stack);
// 打印最终统计报告
TEST_REPORT();
RETURN_TEST_STATUS;
}