#include "c_TrieST.h" #include "c_Test.h" #include #include 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); }