aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/simple-test.h448
1 files changed, 213 insertions, 235 deletions
diff --git a/src/simple-test.h b/src/simple-test.h
index b1dbfdf..63da668 100644
--- a/src/simple-test.h
+++ b/src/simple-test.h
@@ -10,11 +10,9 @@
#include <string.h>
-/****************************
- * INTERNAL FUNCTIONALITY *
- ****************************/
-
-
+/**************************************************
+ * INTERNAL FUNCTIONALITY. DO NOT CALL DIRECTLY *
+ **************************************************/
enum simple_test_type {
SIMPLE_TEST_BOOL,
@@ -38,220 +36,8 @@ enum simple_test_cond {
SIMPLE_TEST_LEQ
};
-#define SIMPLE_TEST_TYPE(a) \
- _Generic((a), \
- bool: SIMPLE_TEST_BOOL, \
- char: SIMPLE_TEST_CHAR, \
- int8_t: SIMPLE_TEST_INT, \
- int16_t: SIMPLE_TEST_INT, \
- int32_t: SIMPLE_TEST_INT, \
- int64_t: SIMPLE_TEST_INT, \
- uint8_t: SIMPLE_TEST_UNSIGNED, \
- uint16_t: SIMPLE_TEST_UNSIGNED, \
- uint32_t: SIMPLE_TEST_UNSIGNED, \
- uint64_t: SIMPLE_TEST_UNSIGNED, \
- char *: SIMPLE_TEST_STRING, \
- void *: SIMPLE_TEST_POINTER, \
- default: SIMPLE_TEST_UNKNOWN)
-
-#define SIMPLE_TEST_PASTE_ACTUAL(a, b) \
- a##b
-
-#define SIMPLE_TEST_PASTE(a, b) \
- SIMPLE_TEST_PASTE_ACTUAL(a, b)
-
-#define SIMPLE_TEST_FAIL1(...) \
- do { \
- printf("\e[1m% *c :: at line %d, \e[m\e[1;31mfail: \e[m", \
- simple_test_pad_width, ' ', __LINE__); \
- printf(__VA_ARGS__); \
- printf("\n"); \
- } while (0)
-
-// #define SIMPLE_TEST_PRINT_VAL(a, type) \
-// do { \
-// printf("\e[1m% *c :: ", simple_test_pad_width, ' '); \
-// printf("`%s` \e[m== \e[1m", #a); \
-// switch (type) { \
-// case SIMPLE_TEST_BOOL: \
-// printf("%s", (a) ? "true" : "false"); \
-// break; \
-// case SIMPLE_TEST_CHAR: \
-// printf("%c", (a)); \
-// break; \
-// case SIMPLE_TEST_INT: \
-// printf("%" PRIdMAX, (a)); \
-// break; \
-// case SIMPLE_TEST_UNSIGNED: \
-// printf("%" PRIuMAX, (a)); \
-// break; \
-// case SIMPLE_TEST_STRING: \
-// printf(((a) ? "\"%s\"" : "%s"), (a)); \
-// break; \
-// case SIMPLE_TEST_POINTER: \
-// printf("%p", (a)); \
-// break; \
-// default: \
-// break; \
-// } \
-// printf("\e[m\n"); \
-// } while (0)
-
-#define SIMPLE_TEST_PRINT_VAL(w, s, t) \
- do { \
- printf("\e[1m% *c :: ", simple_test_pad_width, ' '); \
- printf("`%s` \e[m== \e[1m", s); \
- switch (t) { \
- case SIMPLE_TEST_BOOL: \
- printf("%s", (w ? simple_test_il : simple_test_ir) \
- ? "true" : "false"); \
- break; \
- case SIMPLE_TEST_CHAR: \
- printf("%c", w ? simple_test_il : simple_test_ir); \
- break; \
- case SIMPLE_TEST_INT: \
- printf("%" PRIdMAX, w ? simple_test_il : simple_test_ir); \
- break; \
- case SIMPLE_TEST_UNSIGNED: \
- printf("%" PRIuMAX, w ? simple_test_ul : simple_test_ur); \
- break; \
- case SIMPLE_TEST_STRING: \
- printf(((w ? simple_test_sl : simple_test_sr) \
- ? "\"%s\"" : "%s"), w \
- ? simple_test_sl : simple_test_sr); \
- break; \
- case SIMPLE_TEST_POINTER: \
- printf("%p", w ? simple_test_pl : simple_test_pr); \
- break; \
- default: \
- break; \
- } \
- printf("\e[m\n"); \
- } while (0)
-
-#define SIMPLE_TEST_FAIL2 \
- do { \
- simple_test_fail_count++; \
- goto simple_test_loop_end; \
- } while (0)
-
-#define SIMPLE_TEST_ERR(...) \
- do { \
- printf("\e[1m% *c :: at line %d, \e[m\e[1;31merr: \e[m", \
- simple_test_pad_width, ' ', __LINE__); \
- printf(__VA_ARGS__); \
- printf("\n"); \
- exit(1); \
- } while (0)
-
-#define SIMPLE_TEST_PRINT_BUF_WIDTH 512
-
-
-/******************
- * BASIC MACROS *
- ******************/
-
-#define REGISTER_TEARDOWN(f) \
- do { \
- if (simple_test_teardown != NULL) \
- SIMPLE_TEST_ERR("teardown function already defined"); \
- simple_test_teardown = _Generic((f), \
- void(*)(void): (f), default: NULL); \
- if (simple_test_teardown == NULL) { \
- SIMPLE_TEST_ERR( \
- "wrongly-typed function passed to REGISTER_TEARDOWN"); \
- } \
- } while (0)
-
-
-#define USE_TEARDOWN \
- do { \
- if (simple_test_teardown == NULL) \
- SIMPLE_TEST_ERR("teardown function undefined"); \
- simple_test_do_teardown = true; \
- } while (0)
-
-
-
-
-/* must appear before all tests */
-#define BEGIN_TEST \
- int main(int argc, char **argv) \
- { \
- int simple_test_iterator; \
- int simple_test_pad_width = 0; \
- int simple_test_fail_count = 0; \
- char simple_test_print_buf[SIMPLE_TEST_PRINT_BUF_WIDTH]; \
- int simple_test_test_count = 0; \
- int simple_test_test_current = 1; \
- int simple_test_pass_number = 0; \
- bool simple_test_do_teardown = false; \
- void (*simple_test_teardown)(void) = NULL; \
- do { \
- if (simple_test_pass_number == 0) { \
- printf("\e[1mstarting tests in " __FILE__ "...\n"); \
- } else { \
- simple_test_pad_width = sprintf(simple_test_print_buf, \
- "%d", simple_test_test_count) + 1; \
- } \
- for (simple_test_iterator = 0; simple_test_pass_number == 0 && \
- simple_test_iterator < 1; simple_test_iterator++) { \
- (void)0; \
-
-
-#define TEST(description) \
- } \
- if (simple_test_do_teardown) { \
- simple_test_do_teardown = false; \
- simple_test_teardown(); \
- } \
- int SIMPLE_TEST_PASTE(simple_test_test_slot_, __LINE__); \
- if (simple_test_pass_number == 0) { \
- SIMPLE_TEST_PASTE(simple_test_test_slot_, __LINE__) \
- = ++simple_test_test_count; \
- } else if (simple_test_pass_number \
- == SIMPLE_TEST_PASTE(simple_test_test_slot_, __LINE__)) { \
- printf("\e[m% *d \e[1m:: \e[m\e[33m%s\e[m\n", simple_test_pad_width, \
- simple_test_test_current++, description); \
-
-/* must appear after all tests */
-#define END_TEST \
- } \
- if (simple_test_do_teardown) { \
- simple_test_do_teardown = false; \
- simple_test_teardown(); \
- } \
- if (simple_test_test_count == 0) { \
- SIMPLE_TEST_ERR("no tests defined"); \
- } \
-simple_test_loop_end: \
- (void)0; \
- } while (simple_test_pass_number++ < simple_test_test_count); \
- if (simple_test_fail_count) { \
- printf("\e[1;31m%d of %d tests failed\e[m\n", \
- simple_test_fail_count, simple_test_test_count); \
- return 1; \
- } else { \
- printf("\e[1;32mall tests passed!\e[m\n"); \
- return 0; \
- } \
- }
-
-#define ECHO(...) \
- do { \
- printf("\e[1m% *c :: \e[m\e[34m", simple_test_pad_width, ' '); \
- printf(__VA_ARGS__); \
- printf("...\e[m\n"); \
- } while (0)
-
-
-/**********************
- * ASSERTION MACROS *
- **********************/
-
static intmax_t simple_test_il, simple_test_ir;
static uintmax_t simple_test_ul, simple_test_ur;
-static char simple_test_cl, simple_test_cr;
static char *simple_test_sl, *simple_test_sr;
static void *simple_test_pl, *simple_test_pr;
@@ -341,22 +127,40 @@ static int simple_test_assert(enum simple_test_type t,
r = simple_test_sl == NULL;
goto end;
case SIMPLE_TEST_EQ:
- r = strcmp(simple_test_sl, simple_test_sr) ? 0 : 1;
+ if (simple_test_sl == NULL || simple_test_sr == NULL)
+ r = simple_test_sl == simple_test_sr;
+ else
+ r = strcmp(simple_test_sl, simple_test_sr) ? 0 : 1;
goto end;
case SIMPLE_TEST_NEQ:
- r = strcmp(simple_test_sl, simple_test_sr) ? 1 : 0;
+ if (simple_test_sl == NULL || simple_test_sr == NULL)
+ r = simple_test_sl != simple_test_sr;
+ else
+ r = strcmp(simple_test_sl, simple_test_sr) ? 1 : 0;
goto end;
case SIMPLE_TEST_GT:
- r = strcmp(simple_test_sl, simple_test_sr) > 0 ? 1 : 0;
+ if (simple_test_sl == NULL || simple_test_sr == NULL)
+ r = false;
+ else
+ r = strcmp(simple_test_sl, simple_test_sr) > 0 ? 1 : 0;
goto end;
case SIMPLE_TEST_LT:
- r = strcmp(simple_test_sl, simple_test_sr) < 0 ? 1 : 0;
+ if (simple_test_sl == NULL || simple_test_sr == NULL)
+ r = false;
+ else
+ r = strcmp(simple_test_sl, simple_test_sr) < 0 ? 1 : 0;
goto end;
case SIMPLE_TEST_GEQ:
- r = strcmp(simple_test_sl, simple_test_sr) >= 0 ? 1 : 0;
+ if (simple_test_sl == NULL || simple_test_sr == NULL)
+ r = false;
+ else
+ r = strcmp(simple_test_sl, simple_test_sr) >= 0 ? 1 : 0;
goto end;
case SIMPLE_TEST_LEQ:
- r = strcmp(simple_test_sl, simple_test_sr) <= 0 ? 1 : 0;
+ if (simple_test_sl == NULL || simple_test_sr == NULL)
+ r = false;
+ else
+ r = strcmp(simple_test_sl, simple_test_sr) <= 0 ? 1 : 0;
goto end;
}
@@ -403,22 +207,22 @@ static enum simple_test_type simple_test_type_resolve(enum simple_test_type t1,
enum simple_test_type t2)
{
if (t1 != t2) {
- if (t1 == SIMPLE_TEST_INT && t2 == SIMPLE_TEST_UNSIGNED
- || t1 == SIMPLE_TEST_UNSIGNED && t2 == SIMPLE_TEST_INT
- || t1 == SIMPLE_TEST_BOOL && t2 == SIMPLE_TEST_UNSIGNED
- || t1 == SIMPLE_TEST_UNSIGNED && t2 == SIMPLE_TEST_BOOL) {
+ if ((t1 == SIMPLE_TEST_INT && t2 == SIMPLE_TEST_UNSIGNED)
+ || (t1 == SIMPLE_TEST_UNSIGNED && t2 == SIMPLE_TEST_INT)
+ || (t1 == SIMPLE_TEST_BOOL && t2 == SIMPLE_TEST_UNSIGNED)
+ || (t1 == SIMPLE_TEST_UNSIGNED && t2 == SIMPLE_TEST_BOOL)) {
return SIMPLE_TEST_UNSIGNED;
- } else if (t1 == SIMPLE_TEST_BOOL && t2 == SIMPLE_TEST_INT
- || t1 == SIMPLE_TEST_INT && t2 == SIMPLE_TEST_BOOL) {
+ } else if ((t1 == SIMPLE_TEST_BOOL && t2 == SIMPLE_TEST_INT)
+ || (t1 == SIMPLE_TEST_INT && t2 == SIMPLE_TEST_BOOL)) {
return SIMPLE_TEST_INT;
- } else if (t1 == SIMPLE_TEST_INT && t2 == SIMPLE_TEST_CHAR
- || t1 == SIMPLE_TEST_CHAR && t2 == SIMPLE_TEST_INT) {
+ } else if ((t1 == SIMPLE_TEST_INT && t2 == SIMPLE_TEST_CHAR)
+ || (t1 == SIMPLE_TEST_CHAR && t2 == SIMPLE_TEST_INT)) {
return SIMPLE_TEST_CHAR;
- } else if (t1 == SIMPLE_TEST_CHAR && t2 == SIMPLE_TEST_UNSIGNED
- || t1 == SIMPLE_TEST_UNSIGNED && t2 == SIMPLE_TEST_CHAR){
+ } else if ((t1 == SIMPLE_TEST_CHAR && t2 == SIMPLE_TEST_UNSIGNED)
+ || (t1 == SIMPLE_TEST_UNSIGNED && t2 == SIMPLE_TEST_CHAR)) {
return SIMPLE_TEST_UNSIGNED;
- } else if (t1 == SIMPLE_TEST_POINTER && t2 == SIMPLE_TEST_STRING
- || t1 == SIMPLE_TEST_STRING && t2 == SIMPLE_TEST_POINTER){
+ } else if ((t1 == SIMPLE_TEST_POINTER && t2 == SIMPLE_TEST_STRING)
+ || (t1 == SIMPLE_TEST_STRING && t2 == SIMPLE_TEST_POINTER)) {
return SIMPLE_TEST_POINTER;
} else {
return SIMPLE_TEST_MISMATCH;
@@ -428,6 +232,79 @@ static enum simple_test_type simple_test_type_resolve(enum simple_test_type t1,
return t1;
}
+#define SIMPLE_TEST_TYPE(a) \
+ _Generic((a), \
+ bool: SIMPLE_TEST_BOOL, \
+ char: SIMPLE_TEST_CHAR, \
+ int8_t: SIMPLE_TEST_INT, \
+ int16_t: SIMPLE_TEST_INT, \
+ int32_t: SIMPLE_TEST_INT, \
+ int64_t: SIMPLE_TEST_INT, \
+ uint8_t: SIMPLE_TEST_UNSIGNED, \
+ uint16_t: SIMPLE_TEST_UNSIGNED, \
+ uint32_t: SIMPLE_TEST_UNSIGNED, \
+ uint64_t: SIMPLE_TEST_UNSIGNED, \
+ char *: SIMPLE_TEST_STRING, \
+ void *: SIMPLE_TEST_POINTER, \
+ default: SIMPLE_TEST_UNKNOWN)
+
+#define SIMPLE_TEST_FAIL1(...) \
+ do { \
+ printf("\e[1m%*c :: at line %d, \e[m\e[1;31mfail: \e[m", \
+ simple_test_pad_width, ' ', __LINE__); \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ } while (0)
+
+#define SIMPLE_TEST_PRINT_VAL(w, s, t) \
+ do { \
+ printf("\e[1m%*c :: ", simple_test_pad_width, ' '); \
+ printf("`%s` \e[m== \e[1m", s); \
+ switch (t) { \
+ case SIMPLE_TEST_BOOL: \
+ printf("%s", (w ? simple_test_il : simple_test_ir) \
+ ? "true" : "false"); \
+ break; \
+ case SIMPLE_TEST_CHAR: \
+ printf("%c", w ? (char)simple_test_il : (char)simple_test_ir); \
+ break; \
+ case SIMPLE_TEST_INT: \
+ printf("%" PRIdMAX, w ? simple_test_il : simple_test_ir); \
+ break; \
+ case SIMPLE_TEST_UNSIGNED: \
+ printf("%" PRIuMAX, w ? simple_test_ul : simple_test_ur); \
+ break; \
+ case SIMPLE_TEST_STRING: \
+ printf(((w ? simple_test_sl : simple_test_sr) \
+ ? "\"%s\"" : "%s"), w \
+ ? simple_test_sl : simple_test_sr); \
+ break; \
+ case SIMPLE_TEST_POINTER: \
+ printf("%p", w ? simple_test_pl : simple_test_pr); \
+ break; \
+ default: \
+ break; \
+ } \
+ printf("\e[m\n"); \
+ } while (0)
+
+#define SIMPLE_TEST_FAIL2 \
+ do { \
+ simple_test_fail_count++; \
+ goto simple_test_loop_end; \
+ } while (0)
+
+#define SIMPLE_TEST_ERR(...) \
+ do { \
+ printf("\e[1m%*c :: at line %d, \e[m\e[1;31merr: \e[m", \
+ simple_test_pad_width, ' ', __LINE__); \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ exit(1); \
+ } while (0)
+
+#define SIMPLE_TEST_PRINT_BUF_WIDTH 512
+
#define SIMPLE_TEST_ASSERT1(t, c, s, a) \
do { \
switch ( simple_test_assert(t, c, (a)) ) { \
@@ -460,6 +337,107 @@ static enum simple_test_type simple_test_type_resolve(enum simple_test_type t1,
} \
} while (0)
+
+/******************
+ * BASIC MACROS *
+ ******************/
+
+#define REGISTER_TEARDOWN(f) \
+ do { \
+ if (simple_test_teardown != NULL) \
+ SIMPLE_TEST_ERR("teardown function already defined"); \
+ simple_test_teardown = _Generic((f), \
+ void(*)(void): (f), default: NULL); \
+ if (simple_test_teardown == NULL) { \
+ SIMPLE_TEST_ERR( \
+ "wrongly-typed function passed to REGISTER_TEARDOWN"); \
+ } \
+ } while (0)
+
+
+#define USE_TEARDOWN \
+ do { \
+ if (simple_test_teardown == NULL) \
+ SIMPLE_TEST_ERR("teardown function undefined"); \
+ simple_test_do_teardown = true; \
+ } while (0)
+
+/* must appear before all tests */
+#define BEGIN_TEST \
+ int main(int argc, char **argv) \
+ { \
+ int simple_test_iterator; \
+ int simple_test_pad_width = 0; \
+ int simple_test_fail_count = 0; \
+ char simple_test_print_buf[SIMPLE_TEST_PRINT_BUF_WIDTH]; \
+ int simple_test_test_count = 0; \
+ int simple_test_test_current = 1; \
+ int simple_test_test_current_at; \
+ int simple_test_pass_number = 0; \
+ bool simple_test_do_teardown = false; \
+ void (*simple_test_teardown)(void) = NULL; \
+ do { \
+ simple_test_test_current_at = 0; \
+ if (simple_test_pass_number == 0) { \
+ printf("\e[1mstarting tests in " __FILE__ "...\n"); \
+ } else { \
+ simple_test_pad_width = sprintf(simple_test_print_buf, \
+ "%d", simple_test_test_count) + 1; \
+ } \
+ for (simple_test_iterator = 0; simple_test_pass_number == 0 && \
+ simple_test_iterator < 1; simple_test_iterator++) { \
+ (void)0; \
+
+
+#define TEST(description) \
+ } \
+ if (simple_test_do_teardown) { \
+ simple_test_do_teardown = false; \
+ simple_test_teardown(); \
+ } \
+ simple_test_test_current_at++; \
+ if (simple_test_pass_number == 0) { \
+ simple_test_test_count++; \
+ } else if (simple_test_pass_number \
+ == simple_test_test_current_at) { \
+ printf("\e[m%*d \e[1m:: \e[m\e[33m%s\e[m\n", simple_test_pad_width, \
+ simple_test_test_current++, description); \
+
+/* must appear after all tests */
+#define END_TEST \
+ } \
+ if (simple_test_do_teardown) { \
+ simple_test_do_teardown = false; \
+ simple_test_teardown(); \
+ } \
+ if (simple_test_test_count == 0) { \
+ SIMPLE_TEST_ERR("no tests defined"); \
+ } \
+simple_test_loop_end: \
+ (void)0; \
+ } while (simple_test_pass_number++ < simple_test_test_count); \
+ if (simple_test_fail_count) { \
+ printf("\e[1;31m%d of %d tests failed\e[m\n", \
+ simple_test_fail_count, simple_test_test_count); \
+ return 1; \
+ } else { \
+ printf("\e[1;32mall tests passed!\e[m\n"); \
+ return 0; \
+ } \
+ }
+
+#define ECHO(...) \
+ do { \
+ printf("\e[1m%*c :: \e[m\e[34m", simple_test_pad_width, ' '); \
+ printf(__VA_ARGS__); \
+ printf("...\e[m\n"); \
+ } while (0)
+
+
+/**********************
+ * ASSERTION MACROS *
+ **********************/
+
#define ASSERT(a) \
SIMPLE_TEST_ASSERT1(SIMPLE_TEST_TYPE((a)), SIMPLE_TEST_TRUE, "ASSERT", a)