1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2015-2024 Cyril Hrubis <[email protected]> 4 * Copyright (c) Linux Test Project, 2021-2022 5 */ 6 7 #ifndef TST_TEST_MACROS_H__ 8 #define TST_TEST_MACROS_H__ 9 10 #include <stdbool.h> 11 12 #define TEST(SCALL) \ 13 do { \ 14 errno = 0; \ 15 TST_RET = SCALL; \ 16 TST_ERR = errno; \ 17 } while (0) 18 19 #define TEST_VOID(SCALL) \ 20 do { \ 21 errno = 0; \ 22 SCALL; \ 23 TST_ERR = errno; \ 24 } while (0) 25 26 extern long TST_RET; 27 extern int TST_ERR; 28 extern int TST_PASS; 29 30 extern void *TST_RET_PTR; 31 32 #define TESTPTR(SCALL) \ 33 do { \ 34 errno = 0; \ 35 TST_RET_PTR = (void*)SCALL; \ 36 TST_ERR = errno; \ 37 } while (0) 38 39 40 #define TST_2_(_1, _2, ...) _2 41 42 #define TST_FMT_(FMT, _1, ...) FMT, ##__VA_ARGS__ 43 44 #define TST_MSG_(RES, FMT, SCALL, ...) \ 45 tst_res_(__FILE__, __LINE__, RES, \ 46 TST_FMT_(TST_2_(dummy, ##__VA_ARGS__, SCALL) FMT, __VA_ARGS__)) 47 48 #define TST_MSGP_(RES, FMT, PAR, SCALL, ...) \ 49 tst_res_(__FILE__, __LINE__, RES, \ 50 TST_FMT_(TST_2_(dummy, ##__VA_ARGS__, SCALL) FMT, __VA_ARGS__), PAR) 51 52 #define TST_MSGP2_(RES, FMT, PAR, PAR2, SCALL, ...) \ 53 tst_res_(__FILE__, __LINE__, RES, \ 54 TST_FMT_(TST_2_(dummy, ##__VA_ARGS__, SCALL) FMT, __VA_ARGS__), PAR, PAR2) 55 56 #define TST_EXP_POSITIVE__(SCALL, SSCALL, ...) \ 57 do { \ 58 TEST(SCALL); \ 59 \ 60 TST_PASS = 0; \ 61 \ 62 if (TST_RET == -1) { \ 63 TST_MSG_(TFAIL | TTERRNO, " failed", \ 64 SSCALL, ##__VA_ARGS__); \ 65 break; \ 66 } \ 67 \ 68 if (TST_RET < 0) { \ 69 TST_MSGP_(TFAIL | TTERRNO, " invalid retval %ld", \ 70 TST_RET, SSCALL, ##__VA_ARGS__); \ 71 break; \ 72 } \ 73 \ 74 TST_PASS = 1; \ 75 \ 76 } while (0) 77 78 #define TST_EXP_POSITIVE_(SCALL, SSCALL, ...) \ 79 ({ \ 80 TST_EXP_POSITIVE__(SCALL, SSCALL, ##__VA_ARGS__); \ 81 TST_RET; \ 82 }) 83 84 #define TST_EXP_POSITIVE(SCALL, ...) \ 85 ({ \ 86 TST_EXP_POSITIVE__(SCALL, #SCALL, ##__VA_ARGS__); \ 87 \ 88 if (TST_PASS) { \ 89 TST_MSGP_(TPASS, " returned %ld", \ 90 TST_RET, #SCALL, ##__VA_ARGS__); \ 91 } \ 92 \ 93 TST_RET; \ 94 }) 95 96 #define TST_EXP_FD_SILENT(SCALL, ...) TST_EXP_POSITIVE_(SCALL, #SCALL, ##__VA_ARGS__) 97 98 #define TST_EXP_FD(SCALL, ...) \ 99 ({ \ 100 TST_EXP_POSITIVE__(SCALL, #SCALL, ##__VA_ARGS__); \ 101 \ 102 if (TST_PASS) \ 103 TST_MSGP_(TPASS, " returned fd %ld", TST_RET, \ 104 #SCALL, ##__VA_ARGS__); \ 105 \ 106 TST_RET; \ 107 }) 108 109 #define TST_EXP_FD_OR_FAIL(SCALL, ERRNO, ...) \ 110 ({ \ 111 if (ERRNO) \ 112 TST_EXP_FAIL(SCALL, ERRNO, ##__VA_ARGS__); \ 113 else \ 114 TST_EXP_FD(SCALL, ##__VA_ARGS__); \ 115 \ 116 TST_RET; \ 117 }) 118 119 #define TST_EXP_PID_SILENT(SCALL, ...) TST_EXP_POSITIVE_(SCALL, #SCALL, ##__VA_ARGS__) 120 121 #define TST_EXP_PID(SCALL, ...) \ 122 ({ \ 123 TST_EXP_POSITIVE__(SCALL, #SCALL, ##__VA_ARGS__); \ 124 \ 125 if (TST_PASS) \ 126 TST_MSGP_(TPASS, " returned pid %ld", TST_RET, \ 127 #SCALL, ##__VA_ARGS__); \ 128 \ 129 TST_RET; \ 130 }) 131 132 #define TST_EXP_VAL_SILENT_(SCALL, VAL, SSCALL, ...) \ 133 do { \ 134 TEST(SCALL); \ 135 \ 136 TST_PASS = 0; \ 137 \ 138 if (TST_RET != VAL) { \ 139 TST_MSGP2_(TFAIL | TTERRNO, " retval %ld != %ld", \ 140 TST_RET, (long)VAL, SSCALL, ##__VA_ARGS__); \ 141 break; \ 142 } \ 143 \ 144 TST_PASS = 1; \ 145 \ 146 } while (0) 147 148 #define TST_EXP_VAL_SILENT(SCALL, VAL, ...) TST_EXP_VAL_SILENT_(SCALL, VAL, #SCALL, ##__VA_ARGS__) 149 150 #define TST_EXP_VAL(SCALL, VAL, ...) \ 151 do { \ 152 TST_EXP_VAL_SILENT_(SCALL, VAL, #SCALL, ##__VA_ARGS__); \ 153 \ 154 if (TST_PASS) \ 155 TST_MSG_(TPASS, " passed", #SCALL, ##__VA_ARGS__); \ 156 \ 157 } while(0) 158 159 #define TST_EXP_PASS_SILENT_(SCALL, SSCALL, ...) \ 160 do { \ 161 TEST(SCALL); \ 162 \ 163 TST_PASS = 0; \ 164 \ 165 if (TST_RET == -1) { \ 166 TST_MSG_(TFAIL | TTERRNO, " failed", \ 167 SSCALL, ##__VA_ARGS__); \ 168 break; \ 169 } \ 170 \ 171 if (TST_RET != 0) { \ 172 TST_MSGP_(TFAIL | TTERRNO, " invalid retval %ld", \ 173 TST_RET, SSCALL, ##__VA_ARGS__); \ 174 break; \ 175 } \ 176 \ 177 TST_PASS = 1; \ 178 \ 179 } while (0) 180 181 #define TST_EXP_PASS_SILENT(SCALL, ...) TST_EXP_PASS_SILENT_(SCALL, #SCALL, ##__VA_ARGS__) 182 183 #define TST_EXP_PASS(SCALL, ...) \ 184 do { \ 185 TST_EXP_PASS_SILENT_(SCALL, #SCALL, ##__VA_ARGS__); \ 186 \ 187 if (TST_PASS) \ 188 TST_MSG_(TPASS, " passed", #SCALL, ##__VA_ARGS__); \ 189 } while (0) \ 190 191 /* 192 * Returns true if err is in the exp_err array. 193 */ 194 bool tst_errno_in_set(int err, const int *exp_errs, int exp_errs_cnt); 195 196 /* 197 * Fills in the buf with the errno names in the exp_err set. The buf must be at 198 * least 20 * exp_errs_cnt bytes long. 199 */ 200 const char *tst_errno_names(char *buf, const int *exp_errs, int exp_errs_cnt); 201 202 #define TST_EXP_FAIL_SILENT_(PASS_COND, SCALL, SSCALL, ERRNOS, ERRNOS_CNT, ...)\ 203 do { \ 204 TEST(SCALL); \ 205 \ 206 TST_PASS = 0; \ 207 \ 208 if (PASS_COND) { \ 209 TST_MSG_(TFAIL, " succeeded", SSCALL, ##__VA_ARGS__); \ 210 break; \ 211 } \ 212 \ 213 if (TST_RET != -1) { \ 214 TST_MSGP_(TFAIL | TTERRNO, " invalid retval %ld", \ 215 TST_RET, SSCALL, ##__VA_ARGS__); \ 216 break; \ 217 } \ 218 \ 219 if (tst_errno_in_set(TST_ERR, ERRNOS, ERRNOS_CNT)) { \ 220 TST_PASS = 1; \ 221 } else { \ 222 char tst_str_buf__[ERRNOS_CNT * 20]; \ 223 TST_MSGP_(TFAIL | TTERRNO, " expected %s", \ 224 tst_errno_names(tst_str_buf__, \ 225 ERRNOS, ERRNOS_CNT), \ 226 SSCALL, ##__VA_ARGS__); \ 227 } \ 228 } while (0) 229 230 #define TST_EXP_FAIL_SILENT_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, \ 231 ERRNOS, ERRNOS_CNT, ...) \ 232 do { \ 233 TESTPTR(SCALL); \ 234 \ 235 TST_PASS = 0; \ 236 \ 237 if (TST_RET_PTR != FAIL_PTR_VAL) { \ 238 TST_MSG_(TFAIL, " succeeded", SSCALL, ##__VA_ARGS__); \ 239 break; \ 240 } \ 241 \ 242 if (!tst_errno_in_set(TST_ERR, ERRNOS, ERRNOS_CNT)) { \ 243 char tst_str_buf__[ERRNOS_CNT * 20]; \ 244 TST_MSGP_(TFAIL | TTERRNO, " expected %s", \ 245 tst_errno_names(tst_str_buf__, \ 246 ERRNOS, ERRNOS_CNT), \ 247 SSCALL, ##__VA_ARGS__); \ 248 break; \ 249 } \ 250 \ 251 TST_PASS = 1; \ 252 \ 253 } while (0) 254 255 #define TST_EXP_FAIL_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, \ 256 ERRNOS, ERRNOS_CNT, ...) \ 257 do { \ 258 TST_EXP_FAIL_SILENT_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, \ 259 ERRNOS, ERRNOS_CNT, ##__VA_ARGS__); \ 260 if (TST_PASS) \ 261 TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \ 262 } while (0) 263 264 265 #define TST_EXP_FAIL_ARR_(SCALL, SSCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 266 do { \ 267 TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, SSCALL, \ 268 EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \ 269 if (TST_PASS) \ 270 TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \ 271 } while (0) 272 273 #define TST_EXP_FAIL(SCALL, EXP_ERR, ...) \ 274 do { \ 275 int tst_exp_err__ = EXP_ERR; \ 276 TST_EXP_FAIL_ARR_(SCALL, #SCALL, &tst_exp_err__, 1, \ 277 ##__VA_ARGS__); \ 278 } while (0) 279 280 #define TST_EXP_FAIL_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 281 TST_EXP_FAIL_ARR_(SCALL, #SCALL, EXP_ERRS, \ 282 EXP_ERRS_CNT, ##__VA_ARGS__); 283 284 #define TST_EXP_FAIL2_ARR_(SCALL, SSCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 285 do { \ 286 TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, SSCALL, \ 287 EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \ 288 if (TST_PASS) \ 289 TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \ 290 } while (0) 291 292 #define TST_EXP_FAIL2_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 293 TST_EXP_FAIL2_ARR_(SCALL, #SCALL, EXP_ERRS, \ 294 EXP_ERRS_CNT, ##__VA_ARGS__); 295 296 #define TST_EXP_FAIL_PTR_NULL(SCALL, EXP_ERR, ...) \ 297 do { \ 298 int tst_exp_err__ = EXP_ERR; \ 299 TST_EXP_FAIL_PTR_(SCALL, #SCALL, NULL, \ 300 &tst_exp_err__, 1, ##__VA_ARGS__); \ 301 } while (0) 302 303 #define TST_EXP_FAIL_PTR_NULL_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 304 do { \ 305 TST_EXP_FAIL_PTR_(SCALL, #SCALL, NULL, \ 306 EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \ 307 } while (0) 308 309 #define TST_EXP_FAIL_PTR_VOID(SCALL, EXP_ERR, ...) \ 310 do { \ 311 int tst_exp_err__ = EXP_ERR; \ 312 TST_EXP_FAIL_PTR_(SCALL, #SCALL, (void *)-1, \ 313 &tst_exp_err__, 1, ##__VA_ARGS__); \ 314 } while (0) 315 316 #define TST_EXP_FAIL_PTR_VOID_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 317 do { \ 318 TST_EXP_FAIL_PTR_(SCALL, #SCALL, (void *)-1, \ 319 EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \ 320 } while (0) 321 322 #define TST_EXP_FAIL2(SCALL, EXP_ERR, ...) \ 323 do { \ 324 int tst_exp_err__ = EXP_ERR; \ 325 TST_EXP_FAIL2_ARR_(SCALL, #SCALL, &tst_exp_err__, 1, \ 326 ##__VA_ARGS__); \ 327 } while (0) 328 329 #define TST_EXP_FAIL_SILENT(SCALL, EXP_ERR, ...) \ 330 do { \ 331 int tst_exp_err__ = EXP_ERR; \ 332 TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, #SCALL, \ 333 &tst_exp_err__, 1, ##__VA_ARGS__); \ 334 } while (0) 335 336 #define TST_EXP_FAIL2_SILENT(SCALL, EXP_ERR, ...) \ 337 do { \ 338 int tst_exp_err__ = EXP_ERR; \ 339 TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, #SCALL, \ 340 &tst_exp_err__, 1, ##__VA_ARGS__); \ 341 } while (0) 342 343 #define TST_EXP_EXPR(EXPR, FMT, ...) \ 344 tst_res_(__FILE__, __LINE__, (EXPR) ? TPASS : TFAIL, "Expect: " FMT, ##__VA_ARGS__); 345 346 #define TST_EXP_EQ_(VAL_A, SVAL_A, VAL_B, SVAL_B, TYPE, PFS) do {\ 347 TYPE tst_tmp_a__ = VAL_A; \ 348 TYPE tst_tmp_b__ = VAL_B; \ 349 if (tst_tmp_a__ == tst_tmp_b__) { \ 350 tst_res_(__FILE__, __LINE__, TPASS, \ 351 SVAL_A " == " SVAL_B " (" PFS ")", tst_tmp_a__); \ 352 } else { \ 353 tst_res_(__FILE__, __LINE__, TFAIL, \ 354 SVAL_A " (" PFS ") != " SVAL_B " (" PFS ")", \ 355 tst_tmp_a__, tst_tmp_b__); \ 356 } \ 357 } while (0) 358 359 #define TST_EXP_EQ_LI(VAL_A, VAL_B) \ 360 TST_EXP_EQ_(VAL_A, #VAL_A, VAL_B, #VAL_B, long long, "%lli") 361 362 #define TST_EXP_EQ_LU(VAL_A, VAL_B) \ 363 TST_EXP_EQ_(VAL_A, #VAL_A, VAL_B, #VAL_B, unsigned long long, "%llu") 364 365 #define TST_EXP_EQ_SZ(VAL_A, VAL_B) \ 366 TST_EXP_EQ_(VAL_A, #VAL_A, VAL_B, #VAL_B, size_t, "%zu") 367 368 #define TST_EXP_EQ_SSZ(VAL_A, VAL_B) \ 369 TST_EXP_EQ_(VAL_A, #VAL_A, VAL_B, #VAL_B, ssize_t, "%zi") 370 371 #endif /* TST_TEST_MACROS_H__ */ 372