76 lines
3.4 KiB
C
76 lines
3.4 KiB
C
#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;
|
||
|
|
}
|