From 01734f511be752bd1393bb2f51120f2e3c16cc8d Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Wed, 29 Jul 2026 15:47:17 -0400 Subject: [PATCH] Make error-status assertions authoritative 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. --- tests/aksl_capture.h | 41 ++++++++++++++++++++++++++++++++++++++--- tests/test_linkedlist.c | 5 +++-- tests/test_memory.c | 21 ++++++++++----------- 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/tests/aksl_capture.h b/tests/aksl_capture.h index 2c8675a..57dce3b 100644 --- a/tests/aksl_capture.h +++ b/tests/aksl_capture.h @@ -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 */ diff --git a/tests/test_linkedlist.c b/tests/test_linkedlist.c index 0d24f72..be44b6b 100644 --- a/tests/test_linkedlist.c +++ b/tests/test_linkedlist.c @@ -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; } diff --git a/tests/test_memory.c b/tests/test_memory.c index a5135d1..fce15e1 100644 --- a/tests/test_memory.c +++ b/tests/test_memory.c @@ -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; }