1/* @title: Test Assertion Macros */
2#pragma once
3#include <compiler.h>
4#include <errno.h>
5#include <stdbool.h>
6#include <stddef.h>
7#include <stdint.h>
8#include <string.h>
9
10/* We expect
11 * - test_err(fmt, ...)
12 * - TEST_FAIL(msg)
13 * - test_global
14 *
15 * from test.h
16 */
17
18/* ==================== Boolean + Truthiness ==================== */
19
20#define TEST_ASSERT(cond) \
21 do { \
22 if (!(cond)) { \
23 test_err("assert \"%s\" failed", #cond); \
24 return TEST_FAIL(#cond); \
25 } \
26 } while (0)
27
28#define TEST_ASSERT_TRUE(cond) TEST_ASSERT(cond)
29
30#define TEST_ASSERT_FALSE(cond) \
31 do { \
32 if (cond) { \
33 test_err("assert false \"%s\" failed (was true)", #cond); \
34 return TEST_FAIL("!" #cond); \
35 } \
36 } while (0)
37
38#define TEST_ASSERT_MSG(cond, fmt, ...) \
39 do { \
40 if (!(cond)) { \
41 test_err("assert \"%s\" failed: " fmt, #cond, ##__VA_ARGS__); \
42 return TEST_FAIL(#cond); \
43 } \
44 } while (0)
45
46/* ==================== Pointer ==================== */
47#define TEST_ASSERT_NULL(ptr) \
48 do { \
49 const void *_p = (const void *) (ptr); \
50 if (_p != NULL) { \
51 test_err("assert \"%s == NULL\" failed (got %p)", #ptr, _p); \
52 return TEST_FAIL(#ptr " == NULL"); \
53 } \
54 } while (0)
55
56#define TEST_ASSERT_NONNULL(ptr) \
57 do { \
58 const void *_p = (const void *) (ptr); \
59 if (_p == NULL) { \
60 test_err("assert \"%s != NULL\" failed (got NULL)", #ptr); \
61 return TEST_FAIL(#ptr " != NULL"); \
62 } \
63 } while (0)
64
65#define TEST_ASSERT_PTR_EQ(a, b) \
66 do { \
67 const void *_pa = (const void *) (a); \
68 const void *_pb = (const void *) (b); \
69 if (_pa != _pb) { \
70 test_err("assert ptr \"%s == %s\" failed (%p != %p)", #a, #b, _pa, \
71 _pb); \
72 return TEST_FAIL(#a " == " #b); \
73 } \
74 } while (0)
75
76#define TEST_ASSERT_PTR_NE(a, b) \
77 do { \
78 const void *_pa = (const void *) (a); \
79 const void *_pb = (const void *) (b); \
80 if (_pa == _pb) { \
81 test_err("assert ptr \"%s != %s\" failed (both %p)", #a, #b, _pa); \
82 return TEST_FAIL(#a " != " #b); \
83 } \
84 } while (0)
85
86/* ==================== Unsigned Equality & Comparison ==================== */
87#define TEST_ASSERT_EQ(a, b) \
88 do { \
89 __typeof__(a) _a = (a); \
90 __typeof__(b) _b = (b); \
91 if ((uint64_t) (_a) != (uint64_t) (_b)) { \
92 test_err("assert \"%s == %s\" failed (%llu != %llu / 0x%llx != " \
93 "0x%llx)", \
94 #a, #b, (unsigned long long) (uint64_t) (_a), \
95 (unsigned long long) (uint64_t) (_b), \
96 (unsigned long long) (uint64_t) (_a), \
97 (unsigned long long) (uint64_t) (_b)); \
98 return TEST_FAIL(#a " == " #b); \
99 } \
100 } while (0)
101
102#define TEST_ASSERT_NE(a, b) \
103 do { \
104 __typeof__(a) _a = (a); \
105 __typeof__(b) _b = (b); \
106 if ((uint64_t) (_a) == (uint64_t) (_b)) { \
107 test_err("assert \"%s != %s\" failed (both equal %llu / 0x%llx)", \
108 #a, #b, (unsigned long long) (uint64_t) (_a), \
109 (unsigned long long) (uint64_t) (_a)); \
110 return TEST_FAIL(#a " != " #b); \
111 } \
112 } while (0)
113
114#define TEST_ASSERT_LT(a, b) \
115 do { \
116 __typeof__(a) _a = (a); \
117 __typeof__(b) _b = (b); \
118 if (!((uint64_t) (_a) < (uint64_t) (_b))) { \
119 test_err("assert \"%s < %s\" failed (%llu >= %llu)", #a, #b, \
120 (unsigned long long) (uint64_t) (_a), \
121 (unsigned long long) (uint64_t) (_b)); \
122 return TEST_FAIL(#a " < " #b); \
123 } \
124 } while (0)
125
126#define TEST_ASSERT_LE(a, b) \
127 do { \
128 __typeof__(a) _a = (a); \
129 __typeof__(b) _b = (b); \
130 if (!((uint64_t) (_a) <= (uint64_t) (_b))) { \
131 test_err("assert \"%s <= %s\" failed (%llu > %llu)", #a, #b, \
132 (unsigned long long) (uint64_t) (_a), \
133 (unsigned long long) (uint64_t) (_b)); \
134 return TEST_FAIL(#a " <= " #b); \
135 } \
136 } while (0)
137
138#define TEST_ASSERT_GT(a, b) \
139 do { \
140 __typeof__(a) _a = (a); \
141 __typeof__(b) _b = (b); \
142 if (!((uint64_t) (_a) > (uint64_t) (_b))) { \
143 test_err("assert \"%s > %s\" failed (%llu <= %llu)", #a, #b, \
144 (unsigned long long) (uint64_t) (_a), \
145 (unsigned long long) (uint64_t) (_b)); \
146 return TEST_FAIL(#a " > " #b); \
147 } \
148 } while (0)
149
150#define TEST_ASSERT_GE(a, b) \
151 do { \
152 __typeof__(a) _a = (a); \
153 __typeof__(b) _b = (b); \
154 if (!((uint64_t) (_a) >= (uint64_t) (_b))) { \
155 test_err("assert \"%s >= %s\" failed (%llu < %llu)", #a, #b, \
156 (unsigned long long) (uint64_t) (_a), \
157 (unsigned long long) (uint64_t) (_b)); \
158 return TEST_FAIL(#a " >= " #b); \
159 } \
160 } while (0)
161
162/* ==================== Signed Integer Comparisons ==================== */
163#define TEST_ASSERT_EQ_S(a, b) \
164 do { \
165 __typeof__(a) _a = (a); \
166 __typeof__(b) _b = (b); \
167 if ((int64_t) (_a) != (int64_t) (_b)) { \
168 test_err("assert \"%s == %s\" failed (%lld != %lld)", #a, #b, \
169 (long long) (int64_t) (_a), (long long) (int64_t) (_b)); \
170 return TEST_FAIL(#a " == " #b); \
171 } \
172 } while (0)
173
174#define TEST_ASSERT_LT_S(a, b) \
175 do { \
176 __typeof__(a) _a = (a); \
177 __typeof__(b) _b = (b); \
178 if (!((int64_t) (_a) < (int64_t) (_b))) { \
179 test_err("assert \"%s < %s\" failed (%lld >= %lld)", #a, #b, \
180 (long long) (int64_t) (_a), (long long) (int64_t) (_b)); \
181 return TEST_FAIL(#a " < " #b); \
182 } \
183 } while (0)
184
185#define TEST_ASSERT_LE_S(a, b) \
186 do { \
187 __typeof__(a) _a = (a); \
188 __typeof__(b) _b = (b); \
189 if (!((int64_t) (_a) <= (int64_t) (_b))) { \
190 test_err("assert \"%s <= %s\" failed (%lld > %lld)", #a, #b, \
191 (long long) (int64_t) (_a), (long long) (int64_t) (_b)); \
192 return TEST_FAIL(#a " <= " #b); \
193 } \
194 } while (0)
195
196#define TEST_ASSERT_GT_S(a, b) \
197 do { \
198 __typeof__(a) _a = (a); \
199 __typeof__(b) _b = (b); \
200 if (!((int64_t) (_a) > (int64_t) (_b))) { \
201 test_err("assert \"%s > %s\" failed (%lld <= %lld)", #a, #b, \
202 (long long) (int64_t) (_a), (long long) (int64_t) (_b)); \
203 return TEST_FAIL(#a " > " #b); \
204 } \
205 } while (0)
206
207#define TEST_ASSERT_GE_S(a, b) \
208 do { \
209 __typeof__(a) _a = (a); \
210 __typeof__(b) _b = (b); \
211 if (!((int64_t) (_a) >= (int64_t) (_b))) { \
212 test_err("assert \"%s >= %s\" failed (%lld < %lld)", #a, #b, \
213 (long long) (int64_t) (_a), (long long) (int64_t) (_b)); \
214 return TEST_FAIL(#a " >= " #b); \
215 } \
216 } while (0)
217
218/* ==================== Memory and String ==================== */
219#define TEST_ASSERT_STR_EQ(a, b) \
220 do { \
221 const char *_sa = (const char *) (a); \
222 const char *_sb = (const char *) (b); \
223 if (_sa == NULL || _sb == NULL || strcmp(_sa, _sb) != 0) { \
224 test_err("assert str \"%s == %s\" failed (\"%s\" != \"%s\")", #a, \
225 #b, _sa ? _sa : "<NULL>", _sb ? _sb : "<NULL>"); \
226 return TEST_FAIL(#a " == " #b); \
227 } \
228 } while (0)
229
230#define TEST_ASSERT_STR_NE(a, b) \
231 do { \
232 const char *_sa = (const char *) (a); \
233 const char *_sb = (const char *) (b); \
234 if (_sa == _sb || \
235 (_sa != NULL && _sb != NULL && strcmp(_sa, _sb) == 0)) { \
236 test_err("assert str \"%s != %s\" failed (both \"%s\")", #a, #b, \
237 _sa ? _sa : "<NULL>"); \
238 return TEST_FAIL(#a " != " #b); \
239 } \
240 } while (0)
241
242#define TEST_ASSERT_MEM_EQ(a, b, size) \
243 do { \
244 const void *_ma = (const void *) (a); \
245 const void *_mb = (const void *) (b); \
246 size_t _sz = (size_t) (size); \
247 if (memcmp(_ma, _mb, _sz) != 0) { \
248 test_err("assert mem \"%s == %s\" failed (size %zu)", #a, #b, \
249 _sz); \
250 return TEST_FAIL(#a " == " #b); \
251 } \
252 } while (0)
253
254#define TEST_ASSERT_MEM_ZERO(ptr, size) \
255 do { \
256 const uint8_t *_pz = (const uint8_t *) (ptr); \
257 size_t _sz = (size_t) (size); \
258 bool _all_zero = true; \
259 size_t _first_bad = 0; \
260 for (size_t _i = 0; _i < _sz; _i++) { \
261 if (_pz[_i] != 0) { \
262 _all_zero = false; \
263 _first_bad = _i; \
264 break; \
265 } \
266 } \
267 if (!_all_zero) { \
268 test_err("assert mem_zero \"%s\" failed (nonzero byte 0x%02x at " \
269 "offset %zu of %zu)", \
270 #ptr, _pz[_first_bad], _first_bad, _sz); \
271 return TEST_FAIL(#ptr " is zero"); \
272 } \
273 } while (0)
274
275/* ==================== Errors and statuses ==================== */
276#define TEST_ASSERT_OK(err) \
277 do { \
278 __typeof__(err) _err = (err); \
279 if (_err != 0) { \
280 test_err("assert ok \"%s == 0\" failed (error code %lld / " \
281 "0x%llx)", \
282 #err, (long long) (int64_t) (_err), \
283 (unsigned long long) (uint64_t) (_err)); \
284 return TEST_FAIL(#err " == 0"); \
285 } \
286 } while (0)
287
288/* ==================== Range and Bit Manipulation ==================== */
289#define TEST_ASSERT_IN_RANGE(val, min, max) \
290 do { \
291 __typeof__(val) _v = (val); \
292 __typeof__(min) _min = (min); \
293 __typeof__(max) _max = (max); \
294 if (!((_v) >= (_min) && (_v) <= (_max))) { \
295 test_err("assert in range \"%s <= %s <= %s\" failed (val=%llu, " \
296 "range=[%llu, %llu])", \
297 #min, #val, #max, (unsigned long long) (uint64_t) (_v), \
298 (unsigned long long) (uint64_t) (_min), \
299 (unsigned long long) (uint64_t) (_max)); \
300 return TEST_FAIL(#val " in range [" #min ", " #max "]"); \
301 } \
302 } while (0)
303
304#define TEST_ASSERT_BIT_SET(val, bit) \
305 do { \
306 uint64_t _v = (uint64_t) (val); \
307 uint32_t _b = (uint32_t) (bit); \
308 if (!(_v & (1ULL << _b))) { \
309 test_err("assert bit set \"%s bit %u\" failed (val=0x%llx)", #val, \
310 _b, (unsigned long long) _v); \
311 return TEST_FAIL(#val " bit " #bit " is set"); \
312 } \
313 } while (0)
314
315#define TEST_ASSERT_BIT_CLEAR(val, bit) \
316 do { \
317 uint64_t _v = (uint64_t) (val); \
318 uint32_t _b = (uint32_t) (bit); \
319 if (_v & (1ULL << _b)) { \
320 test_err("assert bit clear \"%s bit %u\" failed (val=0x%llx)", \
321 #val, _b, (unsigned long long) _v); \
322 return TEST_FAIL(#val " bit " #bit " is clear"); \
323 } \
324 } while (0)
325
326#define TEST_ASSERT_MASK_SET(val, mask) \
327 do { \
328 uint64_t _v = (uint64_t) (val); \
329 uint64_t _m = (uint64_t) (mask); \
330 if ((_v & _m) != _m) { \
331 test_err("assert mask set \"%s & %s == %s\" failed (val=0x%llx, " \
332 "mask=0x%llx)", \
333 #val, #mask, #mask, (unsigned long long) _v, \
334 (unsigned long long) _m); \
335 return TEST_FAIL(#val " has mask " #mask); \
336 } \
337 } while (0)
338
339/* ==================== For void helper functions ==================== */
340#define TEST_ASSERT_VOID(cond) \
341 do { \
342 if (!(cond)) { \
343 test_err("assert void \"%s\" failed", #cond); \
344 return; \
345 } \
346 } while (0)
347
348#define TEST_ASSERT_VOID_MSG(cond, fmt, ...) \
349 do { \
350 if (!(cond)) { \
351 test_err("assert void \"%s\" failed: " fmt, #cond, ##__VA_ARGS__); \
352 return; \
353 } \
354 } while (0)
355
356#define TEST_ASSERT_VOID_EQ(a, b) \
357 do { \
358 __typeof__(a) _a = (a); \
359 __typeof__(b) _b = (b); \
360 if ((uint64_t) (_a) != (uint64_t) (_b)) { \
361 test_err("assert void \"%s == %s\" failed (%llu != %llu / 0x%llx " \
362 "!= 0x%llx)", \
363 #a, #b, (unsigned long long) (uint64_t) (_a), \
364 (unsigned long long) (uint64_t) (_b), \
365 (unsigned long long) (uint64_t) (_a), \
366 (unsigned long long) (uint64_t) (_b)); \
367 return; \
368 } \
369 } while (0)
370
371#define TEST_ASSERT_VOID_NONNULL(ptr) \
372 do { \
373 const void *_p = (const void *) (ptr); \
374 if (_p == NULL) { \
375 test_err("assert void \"%s != NULL\" failed", #ptr); \
376 return; \
377 } \
378 } while (0)
379
380/* ==================== Soft assertions ==================== */
381#define TEST_EXPECT(cond) \
382 do { \
383 if (!(cond)) { \
384 test_err("expect \"%s\" failed", #cond); \
385 if (test_global.current_test) \
386 test_global.current_test->soft_fails++; \
387 } \
388 } while (0)
389
390#define TEST_EXPECT_EQ(a, b) \
391 do { \
392 __typeof__(a) _a = (a); \
393 __typeof__(b) _b = (b); \
394 if ((uint64_t) (_a) != (uint64_t) (_b)) { \
395 test_err("expect \"%s == %s\" failed (%llu != %llu / 0x%llx != " \
396 "0x%llx)", \
397 #a, #b, (unsigned long long) (uint64_t) (_a), \
398 (unsigned long long) (uint64_t) (_b), \
399 (unsigned long long) (uint64_t) (_a), \
400 (unsigned long long) (uint64_t) (_b)); \
401 if (test_global.current_test) \
402 test_global.current_test->soft_fails++; \
403 } \
404 } while (0)
405
406#define TEST_EXPECT_NONNULL(ptr) \
407 do { \
408 const void *_p = (const void *) (ptr); \
409 if (_p == NULL) { \
410 test_err("expect \"%s != NULL\" failed", #ptr); \
411 if (test_global.current_test) \
412 test_global.current_test->soft_fails++; \
413 } \
414 } while (0)
415
416#define TEST_EXPECT_MSG(cond, fmt, ...) \
417 do { \
418 if (!(cond)) { \
419 test_err("expect \"%s\" failed: " fmt, #cond, ##__VA_ARGS__); \
420 if (test_global.current_test) \
421 test_global.current_test->soft_fails++; \
422 } \
423 } while (0)
424