#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
+#include <setjmp.h>
#include <valgrind/valgrind.h>
#include "litest-runner.h"
#include "util-list.h"
#include "util-stringbuf.h"
+static bool use_jmpbuf; /* only used for max_forks = 0 */
+static jmp_buf jmpbuf;
+
/* musl doesn't have this one but it's not that important */
#ifndef HAVE_SIGABBREV_NP
#define sigabbrev_np(...) "???"
}
}
+__attribute__((noreturn))
+void
+litest_runner_abort(void) {
+ if (use_jmpbuf) {
+ longjmp(jmpbuf, SIGABRT);
+ } else {
+ abort();
+ }
+}
+
static int
litest_runner_run_test(struct litest_runner *runner, struct litest_runner_test *t)
{
- int r = 0;
+ int r;
t->result = LITEST_SYSTEM_ERROR;
t->times.start_millis = us2ms(now);
if (runner->max_forks == 0) {
- t->result = litest_runner_test_run(&t->desc);
+ if (use_jmpbuf && setjmp(jmpbuf) == 0) {
+ t->result = litest_runner_test_run(&t->desc);
+ } else {
+ t->result = LITEST_FAIL;
+ }
+ r = 0; /* -Wclobbered */
} else {
r = litest_runner_fork_test(runner, t);
if (r >= 0)
if (runner->global.setup)
runner->global.setup(runner->global.userdata);
+ use_jmpbuf = runner->max_forks == 0;
+
setup_sighandler(SIGINT);
uint64_t now = 0;
void *userdata);
void litest_runner_destroy(struct litest_runner *runner);
+
+/*
+ * Function to call abort(). Depending on the number of forks permitted,
+ * this function may simply abort() or it may longjmp back out to collect
+ * errors from non-forking tests.
+ */
+__attribute__((noreturn))
+void litest_runner_abort(void);
litest_log("in %s() (%s:%d)\n", func, file, line);
litest_backtrace();
- abort();
+ litest_runner_abort();
}
__attribute__((noreturn))
litest_log("Resolved to: %d %s %d\n", a, operator, b);
litest_log("in %s() (%s:%d)\n", func, file, line);
litest_backtrace();
- abort();
+ litest_runner_abort();
}
__attribute__((noreturn))
litest_log("Resolved to: %.3f %s %.3f\n", a, operator, b);
litest_log("in %s() (%s:%d)\n", func, file, line);
litest_backtrace();
- abort();
+ litest_runner_abort();
}
__attribute__((noreturn))
litest_log("FAILED COMPARISON: %s\n", comparison);
litest_log("in %s() (%s:%d)\n", func, file, line);
litest_backtrace();
- abort();
+ litest_runner_abort();
}
__attribute__((noreturn))
litest_log("Resolved to: %s %s %s\n", astr, operator, bstr);
litest_log("in %s() (%s:%d)\n", func, file, line);
litest_backtrace();
- abort();
+ litest_runner_abort();
}
struct test {
fprintf(stderr, "\nWrong event is: ");
litest_print_event(event);
litest_backtrace();
- abort();
+ litest_runner_abort();
}
void
fprintf(stderr, "\nWrong event is: ");
litest_print_event(event);
litest_backtrace();
- abort();
+ litest_runner_abort();
}
void