diff options
author | sanine <sanine.not@pm.me> | 2022-12-21 20:11:30 -0600 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-12-21 20:11:30 -0600 |
commit | 423082adc4b8d0e8964ca73e79ed7d9ac8b391a3 (patch) | |
tree | 7842320ed549e6487daa4c14070cfd2416e8731a | |
parent | 182b4002e63f330de6150e160a1ad23b1e6b33b8 (diff) |
add example
-rw-r--r-- | example/sum.c | 29 | ||||
-rw-r--r-- | lily-test.h | 81 | ||||
-rw-r--r-- | tests/assertions.c | 30 | ||||
-rw-r--r-- | tests/tests.h | 1 |
4 files changed, 131 insertions, 10 deletions
diff --git a/example/sum.c b/example/sum.c new file mode 100644 index 0000000..d9d1221 --- /dev/null +++ b/example/sum.c @@ -0,0 +1,29 @@ +#define LILY_IMPLEMENTATION +#include "lily-test.h" + +int sum(int a, int b) +{ + return 0; +} + + +LILY_FILE_BEGIN(sum_suite) + +LILY_TEST("sums are correct") +{ + CHECK_EQ(sum(0, 0), 0, "%d"); + CHECK_EQ(sum(1, 0), 1, "%d"); + INFO("this is some info"); + CHECK_EQ(sum(2, 2), 4, "%d"); +} +#include LILY_PUSH_TEST() + +#define LILY_FILE_END +#include LILY_REGISTER_TESTS() + + +int main() +{ + sum_suite(); + return 0; +} diff --git a/lily-test.h b/lily-test.h index c9ae02d..1bc4e74 100644 --- a/lily-test.h +++ b/lily-test.h @@ -55,6 +55,7 @@ #include <setjmp.h> #include <stdio.h> #include <stdarg.h> +#include <stdlib.h> #define STR_IMP(x) #x #define STR(x) STR_IMP(x) @@ -89,7 +90,10 @@ typedef struct lily_ll_node_t { void (*f)(); } lily_ll_node_t; #define LILY_FILE_BEGIN(unique_id) \ -static lily_ll_node_t lily_ll_last = { NULL, NULL }; +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 @@ -98,15 +102,21 @@ static lily_ll_node_t lily_ll_last = { NULL, NULL }; #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_(f, desc_str, description) \ -static const char * const desc_str = 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_FUNC, LILY_ANON_DESC, description) +#define LILY_TEST(description) LILY_TEST_(LILY_ANON_WRAP, LILY_ANON_FUNC, LILY_ANON_DESC, description) /* assertions */ typedef struct lily_test_msg_t { @@ -124,23 +134,36 @@ void lily_info(const char *location, const char *fmt, ...); void lily_check(int x, const char *location, const char *fmt, ...); #define LILY_CHECK_(str, x, location) \ - lily_check(x, location, "%s", str) + 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_EQ_(test, location, fmt, x, y, xstr, ystr) \ + lily_check(test, location, "CHECK failed: %s == %s (" fmt " == " fmt ")", xstr, ystr, x, y) +#define LILY_CHECK_EQ(x, y, xstr, ystr, fmt) LILY_CHECK_EQ_(x == y, LILY_LOCATION, fmt, x, y, xstr, ystr) +#define CHECK_EQ(x, y, fmt) LILY_CHECK_EQ(x, y, #x, #y, fmt) + void lily_require(int x, const char *location, const char *fmt, ...); #define LILY_REQUIRE_(str, x, location) \ - lily_require(x, location, "%s", str) + 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) +void lily_run_test(void (*test)()); + + 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; } extern lily_g; #ifdef LILY_IMPLEMENTATION @@ -172,6 +195,11 @@ lily_test_msg_t *lily_msg_create(const char *location, const char *fmt, va_list 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); @@ -182,6 +210,31 @@ void lily_msg_destroy(lily_test_msg_t *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) { + printf("================================================================================\n\n"); + printf("test \"%s\" failed!\n\n", lily_g.test_name); + lily_test_msg_t *n = lily_g.HEAD.next; + while(n != NULL) { + printf(" %s\n [%s]\n\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; @@ -195,8 +248,11 @@ void lily_info(const char *location, const char *fmt, ...) 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); @@ -211,8 +267,11 @@ void lily_check(int x, const char *location, const char *fmt, ...) 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); @@ -548,6 +607,14 @@ void lily_require(int x, const char *location, const char *fmt, ...) #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 */ @@ -558,7 +625,7 @@ static lily_ll_node_t LILY_ANON_NODE = { &LILY_LIST_HEAD, #define LILY_COUNTER_INCREMENT #include LILY_TEST_H_LOCATION - LILY_ANON_FUNC, + LILY_ANON_WRAP, }; #undef LILY_LIST_HEAD #define LILY_LIST_HEAD LILY_ANON_NODE diff --git a/tests/assertions.c b/tests/assertions.c index 156a484..5a32854 100644 --- a/tests/assertions.c +++ b/tests/assertions.c @@ -49,14 +49,14 @@ const char * test_CHECK() return "CHECK did not append any failure messages"; lily_test_msg_t *m = lily_g.HEAD.next; - if (strcmp(m->msg, "1 == 0") != 0) + if (strcmp(m->msg, "CHECK failed: 1 == 0") != 0) return "first assert has wrong message"; if (m->next == NULL) return "only one message appended"; m = m->next; - if (strcmp(m->msg, "4 == 3") != 0) + if (strcmp(m->msg, "CHECK failed: 4 == 3") != 0) return "second message is incorrect"; if (m->next != NULL) @@ -71,6 +71,30 @@ const char * test_CHECK() } +const char * test_CHECK_EQ() +{ + lily_g.HEAD.next = NULL; + lily_g.TAIL = &(lily_g.HEAD); + lily_g.failed = 0; + + int k = 5; + CHECK_EQ(k, 5, "%d"); + CHECK_EQ(4, k, "%02d"); + + if (lily_g.HEAD.next == NULL) + return "CHECK_EQ did not append any failure message"; + + if (lily_g.HEAD.next->next != NULL) + return "CHECK_EQ appended more than one message"; + + if (strcmp(lily_g.HEAD.next->msg, "CHECK failed: 4 == k (04 == 05)") != 0) + return "incorrect message"; + + lily_msg_destroy(lily_g.HEAD.next); + return 0; +} + + int aR, bR; static void f_test_REQUIRE() { @@ -94,7 +118,7 @@ const char * test_REQUIRE() if (lily_g.HEAD.next == NULL) return "test did not generate any messages"; - if (strcmp(lily_g.HEAD.next->msg, "2+2 == 5") != 0) + if (strcmp(lily_g.HEAD.next->msg, "REQUIRE failed: 2+2 == 5") != 0) return "test generated incorrect message"; if (lily_g.HEAD.next->next != NULL) diff --git a/tests/tests.h b/tests/tests.h index 2942fa3..393da87 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -14,6 +14,7 @@ int validate_message(const char* received, const char* expected, X(test_auto_registration) \ X(test_INFO) \ X(test_CHECK) \ + X(test_CHECK_EQ) \ X(test_REQUIRE) \ #define X(test) const char * test(); |