xref: /linux/tools/verification/tests/engine.sh (revision 55ee4b931a7ffedc886175d265dd6e6d08fd4151)
192f0ce55SGabriele Monaco#!/bin/bash
292f0ce55SGabriele Monaco# SPDX-License-Identifier: GPL-2.0
392f0ce55SGabriele Monacotest_begin() {
492f0ce55SGabriele Monaco	# Count tests to allow the test harness to double-check if all were
592f0ce55SGabriele Monaco	# included correctly.
692f0ce55SGabriele Monaco	ctr=0
792f0ce55SGabriele Monaco	[ -z "$RV" ] && RV="../rv/rv"
8*36c1af42SGabriele Monaco	[ -z "$RVGEN" ] && RVGEN="python3 ../rvgen"
9*36c1af42SGabriele Monaco	[ -z "$GOLDEN_DIR" ] && GOLDEN_DIR="tests/golden"
1092f0ce55SGabriele Monaco	[ -n "$TEST_COUNT" ] && echo "1..$TEST_COUNT"
1192f0ce55SGabriele Monaco}
1292f0ce55SGabriele Monaco
1392f0ce55SGabriele Monacofailure() {
1492f0ce55SGabriele Monaco	fail=1
1592f0ce55SGabriele Monaco	if [ $# -gt 0 ]; then
1692f0ce55SGabriele Monaco		failbuf+="$1"
1792f0ce55SGabriele Monaco		failbuf+=$'\n'
1892f0ce55SGabriele Monaco	fi
1992f0ce55SGabriele Monaco}
2092f0ce55SGabriele Monaco
2192f0ce55SGabriele Monacoreport() {
2292f0ce55SGabriele Monaco	local desc="$1"
2392f0ce55SGabriele Monaco
2492f0ce55SGabriele Monaco	if [ "$fail" -eq 0 ]; then
2592f0ce55SGabriele Monaco		echo "ok $ctr - $desc"
2692f0ce55SGabriele Monaco	else
2792f0ce55SGabriele Monaco		# Add output and exit code as comments in case of failure
2892f0ce55SGabriele Monaco		echo "not ok $ctr - $desc"
2992f0ce55SGabriele Monaco		echo -n "$failbuf"
3092f0ce55SGabriele Monaco		echo "$result" | col -b | while read -r line; do echo "# $line"; done
3192f0ce55SGabriele Monaco		printf "#\n# exit code %s\n" "$exitcode"
3292f0ce55SGabriele Monaco	fi
3392f0ce55SGabriele Monaco}
3492f0ce55SGabriele Monaco
3592f0ce55SGabriele Monaco_check() {
3692f0ce55SGabriele Monaco	local command=$2
3792f0ce55SGabriele Monaco	local expected_exitcode=${3:-0}
3892f0ce55SGabriele Monaco	local expected_output=$4
3992f0ce55SGabriele Monaco	local unexpected_output=$5
4092f0ce55SGabriele Monaco	local all_lines_pattern=$6
4192f0ce55SGabriele Monaco	local patterns="$expected_output $unexpected_output $all_lines_pattern"
4292f0ce55SGabriele Monaco	local bgpid pid
4392f0ce55SGabriele Monaco
4492f0ce55SGabriele Monaco	eval "$TIMEOUT" "$command" &> check_output.$$ &
4592f0ce55SGabriele Monaco	bgpid=$!
4692f0ce55SGabriele Monaco
4792f0ce55SGabriele Monaco	if grep -q "\$pid" <<< "$patterns"; then
4892f0ce55SGabriele Monaco		for _ in {1..30}; do
4992f0ce55SGabriele Monaco			pid=$(pgrep -f "${command%%[|;&>]*}" | tail -n1)
5092f0ce55SGabriele Monaco			[ -n "$pid" ] && break
5192f0ce55SGabriele Monaco			sleep 0.1
5292f0ce55SGabriele Monaco		done
5392f0ce55SGabriele Monaco	fi
5492f0ce55SGabriele Monaco
5592f0ce55SGabriele Monaco	wait $bgpid
5692f0ce55SGabriele Monaco	exitcode=$?
5792f0ce55SGabriele Monaco	result=$(tr -d '\0' < check_output.$$)
5892f0ce55SGabriele Monaco	rm -f check_output.$$
5992f0ce55SGabriele Monaco
6092f0ce55SGabriele Monaco	failbuf=''
6192f0ce55SGabriele Monaco	fail=0
6292f0ce55SGabriele Monaco
6392f0ce55SGabriele Monaco	# Suppress any other error if a needed pid is empty
6492f0ce55SGabriele Monaco	if [ -z "$pid" ] && grep -q "\$pid" <<< "$patterns"; then
6592f0ce55SGabriele Monaco		result=''
6692f0ce55SGabriele Monaco		failure "# Empty pid for $command"
6792f0ce55SGabriele Monaco		return 1
6892f0ce55SGabriele Monaco	fi
6992f0ce55SGabriele Monaco
7092f0ce55SGabriele Monaco	expected_output="${expected_output//\$pid/$pid}"
7192f0ce55SGabriele Monaco	unexpected_output="${unexpected_output//\$pid/$pid}"
7292f0ce55SGabriele Monaco	all_lines_pattern="${all_lines_pattern//\$pid/$pid}"
7392f0ce55SGabriele Monaco
7492f0ce55SGabriele Monaco	# Test if the results matches if requested
7592f0ce55SGabriele Monaco	if [ -n "$expected_output" ] && ! grep -qe "$expected_output" <<< "$result"; then
7692f0ce55SGabriele Monaco		failure "# Output match failed: \"$expected_output\""
7792f0ce55SGabriele Monaco	fi
7892f0ce55SGabriele Monaco
7992f0ce55SGabriele Monaco	if [ -n "$unexpected_output" ] && grep -qe "$unexpected_output" <<< "$result"; then
8092f0ce55SGabriele Monaco		failure "# Output non-match failed: \"$unexpected_output\""
8192f0ce55SGabriele Monaco	fi
8292f0ce55SGabriele Monaco
8392f0ce55SGabriele Monaco	if [ -n "$all_lines_pattern" ] && grep -vqe "$all_lines_pattern" <<< "$result"; then
8492f0ce55SGabriele Monaco		failure "# All-lines pattern failed: \"$all_lines_pattern\""
8592f0ce55SGabriele Monaco	fi
8692f0ce55SGabriele Monaco
8792f0ce55SGabriele Monaco	if [ $exitcode -ne "$expected_exitcode" ]; then
8892f0ce55SGabriele Monaco		failure "# Expected exit code $expected_exitcode"
8992f0ce55SGabriele Monaco	fi
9092f0ce55SGabriele Monaco}
9192f0ce55SGabriele Monaco
9292f0ce55SGabriele Monacocheck() {
9392f0ce55SGabriele Monaco	# Simple check: run the command with given arguments and test exit code.
9492f0ce55SGabriele Monaco	# If TEST_COUNT is set, run the test. Otherwise, just count.
9592f0ce55SGabriele Monaco	ctr=$((ctr + 1))
9692f0ce55SGabriele Monaco	if [ -n "$TEST_COUNT" ]; then
9792f0ce55SGabriele Monaco		_check "$@"
9892f0ce55SGabriele Monaco		report "$1"
9992f0ce55SGabriele Monaco	fi
10092f0ce55SGabriele Monaco}
10192f0ce55SGabriele Monaco
10292f0ce55SGabriele Monacocheck_if_exists() {
10392f0ce55SGabriele Monaco	# Conditional check that skips if a file or folder doesn't exist
10492f0ce55SGabriele Monaco	local desc=$1
10592f0ce55SGabriele Monaco	local command=$2
10692f0ce55SGabriele Monaco	local file=$3
10792f0ce55SGabriele Monaco	local expected_output=$4
10892f0ce55SGabriele Monaco	local unexpected_output=$5
10992f0ce55SGabriele Monaco	local all_lines_pattern=$6
11092f0ce55SGabriele Monaco
11192f0ce55SGabriele Monaco	ctr=$((ctr + 1))
11292f0ce55SGabriele Monaco	if [ -n "$TEST_COUNT" ]; then
11392f0ce55SGabriele Monaco		if [ ! -e "$file" ]; then
11492f0ce55SGabriele Monaco			echo "ok $ctr - $desc # SKIP file not found: $file"
11592f0ce55SGabriele Monaco		else
11692f0ce55SGabriele Monaco			_check "$desc" "$command" 0 "$expected_output" \
11792f0ce55SGabriele Monaco				"$unexpected_output" "$all_lines_pattern"
11892f0ce55SGabriele Monaco			report "$desc"
11992f0ce55SGabriele Monaco		fi
12092f0ce55SGabriele Monaco	fi
12192f0ce55SGabriele Monaco}
12292f0ce55SGabriele Monaco
123*36c1af42SGabriele Monacocheck_and_compare_folder() {
124*36c1af42SGabriele Monaco	# Run command, compare generated folder to golden, and cleanup
125*36c1af42SGabriele Monaco	local desc=$1
126*36c1af42SGabriele Monaco	local command=$2
127*36c1af42SGabriele Monaco	local generated_dir=$3
128*36c1af42SGabriele Monaco	local expected_output=$4
129*36c1af42SGabriele Monaco	local unexpected_output=$5
130*36c1af42SGabriele Monaco	local golden_dir="$GOLDEN_DIR/$generated_dir"
131*36c1af42SGabriele Monaco
132*36c1af42SGabriele Monaco	ctr=$((ctr + 1))
133*36c1af42SGabriele Monaco	if [ -n "$TEST_COUNT" ]; then
134*36c1af42SGabriele Monaco		rm -rf "$generated_dir"
135*36c1af42SGabriele Monaco		_check "$desc" "$command" 0 "$expected_output" "$unexpected_output"
136*36c1af42SGabriele Monaco
137*36c1af42SGabriele Monaco		if [ "$fail" -eq 0 ] && [ ! -d "$generated_dir" ]; then
138*36c1af42SGabriele Monaco			failure "# Generated directory not found: $generated_dir"
139*36c1af42SGabriele Monaco		fi
140*36c1af42SGabriele Monaco
141*36c1af42SGabriele Monaco		if [ "$fail" -ne 0 ]; then
142*36c1af42SGabriele Monaco			:
143*36c1af42SGabriele Monaco		elif ! diff -r "$generated_dir" "$golden_dir" &> /dev/null; then
144*36c1af42SGabriele Monaco			failure "# Directories differ:"
145*36c1af42SGabriele Monaco			failbuf+=$(diff -r "$generated_dir" "$golden_dir" 2>&1 | sed 's/^/#   /')
146*36c1af42SGabriele Monaco			failbuf+=$'\n'
147*36c1af42SGabriele Monaco		fi
148*36c1af42SGabriele Monaco
149*36c1af42SGabriele Monaco		report "$1"
150*36c1af42SGabriele Monaco
151*36c1af42SGabriele Monaco		rm -rf "$generated_dir"
152*36c1af42SGabriele Monaco	fi
153*36c1af42SGabriele Monaco}
154*36c1af42SGabriele Monaco
15592f0ce55SGabriele Monacoset_timeout() {
15692f0ce55SGabriele Monaco	TIMEOUT="timeout -v -k 30s $1"
15792f0ce55SGabriele Monaco}
15892f0ce55SGabriele Monaco
15992f0ce55SGabriele Monacoset_expected_timeout() {
16092f0ce55SGabriele Monaco	TIMEOUT="timeout --preserve-status -k 30s $1"
16192f0ce55SGabriele Monaco}
16292f0ce55SGabriele Monaco
16392f0ce55SGabriele Monacounset_timeout() {
16492f0ce55SGabriele Monaco	unset TIMEOUT
16592f0ce55SGabriele Monaco}
16692f0ce55SGabriele Monaco
16792f0ce55SGabriele Monacotest_end() {
16892f0ce55SGabriele Monaco	# If running without TEST_COUNT, tests are not actually run, just
16992f0ce55SGabriele Monaco	# counted. In that case, re-run the test with the correct count.
17092f0ce55SGabriele Monaco	[ -z "$TEST_COUNT" ] && TEST_COUNT=$ctr exec bash "$0" || true
17192f0ce55SGabriele Monaco}
17292f0ce55SGabriele Monaco
17392f0ce55SGabriele Monaco# Avoid any environmental discrepancies
17492f0ce55SGabriele Monacoexport LC_ALL=C
17592f0ce55SGabriele Monacounset_timeout
176