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