/**
 * @file version_check.c
 * @brief Tests that the loaded dependencies match the headers we compiled against.
 *
 * The soname normally catches a mismatch at load time. This earns its keep when
 * the soname is bypassed -- a 0.2.0 dropped in under the 0.1 filename loads
 * happily, and only the check notices.
 */

#include <string.h>

#include <akstdlib.h>

#include <akbasic/error.h>

#include "testutil.h"

int main(void)
{
    int major = 0;
    int minor = 0;
    int patch = 0;

    TEST_REQUIRE_OK(akbasic_error_register());

    /*
     * AKSL_VERSION_CHECK() is a macro on purpose: it expands here so it captures
     * the numbers *this* translation unit was built with, and compares them to
     * the ones baked into the library that actually loaded.
     */
    TEST_REQUIRE_OK(AKSL_VERSION_CHECK());

    TEST_REQUIRE_OK(aksl_version(&major, &minor, &patch));
    TEST_REQUIRE_INT(major, AKSL_VERSION_MAJOR);
    TEST_REQUIRE_INT(minor, AKSL_VERSION_MINOR);
    TEST_REQUIRE_STR(aksl_version_string(), AKSL_VERSION_STRING);
    TEST_REQUIRE_STR(aksl_version_soname(), AKSL_VERSION_SONAME);

    /*
     * While libakstdlib's major is 0 the soname carries MAJOR.MINOR, so 0.1 and
     * 0.2 are different ABIs. Asserting the shape here means a future 1.0 bump
     * that forgets to change the soname rule fails a test rather than shipping.
     */
    if ( major == 0 ) {
	char expected[32];
	snprintf(expected, sizeof(expected), "%d.%d", major, minor);
	TEST_REQUIRE_STR(aksl_version_soname(), expected);
    }

    /*
     * libakerror publishes no version macro at all, so there is nothing to
     * compare. Its floor is the two #errors akbasic/error.h carries -- if this
     * file compiled, both guards passed. What is asserted here is the *value* of
     * what they test, because a guard that only checks a macro is defined passes
     * against a header that defines it to something else entirely.
     */
    TEST_REQUIRE_INT(AKERR_FIRST_CONSUMER_STATUS, 256);
    TEST_REQUIRE_INT(AKERR_THREAD_SAFE, 1);

    /*
     * The one that matters most to this band. AKBASIC_ERR_BASE is 512, and a
     * process exit status is one byte: 512 truncates to 0, so before libakerror
     * 2.0.1 an unhandled AKBASIC_ERR_SYNTAX exited *success*. akerr_exit()
     * substitutes 125 for anything a byte cannot carry.
     *
     * Asserted as a number rather than trusted as a macro because this is the
     * value a supervisor watching $? actually sees, and 125 is chosen to sit
     * clear of the 1-124 range a program is likely to use for itself.
     */
    TEST_REQUIRE_INT(AKERR_EXIT_STATUS_UNREPRESENTABLE, 125);
    TEST_REQUIRE((AKBASIC_ERR_BASE & 0xff) == 0,
		 "AKBASIC_ERR_BASE %d no longer truncates to zero -- if the band moved, "
		 "the exit-status hazard this guards moved with it",
		 AKBASIC_ERR_BASE);

    return akbasic_test_failures;
}
