From: Martin Willi Date: Tue, 15 Oct 2013 15:40:58 +0000 (+0200) Subject: unit-tests: Add support for Windows build X-Git-Tag: 5.2.0dr6~24^2~119 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4aaf0320d0007f07ba06e243d2eed6b7e8ce3078;p=thirdparty%2Fstrongswan.git 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. --- diff --git a/src/libstrongswan/tests/test_suite.c b/src/libstrongswan/tests/test_suite.c index a636d6f7cb..c80c6efd61 100644 --- a/src/libstrongswan/tests/test_suite.c +++ b/src/libstrongswan/tests/test_suite.c @@ -18,7 +18,11 @@ #include #include +#ifndef WIN32 #include +#endif + +#include /** * Failure message buf @@ -45,11 +49,6 @@ static backtrace_t *failure_backtrace; */ static bool worker_failed; -/** - * Longjump restore point when failing - */ -sigjmp_buf test_restore_point_env; - /** * See header. */ @@ -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. */ diff --git a/src/libstrongswan/tests/test_suite.h b/src/libstrongswan/tests/test_suite.h index 4bef6ff37d..da57ab46c4 100644 --- a/src/libstrongswan/tests/test_suite.h +++ b/src/libstrongswan/tests/test_suite.h @@ -174,7 +174,11 @@ void test_suite_add_case(test_suite_t *suite, test_case_t *tcase); /** * sigjmp restore point used by test_restore_point */ +#ifdef WIN32 +extern jmp_buf test_restore_point_env; +#else extern sigjmp_buf test_restore_point_env; +#endif /** * Set or return from an execution restore point @@ -185,7 +189,11 @@ extern sigjmp_buf test_restore_point_env; * * @return TRUE if restore point set, FALSE when restored */ -#define test_restore_point() (sigsetjmp(test_restore_point_env, 1) == 0) +#ifdef WIN32 +# define test_restore_point() (setjmp(test_restore_point_env) == 0) +#else +# define test_restore_point() (sigsetjmp(test_restore_point_env, 1) == 0) +#endif /** * Set up signal handlers for test cases