metadata: category: Gaps description: Tests converted from POSIX compliance suite auto_generated: true needs_review: Tests with MANUAL_REVIEW need expected output verification tests: - name: '92. REDIRECTION OPERATOR <> (READ/WRITE): redirect <> creates file (exit code)' steps: - send_line: echo test <> /tmp/posix_gaps_rw_$$; test -f /tmp/posix_gaps_rw_$$; rm -f /tmp/posix_gaps_rw_$$ - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '92. REDIRECTION OPERATOR <> (READ/WRITE): redirect <> opens existing (exit code)' steps: - send_line: echo data > /tmp/posix_gaps_rw2_$$; cat <> /tmp/posix_gaps_rw2_$$ 2>/dev/null; rm -f /tmp/posix_gaps_rw2_$$ - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '93. COMPLEX IFS FIELD SPLITTING: IFS mixed ws and non-ws' steps: - send_line: 'IFS='': \t''; VAR=''a:b c:d''; set -- $VAR; echo $# $1 $2 $3 $4' expect_output: '4' match_type: contains auto_fixed: shell_execution - name: '93. COMPLEX IFS FIELD SPLITTING: IFS multiple delimiters' steps: - send_line: IFS=',:'; VAR='a,b:c,d'; set -- $VAR; echo $# expect_output: '4' match_type: contains auto_fixed: shell_execution - name: '93. COMPLEX IFS FIELD SPLITTING: IFS trailing delimiters' steps: - send_line: IFS=:; VAR='a:b:c:'; set -- $VAR; echo $# expect_output: '3' match_type: contains auto_fixed: shell_execution - name: '93. COMPLEX IFS FIELD SPLITTING: IFS leading and trailing' steps: - send_line: IFS=:; VAR=':a:b:'; set -- $VAR; echo $# $1 $2 expect_output: '3' match_type: contains auto_fixed: shell_execution - name: '93. COMPLEX IFS FIELD SPLITTING: IFS consecutive delimiters' steps: - send_line: IFS=:; VAR='a::b'; set -- $VAR; echo $# $1 $2 $3 expect_output: '3' match_type: contains auto_fixed: shell_execution - name: '93. COMPLEX IFS FIELD SPLITTING: IFS whitespace collapsing' steps: - send_line: IFS=' '; VAR='a b c'; set -- $VAR; echo $# expect_output: '3' match_type: contains auto_fixed: shell_execution - name: '93. COMPLEX IFS FIELD SPLITTING: IFS null splits nothing' steps: - send_line: IFS=''; VAR='a b c'; set -- $VAR; echo $# expect_output: '1' match_type: contains auto_fixed: shell_execution - name: '94. NESTED PARAMETER EXPANSION: nested default expansion' steps: - send_line: unset A; B=inner; echo ${A:-${B}} expect_output: inner match_type: contains auto_fixed: shell_execution - name: '94. NESTED PARAMETER EXPANSION: nested length expansion' steps: - send_line: VAR=hello; echo ${#VAR} expect_output: '5' match_type: contains auto_fixed: shell_execution - name: '94. NESTED PARAMETER EXPANSION: nested pattern removal' steps: - send_line: VAR=/usr/local/bin; echo ${VAR#${VAR%/*}} expect_output: /bin match_type: contains auto_fixed: shell_execution - name: '94. NESTED PARAMETER EXPANSION: multiple parameter expansions' steps: - send_line: A=foo; B=bar; echo ${A}${B} expect_output: foobar match_type: contains auto_fixed: shell_execution - name: '94. NESTED PARAMETER EXPANSION: nested with quotes' steps: - send_line: A='a b'; echo "${A:-default}" expect_output: a b match_type: contains - name: '95. COMMAND NAME RESOLUTION ORDER: function overrides echo' steps: - send_line: echo() { printf 'function\n'; }; echo test | grep -c function expect_output: '1' match_type: contains - name: '95. COMMAND NAME RESOLUTION ORDER: command -v finds function' steps: - send_line: func() { :; }; command -v func | grep -c func expect_output: '[0-9]+' match_type: regex - name: '95. COMMAND NAME RESOLUTION ORDER: command bypasses function' steps: - send_line: echo() { printf 'func\n'; }; command echo test expect_output: test match_type: contains auto_fixed: shell_execution - name: '95. COMMAND NAME RESOLUTION ORDER: unset function reveals builtin' steps: - send_line: echo() { printf 'f\n'; }; unset -f echo; echo test | grep -c test expect_output: '1' match_type: contains - name: '96. COMPLEX QUOTING AND ESCAPING: backslash in double quotes' steps: - send_line: echo "test\\nword" expect_output: test\\nword match_type: contains - name: '96. COMPLEX QUOTING AND ESCAPING: dollar in double quotes' steps: - send_line: "echo 'price: $5'" expect_output: 'price:' match_type: contains - name: '96. COMPLEX QUOTING AND ESCAPING: backtick in double quotes' steps: - send_line: 'echo "date: `date +%Y`" | grep -c date' expect_output: '1' match_type: contains - name: '96. COMPLEX QUOTING AND ESCAPING: mixed quoting' steps: - send_line: echo 'single'"double" expect_output: singledouble match_type: contains - name: '96. COMPLEX QUOTING AND ESCAPING: empty quotes concatenation' steps: - send_line: echo ''test'' expect_output: test match_type: contains - name: '96. COMPLEX QUOTING AND ESCAPING: quote removal' steps: - send_line: VAR="\"test\""; echo $VAR expect_output: '"test"' match_type: contains - name: '97. PIPELINE EXIT STATUS: pipeline last command status (exit code)' steps: - send_line: true | true | false - send_line: echo "EXIT=$?" expect_output: EXIT=1 match_type: contains - name: '97. PIPELINE EXIT STATUS: pipeline first fails (exit code)' steps: - send_line: false | true | true - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '97. PIPELINE EXIT STATUS: pipeline middle fails (exit code)' steps: - send_line: true | false | true - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '97. PIPELINE EXIT STATUS: PIPESTATUS concept' steps: - send_line: false | true | true; echo $? expect_output: '0' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic negative numbers' steps: - send_line: echo $((-5 * -3)) expect_output: '15' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic large numbers' steps: - send_line: echo $((999999 + 1)) expect_output: '1000000' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic modulo negative' steps: - send_line: echo $((-17 % 5)) expect_output: '-2' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic nested parens' steps: - send_line: echo $(((2 + 3) * (4 + 5))) expect_output: '45' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic comparison chain' steps: - send_line: echo $((5 > 3 && 10 > 8)) expect_output: '1' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic unary minus' steps: - send_line: X=5; echo $((-X)) expect_output: '-5' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic unary plus' steps: - send_line: X=5; echo $((+X)) expect_output: '5' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic octal numbers' steps: - send_line: echo $((010)) expect_output: '8' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic hex numbers' steps: - send_line: echo $((0x10)) expect_output: '16' match_type: contains auto_fixed: shell_execution - name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic division by zero (exit code)' steps: - send_line: echo $((5 / 0)) 2>/dev/null - send_line: echo "EXIT=$?" expect_output: EXIT=1 match_type: contains - name: '99. PATHNAME EXPANSION EDGE CASES: glob bracket literal' steps: - send_line: ls /tmp/posix_gaps_test_glob/file[[]3].txt 2>/dev/null | wc -l expect_output: '[0-9]+' match_type: regex - name: '99. PATHNAME EXPANSION EDGE CASES: glob dash in bracket' steps: - send_line: ls /tmp/posix_gaps_test_glob/[-a-z]file.txt 2>/dev/null | wc -l expect_output: '[0-9]+' match_type: regex - name: '99. PATHNAME EXPANSION EDGE CASES: glob no match returns literal' steps: - send_line: echo /tmp/posix_gaps_test_glob/*.xyz | grep -c '\*' expect_output: '1' match_type: contains - name: '99. PATHNAME EXPANSION EDGE CASES: glob hidden dirs' steps: - send_line: ls -d /tmp/posix_gaps_test_glob/.* 2>/dev/null | grep -c hidden expect_output: '[0-9]+' match_type: regex - name: '99. PATHNAME EXPANSION EDGE CASES: glob character class digit' steps: - send_line: touch /tmp/posix_gaps_test_glob/f1.txt; ls /tmp/posix_gaps_test_glob/f[[:digit:]].txt 2>/dev/null | wc -l expect_output: '[0-9]+' match_type: regex - name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: function local scope via subshell' steps: - send_line: f() { (X=inner; echo $X); }; X=outer; f; echo $X expect_output: inner match_type: contains - name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: function positional params' steps: - send_line: f() { echo $1 $2; }; set -- a b; f x y expect_output: x y match_type: contains - name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: function preserves positional' steps: - send_line: f() { echo $1; }; set -- a b; f x; echo $1 expect_output: 'x' match_type: contains - name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: nested function calls' steps: - send_line: a() { b; }; b() { c; }; c() { echo deep; }; a expect_output: deep match_type: contains auto_fixed: shell_execution - name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: function return in subshell' steps: - send_line: f() { (return 5); echo $?; }; f expect_output: '5' match_type: contains - name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: recursive factorial' steps: - send_line: fact() { if [ $1 -le 1 ]; then echo 1; else local r=$(fact $(($1-1)) 2>/dev/null || fact $(($1-1))); echo $(($1 * r)); fi; }; fact 4 expect_output: '24' match_type: contains auto_fixed: shell_execution - name: '101. EXIT STATUS IN COMPOUND COMMANDS: subshell exit status (exit code)' steps: - send_line: (exit 42); echo $? - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '101. EXIT STATUS IN COMPOUND COMMANDS: brace group exit status (exit code)' steps: - send_line: '{ false; }; echo $?' - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '101. EXIT STATUS IN COMPOUND COMMANDS: if statement exit status (exit code)' steps: - send_line: if true; then true; fi; echo $? - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '101. EXIT STATUS IN COMPOUND COMMANDS: for loop exit status (exit code)' steps: - send_line: for i in 1; do false; done; echo $? - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '101. EXIT STATUS IN COMPOUND COMMANDS: while loop exit status (exit code)' steps: - send_line: while false; do :; done; echo $? - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '101. EXIT STATUS IN COMPOUND COMMANDS: case exit status (exit code)' steps: - send_line: case x in x) false;; esac; echo $? - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '102. SET BUILTIN EDGE CASES: set -- clears positionals' steps: - send_line: set -- a b; set --; echo $# expect_output: '0' match_type: contains - name: '102. SET BUILTIN EDGE CASES: set -- with empty' steps: - send_line: set -- ''; echo $# |$1| expect_output: 1 || match_type: contains auto_fixed: manual_determination - name: '102. SET BUILTIN EDGE CASES: set -- with spaces' steps: - send_line: set -- 'a b' 'c d'; echo $1 expect_output: '''a' match_type: contains auto_fixed: shell_execution - name: '102. SET BUILTIN EDGE CASES: set without args shows vars' steps: - send_line: X=1; set | grep -c '^X=' expect_output: '[0-9]+' match_type: regex - name: '102. SET BUILTIN EDGE CASES: set -o lists options' steps: - send_line: set -o 2>&1 | wc -l expect_output: '[0-9]+' match_type: regex - name: '103. SHIFT EDGE CASES: shift with count' steps: - send_line: set -- a b c d e; shift 3; echo $1 expect_output: 'd' match_type: contains - name: '103. SHIFT EDGE CASES: shift too many (exit code)' steps: - send_line: set -- a b; shift 5 2>/dev/null - send_line: echo "EXIT=$?" expect_output: EXIT=1 match_type: contains - name: '103. SHIFT EDGE CASES: shift zero' steps: - send_line: set -- a b c; shift 0; echo $# expect_output: '3' match_type: contains - name: '103. SHIFT EDGE CASES: shift all' steps: - send_line: set -- a b c; shift 3; echo $# expect_output: '0' match_type: contains - name: '103. SHIFT EDGE CASES: shift with no args (exit code)' steps: - send_line: set --; shift 2>/dev/null - send_line: echo "EXIT=$?" expect_output: EXIT=1 match_type: contains - name: '104. EVAL EDGE CASES: eval with semicolons' steps: - send_line: eval 'echo a; echo b' | wc -l expect_output: '2' match_type: contains - name: '104. EVAL EDGE CASES: eval with pipes' steps: - send_line: eval 'echo test | cat' expect_output: test match_type: contains auto_fixed: shell_execution - name: '104. EVAL EDGE CASES: eval with redirects' steps: - send_line: eval 'echo test > /tmp/posix_gaps_eval_$$'; cat /tmp/posix_gaps_eval_$$; rm -f /tmp/posix_gaps_eval_$$ expect_output: test match_type: contains auto_fixed: shell_execution - name: '104. EVAL EDGE CASES: eval double expansion' steps: - send_line: VAR='echo $HOME'; eval $VAR | grep -c / expect_output: '[0-9]+' match_type: regex - name: '104. EVAL EDGE CASES: eval empty string' steps: - send_line: eval ''; echo ok expect_output: ok match_type: contains - name: '104. EVAL EDGE CASES: nested eval' steps: - send_line: eval eval echo nested expect_output: nested match_type: contains auto_fixed: shell_execution - name: '105. READONLY AND UNSET INTERACTIONS: readonly then unset fails (exit code)' steps: - send_line: readonly X=1; unset X 2>/dev/null - send_line: echo "EXIT=$?" expect_output: EXIT=1 match_type: contains - name: '105. READONLY AND UNSET INTERACTIONS: export readonly (exit code)' steps: - send_line: readonly XP=1; export XP; sh -c 'echo $XP' | grep -c 1 - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '105. READONLY AND UNSET INTERACTIONS: readonly in subshell' steps: - send_line: (readonly Y=2; echo $Y); readonly | grep -c Y || echo 0 expect_output: '[0-9]+' match_type: regex - name: '106. RETURN BUILTIN EDGE CASES: return without function' steps: - send_line: return 2>/dev/null || echo ok expect_output: ok match_type: contains auto_fixed: shell_execution - name: '106. RETURN BUILTIN EDGE CASES: return value preserved' steps: - send_line: f() { return 42; }; f; echo $? expect_output: '42' match_type: contains - name: '106. RETURN BUILTIN EDGE CASES: return in sourced script' steps: - send_line: echo 'return 7' > /tmp/posix_gaps_source_$$; . /tmp/posix_gaps_source_$$ 2>/dev/null || echo $?; rm -f /tmp/posix_gaps_source_$$ expect_output: '7' match_type: contains - name: '107. DOT (.) BUILTIN EDGE CASES: source with PATH search' steps: - send_line: echo 'echo sourced' > /tmp/posix_gaps_dot_$$; PATH=/tmp:$PATH; . posix_gaps_dot_$$ 2>/dev/null || echo 'not found'; rm -f /tmp/posix_gaps_dot_$$ expect_output: sourced match_type: contains auto_fixed: shell_execution - name: '107. DOT (.) BUILTIN EDGE CASES: source nonexistent (exit code)' steps: - send_line: . /tmp/posix_gaps_nonexistent_$$ 2>/dev/null - send_line: echo "EXIT=$?" expect_output: EXIT=1 match_type: contains - name: '107. DOT (.) BUILTIN EDGE CASES: source preserves variables' steps: - send_line: echo 'A=from_source' > /tmp/posix_gaps_dot2_$$; . /tmp/posix_gaps_dot2_$$; echo $A; rm -f /tmp/posix_gaps_dot2_$$ expect_output: from_source match_type: contains - name: '108. BREAK AND CONTINUE EDGE CASES: break with level 0' steps: - send_line: for i in 1 2; do break 0 2>/dev/null || break; echo $i; done || echo ok expect_output: ok match_type: contains auto_fixed: shell_execution - name: '108. BREAK AND CONTINUE EDGE CASES: break level too high' steps: - send_line: for i in 1 2; do break 10 2>/dev/null || break; echo $i; done || echo done expect_output: '' match_type: exact - name: '108. BREAK AND CONTINUE EDGE CASES: continue with level' steps: - send_line: for i in 1 2; do for j in a b; do continue 2 2>/dev/null || continue; echo $i$j; done; done || echo ok expect_output: '' match_type: exact - name: '108. BREAK AND CONTINUE EDGE CASES: break outside loop' steps: - send_line: break 2>/dev/null || echo ok expect_output: ok match_type: contains auto_fixed: manual_determination - name: '108. BREAK AND CONTINUE EDGE CASES: continue outside loop' steps: - send_line: continue 2>/dev/null || echo ok expect_output: ok match_type: contains auto_fixed: manual_determination - name: '109. CASE STATEMENT EDGE CASES: case empty pattern' steps: - send_line: x=''; case $x in '') echo empty;; esac expect_output: empty match_type: contains auto_fixed: shell_execution - name: '109. CASE STATEMENT EDGE CASES: case no match' steps: - send_line: x=z; case $x in a) echo a;; b) echo b;; esac; echo ok expect_output: ok match_type: contains - name: '109. CASE STATEMENT EDGE CASES: case with quotes' steps: - send_line: x='a b'; case $x in 'a b') echo match;; esac expect_output: match match_type: contains auto_fixed: shell_execution - name: '109. CASE STATEMENT EDGE CASES: case glob vs literal' steps: - send_line: x='*'; case $x in '*') echo literal;; esac expect_output: literal match_type: contains auto_fixed: shell_execution - name: '109. CASE STATEMENT EDGE CASES: case bracket range' steps: - send_line: x=b; case $x in [a-c]) echo range;; esac expect_output: range match_type: contains auto_fixed: shell_execution - name: '109. CASE STATEMENT EDGE CASES: case multiple patterns order' steps: - send_line: x=a; case $x in a|b) echo first;; a) echo second;; esac expect_output: first match_type: contains auto_fixed: shell_execution - name: '109. CASE STATEMENT EDGE CASES: case with variable pattern' steps: - send_line: P='a*'; x=abc; case $x in $P) echo var_pattern;; esac expect_output: var_pattern match_type: contains auto_fixed: shell_execution - name: '110. FOR LOOP EDGE CASES: for empty word list' steps: - send_line: for i in; do echo $i; done; echo empty expect_output: empty match_type: contains - name: '110. FOR LOOP EDGE CASES: for single item' steps: - send_line: for i in one; do echo $i; done expect_output: one match_type: contains - name: '110. FOR LOOP EDGE CASES: for with glob expansion' steps: - send_line: touch /tmp/posix_gaps_for{1,2,3}_$$.txt 2>/dev/null; for f in /tmp/posix_gaps_for*_$$.txt; do test -f $f && echo yes; done | head -1; rm -f /tmp/posix_gaps_for*_$$.txt expect_output: 'yes' match_type: contains auto_fixed: shell_execution - name: '110. FOR LOOP EDGE CASES: for preserves IFS' steps: - send_line: IFS=:; for i in a b c; do echo $i; done; echo $IFS | od -A n -t x1 | grep -c 3a expect_output: '1' match_type: contains auto_fixed: manual_determination - name: '111. WHILE AND UNTIL EDGE CASES: while true with break' steps: - send_line: i=0; while true; do i=$((i+1)); test $i -eq 3 && break; done; echo $i expect_output: '3' match_type: contains auto_fixed: shell_execution - name: '111. WHILE AND UNTIL EDGE CASES: until false with break' steps: - send_line: i=0; until false; do i=$((i+1)); test $i -eq 3 && break; done; echo $i expect_output: '3' match_type: contains auto_fixed: shell_execution - name: '111. WHILE AND UNTIL EDGE CASES: while with exit status' steps: - send_line: i=5; while [ $i -gt 0 ]; do i=$((i-1)); done; echo $? expect_output: '0' match_type: contains auto_fixed: shell_execution - name: '111. WHILE AND UNTIL EDGE CASES: until with complex condition' steps: - send_line: i=0; until [ $i -gt 3 ] && [ $i -lt 10 ]; do i=$((i+1)); done; echo $i expect_output: '4' match_type: contains auto_fixed: shell_execution - name: '112. SUBSHELL VARIABLE ISOLATION: subshell doesnt modify parent' steps: - send_line: (X=inner); echo ${X:-unset} expect_output: unset match_type: contains - name: '112. SUBSHELL VARIABLE ISOLATION: subshell inherits variables' steps: - send_line: X=outer; (echo $X) expect_output: outer match_type: contains - name: '112. SUBSHELL VARIABLE ISOLATION: nested subshells' steps: - send_line: X=1; (X=2; (X=3; echo $X); echo $X); echo $X expect_output: '3' match_type: contains - name: '112. SUBSHELL VARIABLE ISOLATION: subshell with exports' steps: - send_line: export X=exp; (X=inner; echo $X); echo $X expect_output: inner match_type: contains - name: '113. BRACE GROUP SCOPING: brace group modifies parent' steps: - send_line: X=1; { X=2; }; echo $X expect_output: '2' match_type: contains - name: '113. BRACE GROUP SCOPING: brace group with redirects' steps: - send_line: '{ echo a; echo b; } | wc -l' expect_output: '[0-9]+' match_type: regex - name: '113. BRACE GROUP SCOPING: nested brace groups' steps: - send_line: X=1; { { X=2; }; echo $X; }; echo $X expect_output: '2' match_type: contains - name: '114. ALIAS EDGE CASES: alias with args' steps: - send_line: alias ll='ls -l'; alias ll | grep -c 'ls -l' expect_output: '[0-9]+' match_type: regex - name: '114. ALIAS EDGE CASES: alias recursive prevention' steps: - send_line: alias ls='ls -a'; command ls /tmp >/dev/null; echo $? expect_output: '0' match_type: contains - name: '114. ALIAS EDGE CASES: unalias nonexistent' steps: - send_line: unalias nonexistent_alias_$$ 2>/dev/null || echo ok expect_output: ok match_type: contains auto_fixed: shell_execution - name: '114. ALIAS EDGE CASES: alias name same as builtin' steps: - send_line: alias echo='printf'; unalias echo; command -v echo | grep -c echo expect_output: '[0-9]+' match_type: regex - name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test complex AND/OR (exit code)' steps: - send_line: test 5 -gt 3 -a \( 10 -lt 20 -o 1 -eq 2 \) - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test negation precedence (exit code)' steps: - send_line: test ! 5 -gt 10 - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test string empty (exit code)' steps: - send_line: test -z '' - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test string nonempty (exit code)' steps: - send_line: test -n 'x' - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test string unary (exit code)' steps: - send_line: test 'nonempty' - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '116. SPECIAL PARAMETER EDGE CASES: \$@ with IFS' steps: - send_line: 'IFS=:; set -- a b c; echo "$@"' expect_output: 'a b c' match_type: contains - name: '116. SPECIAL PARAMETER EDGE CASES: \$* vs \$@ unquoted' steps: - send_line: set -- a b c; for x in $*; do echo $x; done | wc -l expect_output: '[0-9]+' match_type: regex - name: '116. SPECIAL PARAMETER EDGE CASES: \$@ quoted iteration' steps: - send_line: 'set -- "a b" "c d"; for x in "$@"; do echo "$x"; done | wc -l' expect_output: '2' match_type: contains - name: '116. SPECIAL PARAMETER EDGE CASES: \$# after shift' steps: - send_line: set -- a b c; shift; echo $# expect_output: '2' match_type: contains - name: '116. SPECIAL PARAMETER EDGE CASES: \$- shows options' steps: - send_line: echo $- | grep -c '[a-z]' expect_output: '1' match_type: contains auto_fixed: shell_execution - name: '116. SPECIAL PARAMETER EDGE CASES: \$\$ is numeric' steps: - send_line: echo $$ | grep -c '^[0-9]*$' expect_output: '1' match_type: contains auto_fixed: shell_execution - name: '116. SPECIAL PARAMETER EDGE CASES: \$! after background' steps: - send_line: sleep 0.1 & echo $! | grep -c '^[0-9]*$' expect_output: '[0-9]+' match_type: regex - name: '117. TILDE EXPANSION EDGE CASES: tilde in assignment' steps: - send_line: VAR=~/test; echo $VAR | grep -c '^/' expect_output: '1' match_type: contains - name: '117. TILDE EXPANSION EDGE CASES: tilde in middle no expand' steps: - send_line: echo a~b | grep -c '~' expect_output: '1' match_type: contains - name: '117. TILDE EXPANSION EDGE CASES: tilde in quotes no expand' steps: - send_line: echo '~' | grep -c '~' expect_output: '1' match_type: contains - name: '118. COMMAND SUBSTITUTION EDGE CASES: command subst nested' steps: - send_line: echo $(echo $(echo nested)) expect_output: nested match_type: contains auto_fixed: shell_execution - name: '118. COMMAND SUBSTITUTION EDGE CASES: command subst with pipes' steps: - send_line: echo $(echo a | cat) expect_output: a match_type: contains auto_fixed: shell_execution - name: '118. COMMAND SUBSTITUTION EDGE CASES: command subst multiline' steps: - send_line: 'result=$(echo a; echo b); echo "$result"' expect_output: 'a' match_type: contains - name: '118. COMMAND SUBSTITUTION EDGE CASES: command subst empty' steps: - send_line: 'x=$(true); echo "len=${#x}"' expect_output: 'len=0' match_type: contains - name: '118. COMMAND SUBSTITUTION EDGE CASES: backtick vs dollar-paren' steps: - send_line: 'a=`echo test`; b=$(echo test); test "$a" = "$b" && echo same' expect_output: 'same' match_type: contains - name: '119. REDIRECT EDGE CASES: redirect order matters' steps: - send_line: echo test 2>&1 >/dev/null | wc -l expect_output: '0' match_type: contains - name: '119. REDIRECT EDGE CASES: redirect to same fd' steps: - send_line: echo test >&1 2>&1 expect_output: test match_type: contains - name: '119. REDIRECT EDGE CASES: redirect append' steps: - send_line: echo a > /tmp/posix_gaps_redir_$$; echo b >> /tmp/posix_gaps_redir_$$; wc -l < /tmp/posix_gaps_redir_$$; rm -f /tmp/posix_gaps_redir_$$ expect_output: '2' match_type: contains auto_fixed: shell_execution - name: '120. WAIT BUILTIN EDGE CASES: wait for background job (exit code)' steps: - send_line: '(sleep 0.01 & pid=$!; wait $pid; echo EXIT=$?)' expect_output: EXIT=0 match_type: contains - name: '120. WAIT BUILTIN EDGE CASES: wait all jobs (exit code)' steps: - send_line: '(sleep 0.01 & sleep 0.01 & wait; echo EXIT=$?)' expect_output: EXIT=0 match_type: contains - name: '120. WAIT BUILTIN EDGE CASES: wait nonexistent PID (exit code)' steps: - send_line: wait 9999999 2>/dev/null - send_line: echo "EXIT=$?" expect_output: EXIT=127 match_type: contains - name: '120. WAIT BUILTIN EDGE CASES: wait preserves exit status' steps: - send_line: sh -c 'exit 42' & pid=$!; wait $pid; echo $? expect_output: '42' match_type: contains - name: '121. GETOPTS COMPREHENSIVE: getopts basic' steps: - send_line: set -- -a test; getopts 'a:' opt; echo $opt expect_output: 'a' match_type: contains - name: '121. GETOPTS COMPREHENSIVE: getopts OPTARG' steps: - send_line: set -- -a value; getopts 'a:' opt; echo $OPTARG expect_output: 'value' match_type: contains - name: '121. GETOPTS COMPREHENSIVE: getopts OPTIND' steps: - send_line: set -- -a -b; getopts 'ab' opt; echo $OPTIND expect_output: '2' match_type: contains - name: '121. GETOPTS COMPREHENSIVE: getopts invalid option' steps: - send_line: set -- -z; getopts 'ab' opt 2>/dev/null; echo $opt | grep -c '?' expect_output: '1' match_type: contains auto_fixed: shell_execution - name: '122. UMASK EDGE CASES: umask get' steps: - send_line: umask | grep -c '^[0-9]*$' expect_output: '[0-9]+' match_type: regex - name: '122. UMASK EDGE CASES: umask set and get' steps: - send_line: old=$(umask); umask 022; umask; umask $old | head -1 expect_output: '0022' match_type: contains auto_fixed: shell_execution - name: '123. HASH BUILTIN EDGE CASES: hash command (exit code)' steps: - send_line: hash echo 2>/dev/null - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '123. HASH BUILTIN EDGE CASES: hash -r clears (exit code)' steps: - send_line: hash -r - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '123. HASH BUILTIN EDGE CASES: hash nonexistent' steps: - send_line: hash nonexistent_cmd_$$ 2>&1 | grep -c 'not found\\|hash' expect_output: '[0-9]+' match_type: regex - name: '124. TYPE BUILTIN EDGE CASES: type builtin' steps: - send_line: type echo | grep -ci 'builtin\\|built-in\\|shell builtin' expect_output: '[0-9]+' match_type: regex - name: '124. TYPE BUILTIN EDGE CASES: type function' steps: - send_line: f() { :; }; type f | grep -c function expect_output: '[0-9]+' match_type: regex - name: '124. TYPE BUILTIN EDGE CASES: type external' steps: - send_line: type cat | grep -c '/' expect_output: '[0-9]+' match_type: regex - name: '124. TYPE BUILTIN EDGE CASES: type nonexistent (exit code)' steps: - send_line: type nonexistent_$$ 2>/dev/null - send_line: echo "EXIT=$?" expect_output: EXIT=1 match_type: contains - name: '125. TIMES BUILTIN: times output format' steps: - send_line: times | wc -l expect_output: '[0-9]+' match_type: regex - name: '125. TIMES BUILTIN: times exit status (exit code)' steps: - send_line: times >/dev/null - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '126. TRAP SIGNAL EDGE CASES: trap with signal number' steps: - send_line: trap 'echo sig' 15; trap | grep -c 15 expect_output: '[0-9]+' match_type: regex - name: '126. TRAP SIGNAL EDGE CASES: trap with multiple signals' steps: - send_line: trap 'echo multi' INT TERM; trap | grep -c 'echo multi' expect_output: '[0-9]+' match_type: regex - name: '126. TRAP SIGNAL EDGE CASES: trap ignore signal' steps: - send_line: trap '' INT; trap | grep INT | grep -c '' expect_output: '[0-9]+' match_type: regex - name: '127. EMPTY AND WHITESPACE EDGE CASES: empty command in list' steps: - send_line: ': ; echo ok' expect_output: ok match_type: contains - name: '127. EMPTY AND WHITESPACE EDGE CASES: whitespace only' steps: - send_line: ' ; echo ok' expect_output: ok match_type: contains - name: '127. EMPTY AND WHITESPACE EDGE CASES: multiple empty commands' steps: - send_line: ': ; : ; echo ok' expect_output: ok match_type: contains - name: '127. EMPTY AND WHITESPACE EDGE CASES: empty string as command' steps: - send_line: ''''' 2>/dev/null || echo ok' expect_output: ok match_type: contains auto_fixed: shell_execution - name: '128. COMPLEX PIPELINES: five stage pipeline' steps: - send_line: echo test | cat | cat | cat | cat expect_output: test match_type: contains - name: '128. COMPLEX PIPELINES: pipeline with negation (exit code)' steps: - send_line: '! false | false' - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '128. COMPLEX PIPELINES: pipeline with subshell' steps: - send_line: (echo a; echo b) | wc -l expect_output: '2' match_type: contains - name: '128. COMPLEX PIPELINES: pipeline with brace group' steps: - send_line: '{ echo x; echo y; } | wc -l' expect_output: '[0-9]+' match_type: regex - name: '129. EXIT BUILTIN EDGE CASES: exit with status (exit code)' steps: - send_line: sh -c 'exit 42' - send_line: echo "EXIT=$?" expect_output: EXIT=42 match_type: contains - name: '129. EXIT BUILTIN EDGE CASES: exit in subshell (exit code)' steps: - send_line: (exit 7); echo $? - send_line: echo "EXIT=$?" expect_output: EXIT=0 match_type: contains - name: '130. EXPORT EDGE CASES: export without value' steps: - send_line: export VAR; sh -c 'echo ${VAR:-unset}' expect_output: unset match_type: contains - name: '130. EXPORT EDGE CASES: export with value' steps: - send_line: export VAR=value; sh -c 'echo $VAR' expect_output: value match_type: contains - name: '130. EXPORT EDGE CASES: export multiple' steps: - send_line: export A=1 B=2; sh -c 'echo $A $B' expect_output: 1 2 match_type: contains - name: '130. EXPORT EDGE CASES: export readonly' steps: - send_line: readonly XR=ro; export XR; sh -c 'echo $XR' expect_output: ro match_type: contains