#include "c_StrIndexKmp.h" #include #include #include #include "c_Test.h" static size_t g_kmp_alloc_tracker = 0; static void* mock_kmp_alloc(size_t size, void* ctx) { (void)ctx; g_kmp_alloc_tracker++; return malloc(size); } static void mock_kmp_free(void* ptr, void* ctx) { (void)ctx; if (ptr) g_kmp_alloc_tracker--; free(ptr); } TEST_CASE(test_kmp_string_pattern_matcher_closure) { g_kmp_alloc_tracker = 0; c_Allocator_t kmp_pool = { .alloc = mock_kmp_alloc, .realloc = NULL, .free = mock_kmp_free, .dtor = NULL, .ud = NULL }; // ------------------------------------------------------------------------- // 1. 验证常规的 C 风格字符串字符串匹配 // ------------------------------------------------------------------------- const char* txt1 = "ABABDABACDABABCABAB"; const char* pat1 = "ABABCABAB"; // 调用内联包装 API c_size_t idx1 = c_StrIndexKmp(txt1, pat1); ASSERT_INT_EQ(10, (int)idx1); // 特征串应该在索引 10 的坑位被精准揪出来 // ------------------------------------------------------------------------- // 2. 验证多态分配器自治与非阻塞流式“接力二次检索”能力 // ------------------------------------------------------------------------- // 模拟一段由于网络或串口 DMA 传输导致的高密度回绕大字节流 // 里面包含两个相同的特定标志特征码 token "\r\n#OK" const uint8_t binary_stream[] = {0x00, 0x11, '\r', '\n', '#', 'O', 'K', 0xFF, 0xAA, '\r', '\n', '#', 'O', 'K', 0x00}; const uint8_t token_pattern[] = {'\r', '\n', '#', 'O', 'K'}; // 第一次检索:从 0 开始 c_size_t match_1 = c_StrIndexKmpEx(binary_stream, sizeof(binary_stream), token_pattern, sizeof(token_pattern), 0, &kmp_pool); ASSERT_INT_EQ(2, (int)match_1); // 成功在偏移 2 处捕获到第一个标志 ASSERT_INT_EQ(0, g_kmp_alloc_tracker); // 证明内部的 Next 数组是完全在自建多态池中伸降分配的 // 第二次接力检索:利用第一次命中的位置后移一位(match_1 + 1)作为新起点,向后跨越式探测 c_size_t match_2 = c_StrIndexKmpEx(binary_stream, sizeof(binary_stream), token_pattern, sizeof(token_pattern), match_1 + 1, &kmp_pool); ASSERT_INT_EQ(9, (int)match_2); // 完美接力!在偏移 9 处成功挖出了第二个标志码 // ------------------------------------------------------------------------- // 3. 极限下溢防御与销毁平衡断言 // ------------------------------------------------------------------------- // 检索完全不存在的污染码 c_size_t match_fake = c_StrIndexKmpEx(binary_stream, sizeof(binary_stream), "FAKE_TOKEN", 10, 0, &kmp_pool); ASSERT_TRUE(match_fake == C_KMP_NOT_FOUND); // 终极资源账目判决:整个 KMP 解析链条结束后,内部申领的临时 Next 数组必须全部闭环 Free 清算归零! ASSERT_INT_EQ_MSG(0, g_kmp_alloc_tracker, "CRITICAL: KMP internal Next-table leaked memory inside the allocator pool!"); } int main(void) { printf("\n"); TEST_START(C_StringKmp_Advanced_Matcher_Tests); RUN_TEST(test_kmp_string_pattern_matcher_closure); TEST_REPORT(); RETURN_TEST_STATUS; }