Replace the consumer-sized status-name array with private sparse storage and accept arbitrary integer status values. Add explicit range reservations with overlap diagnostics, reserve the library's 0-255 compatibility band, and harden pointer and string boundary handling. Update regression coverage and document the required migration for custom status-code consumers.
90 lines
3.4 KiB
C
90 lines
3.4 KiB
C
#include "akerror.h"
|
|
#include "err_capture.h"
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
|
|
/* Status magnitude is no longer coupled to a public array bound. */
|
|
int main(void)
|
|
{
|
|
akerr_capture_install();
|
|
akerr_init();
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(INT_MAX, "Maximum Status"),
|
|
"Maximum Status") == 0);
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(INT_MIN, "Minimum Status"),
|
|
"Minimum Status") == 0);
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(INT_MAX, NULL),
|
|
"Maximum Status") == 0);
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(INT_MIN, NULL),
|
|
"Minimum Status") == 0);
|
|
|
|
const char *long_name =
|
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-extra";
|
|
char *stored = akerr_name_for_status(1000000, (char *)long_name);
|
|
AKERR_CHECK(strlen(stored) == AKERR_MAX_ERROR_NAME_LENGTH - 1);
|
|
AKERR_CHECK(stored[AKERR_MAX_ERROR_NAME_LENGTH - 1] == '\0');
|
|
|
|
AKERR_CHECK(akerr_reserve_status_range(256, 16, "component-a") ==
|
|
AKERR_STATUS_RANGE_OK);
|
|
AKERR_CHECK(akerr_reserve_status_range(256, 16, "component-a") ==
|
|
AKERR_STATUS_RANGE_OK);
|
|
AKERR_CHECK(akerr_reserve_status_range(260, 2, "component-b") ==
|
|
AKERR_STATUS_RANGE_OVERLAP);
|
|
AKERR_CHECK_CONTAINS("component-a");
|
|
AKERR_CHECK(akerr_reserve_status_range(255, 1, "component-b") ==
|
|
AKERR_STATUS_RANGE_OVERLAP);
|
|
AKERR_CHECK(akerr_reserve_status_range(INT_MAX, 2, "overflow") ==
|
|
AKERR_STATUS_RANGE_INVALID);
|
|
AKERR_CHECK(akerr_reserve_status_range(300, 0, "empty") ==
|
|
AKERR_STATUS_RANGE_INVALID);
|
|
AKERR_CHECK(akerr_reserve_status_range(300, -1, "negative") ==
|
|
AKERR_STATUS_RANGE_INVALID);
|
|
AKERR_CHECK(akerr_reserve_status_range(300, 1, NULL) ==
|
|
AKERR_STATUS_RANGE_INVALID);
|
|
AKERR_CHECK(akerr_reserve_status_range(300, 1, "") ==
|
|
AKERR_STATUS_RANGE_INVALID);
|
|
|
|
char owner63[AKERR_MAX_ERROR_NAME_LENGTH];
|
|
char owner64[AKERR_MAX_ERROR_NAME_LENGTH + 1];
|
|
memset(owner63, 'a', sizeof(owner63) - 1);
|
|
owner63[sizeof(owner63) - 1] = '\0';
|
|
memset(owner64, 'b', sizeof(owner64) - 1);
|
|
owner64[sizeof(owner64) - 1] = '\0';
|
|
AKERR_CHECK(akerr_reserve_status_range(400, 1, owner63) ==
|
|
AKERR_STATUS_RANGE_OK);
|
|
AKERR_CHECK(akerr_reserve_status_range(401, 1, owner64) ==
|
|
AKERR_STATUS_RANGE_INVALID);
|
|
AKERR_CHECK(akerr_reserve_status_range(INT_MAX, 1, "int-max") ==
|
|
AKERR_STATUS_RANGE_OK);
|
|
|
|
AKERR_CHECK(akerr_reserve_status_range(500, 2, "endpoint") ==
|
|
AKERR_STATUS_RANGE_OK);
|
|
AKERR_CHECK(akerr_reserve_status_range(499, 2, "left") ==
|
|
AKERR_STATUS_RANGE_OVERLAP);
|
|
AKERR_CHECK(akerr_reserve_status_range(500, 1, "endpoint") ==
|
|
AKERR_STATUS_RANGE_OVERLAP);
|
|
AKERR_CHECK(akerr_reserve_status_range(501, 1, "endpoint") ==
|
|
AKERR_STATUS_RANGE_OVERLAP);
|
|
AKERR_CHECK(akerr_reserve_status_range(500, 2, "other") ==
|
|
AKERR_STATUS_RANGE_OVERLAP);
|
|
|
|
/* Five ranges exist: library, component-a, owner63, INT_MAX, endpoint. */
|
|
for ( int i = 0; i < 59; i++ ) {
|
|
AKERR_CHECK(akerr_reserve_status_range(1000 + (i * 2), 1, "fill") ==
|
|
AKERR_STATUS_RANGE_OK);
|
|
}
|
|
AKERR_CHECK(akerr_reserve_status_range(2000, 1, "too-many") ==
|
|
AKERR_STATUS_RANGE_FULL);
|
|
|
|
int filled = 0;
|
|
for ( int status = 2000000; status < 2000600; status++ ) {
|
|
if ( strcmp(akerr_name_for_status(status, "Filled"), "Filled") != 0 ) {
|
|
filled = 1;
|
|
break;
|
|
}
|
|
}
|
|
AKERR_CHECK(filled == 1);
|
|
|
|
fprintf(stderr, "err_maxval ok\n");
|
|
return 0;
|
|
}
|