Linux EXT4 FS development
 help / color / mirror / Atom feed
From: Zorro Lang <zlang@kernel.org>
To: fstests@vger.kernel.org
Cc: Theodore Ts'o <tytso@mit.edu>, linux-ext4@vger.kernel.org
Subject: [RFC PATCH 4/4] check: add --loop-while-successful option
Date: Wed, 11 Nov 2026 01:09:20 +0800	[thread overview]
Message-ID: <20261110170920.3302511-5-zlang@kernel.org> (raw)
In-Reply-To: <20261110170920.3302511-1-zlang@kernel.org>

Add one more member of the --loop family: --loop-while-successful runs
each test up to <n> times but stops rerunning it at the first failure.
This is faster than --loop for bisecting flaky tests, since the loop
ends as soon as the failure is reproduced.  The failing run is recorded
in @bad, so a reproduced failure is still reported as a failed test.

Signed-off-by: Zorro Lang <zlang@kernel.org>
---
 check | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/check b/check
index 96e4f2fd..6b7bd23e 100755
--- a/check
+++ b/check
@@ -26,7 +26,8 @@ do_report=false
 DUMP_OUTPUT=false
 iterations=1
 istop=false
-# Selected by -L / --loop and its siblings: "", "always" or "on-fail"
+# Selected by -L / --loop and its siblings: "", "always", "on-fail" or
+# "while-successful"
 loop_mode=""
 # Total number of runs for the current loop mode
 loop_total=0
@@ -74,6 +75,9 @@ General options:
                               aggregate pass/fail metrics
     --loop <n>              run each test <n> times, measuring aggregate
                               pass/fail metrics (test fails if any run fails)
+    --loop-while-successful <n>
+                              run each test up to <n> times, stopping at the
+                              first failure
     -n                      show me, do not run tests
     -r                      randomize test order
     -s section              run only specified section from config file
@@ -402,7 +406,7 @@ _set_loop_mode()
 
 	[[ $count =~ ^[0-9]+$ ]] || usage
 	if [ -n "$loop_mode" ] && [ "$loop_mode" != "$mode" ]; then
-		echo "check: conflicting loop modes: -L, --loop-on-fail and --loop are mutually exclusive" >&2
+		echo "check: conflicting loop modes: -L, --loop, --loop-on-fail and --loop-while-successful are mutually exclusive" >&2
 		usage
 	fi
 	loop_mode="$mode"
@@ -418,7 +422,9 @@ _set_loop_mode()
 parse_check_args()
 {
 	local short_opts="g:x:X:e:E:s:S:lnri:I:TdbR:L:h"
-	local long_opts="fs:,exact-order,large-fs,extra-space:,udiff,help,iterate:,iterate-while-successful:,loop:,loop-on-fail:"
+	local long_opts="fs:,exact-order,large-fs,extra-space:,udiff,help,"
+	long_opts+="iterate:,iterate-while-successful:,"
+	long_opts+="loop:,loop-on-fail:,loop-while-successful:"
 
 	compat_old_option "$@"
 
@@ -534,6 +540,10 @@ parse_check_args()
 			_set_loop_mode always "$2"
 			shift
 			;;
+		--loop-while-successful)
+			_set_loop_mode while-successful "$2"
+			shift
+			;;
 		-h|--help)
 			usage
 			;;
@@ -805,11 +815,13 @@ _add_bad() {
 
 # Print the aggregate results of the current loop once all loop_total runs
 # have been recorded, then reset the loop state so that the next test can
-# start.
+# start.  A non-empty @force argument ends the loop before loop_total runs,
+# which is used to stop a while-successful loop at the first failure.
 _try_loop_aggregate() {
 	local test_seq="$1"
+	local force="$2"
 
-	if ((${#loop_status[*]} >= loop_total)); then
+	if [ -n "$force" ] || ((${#loop_status[*]} >= loop_total)); then
 		printf "%s aggregate results across %d runs: " \
 			"$test_seq" "${#loop_status[*]}"
 		awk "BEGIN {
@@ -845,7 +857,12 @@ _stash_test_status() {
 			# any failed run fails the test
 			_add_bad "$test_seq"
 		fi
-		_try_loop_aggregate "$test_seq"
+		# a while-successful loop stops at the first failed run
+		if [ "$test_status" = "fail" ] && [ "$loop_mode" = "while-successful" ]; then
+			_try_loop_aggregate "$test_seq" force
+		else
+			_try_loop_aggregate "$test_seq"
+		fi
 		# the rerun loop handles @bad/@notrun by itself
 		return
 	fi
@@ -865,7 +882,8 @@ _stash_test_status() {
 		notrun+=("$test_seq")
 		;;
 	pass)
-		if [ "$loop_mode" = "always" ] && ((loop_total > 1)); then
+		if { [ "$loop_mode" = "always" ] || [ "$loop_mode" = "while-successful" ]; } \
+		   && ((loop_total > 1)); then
 			# start a rerun loop
 			_stash_loop_files "$test_seq" ".rerun0"
 			loop_status+=("$test_status")
-- 
2.56.0


      parent reply	other threads:[~2026-11-10 17:09 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 17:09 [RFC PATCH 0/4] check: add --loop* family options for repeating tests Zorro Lang
2026-11-10 17:09 ` [RFC PATCH 1/4] check: add long aliases --iterate and --iterate-while-successful Zorro Lang
2026-11-10 17:09 ` [RFC PATCH 2/4] check: add --loop option to run each test multiple times Zorro Lang
2026-11-10 17:09 ` [RFC PATCH 3/4] check: add --loop-on-fail long name for -L Zorro Lang
2026-11-10 17:09 ` Zorro Lang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261110170920.3302511-5-zlang@kernel.org \
    --to=zlang@kernel.org \
    --cc=fstests@vger.kernel.org \
    --cc=linux-ext4@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox