[LTP] [PATCH] lib: TST_EXP_FAIL: Add array variants

Cyril Hrubis chrubis@suse.cz
Wed Jan 3 12:57:00 CET 2024


For certain cases there is a possibility of a failure with more than one
errno, for instance testcases with invalid fd may return either EINVAL
or EBADFD and in many cases either one is fine, at least that was the
feedback from kernel devs.

This change also adds a tst_errno_in_set() function that is now the
single place to validate errno for all TST_EXP_FAIL*() variants. That is
intentional since this allows us to implement code to relax the
conditions if needed, e.g. we had requests to allow additional errnos
for systems with SELinux where failures may be caused by the SELinux
policies and the errors may differ.

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 include/tst_test_macros.h        | 65 ++++++++++++++++++++++++++------
 lib/newlib_tests/test_macros02.c | 11 ++++++
 lib/tst_test_macros.c            | 36 ++++++++++++++++++
 3 files changed, 101 insertions(+), 11 deletions(-)
 create mode 100644 lib/tst_test_macros.c

diff --git a/include/tst_test_macros.h b/include/tst_test_macros.h
index bd0c491c1..5687d0904 100644
--- a/include/tst_test_macros.h
+++ b/include/tst_test_macros.h
@@ -186,7 +186,18 @@ extern void *TST_RET_PTR;
 			TST_MSG_(TPASS, " passed", #SCALL, ##__VA_ARGS__);     \
 	} while (0)                                                            \
 
-#define TST_EXP_FAIL_SILENT_(PASS_COND, SCALL, SSCALL, ERRNO, ...)             \
+/*
+ * Returns true if err is in the exp_err array.
+ */
+int 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);                                                   \
 		                                                               \
@@ -203,36 +214,68 @@ extern void *TST_RET_PTR;
 			break;                                                 \
 		}                                                              \
 		                                                               \
-		if (TST_ERR == (ERRNO)) {                                      \
+		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_strerrno(ERRNO),                         \
+				  tst_errno_names(tst_str_buf__,               \
+						  ERRNOS, ERRNOS_CNT),         \
 				  SSCALL, ##__VA_ARGS__);                      \
 		}                                                              \
 	} while (0)
 
-#define TST_EXP_FAIL(SCALL, ERRNO, ...)                                        \
+#define TST_EXP_FAIL_ARR_(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...)                  \
 	do {                                                                   \
 		TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, #SCALL,              \
-			ERRNO, ##__VA_ARGS__);                                 \
+			EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__);                \
 		if (TST_PASS)                                                  \
 			TST_MSG_(TPASS | TTERRNO, " ", #SCALL, ##__VA_ARGS__); \
 	} while (0)
 
-#define TST_EXP_FAIL2(SCALL, ERRNO, ...)                                       \
+#define TST_EXP_FAIL(SCALL, EXP_ERR, ...)                                      \
+	do {                                                                   \
+		int tst_exp_err__ = EXP_ERR;                                   \
+		TST_EXP_FAIL_ARR_(SCALL, &tst_exp_err__, 1,                    \
+                                  ##__VA_ARGS__);                              \
+	} while (0)
+
+#define TST_EXP_FAIL_ARR(SCALL, EXP_ERRS, ...)                                 \
+		TST_EXP_FAIL_ARR_(SCALL, EXP_ERRS, ARRAY_SIZE(EXP_ERRS),       \
+                                  ##__VA_ARGS__);                              \
+
+#define TST_EXP_FAIL2_ARR_(SCALL, EXP_ERRS, EXP_ERRS_CNT, ...)                 \
 	do {                                                                   \
 		TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, #SCALL,              \
-			ERRNO, ##__VA_ARGS__);                                 \
+			EXP_ERRS, EXP_ERRS_CNT, ##__VA_ARGS__);                \
 		if (TST_PASS)                                                  \
 			TST_MSG_(TPASS | TTERRNO, " ", #SCALL, ##__VA_ARGS__); \
 	} while (0)
 
-#define TST_EXP_FAIL_SILENT(SCALL, ERRNO, ...) \
-	TST_EXP_FAIL_SILENT_(TST_RET == 0, SCALL, #SCALL, ERRNO, ##__VA_ARGS__)
+#define TST_EXP_FAIL2_ARR(SCALL, EXP_ERRS, ...)                                \
+		TST_EXP_FAIL2_ARR_(SCALL, EXP_ERRS, ARRAY_SIZE(EXP_ERRS),      \
+                                  ##__VA_ARGS__);                              \
 
-#define TST_EXP_FAIL2_SILENT(SCALL, ERRNO, ...) \
-	TST_EXP_FAIL_SILENT_(TST_RET >= 0, SCALL, #SCALL, ERRNO, ##__VA_ARGS__)
+#define TST_EXP_FAIL2(SCALL, EXP_ERR, ...)                                     \
+	do {                                                                   \
+		int tst_exp_err__ = EXP_ERR;                                   \
+		TST_EXP_FAIL2_ARR_(SCALL, &tst_exp_err__, 1,                   \
+                                  ##__VA_ARGS__);                              \
+	} while (0)
+
+#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)
+
+#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)
 
 #define TST_EXP_EXPR(EXPR, FMT, ...)						\
 	tst_res_(__FILE__, __LINE__, (EXPR) ? TPASS : TFAIL, "Expect: " FMT, ##__VA_ARGS__);
diff --git a/lib/newlib_tests/test_macros02.c b/lib/newlib_tests/test_macros02.c
index 647f73682..6c1ca7a8a 100644
--- a/lib/newlib_tests/test_macros02.c
+++ b/lib/newlib_tests/test_macros02.c
@@ -27,6 +27,9 @@ static int inval_ret_fn(void)
 
 static void do_test(void)
 {
+	const int exp_errs_pass[] = {ENOTTY, EINVAL};
+	const int exp_errs_fail[] = {ENOTTY, EISDIR};
+
 	tst_res(TINFO, "Testing TST_EXP_FAIL macro");
 	TST_EXP_FAIL(fail_fn(), EINVAL, "fail_fn()");
 	tst_res(TINFO, "TST_PASS = %i", TST_PASS);
@@ -36,6 +39,10 @@ static void do_test(void)
 	tst_res(TINFO, "TST_PASS = %i", TST_PASS);
 	TST_EXP_FAIL(inval_ret_fn(), ENOTTY, "inval_ret_fn()");
 	tst_res(TINFO, "TST_PASS = %i", TST_PASS);
+	TST_EXP_FAIL_ARR(fail_fn(), exp_errs_pass, "fail_fn()");
+	tst_res(TINFO, "TST_PASS = %i", TST_PASS);
+	TST_EXP_FAIL_ARR(fail_fn(), exp_errs_fail, "fail_fn()");
+	tst_res(TINFO, "TST_PASS = %i", TST_PASS);
 
 	tst_res(TINFO, "Testing TST_EXP_FAIL2 macro");
 	TST_EXP_FAIL2(fail_fn(), EINVAL, "fail_fn()");
@@ -46,6 +53,10 @@ static void do_test(void)
 	tst_res(TINFO, "TST_PASS = %i", TST_PASS);
 	TST_EXP_FAIL2(inval_ret_fn(), ENOTTY, "inval_ret_fn()");
 	tst_res(TINFO, "TST_PASS = %i", TST_PASS);
+	TST_EXP_FAIL2_ARR(fail_fn(), exp_errs_pass, "fail_fn()");
+	tst_res(TINFO, "TST_PASS = %i", TST_PASS);
+	TST_EXP_FAIL2_ARR(fail_fn(), exp_errs_fail, "fail_fn()");
+	tst_res(TINFO, "TST_PASS = %i", TST_PASS);
 }
 
 static struct tst_test test = {
diff --git a/lib/tst_test_macros.c b/lib/tst_test_macros.c
new file mode 100644
index 000000000..a36abbea3
--- /dev/null
+++ b/lib/tst_test_macros.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+#include <stdio.h>
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+#include "tst_test_macros.h"
+
+int tst_errno_in_set(int err, const int *exp_errs, int exp_errs_cnt)
+{
+	int i;
+
+	for (i = 0; i < exp_errs_cnt; i++) {
+		if (err == exp_errs[i])
+			return 1;
+	}
+
+	return 0;
+}
+
+const char *tst_errno_names(char *buf, const int *exp_errs, int exp_errs_cnt)
+{
+	int i;
+	char *cb = buf;
+
+	for (i = 0; i < exp_errs_cnt-1; i++)
+		cb += sprintf(cb, "%s, ", tst_strerrno(exp_errs[i]));
+
+	cb += sprintf(cb, "%s", tst_strerrno(exp_errs[i]));
+
+	*cb = 0;
+
+	return buf;
+}
-- 
2.41.0



More information about the ltp mailing list