117 lines
4.0 KiB
C
117 lines
4.0 KiB
C
#include "c_ShellSort.h"
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
|
||
// 单元测试断言宏
|
||
#define EXPECT_TRUE(cond, msg) \
|
||
do { \
|
||
if (!(cond)) { printf(" [X] 失败: %s\n", msg); return false; } \
|
||
} while(0)
|
||
|
||
|
||
// 复杂结构体元素:员工信息(用于小内存/栈分配测试)
|
||
typedef struct {
|
||
int id;
|
||
char name[16];
|
||
int score;
|
||
} Employee;
|
||
|
||
// 极其庞大的结构体元素(用于逼出堆分配测试,超过 STACK_LIMIT)
|
||
typedef struct {
|
||
int id;
|
||
char massive_payload[256]; // 超过 128 字节限制
|
||
} LargeTask;
|
||
|
||
// 1. 比较器:按员工积分 (score) 升序
|
||
int compareEmpByScore(const void* a, const void* b) {
|
||
const Employee* e1 = (const Employee*)a;
|
||
const Employee* e2 = (const Employee*)b;
|
||
return (e1->score > e2->score) - (e1->score < e2->score);
|
||
}
|
||
|
||
// 2. 比较器:按大任务 ID 降序
|
||
int compareTaskByIdDesc(const void* a, const void* b) {
|
||
const LargeTask* t1 = (const LargeTask*)a;
|
||
const LargeTask* t2 = (const LargeTask*)b;
|
||
return (t2->id > t1->id) - (t2->id < t1->id);
|
||
}
|
||
|
||
// 3. 比较器:普通整型升序
|
||
int compareInt(const void* a, const void* b) {
|
||
return (*(int*)a - *(int*)b);
|
||
}
|
||
|
||
// 测试用例 1:极限边界(空数组或单元素数组不崩溃)
|
||
bool test_boundary_cases() {
|
||
int* empty_arr = NULL;
|
||
c_ShellSort(empty_arr, 0, sizeof(int), compareInt); // 传 NULL 不应崩溃
|
||
|
||
int single_elem[] = { 42 };
|
||
c_ShellSort(single_elem, 1, sizeof(int), compareInt); // 1个元素不处理
|
||
EXPECT_TRUE(single_elem[0] == 42, "单元素数组值被篡改");
|
||
|
||
return true;
|
||
}
|
||
|
||
// 测试用例 2:完全逆序数组的排序(触发大量 Gap 步进调整)
|
||
bool test_reverse_array() {
|
||
Employee emps[] = {
|
||
{4, "Manager", 90},
|
||
{3, "Leader", 80},
|
||
{2, "Senior", 70},
|
||
{1, "Junior", 60}
|
||
};
|
||
c_size_t num = sizeof(emps) / sizeof(emps[0]);
|
||
|
||
c_ShellSort(emps, num, sizeof(Employee), compareEmpByScore);
|
||
|
||
// 预期结果:按积分 60, 70, 80, 90 升序
|
||
EXPECT_TRUE(emps[0].score == 60 && emps[3].score == 90, "逆序数组排序未完全生效");
|
||
for(c_size_t i = 0; i < num - 1; i++) {
|
||
EXPECT_TRUE(emps[i].score <= emps[i+1].score, "逆序序列排序后仍不满足单调递增");
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 测试用例 3:包含大量相同主键的复杂数组(测试减治和覆盖分支)
|
||
bool test_duplicate_keys() {
|
||
Employee emps[] = {
|
||
{1, "A", 100}, {2, "B", 50}, {3, "C", 100}, {4, "D", 50}, {5, "E", 100}
|
||
};
|
||
c_size_t num = sizeof(emps) / sizeof(emps[0]);
|
||
|
||
c_ShellSort(emps, num, sizeof(Employee), compareEmpByScore);
|
||
|
||
EXPECT_TRUE(emps[0].score == 50 && emps[1].score == 50, "相同项未能归拢到前半段");
|
||
EXPECT_TRUE(emps[2].score == 100 && emps[4].score == 100, "相同项未能归拢到后半段");
|
||
return true;
|
||
}
|
||
|
||
// 测试用例 4:大体积结构体(单元素 > 128 字节,强制触发 C_ALLOC 堆内存分配)
|
||
bool test_large_struct_heap() {
|
||
LargeTask tasks[] = {
|
||
{10, "Payload A"}, {99, "Payload B"}, {5, "Payload C"}, {40, "Payload D"}
|
||
};
|
||
c_size_t num = sizeof(tasks) / sizeof(tasks[0]);
|
||
|
||
// 采用【降序】比较器
|
||
c_ShellSort(tasks, num, sizeof(LargeTask), compareTaskByIdDesc);
|
||
|
||
// 预期结果:ID 降序排序 -> 99, 40, 10, 5
|
||
EXPECT_TRUE(tasks[0].id == 99, "堆分配大结构体首位未命中最大值");
|
||
EXPECT_TRUE(tasks[3].id == 5, "堆分配大结构体末位未命中最小值");
|
||
return true;
|
||
}
|
||
|
||
int main() {
|
||
printf("=== 开始 c_ShellSort 框架级单元测试 ===\n");
|
||
|
||
if (test_boundary_cases()) printf("[PASS] 用例 1: 极限边界条件测试通过\n");
|
||
if (test_reverse_array()) printf("[PASS] 用例 2: 逆序复杂元素排序通过\n");
|
||
if (test_duplicate_keys()) printf("[PASS] 用例 3: 密集重复键稳定性分支通过\n");
|
||
if (test_large_struct_heap()) printf("[PASS] 用例 4: 堆分配(>128B)大元素排序通过\n");
|
||
|
||
printf("\n=== 所有测试执行完毕 ===\n");
|
||
return 0;
|
||
}
|