Merge branch 'fetcher-response-code'
[strongswan.git] / src / libstrongswan / tests / test_suite.h
1 /*
2 * Copyright (C) 2013 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 * Copyright (C) 2013 Martin Willi
5 * Copyright (C) 2013 revosec AG
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 /**
19 * @defgroup test_suite test_suite
20 * @{ @ingroup libtest
21 */
22
23 #ifndef TEST_SUITE_H_
24 #define TEST_SUITE_H_
25
26 #define _GNU_SOURCE
27 #include <setjmp.h>
28
29 #include <library.h>
30 #include <utils/debug.h>
31 #include <utils/backtrace.h>
32 #include <collections/array.h>
33
34 typedef struct test_suite_t test_suite_t;
35 typedef struct test_case_t test_case_t;
36 typedef struct test_function_t test_function_t;
37 typedef struct test_fixture_t test_fixture_t;
38
39 /**
40 * Default timeout for a single test function
41 */
42 #define TEST_FUNCTION_DEFAULT_TIMEOUT 2
43
44 /**
45 * Test function implementation
46 */
47 typedef void (*test_function_cb_t)(int);
48
49 /**
50 * Fixture for a test case.
51 */
52 typedef void (*test_fixture_cb_t)(void);
53
54 /**
55 * A test suite; a collection of test cases with fixtures
56 */
57 struct test_suite_t {
58 /** name of the test suite */
59 const char *name;
60 /** test cases registered, as test_case_t* */
61 array_t *tcases;
62 };
63
64 /**
65 * A test case; multiple test functions using the same fixtures
66 */
67 struct test_case_t {
68 /** name of the test case */
69 const char *name;
70 /** tests registered, as test_function_t */
71 array_t *functions;
72 /** fixture for tests, as test_fixture_t */
73 array_t *fixtures;
74 /** timeout for each function, in s */
75 int timeout;
76 };
77
78 /**
79 * A test function, with optional loop setup
80 */
81 struct test_function_t {
82 /** name of test function */
83 char *name;
84 /** tests function registered, test_function_t* */
85 test_function_cb_t cb;
86 /** start for loop test */
87 int start;
88 /** end for loop test */
89 int end;
90 };
91
92 /**
93 * Registered fixture for a test case
94 */
95 struct test_fixture_t {
96 test_fixture_cb_t setup;
97 test_fixture_cb_t teardown;
98 };
99
100 /**
101 * Create a new test suite
102 *
103 * @param name name of the test suite
104 * @return test suite
105 */
106 test_suite_t* test_suite_create(const char *name);
107
108 /**
109 * Create a new test case
110 *
111 * @param name name of test case
112 * @return test case
113 */
114 test_case_t* test_case_create(const char *name);
115
116 /**
117 * Add a setup/teardown function to the test case
118 *
119 * @param tcase test case to add a fixture to
120 * @param setup setup function called before each test
121 * @param teardown cleanup function called after each test
122 */
123 void test_case_add_checked_fixture(test_case_t *tcase, test_fixture_cb_t setup,
124 test_fixture_cb_t teardown);
125
126 /**
127 * Add a test function to a test case, with a name, looped several times
128 *
129 * @param name name of the test case
130 * @param tcase test case to add test function to
131 * @param cb callback function to invoke for test
132 * @param start start of loop counter
133 * @param end end of loop counter
134 */
135 void test_case_add_test_name(test_case_t *tcase, char *name,
136 test_function_cb_t cb, int start, int end);
137
138 /**
139 * Add a test function to a test case
140 *
141 * @param tcase test case to add test function to
142 * @param cb callback function to invoke for test
143 */
144 #define test_case_add_test(tcase, cb) \
145 test_case_add_test_name(tcase, #cb, cb, 0, 1)
146
147 /**
148 * Add a test function to a test case, looped several times
149 *
150 * @param tcase test case to add test function to
151 * @param cb callback function to invoke for test
152 * @param start start of loop counter
153 * @param end end of loop counter
154 */
155 #define test_case_add_loop_test(tcase, cb, start, end) \
156 test_case_add_test_name(tcase, #cb, cb, start, end)
157
158 /**
159 * Set a custom timeout for test functions in a test case
160 *
161 * @param tcase test case to set timeout for
162 * @param s test timeout in s
163 */
164 void test_case_set_timeout(test_case_t *tcase, int s);
165
166 /**
167 * Add a test function to a test case, looped several times
168 *
169 * @param suite test suite to add test case to
170 * @param tcase test case to add
171 */
172 void test_suite_add_case(test_suite_t *suite, test_case_t *tcase);
173
174 /**
175 * sigjmp restore point used by test_restore_point
176 */
177 extern sigjmp_buf test_restore_point_env;
178
179 /**
180 * Set or return from an execution restore point
181 *
182 * This call sets a restore execution point and returns TRUE after it has
183 * been set up. On test failure, the execution is returned to the restore point
184 * and FALSE is returned to indicate test failure.
185 *
186 * @return TRUE if restore point set, FALSE when restored
187 */
188 #define test_restore_point() (sigsetjmp(test_restore_point_env, 1) == 0)
189
190 /**
191 * Set up signal handlers for test cases
192 */
193 void test_setup_handler();
194
195 /**
196 * Set up a timeout to let a test fail
197 *
198 * @param s timeout, 0 to disable timeout
199 */
200 void test_setup_timeout(int s);
201
202 /**
203 * Get info about a test failure
204 *
205 * @param msg buffer receiving failure info
206 * @param len size of msg buffer
207 * @param file pointer receiving source code file
208 * @return source code line number
209 */
210 int test_failure_get(char *msg, int len, const char **file);
211
212 /**
213 * Get a backtrace for a failure.
214 *
215 * @return allocated backtrace of test failure, if any
216 */
217 backtrace_t *test_failure_backtrace();
218
219 /**
220 * Let a test fail and set a message using vprintf style arguments.
221 *
222 * @param file source code file name
223 * @param line source code line number
224 * @param fmt printf format string
225 * @param args argument list for fmt
226 */
227 void test_fail_vmsg(const char *file, int line, char *fmt, va_list args);
228
229 /**
230 * Let a test fail and set a message using printf style arguments.
231 *
232 * @param file source code file name
233 * @param line source code line number
234 * @param fmt printf format string
235 * @param ... arguments for fmt
236 */
237 void test_fail_msg(const char *file, int line, char *fmt, ...);
238
239 /**
240 * Let a test fail if one of the worker threads has failed (only if called from
241 * the main thread).
242 */
243 void test_fail_if_worker_failed();
244
245 /**
246 * Check if two integers equal, fail test if not
247 *
248 * @param a first integer
249 * @param b second integer
250 */
251 #define test_int_eq(a, b) \
252 ({ \
253 typeof(a) _a = a; \
254 typeof(b) _b = b; \
255 test_fail_if_worker_failed(); \
256 if (_a != _b) \
257 { \
258 test_fail_msg(__FILE__, __LINE__, #a " != " #b " (%d != %d)", _a, _b); \
259 } \
260 })
261
262 /**
263 * Check if two strings equal, fail test if not
264 *
265 * @param a first string
266 * @param b second string
267 */
268 #define test_str_eq(a, b) \
269 ({ \
270 char* _a = (char*)a; \
271 char* _b = (char*)b; \
272 test_fail_if_worker_failed(); \
273 if (!_a || !_b || !streq(_a, _b)) \
274 { \
275 test_fail_msg(__FILE__, __LINE__, \
276 #a " != " #b " (\"%s\" != \"%s\")", _a, _b); \
277 } \
278 })
279
280 /**
281 * Check if two chunks are equal, fail test if not
282 *
283 * @param a first chunk
284 * @param b second chunk
285 */
286 #define test_chunk_eq(a, b) \
287 ({ \
288 chunk_t _a = (chunk_t)a; \
289 chunk_t _b = (chunk_t)b; \
290 test_fail_if_worker_failed(); \
291 if (_a.len != _b.len || !memeq(a.ptr, b.ptr, a.len)) \
292 { \
293 test_fail_msg(__FILE__, __LINE__, \
294 #a " != " #b " (\"%#B\" != \"%#B\")", &_a, &_b); \
295 } \
296 })
297
298 /**
299 * Check if a statement evaluates to TRUE, fail test if not
300 *
301 * @param x statement to evaluate
302 */
303 #define test_assert(x) \
304 ({ \
305 test_fail_if_worker_failed(); \
306 if (!(x)) \
307 { \
308 test_fail_msg(__FILE__, __LINE__, #x); \
309 } \
310 })
311
312 /**
313 * Check if a statement evaluates to TRUE, fail and print a message if not
314 *
315 * @param x statement to evaluate
316 * @param fmt message format string
317 * @param ... fmt printf arguments
318 */
319 #define test_assert_msg(x, fmt, ...) \
320 ({ \
321 test_fail_if_worker_failed(); \
322 if (!(x)) \
323 { \
324 test_fail_msg(__FILE__, __LINE__, #x ": " fmt, ##__VA_ARGS__); \
325 } \
326 })
327
328
329
330 /* "check unit testing" compatibility */
331 #define Suite test_suite_t
332 #define TCase test_case_t
333 #define ck_assert_int_eq test_int_eq
334 #define ck_assert test_assert
335 #define ck_assert_msg test_assert_msg
336 #define ck_assert_str_eq test_str_eq
337 #define ck_assert_chunk_eq test_chunk_eq
338 #define fail(fmt, ...) test_fail_msg(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
339 #define fail_if(x, fmt, ...) \
340 ({ \
341 test_fail_if_worker_failed(); \
342 if (x) \
343 { \
344 test_fail_msg(__FILE__, __LINE__, #x ": " fmt, ##__VA_ARGS__); \
345 } \
346 })
347 #define fail_unless test_assert_msg
348 #define suite_create test_suite_create
349 #define tcase_create test_case_create
350 #define tcase_add_checked_fixture test_case_add_checked_fixture
351 #define tcase_add_test test_case_add_test
352 #define tcase_add_loop_test test_case_add_loop_test
353 #define tcase_set_timeout test_case_set_timeout
354 #define suite_add_tcase test_suite_add_case
355 #define START_TEST(name) static void name (int _i) {
356 #define END_TEST test_fail_if_worker_failed(); }
357 #define START_SETUP(name) static void name() {
358 #define END_SETUP test_fail_if_worker_failed(); }
359 #define START_TEARDOWN(name) static void name() {
360 #define END_TEARDOWN test_fail_if_worker_failed(); }
361
362 #endif /** TEST_SUITE_H_ @}*/