123set -euo pipefail45LC_ALL=C6export LC_ALL78if [[ $# -gt 1 ]]; then9 printf 'usage: %s [TEST_DIRECTORY]\n' "${0##*/}" >&210 exit 211fi12script_dir="$(CDPATH='' cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"13test_dir="${1:-$script_dir/tests}"14if [[ -L "$test_dir" || ! -d "$test_dir" ]]; then15 printf 'shell test directory must be a real directory: %s\n' "$test_dir" >&216 exit 117fi18if [[ ! -r "$test_dir" || ! -x "$test_dir" ]]; then19 printf 'shell test directory must be readable and searchable: %s\n' "$test_dir" >&220 exit 121fi2223# Bash expands this array in LC_ALL=C order. dotglob makes a test such as24# `.release-contract.sh` part of the same inventory, while nullglob lets us25# diagnose an empty inventory instead of trying to execute a literal glob.26shopt -s dotglob nullglob27shell_tests=("$test_dir"/*.sh)28shopt -u dotglob nullglob2930if (( ${#shell_tests[@]} == 0 )); then31 printf 'no shell tests were discovered in: %s\n' "$test_dir" >&232 exit 133fi3435# Validate the complete inventory before running its first entry. This keeps a36# malformed or non-executable test late in the sort order from producing a37# partially successful gate.38for shell_test in "${shell_tests[@]}"; do39 printf 'shell_test_discovered=%s\n' "$shell_test"40 if [[ "$shell_test" == *$'\n'* || "$shell_test" == *$'\r'* ]]; then41 printf 'shell test path contains an unsafe line break: %q\n' "$shell_test" >&242 exit 143 fi44 if [[ -L "$shell_test" || ! -f "$shell_test" ]]; then45 printf 'shell test entry must be a regular, non-symlink file: %s\n' \46 "$shell_test" >&247 exit 148 fi49 if [[ ! -r "$shell_test" ]]; then50 printf 'shell test entry is not readable: %s\n' "$shell_test" >&251 exit 152 fi53 if [[ ! -x "$shell_test" ]]; then54 printf 'shell test entry is not executable: %s\n' "$shell_test" >&255 exit 156 fi57done5859for shell_test in "${shell_tests[@]}"; do60 printf 'shell_test_start=%s\n' "$shell_test"61 bash "$shell_test"62done