• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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