Annotation of embedaddon/strongswan/src/libcharon/tests/utils/exchange_test_asserts.h, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2016-2017 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      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: /**
                     17:  * Special assertions using listener_t etc.
                     18:  *
                     19:  * @defgroup exchange_test_asserts exchange_test_asserts
                     20:  * @{ @ingroup test_utils_c
                     21:  */
                     22: 
                     23: #ifndef EXCHANGE_TEST_ASSERTS_H_
                     24: #define EXCHANGE_TEST_ASSERTS_H_
                     25: 
                     26: #include <bus/listeners/listener.h>
                     27: 
                     28: typedef struct listener_hook_assert_t listener_hook_assert_t;
                     29: typedef struct listener_message_assert_t listener_message_assert_t;
                     30: typedef struct listener_message_rule_t listener_message_rule_t;
                     31: typedef struct ipsec_sas_assert_t ipsec_sas_assert_t;
                     32: 
                     33: struct listener_hook_assert_t {
                     34: 
                     35:        /**
                     36:         * Implemented interface
                     37:         */
                     38:        listener_t listener;
                     39: 
                     40:        /**
                     41:         * Original source file
                     42:         */
                     43:        const char *file;
                     44: 
                     45:        /**
                     46:         * Source line
                     47:         */
                     48:        int line;
                     49: 
                     50:        /**
                     51:         * Name of the hook
                     52:         */
                     53:        const char *name;
                     54: 
                     55:        /**
                     56:         * Expected number of calls (-1 to ignore)
                     57:         */
                     58:        int expected;
                     59: 
                     60:        /**
                     61:         * Number of times the hook was called
                     62:         */
                     63:        int count;
                     64: 
                     65:        /**
                     66:         * Expected updown result
                     67:         */
                     68:        bool up;
                     69: 
                     70:        /**
                     71:         * Initiator/Inbound SPIs to expect in rekey event
                     72:         */
                     73:        uint64_t spi_old, spi_new;
                     74: };
                     75: 
                     76: /**
                     77:  * Basic callback for methods on listener_t, counting the number of calls.
                     78:  */
                     79: bool exchange_test_asserts_hook(listener_t *this);
                     80: 
                     81: /**
                     82:  * Implementation of listener_t::ike_updown.
                     83:  */
                     84: bool exchange_test_asserts_ike_updown(listener_t *this, ike_sa_t *ike_sa,
                     85:                                                                          bool up);
                     86: 
                     87: /**
                     88:  * Implementation of listener_t::child_updown.
                     89:  */
                     90: bool exchange_test_asserts_child_updown(listener_t *this, ike_sa_t *ike_sa,
                     91:                                                                                child_sa_t *child_sa, bool up);
                     92: 
                     93: /**
                     94:  * Implementation of listener_t::ike_rekey.
                     95:  */
                     96: bool exchange_test_asserts_ike_rekey(listener_t *this, ike_sa_t *old,
                     97:                                                                         ike_sa_t *new);
                     98: 
                     99: /**
                    100:  * Implementation of listener_t::child_rekey.
                    101:  */
                    102: bool exchange_test_asserts_child_rekey(listener_t *this, ike_sa_t *ike_sa,
                    103:                                                                           child_sa_t *old, child_sa_t *new);
                    104: 
                    105: /**
                    106:  * Check if a statement evaluates to TRUE, use original source file and line
                    107:  * in the error message if not.
                    108:  *
                    109:  * @param x                    statement to evaluate
                    110:  * @param l                    listener providing original source file and line
                    111:  * @param fmt          printf format string
                    112:  * @param ...          arguments for fmt
                    113:  */
                    114: #define assert_listener_msg(x, l, fmt, ...) ({ \
                    115:        test_fail_if_worker_failed(); \
                    116:        if (!(x)) \
                    117:        { \
                    118:                test_fail_msg((l)->file, (l)->line, "%s: " fmt, #x, ##__VA_ARGS__); \
                    119:        } \
                    120: })
                    121: 
                    122: /**
                    123:  * Initialize an assertion that enforces that the given hook was called.
                    124:  * Must be matched by a call to assert_hook().
                    125:  *
                    126:  * @param name         name of the hook
                    127:  */
                    128: #define assert_hook_called(name) \
                    129:        _assert_hook_init(name, exchange_test_asserts_hook, .expected = 1)
                    130: 
                    131: /**
                    132:  * Initialize an assertion that enforces that the given hook was not called.
                    133:  * Must be matched by a call to assert_hook().
                    134:  *
                    135:  * @param name         name of the hook
                    136:  */
                    137: #define assert_hook_not_called(name) \
                    138:        _assert_hook_init(name, exchange_test_asserts_hook, .expected = 0)
                    139: 
                    140: /**
                    141:  * Initialize an assertion that enforces that the given updown hook was called
                    142:  * with the expected result.
                    143:  * Must be matched by a call to assert_hook().
                    144:  *
                    145:  * @param name         name of the hook
                    146:  * @param e                    whether to expect up in the hook to be TRUE or not
                    147:  */
                    148: #define assert_hook_updown(name, e) \
                    149:        _assert_hook_init(name, \
                    150:                streq(#name, "ike_updown") ? (void*)exchange_test_asserts_ike_updown \
                    151:                                                                   : (void*)exchange_test_asserts_child_updown, \
                    152:                .expected = 1, \
                    153:                .up = e, \
                    154:        )
                    155: 
                    156: /**
                    157:  * Initialize an assertion that enforces that the given rekey hook was called
                    158:  * with the SAs with the matching initiator/inbound SPIs.
                    159:  * Must be matched by a call to assert_hook().
                    160:  *
                    161:  * @param name         name of the hook
                    162:  * @param old          SPI of the old SA
                    163:  * @param new          SPI of the new SA
                    164:  */
                    165: #define assert_hook_rekey(name, old, new) \
                    166:        _assert_hook_init(name, \
                    167:                streq(#name, "ike_rekey") ? (void*)exchange_test_asserts_ike_rekey \
                    168:                                                                   : (void*)exchange_test_asserts_child_rekey, \
                    169:                .expected = 1, \
                    170:                .spi_old = old, \
                    171:                .spi_new = new, \
                    172:        )
                    173: 
                    174: /**
                    175:  * Initialize assertions against invocations of listener_t hooks.  Each call
                    176:  * must be matched by a call to assert_hook().
                    177:  */
                    178: #define _assert_hook_init(n, callback, ...) \
                    179: do { \
                    180:        listener_hook_assert_t _hook_listener = { \
                    181:                .listener = { .n = (void*)callback, }, \
                    182:                .file = __FILE__, \
                    183:                .line = __LINE__, \
                    184:                .name = #n, \
                    185:                ##__VA_ARGS__ \
                    186:        }; \
                    187:        exchange_test_helper->add_listener(exchange_test_helper, &_hook_listener.listener)
                    188: 
                    189: /**
                    190:  * Enforce the most recently initialized hook assertion.
                    191:  */
                    192: #define assert_hook() \
                    193:        charon->bus->remove_listener(charon->bus, &_hook_listener.listener); \
                    194:        if (_hook_listener.expected > 0) { \
                    195:                if (_hook_listener.count > 0) { \
                    196:                        assert_listener_msg(_hook_listener.expected == _hook_listener.count, \
                    197:                                                                &_hook_listener, "hook '%s' was called %d times " \
                    198:                                                                "instead of %d", _hook_listener.name, \
                    199:                                                                _hook_listener.count, _hook_listener.expected); \
                    200:                } else { \
                    201:                        assert_listener_msg(_hook_listener.count, &_hook_listener, \
                    202:                                "hook '%s' was not called (expected %d)", _hook_listener.name, \
                    203:                                _hook_listener.expected); \
                    204:                } \
                    205:        } else if (_hook_listener.expected == 0) { \
                    206:                assert_listener_msg(_hook_listener.count == 0, &_hook_listener, \
                    207:                                "hook '%s' was called unexpectedly", _hook_listener.name); \
                    208:        } \
                    209: } while(FALSE)
                    210: 
                    211: /**
                    212:  * Rules regarding payloads/notifies to expect/not expect in a message
                    213:  */
                    214: struct listener_message_rule_t {
                    215: 
                    216:        /**
                    217:         * Whether the payload/notify is expected in the message, FALSE to fail if
                    218:         * it is found
                    219:         */
                    220:        bool expected;
                    221: 
                    222:        /**
                    223:         * Payload type to expect/not expect
                    224:         */
                    225:        payload_type_t payload;
                    226: 
                    227:        /**
                    228:         * Notify type to expect/not expect (payload type does not have to be
                    229:         * specified)
                    230:         */
                    231:        notify_type_t notify;
                    232: };
                    233: 
                    234: /**
                    235:  * Data used to check plaintext messages via listener_t
                    236:  */
                    237: struct listener_message_assert_t {
                    238: 
                    239:        /**
                    240:         * Implemented interface
                    241:         */
                    242:        listener_t listener;
                    243: 
                    244:        /**
                    245:         * Original source file
                    246:         */
                    247:        const char *file;
                    248: 
                    249:        /**
                    250:         * Source line
                    251:         */
                    252:        int line;
                    253: 
                    254:        /**
                    255:         * Whether to check the next inbound or outbound message
                    256:         */
                    257:        bool incoming;
                    258: 
                    259:        /**
                    260:         * Payload count to expect (-1 to ignore the count)
                    261:         */
                    262:        int count;
                    263: 
                    264:        /**
                    265:         * Payloads to expect or not expect in a message
                    266:         */
                    267:        listener_message_rule_t *rules;
                    268: 
                    269:        /**
                    270:         * Number of rules
                    271:         */
                    272:        int num_rules;
                    273: };
                    274: 
                    275: /**
                    276:  * Implementation of listener_t::message collecting data and asserting
                    277:  * certain things.
                    278:  */
                    279: bool exchange_test_asserts_message(listener_t *this, ike_sa_t *ike_sa,
                    280:                                                        message_t *message, bool incoming, bool plain);
                    281: 
                    282: /**
                    283:  * Assert that the next in- or outbound plaintext message is empty.
                    284:  *
                    285:  * @param dir                  IN or OUT to check the next in- or outbound message
                    286:  */
                    287: #define assert_message_empty(dir) \
                    288:                                _assert_payload(#dir, 0)
                    289: 
                    290: /**
                    291:  * Assert that the next in- or outbound plaintext message contains exactly
                    292:  * one payload of the given type.
                    293:  *
                    294:  * @param dir                  IN or OUT to check the next in- or outbound message
                    295:  * @param expected             expected payload type
                    296:  */
                    297: #define assert_single_payload(dir, expected) \
                    298:                                _assert_payload(#dir, 1, { TRUE, expected, 0 })
                    299: 
                    300: /**
                    301:  * Assert that the next in- or outbound plaintext message contains a payload
                    302:  * of the given type.
                    303:  *
                    304:  * @param dir                  IN or OUT to check the next in- or outbound message
                    305:  * @param expected             expected payload type
                    306:  */
                    307: #define assert_payload(dir, expected) \
                    308:                                _assert_payload(#dir, -1, { TRUE, expected, 0 })
                    309: 
                    310: /**
                    311:  * Assert that the next in- or outbound plaintext message contains no payload
                    312:  * of the given type.
                    313:  *
                    314:  * @param dir                  IN or OUT to check the next in- or outbound message
                    315:  * @param unexpected   not expected payload type
                    316:  */
                    317: #define assert_no_payload(dir, unexpected) \
                    318:                                _assert_payload(#dir, -1, { FALSE, unexpected, 0 })
                    319: 
                    320: /**
                    321:  * Assert that the next in- or outbound plaintext message contains exactly
                    322:  * one notify of the given type.
                    323:  *
                    324:  * @param dir                  IN or OUT to check the next in- or outbound message
                    325:  * @param expected             expected notify type
                    326:  */
                    327: #define assert_single_notify(dir, expected) \
                    328:                                _assert_payload(#dir, 1, { TRUE, 0, expected })
                    329: 
                    330: /**
                    331:  * Assert that the next in- or outbound plaintext message contains a notify
                    332:  * of the given type.
                    333:  *
                    334:  * @param dir                  IN or OUT to check the next in- or outbound message
                    335:  * @param expected             expected notify type
                    336:  */
                    337: #define assert_notify(dir, expected) \
                    338:                                _assert_payload(#dir, -1, { TRUE, 0, expected })
                    339: 
                    340: /**
                    341:  * Assert that the next in- or outbound plaintext message does not contain a
                    342:  * notify of the given type.
                    343:  *
                    344:  * @param dir                  IN or OUT to check the next in- or outbound message
                    345:  * @param unexpected   not expected notify type
                    346:  */
                    347: #define assert_no_notify(dir, unexpected) \
                    348:                                _assert_payload(#dir, -1, { FALSE, 0, unexpected })
                    349: 
                    350: #define _assert_payload(dir, c, ...) ({ \
                    351:        listener_message_rule_t _rules[] = { __VA_ARGS__ }; \
                    352:        listener_message_assert_t _listener = { \
                    353:                .listener = { .message = exchange_test_asserts_message, }, \
                    354:                .file = __FILE__, \
                    355:                .line = __LINE__, \
                    356:                .incoming = streq(dir, "IN") ? TRUE : FALSE, \
                    357:                .count = c, \
                    358:                .rules = _rules, \
                    359:                .num_rules = countof(_rules), \
                    360:        }; \
                    361:        exchange_test_helper->add_listener(exchange_test_helper, &_listener.listener); \
                    362: })
                    363: 
                    364: /**
                    365:  * Data used to check IPsec SAs
                    366:  */
                    367: struct ipsec_sas_assert_t {
                    368: 
                    369:        /**
                    370:         * Original source file
                    371:         */
                    372:        const char *file;
                    373: 
                    374:        /**
                    375:         * Source line
                    376:         */
                    377:        int line;
                    378: 
                    379:        /**
                    380:         * IKE_SA that installed the IPsec SAs
                    381:         */
                    382:        ike_sa_t *ike_sa;
                    383: 
                    384:        /**
                    385:         * SPIs to check
                    386:         */
                    387:        uint32_t *spis;
                    388: 
                    389:        /**
                    390:         * Number of SPIs for IPsec SAs to check
                    391:         */
                    392:        int count;
                    393: };
                    394: 
                    395: /**
                    396:  * Assert that all given IPsec SAs (and only these) are installed for the given
                    397:  * IKE_SA.
                    398:  */
                    399: void exchange_test_asserts_ipsec_sas(ipsec_sas_assert_t *sas);
                    400: 
                    401: /**
                    402:  * Assert that the IPsec SAs with the given SPIs (and none other) are currently
                    403:  * installed by the given IKE_SA.
                    404:  *
                    405:  * @param sa           IKE_SA
                    406:  * @param ...          list of SPIs
                    407:  */
                    408: #define assert_ipsec_sas_installed(sa, ...) ({ \
                    409:        uint32_t _spis[] = { __VA_ARGS__ }; \
                    410:        ipsec_sas_assert_t _sas_assert = { \
                    411:                .file = __FILE__, \
                    412:                .line = __LINE__, \
                    413:                .ike_sa = sa, \
                    414:                .spis = _spis, \
                    415:                .count = countof(_spis), \
                    416:        }; \
                    417:        exchange_test_asserts_ipsec_sas(&_sas_assert); \
                    418: })
                    419: 
                    420: #endif /** EXCHANGE_TEST_ASSERTS_H_ @}*/

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