/**
 * @file error_codes.c
 * @brief Tests that akbasic owns its status band and has named every code in it.
 */

#include <string.h>

#include <akbasic/error.h>

#include "testutil.h"

int main(void)
{
    int code = 0;

    /* Registering is idempotent: an identical repeat by the same owner is a no-op. */
    TEST_REQUIRE_OK(akbasic_error_register());
    TEST_REQUIRE_OK(akbasic_error_register());

    /*
     * Every code must read back a real name. An unnamed one degrades to
     * "Unknown Error" in every stack trace that carries it, which nothing else
     * in the suite would notice.
     */
    for ( code = AKBASIC_ERR_SYNTAX; code < AKBASIC_ERR_LAST; code++ ) {
	const char *name = akerr_name_for_status(code, NULL);
	TEST_REQUIRE(name != NULL, "status %d has a NULL name", code);
	TEST_REQUIRE(strcmp(name, "Unknown Error") != 0,
		     "status %d reads back as \"Unknown Error\"", code);
    }

    TEST_REQUIRE_STR(akerr_name_for_status(AKBASIC_ERR_SYNTAX, NULL), "Syntax Error");
    TEST_REQUIRE_STR(akerr_name_for_status(AKBASIC_ERR_STATE, NULL), "State Error");
    TEST_REQUIRE_STR(akerr_name_for_status(AKBASIC_ERR_DEVICE, NULL), "Device Error");

    /*
     * The sentinel must stay inside the band it terminates. If somebody ever adds
     * 250 codes, the loop above walks straight out of our reservation and starts
     * asserting on names libakgl or nobody owns.
     */
    TEST_REQUIRE(AKBASIC_ERR_LAST < AKBASIC_ERR_LIMIT,
		 "AKBASIC_ERR_LAST %d has run past the reserved band ending at %d",
		 AKBASIC_ERR_LAST, AKBASIC_ERR_LIMIT);

    /*
     * The assertion that proves the range is actually ours rather than merely
     * unclaimed: a different owner must be refused.
     */
    TEST_REQUIRE_STATUS(akerr_register_status_name("not-akbasic", AKBASIC_ERR_SYNTAX, "Hijacked"),
			AKERR_STATUS_NAME_FOREIGN);
    TEST_REQUIRE_STATUS(akerr_reserve_status_range(AKBASIC_ERR_BASE, 4, "not-akbasic"),
			AKERR_STATUS_RANGE_OVERLAP);

    /* The band must sit clear of libakerror's reserved 0-255. */
    TEST_REQUIRE(AKBASIC_ERR_BASE >= AKERR_FIRST_CONSUMER_STATUS,
		 "AKBASIC_ERR_BASE %d is inside libakerror's reserved band",
		 AKBASIC_ERR_BASE);

    return akbasic_test_failures;
}
