Files
2026-08-31 22:49:42 +08:00

147 lines
6.0 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_TrieST.h"
#include "c_Test.h"
#include <stdlib.h>
#include <stdio.h>
typedef struct {
uint32_t gateway_id;
char protocol_tag[16];
} RouteConfig_t;
static void* test_trie_val_cp(const void* data, void* arg) {
(void)arg;
const RouteConfig_t* src = (const RouteConfig_t*)data;
RouteConfig_t* clone = (RouteConfig_t*)malloc(sizeof(RouteConfig_t)); // 模拟独立动态开辟
if (clone) {
clone->gateway_id = src->gateway_id;
strcpy(clone->protocol_tag, src->protocol_tag);
}
return (void*)clone;
}
static void test_trie_val_free(void* data, void* arg) {
(void)arg;
if (data) {
free(data); // 原路深层爆破销毁
}
}
TEST_CASE(test_c_TrieST_Extreme_O_W_CRUD) {
c_TrieST_t trie;
// 初始化多态单词查找树,绑定虚操作,且传递 NULL 检验默认 Fallback 降级分配器机制
c_err_t err = c_TrieST_Init(&trie, test_trie_val_cp, test_trie_val_free, NULL, NULL);
ASSERT_INT_EQ(C_ERR_OK, err);
// 构建测试密集变长前缀树丛:"sea", "seashells", "she"
RouteConfig_t config_sea = { 101, "HTTP" };
RouteConfig_t config_shells = { 202, "MQTT" };
RouteConfig_t config_she = { 303, "gRPC" };
// 1. Put 基础写入断言
ASSERT_INT_EQ(C_ERR_OK, c_TrieST_Put(&trie, "sea", &config_sea));
ASSERT_INT_EQ(C_ERR_OK, c_TrieST_Put(&trie, "seashells", &config_shells));
ASSERT_INT_EQ(C_ERR_OK, c_TrieST_Put(&trie, "she", &config_she));
ASSERT_INT_EQ(3, (int)trie.size);
// Contains 与符号模糊隔离断言
ASSERT_TRUE(c_TrieST_Contains(&trie, "seashells"));
ASSERT_TRUE(!c_TrieST_Contains(&trie, "seash")); // 前缀虽通,但非完整独立有效键,必须返回 false
// 2. Get 常数时间穿透读取与多态结构体字段验证
void* fetched_ptr = c_TrieST_Get(&trie, "seashells");
ASSERT_TRUE(fetched_ptr != NULL);
RouteConfig_t* match_conf = (RouteConfig_t*)fetched_ptr;
ASSERT_INT_EQ(202, (int)match_conf->gateway_id);
ASSERT_TRUE(strcmp("MQTT", match_conf->protocol_tag) == 0);
// 3. Put 相同键下的覆写更新(Overwrite)特性核验
RouteConfig_t config_update = { 202, "HTTP/3" };
ASSERT_INT_EQ(C_ERR_OK, c_TrieST_Put(&trie, "seashells", &config_update));
ASSERT_INT_EQ(3, (int)trie.size); // 全局大小强力守恒
match_conf = (RouteConfig_t*)c_TrieST_Get(&trie, "seashells");
ASSERT_TRUE(strcmp("HTTP/3", match_conf->protocol_tag) == 0); // 覆写完全奏效
// 4. Delete 惰性级联剪枝删除绝对安全验证
// 斩断移出带有深度嵌套延伸子代路径的父节点 "sea"
ASSERT_INT_EQ(C_ERR_OK, c_TrieST_Delete(&trie, "sea"));
ASSERT_INT_EQ(2, (int)trie.size);
ASSERT_TRUE(c_TrieST_Get(&trie, "sea") == NULL);
// 🌟【硬核级联完整性验证】:虽然 "sea" 节点对应的 val 被剥离,
// 但因为它的后方还延伸驻留着有效长字符串分支 "seashells"
// 逆向惰性剪枝控制流应当自适应保留后面的子孙拓扑!断言 "seashells" 必须依然可以被完美高并发检索!
ASSERT_TRUE(c_TrieST_Contains(&trie, "seashells"));
// 5. 移出完全孤立的悬空分支节点 "she"
ASSERT_INT_EQ(C_ERR_OK, c_TrieST_Delete(&trie, "she"));
ASSERT_INT_EQ(1, (int)trie.size);
// 6. 统一解构注销,原路物理洗刷洗净所有残存节点与多态对象空间
c_TrieST_Destroy(&trie);
}
TEST_CASE(test_c_TrieST_ParamConstraints) {
c_TrieST_t local_trie;
c_TrieST_Init(&local_trie, NULL, NULL, NULL, &c_DefaultAllocator);
RouteConfig_t dummy = { 999, "RAW" };
// 5. 验证各类极值边界及非法参数的强拦截
ASSERT_INT_EQ(C_ERR_PARAM, c_TrieST_Init(NULL, NULL, NULL, NULL, NULL));
ASSERT_INT_EQ(C_ERR_PARAM, c_TrieST_Put(NULL, "toxic", &dummy));
ASSERT_INT_EQ(C_ERR_EMPTY, c_TrieST_Delete(&local_trie, "toxic")); // 空仓删除安全返回 C_ERR_EMPTY
c_TrieST_Destroy(&local_trie);
}
TEST_CASE(test_c_TrieST_StringBuffer_HighLevelPipeline) {
c_TrieST_t trie;
c_TrieST_Init(&trie, NULL, NULL, NULL, &c_DefaultAllocator);
int dummy_v = 1;
c_TrieST_Put(&trie, "api/v1/user", &dummy_v);
c_TrieST_Put(&trie, "api/v1/user/profile", &dummy_v);
c_TrieST_Put(&trie, "api/v1/user/profile/avatar", &dummy_v);
c_TrieST_Put(&trie, "api/v2/auth", &dummy_v);
c_TrieST_Put(&trie, "app/v1/user", &dummy_v);
c_StringList_t result_list;
c_StringList_Init(&result_list, 4, 0);
// 1. KeysWithPrefix 断言(前缀拼写补全联想)
c_err_t err = c_TrieST_KeysWithPrefix(&trie, "api/v1/user", &result_list);
ASSERT_INT_EQ(C_ERR_OK, err);
ASSERT_INT_EQ(3, (int)c_StringList_Size(&result_list));
ASSERT_TRUE(strcmp("api/v1/user", c_StringList_Get(&result_list, 0)) == 0);
ASSERT_TRUE(strcmp("api/v1/user/profile/avatar", c_StringList_Get(&result_list, 2)) == 0);
// 2. KeysThatMatch 断言(通配符并发拦截)
c_StringList_Clear(&result_list);
err = c_TrieST_KeysThatMatch(&trie, "ap./v1/user", &result_list);
ASSERT_INT_EQ(C_ERR_OK, err);
ASSERT_INT_EQ(2, (int)c_StringList_Size(&result_list));
ASSERT_TRUE(strcmp("api/v1/user", c_StringList_Get(&result_list, 0)) == 0);
// 3. LongestPrefixOf 断言(最长分级掩码前缀寻址)
c_StringList_Clear(&result_list);
const char* network_url = "api/v1/user/profile/settings/security_token";
err = c_TrieST_LongestPrefixOf(&trie, network_url, &result_list);
ASSERT_INT_EQ(C_ERR_OK, err);
ASSERT_INT_EQ(1, (int)c_StringList_Size(&result_list));
ASSERT_TRUE(strcmp("api/v1/user/profile", c_StringList_Get(&result_list, 0)) == 0);
c_StringList_Destroy(&result_list);
c_TrieST_Destroy(&trie);
}
// ==========================================
// 5. 主集成入口
// ==========================================
int main(void) {
TEST_START(C_TrieST_R_waySymbolTable_TestSuite);
RUN_TEST(test_c_TrieST_Extreme_O_W_CRUD);
RUN_TEST(test_c_TrieST_ParamConstraints);
RUN_TEST(test_c_TrieST_StringBuffer_HighLevelPipeline);
TEST_REPORT();
return (g_test_registry.failed_count > 0 ? 1 : 0);
}