static backtrace_t *failure_backtrace;
/**
+ * Flag to indicate if a worker thread failed
+ */
+static bool worker_failed;
+
+/**
* Longjump restore point when failing
*/
sigjmp_buf test_restore_point_env;
}
/**
+ * See header.
+ */
+void test_fail_if_worker_failed()
+{
+ if (pthread_self() == main_thread && worker_failed)
+ {
+ test_failure();
+ }
+}
+
+/**
* Signal handler catching critical and alarm signals
*/
static void test_sighandler(int signal)
switch (signal)
{
case SIGUSR1:
- /* a different thread failed, abort test */
- return test_failure();
+ /* a different thread failed, abort test at the next opportunity */
+ worker_failed = TRUE;
+ return;
case SIGSEGV:
signame = "SIGSEGV";
break;
sigaction(SIGUSR1, &action, NULL);
alarm(s);
+
+ worker_failed = FALSE;
}
/**
void test_fail_msg(const char *file, int line, char *fmt, ...);
/**
+ * Let a test fail if one of the worker threads has failed (only if called from
+ * the main thread).
+ */
+void test_fail_if_worker_failed();
+
+/**
* Check if two integers equal, fail test if not
*
* @param a first integer
({ \
typeof(a) _a = a; \
typeof(b) _b = b; \
+ test_fail_if_worker_failed(); \
if (_a != _b) \
{ \
test_fail_msg(__FILE__, __LINE__, #a " != " #b " (%d != %d)", _a, _b); \
({ \
char* _a = (char*)a; \
char* _b = (char*)b; \
+ test_fail_if_worker_failed(); \
if (!_a || !_b || !streq(_a, _b)) \
{ \
test_fail_msg(__FILE__, __LINE__, \
({ \
chunk_t _a = (chunk_t)a; \
chunk_t _b = (chunk_t)b; \
+ test_fail_if_worker_failed(); \
if (_a.len != _b.len || !memeq(a.ptr, b.ptr, a.len)) \
{ \
test_fail_msg(__FILE__, __LINE__, \
*/
#define test_assert(x) \
({ \
+ test_fail_if_worker_failed(); \
if (!(x)) \
{ \
test_fail_msg(__FILE__, __LINE__, #x); \
*/
#define test_assert_msg(x, fmt, ...) \
({ \
+ test_fail_if_worker_failed(); \
if (!(x)) \
{ \
test_fail_msg(__FILE__, __LINE__, #x ": " fmt, ##__VA_ARGS__); \
#define fail(fmt, ...) test_fail_msg(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define fail_if(x, fmt, ...) \
({ \
+ test_fail_if_worker_failed(); \
if (x) \
{ \
test_fail_msg(__FILE__, __LINE__, #x ": " fmt, ##__VA_ARGS__); \
#define tcase_set_timeout test_case_set_timeout
#define suite_add_tcase test_suite_add_case
#define START_TEST(name) static void name (int _i) {
-#define END_TEST }
+#define END_TEST test_fail_if_worker_failed(); }
#define START_SETUP(name) static void name() {
-#define END_SETUP }
+#define END_SETUP test_fail_if_worker_failed(); }
#define START_TEARDOWN(name) static void name() {
-#define END_TEARDOWN }
+#define END_TEARDOWN test_fail_if_worker_failed(); }
#endif /** TEST_SUITE_H_ @}*/