* Copyright (c) 2015-2024 Cyril Hrubis <chrubis@suse.cz>
* Copyright (c) Linux Test Project, 2021-2024
*/
* DOC: tst_test_macros.h -- helpers for testing syscalls
*/
#ifndef TST_TEST_MACROS_H__
#define TST_TEST_MACROS_H__
#include <stdbool.h>
extern long TST_RET;
extern void *TST_RET_PTR;
extern int TST_ERR;
extern int TST_PASS;
* TEST() - Store syscall retval long and errno.
*
* @SCALL: Tested syscall e.g. write(fd, buf, len).
*
* This macro is a shortcut for storing an errno and a return value. The errno is
* cleared before the syscall is called and saved to a TST_ERR global variable
* right after the call returns. The return value is available in TST_RET
* global variable.
*
* The TST_ERR and TST_RET can be included into tst_res() messages with the
* TST_ERR and TTERRNO and TRERRNO flags.
*
* This macro is also used as a base for all the more specific variants e.g.
* TST_EXP_FAIL().
*/
#define TEST(SCALL) \
do { \
errno = 0; \
TST_RET = SCALL; \
TST_ERR = errno; \
} while (0)
* TESTPTR() - Store syscall retval pointer and errno.
*
* @SCALL: Tested syscall e.g. write(fd, buf, len).
*
* Sets TST_RET_PTR and TST_ERR.
*
* This is the same as TEST() macro the only difference is that the return
* value is a pointer which is stored into TST_RET_PTR instead.
*/
#define TESTPTR(SCALL) \
do { \
errno = 0; \
TST_RET_PTR = (void*)SCALL; \
TST_ERR = errno; \
} while (0)
#define TST_2_(_1, _2, ...) _2
#define TST_FMT_(FMT, _1, ...) FMT, ##__VA_ARGS__
#define TST_MSG_(RES, FMT, SCALL, ...) \
tst_res_(__FILE__, __LINE__, RES, \
TST_FMT_(TST_2_(dummy, ##__VA_ARGS__, SCALL) FMT, __VA_ARGS__))
#define TST_MSGP_(RES, FMT, PAR, SCALL, ...) \
tst_res_(__FILE__, __LINE__, RES, \
TST_FMT_(TST_2_(dummy, ##__VA_ARGS__, SCALL) FMT, __VA_ARGS__), PAR)
#define TST_MSGP2_(RES, FMT, PAR, PAR2, SCALL, ...) \
tst_res_(__FILE__, __LINE__, RES, \
TST_FMT_(TST_2_(dummy, ##__VA_ARGS__, SCALL) FMT, __VA_ARGS__), PAR, PAR2)
#define TST_EXP_POSITIVE__(SCALL, SSCALL, ...) \
do { \
TEST(SCALL); \
\
TST_PASS = 0; \
\
if (TST_RET == -1) { \
TST_MSG_(TFAIL | TTERRNO, " failed", \
SSCALL, ##__VA_ARGS__); \
break; \
} \
\
if (TST_RET < 0) { \
TST_MSGP_(TFAIL | TTERRNO, " invalid retval %ld", \
TST_RET, SSCALL, ##__VA_ARGS__); \
break; \
} \
\
TST_PASS = 1; \
\
} while (0)
#define TST_EXP_POSITIVE_(SCALL, SSCALL, ...) \
({ \
TST_EXP_POSITIVE__(SCALL, SSCALL, ##__VA_ARGS__); \
TST_RET; \
})
* TST_EXP_POSITIVE() - Test syscall, expect return value >= 0.
*
* @SCALL: Tested syscall.
* @...: A printf-like parameters.
*
* This macro calls the SCALL with a TEST() macro and additionaly prints pass
* or fail message. Apart from TST_ERR and TST_RET set by the TEST() macro
* TST_PASS global variable is set as well based on the outcome.
*
* The printf-like parameters can be optionally used to pass a description
* printed by the pass or fail tst_res() calls. If omitted the first parameter
* is converted to a string and used instead.
*/
#define TST_EXP_POSITIVE(SCALL, ...) \
({ \
TST_EXP_POSITIVE__(SCALL, #SCALL, ##__VA_ARGS__); \
\
if (TST_PASS) { \
TST_MSGP_(TPASS, " returned %ld", \
TST_RET, #SCALL, ##__VA_ARGS__); \
} \
\
TST_RET; \
})
* TST_EXP_FD_SILENT() - Test syscall to return a file descriptor, silent variant.
*
* @SCALL: Tested syscall.
* @...: A printf-like parameters.
*
* Unlike TST_EXP_FD() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_FD_SILENT(SCALL, ...) TST_EXP_POSITIVE_(SCALL, #SCALL, ##__VA_ARGS__)
* TST_EXP_FD() - Test syscall to return a file descriptor.
*
* @SCALL: Tested syscall.
* @...: A printf-like parameters.
*
* This is a variant of the TST_EXP_POSSITIVE() for a more specific case that
* the returned value is a file descriptor.
*/
#define TST_EXP_FD(SCALL, ...) \
({ \
TST_EXP_POSITIVE__(SCALL, #SCALL, ##__VA_ARGS__); \
\
if (TST_PASS) \
TST_MSGP_(TPASS, " returned fd %ld", TST_RET, \
#SCALL, ##__VA_ARGS__); \
\
TST_RET; \
})
* TST_EXP_FD_OR_FAIL() - Test syscall to return file descriptor or fail with
* expected errno.
*
* @SCALL: Tested syscall.
* @ERRNO: Expected errno or 0.
* @...: A printf-like parameters.
*
* Expect a file descriptor if errno is 0 otherwise expect a failure with
* expected errno.
*
* Internally it uses TST_EXP_FAIL() and TST_EXP_FD().
*/
#define TST_EXP_FD_OR_FAIL(SCALL, ERRNO, ...) \
({ \
if (ERRNO) \
TST_EXP_FAIL(SCALL, ERRNO, ##__VA_ARGS__); \
else \
TST_EXP_FD(SCALL, ##__VA_ARGS__); \
\
TST_RET; \
})
* TST_EXP_PID_SILENT() - Test syscall to return PID, silent variant.
*
* @SCALL: Tested syscall.
* @...: A printf-like parameters.
*
* Unlike TST_EXP_PID() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_PID_SILENT(SCALL, ...) TST_EXP_POSITIVE_(SCALL, #SCALL, ##__VA_ARGS__)
* TST_EXP_PID() - Test syscall to return PID.
*
* @SCALL: Tested syscall.
* @...: A printf-like parameters.
*
* This is a variant of the TST_EXP_POSSITIVE() for a more specific case that
* the returned value is a pid.
*/
#define TST_EXP_PID(SCALL, ...) \
({ \
TST_EXP_POSITIVE__(SCALL, #SCALL, ##__VA_ARGS__); \
\
if (TST_PASS) \
TST_MSGP_(TPASS, " returned pid %ld", TST_RET, \
#SCALL, ##__VA_ARGS__); \
\
TST_RET; \
})
#define TST_EXP_VAL_SILENT_(SCALL, VAL, SSCALL, ...) \
do { \
TEST(SCALL); \
\
TST_PASS = 0; \
\
if (TST_RET != VAL) { \
TST_MSGP2_(TFAIL | TTERRNO, " retval %ld != %ld", \
TST_RET, (long)VAL, SSCALL, ##__VA_ARGS__); \
break; \
} \
\
TST_PASS = 1; \
\
} while (0)
* TST_EXP_VAL_SILENT() - Test syscall to return specified value, silent variant.
*
* @SCALL: Tested syscall.
* @VAL: Expected return value.
* @...: A printf-like parameters.
*
* Unlike TST_EXP_VAL() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_VAL_SILENT(SCALL, VAL, ...) TST_EXP_VAL_SILENT_(SCALL, VAL, #SCALL, ##__VA_ARGS__)
* TST_EXP_VAL() - Test syscall to return specified value.
*
* @SCALL: Tested syscall.
* @VAL: Expected return value.
* @...: A printf-like parameters.
*
* This macro calls the SCALL with a TEST() macro and additionaly prints pass
* or fail message after comparing the returned value againts the expected
* value. Apart from TST_ERR and TST_RET set by the TEST() macro TST_PASS
* global variable is set as well based on the outcome.
*
* The printf-like parameters can be optionally used to pass a description
* printed by the pass or fail tst_res() calls. If omitted the first parameter
* is converted to a string and used instead.
*/
#define TST_EXP_VAL(SCALL, VAL, ...) \
do { \
TST_EXP_VAL_SILENT_(SCALL, VAL, #SCALL, ##__VA_ARGS__); \
\
if (TST_PASS) \
TST_MSG_(TPASS, " passed", #SCALL, ##__VA_ARGS__); \
\
} while(0)
#define TST_EXP_PASS_SILENT_(SCALL, SSCALL, ...) \
do { \
TEST(SCALL); \
\
TST_PASS = 0; \
\
if (TST_RET == -1) { \
TST_MSG_(TFAIL | TTERRNO, " failed", \
SSCALL, ##__VA_ARGS__); \
break; \
} \
\
if (TST_RET != 0) { \
TST_MSGP_(TFAIL | TTERRNO, " invalid retval %ld", \
TST_RET, SSCALL, ##__VA_ARGS__); \
break; \
} \
\
TST_PASS = 1; \
\
} while (0)
#define TST_EXP_PASS_SILENT_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, ...) \
do { \
TESTPTR(SCALL); \
\
TST_PASS = 0; \
\
if (TST_RET_PTR == FAIL_PTR_VAL) { \
TST_MSG_(TFAIL | TTERRNO, " failed", \
SSCALL, ##__VA_ARGS__); \
break; \
} \
\
if (TST_RET != 0) { \
TST_MSGP_(TFAIL | TTERRNO, " invalid retval %ld", \
TST_RET, SSCALL, ##__VA_ARGS__); \
break; \
} \
\
TST_PASS = 1; \
\
} while (0)
* TST_EXP_PASS_SILENT() - Test syscall to return 0, silent variant.
*
* @SCALL: Tested syscall.
* @...: A printf-like parameters.
*
* Unlike TST_EXP_PASS() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_PASS_SILENT(SCALL, ...) TST_EXP_PASS_SILENT_(SCALL, #SCALL, ##__VA_ARGS__)
* TST_EXP_PASS() - Test syscall to return 0.
*
* @SCALL: Tested syscall.
* @...: A printf-like parameters.
*
* This macro calls the SCALL with a TEST() macro and additionaly prints pass
* or fail message after checking the return value againts zero. Apart from
* TST_ERR and TST_RET set by the TEST() macro TST_PASS global variable is set
* as well based on the outcome.
*
* The printf-like parameters can be optionally used to pass a description
* printed by the pass or fail tst_res() calls. If omitted the first parameter
* is converted to a string and used instead.
*/
#define TST_EXP_PASS(SCALL, ...) \
do { \
TST_EXP_PASS_SILENT_(SCALL, #SCALL, ##__VA_ARGS__); \
\
if (TST_PASS) \
TST_MSG_(TPASS, " passed", #SCALL, ##__VA_ARGS__); \
} while (0) \
#define TST_EXP_PASS_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, ...) \
do { \
TST_EXP_PASS_SILENT_PTR_(SCALL, SSCALL, \
FAIL_PTR_VAL, ##__VA_ARGS__); \
\
if (TST_PASS) \
TST_MSG_(TPASS, " passed", #SCALL, ##__VA_ARGS__); \
} while (0)
* TST_EXP_PASS_PTR_VOID() - Test syscall to return a valid pointer.
*
* @SCALL: Tested syscall.
* @...: A printf-like parameters.
*
* This macro calls the SCALL with a TESTPTR() macro and additionaly prints
* pass or fail message after checking the return value against (void *)-1.
* Apart from TST_ERR and TST_RET_PTR set by the TESTPTR() macro TST_PASS
* global variable is set as well based on the outcome.
*
* The printf-like parameters can be optionally used to pass a description
* printed by the pass or fail tst_res() calls. If omitted the first parameter
* is converted to a string and used instead.
*/
#define TST_EXP_PASS_PTR_VOID(SCALL, ...) \
TST_EXP_PASS_PTR_(SCALL, #SCALL, (void *)-1, ##__VA_ARGS__);
* Returns true if err is in the exp_err array.
*/
bool tst_errno_in_set(int err, const int *exp_errs, int exp_errs_cnt);
* Fills in the buf with the errno names in the exp_err set. The buf must be at
* least 20 * exp_errs_cnt bytes long.
*/
const char *tst_errno_names(char *buf, const int *exp_errs, int exp_errs_cnt);
#define TST_EXP_FAIL_SILENT_(PASS_COND, SCALL, SSCALL, ERRNOS, ERRNOS_CNT, ...)\
do { \
TEST(SCALL); \
\
TST_PASS = 0; \
\
if (PASS_COND) { \
TST_MSG_(TFAIL, " succeeded", SSCALL, ##__VA_ARGS__); \
break; \
} \
\
if (TST_RET != -1) { \
TST_MSGP_(TFAIL | TTERRNO, " invalid retval %ld", \
TST_RET, SSCALL, ##__VA_ARGS__); \
break; \
} \
\
if (tst_errno_in_set(TST_ERR, ERRNOS, ERRNOS_CNT)) { \
TST_PASS = 1; \
} else { \
char tst_str_buf__[ERRNOS_CNT * 20]; \
TST_MSGP_(TFAIL | TTERRNO, " expected %s", \
tst_errno_names(tst_str_buf__, \
ERRNOS, ERRNOS_CNT), \
SSCALL, ##__VA_ARGS__); \
} \
} while (0)
#define TST_EXP_FAIL_SILENT_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, \
ERRNOS, ERRNOS_CNT, ...) \
do { \
TESTPTR(SCALL); \
\
TST_PASS = 0; \
\
if (TST_RET_PTR != FAIL_PTR_VAL) { \
TST_MSG_(TFAIL, " succeeded", SSCALL, ##__VA_ARGS__); \
break; \
} \
\
if (!tst_errno_in_set(TST_ERR, ERRNOS, ERRNOS_CNT)) { \
char tst_str_buf__[ERRNOS_CNT * 20]; \
TST_MSGP_(TFAIL | TTERRNO, " expected %s", \
tst_errno_names(tst_str_buf__, \
ERRNOS, ERRNOS_CNT), \
SSCALL, ##__VA_ARGS__); \
break; \
} \
\
TST_PASS = 1; \
\
} while (0)
#define TST_EXP_FAIL_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, \
ERRNOS, ERRNOS_CNT, ...) \
do { \
TST_EXP_FAIL_SILENT_PTR_(SCALL, SSCALL, FAIL_PTR_VAL, \
ERRNOS, ERRNOS_CNT, ##__VA_ARGS__); \
if (TST_PASS) \
TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \
} while (0)
#define TST_EXP_FAIL_ARR_(SCALL, SSCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \
do { \
TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, SSCALL, \
EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \
if (TST_PASS) \
TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \
} while (0)
* TST_EXP_FAIL() - Test syscall to fail with expected errno.
*
* @SCALL: Tested syscall.
* @EXP_ERR: Expected errno.
* @...: A printf-like parameters.
*
* This macro calls the SCALL with a TEST() macro and additionaly prints pass
* or fail message. The check passes if syscall has returned -1 and failed with
* the specified errno.
*
* The SCALL is supposed to return zero on success. For syscalls that return
* positive number on success TST_EXP_FAIL2() has to be used instead.
*
* Apart from TST_ERR and TST_RET set by the TEST() macro TST_PASS global
* variable is set as well based on the outcome.
*
* The printf-like parameters can be optionally used to pass a description
* printed by the pass or fail tst_res() calls. If omitted the first parameter
* is converted to a string and used instead.
*/
#define TST_EXP_FAIL(SCALL, EXP_ERR, ...) \
do { \
int tst_exp_err__ = EXP_ERR; \
TST_EXP_FAIL_ARR_(SCALL, #SCALL, &tst_exp_err__, 1, \
##__VA_ARGS__); \
} while (0)
* TST_EXP_FAIL_ARR() - Test syscall to fail with expected errnos.
*
* @SCALL: Tested syscall.
* @EXP_ERRS: Array of expected errnos.
* @EXP_ERRS_CNT: Lenght of EXP_ERRS.
* @...: A printf-like parameters.
*
* This is a variant of TST_EXP_FAIL() with an array of possible errors.
*/
#define TST_EXP_FAIL_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \
TST_EXP_FAIL_ARR_(SCALL, #SCALL, EXP_ERRS, \
EXP_ERRS_CNT, ##__VA_ARGS__);
#define TST_EXP_FAIL2_ARR_(SCALL, SSCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \
do { \
TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, SSCALL, \
EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__); \
if (TST_PASS) \
TST_MSG_(TPASS | TTERRNO, " ", SSCALL, ##__VA_ARGS__); \
} while (0)
* TST_EXP_FAIL2_ARR() - Test syscall to fail with expected errnos.
*
* @SCALL: Tested syscall.
* @EXP_ERRS: Array of expected errnos.
* @EXP_ERRS_CNT: Lenght of EXP_ERRS.
* @...: A printf-like parameters.
*
* This is a variant of TST_EXP_FAIL2() with an array of possible errors.
*/
#define TST_EXP_FAIL2_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \
TST_EXP_FAIL2_ARR_(SCALL, #SCALL, EXP_ERRS, \
EXP_ERRS_CNT, ##__VA_ARGS__);
* TST_EXP_FAIL_PTR_NULL() - Test syscall to fail with expected errno and return a NULL pointer.
*
* @SCALL: Tested syscall.
* @EXP_ERR: Expected errno.
* @...: A printf-like parameters.
*
* This macro calls the SCALL with a TESTPTR() macro and additionaly prints
* pass or fail message after checking the return value against NULL and errno.
*
* Apart from TST_ERR and TST_RET_PTR set by the TESTPTR() macro TST_PASS
* global variable is set as well based on the outcome.
*
* The printf-like parameters can be optionally used to pass a description
* printed by the pass or fail tst_res() calls. If omitted the first parameter
* is converted to a string and used instead.
*/
#define TST_EXP_FAIL_PTR_NULL(SCALL, EXP_ERR, ...) \
do { \
int tst_exp_err__ = EXP_ERR; \
TST_EXP_FAIL_PTR_(SCALL, #SCALL, NULL, \
&tst_exp_err__, 1, ##__VA_ARGS__); \
} while (0)
* TST_EXP_FAIL_PTR_NULL_ARR() - Test syscall to fail with expected errnos and return a NULL pointer.
*
* @SCALL: Tested syscall.
* @EXP_ERRS: Array of expected errnos.
* @EXP_ERRS_CNT: Lenght of EXP_ERRS.
* @...: A printf-like parameters.
*
* This is a variant of TST_EXP_FAIL_PTR_NULL() with an array of possible
* errors.
*/
#define TST_EXP_FAIL_PTR_NULL_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \
TST_EXP_FAIL_PTR_(SCALL, #SCALL, NULL, \
EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__);
* TST_EXP_FAIL_PTR_VOID() - Test syscall to fail with expected errno and return a (void *)-1 pointer.
*
* @SCALL: Tested syscall.
* @EXP_ERR: Expected errno.
* @...: A printf-like parameters.
*
* This macro calls the SCALL with a TESTPTR() macro and additionaly prints
* pass or fail message after checking the return value against (void *)-1 and
* errno.
*
* Apart from TST_ERR and TST_RET_PTR set by the TESTPTR() macro TST_PASS
* global variable is set as well based on the outcome.
*
* The printf-like parameters can be optionally used to pass a description
* printed by the pass or fail tst_res() calls. If omitted the first parameter
* is converted to a string and used instead.
*/
#define TST_EXP_FAIL_PTR_VOID(SCALL, EXP_ERR, ...) \
do { \
int tst_exp_err__ = EXP_ERR; \
TST_EXP_FAIL_PTR_(SCALL, #SCALL, (void *)-1, \
&tst_exp_err__, 1, ##__VA_ARGS__); \
} while (0)
* TST_EXP_FAIL_PTR_VOID_ARR() - Test syscall to fail with expected errnos and return a (void *)-1 pointer.
*
* @SCALL: Tested syscall.
* @EXP_ERRS: Array of expected errnos.
* @EXP_ERRS_CNT: Lenght of EXP_ERRS.
* @...: A printf-like parameters.
*
* This is a variant of TST_EXP_FAIL_PTR_VOID() with an array of possible
* errors.
*/
#define TST_EXP_FAIL_PTR_VOID_ARR(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...) \
TST_EXP_FAIL_PTR_(SCALL, #SCALL, (void *)-1, \
EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__);
* TST_EXP_FAIL2() - Test syscall to fail with expected errno.
*
* @SCALL: Tested syscall.
* @EXP_ERR: Expected errno.
* @...: A printf-like parameters.
*
* This macro calls the SCALL with a TEST() macro and additionaly prints pass
* or fail message. The check passes if syscall has returned -1 and failed with
* the specified errno.
*
* The SCALL is supposed to return possitive number on success e.g. pid or file
* descriptor. For syscalls that return zero on success TST_EXP_FAIL() has to
* be used instead.
*
* Apart from TST_ERR and TST_RET set by the TEST() macro TST_PASS global
* variable is set as well based on the outcome.
*
* The printf-like parameters can be optionally used to pass a description
* printed by the pass or fail tst_res() calls. If omitted the first parameter
* is converted to a string and used instead.
*/
#define TST_EXP_FAIL2(SCALL, EXP_ERR, ...) \
do { \
int tst_exp_err__ = EXP_ERR; \
TST_EXP_FAIL2_ARR_(SCALL, #SCALL, &tst_exp_err__, 1, \
##__VA_ARGS__); \
} while (0)
* TST_EXP_FAIL_SILENT() - Test syscall to fail with expected errno, silent variant.
*
* @SCALL: Tested syscall.
* @EXP_ERR: Expected errno.
* @...: A printf-like parameters.
*
* Unlike TST_EXP_FAIL() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_FAIL_SILENT(SCALL, EXP_ERR, ...) \
do { \
int tst_exp_err__ = EXP_ERR; \
TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, #SCALL, \
&tst_exp_err__, 1, ##__VA_ARGS__); \
} while (0)
* TST_EXP_FAIL2_SILENT() - Test syscall to fail with expected errno, silent variant.
*
* @SCALL: Tested syscall.
* @EXP_ERR: Expected errno.
* @...: A printf-like parameters.
*
* Unlike TST_EXP_FAIL2() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_FAIL2_SILENT(SCALL, EXP_ERR, ...) \
do { \
int tst_exp_err__ = EXP_ERR; \
TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, #SCALL, \
&tst_exp_err__, 1, ##__VA_ARGS__); \
} while (0)
* TST_EXP_EXPR() - Check for expected expression.
*
* @EXPR: Expression to be tested.
* @...: A printf-like parameters.
*
* Reports a pass if expression evaluates to non-zero and a fail otherwise.
*
* The printf-like parameters can be optionally used to pass a description
* printed by the pass or fail tst_res() calls. If omitted the expression
* is converted to a string and used instead.
*/
#define TST_EXP_EXPR(EXPR, ...) \
tst_res_(__FILE__, __LINE__, (EXPR) ? TPASS : TFAIL, "Expect: " \
TST_FMT_(TST_2_(dummy, ##__VA_ARGS__, #EXPR), __VA_ARGS__));
#define TST_EXP_EQ_SILENT_(VAL_A, SVAL_A, VAL_B, SVAL_B, TYPE, PFS) do { \
TYPE tst_tmp_a__ = VAL_A; \
TYPE tst_tmp_b__ = VAL_B; \
\
TST_PASS = 0; \
\
if (tst_tmp_a__ != tst_tmp_b__) { \
tst_res_(__FILE__, __LINE__, TFAIL, \
SVAL_A " (" PFS ") != " SVAL_B " (" PFS ")", \
tst_tmp_a__, tst_tmp_b__); \
} else { \
TST_PASS = 1; \
} \
} while (0)
* TST_EXP_EQ_LI() - Compare two long long values.
*
* @VAL_A: long long value A.
* @VAL_B: long long value B.
*
* Reports a pass if values are equal and a fail otherwise.
*/
#define TST_EXP_EQ_LI(VAL_A, VAL_B) do { \
TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, long long, "%lli"); \
\
if (TST_PASS) { \
tst_res_(__FILE__, __LINE__, TPASS, \
#VAL_A " == " #VAL_B " (%lli)", \
(long long)VAL_A); \
} \
} while (0)
* TST_EXP_EQ_LI_SILENT() - Compare two long long values, silent variant.
*
* @VAL_A: long long value A.
* @VAL_B: long long value B.
*
* Unlike TST_EXP_EQ_LI() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_EQ_LI_SILENT(VAL_A, VAL_B) \
TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, long long, "%lli")
* TST_EXP_EQ_LU() - Compare two unsigned long long values.
*
* @VAL_A: unsigned long long value A.
* @VAL_B: unsigned long long value B.
*
* Reports a pass if values are equal and a fail otherwise.
*/
#define TST_EXP_EQ_LU(VAL_A, VAL_B) do { \
TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, unsigned long long, "%llu"); \
\
if (TST_PASS) { \
tst_res_(__FILE__, __LINE__, TPASS, \
#VAL_A " == " #VAL_B " (%llu)", \
(unsigned long long)VAL_A); \
} \
} while (0)
* TST_EXP_EQ_LU_SILENT() - Compare two unsigned long long values, silent variant.
*
* @VAL_A: unsigned long long value A.
* @VAL_B: unsigned long long value B.
*
* Unlike TST_EXP_EQ_LU() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_EQ_LU_SILENT(VAL_A, VAL_B) \
TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, unsigned long long, "%llu")
* TST_EXP_EQ_SZ() - Compare two unsigned size_t values.
*
* @VAL_A: unsigned long long value A.
* @VAL_B: unsigned long long value B.
*
* Reports a pass if values are equal and a fail otherwise.
*/
#define TST_EXP_EQ_SZ(VAL_A, VAL_B) do { \
TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, size_t, "%zu"); \
\
if (TST_PASS) { \
tst_res_(__FILE__, __LINE__, TPASS, \
#VAL_A " == " #VAL_B " (%zu)", \
(size_t)VAL_A); \
} \
} while (0)
* TST_EXP_EQ_SZ_SILENT() - Compare two unsigned size_t values, silent variant.
*
* @VAL_A: unsigned long long value A.
* @VAL_B: unsigned long long value B.
*
* Unlike TST_EXP_EQ_SZ() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_EQ_SZ_SILENT(VAL_A, VAL_B) \
TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, size_t, "%zu")
* TST_EXP_EQ_SSZ() - Compare two unsigned ssize_t values.
*
* @VAL_A: unsigned long long value A.
* @VAL_B: unsigned long long value B.
*
* Reports a pass if values are equal and a fail otherwise.
*/
#define TST_EXP_EQ_SSZ(VAL_A, VAL_B) do { \
TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, size_t, "%zi"); \
\
if (TST_PASS) { \
tst_res_(__FILE__, __LINE__, TPASS, \
#VAL_A " == " #VAL_B " (%zi)", \
(ssize_t)VAL_A); \
} \
} while (0)
* TST_EXP_EQ_SSZ_SILENT() - Compare two unsigned ssize_t values, silent variant.
*
* @VAL_A: unsigned long long value A.
* @VAL_B: unsigned long long value B.
*
* Unlike TST_EXP_EQ_SSZ() does not print :c:enum:`TPASS <tst_res_flags>` on
* success, only prints :c:enum:`TFAIL <tst_res_flags>` on failure.
*/
#define TST_EXP_EQ_SSZ_SILENT(VAL_A, VAL_B) \
TST_EXP_EQ_SILENT_(VAL_A, #VAL_A, VAL_B, #VAL_B, ssize_t, "%zi")
* TST_EXP_EQ_STR() - Compare two strings.
*
* @STR_A: string to compare.
* @STR_B: string to compare.
*
* Reports a pass if strings are equal and a fail otherwise.
*/
#define TST_EXP_EQ_STR(STR_A, STR_B) do { \
TST_PASS = strcmp(STR_A, STR_B) == 0; \
\
if (TST_PASS) { \
tst_res_(__FILE__, __LINE__, TPASS, \
"%s == %s (%s)", \
#STR_A, #STR_B, STR_B); \
} else { \
tst_res_(__FILE__, __LINE__, TFAIL, \
"%s (%s) != %s (%s)", \
#STR_A, STR_A, #STR_B, STR_B); \
} \
} while (0)
* TST_EXP_EQ_STRN() - Compare two strings, providing length as well.
*
* @STR_A: string to compare.
* @STR_B: string to compare.
* @LEN: length of the string.
*
* Reports a pass if first LEN bytes of strings are equal and a fail otherwise.
*/
#define TST_EXP_EQ_STRN(STR_A, STR_B, LEN) do { \
char str_a_cpy[LEN+1]; \
\
strncpy(str_a_cpy, STR_A, LEN); \
str_a_cpy[LEN] = 0; \
\
TST_PASS = strncmp(STR_A, STR_B, LEN) == 0; \
\
if (TST_PASS) { \
tst_res_(__FILE__, __LINE__, TPASS, \
"%s == %s (%s)", \
#STR_A, #STR_B, str_a_cpy); \
} else { \
char str_b_cpy[LEN+1]; \
\
strncpy(str_b_cpy, STR_B, LEN); \
str_b_cpy[LEN] = 0; \
\
tst_res_(__FILE__, __LINE__, TFAIL, \
"%s (%s) != %s (%s)", \
#STR_A, str_a_cpy, #STR_B, str_b_cpy); \
} \
} while (0)
#endif