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, µatf_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