tenseleyflow/bensch / afa9ecd

Browse files

fix test runner paths and bridge env variables for full suite

- POSIX runner: require SHELL_BIN from env, remove fortsh fallback paths
- Export BASH_REF as alias for REF_SHELL (POSIX scripts use BASH_REF)
- Copy test_harness.sh to suites/builtins/ for builtin test sourcing
- Fix test_harness.sh source paths: portable/ goes up one dir,
extended/fortsh/ goes up two dirs
- Clean up stale fortsh references in runner comments
Authored by espadonne
SHA
afa9ecd5a6be9a7246fab2b7ac0934f13593d5b1
Parents
044e500
Tree
b0f15f9

43 changed files

StatusFile+-
M bensch 1 0
M suites/builtins/extended/fortsh/test_abbr.sh 1 1
M suites/builtins/extended/fortsh/test_config.sh 1 1
M suites/builtins/extended/fortsh/test_defun.sh 1 1
M suites/builtins/extended/fortsh/test_help.sh 1 1
M suites/builtins/extended/fortsh/test_memory.sh 1 1
M suites/builtins/extended/fortsh/test_perf.sh 1 1
M suites/builtins/extended/test_complete_compgen.sh 1 1
M suites/builtins/extended/test_coproc.sh 1 1
M suites/builtins/extended/test_let.sh 1 1
M suites/builtins/portable/test_alias.sh 1 1
M suites/builtins/portable/test_arithmetic.sh 1 1
M suites/builtins/portable/test_arrays.sh 1 1
M suites/builtins/portable/test_cd_pwd.sh 1 1
M suites/builtins/portable/test_declare.sh 1 1
M suites/builtins/portable/test_echo.sh 1 1
M suites/builtins/portable/test_eval.sh 1 1
M suites/builtins/portable/test_exec.sh 1 1
M suites/builtins/portable/test_export_unset.sh 1 1
M suites/builtins/portable/test_fc.sh 1 1
M suites/builtins/portable/test_flow_control.sh 1 1
M suites/builtins/portable/test_getopts.sh 1 1
M suites/builtins/portable/test_hash.sh 1 1
M suites/builtins/portable/test_history.sh 1 1
M suites/builtins/portable/test_jobs_fg_bg.sh 1 1
M suites/builtins/portable/test_kill_wait.sh 1 1
M suites/builtins/portable/test_local.sh 1 1
M suites/builtins/portable/test_printf.sh 1 1
M suites/builtins/portable/test_pushd_popd_dirs.sh 1 1
M suites/builtins/portable/test_read.sh 1 1
M suites/builtins/portable/test_readonly.sh 1 1
M suites/builtins/portable/test_set_shopt.sh 1 1
M suites/builtins/portable/test_shift.sh 1 1
M suites/builtins/portable/test_source.sh 1 1
M suites/builtins/portable/test_test.sh 1 1
M suites/builtins/portable/test_times.sh 1 1
M suites/builtins/portable/test_trap.sh 1 1
M suites/builtins/portable/test_type_command.sh 1 1
M suites/builtins/portable/test_ulimit.sh 1 1
M suites/builtins/portable/test_umask.sh 1 1
M suites/builtins/portable/test_variable_ops.sh 1 1
A suites/builtins/test_harness.sh 183 0
M suites/posix/run_posix_tests.sh 5 23
benschmodified
@@ -113,6 +113,7 @@ fi
113
 # Export for child processes
113
 # Export for child processes
114
 export SHELL_BIN
114
 export SHELL_BIN
115
 export REF_SHELL
115
 export REF_SHELL
116
+export BASH_REF="$REF_SHELL"  # Alias for POSIX scripts that use BASH_REF
116
 export BENSCH_PROFILE="$PROFILE"
117
 export BENSCH_PROFILE="$PROFILE"
117
 
118
 
118
 # Build RC_DISABLE_ENV from profile
119
 # Build RC_DISABLE_ENV from profile
suites/builtins/extended/fortsh/test_abbr.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[abbr]"
2
 TEST_PREFIX="[abbr]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/../.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. abbr define"
5
 section "1. abbr define"
6
 check_exit "abbr with no args succeeds" 'abbr' "0"
6
 check_exit "abbr with no args succeeds" 'abbr' "0"
suites/builtins/extended/fortsh/test_config.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[config]"
2
 TEST_PREFIX="[config]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/../.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. config display"
5
 section "1. config display"
6
 check_exit "config show exits successfully" 'config show' "0"
6
 check_exit "config show exits successfully" 'config show' "0"
suites/builtins/extended/fortsh/test_defun.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[defun]"
2
 TEST_PREFIX="[defun]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/../.." && pwd)/test_harness.sh"
4
 
4
 
5
 # defun is a fortsh-specific alternate syntax for function definitions
5
 # defun is a fortsh-specific alternate syntax for function definitions
6
 
6
 
suites/builtins/extended/fortsh/test_help.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[help]"
2
 TEST_PREFIX="[help]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/../.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. help output"
5
 section "1. help output"
6
 check_exit "help exits successfully" 'help' "0"
6
 check_exit "help exits successfully" 'help' "0"
suites/builtins/extended/fortsh/test_memory.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[memory]"
2
 TEST_PREFIX="[memory]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/../.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. memory commands"
5
 section "1. memory commands"
6
 check_exit "memory with no args" 'memory' "0"
6
 check_exit "memory with no args" 'memory' "0"
suites/builtins/extended/fortsh/test_perf.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[perf]"
2
 TEST_PREFIX="[perf]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/../.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. perf commands"
5
 section "1. perf commands"
6
 check_exit "perf with no args" 'perf' "0"
6
 check_exit "perf with no args" 'perf' "0"
suites/builtins/extended/test_complete_compgen.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[complete-compgen]"
2
 TEST_PREFIX="[complete-compgen]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. complete define"
5
 section "1. complete define"
6
 check_exit "complete with -W word list" 'complete -W "start stop restart" myservice' "0"
6
 check_exit "complete with -W word list" 'complete -W "start stop restart" myservice' "0"
suites/builtins/extended/test_coproc.shmodified
@@ -10,7 +10,7 @@ if [ ! -t 0 ] && [ -z "$FORCE_COPROC_TESTS" ]; then
10
     exit 0
10
     exit 0
11
 fi
11
 fi
12
 
12
 
13
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
13
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
14
 
14
 
15
 section "1. coproc basic launch"
15
 section "1. coproc basic launch"
16
 compare_output "coproc sets COPROC_PID" 'coproc sleep 60; test -n "$COPROC_PID" && echo yes; kill $COPROC_PID 2>/dev/null; wait 2>/dev/null'
16
 compare_output "coproc sets COPROC_PID" 'coproc sleep 60; test -n "$COPROC_PID" && echo yes; kill $COPROC_PID 2>/dev/null; wait 2>/dev/null'
suites/builtins/extended/test_let.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[let]"
2
 TEST_PREFIX="[let]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. let arithmetic"
5
 section "1. let arithmetic"
6
 compare_output "let addition" 'let "x=5+3"; echo $x'
6
 compare_output "let addition" 'let "x=5+3"; echo $x'
suites/builtins/portable/test_alias.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[alias]"
2
 TEST_PREFIX="[alias]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. alias basic"
5
 section "1. alias basic"
6
 compare_output "alias define and use via eval" 'shopt -s expand_aliases 2>/dev/null; alias greet="echo hello"; eval greet'
6
 compare_output "alias define and use via eval" 'shopt -s expand_aliases 2>/dev/null; alias greet="echo hello"; eval greet'
suites/builtins/portable/test_arithmetic.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[arithmetic]"
2
 TEST_PREFIX="[arithmetic]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. basic arithmetic"
5
 section "1. basic arithmetic"
6
 compare_output "addition" 'echo $((3 + 4))'
6
 compare_output "addition" 'echo $((3 + 4))'
suites/builtins/portable/test_arrays.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[arrays]"
2
 TEST_PREFIX="[arrays]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. indexed array basics"
5
 section "1. indexed array basics"
6
 compare_output "array literal assignment" 'arr=(a b c); echo ${arr[0]}'
6
 compare_output "array literal assignment" 'arr=(a b c); echo ${arr[0]}'
suites/builtins/portable/test_cd_pwd.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[cd-pwd]"
2
 TEST_PREFIX="[cd-pwd]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. cd basic"
5
 section "1. cd basic"
6
 compare_output "cd no args goes to HOME" 'cd && pwd | tail -1'
6
 compare_output "cd no args goes to HOME" 'cd && pwd | tail -1'
suites/builtins/portable/test_declare.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[declare]"
2
 TEST_PREFIX="[declare]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. declare basic flags"
5
 section "1. declare basic flags"
6
 compare_output "declare -i integer arithmetic" 'declare -i num=5+3; echo $num'
6
 compare_output "declare -i integer arithmetic" 'declare -i num=5+3; echo $num'
suites/builtins/portable/test_echo.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[echo]"
2
 TEST_PREFIX="[echo]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. echo basic"
5
 section "1. echo basic"
6
 compare_output "echo basic string" 'echo hello world'
6
 compare_output "echo basic string" 'echo hello world'
suites/builtins/portable/test_eval.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[eval]"
2
 TEST_PREFIX="[eval]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. eval basic"
5
 section "1. eval basic"
6
 compare_output "eval basic echo" "eval 'echo hello'"
6
 compare_output "eval basic echo" "eval 'echo hello'"
suites/builtins/portable/test_exec.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[exec]"
2
 TEST_PREFIX="[exec]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. exec replaces shell"
5
 section "1. exec replaces shell"
6
 compare_output "exec replaces shell with command" 'exec echo replaced'
6
 compare_output "exec replaces shell with command" 'exec echo replaced'
suites/builtins/portable/test_export_unset.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[export-unset]"
2
 TEST_PREFIX="[export-unset]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. export"
5
 section "1. export"
6
 compare_output "export VAR=value" 'export MYVAR=hello; echo $MYVAR'
6
 compare_output "export VAR=value" 'export MYVAR=hello; echo $MYVAR'
suites/builtins/portable/test_fc.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[fc]"
2
 TEST_PREFIX="[fc]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. fc listing"
5
 section "1. fc listing"
6
 check_exit "fc -l lists history" 'fc -l' "0"
6
 check_exit "fc -l lists history" 'fc -l' "0"
suites/builtins/portable/test_flow_control.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[flow-control]"
2
 TEST_PREFIX="[flow-control]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. exit"
5
 section "1. exit"
6
 compare_exit "exit 0" 'exit 0'
6
 compare_exit "exit 0" 'exit 0'
suites/builtins/portable/test_getopts.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[getopts]"
2
 TEST_PREFIX="[getopts]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. getopts basic"
5
 section "1. getopts basic"
6
 compare_output "getopts basic option parsing" 'f() { while getopts "ab:c" opt; do echo "$opt"; done; }; f -a -c'
6
 compare_output "getopts basic option parsing" 'f() { while getopts "ab:c" opt; do echo "$opt"; done; }; f -a -c'
suites/builtins/portable/test_hash.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[hash]"
2
 TEST_PREFIX="[hash]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. hash basic"
5
 section "1. hash basic"
6
 check_exit "hash with no args" 'hash' "0"
6
 check_exit "hash with no args" 'hash' "0"
suites/builtins/portable/test_history.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[history]"
2
 TEST_PREFIX="[history]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. history display"
5
 section "1. history display"
6
 check_exit "history runs without error" 'history' "0"
6
 check_exit "history runs without error" 'history' "0"
suites/builtins/portable/test_jobs_fg_bg.shmodified
@@ -10,7 +10,7 @@ if [ ! -t 0 ] && [ -z "$FORCE_JOB_TESTS" ]; then
10
     exit 0
10
     exit 0
11
 fi
11
 fi
12
 
12
 
13
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
13
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
14
 
14
 
15
 section "1. jobs display"
15
 section "1. jobs display"
16
 check_exit "jobs with no background jobs" 'jobs' "0"
16
 check_exit "jobs with no background jobs" 'jobs' "0"
suites/builtins/portable/test_kill_wait.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[kill-wait]"
2
 TEST_PREFIX="[kill-wait]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. kill signals"
5
 section "1. kill signals"
6
 check_exit "kill -l lists signals" 'kill -l' "0"
6
 check_exit "kill -l lists signals" 'kill -l' "0"
suites/builtins/portable/test_local.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[local]"
2
 TEST_PREFIX="[local]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. local scope"
5
 section "1. local scope"
6
 compare_output "local restricts scope to function" 'f() { local x=inner; echo $x; }; f; echo ">${x}<"'
6
 compare_output "local restricts scope to function" 'f() { local x=inner; echo $x; }; f; echo ">${x}<"'
suites/builtins/portable/test_printf.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[printf]"
2
 TEST_PREFIX="[printf]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. printf format specifiers"
5
 section "1. printf format specifiers"
6
 compare_output "printf %s string" 'printf "%s\n" hello'
6
 compare_output "printf %s string" 'printf "%s\n" hello'
suites/builtins/portable/test_pushd_popd_dirs.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[pushd-popd-dirs]"
2
 TEST_PREFIX="[pushd-popd-dirs]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. pushd basic"
5
 section "1. pushd basic"
6
 compare_output "pushd changes directory" 'pushd /tmp >/dev/null && pwd'
6
 compare_output "pushd changes directory" 'pushd /tmp >/dev/null && pwd'
suites/builtins/portable/test_read.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[read]"
2
 TEST_PREFIX="[read]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. read basic"
5
 section "1. read basic"
6
 compare_output "read from herestring" 'read VAR <<< "hello"; echo $VAR'
6
 compare_output "read from herestring" 'read VAR <<< "hello"; echo $VAR'
suites/builtins/portable/test_readonly.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[readonly]"
2
 TEST_PREFIX="[readonly]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. readonly basic"
5
 section "1. readonly basic"
6
 compare_output "readonly VAR=value preserves value" 'readonly MYRO=hello; echo $MYRO'
6
 compare_output "readonly VAR=value preserves value" 'readonly MYRO=hello; echo $MYRO'
suites/builtins/portable/test_set_shopt.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[set-shopt]"
2
 TEST_PREFIX="[set-shopt]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. set options"
5
 section "1. set options"
6
 compare_exit "set -e exits on error" 'set -e; false'
6
 compare_exit "set -e exits on error" 'set -e; false'
suites/builtins/portable/test_shift.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[shift]"
2
 TEST_PREFIX="[shift]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. shift basic"
5
 section "1. shift basic"
6
 compare_output "shift removes first param" 'set -- a b c; shift; echo $1'
6
 compare_output "shift removes first param" 'set -- a b c; shift; echo $1'
suites/builtins/portable/test_source.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[source]"
2
 TEST_PREFIX="[source]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 # Create test files
5
 # Create test files
6
 printf 'SOURCED_VAR=hello\n' > "$TEST_TMPDIR/source_var.sh"
6
 printf 'SOURCED_VAR=hello\n' > "$TEST_TMPDIR/source_var.sh"
suites/builtins/portable/test_test.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[test]"
2
 TEST_PREFIX="[test]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. test string operators"
5
 section "1. test string operators"
6
 compare_exit "test -z empty string" 'test -z ""'
6
 compare_exit "test -z empty string" 'test -z ""'
suites/builtins/portable/test_times.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[times]"
2
 TEST_PREFIX="[times]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. times output"
5
 section "1. times output"
6
 check_exit "times exits successfully" 'times' "0"
6
 check_exit "times exits successfully" 'times' "0"
suites/builtins/portable/test_trap.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[trap]"
2
 TEST_PREFIX="[trap]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. trap EXIT"
5
 section "1. trap EXIT"
6
 compare_output "trap EXIT runs on exit" 'trap "echo bye" EXIT; echo hello'
6
 compare_output "trap EXIT runs on exit" 'trap "echo bye" EXIT; echo hello'
suites/builtins/portable/test_type_command.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[type-command]"
2
 TEST_PREFIX="[type-command]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. type builtin"
5
 section "1. type builtin"
6
 compare_exit "type recognizes builtin" 'type echo >/dev/null 2>&1'
6
 compare_exit "type recognizes builtin" 'type echo >/dev/null 2>&1'
suites/builtins/portable/test_ulimit.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[ulimit]"
2
 TEST_PREFIX="[ulimit]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. ulimit display defaults"
5
 section "1. ulimit display defaults"
6
 compare_output "ulimit default shows file size" 'ulimit'
6
 compare_output "ulimit default shows file size" 'ulimit'
suites/builtins/portable/test_umask.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[umask]"
2
 TEST_PREFIX="[umask]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. umask display"
5
 section "1. umask display"
6
 compare_output "umask shows current mask" 'umask'
6
 compare_output "umask shows current mask" 'umask'
suites/builtins/portable/test_variable_ops.shmodified
@@ -1,6 +1,6 @@
1
 #!/bin/sh
1
 #!/bin/sh
2
 TEST_PREFIX="[var-ops]"
2
 TEST_PREFIX="[var-ops]"
3
-. "$(cd "$(dirname "$0")" && pwd)/test_harness.sh"
3
+. "$(cd "$(dirname "$0")/.." && pwd)/test_harness.sh"
4
 
4
 
5
 section "1. default value operators"
5
 section "1. default value operators"
6
 compare_output '${var:-default} with unset var' 'unset V; echo ${V:-fallback}'
6
 compare_output '${var:-default} with unset var' 'unset V; echo ${V:-fallback}'
suites/builtins/test_harness.shadded
@@ -0,0 +1,183 @@
1
+#!/bin/sh
2
+# =====================================
3
+# Shared test harness for builtin tests
4
+# =====================================
5
+# Source this file from individual builtin test scripts.
6
+# Each test file must set TEST_PREFIX before sourcing.
7
+
8
+# Portable timeout: macOS has gtimeout (from coreutils) or no timeout
9
+if command -v timeout >/dev/null 2>&1; then
10
+    run_with_timeout() { timeout "$@"; }
11
+elif command -v gtimeout >/dev/null 2>&1; then
12
+    run_with_timeout() { gtimeout "$@"; }
13
+else
14
+    run_with_timeout() {
15
+        _rwt_secs="$1"; shift
16
+        _rwt_tmp=$(mktemp /tmp/bensch_timeout.XXXXXX)
17
+        ( "$@" ) > "$_rwt_tmp" 2>&1 &
18
+        _rwt_pid=$!
19
+        ( sleep "$_rwt_secs"; kill "$_rwt_pid" 2>/dev/null ) &
20
+        _rwt_wd=$!
21
+        wait "$_rwt_pid" 2>/dev/null
22
+        _rwt_rc=$?
23
+        kill "$_rwt_wd" 2>/dev/null
24
+        wait "$_rwt_wd" 2>/dev/null
25
+        cat "$_rwt_tmp"
26
+        rm -f "$_rwt_tmp"
27
+        return $_rwt_rc
28
+    }
29
+fi
30
+
31
+# Colors (POSIX-compliant way)
32
+RED='\033[0;31m'
33
+GREEN='\033[0;32m'
34
+YELLOW='\033[1;33m'
35
+BLUE='\033[0;34m'
36
+NC='\033[0m'
37
+
38
+CURRENT_SECTION=""
39
+TEST_NUM=0
40
+
41
+PASSED=0
42
+FAILED=0
43
+SKIPPED=0
44
+FAILED_TESTS_LIST=""
45
+
46
+# Get script directory (POSIX way)
47
+SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
48
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
49
+
50
+# Reference bash for expected output — must be bash 4+ for assoc arrays, case transforms
51
+# macOS ships bash 3.2 which lacks these; override with BASH_REF=/opt/homebrew/bin/bash
52
+BASH_REF="${BASH_REF:-bash}"
53
+
54
+# Check if shell binary exists
55
+if [ ! -x "$SHELL_BIN" ]; then
56
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
57
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
58
+    exit 1
59
+fi
60
+
61
+# Temp directory for test files
62
+TEST_TMPDIR=$(mktemp -d)
63
+cleanup() { rm -rf "$TEST_TMPDIR" 2>/dev/null; }
64
+trap cleanup EXIT INT TERM
65
+
66
+pass() {
67
+    TEST_NUM=$((TEST_NUM + 1))
68
+    printf "${GREEN}✓ PASS${NC} ${TEST_PREFIX} ${CURRENT_SECTION}.${TEST_NUM}: %s\n" "$1"
69
+    PASSED=$((PASSED + 1))
70
+}
71
+
72
+fail() {
73
+    TEST_NUM=$((TEST_NUM + 1))
74
+    TEST_ID="${TEST_PREFIX} ${CURRENT_SECTION}.${TEST_NUM}"
75
+    printf "${RED}✗ FAIL${NC} ${TEST_ID}: %s\n" "$1"
76
+    FAILED_TESTS_LIST="${FAILED_TESTS_LIST}  ${TEST_ID}: $1\n"
77
+    if [ -n "$2" ]; then printf "  expected: %s\n" "$2"; fi
78
+    if [ -n "$3" ]; then printf "  got:      %s\n" "$3"; fi
79
+    FAILED=$((FAILED + 1))
80
+}
81
+
82
+skip() {
83
+    TEST_NUM=$((TEST_NUM + 1))
84
+    printf "${YELLOW}⊘ SKIP${NC} ${TEST_PREFIX} ${CURRENT_SECTION}.${TEST_NUM}: %s - %s\n" "$1" "$2"
85
+    SKIPPED=$((SKIPPED + 1))
86
+}
87
+
88
+section() {
89
+    CURRENT_SECTION=$(echo "$1" | grep -oE '^[0-9]+' || echo "0")
90
+    TEST_NUM=0
91
+    printf "\n${BLUE}==========================================\n%s\n==========================================${NC}\n" "$1"
92
+}
93
+
94
+# Normalize shell name prefixes in error messages for comparison
95
+normalize_shell_name() {
96
+    printf '%s\n' "$1" | sed -e 's/[a-z]*sh[0-9]*: line [0-9]*: /SHELL: /g' \
97
+                              -e  \
98
+                              -e 's/[a-z]*sh[0-9]*: /SHELL: /g' \
99
+                              -e 's/[a-z]*sh[0-9]*: /SHELL: /g'
100
+}
101
+
102
+# Per-test timeout (seconds) — prevents hanging tests from blocking CI
103
+TEST_TIMEOUT="${TEST_TIMEOUT:-10}"
104
+
105
+# Helper: compare output against bash
106
+compare_output() {
107
+    test_name="$1"; command="$2"
108
+    expected=$(run_with_timeout "$TEST_TIMEOUT" "$BASH_REF" -c "$command" 2>&1)
109
+    actual=$(run_with_timeout "$TEST_TIMEOUT" "$SHELL_BIN" -c "$command" 2>&1)
110
+    norm_expected=$(normalize_shell_name "$expected")
111
+    norm_actual=$(normalize_shell_name "$actual")
112
+    if [ "$norm_expected" = "$norm_actual" ]; then pass "$test_name"
113
+    else fail "$test_name" "$expected" "$actual"; fi
114
+}
115
+
116
+# Helper: compare exit code only
117
+compare_exit() {
118
+    test_name="$1"; command="$2"
119
+    run_with_timeout "$TEST_TIMEOUT" "$BASH_REF" -c "$command" >/dev/null 2>&1; expected=$?
120
+    run_with_timeout "$TEST_TIMEOUT" "$SHELL_BIN" -c "$command" >/dev/null 2>&1; actual=$?
121
+    if [ "$expected" = "$actual" ]; then pass "$test_name"
122
+    else fail "$test_name" "exit $expected" "exit $actual"; fi
123
+}
124
+
125
+# Helper: compare both output and exit code
126
+compare_both() {
127
+    test_name="$1"; command="$2"
128
+    expected_out=$(run_with_timeout "$TEST_TIMEOUT" "$BASH_REF" -c "$command" 2>&1); expected_exit=$?
129
+    actual_out=$(run_with_timeout "$TEST_TIMEOUT" "$SHELL_BIN" -c "$command" 2>&1); actual_exit=$?
130
+    norm_expected=$(normalize_shell_name "$expected_out")
131
+    norm_actual=$(normalize_shell_name "$actual_out")
132
+    if [ "$norm_expected" = "$norm_actual" ] && [ "$expected_exit" = "$actual_exit" ]; then
133
+        pass "$test_name"
134
+    else
135
+        fail "$test_name" "out='$expected_out' exit=$expected_exit" "out='$actual_out' exit=$actual_exit"
136
+    fi
137
+}
138
+
139
+# Helper: check fortsh output matches expected string
140
+check_output() {
141
+    test_name="$1"; command="$2"; expected="$3"
142
+    actual=$(timeout "$TEST_TIMEOUT" "$SHELL_BIN" -c "$command" 2>&1)
143
+    if [ "$actual" = "$expected" ]; then pass "$test_name"
144
+    else fail "$test_name" "$expected" "$actual"; fi
145
+}
146
+
147
+# Helper: check fortsh exit code matches expected
148
+check_exit() {
149
+    test_name="$1"; command="$2"; expected="$3"
150
+    timeout "$TEST_TIMEOUT" "$SHELL_BIN" -c "$command" >/dev/null 2>&1; actual=$?
151
+    if [ "$actual" = "$expected" ]; then pass "$test_name"
152
+    else fail "$test_name" "exit $expected" "exit $actual"; fi
153
+}
154
+
155
+# Print summary — call at end of each test file
156
+print_summary() {
157
+    printf "\n==========================================\n"
158
+    printf "%s TEST RESULTS\n" "$TEST_PREFIX"
159
+    printf "==========================================\n"
160
+    printf "Passed:  %d\n" "$PASSED"
161
+    printf "Failed:  %d\n" "$FAILED"
162
+    printf "Skipped: %d\n" "$SKIPPED"
163
+    printf "Total:   %d\n" "$((PASSED + FAILED + SKIPPED))"
164
+    printf "==========================================\n"
165
+
166
+    if [ $((PASSED + FAILED)) -gt 0 ]; then
167
+        PASS_RATE=$((PASSED * 100 / (PASSED + FAILED)))
168
+        printf "Pass rate: %d%%\n" "$PASS_RATE"
169
+    fi
170
+
171
+    if [ "$FAILED" -gt 0 ]; then
172
+        printf "\nFailed tests:\n"
173
+        printf "%b" "$FAILED_TESTS_LIST"
174
+        printf "==========================================\n"
175
+    fi
176
+
177
+    if [ "$FAILED" -eq 0 ]; then
178
+        printf "ALL %s TESTS PASSED!\n" "$TEST_PREFIX"
179
+        exit 0
180
+    else
181
+        exit 1
182
+    fi
183
+}
suites/posix/run_posix_tests.shmodified
@@ -18,32 +18,14 @@ NC='\033[0m'
18
 # Get script directory
18
 # Get script directory
19
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
19
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
20
 
20
 
21
-# Find fortsh binary - check multiple locations
21
+# Require SHELL_BIN from environment (set by bensch entry point)
22
-if [ -n "$SHELL_BIN" ] && [ -x "$SHELL_BIN" ]; then
22
+if [ -z "$SHELL_BIN" ] || [ ! -x "$SHELL_BIN" ]; then
23
-    # Use environment variable if set
23
+    printf "${RED}ERROR: SHELL_BIN not set or not executable${NC}\n"
24
-    RESOLVED_SHELL="$SHELL_BIN"
24
+    printf "Run via: bensch --shell /path/to/shell --suite posix\n"
25
-elif [ -x "$SCRIPT_DIR/../bin/fortsh" ]; then
25
+    printf "Or set:  export SHELL_BIN=/path/to/shell\n"
26
-    # Look in ../bin/fortsh (relative to tests/)
27
-    RESOLVED_SHELL="$SCRIPT_DIR/../bin/fortsh"
28
-elif [ -x "./bin/fortsh" ]; then
29
-    # Look in ./bin/fortsh (from project root)
30
-    RESOLVED_SHELL="./bin/fortsh"
31
-elif [ -x "$(pwd)/bin/fortsh" ]; then
32
-    # Look in current working directory
33
-    RESOLVED_SHELL="$(pwd)/bin/fortsh"
34
-else
35
-    printf "${RED}ERROR: shell binary not found!${NC}\n"
36
-    printf "Searched locations:\n"
37
-    printf "  - SHELL_BIN environment variable\n"
38
-    printf "  - %s/bin/fortsh\n" "$SCRIPT_DIR/.."
39
-    printf "  - ./bin/fortsh\n"
40
-    printf "  - $(pwd)/bin/fortsh\n"
41
-    printf "\nPlease build fortsh first with 'make' or set SHELL_BIN\n"
42
     exit 1
26
     exit 1
43
 fi
27
 fi
44
 
28
 
45
-export SHELL_BIN="$RESOLVED_SHELL"
46
-
47
 # Test suite files
29
 # Test suite files
48
 TEST_SUITES="
30
 TEST_SUITES="
49
 posix_compliance_test.sh
31
 posix_compliance_test.sh