From 5ad5cb5a1b5642f40e3df158ff1979de8487dc10 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov <0x7fffff@guattari.ru> Date: Fri, 19 Aug 2022 16:09:33 +0400 Subject: Signals for test environment --- source/kit_test/test.c | 79 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 9 deletions(-) (limited to 'source/kit_test/test.c') diff --git a/source/kit_test/test.c b/source/kit_test/test.c index dea8a23..505392e 100644 --- a/source/kit_test/test.c +++ b/source/kit_test/test.c @@ -4,15 +4,17 @@ #include #include +#include +#include + kit_tests_list_t kit_tests_list = { 0 }; -static void report(int i, char const *file, int line, int ok) { +static void report(int i, int line, int ok) { int const n = kit_tests_list.tests[i].assertions++; if (n >= KIT_TEST_ASSERTIONS_LIMIT) return; - kit_tests_list.tests[i].file[n] = file; kit_tests_list.tests[i].line[n] = line; kit_tests_list.tests[i].status[n] = ok; } @@ -40,16 +42,63 @@ static void color_code(int term_color, int c) { } } -void kit_test_register(char const *name, kit_test_run_fn fn) { +void kit_test_register(char const *name, char const *file, + kit_test_run_fn fn) { int n = kit_tests_list.size++; if (n < KIT_TESTS_SIZE_LIMIT) { kit_tests_list.tests[n].test_fn = fn; kit_tests_list.tests[n].test_name = name; + kit_tests_list.tests[n].test_file = file; kit_tests_list.tests[n].assertions = 0; } } +static jmp_buf kit_test_restore_execution; + +static int const signums[] = { SIGILL, SIGABRT, SIGFPE, SIGSEGV, + SIGTERM }; + +static char const *const signames[] = { + [SIGILL] = "Illegal instruction", + [SIGABRT] = "Abnormal termination", + [SIGFPE] = "Erroneous arithmetic operation", + [SIGSEGV] = "Invalid access to storage", + [SIGTERM] = "Termination request" +}; + +static void handle_signal(int signum) { + longjmp(kit_test_restore_execution, signum); +} + +static void setup_signals() { + for (int i = 0; i < sizeof signums / sizeof *signums; i++) { +#if defined(_WIN32) && !(defined __CYGWIN__) + signal(signums[i], handle_signal); +#else + struct sigaction action; + memset(&action, 0, sizeof action); + action.sa_handler = handle_signal; + + sigaction(signums[i], &action, NULL); +#endif + } +} + +static int run_test(volatile int i) { + int signum = setjmp(kit_test_restore_execution); + + if (signum != 0) { + kit_tests_list.tests[i].signal = signum; + return 0; + } + + kit_tests_list.tests[i].test_fn(i, report); + return 1; +} + int kit_run_tests(int argc, char **argv) { + setup_signals(); + int success_count = 0; int fail_assertion_count = 0; int total_assertion_count = 0; @@ -81,7 +130,7 @@ int kit_run_tests(int argc, char **argv) { struct timespec begin, end; timespec_get(&begin, TIME_UTC); - kit_tests_list.tests[i].test_fn(i, report); + int test_status = run_test(i); timespec_get(&end, TIME_UTC); int duration = (int) (ns_to_ms(end.tv_nsec - begin.tv_nsec) + @@ -90,8 +139,6 @@ int kit_run_tests(int argc, char **argv) { if (carriage_return) quiet || printf("\r"); - int test_status = 1; - for (int j = 0; j < kit_tests_list.tests[i].assertions; j++) if (kit_tests_list.tests[i].status[j] == 0) { fail_assertion_count++; @@ -139,18 +186,32 @@ int kit_run_tests(int argc, char **argv) { if (status != 0) { for (int i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT; i++) { + if (kit_tests_list.tests[i].signal != 0) { + int signum = kit_tests_list.tests[i].signal; + if (signum >= 0 && + signum < sizeof signames / sizeof *signames) + quiet || + printf("Signal \"%s\" (%d) for \"%s\" in \"%s\"!\n", + signames[signum], signum, + kit_tests_list.tests[i].test_name, + kit_tests_list.tests[i].test_file); + else + quiet || + printf("Unknown signal (%d) for \"%s\" in \"%s\"!\n", + signum, kit_tests_list.tests[i].test_name, + kit_tests_list.tests[i].test_file); + } if (kit_tests_list.tests[i].assertions > KIT_TEST_ASSERTIONS_LIMIT) quiet || printf("Too many assertions for \"%s\" in \"%s\"!\n", kit_tests_list.tests[i].test_name, - kit_tests_list.tests[i] - .file[KIT_TEST_ASSERTIONS_LIMIT - 1]); + kit_tests_list.tests[i].test_file); else for (int j = 0; j < kit_tests_list.tests[i].assertions; j++) if (!kit_tests_list.tests[i].status[j]) quiet || printf("Assertion on line %d in \"%s\" failed\n", kit_tests_list.tests[i].line[j], - kit_tests_list.tests[i].file[j]); + kit_tests_list.tests[i].test_file); } quiet || printf("\n"); -- cgit v1.2.3