Raw
1 /*
2 * Copyright (c) Vicent Marti. All rights reserved.
3 *
4 * This file is part of clar, distributed under the ISC license.
5 * For full terms see the included COPYING file.
6 */
7 #ifndef __CLAR_TEST_H__
8 #define __CLAR_TEST_H__
9
10 #include <inttypes.h>
11 #include <stdlib.h>
12 #include <limits.h>
13
14 #if defined(_WIN32) && defined(CLAR_WIN32_LONGPATHS)
15 # define CLAR_MAX_PATH 4096
16 #elif defined(_WIN32)
17 # define CLAR_MAX_PATH MAX_PATH
18 #elif defined(PATH_MAX)
19 # define CLAR_MAX_PATH PATH_MAX
20 #else
21 # define CLAR_MAX_PATH 4096
22 #endif
23
24 #ifndef CLAR_SELFTEST
25 # define CLAR_CURRENT_FILE __FILE__
26 # define CLAR_CURRENT_LINE __LINE__
27 # define CLAR_CURRENT_FUNC __func__
28 #else
29 # define CLAR_CURRENT_FILE "file"
30 # define CLAR_CURRENT_LINE 42
31 # define CLAR_CURRENT_FUNC "func"
32 #endif
33
34 enum cl_test_status {
35 CL_TEST_OK,
36 CL_TEST_FAILURE,
37 CL_TEST_SKIP,
38 CL_TEST_NOTRUN,
39 };
40
41 enum cl_output_format {
42 CL_OUTPUT_CLAP,
43 CL_OUTPUT_TAP,
44 };
45
46 /** Setup clar environment */
47 void clar_test_init(int argc, char *argv[]);
48 int clar_test_run(void);
49 void clar_test_shutdown(void);
50
51 /** One shot setup & run */
52 int clar_test(int argc, char *argv[]);
53
54 const char *clar_sandbox_path(void);
55 const char *clar_tempdir_path(void);
56
57 void cl_set_cleanup(void (*cleanup)(void *), void *opaque);
58 void cl_fs_cleanup(void);
59
60 /**
61 * cl_trace_* is a hook to provide a simple global tracing
62 * mechanism.
63 *
64 * The goal here is to let main() provide clar-proper
65 * with a callback to optionally write log info for
66 * test operations into the same stream used by their
67 * actual tests. This would let them print test names
68 * and maybe performance data as they choose.
69 *
70 * The goal is NOT to alter the flow of control or to
71 * override test selection/skipping. (So the callback
72 * does not return a value.)
73 *
74 * The goal is NOT to duplicate the existing
75 * pass/fail/skip reporting. (So the callback
76 * does not accept a status/errorcode argument.)
77 *
78 */
79 typedef enum cl_trace_event {
80 CL_TRACE__SUITE_BEGIN,
81 CL_TRACE__SUITE_END,
82 CL_TRACE__TEST__BEGIN,
83 CL_TRACE__TEST__END,
84 CL_TRACE__TEST__RUN_BEGIN,
85 CL_TRACE__TEST__RUN_END,
86 CL_TRACE__TEST__LONGJMP,
87 } cl_trace_event;
88
89 typedef void (cl_trace_cb)(
90 cl_trace_event ev,
91 const char *suite_name,
92 const char *test_name,
93 void *payload);
94
95 /**
96 * Register a callback into CLAR to send global trace events.
97 * Pass NULL to disable.
98 */
99 void cl_trace_register(cl_trace_cb *cb, void *payload);
100
101
102 #ifdef CLAR_FIXTURE_PATH
103 const char *cl_fixture(const char *fixture_name);
104 void cl_fixture_sandbox(const char *fixture_name);
105 void cl_fixture_cleanup(const char *fixture_name);
106 const char *cl_fixture_basename(const char *fixture_name);
107 #endif
108
109 /**
110 * Invoke a helper function, which itself will use `cl_assert`
111 * constructs. This will preserve the stack information of the
112 * current call point, so that function name and line number
113 * information is shown from the line of the test, instead of
114 * the helper function.
115 */
116 #define cl_invoke(expr) \
117 do { \
118 clar__set_invokepoint(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE); \
119 expr; \
120 clar__clear_invokepoint(); \
121 } while(0)
122
123 /**
124 * Assertion macros with explicit error message
125 */
126 #define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Function call failed: " #expr, desc, 1)
127 #define cl_must_fail_(expr, desc) clar__assert((expr) < 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expected function call to fail: " #expr, desc, 1)
128 #define cl_assert_(expr, desc) clar__assert((expr) != 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expression is not true: " #expr, desc, 1)
129
130 /**
131 * Check macros with explicit error message
132 */
133 #define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Function call failed: " #expr, desc, 0)
134 #define cl_check_fail_(expr, desc) clar__assert((expr) < 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expected function call to fail: " #expr, desc, 0)
135 #define cl_check_(expr, desc) clar__assert((expr) != 0, CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Expression is not true: " #expr, desc, 0)
136
137 /**
138 * Assertion macros with no error message
139 */
140 #define cl_must_pass(expr) cl_must_pass_(expr, NULL)
141 #define cl_must_fail(expr) cl_must_fail_(expr, NULL)
142 #define cl_assert(expr) cl_assert_(expr, NULL)
143
144 /**
145 * Check macros with no error message
146 */
147 #define cl_check_pass(expr) cl_check_pass_(expr, NULL)
148 #define cl_check_fail(expr) cl_check_fail_(expr, NULL)
149 #define cl_check(expr) cl_check_(expr, NULL)
150
151 /**
152 * Forced failure/warning
153 */
154 #define cl_fail(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Test failed.", desc, 1)
155 #define cl_failf(desc,...) clar__failf(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, 1, "Test failed.", desc, __VA_ARGS__)
156 #define cl_warning(desc) clar__fail(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, "Warning during test execution:", desc, 0)
157
158 #define cl_skip() clar__skip()
159
160 /**
161 * Typed assertion macros
162 */
163 #define cl_assert_equal_s(s1,s2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2))
164 #define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2))
165
166 #define cl_assert_equal_wcs(wcs1,wcs2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2, 1, "%ls", (wcs1), (wcs2))
167 #define cl_assert_equal_wcs_(wcs1,wcs2,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%ls", (wcs1), (wcs2))
168
169 #define cl_assert_equal_strn(s1,s2,len) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2, 1, "%.*s", (s1), (s2), (int)(len))
170 #define cl_assert_equal_strn_(s1,s2,len,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%.*s", (s1), (s2), (int)(len))
171
172 #define cl_assert_equal_wcsn(wcs1,wcs2,len) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2, 1, "%.*ls", (wcs1), (wcs2), (int)(len))
173 #define cl_assert_equal_wcsn_(wcs1,wcs2,len,note) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"String mismatch: " #wcs1 " != " #wcs2 " (" #note ")", 1, "%.*ls", (wcs1), (wcs2), (int)(len))
174
175 #define cl_assert_compare_i_(i1, i2, cmp, error, ...) clar__assert_compare_i(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, 1, cmp, \
176 (i1), (i2), "Expected comparison to hold: " error, __VA_ARGS__)
177 #define cl_assert_compare_i(i1, i2, cmp, error, fmt) do { \
178 intmax_t v1 = (i1), v2 = (i2); \
179 clar__assert_compare_i(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, 1, cmp, \
180 v1, v2, "Expected comparison to hold: " error, fmt, v1, v2); \
181 } while (0)
182 #define cl_assert_equal_i_(i1, i2, ...) cl_assert_compare_i_(i1, i2, CLAR_COMPARISON_EQ, #i1 " == " #i2, __VA_ARGS__)
183 #define cl_assert_equal_i(i1, i2) cl_assert_compare_i (i1, i2, CLAR_COMPARISON_EQ, #i1 " == " #i2, "%"PRIdMAX " != %"PRIdMAX)
184 #define cl_assert_equal_i_fmt(i1, i2, fmt) cl_assert_compare_i_(i1, i2, CLAR_COMPARISON_EQ, #i1 " == " #i2, fmt " != " fmt, (int)(i1), (int)(i2))
185 #define cl_assert_lt_i_(i1, i2, ...) cl_assert_compare_i_(i1, i2, CLAR_COMPARISON_LT, #i1 " < " #i2, __VA_ARGS__)
186 #define cl_assert_lt_i(i1, i2) cl_assert_compare_i (i1, i2, CLAR_COMPARISON_LT, #i1 " < " #i2, "%"PRIdMAX " >= %"PRIdMAX)
187 #define cl_assert_le_i_(i1, i2, ...) cl_assert_compare_i_(i1, i2, CLAR_COMPARISON_LE, #i1 " <= " #i2, __VA_ARGS__)
188 #define cl_assert_le_i(i1, i2) cl_assert_compare_i (i1, i2, CLAR_COMPARISON_LE, #i1 " <= " #i2, "%"PRIdMAX " > %"PRIdMAX)
189 #define cl_assert_gt_i_(i1, i2, ...) cl_assert_compare_i_(i1, i2, CLAR_COMPARISON_GT, #i1 " > " #i2, __VA_ARGS__)
190 #define cl_assert_gt_i(i1, i2) cl_assert_compare_i (i1, i2, CLAR_COMPARISON_GT, #i1 " > " #i2, "%"PRIdMAX " <= %"PRIdMAX)
191 #define cl_assert_ge_i_(i1, i2, ...) cl_assert_compare_i_(i1, i2, CLAR_COMPARISON_GE, #i1 " >= " #i2, __VA_ARGS__)
192 #define cl_assert_ge_i(i1, i2) cl_assert_compare_i (i1, i2, CLAR_COMPARISON_GE, #i1 " >= " #i2, "%"PRIdMAX " < %"PRIdMAX)
193
194 #define cl_assert_compare_u_(u1, u2, cmp, error, ...) clar__assert_compare_u(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, 1, cmp, \
195 (u1), (u2), "Expected comparison to hold: " error, __VA_ARGS__)
196 #define cl_assert_compare_u(u1, u2, cmp, error, fmt) do { \
197 uintmax_t v1 = (u1), v2 = (u2); \
198 clar__assert_compare_u(CLAR_CURRENT_FILE, CLAR_CURRENT_FUNC, CLAR_CURRENT_LINE, 1, cmp, \
199 v1, v2, "Expected comparison to hold: " error, fmt, v1, v2); \
200 } while (0)
201 #define cl_assert_equal_u_(u1, u2, ...) cl_assert_compare_u_(u1, u2, CLAR_COMPARISON_EQ, #u1 " == " #u2, __VA_ARGS__)
202 #define cl_assert_equal_u(u1, u2) cl_assert_compare_u (u1, u2, CLAR_COMPARISON_EQ, #u1 " == " #u2, "%"PRIuMAX " != %"PRIuMAX)
203 #define cl_assert_lt_u_(u1, u2, ...) cl_assert_compare_u_(u1, u2, CLAR_COMPARISON_LT, #u1 " < " #u2, __VA_ARGS__)
204 #define cl_assert_lt_u(u1, u2) cl_assert_compare_u (u1, u2, CLAR_COMPARISON_LT, #u1 " < " #u2, "%"PRIuMAX " >= %"PRIuMAX)
205 #define cl_assert_le_u_(u1, u2, ...) cl_assert_compare_u_(u1, u2, CLAR_COMPARISON_LE, #u1 " <= " #u2, __VA_ARGS__)
206 #define cl_assert_le_u(u1, u2) cl_assert_compare_u (u1, u2, CLAR_COMPARISON_LE, #u1 " <= " #u2, "%"PRIuMAX " > %"PRIuMAX)
207 #define cl_assert_gt_u_(u1, u2, ...) cl_assert_compare_u_(u1, u2, CLAR_COMPARISON_GT, #u1 " > " #u2, __VA_ARGS__)
208 #define cl_assert_gt_u(u1, u2) cl_assert_compare_u (u1, u2, CLAR_COMPARISON_GT, #u1 " > " #u2, "%"PRIuMAX " <= %"PRIuMAX)
209 #define cl_assert_ge_u_(u1, u2, ...) cl_assert_compare_u_(u1, u2, CLAR_COMPARISON_GE, #u1 " >= " #u2, __VA_ARGS__)
210 #define cl_assert_ge_u(u1, u2) cl_assert_compare_u (u1, u2, CLAR_COMPARISON_GE, #u1 " >= " #u2, "%"PRIuMAX " < %"PRIuMAX)
211
212 #define cl_assert_equal_b(b1,b2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0))
213
214 #define cl_assert_equal_p(p1,p2) clar__assert_equal(CLAR_CURRENT_FILE,CLAR_CURRENT_FUNC,CLAR_CURRENT_LINE,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2))
215
216 void clar__skip(void);
217
218 void clar__fail(
219 const char *file,
220 const char *func,
221 size_t line,
222 const char *error,
223 const char *description,
224 int should_abort);
225
226 void clar__failf(
227 const char *file,
228 const char *func,
229 size_t line,
230 int should_abort,
231 const char *error,
232 const char *description,
233 ...);
234
235 void clar__assert(
236 int condition,
237 const char *file,
238 const char *func,
239 size_t line,
240 const char *error,
241 const char *description,
242 int should_abort);
243
244 void clar__assert_equal(
245 const char *file,
246 const char *func,
247 size_t line,
248 const char *err,
249 int should_abort,
250 const char *fmt,
251 ...);
252
253 enum clar_comparison {
254 CLAR_COMPARISON_EQ,
255 CLAR_COMPARISON_LT,
256 CLAR_COMPARISON_LE,
257 CLAR_COMPARISON_GT,
258 CLAR_COMPARISON_GE,
259 };
260
261 void clar__assert_compare_i(
262 const char *file,
263 const char *func,
264 size_t line,
265 int should_abort,
266 enum clar_comparison cmp,
267 intmax_t value1,
268 intmax_t value2,
269 const char *error,
270 const char *description,
271 ...);
272
273 void clar__assert_compare_u(
274 const char *file,
275 const char *func,
276 size_t line,
277 int should_abort,
278 enum clar_comparison cmp,
279 uintmax_t value1,
280 uintmax_t value2,
281 const char *error,
282 const char *description,
283 ...);
284
285 void clar__set_invokepoint(
286 const char *file,
287 const char *func,
288 size_t line);
289
290 void clar__clear_invokepoint(void);
291
292 #endif