#! /bin/sh1#2# SPDX-License-Identifier: BSD-2-Clause3#4# Copyright (c) 2018-2025 Gavin D. Howard and contributors.5#6# Redistribution and use in source and binary forms, with or without7# modification, are permitted provided that the following conditions are met:8#9# * Redistributions of source code must retain the above copyright notice, this10# list of conditions and the following disclaimer.11#12# * Redistributions in binary form must reproduce the above copyright notice,13# this list of conditions and the following disclaimer in the documentation14# and/or other materials provided with the distribution.15#16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"17# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE20# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR21# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF22# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS23# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN24# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)25# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE26# POSSIBILITY OF SUCH DAMAGE.27#2829script="$0"30testdir=$(dirname "$script")3132. "$testdir/../scripts/functions.sh"3334# Just print the usage and exit with an error. This can receive a message to35# print.36# @param 1 A message to print.37usage() {38if [ $# -eq 1 ]; then39printf '%s\n\n' "$1"40fi41print 'usage: %s [-n] dir [run_extra_tests] [run_stack_tests] [gen_tests] [run_problematic_tests] [exec args...]\n' \42"$script"43exit 144}4546# We need to figure out if we should run stuff in parallel.47pll=14849while getopts "n" opt; do5051case "$opt" in52n) pll=0 ; set -e ;;53?) usage "Invalid option: $opt" ;;54esac5556done57shift $(($OPTIND - 1))5859# Command-line processing.60if [ "$#" -ge 1 ]; then61d="$1"62shift63check_d_arg "$d"64else65usage "Not enough arguments"66fi6768if [ "$#" -lt 1 ]; then69extra=170check_bool_arg "$extra"71else72extra="$1"73shift74check_bool_arg "$extra"75fi7677if [ "$#" -lt 1 ]; then78run_stack_tests=179check_bool_arg "$run_stack_tests"80else81run_stack_tests="$1"82shift83check_bool_arg "$run_stack_tests"84fi8586if [ "$#" -lt 1 ]; then87generate_tests=188check_bool_arg "$generate_tests"89else90generate_tests="$1"91shift92check_bool_arg "$generate_tests"93fi9495if [ "$#" -lt 1 ]; then96problematic_tests=197check_bool_arg "$problematic_tests"98else99problematic_tests="$1"100shift101check_bool_arg "$problematic_tests"102fi103104if [ "$#" -lt 1 ]; then105exe="$testdir/../bin/$d"106check_exec_arg "$exe"107else108exe="$1"109shift110check_exec_arg "$exe"111fi112113stars="***********************************************************************"114printf '%s\n' "$stars"115116# Set stuff for the correct calculator.117if [ "$d" = "bc" ]; then118halt="quit"119else120halt="q"121fi122123# I use these, so unset them to make the tests work.124unset BC_ENV_ARGS125unset BC_LINE_LENGTH126unset DC_ENV_ARGS127unset DC_LINE_LENGTH128129# Get the list of tests that require extra math.130extra_required=$(cat "$testdir/extra_required.txt")131132pids=""133134printf '\nRunning %s tests...\n\n' "$d"135136# Run the tests one at a time.137while read t; do138139# If it requires extra, then skip if we don't have it.140if [ "$extra" -eq 0 ]; then141if [ -z "${extra_required##*$t*}" ]; then142printf 'Skipping %s %s\n' "$d" "$t"143continue144fi145fi146147if [ "$pll" -ne 0 ]; then148sh "$testdir/test.sh" "$d" "$t" "$generate_tests" "$exe" "$@" &149pids="$pids $!"150else151sh "$testdir/test.sh" "$d" "$t" "$generate_tests" "$exe" "$@"152fi153154done < "$testdir/$d/all.txt"155156# stdin tests.157if [ "$pll" -ne 0 ]; then158sh "$testdir/stdin.sh" "$d" "$exe" "$@" &159pids="$pids $!"160else161sh "$testdir/stdin.sh" "$d" "$exe" "$@"162fi163164# Script tests.165if [ "$pll" -ne 0 ]; then166sh "$testdir/scripts.sh" "$d" "$extra" "$run_stack_tests" "$generate_tests" \167"$exe" "$@" &168pids="$pids $!"169else170sh "$testdir/scripts.sh" -n "$d" "$extra" "$run_stack_tests" "$generate_tests" \171"$exe" "$@"172fi173174# Error tests.175if [ "$pll" -ne 0 ]; then176sh "$testdir/errors.sh" "$d" "$exe" "$@" &177pids="$pids $!"178else179sh "$testdir/errors.sh" "$d" "$exe" "$@"180fi181182# Test all the files in the errors directory. While the other error test (in183# tests/errors.sh) does a test for every line of certain error files in the main184# directory, this does one test per file in the errors directory, but it runs185# the file through stdin and as a file on the command-line.186for testfile in $testdir/$d/errors/*.txt; do187188b=$(basename "$testfile")189190if [ "$pll" -ne 0 ]; then191sh "$testdir/error.sh" "$d" "$b" "$problematic_tests" "$@" &192pids="$pids $!"193else194sh "$testdir/error.sh" "$d" "$b" "$problematic_tests" "$@"195fi196197done198199if [ "$pll" -ne 0 ]; then200201exit_err=0202203for p in $pids; do204205wait "$p"206err="$?"207208if [ "$err" -ne 0 ]; then209printf 'A test failed!\n'210exit_err=1211fi212done213214if [ "$exit_err" -ne 0 ]; then215exit 1216fi217218fi219220printf '\nAll %s tests passed.\n' "$d"221222printf '\n%s\n' "$stars"223224225