1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0-or-later 3# Copyright (c) 2019 Petr Vorel <pvorel@suse.cz> 4# Copyright (c) 2021 Joerg Vehlow <joerg.vehlow@aox-tech.de> 5 6PATH="$(dirname $0):$(dirname $0)/../../../testcases/lib/:$PATH" 7 8# Test cases are separated by newlines. 9# Every test has the following fields in this order: 10# file 11# timeout_mul 12# use_cat 13# max_runtime 14# expected_exit_code 15# expected passes 16# expected failed 17# expected broken 18# description 19# Whole lines can be commented out using "#" 20DATA=" 21timeout01.sh| |0| |0 22timeout02.sh| |0| |0 23timeout02.sh| foo|0| |2 24timeout02.sh| 2|0| |0 25timeout01.sh| 2|0| |0 26timeout02.sh| 1.1|0| |0 27timeout02.sh| -10|0| |2 28timeout02.sh| -0.1|0| |0 29timeout02.sh| -1.1|0| |2 30timeout02.sh|-10.1|0| |2 31timeout03.sh| |0|12|137| | | |Test is killed, if it does not terminate after SIGTERM 32timeout04.sh| |0| | 2|0|0|1|Verify that timeout is enforced 33timeout02.sh| 2|1| 2| |1|0|0|Test termination of timeout process 34" 35 36# Executes a test 37# Parameter: 38# - test: The test to execute 39# - timeout: The timeout multiplicator (optional) 40# - use_cat: Pipe the output of the command through cat (optional) 41# If this is used, the exit code is NOT returned! 42# 43# The function returns the following global variables: 44# - test_exit: The exit code of the test 45# - test_duration: The duration of the test in seconds 46# - test_output: The full output of the test 47# - test_passed: The number of passed tests parsed from the summary 48# - test_failed: The number of failed tests parsed from the summary 49# - test_broken: The number of broken tests parsed from the summary 50run_test() 51{ 52 local test=$1 53 local timeout=$2 54 local use_cat=$3 55 local tmpfile start end; 56 57 tmpfile=$(mktemp -t ltp_timeout_XXXXXXXX) 58 start=$(date +%s) 59 # We have to use set monitor mode (set -m) here. 60 # In most shells in most cases this creates a 61 # new process group for the next command. 62 # A process group is required for the timeout functionality, 63 # because it sends signals to the whole process group. 64 set -m 65 # The use_cat is for testing if any programm using stdout 66 # is still running, after the test finished. 67 # cat will wait for its stdin to be closed. 68 # 69 # In the pure shell implementation of the timeout handling, 70 # the sleep process was never killed, when a test finished 71 # before the timeout. 72 if [ "$use_cat" = "1" ]; then 73 LTP_TIMEOUT_MUL=$timeout $test 2>&1 | cat >$tmpfile 74 else 75 LTP_TIMEOUT_MUL=$timeout $test 1>$tmpfile 2>&1 76 fi 77 test_exit=$? 78 set +m 79 end=$(date +%s) 80 81 test_duration=$((end - start)) 82 test_output=$(cat $tmpfile) 83 rm $tmpfile 84 85 eval $(echo "$test_output" | awk ' 86 BEGIN {sum=0} 87 $1 == "Summary:" { 88 sum=1; 89 } 90 sum && ( \ 91 $1 == "passed" \ 92 || $1 == "failed" \ 93 || $1 == "broken") { 94 print "test_" $1 "=" $2 95 } 96 ') 97} 98 99echo "Testing timeout in shell API" 100echo 101 102failed=0 103test_nr=0 104 105old_ifs="$IFS" 106IFS=$(printf "\n\b") 107 108# Remove comments and empty lines 109CLEANED_DATA=$(echo "$DATA" | sed '/^\s*#/d;/^\s*$/d') 110test_max=$(echo "$CLEANED_DATA" | wc -l) 111for d in $CLEANED_DATA; do 112 IFS="$old_ifs" 113 114 file=$(echo $d | cut -d'|' -f1 | xargs) 115 timeout=$(echo $d | cut -d'|' -f2 | xargs) 116 use_cat=$(echo $d | cut -d'|' -f3 | xargs) 117 max_runtime=$(echo $d | cut -d'|' -f4 | xargs) 118 max_runtime=${max_runtime:--1} 119 exp_exit=$(echo $d | cut -d'|' -f5 | xargs) 120 exp_exit=${exp_exit:--1} 121 exp_passed=$(echo $d | cut -d'|' -f6 | xargs) 122 exp_passed=${exp_passed:--1} 123 exp_failed=$(echo $d | cut -d'|' -f7 | xargs) 124 exp_failed=${exp_failed:--1} 125 exp_broken=$(echo $d | cut -d'|' -f8 | xargs) 126 exp_broken=${exp_broken:--1} 127 description=$(echo $d | cut -d'|' -f9) 128 129 test_nr=$(($test_nr + 1)) 130 131 cur_fails=0 132 133 if [ -z "$description" ]; then 134 description="$file (LTP_TIMEOUT_MUL='$timeout')" 135 fi 136 137 echo "=== $test_nr/$test_max $description ===" 138 run_test "$file" "$timeout" "$use_cat" 139 140 if [ $max_runtime -ne -1 ] && [ $test_duration -gt $max_runtime ]; then 141 echo "FAILED (runtime: $test_duration, expected less than $max_runtime)" 142 cur_fails=$((cur_fails + 1)) 143 fi 144 145 if [ $exp_passed -ne -1 ] && [ $exp_passed -ne $test_passed ]; then 146 echo "FAILED (passes: $test_passed, expected $exp_passed)" 147 cur_fails=$((cur_fails + 1)) 148 fi 149 150 if [ $exp_failed -ne -1 ] && [ $exp_failed -ne $test_failed ]; then 151 echo "FAILED (failed: $test_failed, expected $exp_failed)" 152 cur_fails=$((cur_fails + 1)) 153 fi 154 155 if [ $exp_broken -ne -1 ] && [ $exp_broken -ne $test_broken ]; then 156 echo "FAILED (broken: $test_broken, expected $exp_broken)" 157 cur_fails=$((cur_fails + 1)) 158 fi 159 160 if [ $exp_exit -ne -1 ] && [ $test_exit -ne $exp_exit ]; then 161 echo "FAILED (exit code: $test_exit, expected $exp_exit)" 162 cur_fails=$((cur_fails + 1)) 163 fi 164 165 if [ $cur_fails -gt 0 ]; then 166 failed=$((failed + 1)) 167 echo "--------" 168 echo "$test_output" 169 echo "--------" 170 else 171 echo "PASSED" 172 fi 173 echo 174done 175IFS="$old_ifs" 176 177echo "Failed tests: $failed" 178exit $failed 179