1#!/usr/bin/env bash 2# SPDX-License-Identifier: LGPL-2.1-or-later 3set -eux 4set -o pipefail 5 6NPROC=$(nproc) 7MAX_QUEUE_SIZE=${NPROC:-2} 8TESTS_GLOB=${TESTS_GLOB:-test-*} 9mapfile -t TEST_LIST < <(find /usr/lib/systemd/tests/ -maxdepth 1 -type f -name "${TESTS_GLOB}") 10 11# reset state 12rm -fv /failed-tests /skipped-tests /skipped 13 14# Check & report test results 15# Arguments: 16# $1: test path 17# $2: test exit code 18function report_result() { 19 if [[ $# -ne 2 ]]; then 20 echo >&2 "check_result: missing arguments" 21 exit 1 22 fi 23 24 local name="${1##*/}" 25 local ret=$2 26 27 if [[ $ret -ne 0 && $ret != 77 ]]; then 28 echo "$name failed with $ret" 29 echo "$name" >>/failed-tests 30 { 31 echo "--- $name begin ---" 32 cat "/$name.log" 33 echo "--- $name end ---" 34 } >>/failed 35 elif [[ $ret == 77 ]]; then 36 echo "$name skipped" 37 echo "$name" >>/skipped-tests 38 { 39 echo "--- $name begin ---" 40 cat "/$name.log" 41 echo "--- $name end ---" 42 } >>/skipped 43 else 44 echo "$name OK" 45 echo "$name" >>/testok 46 fi 47 48 systemd-cat echo "--- $name ---" 49 systemd-cat cat "/$name.log" 50} 51 52# Associative array for running tasks, where running[test-path]=PID 53declare -A running=() 54for task in "${TEST_LIST[@]}"; do 55 # If there's MAX_QUEUE_SIZE running tasks, keep checking the running queue 56 # until one of the tasks finishes, so we can replace it. 57 while [[ ${#running[@]} -ge $MAX_QUEUE_SIZE ]]; do 58 for key in "${!running[@]}"; do 59 if ! kill -0 "${running[$key]}" &>/dev/null; then 60 # Task has finished, report its result and drop it from the queue 61 wait "${running[$key]}" && ec=0 || ec=$? 62 report_result "$key" $ec 63 unset running["$key"] 64 # Break from inner for loop and outer while loop to skip 65 # the sleep below when we find a free slot in the queue 66 break 2 67 fi 68 done 69 70 # Precisely* calculated constant to keep the spinlock from burning the CPU(s) 71 sleep 0.01 72 done 73 74 if [[ -x $task ]]; then 75 log_file="/${task##*/}.log" 76 $task &>"$log_file" & 77 running[$task]=$! 78 fi 79done 80 81# Wait for remaining running tasks 82for key in "${!running[@]}"; do 83 wait ${running[$key]} && ec=0 || ec=$? 84 report_result "$key" $ec 85 unset running["$key"] 86done 87 88# Test logs are sometimes lost, as the system shuts down immediately after 89journalctl --sync 90 91exit 0 92