101 lines
3.3 KiB
C
101 lines
3.3 KiB
C
|
|
#include "akerror.h"
|
||
|
|
#include "err_capture.h"
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
/*
|
||
|
|
* The registry entry points report failure the same way every other function in
|
||
|
|
* this library does: they return akerr_ErrorContext *. A refused reservation is
|
||
|
|
* therefore an ordinary error, and everything that works on an ordinary error
|
||
|
|
* must work on it -- CATCH, HANDLE, PASS, propagation to the caller, and the
|
||
|
|
* stack trace an unhandled one prints.
|
||
|
|
*
|
||
|
|
* This is what distinguishes the current design from the integer return codes
|
||
|
|
* it replaced: a consumer that ignores the result gets a compiler warning
|
||
|
|
* (AKERR_NOIGNORE), and a consumer that catches it but does not handle it gets
|
||
|
|
* the error propagated out of its init function rather than a silently
|
||
|
|
* unreserved range.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define TEST_OWNER "exception-test"
|
||
|
|
|
||
|
|
/* A consumer init function in the shape the documentation recommends. */
|
||
|
|
static akerr_ErrorContext AKERR_NOIGNORE *component_init(int base, const char *owner)
|
||
|
|
{
|
||
|
|
PREPARE_ERROR(errctx);
|
||
|
|
|
||
|
|
ATTEMPT {
|
||
|
|
CATCH(errctx, akerr_reserve_status_range(base, 4, owner));
|
||
|
|
CATCH(errctx, akerr_register_status_name(owner, base, "Component Error"));
|
||
|
|
} CLEANUP {
|
||
|
|
} PROCESS(errctx) {
|
||
|
|
} FINISH(errctx, true);
|
||
|
|
SUCCEED_RETURN(errctx);
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(void)
|
||
|
|
{
|
||
|
|
akerr_capture_install();
|
||
|
|
akerr_init();
|
||
|
|
|
||
|
|
PREPARE_ERROR(errctx);
|
||
|
|
|
||
|
|
/* A successful reservation raises nothing at all. */
|
||
|
|
AKERR_CHECK_SUCCEEDS(component_init(256, TEST_OWNER));
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(256, NULL), "Component Error") == 0);
|
||
|
|
AKERR_CHECK(akerr_slots_in_use() == 0);
|
||
|
|
|
||
|
|
/*
|
||
|
|
* A collision propagates out of the component's init and is caught here.
|
||
|
|
* HANDLE proves the status is a real, distinct exception a consumer can
|
||
|
|
* dispatch on -- not an opaque nonzero int.
|
||
|
|
*/
|
||
|
|
int handled_overlap = 0;
|
||
|
|
ATTEMPT {
|
||
|
|
CATCH(errctx, component_init(258, "other-component"));
|
||
|
|
} CLEANUP {
|
||
|
|
} PROCESS(errctx) {
|
||
|
|
} HANDLE(errctx, AKERR_STATUS_RANGE_OVERLAP) {
|
||
|
|
handled_overlap = 1;
|
||
|
|
} HANDLE_DEFAULT(errctx) {
|
||
|
|
handled_overlap = -1;
|
||
|
|
} FINISH_NORETURN(errctx);
|
||
|
|
AKERR_CHECK(handled_overlap == 1);
|
||
|
|
AKERR_CHECK(akerr_slots_in_use() == 0);
|
||
|
|
|
||
|
|
/* The name-side refusals dispatch the same way. */
|
||
|
|
int handled_foreign = 0;
|
||
|
|
ATTEMPT {
|
||
|
|
CATCH(errctx, akerr_register_status_name("interloper", 256, "Hijack"));
|
||
|
|
} CLEANUP {
|
||
|
|
} PROCESS(errctx) {
|
||
|
|
} HANDLE(errctx, AKERR_STATUS_NAME_FOREIGN) {
|
||
|
|
handled_foreign = 1;
|
||
|
|
} FINISH_NORETURN(errctx);
|
||
|
|
AKERR_CHECK(handled_foreign == 1);
|
||
|
|
AKERR_CHECK(strcmp(akerr_name_for_status(256, NULL), "Component Error") == 0);
|
||
|
|
|
||
|
|
/*
|
||
|
|
* An unhandled refusal carries a stack trace naming the real owner, so the
|
||
|
|
* report a consumer gets is the library's normal one.
|
||
|
|
*/
|
||
|
|
akerr_capture_reset();
|
||
|
|
ATTEMPT {
|
||
|
|
CATCH(errctx, akerr_reserve_status_range(AKERR_VALUE, 1, "encroacher"));
|
||
|
|
} CLEANUP {
|
||
|
|
} PROCESS(errctx) {
|
||
|
|
} HANDLE_DEFAULT(errctx) {
|
||
|
|
LOG_ERROR_WITH_MESSAGE(errctx, "Reservation refused");
|
||
|
|
} FINISH_NORETURN(errctx);
|
||
|
|
AKERR_CHECK_CONTAINS("Reservation refused");
|
||
|
|
AKERR_CHECK_CONTAINS("Status Range Overlap");
|
||
|
|
AKERR_CHECK_CONTAINS(AKERR_LIBRARY_OWNER);
|
||
|
|
AKERR_CHECK_CONTAINS("encroacher");
|
||
|
|
AKERR_CHECK_CONTAINS("error.c");
|
||
|
|
|
||
|
|
/* Nothing above stranded a pool slot. */
|
||
|
|
AKERR_CHECK(akerr_slots_in_use() == 0);
|
||
|
|
|
||
|
|
fprintf(stderr, "err_status_exception ok\n");
|
||
|
|
return 0;
|
||
|
|
}
|