xref: /linux/tools/verification/tests/engine.sh (revision 92f0ce55299082a37ac88c12b552059b278afcbf)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3test_begin() {
4	# Count tests to allow the test harness to double-check if all were
5	# included correctly.
6	ctr=0
7	[ -z "$RV" ] && RV="../rv/rv"
8	[ -n "$TEST_COUNT" ] && echo "1..$TEST_COUNT"
9}
10
11failure() {
12	fail=1
13	if [ $# -gt 0 ]; then
14		failbuf+="$1"
15		failbuf+=$'\n'
16	fi
17}
18
19report() {
20	local desc="$1"
21
22	if [ "$fail" -eq 0 ]; then
23		echo "ok $ctr - $desc"
24	else
25		# Add output and exit code as comments in case of failure
26		echo "not ok $ctr - $desc"
27		echo -n "$failbuf"
28		echo "$result" | col -b | while read -r line; do echo "# $line"; done
29		printf "#\n# exit code %s\n" "$exitcode"
30	fi
31}
32
33_check() {
34	local command=$2
35	local expected_exitcode=${3:-0}
36	local expected_output=$4
37	local unexpected_output=$5
38	local all_lines_pattern=$6
39	local patterns="$expected_output $unexpected_output $all_lines_pattern"
40	local bgpid pid
41
42	eval "$TIMEOUT" "$command" &> check_output.$$ &
43	bgpid=$!
44
45	if grep -q "\$pid" <<< "$patterns"; then
46		for _ in {1..30}; do
47			pid=$(pgrep -f "${command%%[|;&>]*}" | tail -n1)
48			[ -n "$pid" ] && break
49			sleep 0.1
50		done
51	fi
52
53	wait $bgpid
54	exitcode=$?
55	result=$(tr -d '\0' < check_output.$$)
56	rm -f check_output.$$
57
58	failbuf=''
59	fail=0
60
61	# Suppress any other error if a needed pid is empty
62	if [ -z "$pid" ] && grep -q "\$pid" <<< "$patterns"; then
63		result=''
64		failure "# Empty pid for $command"
65		return 1
66	fi
67
68	expected_output="${expected_output//\$pid/$pid}"
69	unexpected_output="${unexpected_output//\$pid/$pid}"
70	all_lines_pattern="${all_lines_pattern//\$pid/$pid}"
71
72	# Test if the results matches if requested
73	if [ -n "$expected_output" ] && ! grep -qe "$expected_output" <<< "$result"; then
74		failure "# Output match failed: \"$expected_output\""
75	fi
76
77	if [ -n "$unexpected_output" ] && grep -qe "$unexpected_output" <<< "$result"; then
78		failure "# Output non-match failed: \"$unexpected_output\""
79	fi
80
81	if [ -n "$all_lines_pattern" ] && grep -vqe "$all_lines_pattern" <<< "$result"; then
82		failure "# All-lines pattern failed: \"$all_lines_pattern\""
83	fi
84
85	if [ $exitcode -ne "$expected_exitcode" ]; then
86		failure "# Expected exit code $expected_exitcode"
87	fi
88}
89
90check() {
91	# Simple check: run the command with given arguments and test exit code.
92	# If TEST_COUNT is set, run the test. Otherwise, just count.
93	ctr=$((ctr + 1))
94	if [ -n "$TEST_COUNT" ]; then
95		_check "$@"
96		report "$1"
97	fi
98}
99
100check_if_exists() {
101	# Conditional check that skips if a file or folder doesn't exist
102	local desc=$1
103	local command=$2
104	local file=$3
105	local expected_output=$4
106	local unexpected_output=$5
107	local all_lines_pattern=$6
108
109	ctr=$((ctr + 1))
110	if [ -n "$TEST_COUNT" ]; then
111		if [ ! -e "$file" ]; then
112			echo "ok $ctr - $desc # SKIP file not found: $file"
113		else
114			_check "$desc" "$command" 0 "$expected_output" \
115				"$unexpected_output" "$all_lines_pattern"
116			report "$desc"
117		fi
118	fi
119}
120
121set_timeout() {
122	TIMEOUT="timeout -v -k 30s $1"
123}
124
125set_expected_timeout() {
126	TIMEOUT="timeout --preserve-status -k 30s $1"
127}
128
129unset_timeout() {
130	unset TIMEOUT
131}
132
133test_end() {
134	# If running without TEST_COUNT, tests are not actually run, just
135	# counted. In that case, re-run the test with the correct count.
136	[ -z "$TEST_COUNT" ] && TEST_COUNT=$ctr exec bash "$0" || true
137}
138
139# Avoid any environmental discrepancies
140export LC_ALL=C
141unset_timeout
142