| 1 | #!/bin/sh |
| 2 | TEST_PREFIX="[int-signal-trap]" |
| 3 | SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) |
| 4 | FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}" |
| 5 | export FORTSH_BIN |
| 6 | . "$SCRIPT_DIR/../test_harness.sh" |
| 7 | |
| 8 | # Integration tests: traps and signal handling |
| 9 | |
| 10 | section "1. EXIT trap" |
| 11 | compare_output "basic EXIT trap" 'trap "echo bye" EXIT; echo main' |
| 12 | compare_output "EXIT with explicit exit" 'trap "echo bye" EXIT; exit 0' |
| 13 | compare_output "function as EXIT handler" 'f() { echo cleaned; }; trap f EXIT; echo main' |
| 14 | compare_output "subshell has own EXIT" 'trap "echo outer" EXIT; (trap "echo inner" EXIT; echo sub)' |
| 15 | compare_output "EXIT trap sees exit status" 'trap "echo status=$?" EXIT; exit 42' |
| 16 | compare_output "EXIT trap on implicit exit" 'trap "echo bye" EXIT; true' |
| 17 | compare_output "EXIT trap with multiple commands" 'trap "echo a; echo b" EXIT; echo main' |
| 18 | |
| 19 | section "2. ERR trap" |
| 20 | compare_output "ERR on false" 'trap "echo error" ERR; false; echo after' |
| 21 | compare_output "ERR not in OR chain" 'trap "echo error" ERR; false || true; echo ok' |
| 22 | compare_output "ERR not in if condition" 'trap "echo error" ERR; if false; then echo no; fi; echo ok' |
| 23 | compare_output "ERR not in while condition" 'trap "echo error" ERR; while false; do :; done; echo ok' |
| 24 | compare_output "ERR not with negation" 'trap "echo error" ERR; ! false; echo ok' |
| 25 | compare_output "ERR on command failure" 'trap "echo err" ERR; /nonexistent_xyz 2>/dev/null; echo after' |
| 26 | |
| 27 | section "3. RETURN trap" |
| 28 | compare_output "RETURN in function" 'f() { trap "echo returned" RETURN; echo body; }; f' |
| 29 | compare_output "RETURN fires on return" 'f() { trap "echo returned" RETURN; echo body; return 0; }; f' |
| 30 | compare_output "RETURN on source" "echo 'echo sourced' > $TEST_TMPDIR/trap_src.sh; trap 'echo returned' RETURN; source $TEST_TMPDIR/trap_src.sh" |
| 31 | compare_output "RETURN multiple calls" 'f() { trap "echo ret" RETURN; echo body; }; f; f; f' |
| 32 | |
| 33 | section "4. signal traps" |
| 34 | compare_output "trap USR1" 'trap "echo caught" USR1; kill -USR1 $$; echo after' |
| 35 | compare_output "ignore signal" 'trap "" TERM; kill -TERM $$ 2>/dev/null; echo survived' |
| 36 | compare_output "trap INT" 'trap "echo interrupted" INT; kill -INT $$; echo after' |
| 37 | compare_output "trap HUP" 'trap "echo hangup" HUP; kill -HUP $$; echo after' |
| 38 | |
| 39 | section "5. trap management" |
| 40 | compare_output "overwrite trap" 'trap "echo a" EXIT; trap "echo b" EXIT' |
| 41 | compare_output "clear trap" 'trap "echo a" EXIT; trap - EXIT; echo done' |
| 42 | compare_output "display trap" 'trap "echo hello" EXIT; trap -p EXIT' |
| 43 | compare_output "trap multiple signals" 'trap "echo caught" USR1 USR2; kill -USR1 $$; kill -USR2 $$; echo done' |
| 44 | compare_output "trap -p shows all" 'trap "echo a" USR1; trap "echo b" USR2; trap -p | grep -cE "USR[12]" | tr -d " "' |
| 45 | compare_output "trap list signals" 'trap -l >/dev/null 2>&1; echo $?' |
| 46 | |
| 47 | section "6. trap interaction with builtins" |
| 48 | compare_output "trap doesnt change exit status" 'trap "echo bye" EXIT; false; echo $?' |
| 49 | compare_output "trap with eval" 'trap "echo bye" EXIT; eval "echo evaled"' |
| 50 | compare_output "trap in subshell" '(trap "echo sub_bye" EXIT; echo sub)' |
| 51 | compare_output "trap preserved across commands" 'trap "echo bye" EXIT; echo a; echo b; echo c' |
| 52 | compare_output "nested trap scopes" 'trap "echo outer_bye" EXIT; (trap "echo inner_bye" EXIT; echo inner); echo between' |
| 53 | |
| 54 | print_summary |