Fix sds unit test and improve unittest output formatting (#14927)

### Summary

1. Fix sdsResize() unit tests
Before this PR, we forgot to call test_report() after the test ended,
resulting in that even if there were failures, we couldn't detect them.
In this PR, the test_report() call has been fixed, and the missed test
failures in sds.c have been resolved.
Since only the allocated size of jemalloc is deterministic, the
allocation size related sds unittests are only run with Jemalloc.

2. Improve the unit test framework output
Add ANSI color highlighting to test_cond (green PASSED / red FAILED) and
test_report, and refactor the test summary in server.c to show per-group
pass/total counts with a formatted summary table.
This commit is contained in:
debing.sun 2026-03-31 16:05:35 +08:00 committed by GitHub
parent a6a27f56f2
commit b22ce4abb5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 51 additions and 24 deletions

View file

@ -1507,27 +1507,42 @@ int sdsTest(int argc, char **argv, int flags) {
x = sdsResize(x, 200, 1);
test_cond("sdsresize() expand len", sdslen(x) == 40);
test_cond("sdsresize() expand strlen", strlen(x) == 40);
test_cond("sdsresize() expand alloc", sdsalloc(x) == 200);
#if defined(USE_JEMALLOC)
/* 224 - hdrlen(3) - 1(\0) */
test_cond("sdsresize() expand alloc", sdsalloc(x) == 220);
#endif
/* Test sdsresize - trim free space */
x = sdsResize(x, 80, 1);
test_cond("sdsresize() shrink len", sdslen(x) == 40);
test_cond("sdsresize() shrink strlen", strlen(x) == 40);
test_cond("sdsresize() shrink alloc", sdsalloc(x) == 80);
#if defined(USE_JEMALLOC)
/* 96 - hdrlen(3) - 1(\0) */
test_cond("sdsresize() shrink alloc", sdsalloc(x) == 92);
#endif
/* Test sdsresize - crop used space */
x = sdsResize(x, 30, 1);
test_cond("sdsresize() crop len", sdslen(x) == 30);
test_cond("sdsresize() crop strlen", strlen(x) == 30);
test_cond("sdsresize() crop alloc", sdsalloc(x) == 30);
#if defined(USE_JEMALLOC)
/* 40 - hdrlen(3) - 1(\0) */
test_cond("sdsresize() crop alloc", sdsalloc(x) == 36);
#endif
/* Test sdsresize - extend to different class */
x = sdsResize(x, 400, 1);
test_cond("sdsresize() expand len", sdslen(x) == 30);
test_cond("sdsresize() expand strlen", strlen(x) == 30);
test_cond("sdsresize() expand alloc", sdsalloc(x) == 400);
#if defined(USE_JEMALLOC)
/* 448 - hdrlen(5) - 1(\0) */
test_cond("sdsresize() expand alloc", sdsalloc(x) == 442);
#endif
/* Test sdsresize - shrink to different class */
x = sdsResize(x, 4, 1);
test_cond("sdsresize() crop len", sdslen(x) == 4);
test_cond("sdsresize() crop strlen", strlen(x) == 4);
#if defined(USE_JEMALLOC)
/* 8 - hdrlen(3) - 1(\0) */
test_cond("sdsresize() crop alloc", sdsalloc(x) == 4);
#endif
sdsfree(x);
{ /* Test adjustTypeIfNeeded() */

View file

@ -7783,7 +7783,8 @@ int zsetTest(int argc, char **argv, int flags);
struct redisTest {
char *name;
redisTestProc *proc;
int failed;
int test_count;
int passed_count;
} redisTests[] = {
{"ziplist", ziplistTest},
{"quicklist", quicklistTest},
@ -7837,32 +7838,40 @@ int main(int argc, char **argv) {
if (!strcasecmp(argv[2], "all")) {
int numtests = sizeof(redisTests)/sizeof(struct redisTest);
for (j = 0; j < numtests; j++) {
redisTests[j].failed = (redisTests[j].proc(argc,argv,flags) != 0);
}
/* Report tests result */
int failed_num = 0;
for (j = 0; j < numtests; j++) {
if (redisTests[j].failed) {
int before_total = __test_num;
int before_failed = __failed_tests;
redisTests[j].proc(argc,argv,flags);
redisTests[j].test_count = __test_num - before_total;
redisTests[j].passed_count = redisTests[j].test_count - (__failed_tests - before_failed);
if (redisTests[j].passed_count < redisTests[j].test_count)
failed_num++;
printf("[failed] Test - %s\n", redisTests[j].name);
} else {
printf("[ok] Test - %s\n", redisTests[j].name);
}
}
printf("%d tests, %d passed, %d failed\n", numtests,
numtests-failed_num, failed_num);
printf("\n========== Test Suite Summary ==========\n\n");
for (j = 0; j < numtests; j++) {
int failed = redisTests[j].passed_count < redisTests[j].test_count;
printf(" %s %-15s (%d/%d passed)%s\n",
failed ? "\033[31m[failed]" : "\033[32m[ok] \033[0m",
redisTests[j].name,
redisTests[j].passed_count, redisTests[j].test_count,
failed ? "\033[0m" : "");
}
return failed_num == 0 ? 0 : 1;
printf("\n Test Groups: %s%d passed\033[0m, %s%d failed\033[0m, %d total\n",
failed_num ? "" : "\033[32m", numtests-failed_num,
failed_num ? "\033[31m" : "", failed_num, numtests);
test_report();
} else {
redisTestProc *proc = getTestProcByName(argv[2]);
if (!proc) return -1; /* test not found */
return proc(argc,argv,flags);
proc(argc,argv,flags);
test_report();
}
return 0;
return __failed_tests ? 1 : 0;
}
#endif

View file

@ -30,14 +30,17 @@ extern int __test_num;
#define test_cond(descr,_c) do { \
__test_num++; printf("%d - %s: ", __test_num, descr); \
if(_c) printf("PASSED\n"); else {printf("FAILED\n"); __failed_tests++;} \
if(_c) printf("\033[32mPASSED\033[0m\n"); else {printf("\033[31mFAILED\033[0m\n"); __failed_tests++;} \
} while(0)
#define test_report() do { \
printf("%d tests, %d passed, %d failed\n", __test_num, \
__test_num-__failed_tests, __failed_tests); \
if (__failed_tests) { \
printf("=== WARNING === We have failed tests here...\n"); \
printf(" Tests: %d passed, \033[31m%d failed\033[0m, %d total\n", \
__test_num-__failed_tests, __failed_tests, __test_num); \
printf("\033[31m=== WARNING === We have failed tests here...\033[0m\n"); \
exit(1); \
} else { \
printf(" Tests: \033[32m%d passed\033[0m, %d failed, %d total\n", \
__test_num-__failed_tests, __failed_tests, __test_num); \
} \
} while(0)