1 #ifndef MICROATF_ATF_C_H_
2 #define MICROATF_ATF_C_H_
3 
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <string.h>
7 
8 #include <unistd.h>
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 /**/
15 
16 #ifdef __cplusplus
17 #define MICROATF_ALIGNAS alignas
18 #else
19 #define MICROATF_ALIGNAS _Alignas
20 #endif
21 #define MICROATF_ATTRIBUTE_UNUSED __attribute__((__unused__))
22 #define MICROATF_ATTRIBUTE_FORMAT_PRINTF(a, b) \
23 	__attribute__((__format__(__printf__, a, b)))
24 #define MICROATF_ATTRIBUTE_NORETURN __attribute__((__noreturn__))
25 
26 /**/
27 
28 struct atf_error;
29 typedef struct atf_error *atf_error_t;
30 
31 /**/
32 
33 struct atf_tc_impl_s_;
34 struct atf_tc_s;
35 typedef struct atf_tc_s atf_tc_t;
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic ignored "-Wpragmas"
38 #pragma GCC diagnostic ignored "-Wpedantic"
39 struct atf_tc_s {
40 	MICROATF_ALIGNAS(8192) char const *name;
41 	void (*head)(atf_tc_t *);
42 	void (*body)(atf_tc_t const *);
43 	struct atf_tc_impl_s_ *impl_;
44 	MICROATF_ALIGNAS(max_align_t) unsigned char impl_space_[];
45 };
46 #pragma GCC diagnostic pop
47 
48 atf_error_t atf_tc_set_md_var(atf_tc_t *tc, /**/
49     char const *key, char const *value, ...);
50 
51 const char *atf_tc_get_md_var(atf_tc_t const *tc, const char *key);
52 const char *atf_tc_get_config_var(atf_tc_t const *tc, const char *key);
53 
54 /**/
55 
56 struct atf_tp_s;
57 typedef struct atf_tp_s atf_tp_t;
58 
59 atf_error_t microatf_tp_add_tc(atf_tp_t *tp, atf_tc_t *tc);
60 
61 /**/
62 
63 MICROATF_ATTRIBUTE_FORMAT_PRINTF(1, 2)
64 void microatf_fail_check(char const *msg, ...);
65 
66 MICROATF_ATTRIBUTE_NORETURN
67 MICROATF_ATTRIBUTE_FORMAT_PRINTF(1, 2)
68 void microatf_fail_require(char const *msg, ...);
69 
70 /**/
71 
72 MICROATF_ATTRIBUTE_FORMAT_PRINTF(1, 2)
73 void atf_tc_expect_timeout(const char *msg, ...);
74 
75 MICROATF_ATTRIBUTE_FORMAT_PRINTF(2, 3)
76 void atf_tc_expect_exit(const int exitcode, const char *msg, ...);
77 
78 MICROATF_ATTRIBUTE_FORMAT_PRINTF(2, 3)
79 void atf_tc_expect_signal(const int signal, const char *msg, ...);
80 
81 MICROATF_ATTRIBUTE_FORMAT_PRINTF(1, 2)
82 void atf_tc_expect_fail(const char *msg, ...);
83 
84 /**/
85 
86 MICROATF_ATTRIBUTE_NORETURN
87 MICROATF_ATTRIBUTE_FORMAT_PRINTF(1, 2)
88 void atf_tc_skip(const char *reason, ...);
89 
90 /**/
91 
92 #pragma GCC diagnostic push
93 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
94 #pragma clang diagnostic push
95 #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
96 
97 #define ATF_REQUIRE_MSG(expression, fmt, ...)                     \
98 	do {                                                      \
99 		if (!(expression)) {                              \
100 			microatf_fail_require("%s:%d: " fmt, /**/ \
101 			    __FILE__, __LINE__, ##__VA_ARGS__);   \
102 		}                                                 \
103 	} while (0)
104 
105 #define ATF_CHECK_MSG(expression, fmt, ...)                     \
106 	do {                                                    \
107 		if (!(expression)) {                            \
108 			microatf_fail_check("%s:%d: " fmt, /**/ \
109 			    __FILE__, __LINE__, ##__VA_ARGS__); \
110 		}                                               \
111 	} while (0)
112 
113 #pragma clang diagnostic pop
114 #pragma GCC diagnostic pop
115 
116 #define ATF_REQUIRE(expression) \
117 	ATF_REQUIRE_MSG((expression), "%s not met", #expression)
118 
119 #define ATF_CHECK(expression) \
120 	ATF_CHECK_MSG((expression), "%s not met", #expression)
121 
122 #define ATF_REQUIRE_EQ(expected, actual) \
123 	ATF_REQUIRE_MSG((expected) == (actual), "%s != %s", #expected, #actual)
124 
125 #define ATF_CHECK_EQ(expected, actual) \
126 	ATF_CHECK_MSG((expected) == (actual), "%s != %s", #expected, #actual)
127 
128 #define ATF_REQUIRE_ERRNO(exp_errno, bool_expr)              \
129 	do {                                                 \
130 		ATF_REQUIRE_MSG((bool_expr),	 /**/        \
131 		    "Expected true value in %s", /**/        \
132 		    #bool_expr);                             \
133 		int ec = errno;                              \
134 		ATF_REQUIRE_MSG(ec == (exp_errno),	/**/ \
135 		    "Expected errno %d, got %d, in %s", /**/ \
136 		    (exp_errno), ec, #bool_expr);            \
137 	} while (0)
138 
139 #define ATF_TC_WITHOUT_HEAD(tc)                                \
140 	static void microatf_tc_##tc##_body(atf_tc_t const *); \
141 	static atf_tc_t microatf_tc_##tc = {                   \
142 		#tc,                                           \
143 		NULL,                                          \
144 		microatf_tc_##tc##_body,                       \
145 		NULL,                                          \
146 	}
147 
148 #define ATF_TC(tc)                                             \
149 	static void microatf_tc_##tc##_head(atf_tc_t *);       \
150 	static void microatf_tc_##tc##_body(atf_tc_t const *); \
151 	static atf_tc_t microatf_tc_##tc = {                   \
152 		#tc,                                           \
153 		microatf_tc_##tc##_head,                       \
154 		microatf_tc_##tc##_body,                       \
155 		NULL,                                          \
156 	}
157 
158 #define ATF_TC_HEAD(tc, tcptr)               \
159 	static void microatf_tc_##tc##_head( \
160 	    atf_tc_t *tcptr MICROATF_ATTRIBUTE_UNUSED)
161 
162 #define ATF_TC_BODY(tc, tcptr)               \
163 	static void microatf_tc_##tc##_body( \
164 	    atf_tc_t const *tcptr MICROATF_ATTRIBUTE_UNUSED)
165 
166 #define ATF_TP_ADD_TCS(tps)                                               \
167 	static atf_error_t microatf_tp_add_tcs(atf_tp_t *);               \
168 	int main(int argc, char **argv)                                   \
169 	{                                                                 \
170 		return microatf_tp_main(argc, argv, microatf_tp_add_tcs); \
171 	}                                                                 \
172 	static atf_error_t microatf_tp_add_tcs(atf_tp_t *tps)
173 
174 #define ATF_TP_ADD_TC(tp, tc)                                               \
175 	do {                                                                \
176 		atf_error_t ec = microatf_tp_add_tc(tp, &microatf_tc_##tc); \
177 		if (atf_is_error(ec)) {                                     \
178 			return ec;                                          \
179 		}                                                           \
180 	} while (0)
181 
182 int microatf_tp_main(int argc, char **argv,
183     atf_error_t (*add_tcs_hook)(atf_tp_t *));
184 
185 atf_error_t atf_no_error(void);
186 bool atf_is_error(atf_error_t const);
187 
188 #ifdef __cplusplus
189 }
190 #endif
191 
192 #endif
193