Commit 6a3c9527ce for openssl.org
commit 6a3c9527ce46e1ef6b0dfe339c79ced7a7f2f6ad
Author: Jakub Zelenka <jakub.zelenka@openssl.foundation>
Date: Mon Jun 1 20:04:37 2026 +0200
mfail: add all tests iterable variants
It adds ADD_MFAIL_ALL_TESTS and ADD_MFAIL_ALL_NO_CHECK_TESTS that work
in similar way as ADD_ALL_TESTS but with mfail testing.
Reviewed-by: Norbert Pocs <norbertp@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
MergeDate: Thu Jun 11 16:00:12 2026
(Merged from https://github.com/openssl/openssl/pull/31356)
diff --git a/test/README.md b/test/README.md
index bc4bd73f49..2a423d3511 100644
--- a/test/README.md
+++ b/test/README.md
@@ -192,8 +192,10 @@ Some tests use the `ADD_MFAIL_TEST` framework to exhaustively verify that
functions handle every possible allocation failure gracefully. These tests
run repeatedly, failing one allocation later each iteration. The
`ADD_MFAIL_NO_CHECK_TEST` variant relaxes the requirement that the test
-return 0 when a failure was triggered. Behavior is controlled with the
-following environment variables:
+return 0 when a failure was triggered. The `ADD_MFAIL_ALL_TESTS` and
+`ADD_MFAIL_ALL_NO_CHECK_TESTS` variants apply the same cycle to each index
+of a parameterised test, the same way `ADD_ALL_TESTS` does. Behavior is
+controlled with the following environment variables:
OPENSSL_TEST_MFAIL_DISABLE=1 Disable mfail custom allocator installation.
diff --git a/test/testutil.h b/test/testutil.h
index 31e5f87412..b38791b287 100644
--- a/test/testutil.h
+++ b/test/testutil.h
@@ -79,6 +79,12 @@
#define ADD_MFAIL_NO_CHECK_TEST(test_fn) \
add_mfail_test(#test_fn, test_fn, MFAIL_TEST_NO_CHECK)
+/* Runs the exhaustive mfail cycle for each 0 <= idx < num */
+#define ADD_MFAIL_ALL_TESTS(test_fn, num) \
+ add_mfail_all_tests(#test_fn, test_fn, num, 0)
+#define ADD_MFAIL_ALL_NO_CHECK_TESTS(test_fn, num) \
+ add_mfail_all_tests(#test_fn, test_fn, num, MFAIL_TEST_NO_CHECK)
+
/*
* A variant of the same without TAP output.
*/
@@ -251,6 +257,8 @@ void add_all_tests(const char *test_case_name, int (*test_fn)(int idx), int num,
int subtest);
void add_mfail_test(const char *test_case_name, int (*test_fn)(void),
int flags);
+void add_mfail_all_tests(const char *test_case_name, int (*test_fn)(int idx),
+ int num, int flags);
#define MFAIL_start mfail_start
#define MFAIL_end mfail_end
diff --git a/test/testutil/driver.c b/test/testutil/driver.c
index eb9087fe64..a3fdc59cc0 100644
--- a/test/testutil/driver.c
+++ b/test/testutil/driver.c
@@ -96,6 +96,20 @@ void add_mfail_test(const char *test_case_name, int (*test_fn)(void), int flags)
++num_test_cases;
}
+void add_mfail_all_tests(const char *test_case_name, int (*test_fn)(int idx),
+ int num, int flags)
+{
+ assert(num_tests != OSSL_NELEM(all_tests));
+ all_tests[num_tests].test_case_name = test_case_name;
+ all_tests[num_tests].param_test_fn = test_fn;
+ all_tests[num_tests].num = num;
+ all_tests[num_tests].subtest = 1;
+ all_tests[num_tests].mfail = 1;
+ all_tests[num_tests].mfail_flags = flags;
+ ++num_tests;
+ ++num_test_cases;
+}
+
static int gcd(int a, int b)
{
while (b != 0) {
@@ -300,19 +314,18 @@ static double mfail_elapsed_secs(clock_t start)
return (double)(clock() - start) / CLOCKS_PER_SEC;
}
-static int mfail_run_test(const char *test_case_name,
- int (*test_fn)(void), int flags)
+static int mfail_run_test(const TEST_INFO *t, int idx)
{
int counting_ok = 1;
int injection_ok = 1;
int injections = 0;
int allocations = 0;
- int no_check = (flags & MFAIL_TEST_NO_CHECK) != 0;
+ int no_check = (t->mfail_flags & MFAIL_TEST_NO_CHECK) != 0;
clock_t start = clock();
level += 4;
test_adjust_streams_tap_level(level);
- test_printf_stdout("Subtest: %s\n", test_case_name);
+ test_printf_stdout("Subtest: %s[%d]\n", t->test_case_name, idx);
test_printf_tapout("1..2\n");
test_flush_stdout();
test_flush_tapout();
@@ -324,13 +337,13 @@ static int mfail_run_test(const char *test_case_name,
int rv;
ERR_clear_error();
- rv = test_fn();
+ rv = t->param_test_fn != NULL ? t->param_test_fn(idx) : t->test_fn();
if (phase == MFAIL_PHASE_COUNTING) {
allocations = mfail_get_count();
if (!TEST_int_eq(rv, 1)) {
TEST_error("mfail test '%s': counting iteration failed",
- test_case_name);
+ t->test_case_name);
counting_ok = 0;
}
test_verdict(counting_ok, "1 - counting (%d allocations)",
@@ -343,7 +356,7 @@ static int mfail_run_test(const char *test_case_name,
if (!no_check && !TEST_int_eq(rv, 0)) {
TEST_error("mfail test '%s': allocation failure at "
"point %d not handled",
- test_case_name, mfail_get_point());
+ t->test_case_name, mfail_get_point());
injection_ok = 0;
}
} else if (mfail_get_mode() == MFAIL_MODE_SINGLE) {
@@ -353,7 +366,7 @@ static int mfail_run_test(const char *test_case_name,
test_flush_tapout();
} else if (!TEST_int_eq(rv, 1)) {
TEST_error("mfail test '%s': no injection but test failed",
- test_case_name);
+ t->test_case_name);
injection_ok = 0;
}
}
@@ -435,8 +448,7 @@ int run_tests(const char *test_prog_name)
set_test_title(all_tests[i].test_case_name);
ERR_clear_error();
if (all_tests[i].mfail)
- verdict = mfail_run_test(all_tests[i].test_case_name,
- all_tests[i].test_fn, all_tests[i].mfail_flags);
+ verdict = mfail_run_test(&all_tests[i], 0);
else
verdict = all_tests[i].test_fn();
finalize(verdict != 0);
@@ -473,7 +485,10 @@ int run_tests(const char *test_prog_name)
if (single_iter != -1 && ((jj + 1) != single_iter))
continue;
ERR_clear_error();
- v = all_tests[i].param_test_fn(j);
+ if (all_tests[i].mfail)
+ v = mfail_run_test(&all_tests[i], j);
+ else
+ v = all_tests[i].param_test_fn(j);
if (v == 0) {
verdict = 0;