/**************************************************************** * * ======== lily-test ======== * * a midsize C unit testing library * copyright (c) 2022 kate swanson (sanine) * * This is anti-capitalist software, released for free use by individuals and * organizations that do not operate by capitalist principles. * * Permission is hereby granted, free of charge, to any person or * organization (the "User") obtaining a copy of this software and associated * documentation files (the "Software"), to use, copy, modify, merge, * distribute, and/or sell copies of the Software, subject to the following * conditions: * * 1. The above copyright notice and this permission notice shall be included * in all copies or modified versions of the Software. * * 2. The User is one of the following: * a. An individual person, laboring for themselves * b. A non-profit organization * c. An educational institution * d. An organization that seeks shared profit for all of its members, and * allows non-members to set the cost of their labor * * 3. If the User is an organization with owners, then all owners are workers * and all workers are owners with equal equity and/or equal vote. * * 4. If the User is an organization, then the User is not law enforcement or * military, or working for or under either. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT EXPRESS OR IMPLIED WARRANTY OF * ANY KIND, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * https://anticapitalist.software/ * https://sanine.net * ****************************************************************/ #ifndef LILY_TEST_H #define LILY_TEST_H #define LILY_VERSION_MAJOR 2 #define LILY_VERSION_MINOR 0 #define LILY_VERSION_PATCH 0 #include #include #include #include #include #include #include #include #define STR_IMP(x) #x #define STR(x) STR_IMP(x) /* define SOURCE_PATH_SIZE to strip away the leading parts of the full compilation path */ #ifndef SOURCE_PATH_SIZE #define LILY_LOCATION (__FILE__ ":" STR(__LINE__)) #else #define LILY_LOCATION ((__FILE__ ":" STR(__LINE__)) + SOURCE_PATH_SIZE) #endif /* self-location macro */ #ifndef LILY_TEST_H_LOCATION #define LILY_TEST_H_LOCATION "lily-test.h" #endif /* counter macros */ #define LILY_HEX_(x) 0x##x #define LILY_HEX(x) LILY_HEX_(x) #define LILY_COUNTER_POS_0 0 #define LILY_COUNTER_POS_1 0 #define LILY_COUNTER_POS_2 0 #define LILY_COUNTER__(a, b, c) 0x##a##b##c #define LILY_COUNTER_(a, b, c) LILY_COUNTER__(a, b, c) #define LILY_COUNTER LILY_COUNTER_(LILY_COUNTER_POS_2, LILY_COUNTER_POS_1, LILY_COUNTER_POS_0) /* automatic registration macros */ typedef struct lily_ll_node_t { struct lily_ll_node_t *next; void (*f)(); } lily_ll_node_t; #define LILY_FILE_BEGIN(unique_id) \ static lily_ll_node_t lily_ll_last = { NULL, NULL }; \ static void file_runner(); \ void (*unique_id)() = file_runner; #define LILY_LIST_HEAD lily_ll_last #define LILY_LIST_NEXT lily_ll_last #define LILY_PUSH_TEST() LILY_TEST_H_LOCATION #define LILY_REGISTER_TESTS() LILY_TEST_H_LOCATION #define LILY_CAT_(x, y) x##y #define LILY_CAT(x, y) LILY_CAT_(x, y) #define LILY_ANON(x) LILY_CAT(x, LILY_COUNTER) #define LILY_ANON_WRAP LILY_ANON(LILY_WRAP_) #define LILY_ANON_FUNC LILY_ANON(LILY_FUNCTION_) #define LILY_ANON_NODE LILY_ANON(LILY_NODE_) #define LILY_ANON_DESC LILY_ANON(LILY_DESCRIPTION_) #define LILY_TEST_(wrap, f, desc_str, description) \ static void f(); \ static void wrap() \ { \ lily_g.test_name = description; \ f(); \ } \ static void f() #define LILY_TEST(description) LILY_TEST_(LILY_ANON_WRAP, LILY_ANON_FUNC, LILY_ANON_DESC, description) /* assertions */ typedef struct lily_test_msg_t { struct lily_test_msg_t *next; char *msg; const char *location; } lily_test_msg_t; void lily_msg_destroy(lily_test_msg_t *m); void lily_info(const char *location, const char *fmt, ...); #define LILY_INFO_(location, ...) \ lily_info(location, __VA_ARGS__) #define LILY_INFO(...) LILY_INFO_(LILY_LOCATION, __VA_ARGS__) #define INFO(...) LILY_INFO(__VA_ARGS__) void lily_check(int x, const char *location, const char *fmt, ...); #define LILY_CHECK_(str, x, location) \ lily_check(x, location, "CHECK failed: %s", str) #define LILY_CHECK(x) LILY_CHECK_(STR(x), x, LILY_LOCATION) #define CHECK(x) LILY_CHECK(x) #define LILY_CHECK_CMP_(x, y, xstr, ystr, cmp, cmpstr, fmt) \ lily_check(x cmp y, LILY_LOCATION, \ "CHECK failed: %s " cmpstr " %s\n %s = " fmt "\n %s = " fmt,\ xstr, ystr, xstr, x, ystr, y) #define LILY_CHECK_CMP(x, cmp, y, fmt) LILY_CHECK_CMP_(x, y, #x, #y, cmp, #cmp, fmt) /* check comparision assertions */ #define CHECK_EQ(x, y, fmt) LILY_CHECK_CMP(x, ==, y, fmt) #define CHECK_NEQ(x, y, fmt) LILY_CHECK_CMP(x, !=, y, fmt) #define CHECK_LT(x, y, fmt) LILY_CHECK_CMP(x, <, y, fmt) #define CHECK_LE(x, y, fmt) LILY_CHECK_CMP(x, <=, y, fmt) #define CHECK_GT(x, y, fmt) LILY_CHECK_CMP(x, >, y, fmt) #define CHECK_GE(x, y, fmt) LILY_CHECK_CMP(x, >=, y, fmt) #define LILY_CHECK_EQF(x, y, xstr, ystr, fmt) \ lily_check(fabs(x-y) < lily_g.epsilon, LILY_LOCATION, \ "CHECK failed: %s == %s\n %s = " fmt "\n %s = " fmt "\n epsilon: %f", \ xstr, ystr, xstr, x, ystr, y, lily_g.epsilon) #define CHECK_EQF(x, y, fmt) LILY_CHECK_EQF(x, y, #x, #y, fmt) #define LILY_CHECK_EQS(x, y, xstr, ystr) \ lily_check(strcmp(x, y) == 0, LILY_LOCATION, \ "CHECK failed: %s == %s\n %s = \"%s\"\n %s = \"%s\"", \ xstr, ystr, xstr, x, ystr, y) #define CHECK_EQS(x, y) LILY_CHECK_EQS(x, y, #x, #y) void lily_require(int x, const char *location, const char *fmt, ...); #define LILY_REQUIRE_(str, x, location) \ lily_require(x, location, "REQUIRE failed: %s", str) #define LILY_REQUIRE(x) LILY_REQUIRE_(STR(x), x, LILY_LOCATION) #define REQUIRE(x) LILY_REQUIRE(x) #define LILY_REQUIRE_CMP_(x, y, xstr, ystr, cmp, cmpstr, fmt) \ lily_require(x cmp y, LILY_LOCATION, \ "REQUIRE failed: %s " cmpstr " %s\n %s = " fmt "\n %s = " fmt,\ xstr, ystr, xstr, x, ystr, y) #define LILY_REQUIRE_CMP(x, cmp, y, fmt) LILY_REQUIRE_CMP_(x, y, #x, #y, cmp, #cmp, fmt) /* require comparison assertions */ #define REQUIRE_EQ(x, y, fmt) LILY_REQUIRE_CMP(x, ==, y, fmt) #define REQUIRE_NEQ(x, y, fmt) LILY_REQUIRE_CMP(x, !=, y, fmt) #define REQUIRE_LT(x, y, fmt) LILY_REQUIRE_CMP(x, <, y, fmt) #define REQUIRE_LE(x, y, fmt) LILY_REQUIRE_CMP(x, <=, y, fmt) #define REQUIRE_GT(x, y, fmt) LILY_REQUIRE_CMP(x, >, y, fmt) #define REQUIRE_GE(x, y, fmt) LILY_REQUIRE_CMP(x, >=, y, fmt) #define LILY_REQUIRE_EQF(x, y, xstr, ystr, fmt) \ lily_require(fabs(x-y) < lily_g.epsilon, LILY_LOCATION, \ "REQUIRE failed: %s == %s\n %s = " fmt "\n %s = " fmt "\n epsilon: %f", \ xstr, ystr, xstr, x, ystr, y, lily_g.epsilon) #define REQUIRE_EQF(x, y, fmt) LILY_REQUIRE_EQF(x, y, #x, #y, fmt) #define LILY_REQUIRE_EQS(x, y, xstr, ystr) \ lily_require(strcmp(x, y) == 0, LILY_LOCATION, \ "REQUIRE failed: %s == %s\n %s = \"%s\"\n %s = \"%s\"", \ xstr, ystr, xstr, x, ystr, y) #define REQUIRE_EQS(x, y) LILY_REQUIRE_EQS(x, y, #x, #y) void lily_begin(); void lily_finish(); void lily_run_test(void (*test)()); void lily_set_epsilon(double epsilon); struct lily_global_t { int failed; jmp_buf env; const char *test_name; lily_test_msg_t HEAD; lily_test_msg_t *TAIL; int n_assertions; int n_assertions_failed; int n_tests; int n_tests_failed; double epsilon; } extern lily_g; #ifdef LILY_IMPLEMENTATION struct lily_global_t lily_g; lily_test_msg_t *lily_msg_create(const char *location, const char *fmt, va_list args) { lily_test_msg_t *m = malloc(sizeof(lily_test_msg_t)); if (m == NULL) { return NULL; } m->next = NULL; m->location = location; va_list args_len; va_copy(args_len, args); size_t len = vsnprintf(NULL, 0, fmt, args_len) + 1; va_end(args_len); m->msg = malloc(len * sizeof(char)); if (m->msg == NULL) { free(m); return NULL; } vsnprintf(m->msg, len, fmt, args); return m; } void lily_msg_destroy(lily_test_msg_t *m) { if (m == NULL) { /* ignore */ return; } if (m->next != NULL) { // destroy the whole chain lily_msg_destroy(m->next); } free(m->msg); free(m); } void lily_run_test(void (*test)()) { lily_g.n_tests += 1; lily_g.HEAD.next = NULL; lily_g.TAIL = &(lily_g.HEAD); lily_g.failed = 0; int jumped = setjmp(lily_g.env); if (!jumped) { test(); } if (lily_g.failed) { lily_g.n_tests_failed += 1; printf("================================================================================\n"); printf("test \"%s\" failed!\n", lily_g.test_name); lily_test_msg_t *n = lily_g.HEAD.next; while(n != NULL) { printf(" %s\n [%s]\n", n->msg, n->location); n = n->next; } lily_msg_destroy(lily_g.HEAD.next); } } void lily_info(const char *location, const char *fmt, ...) { va_list args; va_start(args, fmt); lily_test_msg_t *m = lily_msg_create(location, fmt, args); va_end(args); lily_g.TAIL->next = m; lily_g.TAIL = m; } void lily_check(int x, const char *location, const char *fmt, ...) { lily_g.n_assertions += 1; if (!x) { // assertion failed lily_g.n_assertions_failed += 1; va_list args; va_start(args, fmt); lily_test_msg_t *m = lily_msg_create(location, fmt, args); va_end(args); lily_g.TAIL->next = m; lily_g.TAIL = m; lily_g.failed = 1; } } void lily_require(int x, const char *location, const char *fmt, ...) { lily_g.n_assertions += 1; if (!x) { // assertion failed lily_g.n_assertions_failed += 1; va_list args; va_start(args, fmt); lily_test_msg_t *m = lily_msg_create(location, fmt, args); va_end(args); lily_g.TAIL->next = m; lily_g.TAIL = m; lily_g.failed = 1; /* longjump out of test */ longjmp(lily_g.env, 1); } } void lily_begin() { lily_g.n_tests = 0; lily_g.n_tests_failed = 0; lily_g.n_assertions_failed = 0; lily_g.n_assertions_failed = 0; lily_g.epsilon = 1e-3; printf("================================================================================\n"); printf("lily-test version %d.%d.%d\n", LILY_VERSION_MAJOR, LILY_VERSION_MINOR, LILY_VERSION_PATCH); } void lily_finish() { printf("================================================================================\n"); printf("ran %d tests (%d failed)\n", lily_g.n_tests, lily_g.n_tests_failed); printf("checked %d asserts (%d failed)\n", lily_g.n_assertions, lily_g.n_assertions_failed); } void lily_set_epsilon(double epsilon) { lily_g.epsilon = epsilon; } #endif /* ifdef LILY_TEST_H */ #else /* counter incrementing */ /* this counter can count up to 4096, but it should be pretty trivial to extend it more or less arbitrarily far */ /* to increment the counter, just #define LILY_COUNTER_INCREMENT and then include this file again */ #ifdef LILY_COUNTER_INCREMENT #undef LILY_COUNTER_INCREMENT /* ones position */ # if LILY_HEX(LILY_COUNTER_POS_0) == 0 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 1 # elif LILY_HEX(LILY_COUNTER_POS_0) == 1 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 2 # elif LILY_HEX(LILY_COUNTER_POS_0) == 2 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 3 # elif LILY_HEX(LILY_COUNTER_POS_0) == 3 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 4 # elif LILY_HEX(LILY_COUNTER_POS_0) == 4 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 5 # elif LILY_HEX(LILY_COUNTER_POS_0) == 5 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 6 # elif LILY_HEX(LILY_COUNTER_POS_0) == 6 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 7 # elif LILY_HEX(LILY_COUNTER_POS_0) == 7 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 8 # elif LILY_HEX(LILY_COUNTER_POS_0) == 8 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 9 # elif LILY_HEX(LILY_COUNTER_POS_0) == 9 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 a # elif LILY_HEX(LILY_COUNTER_POS_0) == 10 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 b # elif LILY_HEX(LILY_COUNTER_POS_0) == 11 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 c # elif LILY_HEX(LILY_COUNTER_POS_0) == 12 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 d # elif LILY_HEX(LILY_COUNTER_POS_0) == 13 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 e # elif LILY_HEX(LILY_COUNTER_POS_0) == 14 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 f # elif LILY_HEX(LILY_COUNTER_POS_0) == 15 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 0 /* sixteens position */ # if LILY_HEX(LILY_COUNTER_POS_1) == 0 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 1 # elif LILY_HEX(LILY_COUNTER_POS_1) == 1 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 2 # elif LILY_HEX(LILY_COUNTER_POS_1) == 2 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 3 # elif LILY_HEX(LILY_COUNTER_POS_1) == 3 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 4 # elif LILY_HEX(LILY_COUNTER_POS_1) == 4 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 5 # elif LILY_HEX(LILY_COUNTER_POS_1) == 5 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 6 # elif LILY_HEX(LILY_COUNTER_POS_1) == 6 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 7 # elif LILY_HEX(LILY_COUNTER_POS_1) == 7 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 8 # elif LILY_HEX(LILY_COUNTER_POS_1) == 8 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 9 # elif LILY_HEX(LILY_COUNTER_POS_1) == 9 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 a # elif LILY_HEX(LILY_COUNTER_POS_1) == 10 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 b # elif LILY_HEX(LILY_COUNTER_POS_1) == 11 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 c # elif LILY_HEX(LILY_COUNTER_POS_1) == 12 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 d # elif LILY_HEX(LILY_COUNTER_POS_1) == 13 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 e # elif LILY_HEX(LILY_COUNTER_POS_1) == 14 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 f # elif LILY_HEX(LILY_COUNTER_POS_1) == 15 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 0 /* 256s position */ # if LILY_HEX(LILY_COUNTER_POS_2) == 0 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 1 # elif LILY_HEX(LILY_COUNTER_POS_2) == 1 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 2 # elif LILY_HEX(LILY_COUNTER_POS_2) == 2 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 3 # elif LILY_HEX(LILY_COUNTER_POS_2) == 3 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 4 # elif LILY_HEX(LILY_COUNTER_POS_2) == 4 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 5 # elif LILY_HEX(LILY_COUNTER_POS_2) == 5 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 6 # elif LILY_HEX(LILY_COUNTER_POS_2) == 6 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 7 # elif LILY_HEX(LILY_COUNTER_POS_2) == 7 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 8 # elif LILY_HEX(LILY_COUNTER_POS_2) == 8 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 9 # elif LILY_HEX(LILY_COUNTER_POS_2) == 9 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 a # elif LILY_HEX(LILY_COUNTER_POS_2) == 10 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 b # elif LILY_HEX(LILY_COUNTER_POS_2) == 11 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 c # elif LILY_HEX(LILY_COUNTER_POS_2) == 12 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 d # elif LILY_HEX(LILY_COUNTER_POS_2) == 13 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 e # elif LILY_HEX(LILY_COUNTER_POS_2) == 14 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 f # elif LILY_HEX(LILY_COUNTER_POS_2) == 15 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 0 # endif # endif # endif #elif defined(LILY_COUNTER_DECREMENT) #undef LILY_COUNTER_DECREMENT /* ones position */ # if LILY_HEX(LILY_COUNTER_POS_0) == 15 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 e # elif LILY_HEX(LILY_COUNTER_POS_0) == 14 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 d # elif LILY_HEX(LILY_COUNTER_POS_0) == 13 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 c # elif LILY_HEX(LILY_COUNTER_POS_0) == 12 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 b # elif LILY_HEX(LILY_COUNTER_POS_0) == 11 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 a # elif LILY_HEX(LILY_COUNTER_POS_0) == 10 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 9 # elif LILY_HEX(LILY_COUNTER_POS_0) == 9 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 8 # elif LILY_HEX(LILY_COUNTER_POS_0) == 8 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 7 # elif LILY_HEX(LILY_COUNTER_POS_0) == 7 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 6 # elif LILY_HEX(LILY_COUNTER_POS_0) == 6 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 5 # elif LILY_HEX(LILY_COUNTER_POS_0) == 5 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 4 # elif LILY_HEX(LILY_COUNTER_POS_0) == 4 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 3 # elif LILY_HEX(LILY_COUNTER_POS_0) == 3 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 2 # elif LILY_HEX(LILY_COUNTER_POS_0) == 2 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 1 # elif LILY_HEX(LILY_COUNTER_POS_0) == 1 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 0 # elif LILY_HEX(LILY_COUNTER_POS_0) == 0 # undef LILY_COUNTER_POS_0 # define LILY_COUNTER_POS_0 f /* sixteens position */ # if LILY_HEX(LILY_COUNTER_POS_1) == 15 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 e # elif LILY_HEX(LILY_COUNTER_POS_1) == 14 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 d # elif LILY_HEX(LILY_COUNTER_POS_1) == 13 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 c # elif LILY_HEX(LILY_COUNTER_POS_1) == 12 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 b # elif LILY_HEX(LILY_COUNTER_POS_1) == 11 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 a # elif LILY_HEX(LILY_COUNTER_POS_1) == 10 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 9 # elif LILY_HEX(LILY_COUNTER_POS_1) == 9 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 8 # elif LILY_HEX(LILY_COUNTER_POS_1) == 8 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 7 # elif LILY_HEX(LILY_COUNTER_POS_1) == 7 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 6 # elif LILY_HEX(LILY_COUNTER_POS_1) == 6 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 5 # elif LILY_HEX(LILY_COUNTER_POS_1) == 5 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 4 # elif LILY_HEX(LILY_COUNTER_POS_1) == 4 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 3 # elif LILY_HEX(LILY_COUNTER_POS_1) == 3 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 2 # elif LILY_HEX(LILY_COUNTER_POS_1) == 2 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 1 # elif LILY_HEX(LILY_COUNTER_POS_1) == 1 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 0 # elif LILY_HEX(LILY_COUNTER_POS_1) == 0 # undef LILY_COUNTER_POS_1 # define LILY_COUNTER_POS_1 f /* 256s position */ # if LILY_HEX(LILY_COUNTER_POS_2) == 15 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 e # elif LILY_HEX(LILY_COUNTER_POS_2) == 14 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 d # elif LILY_HEX(LILY_COUNTER_POS_2) == 13 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 c # elif LILY_HEX(LILY_COUNTER_POS_2) == 12 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 b # elif LILY_HEX(LILY_COUNTER_POS_2) == 11 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 a # elif LILY_HEX(LILY_COUNTER_POS_2) == 10 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 9 # elif LILY_HEX(LILY_COUNTER_POS_2) == 9 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 8 # elif LILY_HEX(LILY_COUNTER_POS_2) == 8 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 7 # elif LILY_HEX(LILY_COUNTER_POS_2) == 7 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 6 # elif LILY_HEX(LILY_COUNTER_POS_2) == 6 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 5 # elif LILY_HEX(LILY_COUNTER_POS_2) == 5 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 4 # elif LILY_HEX(LILY_COUNTER_POS_2) == 4 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 3 # elif LILY_HEX(LILY_COUNTER_POS_2) == 3 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 2 # elif LILY_HEX(LILY_COUNTER_POS_2) == 2 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 1 # elif LILY_HEX(LILY_COUNTER_POS_2) == 1 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 0 # elif LILY_HEX(LILY_COUNTER_POS_2) == 0 # undef LILY_COUNTER_POS_2 # define LILY_COUNTER_POS_2 f # endif # endif # endif #elif defined(LILY_FILE_END) /* ending a file */ /* LILY_LIST_HEAD is one too high, so we decrement */ #define LILY_COUNTER_DECREMENT #include LILY_TEST_H_LOCATION void file_runner() { lily_ll_node_t *n = &LILY_LIST_HEAD; while (n->next != NULL) { lily_run_test(n->f); n = n->next; } } #else /* register new test */ static lily_ll_node_t LILY_ANON_NODE = { #define LILY_COUNTER_DECREMENT #include LILY_TEST_H_LOCATION &LILY_LIST_HEAD, #define LILY_COUNTER_INCREMENT #include LILY_TEST_H_LOCATION LILY_ANON_WRAP, }; #undef LILY_LIST_HEAD #define LILY_LIST_HEAD LILY_ANON_NODE #define LILY_COUNTER_INCREMENT #include LILY_TEST_H_LOCATION #endif #endif