/** * @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 #include #include #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; }