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
140 cx_attr_nodiscard
141 cx_attr_cstr_arg(
1)
142 cx_attr_malloc
143 static inline CxTestSuite* cx_test_suite_new(
const char *name) {
144 CxTestSuite* suite = (CxTestSuite*) malloc(
sizeof(CxTestSuite));
145 if (suite !=
NULL) {
146 suite->name = name;
147 suite->success =
0;
148 suite->failure =
0;
149 suite->tests =
NULL;
150 }
151
152 return suite;
153 }
154
155
156
157
158
159
160 static inline
void cx_test_suite_free(CxTestSuite* suite) {
161 if (suite ==
NULL)
return;
162 CxTestSet *l = suite->tests;
163 while (l !=
NULL) {
164 CxTestSet *e = l;
165 l = l->next;
166 free(e);
167 }
168 free(suite);
169 }
170
171
172
173
174
175
176
177
178
179 cx_attr_nonnull
180 static inline
int cx_test_register(CxTestSuite* suite, CxTest test) {
181 CxTestSet *t = (CxTestSet*) malloc(
sizeof(CxTestSet));
182 if (t) {
183 t->test = test;
184 t->next =
NULL;
185 if (suite->tests ==
NULL) {
186 suite->tests = t;
187 }
else {
188 CxTestSet *last = suite->tests;
189 while (last->next) {
190 last = last->next;
191 }
192 last->next = t;
193 }
194 return 0;
195 }
else {
196 return 1;
197 }
198 }
199
200
201
202
203
204
205
206 cx_attr_nonnull
207 static inline
void cx_test_run(CxTestSuite *suite,
208 void *out_target, cx_write_func out_writer) {
209 if (suite->name ==
NULL) {
210 out_writer(
"*** Test Suite ***\n",
1,
19, out_target);
211 }
else {
212 out_writer(
"*** Test Suite : ",
1,
17, out_target);
213 out_writer(suite->name,
1, strlen(suite->name), out_target);
214 out_writer(
" ***\n",
1,
5, out_target);
215 }
216 suite->success =
0;
217 suite->failure =
0;
218 for (CxTestSet *elem = suite->tests; elem; elem = elem->next) {
219 elem->test(suite, out_target, out_writer);
220 }
221 out_writer(
"\nAll test completed.\n",
1,
21, out_target);
222 char total[
80];
223 int len = snprintf(
224 total,
80,
225 " Total: %u\n Success: %u\n Failure: %u\n\n",
226 suite->success + suite->failure, suite->success, suite->failure
227 );
228 out_writer(total,
1, len, out_target);
229 }
230
231
232
233
234
235
236 #define cx_test_run_f(suite, file) cx_test_run(suite, (
void*)file, (cx_write_func)fwrite)
237
238
239
240
241
242 #define cx_test_run_stdout(suite) cx_test_run_f(suite, stdout)
243
244
245
246
247
248
249
250
251 #define CX_TEST(name)
void name(CxTestSuite* _suite_,
void *_output_, cx_write_func _writefnc_)
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 #define CX_TEST_DO _writefnc_(
"Running ",
1,
8, _output_);\
270 _writefnc_(
__FUNCTION__,
1, strlen(
__FUNCTION__), _output_);\
271 _writefnc_(
"... ",
1,
4, _output_);\
272 jmp_buf _env_;\
273 for (
unsigned int _cx_test_loop_ =
0 ;\
274 _cx_test_loop_ ==
0 && !setjmp(_env_);\
275 _writefnc_(
"success.\n",
1,
9, _output_),\
276 _suite_->success++, _cx_test_loop_++)
277
278
279
280
281
282
283
284
285
286 #define CX_TEST_ASSERTM(condition,message)
if (!(condition)) { \
287 const char *_assert_msg_ = message; \
288 _writefnc_(_assert_msg_,
1, strlen(_assert_msg_), _output_); \
289 _writefnc_(
".\n",
1,
2, _output_); \
290 _suite_->failure++; \
291 longjmp(_env_,
1);\
292 } (
void)
0
293
294
295
296
297
298
299
300
301 #define CX_TEST_ASSERT(condition)
CX_TEST_ASSERTM(condition,
#condition " failed")
302
303
304
305
306
307
308
309
310
311
312
313
314 #define CX_TEST_SUBROUTINE(name,...)
void name(CxTestSuite* _suite_,\
315 void *_output_, cx_write_func _writefnc_, jmp_buf _env_,
__VA_ARGS__)
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330 #define CX_TEST_CALL_SUBROUTINE(name,...) \
331 name(_suite_,_output_,_writefnc_,_env_,
__VA_ARGS__)
332
333 #ifdef __cplusplus
334 }
335 #endif
336
337 #endif
338
339