1 /*
2 * Copyright (C) 2018 - 2020 Intel Corporation
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #ifndef _USFSTL_ASSERT_H_
7 #define _USFSTL_ASSERT_H_
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <stdarg.h>
13 #include <stdbool.h>
14
15 /*
16 * usfstl_abort - abort a test and print the given message(s)
17 */
18 static inline void __attribute__((noreturn, format(printf, 4, 5)))
usfstl_abort(const char * fn,unsigned int line,const char * cond,const char * msg,...)19 usfstl_abort(const char *fn, unsigned int line, const char *cond, const char *msg, ...)
20 {
21 va_list va;
22
23 printf("assertion failure in %s (line %d)\n", fn, line);
24 printf("'%s' failed\n", cond);
25 va_start(va, msg);
26 vprintf(msg, va);
27 va_end(va);
28 abort();
29 }
30
31 #define USFSTL_BUILD_BUG_ON(expr) extern void __bbo_##__LINE__(char[1 - 2*!!(expr)]);
32
33 #define _USFSTL_2STR(x) #x
34 #define USFSTL_2STR(x) _USFSTL_2STR(x)
35
36 #define __USFSTL_COUNTDOWN 10,9,8,7,6,5,4,3,2,1,0
37 #define __USFSTL_COUNT(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
38 #define _USFSTL_COUNT(...) __USFSTL_COUNT(__VA_ARGS__)
39 #define USFSTL_COUNT(...) _USFSTL_COUNT(, ##__VA_ARGS__, __USFSTL_COUNTDOWN)
40 #define __USFSTL_ASSERT_HASARGS_LIST 1,1,1,1,1,1,1,1,1,1,0
41 #define USFSTL_HASARGS(...) _USFSTL_COUNT(, ##__VA_ARGS__, __USFSTL_ASSERT_HASARGS_LIST)
42
43 #define __usfstl_dispatch(func, numargs) \
44 func ## numargs
45 #define _usfstl_dispatch(func, numargs) \
46 __usfstl_dispatch(func, numargs)
47 #define usfstl_dispatch(func, ...) \
48 _usfstl_dispatch(func, USFSTL_HASARGS(__VA_ARGS__))
49
50 #define _USFSTL_ASSERT_0(cstr, cond) do { \
51 if (!(cond)) \
52 usfstl_abort(__FILE__, __LINE__, cstr, ""); \
53 } while (0)
54
55 #define _USFSTL_ASSERT_1(cstr, cond, msg, ...) do { \
56 if (!(cond)) \
57 usfstl_abort(__FILE__, __LINE__, cstr, \
58 msg, ##__VA_ARGS__); \
59 } while (0)
60
61 /*
62 * assert, with or without message
63 *
64 * USFSTL_ASSERT(cond)
65 * USFSTL_ASSERT(cond, msg, format)
66 */
67 #define USFSTL_ASSERT(cond, ...) \
68 usfstl_dispatch(_USFSTL_ASSERT_, __VA_ARGS__)(#cond, cond, ##__VA_ARGS__)
69
70 #define _USFSTL_ASSERT_CMP_0(as, a, op, bs, b, fmt) do { \
71 typeof(a) _a = a; \
72 typeof(b) _b = b; \
73 if (!((_a) op (_b))) \
74 usfstl_abort(__FILE__, __LINE__, as " " #op " " bs, \
75 " " as " = " fmt "\n " bs " = " fmt "\n",\
76 _a, _b); \
77 } while (0)
78
79 #define _USFSTL_ASSERT_CMP_1(as, a, op, bs, b, fmt, prfn) do { \
80 typeof(a) _a = a; \
81 typeof(b) _b = b; \
82 if (!((_a) op (_b))) \
83 usfstl_abort(__FILE__, __LINE__, as " " #op " " bs, \
84 " " as " = " fmt "\n " bs " = " fmt "\n",\
85 prfn(_a), prfn(_b)); \
86 } while (0)
87
88 /*
89 * Assert that two values are equal.
90 *
91 * Note that this is a special case of USFSTL_ASSERT_CMP() below, so the
92 * documentation for that applies.
93 */
94 #define USFSTL_ASSERT_EQ(a, b, fmt, ...) \
95 usfstl_dispatch(_USFSTL_ASSERT_CMP_, __VA_ARGS__)(#a, a, ==, \
96 #b, b, fmt, \
97 ##__VA_ARGS__)
98
99 /*
100 * Assert a comparison is true.
101 *
102 * Given a value, comparison operator and another value it checks that
103 * the comparison is true, and aborts the test (or program, if used
104 * outside a test) otherwise.
105 *
106 * You must pass a format string suitable for printing the values.
107 *
108 * You may additionally pass a formatting macro that evaluates the
109 * data for the format string, e.g.
110 *
111 * #define val_and_addr(x) (x), &(x)
112 * ...
113 * int x = 1, y = 2;
114 * USFSTL_ASSERT_CMP(x, ==, y, "%d (at %p)", val_and_addr)
115 *
116 * Will result in the printout
117 * [...]
118 * x = 1 (at 0xffff1110)
119 * y = 2 (at 0xffff1114)
120 */
121 #define USFSTL_ASSERT_CMP(a, op, b, fmt, ...) \
122 usfstl_dispatch(_USFSTL_ASSERT_CMP_, __VA_ARGS__)(#a, a, op, \
123 #b, b, fmt, \
124 ##__VA_ARGS__)
125
126 #endif // _USFSTL_ASSERT_H_
127