Files
2026-08-31 11:50:04 +08:00

129 lines
5.1 KiB
C
Raw Permalink 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_ArrayList.h"
#include <stdlib.h>
#include <stdio.h>
#include <c_Test.h>
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
typedef struct {
uint32_t uid;
int data_block;
} UserPayload_t;
TEST_CASE(test_c_ArrayList_CRUD) {
c_ArrayList_t list;
// 初始化物理插槽总上限被死死限制为 2 的轻量级列表
c_err_t err = c_ArrayList_Init(&list, sizeof(UserPayload_t), 2, &c_DefaultAllocator);
ASSERT_INT_EQ(C_ERR_OK, err);
ASSERT_INT_EQ(0, (int)c_ArrayList_Size(&list)); // 验证内联函数 c_ArrayList_Size 是否正确返回当前 0
ASSERT_INT_EQ(0, (int)list.size);
UserPayload_t p1 = { 8001, 10 };
UserPayload_t p2 = { 8002, 20 };
UserPayload_t p3 = { 8003, 30 };
// 1. 在容量空间未达到天花板前,轻量 Add 应当平滑写入
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_Add(&list, &p1));
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_Add(&list, &p2));
ASSERT_INT_EQ(2, (int)list.size);
// 🌟【确定性轻量策略绝杀断言 1】:当塞入第 3 个数据导致容量溢出时,
// 轻量版 Add 必须无条件前置拦截、拒绝隐式重分配,严肃返回状态码 C_ERR_OUTOFBOUND
ASSERT_INT_EQ(C_ERR_FULL, c_ArrayList_Add(&list, &p3));
ASSERT_INT_EQ(2, (int)list.size); // 大小纹丝不动
// 2. 验证 Read 与 Get 的读取差异
UserPayload_t read_buf;
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_Read(&list, 1, &read_buf));
ASSERT_INT_EQ(8002, (int)read_buf.uid); // 副本安全导出
// 通过 Get 拿到内部指针直接进行原地篡改
UserPayload_t* p_raw_ptr = (UserPayload_t*)c_ArrayList_Get(&list, 1);
ASSERT_TRUE(p_raw_ptr != NULL);
p_raw_ptr->data_block = 9999; // 原地篡改内部物理缓冲区
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_Read(&list, 1, &read_buf));
ASSERT_INT_EQ(9999, read_buf.data_block); // 指针篡改成功核回
// 🌟【确定性轻量策略绝杀断言 2】:使用轻量版 PopBack 弹出
UserPayload_t pop_buf;
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_PopBack(&list, &pop_buf));
ASSERT_INT_EQ(8002, (int)pop_buf.uid);
ASSERT_INT_EQ(1, (int)list.size);
// 尽管存量已经萎缩到总容量的 1/4 以下,轻量版 PopBack 也决不能引发缩容,容量必须卡死留守在 2!
ASSERT_INT_EQ(2, (int)list.capacity);
c_ArrayList_Destroy(&list);
}
TEST_CASE(test_c_ArrayList_Resize) {
c_ArrayList_t list;
c_ArrayList_Init(&list, sizeof(UserPayload_t), 2, NULL); // 降级测试
UserPayload_t p1 = { 9001, 100 };
UserPayload_t p2 = { 9002, 200 };
UserPayload_t p3 = { 9003, 300 }; // 会强迫弹性版触发自动倍增
// 1. 验证自适应变轨 ResizeAdd
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_ResizeAdd(&list, &p1));
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_ResizeAdd(&list, &p2));
// 绝杀:第 3 个数据会自适应变轨,将容量从 2 直接倍增拓宽至 4
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_ResizeAdd(&list, &p3));
ASSERT_INT_EQ(3, (int)list.size);
ASSERT_INT_EQ(4, (int)list.capacity);
// 2. 验证中段中段摘除平移覆盖
UserPayload_t remove_verify;
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_RemoveAt(&list, 1, &remove_verify)); // 拿掉 1 号位的 P2
ASSERT_INT_EQ(9002, (int)remove_verify.uid);
ASSERT_INT_EQ(2, (int)list.size);
// 搬运平移断言:原先在 2 号位的 P3(9003) 应该已经被向前挪移顶替到了 1 号位
UserPayload_t read_verify;
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_Read(&list, 1, &read_verify));
ASSERT_INT_EQ(9003, (int)read_verify.uid);
// 3. 验证弹性版 PopBackResize 与常数缩容锁
UserPayload_t pop_resize_verify;
ASSERT_INT_EQ(C_ERR_OK, c_ArrayList_PopBackResize(&list, &pop_resize_verify));
ASSERT_INT_EQ(9003, (int)pop_resize_verify.uid);
ASSERT_INT_EQ(1, (int)list.size);
// 🌟【核心弹性缩容断言】:此时 N <= Capacity/4 (1 <= 4/4) 且大于配额上限
// 自适应版 PopBackResize 必须自动通过常数缩容锁将物理存储空间腰斩,重新高效卡回容量 2!
ASSERT_INT_EQ(2, (int)list.capacity);
c_ArrayList_Destroy(&list);
}
TEST_CASE(test_c_ArrayList_Toxicity_Defenses) {
c_ArrayList_t local_list;
c_ArrayList_Init(&local_list, sizeof(int), 4, NULL);
int dummy = 0;
// 验证各类入参毒参数及空仓边界的状态码返回线
ASSERT_INT_EQ(C_ERR_PARAM, c_ArrayList_Init(NULL, sizeof(int), 4, NULL));
ASSERT_INT_EQ(C_ERR_EMPTY, c_ArrayList_PopBack(&local_list, &dummy)); // 拦截 C_ERR_EMPTY
ASSERT_INT_EQ(C_ERR_OUTOFBOUND, c_ArrayList_Set(&local_list, 999, &dummy)); // 越界拦截
ASSERT_TRUE(c_ArrayList_Get(&local_list, 0) == NULL);
c_ArrayList_Destroy(&local_list);
}
// ==========================================
// 5. 主集成入口
// ==========================================
int main(void) {
TEST_START(C_ArrayList_DoubleStrategy_TestSuite);
RUN_TEST(test_c_ArrayList_CRUD);
RUN_TEST(test_c_ArrayList_Resize);
RUN_TEST(test_c_ArrayList_Toxicity_Defenses);
TEST_REPORT();
return (g_test_registry.failed_count > 0 ? 1 : 0);
}