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>