From 4c7a49a83e082a7bfff85a9305882f0912655123 Mon Sep 17 00:00:00 2001
From: Tavian Barnes <tavianator@tavianator.com>
Date: Mon, 23 Oct 2023 10:12:25 -0400
Subject: tests: Run test cases in parallel

---
 tests/getopts.sh | 12 +++++++++++
 tests/run.sh     | 61 ++++++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 58 insertions(+), 15 deletions(-)

(limited to 'tests')

diff --git a/tests/getopts.sh b/tests/getopts.sh
index 7d3ef4b..d34df4f 100644
--- a/tests/getopts.sh
+++ b/tests/getopts.sh
@@ -52,6 +52,7 @@ EOF
 
 # Parse the command line
 parse_args() {
+    JOBS=0
     PATTERNS=()
     SUDO=()
     STOP=0
@@ -64,6 +65,9 @@ parse_args() {
 
     for arg; do
         case "$arg" in
+            -j*)
+                JOBS="${arg#-j}"
+                ;;
             --bfs=*)
                 BFS="${arg#*=}"
                 ;;
@@ -127,6 +131,14 @@ parse_args() {
         esac
     done
 
+    if ((JOBS == 0)); then
+        if command -v nproc &>/dev/null; then
+            JOBS=$(nproc)
+        else
+            JOBS=1
+        fi
+    fi
+
     # Try to resolve the path to $BFS before we cd, while also supporting
     # --bfs="./bin/bfs -S ids"
     read -a BFS <<<"${BFS:-$BIN/bfs}"
diff --git a/tests/run.sh b/tests/run.sh
index 28801f4..b46fde6 100644
--- a/tests/run.sh
+++ b/tests/run.sh
@@ -42,6 +42,42 @@ run_test() (
     source "$@"
 )
 
+# Run a test in the background
+bg_test() {
+    if ((VERBOSE_ERRORS)); then
+        run_test "$1"
+    else
+        run_test "$1" 2>"$TMP/TEST.err"
+    fi
+    ret=$?
+
+    if ((ret != 0 && ret != EX_SKIP)); then
+        ((VERBOSE_ERRORS)) || cat "$TMP/$TEST.err" >&2
+        color printf "${BOL}${RED}%s failed!${RST}\n" "$TEST"
+    fi
+
+    return $ret
+}
+
+# Reap a background job
+reap() {
+    wait -n
+    ret=$?
+    ((BG--))
+
+    case $ret in
+        0)
+            ((++passed))
+            ;;
+        $EX_SKIP)
+            ((++skipped))
+            ;;
+        *)
+            ((++failed))
+            ;;
+    esac
+}
+
 # Run all the tests
 run_tests() {
     if ((VERBOSE_TESTS)); then
@@ -70,6 +106,8 @@ run_tests() {
         TEST_FMT="."
     fi
 
+    BG=0
+
     # Turn off set -e (but turn it back on in run_test)
     set +e
 
@@ -79,23 +117,16 @@ run_tests() {
         mkdir -p "$TMP/$TEST"
         OUT="$TMP/$TEST.out"
 
-        if ((VERBOSE_ERRORS)); then
-            run_test "$TESTS/$TEST.sh"
-        else
-            run_test "$TESTS/$TEST.sh" 2>"$TMP/$TEST.err"
+        if ((BG >= JOBS)); then
+            reap
         fi
-        status=$?
+        ((++BG))
 
-        if ((status == 0)); then
-            ((++passed))
-        elif ((status == EX_SKIP)); then
-            ((++skipped))
-        else
-            ((++failed))
-            ((VERBOSE_ERRORS)) || cat "$TMP/$TEST.err" >&2
-            color printf "${BOL}${RED}%s failed!${RST}\n" "$TEST"
-            ((STOP)) && break
-        fi
+        bg_test "$TESTS/$TEST.sh" &
+    done
+
+    while ((BG > 0)); do
+        reap
     done
 
     printf "${BOL}"
-- 
cgit v1.2.3