Bash · 5661 bytes Raw Blame History
1 #!/bin/sh
2 TEST_PREFIX="[int-control-flow]"
3 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4 SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5 export SHELL_BIN
6 . "$SCRIPT_DIR/../test_harness.sh"
7
8 # Integration tests: builtins in loops, conditionals, and control flow
9
10 section "1. builtins as loop conditions"
11 compare_output "while read as condition" 'printf "a\nb\nc\n" | while read line; do echo "got:$line"; done'
12 compare_output "while test as condition" 'i=0; while test $i -lt 3; do echo $i; i=$((i+1)); done'
13 compare_output "while bracket as condition" 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done'
14 compare_output "until test as condition" 'i=0; until test $i -ge 3; do echo $i; i=$((i+1)); done'
15 compare_output "until bracket as condition" 'i=0; until [ $i -ge 3 ]; do echo $i; i=$((i+1)); done'
16 compare_output "while true with break" 'i=0; while true; do i=$((i+1)); [ $i -ge 3 ] && break; echo $i; done'
17 compare_output "while command as condition" 'echo -e "a\nb" > /tmp/test_cf_$$; while read line; do echo $line; done < /tmp/test_cf_$$; rm -f /tmp/test_cf_$$'
18
19 section "2. break and continue"
20 compare_output "basic break" 'for i in 1 2 3 4 5; do echo $i; test $i -eq 3 && break; done'
21 compare_output "basic continue" 'for i in 1 2 3 4 5; do test $i -eq 3 && continue; echo $i; done'
22 compare_output "break in nested for - inner" 'for i in 1 2; do for j in a b c; do [ $j = b ] && break; echo $i$j; done; done'
23 compare_output "continue in nested for" 'for i in 1 2; do for j in a b c; do [ $j = b ] && continue; echo $i$j; done; done'
24 compare_output "break 2 exits both loops" 'for i in 1 2; do for j in a b; do [ $i = 2 ] && break 2; echo $i$j; done; done'
25 compare_output "continue 2 skips outer" 'for i in 1 2 3; do for j in a b; do [ $i = 2 ] && continue 2; echo $i$j; done; done'
26 compare_output "break in while" 'i=0; while true; do i=$((i+1)); [ $i -gt 3 ] && break; echo $i; done'
27 compare_output "continue in while" 'i=0; while [ $i -lt 5 ]; do i=$((i+1)); [ $i -eq 3 ] && continue; echo $i; done'
28
29 section "3. if/elif with builtins"
30 compare_output "if test gt" 'if test 5 -gt 3; then echo yes; fi'
31 compare_output "if bracket dir" 'if [ -d /tmp ]; then echo dir; fi'
32 compare_output "if double bracket glob" 'if [[ "hello" == h* ]]; then echo match; fi'
33 compare_output "if command -v" 'if command -v ls >/dev/null; then echo found; fi'
34 compare_output "elif chain" 'X=2; if [ $X -eq 1 ]; then echo one; elif [ $X -eq 2 ]; then echo two; else echo other; fi'
35 compare_output "triple elif" 'X=3; if [ $X -eq 1 ]; then echo one; elif [ $X -eq 2 ]; then echo two; elif [ $X -eq 3 ]; then echo three; else echo other; fi'
36 compare_output "if false elif false else" 'if false; then echo no; elif false; then echo no2; else echo default; fi'
37 compare_output "if type builtin" 'if type echo >/dev/null 2>&1; then echo builtin; fi'
38 compare_output "if with negation" 'if ! false; then echo negated; fi'
39
40 section "4. case with builtins"
41 compare_output "case with echo result" 'X=hello; case $X in h*) echo starts_h;; *) echo other;; esac'
42 compare_output "case with cmd sub" 'case $(echo hello) in h*) echo match;; esac'
43 compare_output "case on exit status" 'true; case $? in 0) echo ok;; *) echo fail;; esac'
44 compare_output "case multiple patterns" 'X=banana; case $X in apple|pear) echo fruit1;; banana|grape) echo fruit2;; esac'
45 compare_output "case with variable" 'PAT=hello; case $PAT in hello) echo matched;; esac'
46 compare_output "case fallthrough default" 'X=unknown; case $X in a) echo a;; b) echo b;; *) echo default;; esac'
47
48 section "5. compound conditions"
49 compare_output "and chain both true" 'test -d /tmp && test -d /var && echo both'
50 compare_output "or chain first false" 'false || echo fallback'
51 compare_output "and-or chain" 'true && false || echo recovered'
52 compare_output "negation" '! false && echo negated'
53 compare_output "double negation" '! ! true; echo $?'
54 compare_output "complex condition" '[ -d /tmp ] && [ -d /var ] || echo missing'
55 compare_output "grouped conditions" '{ true && true; } && echo both'
56
57 section "6. builtins in loops"
58 compare_output "for in list" 'for i in 1 2 3; do echo $i; done'
59 compare_output "for with cmd sub in list" 'for f in $(echo a b c); do echo $f; done'
60 compare_output "c-style for" 'for ((i=0; i<3; i++)); do echo $i; done'
61 compare_output "echo in while loop" 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done'
62 compare_output "variable survives non-pipeline loop" 'i=0; while [ $i -lt 3 ]; do i=$((i+1)); done; echo $i'
63 compare_output "read loop from heredoc" 'while read line; do echo "got:$line"; done <<EOF
64 x
65 y
66 z
67 EOF'
68 compare_output "for with brace expansion" 'for i in {1..5}; do echo $i; done'
69 compare_output "for with glob" "touch $TEST_TMPDIR/cf_a.txt $TEST_TMPDIR/cf_b.txt; for f in $TEST_TMPDIR/cf_*.txt; do basename \$f; done | sort"
70
71 section "7. loop exit status"
72 compare_output "exit status from loop body" 'for cmd in true false true; do $cmd; echo $?; done'
73 compare_output "while false never runs" 'while false; do echo never; done; echo $?'
74 compare_output "for loop exit status" 'for i in 1; do true; done; echo $?'
75 compare_output "for loop last cmd status" 'for i in 1; do false; done; echo $?'
76
77 section "8. nested control flow"
78 compare_output "if inside for" 'for i in 1 2 3; do if [ $i -eq 2 ]; then echo even; else echo odd; fi; done'
79 compare_output "for inside if" 'if true; then for i in 1 2; do echo $i; done; fi'
80 compare_output "while inside for" 'for i in 1 2; do j=0; while [ $j -lt 2 ]; do echo "$i.$j"; j=$((j+1)); done; done'
81 compare_output "case inside for" 'for x in a b c; do case $x in a) echo first;; b) echo second;; *) echo other;; esac; done'
82
83 print_summary