Files
cKit/Foundation/c_BinarySearch.t.c
T
2026-08-30 22:24:45 +08:00

136 lines
4.7 KiB
C

#include "c_BinarySearch.h"
#include "c_Test.h"
#include <stdlib.h>
#include <stdio.h>
#include "c_StringView.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
// ==========================================
// 1. 测试用例伴生:基础数据类型比对器
// ==========================================
static int compare_ints(const void* a, const void* b) {
int arg1 = *(const int*)a;
int arg2 = *(const int*)b;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}
// 自定义结构体与对应的比对器
typedef struct {
uint32_t id;
uint32_t value;
} TestItem_t;
static int compare_items_by_id(const void* key, const void* elem) {
uint32_t key_id = *(const uint32_t*)key; // 查找时通常可以直接传入 ID 变量的地址作为 key
uint32_t elem_id = ((const TestItem_t*)elem)->id;
if (key_id < elem_id) return -1;
if (key_id > elem_id) return 1;
return 0;
}
// 适配 c_StringView_t 的比对器(对之前 Cmp 函数的外壳包裹)
static int compare_string_views(const void* key, const void* elem) {
return c_StringView_Cmp((c_StringView_t*)key, (c_StringView_t*)elem);
}
// ==========================================
// 2. 核心测试用例
// ==========================================
TEST_CASE(test_c_BinarySearch_IntArray) {
int sorted_ints[] = { 2, 5, 8, 12, 16, 23, 38, 56, 72, 91 };
c_size_t array_len = sizeof(sorted_ints) / sizeof(sorted_ints[0]);
// 1. 查找存在的元素
int target_exist = 23;
const int* result1 = (const int*)c_BinarySearch(&target_exist, sorted_ints, array_len, sizeof(int), compare_ints);
ASSERT_PTR_NOT_NULL(result1);
ASSERT_INT_EQ(23, *result1);
ASSERT_LL_EQ(5, result1 - sorted_ints); // 校验指针偏移,确定下标为 5
// 2. 查找不存在的元素
int target_missing = 40;
const int* result2 = (const int*)c_BinarySearch(&target_missing, sorted_ints, array_len, sizeof(int), compare_ints);
ASSERT_TRUE(result2 == NULL);
}
TEST_CASE(test_c_BinarySearch_StructArray) {
// 模拟数据库索引项或符号表,已按 ID 升序排好
TestItem_t items[] = {
{ 1001, 55 },
{ 1005, 99 },
{ 1012, 12 },
{ 1045, 78 }
};
c_size_t array_len = sizeof(items) / sizeof(items[0]);
// 查找 ID 为 1012 的结构体数据
uint32_t search_id = 1012;
const TestItem_t* match = (const TestItem_t*)c_BinarySearch(&search_id, items, array_len, sizeof(TestItem_t), compare_items_by_id);
ASSERT_PTR_NOT_NULL(match);
ASSERT_INT_EQ(1012, (int)match->id);
ASSERT_INT_EQ(12, (int)match->value); // 成功提取对应的值
ASSERT_LL_EQ(2, match - items); // 下标确认
}
TEST_CASE(test_c_BinarySearch_StringViewArray) {
// 复用之前的有序 StringView 数组进行查找
c_StringView_t sv_array[] = {
c_StringView_FromCStr("apple"),
c_StringView_FromCStr("banana"),
c_StringView_FromCStr("cherry"),
c_StringView_FromCStr("date")
};
c_size_t array_len = sizeof(sv_array) / sizeof(sv_array[0]);
c_StringView_t target = c_StringView_FromCStr("banana");
const c_StringView_t* match = (const c_StringView_t*)c_BinarySearch(&target, sv_array, array_len, sizeof(c_StringView_t), compare_string_views);
ASSERT_PTR_NOT_NULL(match);
ASSERT_INT_EQ(6, (int)match->size);
ASSERT_TRUE(memcmp(match->str, "banana", 6) == 0);
ASSERT_LL_EQ(1, match - sv_array); // 确认位于数组第 1 项
}
TEST_CASE(test_c_BinarySearch_EdgeAndNull) {
int single_elem[] = { 42 };
int target = 42;
// 1. 空参数安全防御
ASSERT_TRUE(c_BinarySearch(NULL, single_elem, 1, sizeof(int), compare_ints) == NULL);
ASSERT_TRUE(c_BinarySearch(&target, NULL, 1, sizeof(int), compare_ints) == NULL);
ASSERT_TRUE(c_BinarySearch(&target, single_elem, 1, sizeof(int), NULL) == NULL);
ASSERT_TRUE(c_BinarySearch(&target, single_elem, 0, sizeof(int), compare_ints) == NULL);
// 2. 单元素数组边界查找
const int* match = (const int*)c_BinarySearch(&target, single_elem, 1, sizeof(int), compare_ints);
ASSERT_PTR_NOT_NULL(match);
ASSERT_INT_EQ(42, *match);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
int main(int argc, char** argv){
TEST_START(Unit Tests);
// 运行普通无环境要求的用例
RUN_TEST(test_c_BinarySearch_IntArray);
RUN_TEST(test_c_BinarySearch_StructArray);
RUN_TEST(test_c_BinarySearch_StringViewArray);
RUN_TEST(test_c_BinarySearch_EdgeAndNull);
// 打印最终统计报告
TEST_REPORT();
RETURN_TEST_STATUS;
}