Annotation of embedaddon/strongswan/src/libcharon/tests/utils/exchange_test_asserts.h, revision 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>