98 lines
4.1 KiB
C
98 lines
4.1 KiB
C
|
|
#include "akerror.h"
|
||
|
|
#include "err_capture.h"
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Reserving a range used to be pure bookkeeping: akerr_name_for_status() would
|
||
|
|
* name any status for any caller, so two components could still register names
|
||
|
|
* for the same code -- and HANDLE the same code -- with nothing detecting it.
|
||
|
|
* Reservation only caught components that both opted in AND declared ranges
|
||
|
|
* that happened to overlap.
|
||
|
|
*
|
||
|
|
* Naming a status is now permitted only inside a reservation:
|
||
|
|
* - akerr_register_status_name() requires the range to belong to the caller;
|
||
|
|
* - the legacy two-argument akerr_name_for_status() set path cannot identify
|
||
|
|
* its caller, so it can only require that *some* reservation covers the
|
||
|
|
* status -- still enough to stop a code nobody claimed.
|
||
|
|
* Every refusal is logged, because a name that fails to register degrades the
|
||
|
|
* status to "Unknown Error" in every later stack trace.
|
||
|
|
*/
|
||
|
|
|
||
|
|
int main(void)
|
||
|
|
{
|
||
|
|
akerr_capture_install();
|
||
|
|
akerr_init();
|
||
|
|
|
||
|
|
AKERR_CHECK(akerr_reserve_status_range(256, 16, "lib-a") ==
|
||
|
|
AKERR_STATUS_RANGE_OK);
|
||
|
|
AKERR_CHECK(akerr_reserve_status_range(512, 16, "lib-b") ==
|
||
|
|
AKERR_STATUS_RANGE_OK);
|
||
|
|
|
||
|
|
/* The owner of a range may name statuses inside it. */
|
||
|
|
AKERR_CHECK(akerr_register_status_name("lib-a", 256, "A Parse Error") ==
|
||
|
|
AKERR_STATUS_NAME_OK);
|
||
|
|
AKERR_CHECK(akerr_register_status_name("lib-a", 271, "A Last Error") ==
|
||
|
|
AKERR_STATUS_NAME_OK);
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(256, NULL), "A Parse Error") == 0);
|
||
|
|
|
||
|
|
/* Naming another owner's status is refused and names the real owner. */
|
||
|
|
akerr_capture_reset();
|
||
|
|
AKERR_CHECK(akerr_register_status_name("lib-b", 256, "B Hijack") ==
|
||
|
|
AKERR_STATUS_NAME_FOREIGN);
|
||
|
|
AKERR_CHECK_CONTAINS("lib-a");
|
||
|
|
AKERR_CHECK_CONTAINS("lib-b");
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(256, NULL), "A Parse Error") == 0);
|
||
|
|
|
||
|
|
/* Including the library's own reserved band. */
|
||
|
|
akerr_capture_reset();
|
||
|
|
AKERR_CHECK(akerr_register_status_name("lib-b", AKERR_VALUE, "B Value") ==
|
||
|
|
AKERR_STATUS_NAME_FOREIGN);
|
||
|
|
AKERR_CHECK_CONTAINS(AKERR_LIBRARY_OWNER);
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(AKERR_VALUE, NULL), "Value Error") == 0);
|
||
|
|
|
||
|
|
/* A status nobody reserved cannot be named through either entry point. */
|
||
|
|
akerr_capture_reset();
|
||
|
|
AKERR_CHECK(akerr_register_status_name("lib-a", 9999, "Unclaimed") ==
|
||
|
|
AKERR_STATUS_NAME_UNRESERVED);
|
||
|
|
AKERR_CHECK_CONTAINS("no reserved range");
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(9999, NULL), "Unknown Error") == 0);
|
||
|
|
|
||
|
|
akerr_capture_reset();
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(9999, "Unclaimed Legacy"),
|
||
|
|
"Unknown Error") == 0);
|
||
|
|
AKERR_CHECK_CONTAINS("no reserved range");
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(9999, NULL), "Unknown Error") == 0);
|
||
|
|
|
||
|
|
/* Boundaries: just outside lib-a's range is not lib-a's to name. */
|
||
|
|
AKERR_CHECK(akerr_register_status_name("lib-a", 255, "Below") ==
|
||
|
|
AKERR_STATUS_NAME_FOREIGN);
|
||
|
|
AKERR_CHECK(akerr_register_status_name("lib-a", 272, "Above") ==
|
||
|
|
AKERR_STATUS_NAME_UNRESERVED);
|
||
|
|
|
||
|
|
/* The legacy set path still works inside any reservation. */
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(513, "B Legacy"), "B Legacy") == 0);
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(513, NULL), "B Legacy") == 0);
|
||
|
|
|
||
|
|
/* Re-registering your own status overwrites the name. */
|
||
|
|
AKERR_CHECK(akerr_register_status_name("lib-a", 256, "A Renamed") ==
|
||
|
|
AKERR_STATUS_NAME_OK);
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(256, NULL), "A Renamed") == 0);
|
||
|
|
|
||
|
|
/* Argument validation. */
|
||
|
|
AKERR_CHECK(akerr_register_status_name(NULL, 257, "No Owner") ==
|
||
|
|
AKERR_STATUS_NAME_INVALID);
|
||
|
|
AKERR_CHECK(akerr_register_status_name("", 257, "Empty Owner") ==
|
||
|
|
AKERR_STATUS_NAME_INVALID);
|
||
|
|
AKERR_CHECK(akerr_register_status_name("lib-a", 257, NULL) ==
|
||
|
|
AKERR_STATUS_NAME_INVALID);
|
||
|
|
|
||
|
|
/* A refused registration must not consume a slot or leave a partial entry. */
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(257, NULL), "Unknown Error") == 0);
|
||
|
|
|
||
|
|
/* Lookup is unaffected by ownership -- anyone may read any name. */
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(271, NULL), "A Last Error") == 0);
|
||
|
|
|
||
|
|
fprintf(stderr, "err_name_ownership ok\n");
|
||
|
|
return 0;
|
||
|
|
}
|