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>