dcavalca / rpms / systemd

Forked from rpms/systemd 4 months ago
Clone
c2dfb7
From 7ba4a6f5a02f6142d0e28fd475fd008532fb1083 Mon Sep 17 00:00:00 2001
c2dfb7
From: Frantisek Sumsal <frantisek@sumsal.cz>
c2dfb7
Date: Tue, 5 Mar 2019 13:50:28 +0100
c2dfb7
Subject: [PATCH] test: parallelize tasks in TEST-24-UNIT-TESTS
c2dfb7
c2dfb7
(cherry picked from commit 2f2a0454efd07644a4e0ccb3f00f1db2d7043391)
c2dfb7
c2dfb7
Related: #1823767
c2dfb7
---
c2dfb7
 test/TEST-24-UNIT-TESTS/test.sh      |  2 +
c2dfb7
 test/TEST-24-UNIT-TESTS/testsuite.sh | 97 +++++++++++++++++++++-------
c2dfb7
 2 files changed, 77 insertions(+), 22 deletions(-)
c2dfb7
c2dfb7
diff --git a/test/TEST-24-UNIT-TESTS/test.sh b/test/TEST-24-UNIT-TESTS/test.sh
c2dfb7
index 014ee52277..fc8c89fe0a 100755
c2dfb7
--- a/test/TEST-24-UNIT-TESTS/test.sh
c2dfb7
+++ b/test/TEST-24-UNIT-TESTS/test.sh
c2dfb7
@@ -78,6 +78,8 @@ test_setup() {
c2dfb7
         setup_basic_environment
c2dfb7
         install_keymaps yes
c2dfb7
         install_zoneinfo
c2dfb7
+        # Install nproc to determine # of CPUs for correct parallelization
c2dfb7
+        inst_binary nproc
c2dfb7
 
c2dfb7
         # setup the testsuite service
c2dfb7
         cat >$initdir/etc/systemd/system/testsuite.service <
c2dfb7
diff --git a/test/TEST-24-UNIT-TESTS/testsuite.sh b/test/TEST-24-UNIT-TESTS/testsuite.sh
c2dfb7
index 7c0e495dbd..7c7a068556 100755
c2dfb7
--- a/test/TEST-24-UNIT-TESTS/testsuite.sh
c2dfb7
+++ b/test/TEST-24-UNIT-TESTS/testsuite.sh
c2dfb7
@@ -4,31 +4,84 @@
c2dfb7
 #set -ex
c2dfb7
 #set -o pipefail
c2dfb7
 
c2dfb7
-for i in /usr/lib/systemd/tests/test-*; do
c2dfb7
-    if [[ ! -x $i ]]; then continue; fi
c2dfb7
-    NAME=${i##*/}
c2dfb7
-    echo "Running $NAME"
c2dfb7
-    $i > /$NAME.log 2>&1
c2dfb7
-    ret=$?
c2dfb7
-    if (( $ret && $ret != 77 )); then
c2dfb7
-        echo "$NAME failed with $ret"
c2dfb7
-        echo $NAME >> /failed-tests
c2dfb7
-        echo "--- $NAME begin ---" >> /failed
c2dfb7
-        cat /$NAME.log >> /failed
c2dfb7
-        echo "--- $NAME end ---" >> /failed
c2dfb7
-    elif (( $ret == 77 )); then
c2dfb7
-        echo "$NAME skipped"
c2dfb7
-        echo $NAME >> /skipped-tests
c2dfb7
-        echo "--- $NAME begin ---" >> /skipped
c2dfb7
-        cat /$NAME.log >> /skipped
c2dfb7
-        echo "--- $NAME end ---" >> /skipped
c2dfb7
+NPROC=$(nproc)
c2dfb7
+MAX_QUEUE_SIZE=${NPROC:-2}
c2dfb7
+IFS=$'\n' TEST_LIST=($(ls /usr/lib/systemd/tests/test-*))
c2dfb7
+
c2dfb7
+# Check & report test results
c2dfb7
+# Arguments:
c2dfb7
+#   $1: test path
c2dfb7
+#   $2: test exit code
c2dfb7
+function report_result() {
c2dfb7
+    if [[ $# -ne 2 ]]; then
c2dfb7
+        echo >&2 "check_result: missing arguments"
c2dfb7
+        exit 1
c2dfb7
+    fi
c2dfb7
+
c2dfb7
+    local name="${1##*/}"
c2dfb7
+    local ret=$2
c2dfb7
+
c2dfb7
+    if [[ $ret -ne 0 && $ret != 77 ]]; then
c2dfb7
+        echo "$name failed with $ret"
c2dfb7
+        echo "$name" >> /failed-tests
c2dfb7
+        {
c2dfb7
+            echo "--- $name begin ---"
c2dfb7
+            cat "/$name.log"
c2dfb7
+            echo "--- $name end ---"
c2dfb7
+        } >> /failed
c2dfb7
+    elif [[ $ret == 77 ]]; then
c2dfb7
+        echo "$name skipped"
c2dfb7
+        echo "$name" >> /skipped-tests
c2dfb7
+        {
c2dfb7
+            echo "--- $name begin ---"
c2dfb7
+            cat "/$name.log"
c2dfb7
+            echo "--- $name end ---"
c2dfb7
+        } >> /skipped
c2dfb7
     else
c2dfb7
-        echo "$NAME OK"
c2dfb7
-        echo $NAME >> /testok
c2dfb7
+        echo "$name OK"
c2dfb7
+        echo "$name" >> /testok
c2dfb7
+    fi
c2dfb7
+
c2dfb7
+    systemd-cat echo "--- $name ---"
c2dfb7
+    systemd-cat cat "/$name.log"
c2dfb7
+}
c2dfb7
+
c2dfb7
+# Associative array for running tasks, where running[test-path]=PID
c2dfb7
+declare -A running=()
c2dfb7
+for task in "${TEST_LIST[@]}"; do
c2dfb7
+    # If there's MAX_QUEUE_SIZE running tasks, keep checking the running queue
c2dfb7
+    # until one of the tasks finishes, so we can replace it.
c2dfb7
+    while [[ ${#running[@]} -ge $MAX_QUEUE_SIZE ]]; do
c2dfb7
+        for key in "${!running[@]}"; do
c2dfb7
+            if ! kill -0 ${running[$key]} &>/dev/null; then
c2dfb7
+                # Task has finished, report its result and drop it from the queue
c2dfb7
+                wait ${running[$key]}
c2dfb7
+                ec=$?
c2dfb7
+                report_result "$key" $ec
c2dfb7
+                unset running["$key"]
c2dfb7
+                # Break from inner for loop and outer while loop to skip
c2dfb7
+                # the sleep below when we find a free slot in the queue
c2dfb7
+                break 2
c2dfb7
+            fi
c2dfb7
+        done
c2dfb7
+
c2dfb7
+        # Precisely* calculated constant to keep the spinlock from burning the CPU(s)
c2dfb7
+        sleep 0.01
c2dfb7
+    done
c2dfb7
+
c2dfb7
+    if [[ -x $task ]]; then
c2dfb7
+        log_file="/${task##*/}.log"
c2dfb7
+        $task &> "$log_file" &
c2dfb7
+        running[$task]=$!
c2dfb7
     fi
c2dfb7
+done
c2dfb7
 
c2dfb7
-    systemd-cat echo "--- $NAME ---"
c2dfb7
-    systemd-cat cat /$NAME.log
c2dfb7
+# Wait for remaining running tasks
c2dfb7
+for key in "${!running[@]}"; do
c2dfb7
+    wait ${running[$key]}
c2dfb7
+    ec=$?
c2dfb7
+    report_result "$key" $ec
c2dfb7
+    unset running["$key"]
c2dfb7
 done
c2dfb7
 
c2dfb7
 exit 0