Annotation of embedaddon/strongswan/src/libstrongswan/tests/test_suite.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013 Martin Willi
                      3:  * Copyright (C) 2013 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "test_suite.h"
                     17: 
                     18: #include <signal.h>
                     19: #include <unistd.h>
                     20: 
                     21: #ifndef WIN32
                     22: #include <pthread.h>
                     23: #endif
                     24: 
                     25: #include <threading/thread.h>
                     26: 
                     27: /**
                     28:  * Failure message buf
                     29:  */
                     30: static char failure_buf[4096];
                     31: 
                     32: /**
                     33:  * Source file failure occurred
                     34:  */
                     35: static const char *failure_file;
                     36: 
                     37: /**
                     38:  * Line of source file failure occurred
                     39:  */
                     40: static int failure_line;
                     41: 
                     42: /**
                     43:  * Backtrace of failure, if any
                     44:  */
                     45: static backtrace_t *failure_backtrace;
                     46: 
                     47: /**
                     48:  * Flag to indicate if a worker thread failed
                     49:  */
                     50: static bool worker_failed;
                     51: 
                     52: /**
                     53:  * Warning message buf
                     54:  */
                     55: static char warning_buf[4096];
                     56: 
                     57: /**
                     58:  * Source file warning was issued
                     59:  */
                     60: static const char *warning_file;
                     61: 
                     62: /**
                     63:  * Line of source file warning was issued
                     64:  */
                     65: static int warning_line;
                     66: 
                     67: /**
                     68:  * See header.
                     69:  */
                     70: test_suite_t* test_suite_create(const char *name)
                     71: {
                     72:        test_suite_t *suite;
                     73: 
                     74:        INIT(suite,
                     75:                .name = name,
                     76:                .tcases = array_create(0, 0),
                     77:        );
                     78:        return suite;
                     79: }
                     80: 
                     81: /**
                     82:  * See header.
                     83:  */
                     84: test_case_t* test_case_create(const char *name)
                     85: {
                     86:        test_case_t *tcase;
                     87: 
                     88:        INIT(tcase,
                     89:                .name = name,
                     90:                .functions = array_create(sizeof(test_function_t), 0),
                     91:                .fixtures = array_create(sizeof(test_fixture_t), 0),
                     92:                .timeout = TEST_FUNCTION_DEFAULT_TIMEOUT,
                     93:        );
                     94:        return tcase;
                     95: }
                     96: 
                     97: /**
                     98:  * See header.
                     99:  */
                    100: void test_case_add_checked_fixture(test_case_t *tcase, test_fixture_cb_t setup,
                    101:                                                                   test_fixture_cb_t teardown)
                    102: {
                    103:        test_fixture_t fixture = {
                    104:                .setup = setup,
                    105:                .teardown = teardown,
                    106:        };
                    107:        array_insert(tcase->fixtures, -1, &fixture);
                    108: }
                    109: 
                    110: /**
                    111:  * See header.
                    112:  */
                    113: void test_case_add_test_name(test_case_t *tcase, char *name,
                    114:                                                         test_function_cb_t cb, int start, int end)
                    115: {
                    116:        test_function_t fun = {
                    117:                .name = name,
                    118:                .cb = cb,
                    119:                .start = start,
                    120:                .end = end,
                    121:        };
                    122:        array_insert(tcase->functions, -1, &fun);
                    123: }
                    124: 
                    125: /**
                    126:  * See header.
                    127:  */
                    128: void test_case_set_timeout(test_case_t *tcase, int s)
                    129: {
                    130:        tcase->timeout = s;
                    131: }
                    132: 
                    133: /**
                    134:  * See header.
                    135:  */
                    136: void test_suite_add_case(test_suite_t *suite, test_case_t *tcase)
                    137: {
                    138:        array_insert(suite->tcases, -1, tcase);
                    139: }
                    140: 
                    141: #ifdef WIN32
                    142: 
                    143: /**
                    144:  * Longjump restore point when failing
                    145:  */
                    146: jmp_buf test_restore_point_env;
                    147: 
                    148: /**
                    149:  * Thread ID of main thread
                    150:  */
                    151: static DWORD main_thread;
                    152: 
                    153: /**
                    154:  * APC routine invoked by main thread on worker failure
                    155:  */
                    156: static void WINAPI set_worker_failure(ULONG_PTR dwParam)
                    157: {
                    158:        worker_failed = TRUE;
                    159: }
                    160: 
                    161: /**
                    162:  * Let test case fail
                    163:  */
                    164: static void test_failure()
                    165: {
                    166:        if (GetCurrentThreadId() == main_thread)
                    167:        {
                    168:                longjmp(test_restore_point_env, 1);
                    169:        }
                    170:        else
                    171:        {
                    172:                HANDLE *thread;
                    173: 
                    174:                thread = OpenThread(THREAD_SET_CONTEXT, FALSE, main_thread);
                    175:                if (thread)
                    176:                {
                    177:                        QueueUserAPC(set_worker_failure, thread, (uintptr_t)NULL);
                    178:                        CloseHandle(thread);
                    179:                }
                    180:                thread_exit(NULL);
                    181:        }
                    182: }
                    183: 
                    184: /**
                    185:  * See header.
                    186:  */
                    187: void test_fail_if_worker_failed()
                    188: {
                    189:        if (GetCurrentThreadId() == main_thread && worker_failed)
                    190:        {
                    191:                test_failure();
                    192:        }
                    193: }
                    194: 
                    195: /**
                    196:  * Vectored exception handler
                    197:  */
                    198: static long WINAPI eh_handler(PEXCEPTION_POINTERS ei)
                    199: {
                    200:        char *ename;
                    201:        bool old = FALSE;
                    202: 
                    203:        switch (ei->ExceptionRecord->ExceptionCode)
                    204:        {
                    205:                case EXCEPTION_ACCESS_VIOLATION:
                    206:                        ename = "ACCESS_VIOLATION";
                    207:                        break;
                    208:                case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
                    209:                        ename = "ARRAY_BOUNDS_EXCEEDED";
                    210:                        break;
                    211:                case EXCEPTION_DATATYPE_MISALIGNMENT:
                    212:                        ename = "DATATYPE_MISALIGNMENT";
                    213:                        break;
                    214:                case EXCEPTION_FLT_DENORMAL_OPERAND:
                    215:                        ename = "FLT_DENORMAL_OPERAND";
                    216:                        break;
                    217:                case EXCEPTION_FLT_DIVIDE_BY_ZERO:
                    218:                        ename = "FLT_DIVIDE_BY_ZERO";
                    219:                        break;
                    220:                case EXCEPTION_FLT_INEXACT_RESULT:
                    221:                        ename = "FLT_INEXACT_RESULT";
                    222:                        break;
                    223:                case EXCEPTION_FLT_INVALID_OPERATION:
                    224:                        ename = "FLT_INVALID_OPERATION";
                    225:                        break;
                    226:                case EXCEPTION_FLT_OVERFLOW:
                    227:                        ename = "FLT_OVERFLOW";
                    228:                        break;
                    229:                case EXCEPTION_FLT_STACK_CHECK:
                    230:                        ename = "FLT_STACK_CHECK";
                    231:                        break;
                    232:                case EXCEPTION_FLT_UNDERFLOW:
                    233:                        ename = "FLT_UNDERFLOW";
                    234:                        break;
                    235:                case EXCEPTION_ILLEGAL_INSTRUCTION:
                    236:                        ename = "ILLEGAL_INSTRUCTION";
                    237:                        break;
                    238:                case EXCEPTION_IN_PAGE_ERROR:
                    239:                        ename = "IN_PAGE_ERROR";
                    240:                        break;
                    241:                case EXCEPTION_INT_DIVIDE_BY_ZERO:
                    242:                        ename = "INT_DIVIDE_BY_ZERO";
                    243:                        break;
                    244:                case EXCEPTION_INT_OVERFLOW:
                    245:                        ename = "INT_OVERFLOW";
                    246:                        break;
                    247:                case EXCEPTION_INVALID_DISPOSITION:
                    248:                        ename = "INVALID_DISPOSITION";
                    249:                        break;
                    250:                case EXCEPTION_NONCONTINUABLE_EXCEPTION:
                    251:                        ename = "NONCONTINUABLE_EXCEPTION";
                    252:                        break;
                    253:                case EXCEPTION_PRIV_INSTRUCTION:
                    254:                        ename = "PRIV_INSTRUCTION";
                    255:                        break;
                    256:                case EXCEPTION_STACK_OVERFLOW:
                    257:                        ename = "STACK_OVERFLOW";
                    258:                        break;
                    259:                default:
                    260:                        return EXCEPTION_CONTINUE_EXECUTION;
                    261:        }
                    262: 
                    263:        if (lib->leak_detective)
                    264:        {
                    265:                old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
                    266:        }
                    267:        failure_backtrace = backtrace_create(5);
                    268:        if (lib->leak_detective)
                    269:        {
                    270:                lib->leak_detective->set_state(lib->leak_detective, old);
                    271:        }
                    272:        failure_line = 0;
                    273:        test_fail_msg(NULL, 0, "%s exception", ename);
                    274:        /* not reached */
                    275:        return EXCEPTION_CONTINUE_EXECUTION;
                    276: }
                    277: 
                    278: /**
                    279:  * See header.
                    280:  */
                    281: void test_setup_handler()
                    282: {
                    283:        main_thread = GetCurrentThreadId();
                    284:        AddVectoredExceptionHandler(0, eh_handler);
                    285: }
                    286: 
                    287: /**
                    288:  * See header.
                    289:  */
                    290: void test_setup_timeout(int s)
                    291: {
                    292:        /* TODO: currently not supported. SetTimer()? */
                    293: 
                    294:        worker_failed = FALSE;
                    295: }
                    296: 
                    297: #else /* !WIN32 */
                    298: 
                    299: /**
                    300:  * Longjump restore point when failing
                    301:  */
                    302: sigjmp_buf test_restore_point_env;
                    303: 
                    304: /**
                    305:  * Main thread performing tests
                    306:  */
                    307: static pthread_t main_thread;
                    308: 
                    309: /**
                    310:  * Let test case fail
                    311:  */
                    312: static inline void test_failure()
                    313: {
                    314:        if (pthread_self() == main_thread)
                    315:        {
                    316:                siglongjmp(test_restore_point_env, 1);
                    317:        }
                    318:        else
                    319:        {
                    320:                pthread_kill(main_thread, SIGUSR1);
                    321:                /* terminate thread to prevent it from going wild */
                    322:                pthread_exit(NULL);
                    323:        }
                    324: }
                    325: 
                    326: /**
                    327:  * See header.
                    328:  */
                    329: void test_fail_if_worker_failed()
                    330: {
                    331:        if (pthread_self() == main_thread && worker_failed)
                    332:        {
                    333:                test_failure();
                    334:        }
                    335: }
                    336: 
                    337: /**
                    338:  * Signal handler catching critical and alarm signals
                    339:  */
                    340: static void test_sighandler(int signal)
                    341: {
                    342:        char *signame;
                    343:        bool old = FALSE;
                    344: 
                    345:        switch (signal)
                    346:        {
                    347:                case SIGUSR1:
                    348:                        /* a different thread failed, abort test at the next opportunity */
                    349:                        worker_failed = TRUE;
                    350:                        return;
                    351:                case SIGSEGV:
                    352:                        signame = "SIGSEGV";
                    353:                        break;
                    354:                case SIGILL:
                    355:                        signame = "SIGILL";
                    356:                        break;
                    357:                case SIGBUS:
                    358:                        signame = "SIGBUS";
                    359:                        break;
                    360:                case SIGALRM:
                    361:                        signame = "timeout";
                    362:                        break;
                    363:                default:
                    364:                        signame = "SIG";
                    365:                        break;
                    366:        }
                    367:        if (lib->leak_detective)
                    368:        {
                    369:                old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
                    370:        }
                    371:        failure_backtrace = backtrace_create(3);
                    372:        if (lib->leak_detective)
                    373:        {
                    374:                lib->leak_detective->set_state(lib->leak_detective, old);
                    375:        }
                    376:        test_fail_msg(NULL, 0, "%s(%d)", signame, signal);
                    377:        /* unable to restore a valid context for that thread, terminate */
                    378:        fprintf(stderr, "\n%s(%d) outside of main thread:\n", signame, signal);
                    379:        failure_backtrace->log(failure_backtrace, stderr, TRUE);
                    380:        fprintf(stderr, "terminating...\n");
                    381:        abort();
                    382: }
                    383: 
                    384: /**
                    385:  * See header.
                    386:  */
                    387: void test_setup_handler()
                    388: {
                    389:        struct sigaction action = {
                    390:                .sa_handler = test_sighandler,
                    391:        };
                    392: 
                    393:        main_thread = pthread_self();
                    394: 
                    395:        /* signal handler inherited by all threads */
                    396:        sigaction(SIGSEGV, &action, NULL);
                    397:        sigaction(SIGILL, &action, NULL);
                    398:        sigaction(SIGBUS, &action, NULL);
                    399:        /* ignore ALRM/USR1, these are caught by main thread only */
                    400:        action.sa_handler = SIG_IGN;
                    401:        sigaction(SIGALRM, &action, NULL);
                    402:        sigaction(SIGUSR1, &action, NULL);
                    403: }
                    404: 
                    405: /**
                    406:  * See header.
                    407:  */
                    408: void test_setup_timeout(int s)
                    409: {
                    410:        struct sigaction action = {
                    411:                .sa_handler = test_sighandler,
                    412:        };
                    413: 
                    414:        /* This called by main thread only. Setup handler for timeout and
                    415:         * failure cross-thread signaling. */
                    416:        sigaction(SIGALRM, &action, NULL);
                    417:        sigaction(SIGUSR1, &action, NULL);
                    418: 
                    419:        alarm(s);
                    420: 
                    421:        worker_failed = FALSE;
                    422: }
                    423: 
                    424: #endif /* !WIN32 */
                    425: 
                    426: /**
                    427:  * See header.
                    428:  */
                    429: void test_fail_vmsg(const char *file, int line, char *fmt, va_list args)
                    430: {
                    431:        vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
                    432:        failure_line = line;
                    433:        failure_file = file;
                    434: 
                    435:        test_failure();
                    436: }
                    437: 
                    438: /**
                    439:  * See header.
                    440:  */
                    441: void test_warn_msg(const char *file, int line, char *fmt, ...)
                    442: {
                    443:        va_list args;
                    444: 
                    445:        va_start(args, fmt);
                    446:        vsnprintf(warning_buf, sizeof(warning_buf), fmt, args);
                    447:        warning_line = line;
                    448:        warning_file = file;
                    449:        va_end(args);
                    450: }
                    451: 
                    452: /**
                    453:  * See header.
                    454:  */
                    455: void test_fail_msg(const char *file, int line, char *fmt, ...)
                    456: {
                    457:        va_list args;
                    458: 
                    459:        va_start(args, fmt);
                    460:        vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
                    461:        failure_line = line;
                    462:        failure_file = file;
                    463:        va_end(args);
                    464: 
                    465:        test_failure();
                    466: }
                    467: 
                    468: /**
                    469:  * See header.
                    470:  */
                    471: int test_failure_get(char *msg, int len, const char **file)
                    472: {
                    473:        strncpy(msg, failure_buf, len - 1);
                    474:        msg[len - 1] = 0;
                    475:        *file = failure_file;
                    476:        return failure_line;
                    477: }
                    478: 
                    479: /**
                    480:  * See header.
                    481:  */
                    482: int test_warning_get(char *msg, int len, const char **file)
                    483: {
                    484:        int line = warning_line;
                    485: 
                    486:        if (!line)
                    487:        {
                    488:                return 0;
                    489:        }
                    490:        strncpy(msg, warning_buf, len - 1);
                    491:        msg[len - 1] = 0;
                    492:        *file = warning_file;
                    493:        /* reset state */
                    494:        warning_line = 0;
                    495:        return line;
                    496: }
                    497: 
                    498: /**
                    499:  * See header.
                    500:  */
                    501: backtrace_t *test_failure_backtrace()
                    502: {
                    503:        backtrace_t *bt;
                    504: 
                    505:        bt = failure_backtrace;
                    506:        failure_backtrace = NULL;
                    507: 
                    508:        return bt;
                    509: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>