summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/kit_test/test.c79
-rw-r--r--source/kit_test/test.h16
-rw-r--r--source/test/programs/CMakeLists.txt10
-rw-r--r--source/test/programs/signals.c18
-rw-r--r--source/test/programs/too_many_tests.c2
-rw-r--r--source/test/unittests/test_duration.test.c2
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) {