]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
unit-tests: Defer failures by worker threads
authorTobias Brunner <tobias@strongswan.org>
Fri, 9 May 2014 15:42:37 +0000 (17:42 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 19 May 2014 12:06:55 +0000 (14:06 +0200)
In some cases the main thread is not ready to immediately call siglongjmp(),
e.g. if it currently holds a mutex that is later required during
shutdown.

Therefore, we delay handling errors in worker threads until the main
thread performs the next check itself (or the test function ends).

The same issue remains with SIGALRM.

src/libstrongswan/tests/test_suite.c
src/libstrongswan/tests/test_suite.h

index fb40b05c13be6710fcf3759c2ead434f27c68ad2..a636d6f7cb0c1bf0dfc44f2ce3426003368cb8f1 100644 (file)
@@ -40,6 +40,11 @@ static int failure_line;
  */
 static backtrace_t *failure_backtrace;
 
+/**
+ * Flag to indicate if a worker thread failed
+ */
+static bool worker_failed;
+
 /**
  * Longjump restore point when failing
  */
@@ -169,6 +174,17 @@ void test_fail_msg(const char *file, int line, char *fmt, ...)
        test_failure();
 }
 
+/**
+ * See header.
+ */
+void test_fail_if_worker_failed()
+{
+       if (pthread_self() == main_thread && worker_failed)
+       {
+               test_failure();
+       }
+}
+
 /**
  * Signal handler catching critical and alarm signals
  */
@@ -180,8 +196,9 @@ 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;
@@ -251,6 +268,8 @@ void test_setup_timeout(int s)
        sigaction(SIGUSR1, &action, NULL);
 
        alarm(s);
+
+       worker_failed = FALSE;
 }
 
 /**
index 2b1a64c2df86a5c0f39496e4e1f4da88c6b84718..4bef6ff37d7e9e7c7c81b33b3acaea4cb9d580f0 100644 (file)
@@ -236,6 +236,12 @@ void test_fail_vmsg(const char *file, int line, char *fmt, va_list args);
  */
 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
  *
@@ -246,6 +252,7 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 ({ \
        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); \
@@ -262,6 +269,7 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 ({ \
        char* _a = (char*)a; \
        char* _b = (char*)b; \
+       test_fail_if_worker_failed(); \
        if (!_a || !_b || !streq(_a, _b)) \
        { \
                test_fail_msg(__FILE__, __LINE__, \
@@ -279,6 +287,7 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 ({ \
        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__, \
@@ -293,6 +302,7 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
  */
 #define test_assert(x) \
 ({ \
+       test_fail_if_worker_failed(); \
        if (!(x)) \
        { \
                test_fail_msg(__FILE__, __LINE__, #x); \
@@ -308,6 +318,7 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
  */
 #define test_assert_msg(x, fmt, ...) \
 ({ \
+       test_fail_if_worker_failed(); \
        if (!(x)) \
        { \
                test_fail_msg(__FILE__, __LINE__, #x ": " fmt, ##__VA_ARGS__); \
@@ -327,6 +338,7 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 #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__); \
@@ -341,10 +353,10 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 #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_ @}*/