Files
cKit/Foundation/c_StrIndexKmp.t.c
T

76 lines
3.4 KiB
C
Raw Normal View History

2026-08-30 03:52:23 +08:00
#include "c_StrIndexKmp.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#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;
}