aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/tests/test_suite.c
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-10-15 17:40:58 +0200
committerMartin Willi <martin@revosec.ch>2014-06-04 15:52:58 +0200
commit4aaf0320d0007f07ba06e243d2eed6b7e8ce3078 (patch)
tree6e5d02349e2145624afa689dd0546d75383a63af /src/libstrongswan/tests/test_suite.c
parenta2216a28687f776052163bd1bda315d19ceb70a6 (diff)
downloadstrongswan-4aaf0320d0007f07ba06e243d2eed6b7e8ce3078.tar.bz2
strongswan-4aaf0320d0007f07ba06e243d2eed6b7e8ce3078.tar.xz
unit-tests: Add support for Windows build
Instead of signals we catch Windows exceptions. Currently not supported are timers, which is more a convenience thing anyway.
Diffstat (limited to 'src/libstrongswan/tests/test_suite.c')
-rw-r--r--src/libstrongswan/tests/test_suite.c215
1 files changed, 189 insertions, 26 deletions
diff --git a/src/libstrongswan/tests/test_suite.c b/src/libstrongswan/tests/test_suite.c
index a636d6f7c..c80c6efd6 100644
--- a/src/libstrongswan/tests/test_suite.c
+++ b/src/libstrongswan/tests/test_suite.c
@@ -18,7 +18,11 @@
#include <signal.h>
#include <unistd.h>
+#ifndef WIN32
#include <pthread.h>
+#endif
+
+#include <threading/thread.h>
/**
* Failure message buf
@@ -46,11 +50,6 @@ static backtrace_t *failure_backtrace;
static bool worker_failed;
/**
- * Longjump restore point when failing
- */
-sigjmp_buf test_restore_point_env;
-
-/**
* See header.
*/
test_suite_t* test_suite_create(const char *name)
@@ -124,54 +123,189 @@ void test_suite_add_case(test_suite_t *suite, test_case_t *tcase)
array_insert(suite->tcases, -1, tcase);
}
+#ifdef WIN32
+
/**
- * Main thread performing tests
+ * Longjump restore point when failing
*/
-static pthread_t main_thread;
+jmp_buf test_restore_point_env;
+
+/**
+ * Thread ID of main thread
+ */
+static DWORD main_thread;
+
+/**
+ * APC routine invoked by main thread on worker failure
+ */
+static void set_worker_failure(ULONG_PTR dwParam)
+{
+ worker_failed = TRUE;
+}
/**
* Let test case fail
*/
-static inline void test_failure()
+static void test_failure()
{
- if (pthread_self() == main_thread)
+ if (GetCurrentThreadId() == main_thread)
{
- siglongjmp(test_restore_point_env, 1);
+ longjmp(test_restore_point_env, 1);
}
else
{
- pthread_kill(main_thread, SIGUSR1);
- /* terminate thread to prevent it from going wild */
- pthread_exit(NULL);
+ HANDLE *thread;
+
+ thread = OpenThread(THREAD_SET_CONTEXT, FALSE, main_thread);
+ if (thread)
+ {
+ QueueUserAPC(set_worker_failure, thread, (uintptr_t)NULL);
+ CloseHandle(thread);
+ }
+ thread_exit(NULL);
}
}
/**
* See header.
*/
-void test_fail_vmsg(const char *file, int line, char *fmt, va_list args)
+void test_fail_if_worker_failed()
{
- vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
- failure_line = line;
- failure_file = file;
+ if (GetCurrentThreadId() == main_thread && worker_failed)
+ {
+ test_failure();
+ }
+}
- test_failure();
+/**
+ * Vectored exception handler
+ */
+static long eh_handler(PEXCEPTION_POINTERS ei)
+{
+ char *ename;
+ bool old = FALSE;
+
+ switch (ei->ExceptionRecord->ExceptionCode)
+ {
+ case EXCEPTION_ACCESS_VIOLATION:
+ ename = "ACCESS_VIOLATION";
+ break;
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ ename = "ARRAY_BOUNDS_EXCEEDED";
+ break;
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ ename = "DATATYPE_MISALIGNMENT";
+ break;
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ ename = "FLT_DENORMAL_OPERAND";
+ break;
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ ename = "FLT_DIVIDE_BY_ZERO";
+ break;
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ ename = "FLT_INEXACT_RESULT";
+ break;
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ ename = "FLT_INVALID_OPERATION";
+ break;
+ case EXCEPTION_FLT_OVERFLOW:
+ ename = "FLT_OVERFLOW";
+ break;
+ case EXCEPTION_FLT_STACK_CHECK:
+ ename = "FLT_STACK_CHECK";
+ break;
+ case EXCEPTION_FLT_UNDERFLOW:
+ ename = "FLT_UNDERFLOW";
+ break;
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ ename = "ILLEGAL_INSTRUCTION";
+ break;
+ case EXCEPTION_IN_PAGE_ERROR:
+ ename = "IN_PAGE_ERROR";
+ break;
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ ename = "INT_DIVIDE_BY_ZERO";
+ break;
+ case EXCEPTION_INT_OVERFLOW:
+ ename = "INT_OVERFLOW";
+ break;
+ case EXCEPTION_INVALID_DISPOSITION:
+ ename = "INVALID_DISPOSITION";
+ break;
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ ename = "NONCONTINUABLE_EXCEPTION";
+ break;
+ case EXCEPTION_PRIV_INSTRUCTION:
+ ename = "PRIV_INSTRUCTION";
+ break;
+ case EXCEPTION_STACK_OVERFLOW:
+ ename = "STACK_OVERFLOW";
+ break;
+ default:
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ if (lib->leak_detective)
+ {
+ old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
+ }
+ failure_backtrace = backtrace_create(5);
+ if (lib->leak_detective)
+ {
+ lib->leak_detective->set_state(lib->leak_detective, old);
+ }
+ failure_line = 0;
+ test_fail_msg(NULL, 0, "%s exception", ename);
+ /* not reached */
+ return EXCEPTION_CONTINUE_EXECUTION;
}
/**
* See header.
*/
-void test_fail_msg(const char *file, int line, char *fmt, ...)
+void test_setup_handler()
{
- va_list args;
+ main_thread = GetCurrentThreadId();
+ AddVectoredExceptionHandler(0, eh_handler);
+}
- va_start(args, fmt);
- vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
- failure_line = line;
- failure_file = file;
- va_end(args);
+/**
+ * See header.
+ */
+void test_setup_timeout(int s)
+{
+ /* TODO: currently not supported. SetTimer()? */
- test_failure();
+ worker_failed = FALSE;
+}
+
+#else /* !WIN32 */
+
+/**
+ * Longjump restore point when failing
+ */
+sigjmp_buf test_restore_point_env;
+
+/**
+ * Main thread performing tests
+ */
+static pthread_t main_thread;
+
+/**
+ * Let test case fail
+ */
+static inline void test_failure()
+{
+ if (pthread_self() == main_thread)
+ {
+ siglongjmp(test_restore_point_env, 1);
+ }
+ else
+ {
+ pthread_kill(main_thread, SIGUSR1);
+ /* terminate thread to prevent it from going wild */
+ pthread_exit(NULL);
+ }
}
/**
@@ -272,6 +406,35 @@ void test_setup_timeout(int s)
worker_failed = FALSE;
}
+#endif /* !WIN32 */
+
+/**
+ * See header.
+ */
+void test_fail_vmsg(const char *file, int line, char *fmt, va_list args)
+{
+ vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
+ failure_line = line;
+ failure_file = file;
+
+ test_failure();
+}
+/**
+ * See header.
+ */
+void test_fail_msg(const char *file, int line, char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
+ failure_line = line;
+ failure_file = file;
+ va_end(args);
+
+ test_failure();
+}
+
/**
* See header.
*/