1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 #ifndef UCX_TEST_H
68 #define UCX_TEST_H
69
70 #include "common.h"
71
72 #include <stdio.h>
73 #include <string.h>
74 #include <setjmp.h>
75
76 #ifdef __cplusplus
77 extern "C" {
78 #endif
79
80 #ifndef __FUNCTION__
81
82
83
84
85
86
87 #define __FUNCTION__ __func__
88 #endif
89
90 #if !defined(__clang__) &&
__GNUC__ >
3
91 #pragma GCC diagnostic ignored
"-Wclobbered"
92 #endif
93
94
95 typedef struct CxTestSuite CxTestSuite;
96
97
98 typedef void(*CxTest)(CxTestSuite *,
void *, cx_write_func);
99
100
101 typedef struct CxTestSet CxTestSet;
102
103
104 struct CxTestSet {
105
106
107 CxTest test;
108
109
110 CxTestSet *next;
111 };
112
113
114
115
116 struct CxTestSuite {
117
118
119 unsigned int success;
120
121
122 unsigned int failure;
123
124
125 const char *name;
126
127
128
129
130
131 CxTestSet *tests;
132 };
133
134
135
136
137
138
139 cx_attr_nonnull cx_attr_nodiscard cx_attr_cstr_arg(
1) cx_attr_malloc
140 static inline CxTestSuite* cx_test_suite_new(
const char *name) {
141 CxTestSuite* suite = (CxTestSuite*) malloc(
sizeof(CxTestSuite));
142 if (suite !=
NULL) {
143 suite->name = name;
144 suite->success =
0;
145 suite->failure =
0;
146 suite->tests =
NULL;
147 }
148
149 return suite;
150 }
151
152
153
154
155
156
157 CX_INLINE void cx_test_suite_free(CxTestSuite* suite) {
158 if (suite ==
NULL)
return;
159 CxTestSet *l = suite->tests;
160 while (l !=
NULL) {
161 CxTestSet *e = l;
162 l = l->next;
163 free(e);
164 }
165 free(suite);
166 }
167
168
169
170
171
172
173
174
175
176 cx_attr_nonnull
177 CX_INLINE int cx_test_register(CxTestSuite* suite, CxTest test) {
178 CxTestSet *t = (CxTestSet*) malloc(
sizeof(CxTestSet));
179 if (t) {
180 t->test = test;
181 t->next =
NULL;
182 if (suite->tests ==
NULL) {
183 suite->tests = t;
184 }
else {
185 CxTestSet *last = suite->tests;
186 while (last->next) {
187 last = last->next;
188 }
189 last->next = t;
190 }
191 return 0;
192 }
else {
193 return 1;
194 }
195 }
196
197
198
199
200
201
202
203 cx_attr_nonnull
204 CX_INLINE void cx_test_run(CxTestSuite *suite,
void *out_target, cx_write_func out_writer) {
205 if (suite->name ==
NULL) {
206 out_writer(
"*** Test Suite ***\n",
1,
19, out_target);
207 }
else {
208 out_writer(
"*** Test Suite : ",
1,
17, out_target);
209 out_writer(suite->name,
1, strlen(suite->name), out_target);
210 out_writer(
" ***\n",
1,
5, out_target);
211 }
212 suite->success =
0;
213 suite->failure =
0;
214 for (CxTestSet *elem = suite->tests; elem; elem = elem->next) {
215 elem->test(suite, out_target, out_writer);
216 }
217 out_writer(
"\nAll test completed.\n",
1,
21, out_target);
218 char total[
80];
219 int len = snprintf(
220 total,
80,
221 " Total: %u\n Success: %u\n Failure: %u\n\n",
222 suite->success + suite->failure, suite->success, suite->failure
223 );
224 out_writer(total,
1, len, out_target);
225 }
226
227
228
229
230
231
232 #define cx_test_run_f(suite, file) cx_test_run(suite, (
void*)file, (cx_write_func)fwrite)
233
234
235
236
237
238 #define cx_test_run_stdout(suite) cx_test_run_f(suite, stdout)
239
240
241
242
243
244
245
246
247 #define CX_TEST(name)
void name(CxTestSuite* _suite_,
void *_output_, cx_write_func _writefnc_)
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 #define CX_TEST_DO _writefnc_(
"Running ",
1,
8, _output_);\
266 _writefnc_(
__FUNCTION__,
1, strlen(
__FUNCTION__), _output_);\
267 _writefnc_(
"... ",
1,
4, _output_);\
268 jmp_buf _env_;\
269 for (
unsigned int _cx_test_loop_ =
0 ;\
270 _cx_test_loop_ ==
0 && !setjmp(_env_);\
271 _writefnc_(
"success.\n",
1,
9, _output_),\
272 _suite_->success++, _cx_test_loop_++)
273
274
275
276
277
278
279
280
281
282 #define CX_TEST_ASSERTM(condition,message)
if (!(condition)) { \
283 const char *_assert_msg_ = message; \
284 _writefnc_(_assert_msg_,
1, strlen(_assert_msg_), _output_); \
285 _writefnc_(
".\n",
1,
2, _output_); \
286 _suite_->failure++; \
287 longjmp(_env_,
1);\
288 } (
void)
0
289
290
291
292
293
294
295
296
297 #define CX_TEST_ASSERT(condition)
CX_TEST_ASSERTM(condition,
#condition " failed")
298
299
300
301
302
303
304
305
306
307
308
309
310 #define CX_TEST_SUBROUTINE(name,...)
void name(CxTestSuite* _suite_,\
311 void *_output_, cx_write_func _writefnc_, jmp_buf _env_,
__VA_ARGS__)
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326 #define CX_TEST_CALL_SUBROUTINE(name,...) \
327 name(_suite_,_output_,_writefnc_,_env_,
__VA_ARGS__)
328
329 #ifdef __cplusplus
330 }
331 #endif
332
333 #endif
334
335