1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2015-2024 Cyril Hrubis <chrubis@suse.cz> 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_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, ...) \ 182 do { \ 183 TESTPTR(SCALL); \ 184 \ 185 TST_PASS = 0; \ 186 \ 187 if (TST_RET_PTR == FAIL_PTR_VAL) { \ 188 TST_MSG_(TFAIL | TTERRNO, " failed", \ 189 SSCALL, ##__VA_ARGS__); \ 190 break; \ 191 } \ 192 \ 193 if (TST_RET != 0) { \ 194 TST_MSGP_(TFAIL | TTERRNO, " invalid retval %ld", \ 195 TST_RET, SSCALL, ##__VA_ARGS__); \ 196 break; \ 197 } \ 198 \ 199 TST_PASS = 1; \ 200 \ 201 } while (0) 202 203 #define TST_EXP_PASS_SILENT(SCALL, ...) TST_EXP_PASS_SILENT_(SCALL, #SCALL, ##__VA_ARGS__) 204 205 #define TST_EXP_PASS(SCALL, ...) \ 206 do { \ 207 TST_EXP_PASS_SILENT_(SCALL, #SCALL, ##__VA_ARGS__); \ 208 \ 209 if (TST_PASS) \ 210 TST_MSG_(TPASS, " passed", #SCALL, ##__VA_ARGS__); \ 211 } while (0) \ 212 213 #define TST_EXP_PASS_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, ...) \ 214 do { \ 215 TST_EXP_PASS_SILENT_PTR_(SCALL, SSCALL, \ 216 FAIL_PTR_VAL, ##__VA_ARGS__); \ 217 \ 218 if (TST_PASS) \ 219 TST_MSG_(TPASS, " passed", #SCALL, ##__VA_ARGS__); \ 220 } while (0) 221 222 #define TST_EXP_PASS_PTR_VOID(SCALL, ...) \ 223 TST_EXP_PASS_PTR_(SCALL, #SCALL, (void *)-1, ##__VA_ARGS__); 224 225 /* 226 * Returns true if err is in the exp_err array. 227 */ 228 bool tst_errno_in_set(int err, const int *exp_errs, int exp_errs_cnt); 229 230 /* 231 * Fills in the buf with the errno names in the exp_err set. The buf must be at 232 * least 20 * exp_errs_cnt bytes long. 233 */ 234 const char *tst_errno_names(char *buf, const int *exp_errs, int exp_errs_cnt); 235 236 #define TST_EXP_FAIL_SILENT_(PASS_COND, SCALL, SSCALL, ERRNOS, ERRNOS_CNT, ...)\ 237 do { \ 238 TEST(SCALL); \ 239 \ 240 TST_PASS = 0; \ 241 \ 242 if (PASS_COND) { \ 243 TST_MSG_(TFAIL, " succeeded", SSCALL, ##__VA_ARGS__); \ 244 break; \ 245 } \ 246 \ 247 if (TST_RET != -1) { \ 248 TST_MSGP_(TFAIL | TTERRNO, " invalid retval %ld", \ 249 TST_RET, SSCALL, ##__VA_ARGS__); \ 250 break; \ 251 } \ 252 \ 253 if (tst_errno_in_set(TST_ERR, ERRNOS, ERRNOS_CNT)) { \ 254 TST_PASS = 1; \ 255 } else { \ 256 char tst_str_buf__[ERRNOS_CNT * 20]; \ 257 TST_MSGP_(TFAIL | TTERRNO, " expected %s", \ 258 tst_errno_names(tst_str_buf__, \ 259 ERRNOS, ERRNOS_CNT), \ 260 SSCALL, ##__VA_ARGS__); \ 261 } \ 262 } while (0) 263 264 #define TST_EXP_FAIL_SILENT_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, \ 265 ERRNOS, ERRNOS_CNT, ...) \ 266 do { \ 267 TESTPTR(SCALL); \ 268 \ 269 TST_PASS = 0; \ 270 \ 271 if (TST_RET_PTR != FAIL_PTR_VAL) { \ 272 TST_MSG_(TFAIL, " succeeded", SSCALL, ##__VA_ARGS__); \ 273 break; \ 274 } \ 275 \ 276 if (!tst_errno_in_set(TST_ERR, ERRNOS, ERRNOS_CNT)) { \ 277 char tst_str_buf__[ERRNOS_CNT * 20]; \ 278 TST_MSGP_(TFAIL | TTERRNO, " expected %s", \ 279 tst_errno_names(tst_str_buf__, \ 280 ERRNOS, ERRNOS_CNT), \ 281 SSCALL, ##__VA_ARGS__); \ 282 break; \ 283 } \ 284 \ 285 TST_PASS = 1; \ 286 \ 287 } while (0) 288 289 #define TST_EXP_FAIL_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, \ 290 ERRNOS, ERRNOS_CNT, ...) \ 291 do { \ 292 TST_EXP_FAIL_SILENT_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, \ 293 ERRNOS, ERRNOS_CNT, ##__VA_ARGS__); \ 294 if (TST_PASS) \ 295 TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \ 296 } while (0) 297 298 299 #define TST_EXP_FAIL_ARR_(SCALL, SSCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 300 do { \ 301 TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, SSCALL, \ 302 EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \ 303 if (TST_PASS) \ 304 TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \ 305 } while (0) 306 307 #define TST_EXP_FAIL(SCALL, EXP_ERR, ...) \ 308 do { \ 309 int tst_exp_err__ = EXP_ERR; \ 310 TST_EXP_FAIL_ARR_(SCALL, #SCALL, &tst_exp_err__, 1, \ 311 ##__VA_ARGS__); \ 312 } while (0) 313 314 #define TST_EXP_FAIL_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 315 TST_EXP_FAIL_ARR_(SCALL, #SCALL, EXP_ERRS, \ 316 EXP_ERRS_CNT, ##__VA_ARGS__); 317 318 #define TST_EXP_FAIL2_ARR_(SCALL, SSCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 319 do { \ 320 TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, SSCALL, \ 321 EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \ 322 if (TST_PASS) \ 323 TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \ 324 } while (0) 325 326 #define TST_EXP_FAIL2_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 327 TST_EXP_FAIL2_ARR_(SCALL, #SCALL, EXP_ERRS, \ 328 EXP_ERRS_CNT, ##__VA_ARGS__); 329 330 #define TST_EXP_FAIL_PTR_NULL(SCALL, EXP_ERR, ...) \ 331 do { \ 332 int tst_exp_err__ = EXP_ERR; \ 333 TST_EXP_FAIL_PTR_(SCALL, #SCALL, NULL, \ 334 &tst_exp_err__, 1, ##__VA_ARGS__); \ 335 } while (0) 336 337 #define TST_EXP_FAIL_PTR_NULL_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 338 TST_EXP_FAIL_PTR_(SCALL, #SCALL, NULL, \ 339 EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); 340 341 #define TST_EXP_FAIL_PTR_VOID(SCALL, EXP_ERR, ...) \ 342 do { \ 343 int tst_exp_err__ = EXP_ERR; \ 344 TST_EXP_FAIL_PTR_(SCALL, #SCALL, (void *)-1, \ 345 &tst_exp_err__, 1, ##__VA_ARGS__); \ 346 } while (0) 347 348 #define TST_EXP_FAIL_PTR_VOID_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \ 349 TST_EXP_FAIL_PTR_(SCALL, #SCALL, (void *)-1, \ 350 EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); 351 352 #define TST_EXP_FAIL2(SCALL, EXP_ERR, ...) \ 353 do { \ 354 int tst_exp_err__ = EXP_ERR; \ 355 TST_EXP_FAIL2_ARR_(SCALL, #SCALL, &tst_exp_err__, 1, \ 356 ##__VA_ARGS__); \ 357 } while (0) 358 359 #define TST_EXP_FAIL_SILENT(SCALL, EXP_ERR, ...) \ 360 do { \ 361 int tst_exp_err__ = EXP_ERR; \ 362 TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, #SCALL, \ 363 &tst_exp_err__, 1, ##__VA_ARGS__); \ 364 } while (0) 365 366 #define TST_EXP_FAIL2_SILENT(SCALL, EXP_ERR, ...) \ 367 do { \ 368 int tst_exp_err__ = EXP_ERR; \ 369 TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, #SCALL, \ 370 &tst_exp_err__, 1, ##__VA_ARGS__); \ 371 } while (0) 372 373 #define TST_EXP_EXPR(EXPR, ...) \ 374 tst_res_(__FILE__, __LINE__, (EXPR) ? TPASS : TFAIL, "Expect: " \ 375 TST_FMT_(TST_2_(dummy, ##__VA_ARGS__, #EXPR), __VA_ARGS__)); 376 377 #define TST_EXP_EQ_SILENT_(VAL_A, SVAL_A, VAL_B, SVAL_B, TYPE, PFS) do { \ 378 TYPE tst_tmp_a__ = VAL_A; \ 379 TYPE tst_tmp_b__ = VAL_B; \ 380 \ 381 TST_PASS = 0; \ 382 \ 383 if (tst_tmp_a__ != tst_tmp_b__) { \ 384 tst_res_(__FILE__, __LINE__, TFAIL, \ 385 SVAL_A " (" PFS ") != " SVAL_B " (" PFS ")", \ 386 tst_tmp_a__, tst_tmp_b__); \ 387 } else { \ 388 TST_PASS = 1; \ 389 } \ 390 } while (0) 391 392 #define TST_EXP_EQ_LI(VAL_A, VAL_B) do { \ 393 TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, long long, "%lli"); \ 394 \ 395 if (TST_PASS) { \ 396 tst_res_(__FILE__, __LINE__, TPASS, \ 397 #VAL_A " == " #VAL_B " (%lli)", \ 398 (long long)VAL_A); \ 399 } \ 400 } while (0) 401 402 #define TST_EXP_EQ_LI_SILENT(VAL_A, VAL_B) \ 403 TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, long long, "%lli") 404 405 #define TST_EXP_EQ_LU(VAL_A, VAL_B) do { \ 406 TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, unsigned long long, "%llu"); \ 407 \ 408 if (TST_PASS) { \ 409 tst_res_(__FILE__, __LINE__, TPASS, \ 410 #VAL_A " == " #VAL_B " (%llu)", \ 411 (unsigned long long)VAL_A); \ 412 } \ 413 } while (0) 414 415 #define TST_EXP_EQ_LU_SILENT(VAL_A, VAL_B) \ 416 TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, unsigned long long, "%llu") 417 418 #define TST_EXP_EQ_SZ(VAL_A, VAL_B) do { \ 419 TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, size_t, "%zu"); \ 420 \ 421 if (TST_PASS) { \ 422 tst_res_(__FILE__, __LINE__, TPASS, \ 423 #VAL_A " == " #VAL_B " (%zu)", \ 424 (size_t)VAL_A); \ 425 } \ 426 } while (0) 427 428 #define TST_EXP_EQ_SZ_SILENT(VAL_A, VAL_B) \ 429 TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, size_t, "%zu") 430 431 #define TST_EXP_EQ_SSZ(VAL_A, VAL_B) do { \ 432 TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, size_t, "%zi"); \ 433 \ 434 if (TST_PASS) { \ 435 tst_res_(__FILE__, __LINE__, TPASS, \ 436 #VAL_A " == " #VAL_B " (%zi)", \ 437 (ssize_t)VAL_A); \ 438 } \ 439 } while (0) 440 441 #define TST_EXP_EQ_SSZ_SILENT(VAL_A, VAL_B) \ 442 TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, ssize_t, "%zi") 443 444 #define TST_EXP_EQ_STR(STR_A, STR_B) do { \ 445 TST_PASS = strcmp(STR_A, STR_B) == 0; \ 446 \ 447 if (TST_PASS) { \ 448 tst_res_(__FILE__, __LINE__, TPASS, \ 449 "%s == %s (%s)", \ 450 #STR_A, #STR_B, STR_B); \ 451 } else { \ 452 tst_res_(__FILE__, __LINE__, TFAIL, \ 453 "%s (%s) != %s (%s)", \ 454 #STR_A, STR_A, #STR_B, STR_B); \ 455 } \ 456 } while (0) 457 458 /** 459 * TST_EXP_EQ_STRN() - Compare two strings, providing length as well. 460 * 461 * @STR_A: string to compare. 462 * @STR_B: string to compare. 463 * @LEN: length of the string. 464 */ 465 #define TST_EXP_EQ_STRN(STR_A, STR_B, LEN) do { \ 466 char str_a_cpy[LEN+1]; \ 467 \ 468 strncpy(str_a_cpy, STR_A, LEN); \ 469 str_a_cpy[LEN] = 0; \ 470 \ 471 TST_PASS = strncmp(STR_A, STR_B, LEN) == 0; \ 472 \ 473 if (TST_PASS) { \ 474 tst_res_(__FILE__, __LINE__, TPASS, \ 475 "%s == %s (%s)", \ 476 #STR_A, #STR_B, str_a_cpy); \ 477 } else { \ 478 char str_b_cpy[LEN+1]; \ 479 \ 480 strncpy(str_b_cpy, STR_B, LEN); \ 481 str_b_cpy[LEN] = 0; \ 482 \ 483 tst_res_(__FILE__, __LINE__, TFAIL, \ 484 "%s (%s) != %s (%s)", \ 485 #STR_A, str_a_cpy, #STR_B, str_b_cpy); \ 486 } \ 487 } while (0) 488 489 #endif /* TST_TEST_MACROS_H__ */ 490