diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/kit_test/test.c | 79 | ||||
-rw-r--r-- | source/kit_test/test.h | 16 | ||||
-rw-r--r-- | source/test/programs/CMakeLists.txt | 10 | ||||
-rw-r--r-- | source/test/programs/signals.c | 18 | ||||
-rw-r--r-- | source/test/programs/too_many_tests.c | 2 | ||||
-rw-r--r-- | source/test/unittests/test_duration.test.c | 2 |
6 files changed, 109 insertions, 18 deletions
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 <string.h> #include <time.h> +#include <setjmp.h> +#include <signal.h> + 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"); diff --git a/source/kit_test/test.h b/source/kit_test/test.h index 176d957..2ef339f 100644 --- a/source/kit_test/test.h +++ b/source/kit_test/test.h @@ -19,18 +19,18 @@ extern "C" { # define KIT_TEST_ASSERTIONS_LIMIT 0x50 #endif -typedef void (*kit_test_report_fn)(int test_index, char const *file, - int line, int ok); +typedef void (*kit_test_report_fn)(int test_index, int line, int ok); typedef void (*kit_test_run_fn)( int kit_test_index_, kit_test_report_fn kit_test_report_fn_); typedef struct { char const *test_name; + char const *test_file; kit_test_run_fn test_fn; int assertions; - char const *file[KIT_TEST_ASSERTIONS_LIMIT]; int line[KIT_TEST_ASSERTIONS_LIMIT]; int status[KIT_TEST_ASSERTIONS_LIMIT]; + int signal; } kit_test_case_t; typedef struct { @@ -75,7 +75,8 @@ extern kit_tests_list_t kit_tests_list; # endif #endif -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); #define KIT_TEST(name) \ static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, \ @@ -84,16 +85,15 @@ void kit_test_register(char const *name, kit_test_run_fn fn); KIT_TEST_ON_START_( \ KIT_TEST_CONCAT3_(kit_test_case_, __LINE__, KIT_TEST_FILE)) { \ kit_test_register( \ - name, \ + name, __FILE__, \ KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, KIT_TEST_FILE)); \ } \ static void KIT_TEST_CONCAT3_(kit_test_run_, __LINE__, \ KIT_TEST_FILE)( \ int kit_test_index_, kit_test_report_fn kit_test_report_fn_) -#define KIT_REQUIRE(...) \ - kit_test_report_fn_(kit_test_index_, __FILE__, __LINE__, \ - (__VA_ARGS__)) +#define KIT_REQUIRE(...) \ + kit_test_report_fn_(kit_test_index_, __LINE__, (__VA_ARGS__)) int kit_run_tests(int argc, char **argv); diff --git a/source/test/programs/CMakeLists.txt b/source/test/programs/CMakeLists.txt index 24932bd..9c58599 100644 --- a/source/test/programs/CMakeLists.txt +++ b/source/test/programs/CMakeLists.txt @@ -28,4 +28,14 @@ if(KIT_ENABLE_TESTING) cpp_example_test PROPERTIES TIMEOUT "30") + + add_executable(signals signals.c) + target_link_libraries(signals ${KIT_TEST_LIBRARY}) + add_test( + NAME signals_test + COMMAND signals) + set_tests_properties( + signals_test + PROPERTIES + TIMEOUT "30") endif() diff --git a/source/test/programs/signals.c b/source/test/programs/signals.c new file mode 100644 index 0000000..935623a --- /dev/null +++ b/source/test/programs/signals.c @@ -0,0 +1,18 @@ +#include "../../kit_test/test.h" + +#include <stdlib.h> + +TEST("abort") { + abort(); +} + +TEST("invalid access") { + *(volatile int *) NULL = 42; +} + +int main(int argc, char **argv) { + if (run_tests(argc, argv) != 1) + return 1; + + return 0; +} diff --git a/source/test/programs/too_many_tests.c b/source/test/programs/too_many_tests.c index 9893e84..bc7b543 100644 --- a/source/test/programs/too_many_tests.c +++ b/source/test/programs/too_many_tests.c @@ -4,7 +4,7 @@ void bar(int index, kit_test_report_fn report) { } int main(int argc, char **argv) { for (int i = 0; i <= KIT_TESTS_SIZE_LIMIT; i++) - test_register("foo", bar); + test_register("foo", __FILE__, bar); if (run_tests(argc, argv) != 1) return 1; diff --git a/source/test/unittests/test_duration.test.c b/source/test/unittests/test_duration.test.c index 5d9e578..0912d9f 100644 --- a/source/test/unittests/test_duration.test.c +++ b/source/test/unittests/test_duration.test.c @@ -1,6 +1,8 @@ #define KIT_TEST_FILE test_duration #include "../../kit_test/test.h" +#include <stdlib.h> + #if defined(_WIN32) && !defined(__CYGWIN__) __declspec(dllimport) void __stdcall Sleep(unsigned long timeout); static void kit_sleep(int ms) { |