| 1 | #!/bin/sh |
| 2 | TEST_PREFIX="[int-pipeline]" |
| 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: builtins interacting with pipelines |
| 9 | |
| 10 | section "1. builtins as pipeline source" |
| 11 | compare_output "echo into pipeline" 'echo hello world | tr a-z A-Z' |
| 12 | compare_output "printf into pipeline" 'printf "%s\n" a b c | sort -r' |
| 13 | compare_output "echo pipe to wc" 'echo "one two three" | wc -w | tr -d " "' |
| 14 | compare_output "pwd in pipeline" 'pwd | grep -q / && echo yes' |
| 15 | compare_output "type in pipeline" 'type echo | head -1' |
| 16 | compare_output "printf format in pipeline" 'printf "%d\n" 3 1 2 | sort -n' |
| 17 | compare_output "set outputs to pipeline" 'X=hello; set | grep "^X=" | head -1' |
| 18 | compare_output "declare -p in pipeline" 'X=42; declare -p X 2>/dev/null | head -1' |
| 19 | compare_output "export -p in pipeline" 'export EX=val; export -p | grep "^declare -x EX=" | head -1' |
| 20 | compare_output "alias in pipeline" 'alias myalias="echo test" 2>/dev/null; alias | grep myalias | head -1; unalias myalias 2>/dev/null' |
| 21 | |
| 22 | section "2. builtins as pipeline sink" |
| 23 | compare_output "read from pipeline" 'echo hello | read VAR; echo $VAR' |
| 24 | compare_output "read line from pipeline" 'printf "a\nb\nc\n" | while read line; do echo "got:$line"; done' |
| 25 | compare_output "read multiple vars from pipeline" 'echo "one two three" | { read A B C; echo "$A $B $C"; }' |
| 26 | compare_output "read in while from seq" 'seq 3 | while read n; do echo "num:$n"; done' |
| 27 | compare_output "multi-stage to read" 'printf "c\na\nb\n" | sort | while read x; do echo "sorted:$x"; done' |
| 28 | compare_output "read with IFS from pipeline" 'echo "a:b:c" | { IFS=: read A B C; echo "$A $B $C"; }' |
| 29 | |
| 30 | section "3. builtins mid-pipeline" |
| 31 | compare_output "builtin mid-pipeline sort head" 'echo -e "b\na\nc" | sort | head -1' |
| 32 | compare_output "echo tr wc chain" 'echo "hello world" | tr a-z A-Z | wc -c | tr -d " "' |
| 33 | compare_output "printf sort tail chain" 'printf "%d\n" 5 1 3 2 4 | sort -n | tail -1' |
| 34 | compare_output "command substitution in pipeline" 'echo $(echo hello) | tr a-z A-Z' |
| 35 | |
| 36 | section "4. pipeline exit status" |
| 37 | compare_output "last cmd status true" 'false | true; echo $?' |
| 38 | compare_output "last cmd status false" 'true | false; echo $?' |
| 39 | compare_output "pipefail first fails" 'set -o pipefail; false | true; echo $?' |
| 40 | compare_output "pipefail middle fails" 'set -o pipefail; true | false | true; echo $?' |
| 41 | compare_output "pipefail all succeed" 'set -o pipefail; true | true; echo $?' |
| 42 | compare_output "negated pipeline" '! true; echo $?' |
| 43 | compare_output "negated pipeline false" '! false; echo $?' |
| 44 | compare_output "PIPESTATUS basic" 'true | false | true; echo ${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]}' |
| 45 | compare_output "PIPESTATUS all zero" 'true | true | true; echo ${PIPESTATUS[@]}' |
| 46 | |
| 47 | section "5. pipeline subshell semantics" |
| 48 | compare_output "var set in pipeline doesnt leak" 'X=before; echo y | read X; echo $X' |
| 49 | compare_output "cd in pipeline doesnt affect parent" 'cd /tmp | cat; pwd' |
| 50 | # Filter out non-deterministic "Broken pipe" errors from comparison |
| 51 | TEST_NUM=$((TEST_NUM + 1)) |
| 52 | _pp_expected=$(run_with_timeout "$TEST_TIMEOUT" "$BASH_REF" -c 'echo test | { export PVAR=pipe; echo $PVAR; }; echo ${PVAR:-unset}' 2>&1 | grep -v 'Broken pipe') |
| 53 | _pp_actual=$(run_with_timeout "$TEST_TIMEOUT" "$FORTSH_BIN" -c 'echo test | { export PVAR=pipe; echo $PVAR; }; echo ${PVAR:-unset}' 2>&1 | grep -v 'Broken pipe') |
| 54 | if [ "$_pp_expected" = "$_pp_actual" ]; then pass "export in pipeline segment" |
| 55 | else fail "export in pipeline segment" "$_pp_expected" "$_pp_actual"; fi |
| 56 | compare_output "cmd sub in pipeline" 'echo "$(echo hello)" | tr h H' |
| 57 | compare_output "subshell in pipeline" '(echo from_sub) | tr a-z A-Z' |
| 58 | |
| 59 | section "6. pipeline edge cases" |
| 60 | compare_output "empty pipeline source" 'echo -n "" | wc -c | tr -d " "' |
| 61 | compare_output "large data through pipeline" 'printf "%0100s\n" | wc -c | tr -d " "' |
| 62 | compare_output "multiple echo into pipeline" '{ echo a; echo b; echo c; } | sort -r' |
| 63 | compare_output "pipeline with command group" '{ echo 1; echo 2; } | { while read n; do echo "got:$n"; done; }' |
| 64 | compare_output "pipeline preserves whitespace" 'echo " hello " | cat' |
| 65 | compare_output "pipeline with exit in subshell" '(echo before; exit 0; echo after) | cat' |
| 66 | |
| 67 | print_summary |