summaryrefslogtreecommitdiff
path: root/source/kit_test
diff options
context:
space:
mode:
Diffstat (limited to 'source/kit_test')
-rw-r--r--source/kit_test/test.c79
-rw-r--r--source/kit_test/test.h16
2 files changed, 78 insertions, 17 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);