Files
libakerror/tests/err_capture.h
Andrew Kesterson 4ae1decde2
All checks were successful
libakerror CI Build / cmake_build (push) Successful in 2m44s
libakerror CI Build / mutation_test (push) Successful in 7m46s
Expand error status test coverage
- Added explicit status validation across error handling tests.
- Added lifecycle and slot-leak checks to older tests.
- Improved unhandled-error propagation coverage.
- Added repository guidance and a test runner script.
- Verified all 23 CTest tests pass.

Co-Authored by Codex GPT 5.4
2026-07-29 17:12:52 -04:00

91 lines
2.5 KiB
C

#ifndef AKERR_TEST_CAPTURE_H
#define AKERR_TEST_CAPTURE_H
/*
* Shared test helpers for libakerror.
*
* Installs a capturing implementation of akerr_log_method so tests can assert
* on the *content* of log/stacktrace output (messages, status codes, error
* names) instead of relying solely on process exit codes.
*
* Also provides AKERR_CHECK(), a NDEBUG-proof assertion that fails the test by
* returning non-zero from main() (unlike assert(), which is compiled out in
* release builds and would silently turn a test into a no-op).
*/
#include "akerror.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#define AKERR_CAPTURE_BUFSZ 65536
static char akerr_capture_buf[AKERR_CAPTURE_BUFSZ];
static size_t akerr_capture_len = 0;
static void __attribute__((unused)) akerr_capture_logger(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int n = vsnprintf(akerr_capture_buf + akerr_capture_len,
AKERR_CAPTURE_BUFSZ - akerr_capture_len, fmt, ap);
va_end(ap);
if ( n > 0 ) {
akerr_capture_len += (size_t)n;
if ( akerr_capture_len >= AKERR_CAPTURE_BUFSZ ) {
akerr_capture_len = AKERR_CAPTURE_BUFSZ - 1;
}
}
}
static void __attribute__((unused)) akerr_capture_reset(void)
{
akerr_capture_len = 0;
akerr_capture_buf[0] = '\0';
}
/*
* Install the capturing logger. akerr_init() only assigns a default logger when
* akerr_log_method is NULL, and it is idempotent, so calling this either before
* or after the first PREPARE_ERROR keeps our logger in place.
*/
static void __attribute__((unused)) akerr_capture_install(void)
{
akerr_capture_reset();
akerr_log_method = &akerr_capture_logger;
}
/* Count array slots currently checked out of the pool (refcount != 0). */
static int __attribute__((unused)) akerr_slots_in_use(void)
{
int n = 0;
for ( int i = 0; i < AKERR_MAX_ARRAY_ERROR; i++ ) {
if ( AKERR_ARRAY_ERROR[i].refcount != 0 ) {
n++;
}
}
return n;
}
#define AKERR_CHECK(cond) \
do { \
if ( !(cond) ) { \
fprintf(stderr, "CHECK FAILED: %s at %s:%d\n", \
#cond, __FILE__, __LINE__); \
return 1; \
} \
} while ( 0 )
#define AKERR_CHECK_STATUS(errctx, expected_status) \
do { \
AKERR_CHECK((errctx) != NULL); \
AKERR_CHECK((errctx)->status == (expected_status)); \
} while ( 0 )
#define AKERR_CHECK_CONTAINS(needle) \
AKERR_CHECK(strstr(akerr_capture_buf, (needle)) != NULL)
#define AKERR_CHECK_NOT_CONTAINS(needle) \
AKERR_CHECK(strstr(akerr_capture_buf, (needle)) == NULL)
#endif // AKERR_TEST_CAPTURE_H