1*cf5a6c84SAndroid Build Coastguard Worker#!/bin/echo no 2*cf5a6c84SAndroid Build Coastguard Worker 3*cf5a6c84SAndroid Build Coastguard Worker[ -f testing.sh ] && . testing.sh 4*cf5a6c84SAndroid Build Coastguard Worker 5*cf5a6c84SAndroid Build Coastguard Worker# TODO make fake pty wrapper for test infrastructure 6*cf5a6c84SAndroid Build Coastguard Worker 7*cf5a6c84SAndroid Build Coastguard Worker# testing "name" "command" "result" "infile" "stdin" 8*cf5a6c84SAndroid Build Coastguard Worker# texpect "name" "command" [R]I/O/E"string" X[ERR] 9*cf5a6c84SAndroid Build Coastguard Worker 10*cf5a6c84SAndroid Build Coastguard Worker# Use "bash" name for host, "sh" for toybox. (/bin/sh is often defective.) 11*cf5a6c84SAndroid Build Coastguard Worker[ -z "$SH" ] && { [ -z "$TEST_HOST" ] && SH="sh" || export SH="bash" ; } 12*cf5a6c84SAndroid Build Coastguard Worker# The expected prompt is different for root vs normal user 13*cf5a6c84SAndroid Build Coastguard Worker[ $UID -eq 0 ] && P='# ' || P='$ ' 14*cf5a6c84SAndroid Build Coastguard Worker# insulate shell child process to get predictable results 15*cf5a6c84SAndroid Build Coastguard WorkerSS="env -i PATH=${PATH@Q} PS1='\\$ ' $SH --noediting --noprofile --norc -is" 16*cf5a6c84SAndroid Build Coastguard Worker 17*cf5a6c84SAndroid Build Coastguard Worker[ -z "$TEST_HOST" ] && : ${BROKEN=true} 18*cf5a6c84SAndroid Build Coastguard Worker# Wrap txpect for shell testing 19*cf5a6c84SAndroid Build Coastguard Workershxpect() { 20*cf5a6c84SAndroid Build Coastguard Worker X="$1" 21*cf5a6c84SAndroid Build Coastguard Worker shift 22*cf5a6c84SAndroid Build Coastguard Worker txpect "$X" "$SS" E"$P" "$@" X0 23*cf5a6c84SAndroid Build Coastguard Worker} 24*cf5a6c84SAndroid Build Coastguard Worker 25*cf5a6c84SAndroid Build Coastguard Workershxpect "prompt and exit" I$'exit\n' 26*cf5a6c84SAndroid Build Coastguard Workershxpect "prompt and echo" I$'echo hello\n' O$'hello\n' E"$P" 27*cf5a6c84SAndroid Build Coastguard Workershxpect "redir" I$'cat<<<hello\n' O$'hello\n' E"$P" 28*cf5a6c84SAndroid Build Coastguard Workershxpect "redirect err" I$'echo > /dev/full\n' E E"$P" X1 29*cf5a6c84SAndroid Build Coastguard Workershxpect "wait for <(exit)" I$'cat <(echo hello 1>&2)\n' E$'hello\n' E"$P" 30*cf5a6c84SAndroid Build Coastguard Worker 31*cf5a6c84SAndroid Build Coastguard Worker# Test shell command line (-c and how scripts run) before changing EVAL 32*cf5a6c84SAndroid Build Coastguard Workertesting '-c "" exit status 0' '$SH -c "" && echo $?' '0\n' '' '' 33*cf5a6c84SAndroid Build Coastguard Workertesting '-c args' "\$SH -c 'echo \$0,\$1,\$2,\$3' one two three four five" \ 34*cf5a6c84SAndroid Build Coastguard Worker "one,two,three,four\n" "" "" 35*cf5a6c84SAndroid Build Coastguard Workertesting '-c args2' "\$SH -c 'echo \${10}' a b c d e f g h i j k l" "k\n" "" "" 36*cf5a6c84SAndroid Build Coastguard Workertesting '-c arg split' \ 37*cf5a6c84SAndroid Build Coastguard Worker "$SH -c 'for i in a\"\$@\"b;do echo =\$i=;done;echo \$0' 123 456 789" \ 38*cf5a6c84SAndroid Build Coastguard Worker "=a456=\n=789b=\n123\n" "" "" 39*cf5a6c84SAndroid Build Coastguard Workertesting '-c arg split2' \ 40*cf5a6c84SAndroid Build Coastguard Worker "$SH -c 'for i in a\"\$* \$@\"b; do echo =\$i=;done' one two three four five"\ 41*cf5a6c84SAndroid Build Coastguard Worker "=atwo three four five two=\n=three=\n=four=\n=fiveb=\n" "" "" 42*cf5a6c84SAndroid Build Coastguard Workertesting '-c arg count' "$SH -c 'echo \$#' 9 8 7 6 1 2 3 4" "7\n" "" "" 43*cf5a6c84SAndroid Build Coastguard Workertesting 'trailing \' "$SH -c 'echo \'" '\\\n' '' '' 44*cf5a6c84SAndroid Build Coastguard Workertesting "trailing \\ in ''" "$SH -c \$'echo \\'one\\\\\\ntwo\\''" \ 45*cf5a6c84SAndroid Build Coastguard Worker 'one\\\ntwo\n' '' '' 46*cf5a6c84SAndroid Build Coastguard Workertesting 'trailing \ in ""' "$SH -c \$'echo \"one\\\\\\ntwo\"'" 'onetwo\n' \ 47*cf5a6c84SAndroid Build Coastguard Worker '' '' 48*cf5a6c84SAndroid Build Coastguard Workertesting 'vanishing \' "$SH -c \$'echo \\\\\\n a'" 'a\n' '' '' 49*cf5a6c84SAndroid Build Coastguard Workertesting 'command\ arg' "$SH -c \$'echo\\\\\\n abc'" 'abc\n' '' '' 50*cf5a6c84SAndroid Build Coastguard Workertesting "exec3" '$C -c "{ exec readlink /proc/self/fd/0;} < /proc/self/exe"' \ 51*cf5a6c84SAndroid Build Coastguard Worker "$(readlink -f $C)\n" "" "" 52*cf5a6c84SAndroid Build Coastguard Workertesting 'arg shift' "$SH -c '"'for i in "" 2 1 1 1; do echo $? $1; shift $i; done'"' one two three four five" \ 53*cf5a6c84SAndroid Build Coastguard Worker "0 two\n0 three\n0 five\n0\n1\n" "" "" 54*cf5a6c84SAndroid Build Coastguard Workertesting '(subshell)' '$SH -c "(echo hello)"' 'hello\n' '' '' 55*cf5a6c84SAndroid Build Coastguard Workertesting 'syntax' '$SH -c "if true; then echo hello | fi" 2>/dev/null || echo x'\ 56*cf5a6c84SAndroid Build Coastguard Worker 'x\n' '' '' 57*cf5a6c84SAndroid Build Coastguard Workertesting 'syntax2' '$SH -c "for;i 0" 2>&1 | { grep -qi syntax && echo yes; }' \ 58*cf5a6c84SAndroid Build Coastguard Worker 'yes\n' '' '' 59*cf5a6c84SAndroid Build Coastguard Worker 60*cf5a6c84SAndroid Build Coastguard Worker# The bash man page is lying when it says $_ starts with an absolute path. 61*cf5a6c84SAndroid Build Coastguard Workerln -s "$(which $SH)" bash 62*cf5a6c84SAndroid Build Coastguard Workertesting 'non-absolute $_' "./bash -c 'echo \$_'" './bash\n' '' '' 63*cf5a6c84SAndroid Build Coastguard Workerrm bash 64*cf5a6c84SAndroid Build Coastguard Worker 65*cf5a6c84SAndroid Build Coastguard Workertesting 'exec exitval' "$SH -c 'exec echo hello' && echo \$?" "hello\n0\n" "" "" 66*cf5a6c84SAndroid Build Coastguard Workertesting 'simple script' '$SH input' 'input\n' 'echo $0' '' 67*cf5a6c84SAndroid Build Coastguard Workertesting 'simple script2' '$SH ./input two;echo $?' './input+two\n42\n' \ 68*cf5a6c84SAndroid Build Coastguard Worker '\necho $0+$1\n\nexit 42' '' 69*cf5a6c84SAndroid Build Coastguard Worker# this segfaults bash 70*cf5a6c84SAndroid Build Coastguard Workertoyonly testing 'recursion guard' \ 71*cf5a6c84SAndroid Build Coastguard Worker '$SH input 2>/dev/null; [ $? -lt 128 ] && echo pass' 'pass\n' \ 72*cf5a6c84SAndroid Build Coastguard Worker 'source input' '' 73*cf5a6c84SAndroid Build Coastguard Workertesting '$LINENO 1' "$SH input" "1\n" 'echo $LINENO' '' 74*cf5a6c84SAndroid Build Coastguard Worker 75*cf5a6c84SAndroid Build Coastguard Workermkdir sub 76*cf5a6c84SAndroid Build Coastguard Workerecho echo hello > sub/script 77*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'simple script in $PATH' "PATH='$PWD/sub:$PATH' $SH script" \ 78*cf5a6c84SAndroid Build Coastguard Worker 'hello\n' '' '' 79*cf5a6c84SAndroid Build Coastguard Workerrm -rf sub 80*cf5a6c84SAndroid Build Coastguard Worker 81*cf5a6c84SAndroid Build Coastguard Workertesting "script file" "chmod +x input; ./input" "hello\n" "#!$C\necho hello" "" 82*cf5a6c84SAndroid Build Coastguard Workertesting 'IFS $*' "$SH -c 'IFS=xy; echo \"\$*\"' one two tyree" "twoxtyree\n" \ 83*cf5a6c84SAndroid Build Coastguard Worker "" "" 84*cf5a6c84SAndroid Build Coastguard Worker# Without the \n\n bash 5 emits SHLVL=0 85*cf5a6c84SAndroid Build Coastguard Workertesting 'default exports' \ 86*cf5a6c84SAndroid Build Coastguard Worker "env -i \"$(which $SH)\" --noprofile --norc -c \$'env\n\n' | sort" \ 87*cf5a6c84SAndroid Build Coastguard Worker "PWD=$(pwd)\nSHLVL=1\n_=$(which env)\n" "" "" 88*cf5a6c84SAndroid Build Coastguard Worker# toysh order of operations not matching bash 89*cf5a6c84SAndroid Build Coastguard Worker#testing "leading assignment fail" \ 90*cf5a6c84SAndroid Build Coastguard Worker# "{ \$SH -c 'X=\${a?blah} > walroid';ls walroid;} 2>/dev/null" '' '' '' 91*cf5a6c84SAndroid Build Coastguard Workertesting "lineno" "$SH input" "5 one\n6 one\n5 two\n6 two\n" \ 92*cf5a6c84SAndroid Build Coastguard Worker '#!/bin/bash\n\nfor i in one two\ndo\n echo $LINENO $i\n echo $LINENO $i\ndone\n' "" 93*cf5a6c84SAndroid Build Coastguard Workertesting "eval0" "$SH -c 'eval echo \$*' one two three" "two three\n" "" "" 94*cf5a6c84SAndroid Build Coastguard Worker 95*cf5a6c84SAndroid Build Coastguard Worker######################################################################### 96*cf5a6c84SAndroid Build Coastguard Worker# Change EVAL to call sh -c for us, using "bash" explicitly for the host. 97*cf5a6c84SAndroid Build Coastguard Workerexport EVAL="timeout 10 $SH -c" 98*cf5a6c84SAndroid Build Coastguard Worker 99*cf5a6c84SAndroid Build Coastguard Worker# From here on, tests run within the new shell by default. 100*cf5a6c84SAndroid Build Coastguard Worker 101*cf5a6c84SAndroid Build Coastguard Workertesting 'return code' 'if false; then echo true; fi; echo $?' '0\n' '' '' 102*cf5a6c84SAndroid Build Coastguard Workertesting 'return code 2' 'if true; then false; fi; echo $?' '1\n' '' '' 103*cf5a6c84SAndroid Build Coastguard Workertesting 'return code 3' 'x=0; while [ $((x++)) -lt 2 ]; do echo $x; done; echo $?' '1\n2\n0\n' '' '' 104*cf5a6c84SAndroid Build Coastguard Workertesting 'return code 4' 'false; A=B; echo $?' '0\n' '' '' 105*cf5a6c84SAndroid Build Coastguard Workertesting 'local var +whiteout' \ 106*cf5a6c84SAndroid Build Coastguard Worker 'l=X;x(){ local l=47; echo $l;unset l; echo l=$l;};x;echo $l' '47\nl=\nX\n' \ 107*cf5a6c84SAndroid Build Coastguard Worker '' '' 108*cf5a6c84SAndroid Build Coastguard Workertesting 'escape passthrough' 'echo -e "a\nb\nc\td"' 'a\nb\nc\td\n' '' '' 109*cf5a6c84SAndroid Build Coastguard Worker 110*cf5a6c84SAndroid Build Coastguard Workertesting 'trailing $ is literal' 'echo $' '$\n' '' '' 111*cf5a6c84SAndroid Build Coastguard Workertesting 'work after HERE' $'cat<<0;echo hello\npotato\n0' 'potato\nhello\n' '' '' 112*cf5a6c84SAndroid Build Coastguard Workertesting '<<\EOF' $'(cat<<EOF\n$PATH\nEOF\necho "$PATH") | sort -u | wc -l' \ 113*cf5a6c84SAndroid Build Coastguard Worker '1\n' '' '' 114*cf5a6c84SAndroid Build Coastguard Workertesting "<<EOF''" $'(cat<<EOF\'\'\n$PATH\nEOF\necho "$PATH") | sort -u | wc -l'\ 115*cf5a6c84SAndroid Build Coastguard Worker '2\n' '' '' 116*cf5a6c84SAndroid Build Coastguard Workertesting '<<\EOF' $'(cat<<\\EOF\n$PATH\nEOF\necho "$PATH") | sort -u | wc -l' \ 117*cf5a6c84SAndroid Build Coastguard Worker '2\n' '' '' 118*cf5a6c84SAndroid Build Coastguard Workertesting '<< \' $'cat<<EOF\nabc\\\ndef\nEOF\n' 'abcdef\n' '' '' 119*cf5a6c84SAndroid Build Coastguard Workertesting '<< "\"' $'cat<<\\EOF\nabc\\\ndef\nEOF\n' 'abc\\\ndef\n' '' '' 120*cf5a6c84SAndroid Build Coastguard Workertesting '<<""' $'cat<<"";echo hello\npotato\n\necho huh' 'potato\nhello\nhuh\n'\ 121*cf5a6c84SAndroid Build Coastguard Worker '' '' 122*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '<< trailing \' $'cat<<EOF 2>/dev/null\nabcde\nnext\\\nEOF\nEOF' \ 123*cf5a6c84SAndroid Build Coastguard Worker 'abcde\nnextEOF\n' '' '' 124*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '<< trailing \ 2' $'cat<<EOF\nabcde\nEO\\\nF\necho hello' \ 125*cf5a6c84SAndroid Build Coastguard Worker 'abcde\nhello\n' '' '' 126*cf5a6c84SAndroid Build Coastguard Workertesting '<< $(a)' $'cat<<$(a)\nx\n$(a)' 'x\n' '' '' 127*cf5a6c84SAndroid Build Coastguard Workertesting 'HERE straddle' $'cat<<EOF;if true\nhello\nEOF\nthen echo also; fi' \ 128*cf5a6c84SAndroid Build Coastguard Worker 'hello\nalso\n' '' '' 129*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '\\n in <<EOF' $'cat<<EO\\\nF\n$PATH\nEOF\n' "$PATH\n" "" "" 130*cf5a6c84SAndroid Build Coastguard Workertesting '\\n in <<EOF with ""' $'cat<<EO\\\nF""\n$PATH\nEOF\n' '$PATH\n' '' '' 131*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '\\n in HERE terminator' $'cat<<EOF\nabc\nE\\\nOF\necho hello\n' \ 132*cf5a6c84SAndroid Build Coastguard Worker 'abc\nhello\n' '' '' 133*cf5a6c84SAndroid Build Coastguard Workerln -s "$(which echo)" echo2 134*cf5a6c84SAndroid Build Coastguard Workertesting "undelimited redirect doesn't eat prefix" './echo2</dev/null hello' \ 135*cf5a6c84SAndroid Build Coastguard Worker 'hello\n' '' '' 136*cf5a6c84SAndroid Build Coastguard Workerrm -f echo2 137*cf5a6c84SAndroid Build Coastguard Workertesting 'prefix assignment is local' '{ echo $ABC; } {ABC}</dev/null; echo $3'\ 138*cf5a6c84SAndroid Build Coastguard Worker '10\n\n' '' '' 139*cf5a6c84SAndroid Build Coastguard Workertesting 'double quotes' 'echo \x "\x" "\\" "\$" "\`"' 'x \x \ $ `\n' '' '' 140*cf5a6c84SAndroid Build Coastguard Workertesting 'quoted line escapes' $'echo "\\\none" \'\\\ntwo\'' 'one \\\ntwo\n' '' '' 141*cf5a6c84SAndroid Build Coastguard Workertesting 'escape makes argument' 'echo \ | wc -c' '2\n' '' '' 142*cf5a6c84SAndroid Build Coastguard Worker 143*cf5a6c84SAndroid Build Coastguard Worker# TODO testing 'empty +() is literal' 'echo +()' '+()\n' '' '' 144*cf5a6c84SAndroid Build Coastguard Worker 145*cf5a6c84SAndroid Build Coastguard Worker# shxpect "EOF" I$'<<EOF;echo hello' 146*cf5a6c84SAndroid Build Coastguard Workershxpect 'queued work after HERE' I$'<<0;echo hello\n' E"> " I$'0\n' O$'hello\n' 147*cf5a6c84SAndroid Build Coastguard Workershxpect '$_ preserved on assignment error' I$'true hello; a=1 b=2 c=${}\n' \ 148*cf5a6c84SAndroid Build Coastguard Worker E E"$P" I$'echo $_\n' O$'hello\n' 149*cf5a6c84SAndroid Build Coastguard Workershxpect '$_ preserved on prefix error' I$'true hello; a=1 b=2 c=${} true\n' \ 150*cf5a6c84SAndroid Build Coastguard Worker E E"$P" I$'echo $_\n' O$'hello\n' 151*cf5a6c84SAndroid Build Coastguard Workershxpect '$_ preserved on exec error' I$'true hello; ${}\n' \ 152*cf5a6c84SAndroid Build Coastguard Worker E E"$P" I$'echo $_\n' O$'hello\n' 153*cf5a6c84SAndroid Build Coastguard Workershxpect '$_ abspath on exec' I$'env | grep ^_=\n' O$'_=/usr/bin/env\n' 154*cf5a6c84SAndroid Build Coastguard Workertesting '$_ literal after exec' 'env >/dev/null; echo $_' 'env\n' '' '' 155*cf5a6c84SAndroid Build Coastguard Workershxpect '$_ no path for builtin' I$'true; echo $_\n' O$'true\n' 156*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'prefix is local for builtins' 'abc=123; abc=def unset abc; echo $abc' \ 157*cf5a6c84SAndroid Build Coastguard Worker '123\n' '' '' 158*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'prefix localizes magic vars' \ 159*cf5a6c84SAndroid Build Coastguard Worker 'SECONDS=123; SECONDS=345 true; echo $SECONDS' '123\n' '' '' 160*cf5a6c84SAndroid Build Coastguard Workershxpect 'body evaluated before variable exports' I$'a=x${} y${}\n' RE'y${}' X1 161*cf5a6c84SAndroid Build Coastguard Workertesting '$NOTHING clears $_' 'true; $NOTHING; echo $_' '\n' '' '' 162*cf5a6c84SAndroid Build Coastguard Workertesting 'assignment with redirect is persistent, not prefix' \ 163*cf5a6c84SAndroid Build Coastguard Worker 'ABC=DEF > potato && rm potato && echo $ABC' 'DEF\n' '' '' 164*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '$_ with functions' 'true; x(){ echo $_;}; x abc; echo $_' \ 165*cf5a6c84SAndroid Build Coastguard Worker 'true\nabc\n' '' '' 166*cf5a6c84SAndroid Build Coastguard Worker 167*cf5a6c84SAndroid Build Coastguard Workermkdir -p one/two/three 168*cf5a6c84SAndroid Build Coastguard Workertesting 'cd in renamed dir' \ 169*cf5a6c84SAndroid Build Coastguard Worker 'cd one/two/three && mv ../../../{one,four} && cd .. && echo ${PWD: -9:9}' \ 170*cf5a6c84SAndroid Build Coastguard Worker '/four/two\n' '' '' 171*cf5a6c84SAndroid Build Coastguard Workerrm -rf one 172*cf5a6c84SAndroid Build Coastguard Worker 173*cf5a6c84SAndroid Build Coastguard Workertesting "smoketest" "echo hello" "hello\n" "" "" 174*cf5a6c84SAndroid Build Coastguard Workertesting "assignment" 'x=y; echo $x' 'y\n' '' '' 175*cf5a6c84SAndroid Build Coastguard Workertesting "+= assignment" 'x+=abc; y=def; y+=$x; echo $y' 'defabc\n' '' '' 176*cf5a6c84SAndroid Build Coastguard Workertesting "eval" "eval echo hello" "hello\n" "" "" 177*cf5a6c84SAndroid Build Coastguard Workertesting "eval2" "eval 'echo hello'; echo $?" "hello\n0\n" "" "" 178*cf5a6c84SAndroid Build Coastguard Workertesting "eval3" 'X="echo hello"; eval "$X"' "hello\n" "" "" 179*cf5a6c84SAndroid Build Coastguard Workertesting "eval4" 'eval printf '=%s=' \" hello \"' "= hello =" "" "" 180*cf5a6c84SAndroid Build Coastguard WorkerNOSPACE=1 testing "eval5" 'eval echo \" hello \" | wc' ' 1 1 8' "" "" 181*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'eval6' $'false; eval \'echo $?\'' '1\n' '' '' 182*cf5a6c84SAndroid Build Coastguard Workertesting 'eval7' $'eval \'false\'; echo $?' '1\n' '' '' 183*cf5a6c84SAndroid Build Coastguard Workertesting 'eval8' $'false; eval ''; echo $?' '0\n' '' '' 184*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'eval9' $'A=echo; false; eval \'$A $?\'' '1\n' '' '' 185*cf5a6c84SAndroid Build Coastguard Workertesting "exec" "exec echo hello" "hello\n" "" "" 186*cf5a6c84SAndroid Build Coastguard Workertesting "exec2" "exec echo hello; echo $?" "hello\n" "" "" 187*cf5a6c84SAndroid Build Coastguard Worker 188*cf5a6c84SAndroid Build Coastguard Worker# ; | && || 189*cf5a6c84SAndroid Build Coastguard Workertesting "semicolon" "echo one;echo two" "one\ntwo\n" "" "" 190*cf5a6c84SAndroid Build Coastguard Workertesting "simple pipe" "echo hello | cat" "hello\n" "" "" 191*cf5a6c84SAndroid Build Coastguard Workertesting "&&" "true && echo hello" "hello\n" "" "" 192*cf5a6c84SAndroid Build Coastguard Workertesting "&&2" "false && echo hello" "" "" "" 193*cf5a6c84SAndroid Build Coastguard Workertesting "||" "true || echo hello" "" "" "" 194*cf5a6c84SAndroid Build Coastguard Workertesting "||2" "false || echo hello" "hello\n" "" "" 195*cf5a6c84SAndroid Build Coastguard Workertesting "&& ||" "true && false && potato || echo hello" "hello\n" "" "" 196*cf5a6c84SAndroid Build Coastguard Workertesting "&& after function" "x(){ false;};x && echo yes" "" "" "" 197*cf5a6c84SAndroid Build Coastguard Workertesting "|| after function" "x(){ false;};x || echo yes" "yes\n" "" "" 198*cf5a6c84SAndroid Build Coastguard Worker 199*cf5a6c84SAndroid Build Coastguard Worker# redirection 200*cf5a6c84SAndroid Build Coastguard Worker 201*cf5a6c84SAndroid Build Coastguard Workertesting "redir1" "cat < input" "hello\n" "hello\n" "" 202*cf5a6c84SAndroid Build Coastguard Workertesting "redir2" "echo blah >out; cat out" "blah\n" "" "" 203*cf5a6c84SAndroid Build Coastguard Workertesting "redir3" "echo more >>out; cat out" "blah\nmore\n" "" "" 204*cf5a6c84SAndroid Build Coastguard Workertesting "redir4" "touch /not/exist 2>out||grep -o /not/exist out" \ 205*cf5a6c84SAndroid Build Coastguard Worker "/not/exist\n" "" "" 206*cf5a6c84SAndroid Build Coastguard Workertesting "redir5" "ls out /not/exist &> out2 || wc -l < out2" "2\n" "" "" 207*cf5a6c84SAndroid Build Coastguard Workertesting "redir6" "ls out /not/exist &>>-abc || wc -l < ./-abc" "2\n" "" "" 208*cf5a6c84SAndroid Build Coastguard Workertesting "redir7" "ls out /not/exist |& wc -l" "2\n" "" "" 209*cf5a6c84SAndroid Build Coastguard Workertesting "redir8" 'echo -n $(<input)' "boing" "boing\n" "" 210*cf5a6c84SAndroid Build Coastguard Workershxpect "redir9" I$'echo hello > out 2>/does/not/exist\n' E E"$P" \ 211*cf5a6c84SAndroid Build Coastguard Worker I$'wc -l < out\n' O$'0\n' 212*cf5a6c84SAndroid Build Coastguard Workertesting "redir10" 'echo hello 3<&3' "hello\n" "" "" 213*cf5a6c84SAndroid Build Coastguard Workertesting "redir11" 'if :;then echo one;fi {abc}<input; cat <&$abc' \ 214*cf5a6c84SAndroid Build Coastguard Worker "one\npotato\n" "potato\n" "" 215*cf5a6c84SAndroid Build Coastguard Workerrm -f out out2 ./-abc 216*cf5a6c84SAndroid Build Coastguard Worker 217*cf5a6c84SAndroid Build Coastguard Worker# expansion 218*cf5a6c84SAndroid Build Coastguard Worker 219*cf5a6c84SAndroid Build Coastguard Workertesting "tilde expansion" "echo ~" "$HOME\n" "" "" 220*cf5a6c84SAndroid Build Coastguard Workertesting "tilde2" "echo ~/dir" "$HOME/dir\n" "" "" 221*cf5a6c84SAndroid Build Coastguard Workertesting "bracket expansion" \ 222*cf5a6c84SAndroid Build Coastguard Worker "echo {A{a,b}B{c,d}C}" "{AaBcC} {AaBdC} {AbBcC} {AbBdC}\n" "" "" 223*cf5a6c84SAndroid Build Coastguard Workertesting "brackets2" "echo {A{a,b}B{c,d}C,D}" "AaBcC AaBdC AbBcC AbBdC D\n" "" "" 224*cf5a6c84SAndroid Build Coastguard Workertesting "brackets3" 'echo {A"b,c"D}' "{Ab,cD}\n" "" "" 225*cf5a6c84SAndroid Build Coastguard Workertesting "brackets4" 'echo {A"bc",D}' "Abc D\n" "" "" 226*cf5a6c84SAndroid Build Coastguard Workertesting "brackets5" 'echo {A,B,C' "{A,B,C\n" "" "" 227*cf5a6c84SAndroid Build Coastguard Workertesting "brackets6" 'echo {{{{A,B},C}D},E}' "{AD} {BD} {CD} E\n" "" "" 228*cf5a6c84SAndroid Build Coastguard Workertesting "brackets7" 'echo {{{a,b},c,{d,e}},f}' "a b c d e f\n" "" "" 229*cf5a6c84SAndroid Build Coastguard Workertesting "brackets8" 'echo A{a{b,c{B,C}D}d{e,f},g{h,i}j}E' \ 230*cf5a6c84SAndroid Build Coastguard Worker "AabdeE AabdfE AacBDdeE AacBDdfE AacCDdeE AacCDdfE AghjE AgijE\n" "" "" 231*cf5a6c84SAndroid Build Coastguard Workertesting "brackets9" 'echo A{B{C,D}E{N,O},F{G,H}I}J{K,L}M' \ 232*cf5a6c84SAndroid Build Coastguard Worker "ABCENJKM ABCENJLM ABCEOJKM ABCEOJLM ABDENJKM ABDENJLM ABDEOJKM ABDEOJLM AFGIJKM AFGIJLM AFHIJKM AFHIJLM\n" "" "" 233*cf5a6c84SAndroid Build Coastguard Workerfor i in /root /var/root /; do [ -e $i ] && EXPECT=$i && break; done 234*cf5a6c84SAndroid Build Coastguard Workertesting "bracket+tilde" "echo {~,~root}/pwd" "$HOME/pwd $EXPECT/pwd\n" "" "" 235*cf5a6c84SAndroid Build Coastguard Worker 236*cf5a6c84SAndroid Build Coastguard Worker# Slices 237*cf5a6c84SAndroid Build Coastguard Worker 238*cf5a6c84SAndroid Build Coastguard Workertesting '${x#prefix}' 'x=abcde; echo ${x#abc}' 'de\n' '' '' 239*cf5a6c84SAndroid Build Coastguard Workertesting '${x#short} ${x##long}' 'x=banana; echo ${x#b*n} ${x##b*n}' \ 240*cf5a6c84SAndroid Build Coastguard Worker 'ana a\n' '' '' 241*cf5a6c84SAndroid Build Coastguard Workertoyonly testing '${x#utf8}' 'x=aそcde; echo ${x##a?c}' 'de\n' '' '' 242*cf5a6c84SAndroid Build Coastguard Workertesting '${x%y}' 'x=potato; echo ${x%t*o} ${x%%t*o}' 'pota po\n' '' '' 243*cf5a6c84SAndroid Build Coastguard Workertesting 'x=${x%y}' 'x=potato; x=${x%t*o}; echo $x' 'pota\n' '' '' 244*cf5a6c84SAndroid Build Coastguard Workertesting '${x%glob}' 'x=abc-def; echo ${x%-*f} ${x-*c}' 'abc abc-def\n' '' '' 245*cf5a6c84SAndroid Build Coastguard Workertesting 'x=${x//y}' 'x=potato; x=${x//ta}; echo $x' 'poto\n' '' '' 246*cf5a6c84SAndroid Build Coastguard Workertesting '${x^y}' 'x=aaaaa; echo ${x^a}' 'Aaaaa\n' '' '' 247*cf5a6c84SAndroid Build Coastguard Workertesting '${x^^y}' 'x=abccdec; echo ${x^^c}; x=abcdec; echo ${x^^c}' \ 248*cf5a6c84SAndroid Build Coastguard Worker 'abCCdeC\nabCdeC\n' '' '' 249*cf5a6c84SAndroid Build Coastguard Workertesting '${x,y}' 'x=BBB; echo ${x,B}' 'bBB\n' '' '' 250*cf5a6c84SAndroid Build Coastguard Workertesting '${x,,y}' 'x=POTATO; echo ${x,,} ${x,,?} ${x,,*} ${x,,T}' \ 251*cf5a6c84SAndroid Build Coastguard Worker 'potato potato potato POtAtO\n' '' '' 252*cf5a6c84SAndroid Build Coastguard Worker 253*cf5a6c84SAndroid Build Coastguard Workermkdir -p abc/def/ghi 254*cf5a6c84SAndroid Build Coastguard Workertouch www 255*cf5a6c84SAndroid Build Coastguard Workertesting 'wildcards' 'echo w[v-x]w w[x-v]w abc/*/ghi' \ 256*cf5a6c84SAndroid Build Coastguard Worker 'www w[x-v]w abc/def/ghi\n' '' '' 257*cf5a6c84SAndroid Build Coastguard Workertesting 'hidden wildcards' \ 258*cf5a6c84SAndroid Build Coastguard Worker 'touch .abc abc && echo *bc && echo and && echo .*bc' \ 259*cf5a6c84SAndroid Build Coastguard Worker 'abc\nand\n.abc\n' '' '' 260*cf5a6c84SAndroid Build Coastguard Worker 261*cf5a6c84SAndroid Build Coastguard Workertesting "backtick1" 'x=fred; echo `echo $x`' 'fred\n' "" "" 262*cf5a6c84SAndroid Build Coastguard Workertesting "backtick2" 'x=fred; echo `x=y; echo $x`; echo $x' 'y\nfred\n' "" "" 263*cf5a6c84SAndroid Build Coastguard Workertesting '$(( ) )' 'echo ab$((echo hello) | tr e x)cd' "abhxllocd\n" "" "" 264*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '$((x=y)) lifetime' 'a=boing; echo $a $a$((a=4))$a $a' 'boing boing44 4\n' '' '' 265*cf5a6c84SAndroid Build Coastguard Worker 266*cf5a6c84SAndroid Build Coastguard Workertesting 'quote' "echo \"'\"" "'\n" "" "" 267*cf5a6c84SAndroid Build Coastguard Worker 268*cf5a6c84SAndroid Build Coastguard Workertesting "math" 'echo $((1+2))' '3\n' '' '' 269*cf5a6c84SAndroid Build Coastguard Workertesting "[oldmath]" 'echo $[1+2]' '3\n' '' '' 270*cf5a6c84SAndroid Build Coastguard Workertesting "math basic priority" 'echo $((1+2*3**4))' '163\n' '' '' 271*cf5a6c84SAndroid Build Coastguard Workertesting "math paren" 'echo $(((1+2)*3))' '9\n' '' '' 272*cf5a6c84SAndroid Build Coastguard Workertesting "math spaces" 'echo $(( ( 1 + 2 ) * 7 - 5 ** 2 ))' '-4\n' '' '' 273*cf5a6c84SAndroid Build Coastguard Workertesting "((<)) isn't redirect" '((1<2)) </dev/null && echo yes' 'yes\n' '' '' 274*cf5a6c84SAndroid Build Coastguard Workertesting "((>)) isn't redirect" '((1>2)) </dev/null || echo yes' 'yes\n' '' '' 275*cf5a6c84SAndroid Build Coastguard Workertesting "((not math) )" '((echo hello) )' 'hello\n' '' '' 276*cf5a6c84SAndroid Build Coastguard Workertesting "preincrement" 'echo $((++x)); echo $x' '1\n1\n' '' '' 277*cf5a6c84SAndroid Build Coastguard Workertesting "preincrement vs prefix plus" 'echo $((+++x)); echo $x' '1\n1\n' '' '' 278*cf5a6c84SAndroid Build Coastguard Workertesting "predecrement" 'echo $((--x)); echo $x' '-1\n-1\n' '' '' 279*cf5a6c84SAndroid Build Coastguard Workertesting "predecrement vs prefix minus" 'echo $((---x)); echo $x' '1\n-1\n' '' '' 280*cf5a6c84SAndroid Build Coastguard Workertesting "minus-minus-minus" 'echo $((x---7)); echo $x' '-7\n-1\n' '' '' 281*cf5a6c84SAndroid Build Coastguard Workertesting "x---y is x-- -y not x- --y" 'x=1 y=1; echo $((x---y)) $x $y' '0 0 1\n'\ 282*cf5a6c84SAndroid Build Coastguard Worker '' '' 283*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing "nesting ? :" \ 284*cf5a6c84SAndroid Build Coastguard Worker 'for((i=0;i<8;i++)); do echo $((i&1?i&2?1:i&4?2:3:4));done' \ 285*cf5a6c84SAndroid Build Coastguard Worker '4\n3\n4\n1\n4\n2\n4\n1\n' '' '' 286*cf5a6c84SAndroid Build Coastguard Workertesting "inherited assignment suppression" 'echo $((0 ? (x++) : 2)); echo $x' \ 287*cf5a6c84SAndroid Build Coastguard Worker "2\n\n" "" "" 288*cf5a6c84SAndroid Build Coastguard Workertesting "boolean vs logical" 'echo $((2|4&&8))' '1\n' '' '' 289*cf5a6c84SAndroid Build Coastguard Workertesting "&& vs || priority" \ 290*cf5a6c84SAndroid Build Coastguard Worker 'echo $((w++||x++&&y++||z++)) w=$w x=$x y=$y z=$z' \ 291*cf5a6c84SAndroid Build Coastguard Worker '0 w=1 x=1 y= z=1\n' '' '' 292*cf5a6c84SAndroid Build Coastguard Workertesting "|| vs && priority" \ 293*cf5a6c84SAndroid Build Coastguard Worker 'echo $((w++&&x++||y++&&z++)) w=$w x=$x y=$y z=$z' \ 294*cf5a6c84SAndroid Build Coastguard Worker '0 w=1 x= y=1 z=\n' '' '' 295*cf5a6c84SAndroid Build Coastguard Worker$BROKEN shxpect '/0' I$'echo $((1/0)); echo here\n' E E"$P" I$'echo $?\n' O$'1\n' 296*cf5a6c84SAndroid Build Coastguard Worker$BROKEN shxpect '%0' I$'echo $((1%0)); echo here\n' E E"$P" I$'echo $?\n' O$'1\n' 297*cf5a6c84SAndroid Build Coastguard Worker$BROKEN shxpect '/=0' I$'echo $((x/=0)); echo here\n' E E"$P" I$'echo $?\n' O$'1\n' 298*cf5a6c84SAndroid Build Coastguard Worker$BROKEN shxpect '%=0' I$'echo $((x%=0)); echo here\n' E E"$P" I$'echo $?\n' O$'1\n' 299*cf5a6c84SAndroid Build Coastguard Worker 300*cf5a6c84SAndroid Build Coastguard Worker# Loops and flow control 301*cf5a6c84SAndroid Build Coastguard Workertesting "case" 'for i in A C J B; do case "$i" in A) echo got A ;; B) echo and B ;; C) echo then C ;; *) echo default ;; esac; done' \ 302*cf5a6c84SAndroid Build Coastguard Worker "got A\nthen C\ndefault\nand B\n" "" "" 303*cf5a6c84SAndroid Build Coastguard Workertesting 'case;;&' 'case wow in w?w) echo ok;;& wow) echo no; esac' 'ok\nno\n' \ 304*cf5a6c84SAndroid Build Coastguard Worker "" "" 305*cf5a6c84SAndroid Build Coastguard Workertesting "case newlines" \ 306*cf5a6c84SAndroid Build Coastguard Worker $'case i\n\nin\n\na) echo one\n\n;;\n\ni)\n\necho two\n\n;;\n\nesac' \ 307*cf5a6c84SAndroid Build Coastguard Worker "two\n" "" "" 308*cf5a6c84SAndroid Build Coastguard Workertesting "case block" \ 309*cf5a6c84SAndroid Build Coastguard Worker $'case X in\n X) printf %s "X" || { echo potato;} ;;\nesac' 'X' '' '' 310*cf5a6c84SAndroid Build Coastguard Workertesting 'loop in && ||' \ 311*cf5a6c84SAndroid Build Coastguard Worker 'false && for i in a b c; do echo $i; done || echo no' 'no\n' '' '' 312*cf5a6c84SAndroid Build Coastguard Workertesting "continue" 'for i in a b c; do for j in d e f; do echo $i $j; continue 2; done; done' \ 313*cf5a6c84SAndroid Build Coastguard Worker "a d\nb d\nc d\n" "" "" 314*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing "piped loops that don't exit" \ 315*cf5a6c84SAndroid Build Coastguard Worker 'while X=$(($X+1)); do echo $X; done | while read i; do echo $i; done | head -n 5' \ 316*cf5a6c84SAndroid Build Coastguard Worker '1\n2\n3\n4\n5\n' '' '' 317*cf5a6c84SAndroid Build Coastguard Worker 318*cf5a6c84SAndroid Build Coastguard Worker# <glinda>A variable occurred</glinda> 319*cf5a6c84SAndroid Build Coastguard Worker 320*cf5a6c84SAndroid Build Coastguard Workertesting "expand" 'echo $PWD' "$(pwd)\n" "" "" 321*cf5a6c84SAndroid Build Coastguard Workertesting "expand2" 'echo "$PWD"' "$(pwd)\n" "" "" 322*cf5a6c84SAndroid Build Coastguard Workertesting "expand3" 'echo "$"PWD' '$PWD\n' "" "" 323*cf5a6c84SAndroid Build Coastguard Workertesting "expand4" 'P=x; echo "$P"WD' 'xWD\n' "" "" 324*cf5a6c84SAndroid Build Coastguard Workertesting "dequote" "echo one 'two' ''three 'fo'ur '\\'" \ 325*cf5a6c84SAndroid Build Coastguard Worker 'one two three four \\\n' '' '' 326*cf5a6c84SAndroid Build Coastguard Worker 327*cf5a6c84SAndroid Build Coastguard Workertesting "leading variable assignment" 'abc=def env | grep ^abc=; echo $abc' \ 328*cf5a6c84SAndroid Build Coastguard Worker "abc=def\n\n" "" "" 329*cf5a6c84SAndroid Build Coastguard Workertesting "leading variable assignments" \ 330*cf5a6c84SAndroid Build Coastguard Worker "abc=def ghi=jkl env | egrep '^(abc|ghi)=' | sort; echo \$abc \$ghi" \ 331*cf5a6c84SAndroid Build Coastguard Worker "abc=def\nghi=jkl\n\n" "" "" 332*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing "leading assignment occurs after parsing" \ 333*cf5a6c84SAndroid Build Coastguard Worker 'abc=def; abc=ghi echo $abc' "def\n" "" "" 334*cf5a6c84SAndroid Build Coastguard Workertesting "leading assignment space" 'X="abc def"; Y=$X; echo "$Y"' \ 335*cf5a6c84SAndroid Build Coastguard Worker "abc def\n" "" "" 336*cf5a6c84SAndroid Build Coastguard Workertesting "leading assignment space2" \ 337*cf5a6c84SAndroid Build Coastguard Worker 'chicken() { X="$@"; }; chicken a b c d e; echo "$X"' 'a b c d e\n' '' '' 338*cf5a6c84SAndroid Build Coastguard Workertesting "leading assignment fail2" \ 339*cf5a6c84SAndroid Build Coastguard Worker "{ 1blah=123 echo hello;} 2>/dev/null || echo no" "no\n" "" "" 340*cf5a6c84SAndroid Build Coastguard Workertesting "leading assignment redirect" \ 341*cf5a6c84SAndroid Build Coastguard Worker "blah=123 echo hello > walrus && ls walrus" "walrus\n" "" "" 342*cf5a6c84SAndroid Build Coastguard Workerrm -f walrus 343*cf5a6c84SAndroid Build Coastguard Worker 344*cf5a6c84SAndroid Build Coastguard Workertesting "{1..5}" "echo {1..5}" "1 2 3 4 5\n" "" "" 345*cf5a6c84SAndroid Build Coastguard Workertesting "{5..1}" "echo {5..1}" "5 4 3 2 1\n" "" "" 346*cf5a6c84SAndroid Build Coastguard Workertesting "{5..1..2}" "echo {5..1..2}" "5 3 1\n" "" "" 347*cf5a6c84SAndroid Build Coastguard Workertesting "{a..z..-3}" "echo {a..z..-3}" "a d g j m p s v y\n" "" "" 348*cf5a6c84SAndroid Build Coastguard Worker 349*cf5a6c84SAndroid Build Coastguard Workermkfifo POIT 350*cf5a6c84SAndroid Build Coastguard Workertesting 'background curly block' \ 351*cf5a6c84SAndroid Build Coastguard Worker '{ sed s/ll/xx/ POIT; }& echo hello > POIT; wait && echo yes' \ 352*cf5a6c84SAndroid Build Coastguard Worker 'hexxo\nyes\n' '' '' 353*cf5a6c84SAndroid Build Coastguard Workerrm -f POIT 354*cf5a6c84SAndroid Build Coastguard Worker 355*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'background pipe block' \ 356*cf5a6c84SAndroid Build Coastguard Worker 'if true; then { sleep .25;bzcat "$FILES"/blkid/ntfs.bz2; }& fi | wc -c' \ 357*cf5a6c84SAndroid Build Coastguard Worker '8388608\n' '' '' 358*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'background variable assignment' 'X=x; X=y & echo $X' 'x\n' '' '' 359*cf5a6c84SAndroid Build Coastguard Worker 360*cf5a6c84SAndroid Build Coastguard Worker#$ IFS=x X=xyxz; for i in abc${X}def; do echo =$i=; done 361*cf5a6c84SAndroid Build Coastguard Worker#=abc= 362*cf5a6c84SAndroid Build Coastguard Worker#=y= 363*cf5a6c84SAndroid Build Coastguard Worker#=zdef= 364*cf5a6c84SAndroid Build Coastguard Worker 365*cf5a6c84SAndroid Build Coastguard Workertesting "IFS whitespace before/after" \ 366*cf5a6c84SAndroid Build Coastguard Worker 'IFS=" x"; A=" x " B=" x" C="x " D=x E=" "; for i in $A $B $C $D L$A L$B L$C L$D $A= $B= $C= $D= L$A= L$B= L$C= L$D=; do echo -n {$i}; done' \ 367*cf5a6c84SAndroid Build Coastguard Worker "{}{}{}{}{L}{L}{L}{L}{}{=}{}{=}{}{=}{}{=}{L}{=}{L}{=}{L}{=}{L}{=}" "" "" 368*cf5a6c84SAndroid Build Coastguard Workertesting "quotes and whitespace" \ 369*cf5a6c84SAndroid Build Coastguard Worker 'A=" abc def "; for i in ""$A""; do echo =$i=; done' \ 370*cf5a6c84SAndroid Build Coastguard Worker "==\n=abc=\n=def=\n==\n" "" "" 371*cf5a6c84SAndroid Build Coastguard Workertesting "quotes and whitespace2" \ 372*cf5a6c84SAndroid Build Coastguard Worker 'A=" abc def "; for i in """"$A""; do echo =$i=; done' \ 373*cf5a6c84SAndroid Build Coastguard Worker "==\n=abc=\n=def=\n==\n" "" "" 374*cf5a6c84SAndroid Build Coastguard Workertesting "quotes and whitespace3" \ 375*cf5a6c84SAndroid Build Coastguard Worker 'A=" abc def "; for i in ""x""$A""; do echo =$i=; done' \ 376*cf5a6c84SAndroid Build Coastguard Worker "=x=\n=abc=\n=def=\n==\n" "" "" 377*cf5a6c84SAndroid Build Coastguard Worker 378*cf5a6c84SAndroid Build Coastguard Workertesting "IFS" 'IFS=x; A=abx; echo -n "$A"' "abx" "" "" 379*cf5a6c84SAndroid Build Coastguard Workertesting "IFS2" 'IFS=x; A=abx; echo -n $A' "ab" "" "" 380*cf5a6c84SAndroid Build Coastguard Workertesting "IFS3" 'IFS=x; echo "$(echo abx)"' "abx\n" "" "" 381*cf5a6c84SAndroid Build Coastguard Workertesting "IFS4" 'IFS=x; echo $(echo abx)y' "ab y\n" "" "" 382*cf5a6c84SAndroid Build Coastguard Workertesting "IFS5" 'IFS=xy; for i in abcxdefyghi; do echo =$i=; done' \ 383*cf5a6c84SAndroid Build Coastguard Worker "=abc def ghi=\n" "" "" 384*cf5a6c84SAndroid Build Coastguard Workertesting "curly bracket whitespace" 'for i in {$,} ""{$,}; do echo ="$i"=; done'\ 385*cf5a6c84SAndroid Build Coastguard Worker '=$=\n=$=\n==\n' '' '' 386*cf5a6c84SAndroid Build Coastguard Worker 387*cf5a6c84SAndroid Build Coastguard Workertesting 'empty $! is blank' 'echo $!' "\n" "" "" 388*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '$! = jobs -p' 'true & [ $(jobs -p) = $! ] && echo yes' "yes\n" "" "" 389*cf5a6c84SAndroid Build Coastguard Worker 390*cf5a6c84SAndroid Build Coastguard Workertesting '$*' 'cc(){ for i in $*;do echo =$i=;done;};cc "" "" "" "" ""' \ 391*cf5a6c84SAndroid Build Coastguard Worker "" "" "" 392*cf5a6c84SAndroid Build Coastguard Workertesting '$*2' 'cc(){ for i in "$*";do echo =$i=;done;};cc ""' \ 393*cf5a6c84SAndroid Build Coastguard Worker "==\n" "" "" 394*cf5a6c84SAndroid Build Coastguard Workertesting '$*3... Flame. Flames. Flames, on the side of my face...' \ 395*cf5a6c84SAndroid Build Coastguard Worker 'cc(){ for i in "$*";do echo =$i=;done;};cc "" ""' "= =\n" "" "" 396*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'why... oh.' \ 397*cf5a6c84SAndroid Build Coastguard Worker 'cc() { echo ="$*"=; for i in =$*=; do echo -$i-; done;}; cc "" ""; echo and; cc ""' \ 398*cf5a6c84SAndroid Build Coastguard Worker '= =\n-=-\n-=-\nand\n==\n-==-\n' "" "" 399*cf5a6c84SAndroid Build Coastguard Workertesting 'really?' 'cc() { for i in $*; do echo -$i-; done;}; cc "" "" ""' \ 400*cf5a6c84SAndroid Build Coastguard Worker "" "" "" 401*cf5a6c84SAndroid Build Coastguard Workertesting 'Sigh.' 'cc() { echo =$1$2=;}; cc "" ""' "==\n" "" "" 402*cf5a6c84SAndroid Build Coastguard Workertesting '$*4' 'cc(){ for i in "$*";do echo =$i=;done;};cc "" "" "" "" ""' \ 403*cf5a6c84SAndroid Build Coastguard Worker "= =\n" "" "" 404*cf5a6c84SAndroid Build Coastguard Workertesting '$*5' 'cc(){ for i in "$*";do echo =$i=;done;};cc "" "abc" ""' \ 405*cf5a6c84SAndroid Build Coastguard Worker "= abc =\n" "" "" 406*cf5a6c84SAndroid Build Coastguard Worker 407*cf5a6c84SAndroid Build Coastguard Worker# creating empty arguments without quotes 408*cf5a6c84SAndroid Build Coastguard Workertesting '$* + IFS' \ 409*cf5a6c84SAndroid Build Coastguard Worker 'IFS=x; cc(){ for i in $*; do echo =$i=;done;};cc xabcxx' \ 410*cf5a6c84SAndroid Build Coastguard Worker "==\n=abc=\n==\n" "" "" 411*cf5a6c84SAndroid Build Coastguard Workertesting '$@' 'cc(){ for i in "$@";do echo =$i=;done;};cc "" "" "" "" ""' \ 412*cf5a6c84SAndroid Build Coastguard Worker "==\n==\n==\n==\n==\n" "" "" 413*cf5a6c84SAndroid Build Coastguard Workertesting "IFS10" 'IFS=bcd; A=abcde; for i in $A; do echo =$i=; done' \ 414*cf5a6c84SAndroid Build Coastguard Worker "=a=\n==\n==\n=e=\n" "" "" 415*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing "IFS11" \ 416*cf5a6c84SAndroid Build Coastguard Worker 'IFS=x; chicken() { for i in $@$@; do echo =$i=; done;}; chicken one "" abc dxf ghi' \ 417*cf5a6c84SAndroid Build Coastguard Worker "=one=\n==\n=abc=\n=d=\n=f=\n=ghione=\n==\n=abc=\n=d=\n=f=\n=ghi=\n" "" "" 418*cf5a6c84SAndroid Build Coastguard Workertesting "IFS12" 'IFS=3;chicken(){ return 3;}; chicken;echo 3$?3' '3 3\n' "" "" 419*cf5a6c84SAndroid Build Coastguard Worker 420*cf5a6c84SAndroid Build Coastguard Workertesting "IFS combinations" \ 421*cf5a6c84SAndroid Build Coastguard Worker 'IFS=" x"; A=" x " B=" x" C="x " D=x E=" "; for i in $A $B $C $D L$A L$B L$C L$D $A= $B= $C= $D= L$A= L$B= L$C= L$D=; do echo -n {$i}; done' \ 422*cf5a6c84SAndroid Build Coastguard Worker "{}{}{}{}{L}{L}{L}{L}{}{=}{}{=}{}{=}{}{=}{L}{=}{L}{=}{L}{=}{L}{=}" "" "" 423*cf5a6c84SAndroid Build Coastguard Worker 424*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing "! isn't special" "echo !" "!\n" "" "" 425*cf5a6c84SAndroid Build Coastguard Workertesting "! by itself" '!; echo $?' "1\n" "" "" 426*cf5a6c84SAndroid Build Coastguard Workertesting "! true" '! true; echo $?' "1\n" "" "" 427*cf5a6c84SAndroid Build Coastguard Workertesting "! ! true" '! ! true; echo $?' "0\n" "" "" 428*cf5a6c84SAndroid Build Coastguard Workertesting "! syntax err" '! echo 2>/dev/null < doesnotexist; echo $?' "0\n" "" "" 429*cf5a6c84SAndroid Build Coastguard Worker 430*cf5a6c84SAndroid Build Coastguard Worker# The bash man page doesn't say quote removal here, and yet: 431*cf5a6c84SAndroid Build Coastguard Workertesting "case quoting" 'case a in "a") echo hello;; esac' 'hello\n' "" "" 432*cf5a6c84SAndroid Build Coastguard Worker 433*cf5a6c84SAndroid Build Coastguard Workertesting "subshell splitting" 'for i in $(true); do echo =$i=; done' "" "" "" 434*cf5a6c84SAndroid Build Coastguard Workertesting "subshell split 2" 'for i in $(echo "one two thr"); do echo =$i=; done'\ 435*cf5a6c84SAndroid Build Coastguard Worker "=one=\n=two=\n=thr=\n" "" "" 436*cf5a6c84SAndroid Build Coastguard Worker 437*cf5a6c84SAndroid Build Coastguard Worker# variable assignment argument splitting only performed for "$@" 438*cf5a6c84SAndroid Build Coastguard Workertesting "assignment nosplit" 'X="one two"; Y=$X; echo $Y' "one two\n" "" "" 439*cf5a6c84SAndroid Build Coastguard Workertesting "argument splitting" \ 440*cf5a6c84SAndroid Build Coastguard Worker 'chicken() { for i in a"$@"b;do echo =$i=;done;}; chicken 123 456 789' \ 441*cf5a6c84SAndroid Build Coastguard Worker "=a123=\n=456=\n=789b=\n" "" "" 442*cf5a6c84SAndroid Build Coastguard Workertesting "assignment nosplit2" 'pop(){ X="$@";};pop one two three; echo $X' \ 443*cf5a6c84SAndroid Build Coastguard Worker "one two three\n" "" "" 444*cf5a6c84SAndroid Build Coastguard Worker 445*cf5a6c84SAndroid Build Coastguard Worker#testing "leading assignments don't affect current line" \ 446*cf5a6c84SAndroid Build Coastguard Worker# 'VAR=12345 echo ${VAR}a' "a\n" "" "" 447*cf5a6c84SAndroid Build Coastguard Worker#testing "can't have space before first : but yes around arguments" \ 448*cf5a6c84SAndroid Build Coastguard Worker# 'BLAH=abcdefghi; echo ${BLAH: 1 : 3 }' "bcd\n" "" "" 449*cf5a6c84SAndroid Build Coastguard Worker 450*cf5a6c84SAndroid Build Coastguard Workertesting "subshell exit err" '(exit 42); echo $?' "42\n" "" "" 451*cf5a6c84SAndroid Build Coastguard Worker 452*cf5a6c84SAndroid Build Coastguard Worker# Same thing twice, but how do we cmp if exec exited? 453*cf5a6c84SAndroid Build Coastguard Worker#testing 'exec and $$' testing 'echo $$;exec readlink /proc/self' 454*cf5a6c84SAndroid Build Coastguard Worker 455*cf5a6c84SAndroid Build Coastguard WorkerX="$(realpath $(which readlink))" 456*cf5a6c84SAndroid Build Coastguard Workertesting "exec in paren" \ 457*cf5a6c84SAndroid Build Coastguard Worker '(exec readlink /proc/self/exe);echo hello' "$X\nhello\n" "" "" 458*cf5a6c84SAndroid Build Coastguard Workertesting "exec in brackets" \ 459*cf5a6c84SAndroid Build Coastguard Worker "{ exec readlink /proc/self/exe;};echo hi" "$X\n" "" "" 460*cf5a6c84SAndroid Build Coastguard Worker 461*cf5a6c84SAndroid Build Coastguard WorkerNOSPACE=1 testing "curly brackets and pipe" \ 462*cf5a6c84SAndroid Build Coastguard Worker '{ echo one; echo two ; } | tee blah.txt; wc blah.txt' \ 463*cf5a6c84SAndroid Build Coastguard Worker "one\ntwo\n2 2 8 blah.txt\n" "" "" 464*cf5a6c84SAndroid Build Coastguard WorkerNOSPACE=1 testing "parentheses and pipe" \ 465*cf5a6c84SAndroid Build Coastguard Worker '(echo two;echo three)|tee blah.txt;wc blah.txt' \ 466*cf5a6c84SAndroid Build Coastguard Worker "two\nthree\n2 2 10 blah.txt\n" "" "" 467*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing "pipe into parentheses" \ 468*cf5a6c84SAndroid Build Coastguard Worker 'echo hello | (read i <input; echo $i; read i; echo $i)' \ 469*cf5a6c84SAndroid Build Coastguard Worker "there\nhello\n" "there\n" "" 470*cf5a6c84SAndroid Build Coastguard Worker 471*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing "\$''" $'echo $\'abc\\\'def\\nghi\'' "abc'def\nghi\n" '' '' 472*cf5a6c84SAndroid Build Coastguard Workertesting "shift shift" 'shift; shift; shift; echo $? hello' "1 hello\n" "" "" 473*cf5a6c84SAndroid Build Coastguard Workertesting 'search cross $*' 'chicken() { echo ${*/b c/ghi}; }; chicken a b c d' \ 474*cf5a6c84SAndroid Build Coastguard Worker "a b c d\n" "" "" 475*cf5a6c84SAndroid Build Coastguard Workertesting 'eval $IFS' 'IFS=x; X=x; eval abc=a${X}b 2>/dev/null; echo $abc' \ 476*cf5a6c84SAndroid Build Coastguard Worker "\n" '' '' 477*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${@:3:5}' 'chicken() { for i in "${@:3:5}"; do echo =$i=; done; } ; chicken ab cd ef gh ij kl mn op qr' \ 478*cf5a6c84SAndroid Build Coastguard Worker '=ef=\n=gh=\n=ij=\n=kl=\n=mn=\n' '' '' 479*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${*:3:5}' 'chicken() { for i in "${*:3:5}"; do unset IFS; echo =$i=; done; } ; IFS=x chicken ab cd ef gh ij kl mn op qr' \ 480*cf5a6c84SAndroid Build Coastguard Worker '=efxghxijxklxmn=\n' '' '' 481*cf5a6c84SAndroid Build Coastguard Workertesting 'sequence check' 'IFS=x; X=abxcd; echo ${X/bxc/g}' 'agd\n' '' '' 482*cf5a6c84SAndroid Build Coastguard Worker 483*cf5a6c84SAndroid Build Coastguard Worker# TODO: The txpect plumbing does not work right yet even on TEST_HOST 484*cf5a6c84SAndroid Build Coastguard Worker#txpect "backtick0" "$SS" "E$P" 'IX=fred; echo `echo \\\\$x`'$'\n' 'Ofred' "E$P" X0 485*cf5a6c84SAndroid Build Coastguard Worker#txpect "backtick1" "$SS" "E$P" 'IX=fred; echo `echo $x`'$'\n' 'Ofred'$'\n' "E$P" X0 486*cf5a6c84SAndroid Build Coastguard Worker#txpect "backtick2" "$SS" "E$P" 'IX=fred; echo `x=y; echo $x`' $'Oy\n' "E$P" X0 487*cf5a6c84SAndroid Build Coastguard Worker 488*cf5a6c84SAndroid Build Coastguard Workershxpect '${ with newline' I$'HELLO=abc; echo ${HELLO/b/\n' E"> " I$'}\n' O$'a c\n' 489*cf5a6c84SAndroid Build Coastguard Worker 490*cf5a6c84SAndroid Build Coastguard Workertesting 'here0' 'cat<<<hello' 'hello\n' '' '' 491*cf5a6c84SAndroid Build Coastguard Workershxpect 'here1' I$'POTATO=123; cat << EOF\n' E"> " \ 492*cf5a6c84SAndroid Build Coastguard Worker I$'$POTATO\n' E"> " I$'EOF\n' O$'123\n' 493*cf5a6c84SAndroid Build Coastguard Workershxpect 'here2' I$'POTATO=123; cat << E"O"F\n' E"> " \ 494*cf5a6c84SAndroid Build Coastguard Worker I$'$POTATO\n' E"> " I$'EOF\n' O$'$POTATO\n' 495*cf5a6c84SAndroid Build Coastguard Workertesting 'here3' 'abc(){ cat <<< x"$@"yz;};abc one two "three four"' \ 496*cf5a6c84SAndroid Build Coastguard Worker "xone two three fouryz\n" "" "" 497*cf5a6c84SAndroid Build Coastguard Workertesting 'here4' 'for i in one two three; do cat <<< "ab${i}de"; done' \ 498*cf5a6c84SAndroid Build Coastguard Worker 'abonede\nabtwode\nabthreede\n' '' '' 499*cf5a6c84SAndroid Build Coastguard Workertesting 'here5' $'cat << EOF && cat << EOF2\nEOF2\nEOF\nEOF\nEOF2' \ 500*cf5a6c84SAndroid Build Coastguard Worker 'EOF2\nEOF\n' '' '' 501*cf5a6c84SAndroid Build Coastguard Worker# Nothing is actually quoted, but there are quotes, therefore... 502*cf5a6c84SAndroid Build Coastguard Workertesting 'here6' $'cat << EOF""\n$POTATO\nEOF' '$POTATO\n' '' '' 503*cf5a6c84SAndroid Build Coastguard Worker# Not ambiguous when split, unlike <$FILENAME redirects 504*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'here7' 'ABC="abc def"; cat <<< $ABC' 'abc def\n' '' '' 505*cf5a6c84SAndroid Build Coastguard Worker# What does HERE expansion _not_ expand? 506*cf5a6c84SAndroid Build Coastguard Workertesting 'here8' $'ABC="x y"\ncat << EOF\n~root/{"$ABC",def}\nEOF' \ 507*cf5a6c84SAndroid Build Coastguard Worker '~root/{"x y",def}\n' '' '' 508*cf5a6c84SAndroid Build Coastguard Workertesting '<<- eats leading tabs before expansion, but not after' \ 509*cf5a6c84SAndroid Build Coastguard Worker $'A=$\'\\tone\'; cat <<- EOF\n\t\t$A\n\ttwo\nEOF' "\tone\ntwo\n" '' '' 510*cf5a6c84SAndroid Build Coastguard Worker 511*cf5a6c84SAndroid Build Coastguard Workertesting '${var}' 'X=abcdef; echo ${X}' 'abcdef\n' '' '' 512*cf5a6c84SAndroid Build Coastguard Workertesting '${#}' 'X=abcdef; echo ${#X}' "6\n" "" "" 513*cf5a6c84SAndroid Build Coastguard Workertesting 'empty ${}' '{ echo ${};} 2>&1 | grep -o bad' 'bad\n' '' '' 514*cf5a6c84SAndroid Build Coastguard Worker$BROKEN shxpect 'empty ${} syntax err abort' I$'echo ${}; echo hello\n' \ 515*cf5a6c84SAndroid Build Coastguard Worker E I$'echo and\n' O$'and\n' 516*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${$b}' '{ echo ${$b};} 2>&1 | grep -o bad' 'bad\n' '' '' 517*cf5a6c84SAndroid Build Coastguard Workertesting '${!PATH*}' 'echo ${!PATH*}' 'PATH\n' '' '' 518*cf5a6c84SAndroid Build Coastguard Workertesting '${!PATH@}' 'echo ${!PATH@}' 'PATH\n' '' '' 519*cf5a6c84SAndroid Build Coastguard Worker#testing '${!PATH[@]}' 'echo ${!PATH[@]}' '0\n' '' '' 520*cf5a6c84SAndroid Build Coastguard Workertesting '${!x}' 'X=abcdef Y=X; echo ${!Y}' 'abcdef\n' '' '' 521*cf5a6c84SAndroid Build Coastguard Workertesting '${!x@}' 'ABC=def; def=ghi; echo ${!ABC@}' 'ABC\n' '' '' 522*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${!x} err' '{ X=abcdef Y=X:2; echo ${!Y}; echo bang;} 2>/dev/null' \ 523*cf5a6c84SAndroid Build Coastguard Worker '' '' '' 524*cf5a6c84SAndroid Build Coastguard Workertesting '${!x*}' 'abcdef=1 abc=2 abcq=; echo "${!abc@}" | tr " " \\n | sort' \ 525*cf5a6c84SAndroid Build Coastguard Worker 'abc\nabcdef\nabcq\n' '' '' 526*cf5a6c84SAndroid Build Coastguard Workertesting '${!x*} none' 'echo "${!abc*}"' '\n' '' '' 527*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${!x*} err' '{ echo "${!abc*x}"; echo boing;} 2>/dev/null' '' '' '' 528*cf5a6c84SAndroid Build Coastguard Worker# TODO bash 5.x broke this 529*cf5a6c84SAndroid Build Coastguard Worker#testing '${!none@Q}' 'echo ${X@Q} ${!X@Q}; X=ABC; echo ${!X@Q}' '\n\n' '' '' 530*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${!x@Q}' 'ABC=123 X=ABC; echo ${!X@Q}' "'123'\n" '' '' 531*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${#@Q}' 'echo ${#@Q}' "'0'\n" '' '' 532*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${!*}' 'xx() { echo ${!*};}; fruit=123; xx fruit' '123\n' '' '' 533*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${!*} indirect' 'xx() { echo ${!a@Q};}; a=@; xx one two three' \ 534*cf5a6c84SAndroid Build Coastguard Worker "'one' 'two' 'three'\n" '' '' 535*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${!x@ } match' \ 536*cf5a6c84SAndroid Build Coastguard Worker '{ ABC=def; def=ghi; echo ${!ABC@ }; } 2>&1 | grep -o bad' 'bad\n' '' '' 537*cf5a6c84SAndroid Build Coastguard Worker# Bash added an error for this between 4.4 and 5.x. 538*cf5a6c84SAndroid Build Coastguard Worker#testing '${!x@ } no match no err' 'echo ${!ABC@ }def' 'def\n' '' '' 539*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${!x@ } no match no err2' 'ABC=def; echo ${!ABC@ }ghi' 'ghi\n' '' '' 540*cf5a6c84SAndroid Build Coastguard Workertoyonly testing '${#x::}' 'ABC=abcdefghijklmno; echo ${#ABC:1:2}' '5\n' '' '' 541*cf5a6c84SAndroid Build Coastguard Worker# TODO: ${!abc@x} does _not_ error? And ${PWD@q} 542*cf5a6c84SAndroid Build Coastguard Workertesting '$""' 'ABC=def; echo $"$ABC"' 'def\n' '' '' 543*cf5a6c84SAndroid Build Coastguard Workertesting '"$""" does not nest' 'echo "$"abc""' '$abc\n' '' '' 544*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${\}}' 'ABC=ab}cd; echo ${ABC/\}/x}' 'abxcd\n' '' '' 545*cf5a6c84SAndroid Build Coastguard Workertesting 'bad ${^}' '{ echo ${^};} 2>&1 | grep -o bad' 'bad\n' '' '' 546*cf5a6c84SAndroid Build Coastguard Workershxpect '${:} empty len is err' I$'ABC=def; echo ${ABC:}\n' RE'ABC' X 547*cf5a6c84SAndroid Build Coastguard Workertesting '${::} both empty=0' 'ABC=def; echo ${ABC::}' '\n' '' '' 548*cf5a6c84SAndroid Build Coastguard Workertesting '${::} first empty' 'ABC=def; echo ${ABC: : 2 }' 'de\n' '' '' 549*cf5a6c84SAndroid Build Coastguard Workertesting '${::} second empty' 'ABC=def; echo ${ABC: 2 : }' '\n' '' '' 550*cf5a6c84SAndroid Build Coastguard Workertesting '${:}' 'ABC=def; echo ${ABC:1}' 'ef\n' '' '' 551*cf5a6c84SAndroid Build Coastguard Workertesting '${a: }' 'ABC=def; echo ${ABC: 1}' 'ef\n' '' '' 552*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${a :}' 'ABC=def; { echo ${ABC :1};} 2>&1 | grep -o bad' 'bad\n' '' '' 553*cf5a6c84SAndroid Build Coastguard Workertesting '${::}' 'ABC=defghi; echo ${ABC:1:2}' 'ef\n' '' '' 554*cf5a6c84SAndroid Build Coastguard Workertesting '${: : }' 'ABC=defghi; echo ${ABC: 1 : 2 }' 'ef\n' '' '' 555*cf5a6c84SAndroid Build Coastguard Workertesting '${::} indirect' \ 556*cf5a6c84SAndroid Build Coastguard Worker 'ABC=defghi:1:2; ( echo ${!ABC};) 2>input; [ -s input ] && echo yes' \ 557*cf5a6c84SAndroid Build Coastguard Worker 'yes\n' '' '' 558*cf5a6c84SAndroid Build Coastguard Workertesting '${::-}' 'ABC=defghi; echo ${ABC:1:-2}' 'efg\n' '' '' 559*cf5a6c84SAndroid Build Coastguard Workertesting '${:-:-}' 'ABC=defghi; echo ${ABC:-3:2}' 'defghi\n' '' '' 560*cf5a6c84SAndroid Build Coastguard Workertesting '${:-:-}2' 'echo ${ABC:-3:2}' '3:2\n' '' '' 561*cf5a6c84SAndroid Build Coastguard Workertesting '${: -:}' 'ABC=defghi; echo ${ABC: -3:2}' 'gh\n' '' '' 562*cf5a6c84SAndroid Build Coastguard Workertesting '${@%}' 'chicken() { for i in "${@%abc}"; do echo "=$i="; done;}; chicken 1abc 2abc 3abc' '=1=\n=2=\n=3=\n' '' '' 563*cf5a6c84SAndroid Build Coastguard Workertesting '${*%}' 'chicken() { for i in "${*%abc}"; do echo "=$i="; done;}; chicken 1abc 2abc 3abc' '=1 2 3=\n' '' '' 564*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '${@@Q}' 'xx() { echo "${@@Q}"; }; xx one two three' \ 565*cf5a6c84SAndroid Build Coastguard Worker "'one' 'two' 'three'\n" '' '' 566*cf5a6c84SAndroid Build Coastguard Worker 567*cf5a6c84SAndroid Build Coastguard Workershxpect '${/newline/}' I$'x=$\'\na\';echo ${x/\n' E'> ' I$'/b}\n' O$'ba\n' E'> ' 568*cf5a6c84SAndroid Build Coastguard Worker 569*cf5a6c84SAndroid Build Coastguard Workershxpect 'line continuation' I$'echo "hello" \\\n' E'> ' I$'> blah\n' E"$P" \ 570*cf5a6c84SAndroid Build Coastguard Worker I$'wc blah\n' O$'1 1 6 blah\n' 571*cf5a6c84SAndroid Build Coastguard Workershxpect 'line continuation2' I$'echo ABC\\\n' E'> ' I$'DEF\n' O$'ABCDEF\n' 572*cf5a6c84SAndroid Build Coastguard Workertesting "line continuation3" $'ec\\\nho hello' 'hello\n' '' '' 573*cf5a6c84SAndroid Build Coastguard Workertesting "line continuation4" $'if true | \\\n(true);then echo true;fi' 'true\n' '' '' 574*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing "line continuation5" $'XYZ=xyz; echo "abc$\\\nXYZ"' 'abcxyz\n' '' '' 575*cf5a6c84SAndroid Build Coastguard Worker 576*cf5a6c84SAndroid Build Coastguard Worker# Race condition (in bash, but not in toysh) can say 43. 577*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'SECONDS' 'readonly SECONDS=41; sleep 1; echo $SECONDS' '42\n' '' '' 578*cf5a6c84SAndroid Build Coastguard Worker# testing 'SECONDS2' 'readonly SECONDS; SECONDS=0; echo $SECONDS' '' '' '' #bash! 579*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'SECONDS2' 'SECONDS=123+456; echo $SECONDS' '0\n' '' '' #bash!! 580*cf5a6c84SAndroid Build Coastguard Workertesting '$LINENO 2' $'echo $LINENO\necho $LINENO' '1\n2\n' '' '' 581*cf5a6c84SAndroid Build Coastguard Workertesting '$EUID' 'echo $EUID' "$(id -u)\n" '' '' 582*cf5a6c84SAndroid Build Coastguard Workertesting '$UID' 'echo $UID' "$(id -ur)\n" '' '' 583*cf5a6c84SAndroid Build Coastguard Worker 584*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'readonly leading assignment' \ 585*cf5a6c84SAndroid Build Coastguard Worker '{ readonly abc=123;abc=def echo hello; echo $?;} 2>output; grep -o readonly output' \ 586*cf5a6c84SAndroid Build Coastguard Worker 'hello\n0\nreadonly\n' '' '' 587*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'readonly leading assignment2' \ 588*cf5a6c84SAndroid Build Coastguard Worker 'readonly boink=123; export boink; { boink=234 env | grep ^boink=;} 2>/dev/null; echo $?' 'boink=123\n0\n' '' '' 589*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'readonly for' \ 590*cf5a6c84SAndroid Build Coastguard Worker 'readonly i; for i in one two three; do echo $i; done 2>/dev/null; echo $?' \ 591*cf5a6c84SAndroid Build Coastguard Worker '1\n' '' '' 592*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'readonly {}<' \ 593*cf5a6c84SAndroid Build Coastguard Worker 'readonly i; echo hello 2>/dev/null {i}</dev/null; echo $?' '1\n' '' '' 594*cf5a6c84SAndroid Build Coastguard Workertesting '$_ 1' 'echo walrus; echo $_' 'walrus\nwalrus\n' '' '' 595*cf5a6c84SAndroid Build Coastguard Workertesting '$_ 2' 'unset _; echo $_' '_\n' '' '' 596*cf5a6c84SAndroid Build Coastguard Worker 597*cf5a6c84SAndroid Build Coastguard Worker# wildcards 598*cf5a6c84SAndroid Build Coastguard Worker 599*cf5a6c84SAndroid Build Coastguard Workertouch walrus wallpapers 600*cf5a6c84SAndroid Build Coastguard Workertesting 'IFS wildcards' \ 601*cf5a6c84SAndroid Build Coastguard Worker 'IFS=xy; ABC=abcywal*sxdef; echo $ABC | tr " " "\n" | sort' \ 602*cf5a6c84SAndroid Build Coastguard Worker 'abc\ndef\nwallpapers\nwalrus\n' '' '' 603*cf5a6c84SAndroid Build Coastguard Workerrm -f walrus wallpapers 604*cf5a6c84SAndroid Build Coastguard Worker 605*cf5a6c84SAndroid Build Coastguard Worker# Force parsing granularity via interactive shxpect because bash parses all 606*cf5a6c84SAndroid Build Coastguard Worker# of sh -c "str" in one go, meaning the "shopt -s extglob" won't take effect 607*cf5a6c84SAndroid Build Coastguard Worker$BROKEN shxpect 'IFS +(extglob)' I$'shopt -s extglob\n' E"$P" \ 608*cf5a6c84SAndroid Build Coastguard Worker I$'IFS=x; ABC=cxd; for i in +($ABC); do echo =$i=; done\n' \ 609*cf5a6c84SAndroid Build Coastguard Worker O$'=+(c=\n' O$'=d)=\n' 610*cf5a6c84SAndroid Build Coastguard Worker 611*cf5a6c84SAndroid Build Coastguard Workertouch abc\)d 612*cf5a6c84SAndroid Build Coastguard Worker$BROKEN shxpect 'IFS +(extglob) 2' I$'shopt -s extglob\n' E"$P" \ 613*cf5a6c84SAndroid Build Coastguard Worker I$'ABC="c?d"; for i in ab+($ABC); do echo =$i=; done\n' \ 614*cf5a6c84SAndroid Build Coastguard Worker O$'=abc)d=\n' 615*cf5a6c84SAndroid Build Coastguard Workerrm abc\)d 616*cf5a6c84SAndroid Build Coastguard Worker 617*cf5a6c84SAndroid Build Coastguard Worker$BROKEN shxpect '[+(]) overlap priority' I$'shopt -s extglob\n' E"$P" \ 618*cf5a6c84SAndroid Build Coastguard Worker I$'touch "AB[DEF]"; echo AB[+(DEF]) AB[+(DEF)? AB+([DEF)]\n' \ 619*cf5a6c84SAndroid Build Coastguard Worker O$'AB[+(DEF]) AB[DEF] AB+([DEF)]\n' \ 620*cf5a6c84SAndroid Build Coastguard Worker I$'X="("; Y=")"; echo AB[+${X}DEF${Y}?\n' O$'AB[DEF]\n' 621*cf5a6c84SAndroid Build Coastguard Worker 622*cf5a6c84SAndroid Build Coastguard Worker# TODO: syntax error takes out ': ${a?b}; echo $?' (I.E. never runs echo) 623*cf5a6c84SAndroid Build Coastguard Workershxpect '${a?b} sets err, stops cmdline eval' \ 624*cf5a6c84SAndroid Build Coastguard Worker I$': ${a?b} ${c:=d}\n' E E"$P" I$'echo $?$c\n' O$'1\n' 625*cf5a6c84SAndroid Build Coastguard Worker 626*cf5a6c84SAndroid Build Coastguard Worker$BROKEN shxpect 'trace redirect' I$'set -x; echo one\n' E$'+ echo one\n'"$P" O$'one\n' \ 627*cf5a6c84SAndroid Build Coastguard Worker I$'echo two 2>/dev/null\n' O$'two\n' E$'+ echo two\n'"$P" \ 628*cf5a6c84SAndroid Build Coastguard Worker I$'{ echo three; } 2>/dev/null\n' O$'three\n' E"$P" 629*cf5a6c84SAndroid Build Coastguard Workershxpect 'set -u' I$'set -u; echo $walrus\n' REwalrus X 630*cf5a6c84SAndroid Build Coastguard Worker 631*cf5a6c84SAndroid Build Coastguard Workertesting 'source file' 'source input' 'hello\n' 'echo hello \\\n' '' 632*cf5a6c84SAndroid Build Coastguard Workertesting '. file' '. input' 'hello\n' 'echo hello \\\n' '' 633*cf5a6c84SAndroid Build Coastguard Workertesting 'source no newline' 'source input' 'hello \\\n' 'echo hello \\' '' 634*cf5a6c84SAndroid Build Coastguard Workertesting 'source continues' 'echo hello; source <(echo false); echo $?' \ 635*cf5a6c84SAndroid Build Coastguard Worker 'hello\n1\n' '' '' 636*cf5a6c84SAndroid Build Coastguard Workertesting 'source returns' 'source <(echo return 37); echo $?' '37\n' '' '' 637*cf5a6c84SAndroid Build Coastguard Workertesting 'source is live' \ 638*cf5a6c84SAndroid Build Coastguard Worker 'for i in one two three; do echo "echo $i" > input; source input; done' \ 639*cf5a6c84SAndroid Build Coastguard Worker 'one\ntwo\nthree\n' 'x' '' 640*cf5a6c84SAndroid Build Coastguard Workertesting 'source is live in functions' \ 641*cf5a6c84SAndroid Build Coastguard Worker 'func() { source input; }; for i in one two three; do echo echo $i > input; func; done' \ 642*cf5a6c84SAndroid Build Coastguard Worker 'one\ntwo\nthree\n' 'x' '' 643*cf5a6c84SAndroid Build Coastguard Workertesting 'subshell inheritance' \ 644*cf5a6c84SAndroid Build Coastguard Worker 'func() { source input; cat <(echo $xx; xx=456; echo $xx); echo $xx;}; echo local xx=123 > input; func; echo $xx' \ 645*cf5a6c84SAndroid Build Coastguard Worker '123\n456\n123\n\n' 'x' '' 646*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'semicolon vs newline' \ 647*cf5a6c84SAndroid Build Coastguard Worker 'source input 2>/dev/null || echo yes' 'one\nyes\n' \ 648*cf5a6c84SAndroid Build Coastguard Worker 'echo one\necho two; echo |' '' 649*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'syntax err pops to source but encapsulating function continues' \ 650*cf5a6c84SAndroid Build Coastguard Worker 'func() { echo one; source <(echo -e "echo hello\necho |") 2>/dev/null; echo three;}; func; echo four' \ 651*cf5a6c84SAndroid Build Coastguard Worker 'one\nhello\nthree\nfour\n' '' '' 652*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '"exit shell" means exit eval but encapsulating function continues' \ 653*cf5a6c84SAndroid Build Coastguard Worker 'func() { eval "echo one; echo \${?potato}; echo and" 2>/dev/null; echo plus;}; func; echo then' \ 654*cf5a6c84SAndroid Build Coastguard Worker 'one\nplus\nthen\n' '' '' 655*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'return needs function or source' \ 656*cf5a6c84SAndroid Build Coastguard Worker 'cat <(return 0 2>/dev/null; echo $?); echo after' '2\nafter\n' '' '' 657*cf5a6c84SAndroid Build Coastguard Workertesting 'return nests' 'y(){ x; return $((3+$?));};x(){ return 5; };y;echo $?' \ 658*cf5a6c84SAndroid Build Coastguard Worker '8\n' '' '' 659*cf5a6c84SAndroid Build Coastguard Worker 660*cf5a6c84SAndroid Build Coastguard Workershxpect "functions need block" I$'x() echo;\n' RE'[Ss]yntax [Ee]rror' X2 661*cf5a6c84SAndroid Build Coastguard Workertesting 'functions() {} in same PID' \ 662*cf5a6c84SAndroid Build Coastguard Worker '{ echo $BASHPID; chicken() { echo $BASHPID;}; chicken;} | sort -u | wc -l' '1\n' '' '' 663*cf5a6c84SAndroid Build Coastguard Workertesting 'functions() () different PID' \ 664*cf5a6c84SAndroid Build Coastguard Worker '{ echo $BASHPID; chicken() ( echo $BASHPID;); chicken;} | sort -u | wc -l' '2\n' '' '' 665*cf5a6c84SAndroid Build Coastguard Workertesting 'function() just wants any block span' \ 666*cf5a6c84SAndroid Build Coastguard Worker 'func() if true; then echo hello; fi; echo one; func; echo two' \ 667*cf5a6c84SAndroid Build Coastguard Worker 'one\nhello\ntwo\n' '' '' 668*cf5a6c84SAndroid Build Coastguard Workertesting 'function alternate syntax' \ 669*cf5a6c84SAndroid Build Coastguard Worker 'function func if true; then echo hello; fi; echo one; func; echo two' \ 670*cf5a6c84SAndroid Build Coastguard Worker 'one\nhello\ntwo\n' '' '' 671*cf5a6c84SAndroid Build Coastguard Workertesting 'function syntax 3' \ 672*cf5a6c84SAndroid Build Coastguard Worker 'function func ( ) if true; then echo hello; fi; echo one; func; echo two' \ 673*cf5a6c84SAndroid Build Coastguard Worker 'one\nhello\ntwo\n' '' '' 674*cf5a6c84SAndroid Build Coastguard Workertesting 'function nested parentheses' \ 675*cf5a6c84SAndroid Build Coastguard Worker '( potato() { echo aaa; }; potato )' 'aaa\n' '' '' 676*cf5a6c84SAndroid Build Coastguard Workershxpect 'local creates a whiteout' \ 677*cf5a6c84SAndroid Build Coastguard Worker I$'func() { local potato; echo ${potato?bang}; }; potato=123; func\n' \ 678*cf5a6c84SAndroid Build Coastguard Worker E E"$P" I$'echo $?\n' O$'1\n' 679*cf5a6c84SAndroid Build Coastguard Workertesting 'local replaces/preserves magic type' \ 680*cf5a6c84SAndroid Build Coastguard Worker 'x() { local RANDOM=potato; echo $RANDOM;};x;echo -e "$RANDOM\n$RANDOM"|wc -l'\ 681*cf5a6c84SAndroid Build Coastguard Worker 'potato\n2\n' '' '' 682*cf5a6c84SAndroid Build Coastguard Worker 683*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '$$ is parent shell' \ 684*cf5a6c84SAndroid Build Coastguard Worker '{ echo $$; (echo $$) } | sort -u | wc -l' "1\n" "" "" 685*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '$PPID is parent shell' \ 686*cf5a6c84SAndroid Build Coastguard Worker '{ echo $PPID; (echo $PPID) } | sort -u | wc -l' "1\n" "" "" 687*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '$BASHPID is current PID' \ 688*cf5a6c84SAndroid Build Coastguard Worker '{ echo $BASHPID; (echo $BASHPID) } | sort -u | wc -l' "2\n" "" "" 689*cf5a6c84SAndroid Build Coastguard Worker 690*cf5a6c84SAndroid Build Coastguard Workertesting 'unexport supports +=' 'export -n ABC+=DEF; declare -p ABC' \ 691*cf5a6c84SAndroid Build Coastguard Worker 'declare -- ABC="DEF"\n' '' '' 692*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'unexport existing +=' \ 693*cf5a6c84SAndroid Build Coastguard Worker 'export ABC=XYZ; export -n ABC+=DEF; declare -p ABC' \ 694*cf5a6c84SAndroid Build Coastguard Worker 'declare -- ABC="XYZDEF"\n' '' '' 695*cf5a6c84SAndroid Build Coastguard Worker 696*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '$!' '{ echo $BASHPID & echo $!; echo ${!};} | sort -u | wc -l' '1\n' \ 697*cf5a6c84SAndroid Build Coastguard Worker '' '' 698*cf5a6c84SAndroid Build Coastguard Worker 699*cf5a6c84SAndroid Build Coastguard Workershxpect 'blank line preserves $?' \ 700*cf5a6c84SAndroid Build Coastguard Worker I$'false\n' E"$P" I$'\n' E"$P" I$'echo $?\n' O$'1\n' 701*cf5a6c84SAndroid Build Coastguard Workertesting 'NOP line clears $?' 'false;$NOTHING;echo $?' '0\n' '' '' 702*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing 'run "$@"' 'false;"$@";echo $?' '0\n' '' '' 703*cf5a6c84SAndroid Build Coastguard Worker 704*cf5a6c84SAndroid Build Coastguard Worker# "Word splitting... not performed on the words between the [[ and ]]" 705*cf5a6c84SAndroid Build Coastguard Workertesting '[[split1]]' 'A="1 -lt 2"; [[ $A ]] && echo yes' 'yes\n' '' '' 706*cf5a6c84SAndroid Build Coastguard Workertesting '[[split2]]' 'A="2 -lt 1"; [[ $A ]] && echo yes' 'yes\n' '' '' 707*cf5a6c84SAndroid Build Coastguard Workertesting '[[split3]]' \ 708*cf5a6c84SAndroid Build Coastguard Worker 'A="2 -lt 1"; [[ -e $A ]] && echo one; touch "$A" && [[ -e $A ]] && echo two'\ 709*cf5a6c84SAndroid Build Coastguard Worker 'two\n' '' '' 710*cf5a6c84SAndroid Build Coastguard Workerrm -f '2 -lt 1' 711*cf5a6c84SAndroid Build Coastguard Workertesting '[[split4]]' \ 712*cf5a6c84SAndroid Build Coastguard Worker '[[ $(cat) == "a b" ]] <<< "a b" > potato && rm potato && echo ok' \ 713*cf5a6c84SAndroid Build Coastguard Worker 'ok\n' '' '' 714*cf5a6c84SAndroid Build Coastguard Worker$BROKEN testing '[[split5]]' \ 715*cf5a6c84SAndroid Build Coastguard Worker '[[ $(cat) == "a b" ]] < <(echo a b) > potato && rm potato && echo ok' \ 716*cf5a6c84SAndroid Build Coastguard Worker 'ok\n' '' '' 717*cf5a6c84SAndroid Build Coastguard Worker# And token parsing leaking through: 1>2 is an error, 1 >2 is not 718*cf5a6c84SAndroid Build Coastguard Workertesting '[[1>2]] is not a redirect' '[[ 1 >2 ]] || [ -e 2 ] || echo yup' \ 719*cf5a6c84SAndroid Build Coastguard Worker 'yup\n' '' '' 720*cf5a6c84SAndroid Build Coastguard Workertesting "[[1 >0]] doesn't need that second space" \ 721*cf5a6c84SAndroid Build Coastguard Worker '[[ 1 >0 ]] && { [ -e 2 ] || echo yup; }' 'yup\n' '' '' 722*cf5a6c84SAndroid Build Coastguard Workertesting '[[1<2]] is alphabetical, not numeric' '[[ 123 < 19 ]] && echo yes' \ 723*cf5a6c84SAndroid Build Coastguard Worker 'yes\n' '' '' 724*cf5a6c84SAndroid Build Coastguard Workertesting '[[~]]' '[[ ~ == $HOME ]] && echo yes' 'yes\n' '' '' 725*cf5a6c84SAndroid Build Coastguard Worker 726*cf5a6c84SAndroid Build Coastguard Worker# The trailing space is because the \n gets stripped off otherwise 727*cf5a6c84SAndroid Build Coastguard Workertesting 'quoting contexts nest' \ 728*cf5a6c84SAndroid Build Coastguard Worker $'echo -n "$(echo "hello $(eval $\'echo -\\\\\\ne \\\'world\\n \\\'\')")"' \ 729*cf5a6c84SAndroid Build Coastguard Worker 'hello world\n ' '' '' 730*cf5a6c84SAndroid Build Coastguard Workertesting "\$'' suppresses variable expansion" \ 731*cf5a6c84SAndroid Build Coastguard Worker $'echo $\'$(abc\'' '$(abc\n' '' '' 732*cf5a6c84SAndroid Build Coastguard Worker 733*cf5a6c84SAndroid Build Coastguard Workertesting 'if; is a syntax error but if $EMPTY; is not' \ 734*cf5a6c84SAndroid Build Coastguard Worker 'if $NONE; then echo hello; fi' 'hello\n' '' '' 735*cf5a6c84SAndroid Build Coastguard Worker 736*cf5a6c84SAndroid Build Coastguard Worker# TODO finish variable list from shell init 737*cf5a6c84SAndroid Build Coastguard Worker 738*cf5a6c84SAndroid Build Coastguard Worker# $# $? $- $! $0 # $$ 739*cf5a6c84SAndroid Build Coastguard Worker# always exported: PWD SHLVL _ 740*cf5a6c84SAndroid Build Coastguard Worker# ./bash -c 'echo $_' prints $BASH, but PATH search shows path? Hmmm... 741*cf5a6c84SAndroid Build Coastguard Worker# ro: UID PPID EUID $ 742*cf5a6c84SAndroid Build Coastguard Worker# IFS LINENO 743*cf5a6c84SAndroid Build Coastguard Worker# PATH HOME SHELL USER LOGNAME SHLVL HOSTNAME HOSTTYPE MACHTYPE OSTYPE OLDPWD 744*cf5a6c84SAndroid Build Coastguard Worker# PS0 PS1='$ ' PS2='> ' PS3 PS4 BASH BASH_VERSION 745*cf5a6c84SAndroid Build Coastguard Worker# ENV - if [ -n "$ENV" ]; then . "$ENV"; fi # BASH_ENV - synonym for ENV 746*cf5a6c84SAndroid Build Coastguard Worker# FUNCNEST - maximum function nesting level (abort when above) 747*cf5a6c84SAndroid Build Coastguard Worker# REPLY - set by input with no args 748*cf5a6c84SAndroid Build Coastguard Worker# OPTARG OPTIND - set by getopts builtin 749*cf5a6c84SAndroid Build Coastguard Worker# OPTERR 750*cf5a6c84SAndroid Build Coastguard Worker 751*cf5a6c84SAndroid Build Coastguard Worker# maybe not: EXECIGNORE, FIGNORE, GLOBIGNORE 752*cf5a6c84SAndroid Build Coastguard Worker 753*cf5a6c84SAndroid Build Coastguard Worker#BASH_SUBSHELL - SHLVL synonym 754*cf5a6c84SAndroid Build Coastguard Worker#BASH_EXECUTION_STRING - -c argument 755*cf5a6c84SAndroid Build Coastguard Worker# 756*cf5a6c84SAndroid Build Coastguard Worker#automatically set: 757*cf5a6c84SAndroid Build Coastguard Worker#OPTARG - set by getopts builtin 758*cf5a6c84SAndroid Build Coastguard Worker#OPTIND - set by getopts builtin 759*cf5a6c84SAndroid Build Coastguard Worker# 760*cf5a6c84SAndroid Build Coastguard Worker#PROMPT_COMMAND PROMPT_DIRTRIM PS0 PS1 PS2 PS3 PS4 761*cf5a6c84SAndroid Build Coastguard Worker# 762*cf5a6c84SAndroid Build Coastguard Worker#unsettable (assignments ignored before then) 763*cf5a6c84SAndroid Build Coastguard Worker#LINENO SECONDS RANDOM 764*cf5a6c84SAndroid Build Coastguard Worker#GROUPS - id -g 765*cf5a6c84SAndroid Build Coastguard Worker#HISTCMD - history number 766*cf5a6c84SAndroid Build Coastguard Worker# 767*cf5a6c84SAndroid Build Coastguard Worker#TMOUT - used by read 768*cf5a6c84SAndroid Build Coastguard Worker 769*cf5a6c84SAndroid Build Coastguard Worker# does not match: ./sh -c 'echo {a..Z}' becomes a ` _ ^ ] \ [ Z 770*cf5a6c84SAndroid Build Coastguard Worker 771*cf5a6c84SAndroid Build Coastguard Worker# commit ec6639407b9e 772*cf5a6c84SAndroid Build Coastguard Worker#- IS_TOYBOX_RE='(toybox|This is not GNU).*' 773*cf5a6c84SAndroid Build Coastguard Worker#- [[ "$IS_TOYBOX" =~ $IS_TOYBOX_RE ]] || SKIPNEXT=1 774*cf5a6c84SAndroid Build Coastguard Worker#+ case "$IS_TOYBOX" in 775*cf5a6c84SAndroid Build Coastguard Worker#+ toybox*) ;; 776*cf5a6c84SAndroid Build Coastguard Worker#+ This\ is\ not\ GNU*) ;; 777*cf5a6c84SAndroid Build Coastguard Worker#+ *) SKIPNEXT=1 ;; 778*cf5a6c84SAndroid Build Coastguard Worker#+ esac 779*cf5a6c84SAndroid Build Coastguard Worker 780*cf5a6c84SAndroid Build Coastguard Worker# TODO: categorize tests 781*cf5a6c84SAndroid Build Coastguard Worker 782*cf5a6c84SAndroid Build Coastguard Worker# TODO https://mywiki.wooledge.org/BashFAQ 783*cf5a6c84SAndroid Build Coastguard Worker# http://tiswww.case.edu/php/chet/bash/FAQ 784*cf5a6c84SAndroid Build Coastguard Worker# https://mywiki.wooledge.org/BashPitfalls#set_-euo_pipefail 785*cf5a6c84SAndroid Build Coastguard Worker 786*cf5a6c84SAndroid Build Coastguard Worker# // ${#} ${#x} ${#@} ${#x[@]} ${#!} ${!#} 787*cf5a6c84SAndroid Build Coastguard Worker# // ${!} ${!@} ${!@Q} ${!x} ${!x@} ${!x@Q} ${!x#} ${!x[} ${!x[*]} 788*cf5a6c84SAndroid Build Coastguard Worker 789*cf5a6c84SAndroid Build Coastguard Worker# Looked like a prefix but wasn't: three chars (@ # -) are both paremeter name 790*cf5a6c84SAndroid Build Coastguard Worker# and slice operator. When immediately followed by } it's parameter, otherwise 791*cf5a6c84SAndroid Build Coastguard Worker# we did NOT have a prefix and it's an operator. 792*cf5a6c84SAndroid Build Coastguard Worker# 793*cf5a6c84SAndroid Build Coastguard Worker# ${#-} ${#-abc} 794*cf5a6c84SAndroid Build Coastguard Worker# ${##} ${##0} 795*cf5a6c84SAndroid Build Coastguard Worker# ${#@} ${#@Q} 796*cf5a6c84SAndroid Build Coastguard Worker# 797*cf5a6c84SAndroid Build Coastguard Worker# backslash not discarded: echo "abc\"def" 798*cf5a6c84SAndroid Build Coastguard Worker 799*cf5a6c84SAndroid Build Coastguard Worker# ${x:-y} use default 800*cf5a6c84SAndroid Build Coastguard Worker# ${x:=y} assign default (error if positional) 801*cf5a6c84SAndroid Build Coastguard Worker# ${x:?y} err if null 802*cf5a6c84SAndroid Build Coastguard Worker# ${x:+y} alt value 803*cf5a6c84SAndroid Build Coastguard Worker# ${x:off} ${x:off:len} off<0 from end (must ": -"), len<0 also from end must 804*cf5a6c84SAndroid Build Coastguard Worker# 0-based indexing 805*cf5a6c84SAndroid Build Coastguard Worker# ${@:off:len} positional parameters, off -1 = len, -len is error 806*cf5a6c84SAndroid Build Coastguard Worker# 1-based indexing 807*cf5a6c84SAndroid Build Coastguard Worker 808*cf5a6c84SAndroid Build Coastguard Worker# [] wins over +() 809*cf5a6c84SAndroid Build Coastguard Worker# touch 'AB[DEF]'; echo AB[+(DEF]) AB[+(DEF)? 810*cf5a6c84SAndroid Build Coastguard Worker# AB[+(DEF]) AB[DEF] 811*cf5a6c84SAndroid Build Coastguard Worker 812*cf5a6c84SAndroid Build Coastguard Worker# Testing shell corner cases _within_ a shell script is kind of hard. 813