Files
cKit/Foundation/c_StringList.t.c
T

105 lines
5.1 KiB
C
Raw Normal View History

2026-08-30 03:59:45 +08:00
#include <stdio.h>
#include <stdlib.h>
#include "c_StringList.h"
#include "c_Test.h"
static size_t g_list_pool_active_chunks = 0; // 监控多态内存池中处于活跃分配态的物理块个数
// 模拟伙伴系统或 Arena 内存池的分配监控桩实现
static void* mock_list_pool_alloc(size_t size, void* ctx) {
(void)ctx; g_list_pool_active_chunks++; return malloc(size);
}
static void mock_list_pool_free(void* ptr, void* ctx) {
(void)ctx; if (ptr) g_list_pool_active_chunks--; free(ptr);
}
static void* mock_list_pool_realloc(void* ptr, size_t old_size, size_t new_size, void* ctx) {
(void)ctx; (void)old_size; return realloc(ptr, new_size);
}
TEST_CASE(test_string_list_polymorphic_deep_copy_closure) {
g_list_pool_active_chunks = 0;
// 1. 原地构建自定义专属内存池分配器
c_Allocator_t my_pool = {
.alloc = mock_list_pool_alloc,
.realloc = mock_list_pool_realloc,
.free = mock_list_pool_free,
.dtor = NULL,
.ud = NULL
};
c_StringList list;
// 初始化容量为 2 的特化字符串链表,并注入分配器
ASSERT_INT_EQ(C_ERR_OK, c_StringList_Init(&list, 2, &my_pool));
// 审计校准:此时内存池只分配了 1 个矩阵控制大底座,活跃物理块精确定格为 1
ASSERT_INT_EQ(1, (int)g_list_pool_active_chunks);
ASSERT_INT_EQ(0, (int)c_StringList_Size(&list));
// 2. 验证元素填充、深度值复制、以及内部自适应动态翻倍扩容
char stack_buffer[] = "STACK_TXT_A"; // 分配在局部栈上的临时垃圾包
ASSERT_INT_EQ(C_ERR_OK, c_StringList_Add(&list, stack_buffer));
ASSERT_INT_EQ(C_ERR_OK, c_StringList_Add(&list, "STACK_TXT_B"));
// 此时触发 2 -> 4 自动扩容:内部 realloc 成功原地续约底座,并塞入第三行
ASSERT_INT_EQ(C_ERR_OK, c_StringList_Add(&list, "STACK_TXT_A")); // 故意塞入重复项用于后续去重
ASSERT_INT_EQ(3, (int)c_StringList_Size(&list));
ASSERT_INT_EQ(4, (int)list.capacity);
// 活跃物理块计算:1个指针矩阵大底座 + 3个行级独立分配的独占堆字符串 = 4 个活跃块
ASSERT_INT_EQ(4, (int)g_list_pool_active_chunks);
// 3. 强隔离隔离性判定:故意洗刷外部栈变量,内部持有的内容必须坚若磐石
memset(stack_buffer, 'X', sizeof(stack_buffer));
ASSERT_TRUE(strcmp(c_StringList_Get(&list, 0), "STACK_TXT_A") == 0); // 必须依旧是原值,证明深度值复制成立
// 4. 验证中段定点随机插入(InsertAt)及相对物理寻址
ASSERT_INT_EQ(C_ERR_OK, c_StringList_InsertAt(&list, 1, "INSERTED_VAL"));
ASSERT_INT_EQ(4, (int)c_StringList_Size(&list));
// 确认原本在索引 1 的项被 memmove 完美向右推挤到了索引 2 位置
ASSERT_TRUE(strcmp(c_StringList_Get(&list, 1), "INSERTED_VAL") == 0);
ASSERT_TRUE(strcmp(c_StringList_Get(&list, 2), "STACK_TXT_B") == 0);
ASSERT_INT_EQ(5, (int)g_list_pool_active_chunks);
// 5. 验证中段定点删除(RemoveAt)与后续行指针平移重组
ASSERT_INT_EQ(C_ERR_OK, c_StringList_RemoveAt(&list, 1)); // 抹杀刚插入的项
ASSERT_INT_EQ(3, (int)c_StringList_Size(&list));
ASSERT_TRUE(strcmp(c_StringList_Get(&list, 1), "STACK_TXT_B") == 0); // 后面重新前滑补缺
ASSERT_INT_EQ(4, (int)g_list_pool_active_chunks); // 行物理壳资源被精准火化扣减 1
// 6. 验证高级全词原位去重机制 (Deduplicate)
// 当前排列为: "STACK_TXT_A", "STACK_TXT_B", "STACK_TXT_A"
ASSERT_INT_EQ(C_ERR_OK, c_StringList_Deduplicate(&list));
ASSERT_INT_EQ(2, (int)c_StringList_Size(&list)); // 末尾重复的 A 被定点剔除
ASSERT_TRUE(strcmp(c_StringList_Get(&list, 0), "STACK_TXT_A") == 0);
ASSERT_TRUE(strcmp(c_StringList_Get(&list, 1), "STACK_TXT_B") == 0);
ASSERT_INT_EQ(3, (int)g_list_pool_active_chunks); // 重复行的物理资源被内置分配器在底层连根拔起
// 7. 验证克隆体深拷贝承袭能力 (Clone)
c_StringList clone_list;
c_StringList_Init(&clone_list, 1, &my_pool); // 给个小容量 1
ASSERT_INT_EQ(C_ERR_OK, c_StringList_Clone(&clone_list, &list));
ASSERT_INT_EQ(2, (int)c_StringList_Size(&clone_list));
ASSERT_TRUE(strcmp(c_StringList_Get(&clone_list, 0), "STACK_TXT_A") == 0);
// 8. 终极连环解体大清算
c_StringList_Destroy(&list);
c_StringList_Destroy(&clone_list);
// 终极双向一致性账目审判:
// 当两个大容器彻底解体消亡后,无论是行级独立开辟的变长串,还是指针底座大矩阵,必须全数物理火化!
// 挂载的多态池活跃计数量 g_list_pool_active_chunks 必须以极致优美的姿态完美重归于 0(0 空间泄漏,0 碎片滞留)
ASSERT_INT_EQ_MSG(0, (int)g_list_pool_active_chunks, "CRITICAL: c_StringList leaked exclusive heap elements inside the polymorphic allocator pool!");
}
int main(void) {
printf("\n");
TEST_START(C_StringList_Polymorphic_DeepCopy_Tests);
// 驱动高防御型特化字符串顺序表全功能单元测试验证
RUN_TEST(test_string_list_polymorphic_deep_copy_closure);
TEST_REPORT();
RETURN_TEST_STATUS;
}