Files
libakerror/tests/err_maxval.c
Andrew Kesterson 10f7203e8f
All checks were successful
libakerror CI Build / cmake_build (push) Successful in 2m41s
libakerror CI Build / mutation_test (push) Successful in 6m54s
Fix AKERR_MAX_ERR_VALUE to cover all AKERR_* codes
AKERR_MAX_ERR_VALUE was AKERR_LAST_ERRNO_VALUE + 15, but the highest defined
code, AKERR_BADEXC, is + 17 (AKERR_NOT_IMPLEMENTED is + 16). akerr_name_for_status
rejects any status above the max, so those codes could never have a registered
name and the AKERR_BADEXC registration in akerr_init was dead code -- a gap
found by mutation testing. Bump the max to + 17.

- err_maxval: new test asserting the reserved AKERR_* range exceeds the number
  of AKERR_* codes and that every code is individually indexable. Fails against
  the old + 15 value (verified), guarding against regression.
- err_error_names: now also checks AKERR_BADEXC's name, which the fix makes
  reachable.

Mutation score on src/error.c rises 71% -> 74%: the previously-dead BADEXC
registration and the name_for_status upper-bound check are now killable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 17:17:26 -04:00

53 lines
1.6 KiB
C

#include "akerror.h"
#include "err_capture.h"
/*
* AKERR_MAX_ERR_VALUE sizes the __AKERR_ERROR_NAMES table and is the upper bound
* akerr_name_for_status() will accept. If it is smaller than the highest AKERR_*
* code, those codes silently lose their names (this was a real bug: the max was
* +15 while AKERR_BADEXC is +17).
*
* Guard the invariant: the AKERR_* range reserved above AKERR_LAST_ERRNO_VALUE
* must be larger than the number of AKERR_* codes defined, and every code must
* be individually indexable.
*/
/* Every AKERR_* library error code. Keep in sync with akerror.h. */
static const int akerr_codes[] = {
AKERR_NULLPOINTER,
AKERR_OUTOFBOUNDS,
AKERR_API,
AKERR_ATTRIBUTE,
AKERR_TYPE,
AKERR_KEY,
AKERR_INDEX,
AKERR_FORMAT,
AKERR_IO,
AKERR_VALUE,
AKERR_RELATIONSHIP,
AKERR_EOF,
AKERR_CIRCULAR_REFERENCE,
AKERR_ITERATOR_BREAK,
AKERR_NOT_IMPLEMENTED,
AKERR_BADEXC,
};
int main(void)
{
int n = (int)(sizeof(akerr_codes) / sizeof(akerr_codes[0]));
/* AKERR_MAX_ERR_VALUE must reserve more codes than are actually defined. */
AKERR_CHECK((AKERR_MAX_ERR_VALUE - AKERR_LAST_ERRNO_VALUE) > n);
/* Stronger: every defined code must fall within the addressable range so
* its name can be stored and retrieved. */
for ( int i = 0; i < n; i++ ) {
AKERR_CHECK(akerr_codes[i] > AKERR_LAST_ERRNO_VALUE);
AKERR_CHECK(akerr_codes[i] <= AKERR_MAX_ERR_VALUE);
}
fprintf(stderr, "err_maxval ok (%d codes, range %d)\n",
n, AKERR_MAX_ERR_VALUE - AKERR_LAST_ERRNO_VALUE);
return 0;
}