Make error-status assertions authoritative
All checks were successful
libakstdlib CI Build / cmake_build (push) Successful in 2m46s
libakstdlib CI Build / mutation_test (push) Successful in 8m1s

Replace standalone message assertions with a helper that checks the returned akerr status first, then validates message content only as secondary context. Drop ambiguous memcpy message checks where both NULL guards use the same format string.
This commit is contained in:
2026-07-29 15:47:17 -04:00
parent 8003239116
commit 01734f511b
3 changed files with 51 additions and 16 deletions

View File

@@ -18,6 +18,8 @@
* AKSL_CHECK_STATUS() run an akerror-returning expression, assert on the
* status it came back with, and release the context
* so the error pool does not leak.
* AKSL_CHECK_STATUS_MSG_CONTAINS()
* assert status first, then message content.
* AKSL_CHECK_OK() assert a call returned no error context at all.
* aksl_last_status/... the status, message and function name of the most
* recent context taken by AKSL_CHECK_STATUS.
@@ -200,9 +202,42 @@ static int __attribute__((unused)) aksl_take(akerr_ErrorContext *e)
#define AKSL_CHECK_NOT_CONTAINS(needle) \
AKSL_CHECK(strstr(aksl_capture_buf, (needle)) == NULL)
/* Assert on the message of the context most recently taken. */
#define AKSL_CHECK_MSG_CONTAINS(needle) \
AKSL_CHECK(strstr(aksl_last_message, (needle)) != NULL)
/*
* Message checks are secondary: the returned akerr status is the contract. Keep
* the status and message assertions coupled so tests cannot pass on text alone.
*/
#define AKSL_CHECK_STATUS_MSG_CONTAINS(__expr, __expected, __needle) \
do { \
int __st = aksl_take(__expr); \
if ( __st != (__expected) ) { \
fprintf(stderr, \
" CHECK FAILED: %s\n" \
" got %d (%s) \"%s\"\n" \
" expected %d (%s)\n" \
" at %s:%d\n", \
#__expr, \
__st, akerr_name_for_status(__st, NULL), \
aksl_last_message, \
(__expected), \
akerr_name_for_status((__expected), NULL), \
__FILE__, __LINE__); \
return 1; \
} \
if ( strstr(aksl_last_message, (__needle)) == NULL ) { \
fprintf(stderr, \
" CHECK FAILED: message from %s\n" \
" got \"%s\"\n" \
" expected substring \"%s\"\n" \
" status %d (%s)\n" \
" at %s:%d\n", \
#__expr, \
aksl_last_message, \
(__needle), \
__st, akerr_name_for_status(__st, NULL), \
__FILE__, __LINE__); \
return 1; \
} \
} while ( 0 )
/* ---------------------------------------------------------------------- */
/* Test driver */

View File

@@ -190,8 +190,9 @@ static int test_iterate_propagates_callback_error(void)
visitlog_init(&log);
log.fail_at = 0;
AKSL_CHECK_STATUS(aksl_list_iterate(&node, &record_visit, &log), AKERR_VALUE);
AKSL_CHECK_MSG_CONTAINS("iterator failed at visit 0");
AKSL_CHECK_STATUS_MSG_CONTAINS(
aksl_list_iterate(&node, &record_visit, &log),
AKERR_VALUE, "iterator failed at visit 0");
AKSL_CHECK(log.count == 1);
return 0;
}

View File

@@ -10,7 +10,6 @@
#include "aksl_capture.h"
static int test_malloc_writes_nonnull_pointer(void)
{
void *ptr = NULL;
@@ -23,15 +22,15 @@ static int test_malloc_writes_nonnull_pointer(void)
static int test_malloc_rejects_null_destination(void)
{
AKSL_CHECK_STATUS(aksl_malloc(32, NULL), AKERR_NULLPOINTER);
AKSL_CHECK_MSG_CONTAINS("NULL");
AKSL_CHECK_STATUS_MSG_CONTAINS(aksl_malloc(32, NULL),
AKERR_NULLPOINTER, "NULL");
return 0;
}
static int test_free_rejects_null_pointer(void)
{
AKSL_CHECK_STATUS(aksl_free(NULL), AKERR_NULLPOINTER);
AKSL_CHECK_MSG_CONTAINS("NULL");
AKSL_CHECK_STATUS_MSG_CONTAINS(aksl_free(NULL),
AKERR_NULLPOINTER, "NULL");
return 0;
}
@@ -79,8 +78,8 @@ static int test_memset_zero_length_is_noop(void)
static int test_memset_rejects_null_buffer(void)
{
AKSL_CHECK_STATUS(aksl_memset(NULL, 0x00, 4), AKERR_NULLPOINTER);
AKSL_CHECK_MSG_CONTAINS("s=");
AKSL_CHECK_STATUS_MSG_CONTAINS(aksl_memset(NULL, 0x00, 4),
AKERR_NULLPOINTER, "s=");
return 0;
}
@@ -113,8 +112,8 @@ static int test_memcpy_rejects_null_destination(void)
{
unsigned char src[1] = { 1 };
AKSL_CHECK_STATUS(aksl_memcpy(NULL, src, sizeof(src)), AKERR_NULLPOINTER);
AKSL_CHECK_MSG_CONTAINS("d=");
AKSL_CHECK_STATUS(aksl_memcpy(NULL, src, sizeof(src)),
AKERR_NULLPOINTER);
return 0;
}
@@ -122,8 +121,8 @@ static int test_memcpy_rejects_null_source(void)
{
unsigned char dst[1] = { 0 };
AKSL_CHECK_STATUS(aksl_memcpy(dst, NULL, sizeof(dst)), AKERR_NULLPOINTER);
AKSL_CHECK_MSG_CONTAINS("s=");
AKSL_CHECK_STATUS(aksl_memcpy(dst, NULL, sizeof(dst)),
AKERR_NULLPOINTER);
return 0;
}