https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=7e18d96dc9dca458d90e48e9355fd692826bc905

commit 7e18d96dc9dca458d90e48e9355fd692826bc905
Author: Christian Franke <christian.fra...@t-online.de>
Date:   Sat Jul 5 19:10:21 2025 +0200

    Cygwin: CI: cygstress: add ability to run all tests multiple times
    
    Add options '-e' and '-r' to control error behavior and number of
    test runs.
    
    Signed-off-by: Christian Franke <christian.fra...@t-online.de>

Diff:
---
 winsup/testsuite/stress/cygstress | 163 +++++++++++++++++++++++++++++++-------
 1 file changed, 135 insertions(+), 28 deletions(-)

diff --git a/winsup/testsuite/stress/cygstress 
b/winsup/testsuite/stress/cygstress
index ac332055f..f1c1a8d11 100755
--- a/winsup/testsuite/stress/cygstress
+++ b/winsup/testsuite/stress/cygstress
@@ -14,9 +14,14 @@ usage()
   cat <<EOF
 Usage: ${0##*/} [OPTION...] {CI|WORK|FAIL|test...}
 
-  -n        print commands only (dry-run)
-  -f        force execution of tests tagged 'heavy' or 'admin'
   -c LIST   set CPU affinity to LIST
+  -e MODE   select handling of failed tests:
+              c[ont]   continue with next test [default]
+              s[kip]   continue but do not repeat the failed test
+              e[xit]   exit after first failed test
+  -f        force execution of tests tagged 'heavy' or 'admin'
+  -n        print commands only (dry-run)
+  -r N      run test set N times [default: 1]
   -s PATH   stress-ng executable [default: stress-ng]
   -t N      run each test for at least N seconds [default: 5]
   -v        print stress-ng output always [default: on error only]
@@ -450,15 +455,17 @@ stress_tests='
   zombie        # WORKS,CI
 '
 
-stress_ng="stress-ng"
-timeout=5; workers=2
+error_mode="cont"; stress_ng="stress-ng"
+num_runs=1; timeout=5; workers=2
 dryrun=false; force=false; verbose=false
 taskset=
 
 while :; do case $1 in
   -c) shift; taskset=$1 ;;
+  -e) shift; error_mode=$1 ;;
   -f) force=true ;;
   -n) dryrun=true ;;
+  -r) shift; num_runs=$1 ;;
   -s) shift; stress_ng=$1 ;;
   -t) shift; timeout=$1 ;;
   -v) verbose=true ;;
@@ -466,16 +473,25 @@ while :; do case $1 in
   -*) usage ;;
   *) break ;;
 esac; shift || usage; done
+[[ "${num_runs}${timeout}${workers}" =~ ^[0-9]*$ ]] || usage
 
-run_ci=false; run_work=false; run_fail=false
-run_tests=
+skip_after_failure=false; exit_after_failure=false
+case $error_mode in
+  c|cont) skip_after_failure=false; exit_after_failure=false ;;
+  s|skip) skip_after_failure=true;  exit_after_failure=false ;;
+  e|exit) skip_after_failure=false; exit_after_failure=true ;;
+  *) usage ;;
+esac
+
+run_ci=false; run_work=false; run_fail=false;
+declare -A run_tests=()
 
 while [ $# -ge 1 ]; do case $1 in
   CI) run_ci=true ;;  WORK) run_work=true ;; FAIL) run_fail=true ;;
-  [a-z]*[a-z]) run_tests+=" $1" ;;
+  [a-z]*[a-z]) run_tests["$1"]=t ;;
   *) usage ;;
 esac; shift; done
-$run_ci || $run_work || $run_fail || [ ${run_tests:+t} ] || usage
+$run_ci || $run_work || $run_fail || [ ${#run_tests[*]} -gt 0 ] || usage
 
 command -V "$stress_ng" >/dev/null || exit 1
 
@@ -502,8 +518,14 @@ stop_stress()
   taskkill /F /T /IM "${stress_ng_name}.exe" ||:
 }
 
-total=0
-fails=0
+ts()
+{
+  date '+%H:%M:%S.%2N'
+}
+
+total_tested=0; total_failed=0
+total_testcases=0
+stopped=false
 
 # stress TEST [OPTION...]
 stress()
@@ -511,7 +533,7 @@ stress()
   local name=$1
   shift || return 1
 
-  local td="$tempdir/stress-ng.$$.$total.d"
+  local td="$tempdir/stress-ng.$$.$total_tested.d"
   local logfile="$logdir/$name"
   local cmd=("$stress_ng" -v -M --oomable --timestamp --verify --temp-path 
"$td" -t "$timeout")
   test -z "$taskset" || cmd+=(--taskset "$taskset")
@@ -529,8 +551,7 @@ stress()
     ( sleep 1; stop_stress ) &
     exit 0
   ) &
-  local watchdog=$!
-  trap "kill $watchdog 2>/dev/null ||:; exit 130" SIGINT SIGTERM
+  watchdog=$!
 
   mkdir "$td"
   local rc=0
@@ -542,13 +563,14 @@ stress()
   fi
 
   kill $watchdog 2>/dev/null ||:
-  trap - SIGINT SIGTERM
 
   local errs=
   if wait $watchdog; then
-    sleep 2
     errs=", command hangs"
+    sleep 2
   fi
+  watchdog=
+  ! $stopped || return 0
 
   local p
   if p=$(find_stress); then
@@ -559,16 +581,18 @@ stress()
 
   rmdir "$td" 2>/dev/null || errs+=", files left in '$td'"
 
-  ! grep -Eqv '^(stress-ng|info):' "$logfile" || errs+=", unexpected output"
+  ! grep -qv '^stress-ng:' "$logfile" || errs+=", unexpected output"
 
   if [ "${rc}${errs:+t}" != "0" ]; then
     $verbose || cat "$logfile"
-    echo ">>> FAILURE: $name" "$@" "(exit status ${rc}${errs})"
     ! [ ${p:+t} ] || echo "$p"
+    echo ">>> FAILURE: $(ts): $name" "$@" "(exit status ${rc}${errs})"
     echo
     return 1
   fi
-  echo ">>> SUCCESS: $name" "$@"
+
+  ! grep '^stress-ng:.* fail:' "$logfile" || set -- "$@" "(warning: 'fail:' 
messages)"
+  echo ">>> SUCCESS: $(ts): $name" "$@"
   ! $verbose || echo
   return 0
 }
@@ -579,13 +603,15 @@ if p=$(find_stress); then
   $dryrun || exit 1
 fi
 
+tests=()
+
 while read; do
   args=${REPLY#*|}
-  name=${args%% *}
+
   run_this=false
-  for t in $run_tests; do if [ "$t" = "$name" ]; then
-    run_this=true; break
-  fi; done
+  if [ -n "${run_tests["$args"]}" ]; then
+    run_this=true; unset run_tests["$args"]
+  fi
 
   tag=${REPLY%%|*}
   case $tag in
@@ -596,14 +622,13 @@ while read; do
     admin|heavy)
       $run_this || continue
       if ! $force; then
-        echo ">>> SKIPPED: $name (tagged '$tag', use '-f' to override)"; echo
+        echo ">>> SKIPPED: $args (tagged '$tag', use '-f' to override)"
         continue
       fi ;;
     *) echo "*** syntax error: '$REPLY'"; exit 1 ;;
   esac
 
-  : $((++total))
-  stress $args ||: $((++fails))
+  tests+=("$args")
 done <<<"$(
   sed -E \
     -e 's/^ *([-0-9a-z]+)( +-[^#]*[^ #])? +# 
*(FAILS|WORKS(,CI)?|admin|heavy|-----) *(#.*)?$/\3|\1\2/' \
@@ -611,9 +636,91 @@ done <<<"$(
     <<<"$stress_tests"
 )"
 
-if [ $fails -ne 0 ]; then
-  echo ">>> FAILURE: $fails of $total stress test(s) failed"
+if [ ${#run_tests[*]} != 0 ]; then
+  for t in "${!run_tests[@]}"; do
+    echo "$t: unknown test"
+  done
+  exit 1
+fi
+
+tests_run=()
+tests_failed=()
+
+watchdog=
+trap '
+  test -z "$watchdog" || kill $watchdog 2>/dev/null ||:
+  stopped=true
+' SIGINT SIGTERM
+
+echo ">>> STARTED: $(ts)"
+
+for ((r = 0; r < num_runs; r++)); do
+  curr_tested=0; curr_failed=0; curr_skipped=0
+
+  for ((t = 0; t < ${#tests[*]}; t++)); do
+    if $skip_after_failure && [ -n "${tests_failed[t]}" ]; then
+      echo ">>> -------: $(ts): ${tests[t]}"
+      : $((++curr_skipped))
+      continue
+    fi
+
+    rc=0
+    stress ${tests[t]} || rc=$?
+
+    if $stopped; then
+      echo ">>> STOPPED: $(ts): ${tests[t]}"
+      echo
+      break
+    fi
+
+    : $((++curr_tested)) $((++total_tested)) $((++tests_run[t]))
+    test $total_testcases -gt $t || total_testcases=$((t + 1))
+
+    if [ $rc != 0 ]; then
+      : $((++curr_failed)) $((++total_failed)) $((++tests_failed[t]))
+      ! $exit_after_failure || break
+    fi
+  done
+
+  test $num_runs -gt 1 || break
+
+  if [ $curr_failed != 0 ]; then
+    echo -n ">>> FAILURE: $(ts): run $((r+1)) of $num_runs: $curr_failed of 
$curr_tested test(s) failed"
+  else
+    echo -n ">>> SUCCESS: $(ts): run $((r+1)) of $num_runs: all $curr_tested 
test(s) succeeded"
+  fi
+  test $curr_skipped = 0 || echo -n "; $curr_skipped test(s) skipped"
+  if [ $total_failed != 0 ]; then
+    echo "; total: $total_failed of $total_tested test(s) failed"
+  else
+    echo "; total: all $total_tested test(s) succeeded"
+  fi
+  echo
+
+  ! $stopped || break
+  ! $exit_after_failure || [ $curr_failed = 0 ] || break
+  ! $skip_after_failure || [ $curr_failed -lt $curr_tested ] || break
+done
+
+if [ $total_failed != 0 ]; then
+  if [ $num_runs -gt 1 ]; then
+    echo ">>> SUMMARY:"
+    for ((t = 0; t < ${#tests[*]}; t++)); do
+      if [ -n "${tests_failed[t]}" ]; then
+        echo ">>> FAILURE: ${tests[t]}: ${tests_failed[t]} of ${tests_run[t]} 
test(s) failed"
+      else
+        test -z "${tests_run[t]}" \
+        || echo ">>> SUCCESS: ${tests[t]}: all ${tests_run[t]} test(s) 
succeeded"
+      fi
+    done
+    echo
+  fi
+
+  echo -n ">>> FAILURE: $(ts): ${#tests_failed[*]} of $total_testcases test 
case(s) failed"
+  echo "; total: $total_failed of $total_tested test(s) failed"
   exit 1
 fi
-echo ">>> SUCCESS: All $total stress test(s) succeeded"
+
+echo -n ">>> SUCCESS: $(ts): all test(s) of $total_testcases test case(s) 
succeeded"
+echo "; total: $total_tested test(s)"
 exit 0

Reply via email to