1da2e3ebdSchin######################################################################## 2da2e3ebdSchin# # 3da2e3ebdSchin# This software is part of the ast package # 4b30d1939SAndy Fiddaman# Copyright (c) 1982-2012 AT&T Intellectual Property # 5da2e3ebdSchin# and is licensed under the # 6b30d1939SAndy Fiddaman# Eclipse Public License, Version 1.0 # 77c2fbfb3SApril Chin# by AT&T Intellectual Property # 8da2e3ebdSchin# # 9da2e3ebdSchin# A copy of the License is available at # 10b30d1939SAndy Fiddaman# http://www.eclipse.org/org/documents/epl-v10.html # 11b30d1939SAndy Fiddaman# (with md5 checksum b35adb5213ca9657e911e9befb180842) # 12da2e3ebdSchin# # 13da2e3ebdSchin# Information and Software Systems Research # 14da2e3ebdSchin# AT&T Research # 15da2e3ebdSchin# Florham Park NJ # 16da2e3ebdSchin# # 17da2e3ebdSchin# David Korn <dgk@research.att.com> # 18da2e3ebdSchin# # 19da2e3ebdSchin######################################################################## 20da2e3ebdSchinfunction err_exit 21da2e3ebdSchin{ 22da2e3ebdSchin print -u2 -n "\t" 23da2e3ebdSchin print -u2 -r ${Command}[$1]: "${@:2}" 24da2e3ebdSchin let Errors+=1 25da2e3ebdSchin} 26da2e3ebdSchinalias err_exit='err_exit $LINENO' 27da2e3ebdSchin 28da2e3ebdSchinCommand=${0##*/} 29da2e3ebdSchininteger Errors=0 3034f9b3eeSRoland Mainz 3134f9b3eeSRoland Mainztmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; } 3234f9b3eeSRoland Mainztrap "cd /; rm -rf $tmp" EXIT 3334f9b3eeSRoland Mainz 3434f9b3eeSRoland Mainz# test basic file operations like redirection, pipes, file expansion 357c2fbfb3SApril Chinset -- \ 367c2fbfb3SApril Chin go+r 0000 \ 377c2fbfb3SApril Chin go-r 0044 \ 387c2fbfb3SApril Chin ug=r 0330 \ 397c2fbfb3SApril Chin go+w 0000 \ 407c2fbfb3SApril Chin go-w 0022 \ 417c2fbfb3SApril Chin ug=w 0550 \ 427c2fbfb3SApril Chin go+x 0000 \ 437c2fbfb3SApril Chin go-x 0011 \ 447c2fbfb3SApril Chin ug=x 0660 \ 457c2fbfb3SApril Chin go-rx 0055 \ 467c2fbfb3SApril Chin uo-wx 0303 \ 477c2fbfb3SApril Chin ug-rw 0660 \ 487c2fbfb3SApril Chin o= 0007 497c2fbfb3SApril Chinwhile (( $# >= 2 )) 507c2fbfb3SApril Chindo umask 0 517c2fbfb3SApril Chin umask $1 527c2fbfb3SApril Chin g=$(umask) 537c2fbfb3SApril Chin [[ $g == $2 ]] || err_exit "umask 0; umask $1 failed -- expected $2, got $g" 547c2fbfb3SApril Chin shift 2 557c2fbfb3SApril Chindone 56da2e3ebdSchinumask u=rwx,go=rx || err_exit "umask u=rws,go=rx failed" 57da2e3ebdSchinif [[ $(umask -S) != u=rwx,g=rx,o=rx ]] 58da2e3ebdSchinthen err_exit 'umask -S incorrect' 59da2e3ebdSchinfi 60da2e3ebdSchinpwd=$PWD 61da2e3ebdSchin[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL 6234f9b3eeSRoland Mainzcd $tmp || { err_exit "cd $tmp failed"; exit 1; } 637c2fbfb3SApril Chinum=$(umask -S) 647c2fbfb3SApril Chin( umask 0777; > foobar ) 657c2fbfb3SApril Chinrm -f foobar 667c2fbfb3SApril Chin> foobar 677c2fbfb3SApril Chin[[ -r foobar ]] || err_exit 'umask not being restored after subshell' 687c2fbfb3SApril Chinumask "$um" 697c2fbfb3SApril Chinrm -f foobar 70da2e3ebdSchin# optimizer bug test 71da2e3ebdSchin> foobar 72da2e3ebdSchinfor i in 1 2 73da2e3ebdSchindo print foobar* 74da2e3ebdSchin rm -f foobar 7534f9b3eeSRoland Mainzdone > out 7634f9b3eeSRoland Mainzif [[ "$(<out)" != "foobar"$'\n'"foobar*" ]] 77da2e3ebdSchinthen print -u2 "optimizer bug with file expansion" 78da2e3ebdSchinfi 7934f9b3eeSRoland Mainzrm -f out foobar 80da2e3ebdSchinmkdir dir 81da2e3ebdSchinif [[ $(print */) != dir/ ]] 82da2e3ebdSchinthen err_exit 'file expansion with trailing / not working' 83da2e3ebdSchinfi 84da2e3ebdSchinif [[ $(print *) != dir ]] 85da2e3ebdSchinthen err_exit 'file expansion with single file not working' 86da2e3ebdSchinfi 87da2e3ebdSchinprint hi > .foo 88da2e3ebdSchinif [[ $(print *) != dir ]] 89da2e3ebdSchinthen err_exit 'file expansion leading . not working' 90da2e3ebdSchinfi 91da2e3ebdSchindate > dat1 || err_exit "date > dat1 failed" 92da2e3ebdSchintest -r dat1 || err_exit "dat1 is not readable" 93da2e3ebdSchinx=dat1 94da2e3ebdSchincat <$x > dat2 || err_exit "cat < $x > dat2 failed" 95da2e3ebdSchincat dat1 dat2 | cat | cat | cat > dat3 || err_exit "cat pipe failed" 96da2e3ebdSchincat > dat4 <<! 97da2e3ebdSchin$(date) 98da2e3ebdSchin! 99da2e3ebdSchincat dat1 dat2 | cat | cat | cat > dat5 & 100da2e3ebdSchinwait $! 101da2e3ebdSchinset -- dat* 102da2e3ebdSchinif (( $# != 5 )) 103da2e3ebdSchinthen err_exit "dat* matches only $# files" 104da2e3ebdSchinfi 10534f9b3eeSRoland Mainzif (command > foo\\abc) 2> /dev/null 106da2e3ebdSchinthen set -- foo* 107da2e3ebdSchin if [[ $1 != 'foo\abc' ]] 108da2e3ebdSchin then err_exit 'foo* does not match foo\abc' 109da2e3ebdSchin fi 110da2e3ebdSchinfi 111da2e3ebdSchinif ( : > TT* && : > TTfoo ) 2>/dev/null 112da2e3ebdSchinthen set -- TT* 113da2e3ebdSchin if (( $# < 2 )) 114da2e3ebdSchin then err_exit 'TT* not expanding when file TT* exists' 115da2e3ebdSchin fi 116da2e3ebdSchinfi 117da2e3ebdSchincd ~- || err_exit "cd back failed" 11834f9b3eeSRoland Mainzcat > $tmp/script <<- ! 119da2e3ebdSchin #! $SHELL 120da2e3ebdSchin print -r -- \$0 121da2e3ebdSchin! 12234f9b3eeSRoland Mainzchmod 755 $tmp/script 12334f9b3eeSRoland Mainzif [[ $($tmp/script) != "$tmp/script" ]] 124da2e3ebdSchinthen err_exit '$0 not correct for #! script' 125da2e3ebdSchinfi 126da2e3ebdSchinbar=foo 127da2e3ebdSchineval foo=\$bar 128da2e3ebdSchinif [[ $foo != foo ]] 129da2e3ebdSchinthen err_exit 'eval foo=\$bar not working' 130da2e3ebdSchinfi 131da2e3ebdSchinbar='foo=foo\ bar' 132da2e3ebdSchineval $bar 133da2e3ebdSchinif [[ $foo != 'foo bar' ]] 134da2e3ebdSchinthen err_exit 'eval foo=\$bar, with bar="foo\ bar" not working' 135da2e3ebdSchinfi 136da2e3ebdSchincd /tmp 137da2e3ebdSchincd ../../tmp || err_exit "cd ../../tmp failed" 138da2e3ebdSchinif [[ $PWD != /tmp ]] 139da2e3ebdSchinthen err_exit 'cd ../../tmp is not /tmp' 140da2e3ebdSchinfi 141da2e3ebdSchin( sleep 2; cat <<! 142da2e3ebdSchinfoobar 143da2e3ebdSchin! 14434f9b3eeSRoland Mainz) | cat > $tmp/foobar & 145da2e3ebdSchinwait $! 14634f9b3eeSRoland Mainzfoobar=$( < $tmp/foobar) 147da2e3ebdSchinif [[ $foobar != foobar ]] 148da2e3ebdSchinthen err_exit "$foobar is not foobar" 149da2e3ebdSchinfi 150da2e3ebdSchin{ 151da2e3ebdSchin print foo 152da2e3ebdSchin /bin/echo bar 153da2e3ebdSchin print bam 15434f9b3eeSRoland Mainz} > $tmp/foobar 15534f9b3eeSRoland Mainzif [[ $( < $tmp/foobar) != $'foo\nbar\nbam' ]] 15634f9b3eeSRoland Mainzthen err_exit "output file pointer not shared correctly" 157da2e3ebdSchinfi 15834f9b3eeSRoland Mainzcat > $tmp/foobar <<\! 159da2e3ebdSchin print foo 160da2e3ebdSchin /bin/echo bar 161da2e3ebdSchin print bam 162da2e3ebdSchin! 16334f9b3eeSRoland Mainzchmod +x $tmp/foobar 16434f9b3eeSRoland Mainzif [[ $($tmp/foobar) != $'foo\nbar\nbam' ]] 16534f9b3eeSRoland Mainzthen err_exit "script not working" 166da2e3ebdSchinfi 16734f9b3eeSRoland Mainzif [[ $($tmp/foobar | /bin/cat) != $'foo\nbar\nbam' ]] 16834f9b3eeSRoland Mainzthen err_exit "script | cat not working" 169da2e3ebdSchinfi 17034f9b3eeSRoland Mainzif [[ $( $tmp/foobar) != $'foo\nbar\nbam' ]] 17134f9b3eeSRoland Mainzthen err_exit "output file pointer not shared correctly" 172da2e3ebdSchinfi 17334f9b3eeSRoland Mainzrm -f $tmp/foobar 174da2e3ebdSchinx=$( (print foo) ; (print bar) ) 175da2e3ebdSchinif [[ $x != $'foo\nbar' ]] 176da2e3ebdSchinthen err_exit " ( (print foo);(print bar ) failed" 177da2e3ebdSchinfi 178da2e3ebdSchinx=$( (/bin/echo foo) ; (print bar) ) 179da2e3ebdSchinif [[ $x != $'foo\nbar' ]] 180da2e3ebdSchinthen err_exit " ( (/bin/echo);(print bar ) failed" 181da2e3ebdSchinfi 182da2e3ebdSchinx=$( (/bin/echo foo) ; (/bin/echo bar) ) 183da2e3ebdSchinif [[ $x != $'foo\nbar' ]] 184da2e3ebdSchinthen err_exit " ( (/bin/echo);(/bin/echo bar ) failed" 185da2e3ebdSchinfi 18634f9b3eeSRoland Mainzcat > $tmp/script <<\! 187da2e3ebdSchinif [[ -p /dev/fd/0 ]] 188da2e3ebdSchinthen builtin cat 189da2e3ebdSchin cat - > /dev/null 190da2e3ebdSchin [[ -p /dev/fd/0 ]] && print ok 191da2e3ebdSchinelse print no 192da2e3ebdSchinfi 193da2e3ebdSchin! 19434f9b3eeSRoland Mainzchmod +x $tmp/script 19534f9b3eeSRoland Mainzcase $( (print) | $tmp/script;:) in 196da2e3ebdSchinok) ;; 197da2e3ebdSchinno) err_exit "[[ -p /dev/fd/0 ]] fails for standard input pipe" ;; 198da2e3ebdSchin*) err_exit "builtin replaces standard input pipe" ;; 199da2e3ebdSchinesac 20034f9b3eeSRoland Mainzprint 'print $0' > $tmp/script 20134f9b3eeSRoland Mainzprint ". $tmp/script" > $tmp/scriptx 20234f9b3eeSRoland Mainzchmod +x $tmp/scriptx 20334f9b3eeSRoland Mainzif [[ $($tmp/scriptx) != $tmp/scriptx ]] 204da2e3ebdSchinthen err_exit '$0 not correct for . script' 205da2e3ebdSchinfi 20634f9b3eeSRoland Mainzcd $tmp || { err_exit "cd $tmp failed"; exit 1; } 20734f9b3eeSRoland Mainzprint ./b > ./a; print ./c > b; print ./d > c; print ./e > d; print "echo \"hello there\"" > e 208da2e3ebdSchinchmod 755 a b c d e 209da2e3ebdSchinx=$(./a) 210da2e3ebdSchinif [[ $x != "hello there" ]] 21134f9b3eeSRoland Mainzthen err_exit "nested scripts failed" 212da2e3ebdSchinfi 213da2e3ebdSchinx=$( (./a) | cat) 214da2e3ebdSchinif [[ $x != "hello there" ]] 21534f9b3eeSRoland Mainzthen err_exit "scripts in subshells fail" 216da2e3ebdSchinfi 217da2e3ebdSchincd ~- || err_exit "cd back failed" 218da2e3ebdSchinx=$( (/bin/echo foo) 2> /dev/null ) 219da2e3ebdSchinif [[ $x != foo ]] 220da2e3ebdSchinthen err_exit "subshell in command substitution fails" 221da2e3ebdSchinfi 222b30d1939SAndy Fiddamanexec 9>& 1 223da2e3ebdSchinexec 1>&- 224da2e3ebdSchinx=$(print hello) 225da2e3ebdSchinif [[ $x != hello ]] 226da2e3ebdSchinthen err_exit "command subsitution with stdout closed failed" 227da2e3ebdSchinfi 228b30d1939SAndy Fiddamanexec >& 9 229da2e3ebdSchincd $pwd 230da2e3ebdSchinx=$(cat <<\! | $SHELL 231da2e3ebdSchin/bin/echo | /bin/cat 232da2e3ebdSchin/bin/echo hello 233da2e3ebdSchin! 234da2e3ebdSchin) 235da2e3ebdSchinif [[ $x != $'\n'hello ]] 236da2e3ebdSchinthen err_exit "$SHELL not working when standard input is a pipe" 237da2e3ebdSchinfi 238da2e3ebdSchinx=$( (/bin/echo hello) 2> /dev/null ) 239da2e3ebdSchinif [[ $x != hello ]] 240da2e3ebdSchinthen err_exit "subshell in command substitution with 1 closed fails" 241da2e3ebdSchinfi 24234f9b3eeSRoland Mainzcat > $tmp/script <<- \! 243da2e3ebdSchinread line 2> /dev/null 244da2e3ebdSchinprint done 245da2e3ebdSchin! 24634f9b3eeSRoland Mainzif [[ $($SHELL $tmp/script <&-) != done ]] 247da2e3ebdSchinthen err_exit "executing script with 0 closed fails" 248da2e3ebdSchinfi 249da2e3ebdSchintrap '' INT 25034f9b3eeSRoland Mainzcat > $tmp/script <<- \! 251da2e3ebdSchintrap 'print bad' INT 252da2e3ebdSchinkill -s INT $$ 253da2e3ebdSchinprint good 254da2e3ebdSchin! 25534f9b3eeSRoland Mainzchmod +x $tmp/script 25634f9b3eeSRoland Mainzif [[ $($SHELL $tmp/script) != good ]] 257da2e3ebdSchinthen err_exit "traps ignored by parent not ignored" 258da2e3ebdSchinfi 259da2e3ebdSchintrap - INT 26034f9b3eeSRoland Mainzcat > $tmp/script <<- \! 261da2e3ebdSchinread line 262da2e3ebdSchin/bin/cat 263da2e3ebdSchin! 26434f9b3eeSRoland Mainzif [[ $($SHELL $tmp/script <<! 265da2e3ebdSchinone 266da2e3ebdSchintwo 267da2e3ebdSchin! 268da2e3ebdSchin) != two ]] 269da2e3ebdSchinthen err_exit "standard input not positioned correctly" 270da2e3ebdSchinfi 271da2e3ebdSchinword=$(print $'foo\nbar' | { read line; /bin/cat;}) 272da2e3ebdSchinif [[ $word != bar ]] 273da2e3ebdSchinthen err_exit "pipe to { read line; /bin/cat;} not working" 274da2e3ebdSchinfi 275da2e3ebdSchinword=$(print $'foo\nbar' | ( read line; /bin/cat) ) 276da2e3ebdSchinif [[ $word != bar ]] 277da2e3ebdSchinthen err_exit "pipe to ( read line; /bin/cat) not working" 278da2e3ebdSchinfi 279da2e3ebdSchinif [[ $(print x{a,b}y) != 'xay xby' ]] 280da2e3ebdSchinthen err_exit 'brace expansion not working' 281da2e3ebdSchinfi 282da2e3ebdSchinif [[ $(for i in foo bar 283da2e3ebdSchin do ( tgz=$(print $i) 284da2e3ebdSchin print $tgz) 285da2e3ebdSchin done) != $'foo\nbar' ]] 286da2e3ebdSchinthen err_exit 'for loop subshell optimizer bug' 287da2e3ebdSchinfi 288da2e3ebdSchinunset a1 289da2e3ebdSchinoptbug() 290da2e3ebdSchin{ 291da2e3ebdSchin set -A a1 foo bar bam 292da2e3ebdSchin integer i 293da2e3ebdSchin for ((i=0; i < 3; i++)) 294da2e3ebdSchin do 295da2e3ebdSchin (( ${#a1[@]} < 2 )) && return 0 296da2e3ebdSchin set -- "${a1[@]}" 297da2e3ebdSchin shift 298da2e3ebdSchin set -A a1 -- "$@" 299da2e3ebdSchin done 300da2e3ebdSchin return 1 301da2e3ebdSchin} 302da2e3ebdSchinoptbug || err_exit 'array size optimzation bug' 3037c2fbfb3SApril Chinwait # not running --pipefail which would interfere with subsequent tests 304da2e3ebdSchin: $(jobs -p) # required to clear jobs for next jobs -p (interactive side effect) 305da2e3ebdSchinsleep 20 & 3067c2fbfb3SApril Chinpids=$! 307da2e3ebdSchinif [[ $(jobs -p) != $! ]] 30834f9b3eeSRoland Mainzthen err_exit 'jobs -p not reporting a background job' 309da2e3ebdSchinfi 310da2e3ebdSchinsleep 20 & 3117c2fbfb3SApril Chinpids="$pids $!" 312da2e3ebdSchinfoo() 313da2e3ebdSchin{ 314da2e3ebdSchin set -- $(jobs -p) 315da2e3ebdSchin (( $# == 2 )) || err_exit "$# jobs not reported -- 2 expected" 316da2e3ebdSchin} 317da2e3ebdSchinfoo 3187c2fbfb3SApril Chinkill $pids 3197c2fbfb3SApril Chin 3207c2fbfb3SApril Chin[[ $( (trap 'print alarm' ALRM; sleep 4) & sleep 2; kill -ALRM $!; sleep 2; wait) == alarm ]] || err_exit 'ALRM signal not working' 321da2e3ebdSchin[[ $($SHELL -c 'trap "" HUP; $SHELL -c "(sleep 2;kill -HUP $$)& sleep 4;print done"') != done ]] && err_exit 'ignored traps not being ignored' 322da2e3ebdSchin[[ $($SHELL -c 'o=foobar; for x in foo bar; do (o=save);print $o;done' 2> /dev/null ) == $'foobar\nfoobar' ]] || err_exit 'for loop optimization subshell bug' 323da2e3ebdSchincommand exec 3<> /dev/null 324b30d1939SAndy Fiddamanif cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null 325da2e3ebdSchinthen [[ $($SHELL -c 'cat <(print foo)' 2> /dev/null) == foo ]] || err_exit 'process substitution not working' 32634f9b3eeSRoland Mainz [[ $($SHELL -c $'tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!! 327da2e3ebdSchin line0 328da2e3ebdSchin line1 329da2e3ebdSchin line2 330da2e3ebdSchin !!! 331da2e3ebdSchin wait 33234f9b3eeSRoland Mainz cat '$tmp/scriptx 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails' 33334f9b3eeSRoland Mainz > $tmp/scriptx 334da2e3ebdSchin [[ $($SHELL -c $' 335da2e3ebdSchin for i in 1 33634f9b3eeSRoland Mainz do tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!! 337da2e3ebdSchin line0 338da2e3ebdSchin line1 339da2e3ebdSchin line2 340da2e3ebdSchin !!! 341da2e3ebdSchin done 342da2e3ebdSchin wait 34334f9b3eeSRoland Mainz cat '$tmp/scriptx 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop' 344da2e3ebdSchin [[ $({ $SHELL -c 'cat <(for i in x y z; do print $i; done)';} 2> /dev/null) == $'x\ny\nz' ]] || 345da2e3ebdSchin err_exit 'process substitution of compound commands not working' 346da2e3ebdSchinfi 347da2e3ebdSchin[[ $($SHELL -r 'command -p :' 2>&1) == *restricted* ]] || err_exit 'command -p not restricted' 34834f9b3eeSRoland Mainzprint cat > $tmp/scriptx 34934f9b3eeSRoland Mainzchmod +x $tmp/scriptx 35034f9b3eeSRoland Mainz[[ $($SHELL -c "print foo | $tmp/scriptx ;:" 2> /dev/null ) == foo ]] || err_exit 'piping into script fails' 351da2e3ebdSchin[[ $($SHELL -c 'X=1;print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 1 ]] || err_exit 'x=1;${x:=$(..."...")} failure' 352da2e3ebdSchin[[ $($SHELL -c 'print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 0 ]] || err_exit '${x:=$(..."...")} failure' 353b30d1939SAndy Fiddamanif cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null 354da2e3ebdSchinthen [[ $(cat <(print hello) ) == hello ]] || err_exit "process substitution not working outside for or while loop" 355da2e3ebdSchin $SHELL -c '[[ $(for i in 1;do cat <(print hello);done ) == hello ]]' 2> /dev/null|| err_exit "process substitution not working in for or while loop" 356da2e3ebdSchinfi 357da2e3ebdSchinexec 3> /dev/null 35834f9b3eeSRoland Mainzprint 'print foo "$@"' > $tmp/scriptx 35934f9b3eeSRoland Mainz[[ $( print "($tmp/scriptx bar)" | $SHELL 2>/dev/null) == 'foo bar' ]] || err_exit 'script pipe to shell fails' 36034f9b3eeSRoland Mainzprint "#! $SHELL" > $tmp/scriptx 36134f9b3eeSRoland Mainzprint 'print -- $0' >> $tmp/scriptx 36234f9b3eeSRoland Mainzchmod +x $tmp/scriptx 36334f9b3eeSRoland Mainz[[ $($tmp/scriptx) == $tmp/scriptx ]] || err_exit "\$0 is $0 instead of $tmp/scriptx" 36434f9b3eeSRoland Mainzcat > $tmp/scriptx <<- \EOF 3657c2fbfb3SApril Chin myfilter() { x=$(print ok | cat); print -r -- $SECONDS;} 3667c2fbfb3SApril Chin set -o pipefail 3677c2fbfb3SApril Chin sleep 3 | myfilter 3687c2fbfb3SApril ChinEOF 36934f9b3eeSRoland Mainz(( $($SHELL $tmp/scriptx) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang' 370da2e3ebdSchinexec 3<&- 371da2e3ebdSchin( typeset -r foo=bar) 2> /dev/null || err_exit 'readonly variables set in a subshell cannot unset' 3727c2fbfb3SApril Chin$SHELL -c 'x=${ print hello;}; [[ $x == hello ]]' 2> /dev/null || err_exit '${ command;} not supported' 3737c2fbfb3SApril Chin$SHELL 2> /dev/null <<- \EOF || err_exit 'multiline ${...} command substitution not supported' 3747c2fbfb3SApril Chin x=${ 3757c2fbfb3SApril Chin print hello 3767c2fbfb3SApril Chin } 3777c2fbfb3SApril Chin [[ $x == hello ]] 3787c2fbfb3SApril ChinEOF 3797c2fbfb3SApril Chin$SHELL 2> /dev/null <<- \EOF || err_exit '${...} command substitution with side effects not supported ' 3807c2fbfb3SApril Chin y=bye 3817c2fbfb3SApril Chin x=${ 3827c2fbfb3SApril Chin y=hello 3837c2fbfb3SApril Chin print hello 3847c2fbfb3SApril Chin } 3857c2fbfb3SApril Chin [[ $y == $x ]] 3867c2fbfb3SApril ChinEOF 3877c2fbfb3SApril Chin$SHELL 2> /dev/null <<- \EOF || err_exit 'nested ${...} command substitution not supported' 3887c2fbfb3SApril Chin x=${ 3897c2fbfb3SApril Chin print ${ print hello;} $(print world) 3907c2fbfb3SApril Chin } 3917c2fbfb3SApril Chin [[ $x == 'hello world' ]] 3927c2fbfb3SApril ChinEOF 3937c2fbfb3SApril Chin$SHELL 2> /dev/null <<- \EOF || err_exit 'terminating } is not a reserved word with ${ command }' 3947c2fbfb3SApril Chin x=${ { print -n } ; print -n hello ; } ; print ' world' } 3957c2fbfb3SApril Chin [[ $x == '}hello world' ]] 3967c2fbfb3SApril ChinEOF 3977c2fbfb3SApril Chin$SHELL 2> /dev/null <<- \EOF || err_exit '${ command;}xxx not working' 3987c2fbfb3SApril Chin f() 3997c2fbfb3SApril Chin { 4007c2fbfb3SApril Chin print foo 4017c2fbfb3SApril Chin } 4027c2fbfb3SApril Chin [[ ${ f;}bar == foobar ]] 4037c2fbfb3SApril ChinEOF 4047c2fbfb3SApril Chin 4057c2fbfb3SApril Chinunset foo 40634f9b3eeSRoland Mainz[[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset' 40734f9b3eeSRoland Mainz[[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset' 4087c2fbfb3SApril Chin[[ $(print "[${ print foo }]") == '[foo]' ]] || err_exit '${...} not working when } is followed by ]' 4097c2fbfb3SApril Chin[[ $(print "${ print "[${ print foo }]" }") == '[foo]' ]] || err_exit 'nested ${...} not working when } is followed by ]' 4107c2fbfb3SApril Chinunset foo 4117c2fbfb3SApril Chinfoo=$(false) > /dev/null && err_exit 'failed command substitution with redirection not returning false' 4127c2fbfb3SApril Chinexpected=foreback 413b30d1939SAndy Fiddamangot=$(print -n fore; (sleep 2;print back)&) 4147c2fbfb3SApril Chin[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'" 4157c2fbfb3SApril Chin 41634f9b3eeSRoland Mainzbinfalse=$(whence -p false) 41734f9b3eeSRoland Mainzfor false in false $binfalse 4187c2fbfb3SApril Chindo x=$($false) && err_exit "x=\$($false) should fail" 4197c2fbfb3SApril Chin $($false) && err_exit "\$($false) should fail" 4207c2fbfb3SApril Chin $($false) > /dev/null && err_exit "\$($false) > /dev/null should fail" 4217c2fbfb3SApril Chindone 42234f9b3eeSRoland Mainzif env x-a=y >/dev/null 2>&1 42334f9b3eeSRoland Mainzthen [[ $(env 'x-a=y' $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved' 42434f9b3eeSRoland Mainzfi 42534f9b3eeSRoland Mainzfloat s=SECONDS 42634f9b3eeSRoland Mainzsleep=$(whence -p sleep) 42734f9b3eeSRoland Mainzfor i in 1 2 42834f9b3eeSRoland Mainzdo print $i 42934f9b3eeSRoland Mainzdone | while read sec; do ( $sleep $sec; $sleep $sec) done 43034f9b3eeSRoland Mainz(( (SECONDS-s) < 4)) && err_exit '"command | while read...done" finishing too fast' 43134f9b3eeSRoland Mainzs=SECONDS 43234f9b3eeSRoland Mainzset -o pipefail 43334f9b3eeSRoland Mainzfor ((i=0; i < 30; i++)) 43434f9b3eeSRoland Mainzdo print hello 43534f9b3eeSRoland Mainz sleep .1 43634f9b3eeSRoland Mainzdone | $sleep 1 43734f9b3eeSRoland Mainz(( (SECONDS-s) < 2 )) || err_exit 'early termination not causing broken pipe' 43834f9b3eeSRoland Mainz[[ $({ trap 'print trap' 0; print -n | $(whence -p cat); } & wait $!) == trap ]] || err_exit 'trap on exit not getting triggered' 43934f9b3eeSRoland Mainzvar=$({ trap 'print trap' ERR; print -n | $binfalse; } & wait $!) 44034f9b3eeSRoland Mainz[[ $var == trap ]] || err_exit 'trap on ERR not getting triggered' 44134f9b3eeSRoland Mainz 44234f9b3eeSRoland Mainzexp= 44334f9b3eeSRoland Mainzgot=$( 44434f9b3eeSRoland Mainz function fun 44534f9b3eeSRoland Mainz { 44634f9b3eeSRoland Mainz $binfalse && echo FAILED 44734f9b3eeSRoland Mainz } 44834f9b3eeSRoland Mainz : works if this line deleted : | 44934f9b3eeSRoland Mainz fun 45034f9b3eeSRoland Mainz : works if this line deleted : 45134f9b3eeSRoland Mainz) 45234f9b3eeSRoland Mainz[[ $got == $exp ]] || err_exit "pipe to function with conditional fails -- expected '$exp', got '$got'" 45334f9b3eeSRoland Mainzgot=$( 45434f9b3eeSRoland Mainz : works if this line deleted : | 45534f9b3eeSRoland Mainz { $binfalse && echo FAILED; } 45634f9b3eeSRoland Mainz : works if this line deleted : 45734f9b3eeSRoland Mainz) 45834f9b3eeSRoland Mainz[[ $got == $exp ]] || err_exit "pipe to { ... } with conditional fails -- expected '$exp', got '$got'" 45934f9b3eeSRoland Mainz 46034f9b3eeSRoland Mainzgot=$( 46134f9b3eeSRoland Mainz : works if this line deleted : | 46234f9b3eeSRoland Mainz ( $binfalse && echo FAILED ) 46334f9b3eeSRoland Mainz : works if this line deleted : 46434f9b3eeSRoland Mainz) 46534f9b3eeSRoland Mainz[[ $got == $exp ]] || err_exit "pipe to ( ... ) with conditional fails -- expected '$exp', got '$got'" 46634f9b3eeSRoland Mainz 46734f9b3eeSRoland Mainz( $SHELL -c 'trap : DEBUG; x=( $foo); exit 0') 2> /dev/null || err_exit 'trap DEBUG fails' 46834f9b3eeSRoland Mainz 469b30d1939SAndy Fiddamanbintrue=$(whence -p true) 4703e14f97fSRoger A. Faulknerset -o pipefail 4713e14f97fSRoger A. Faulknerfloat start=$SECONDS end 4723e14f97fSRoger A. Faulknerfor ((i=0; i < 2; i++)) 4733e14f97fSRoger A. Faulknerdo print foo 4743e14f97fSRoger A. Faulkner sleep 1.5 475b30d1939SAndy Fiddamandone | { read; $bintrue; end=$SECONDS ;} 4763e14f97fSRoger A. Faulkner(( (SECONDS-start) < 1 )) && err_exit "pipefail not waiting for pipe to finish" 4773e14f97fSRoger A. Faulknerset +o pipefail 478b30d1939SAndy Fiddaman(( (SECONDS-end) > 2 )) && err_exit "pipefail causing $bintrue to wait for other end of pipe" 4793e14f97fSRoger A. Faulkner 4803e14f97fSRoger A. Faulkner 4813e14f97fSRoger A. Faulkner{ env A__z=C+SHLVL $SHELL -c : ;} 2> /dev/null || err_exit "SHLVL with wrong attribute fails" 4823e14f97fSRoger A. Faulkner 483b30d1939SAndy Fiddamanif [[ $bintrue ]] 484b30d1939SAndy Fiddamanthen float t0=SECONDS 485b30d1939SAndy Fiddaman { time sleep 1.5 | $bintrue ;} 2> /dev/null 486b30d1939SAndy Fiddaman (( (SECONDS-t0) < 1 )) && err_exit 'time not waiting for pipeline to complete' 487b30d1939SAndy Fiddamanfi 488b30d1939SAndy Fiddaman 489b30d1939SAndy Fiddamancat > $tmp/foo.sh <<- \EOF 490b30d1939SAndy Fiddaman eval "cat > /dev/null < /dev/null" 491b30d1939SAndy Fiddaman sleep 1 492b30d1939SAndy FiddamanEOF 493b30d1939SAndy Fiddamanfloat sec=SECONDS 494b30d1939SAndy Fiddaman. $tmp/foo.sh | cat > /dev/null 495b30d1939SAndy Fiddaman(( (SECONDS-sec) < .7 )) && err_exit '. script does not restore output redirection with eval' 496b30d1939SAndy Fiddaman 497b30d1939SAndy Fiddamanfile=$tmp/foobar 498b30d1939SAndy Fiddamanbuiltin cat 499b30d1939SAndy Fiddamanfor ((n=0; n < 1000; n++)) 500b30d1939SAndy Fiddamando 501b30d1939SAndy Fiddaman > $file 502b30d1939SAndy Fiddaman { sleep .001;echo $? >$file;} | cat > /dev/null 503b30d1939SAndy Fiddaman if [[ ! -s $file ]] 504b30d1939SAndy Fiddaman then err_exit 'output from pipe is lost with pipe to builtin' 505b30d1939SAndy Fiddaman break; 506b30d1939SAndy Fiddaman fi 507b30d1939SAndy Fiddamandone 508b30d1939SAndy Fiddaman 509b30d1939SAndy Fiddaman$SHELL -c 'kill -0 123456789123456789123456789' 2> /dev/null && err_exit 'kill not catching process id overflows' 510b30d1939SAndy Fiddaman 511b30d1939SAndy Fiddaman[[ $($SHELL -c '{ cd..; print ok;}' 2> /dev/null) == ok ]] || err_exit 'command name ending in .. causes shell to abort' 512b30d1939SAndy Fiddaman 513b30d1939SAndy Fiddaman$SHELL -xc '$(LD_LIBRARY_PATH=$LD_LIBRARY_PATH exec $SHELL -c :)' > /dev/null 2>&1 || err_exit "ksh -xc '(name=value exec ksh)' fails with err=$?" 514b30d1939SAndy Fiddaman 515b30d1939SAndy Fiddaman$SHELL 2> /dev/null -c $'for i;\ndo :;done' || err_exit 'for i ; <newline> not vaid' 516b30d1939SAndy Fiddaman 517*6ba75e24SJohnothan King# The time keyword should obey the errexit option 518*6ba75e24SJohnothan King# https://www.illumos.org/issues/7694 519*6ba75e24SJohnothan Kingtime_errexit="$tmp/time_errexit.sh" 520*6ba75e24SJohnothan Kingcat > "$time_errexit" << 'EOF' 521*6ba75e24SJohnothan Kingtime false 522*6ba75e24SJohnothan Kingecho FAILURE 523*6ba75e24SJohnothan Kingtrue 524*6ba75e24SJohnothan KingEOF 525*6ba75e24SJohnothan Kinggot=$($SHELL -e "$time_errexit" 2>&1) 526*6ba75e24SJohnothan King(( $? == 0 )) && err_exit "The time keyword ignores the errexit option" \ 527*6ba75e24SJohnothan King "(got $(printf %q "$got"))" 528*6ba75e24SJohnothan King[[ -z $got ]] || err_exit "The time keyword produces output when a timed command fails and the errexit option is on" \ 529*6ba75e24SJohnothan King "(got $(printf %q "$got"))" 530*6ba75e24SJohnothan King 531b30d1939SAndy Fiddamanexit $((Errors<125?Errors:125)) 532