]>
Commit | Line | Data |
---|---|---|
632ba2a2 | 1 | /* |
72655fe4 | 2 | * Copyright (C) 2016-2017 Tobias Brunner |
632ba2a2 TB |
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 | /** | |
72655fe4 | 17 | * Special assertions using listener_t etc. |
632ba2a2 TB |
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; | |
fbb0b3cb | 30 | typedef struct listener_message_rule_t listener_message_rule_t; |
72655fe4 | 31 | typedef struct ipsec_sas_assert_t ipsec_sas_assert_t; |
632ba2a2 TB |
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; | |
14588d99 TB |
69 | |
70 | /** | |
71 | * Initiator/Inbound SPIs to expect in rekey event | |
72 | */ | |
73 | uint64_t spi_old, spi_new; | |
632ba2a2 TB |
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 | ||
14588d99 TB |
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 | ||
632ba2a2 TB |
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 | ||
14588d99 TB |
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 | ||
632ba2a2 TB |
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 | }; \ | |
7c6e0c29 | 187 | exchange_test_helper->add_listener(exchange_test_helper, &_hook_listener.listener) |
632ba2a2 TB |
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 | ||
fbb0b3cb TB |
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 | /** | |
b3ab7a48 | 228 | * Notify type to expect/not expect (payload type does not have to be |
fbb0b3cb TB |
229 | * specified) |
230 | */ | |
231 | notify_type_t notify; | |
232 | }; | |
233 | ||
632ba2a2 TB |
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 | /** | |
fbb0b3cb | 260 | * Payload count to expect (-1 to ignore the count) |
632ba2a2 TB |
261 | */ |
262 | int count; | |
263 | ||
264 | /** | |
fbb0b3cb | 265 | * Payloads to expect or not expect in a message |
632ba2a2 | 266 | */ |
fbb0b3cb | 267 | listener_message_rule_t *rules; |
632ba2a2 TB |
268 | |
269 | /** | |
fbb0b3cb | 270 | * Number of rules |
632ba2a2 | 271 | */ |
fbb0b3cb | 272 | int num_rules; |
632ba2a2 TB |
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 | */ | |
fbb0b3cb | 287 | #define assert_message_empty(dir) \ |
67ad553a | 288 | _assert_payload(#dir, 0) |
632ba2a2 TB |
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 | */ | |
fbb0b3cb | 297 | #define assert_single_payload(dir, expected) \ |
67ad553a | 298 | _assert_payload(#dir, 1, { TRUE, expected, 0 }) |
632ba2a2 | 299 | |
202fb101 TB |
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 | ||
632ba2a2 TB |
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 | */ | |
fbb0b3cb | 327 | #define assert_single_notify(dir, expected) \ |
67ad553a | 328 | _assert_payload(#dir, 1, { TRUE, 0, expected }) |
fbb0b3cb TB |
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) \ | |
67ad553a | 338 | _assert_payload(#dir, -1, { TRUE, 0, expected }) |
fbb0b3cb TB |
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) \ | |
67ad553a | 348 | _assert_payload(#dir, -1, { FALSE, 0, unexpected }) |
632ba2a2 | 349 | |
fbb0b3cb TB |
350 | #define _assert_payload(dir, c, ...) ({ \ |
351 | listener_message_rule_t _rules[] = { __VA_ARGS__ }; \ | |
632ba2a2 TB |
352 | listener_message_assert_t _listener = { \ |
353 | .listener = { .message = exchange_test_asserts_message, }, \ | |
354 | .file = __FILE__, \ | |
355 | .line = __LINE__, \ | |
67ad553a | 356 | .incoming = streq(dir, "IN") ? TRUE : FALSE, \ |
632ba2a2 | 357 | .count = c, \ |
fbb0b3cb TB |
358 | .rules = _rules, \ |
359 | .num_rules = countof(_rules), \ | |
632ba2a2 | 360 | }; \ |
7c6e0c29 | 361 | exchange_test_helper->add_listener(exchange_test_helper, &_listener.listener); \ |
632ba2a2 TB |
362 | }) |
363 | ||
72655fe4 TB |
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 | ||
632ba2a2 | 420 | #endif /** EXCHANGE_TEST_ASSERTS_H_ @}*/ |