xref: /onnv-gate/usr/src/lib/libshell/common/tests/basic.sh (revision 12068:08a39a083754)
14887Schin########################################################################
24887Schin#                                                                      #
34887Schin#               This software is part of the ast package               #
4*12068SRoger.Faulkner@Oracle.COM#          Copyright (c) 1982-2010 AT&T Intellectual Property          #
54887Schin#                      and is licensed under the                       #
64887Schin#                  Common Public License, Version 1.0                  #
78462SApril.Chin@Sun.COM#                    by AT&T Intellectual Property                     #
84887Schin#                                                                      #
94887Schin#                A copy of the License is available at                 #
104887Schin#            http://www.opensource.org/licenses/cpl1.0.txt             #
114887Schin#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
124887Schin#                                                                      #
134887Schin#              Information and Software Systems Research               #
144887Schin#                            AT&T Research                             #
154887Schin#                           Florham Park NJ                            #
164887Schin#                                                                      #
174887Schin#                  David Korn <dgk@research.att.com>                   #
184887Schin#                                                                      #
194887Schin########################################################################
204887Schinfunction err_exit
214887Schin{
224887Schin	print -u2 -n "\t"
234887Schin	print -u2 -r ${Command}[$1]: "${@:2}"
244887Schin	let Errors+=1
254887Schin}
264887Schinalias err_exit='err_exit $LINENO'
274887Schin
284887SchinCommand=${0##*/}
294887Schininteger Errors=0
3010898Sroland.mainz@nrubsig.org
3110898Sroland.mainz@nrubsig.orgtmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
3210898Sroland.mainz@nrubsig.orgtrap "cd /; rm -rf $tmp" EXIT
3310898Sroland.mainz@nrubsig.org
3410898Sroland.mainz@nrubsig.org# test basic file operations like redirection, pipes, file expansion
358462SApril.Chin@Sun.COMset -- \
368462SApril.Chin@Sun.COM	go+r	0000	\
378462SApril.Chin@Sun.COM	go-r	0044	\
388462SApril.Chin@Sun.COM	ug=r	0330	\
398462SApril.Chin@Sun.COM	go+w	0000	\
408462SApril.Chin@Sun.COM	go-w	0022	\
418462SApril.Chin@Sun.COM	ug=w	0550	\
428462SApril.Chin@Sun.COM	go+x	0000	\
438462SApril.Chin@Sun.COM	go-x	0011	\
448462SApril.Chin@Sun.COM	ug=x	0660	\
458462SApril.Chin@Sun.COM	go-rx	0055	\
468462SApril.Chin@Sun.COM	uo-wx	0303	\
478462SApril.Chin@Sun.COM	ug-rw	0660	\
488462SApril.Chin@Sun.COM	o=	0007
498462SApril.Chin@Sun.COMwhile	(( $# >= 2 ))
508462SApril.Chin@Sun.COMdo	umask 0
518462SApril.Chin@Sun.COM	umask $1
528462SApril.Chin@Sun.COM	g=$(umask)
538462SApril.Chin@Sun.COM	[[ $g == $2 ]] || err_exit "umask 0; umask $1 failed -- expected $2, got $g"
548462SApril.Chin@Sun.COM	shift 2
558462SApril.Chin@Sun.COMdone
564887Schinumask u=rwx,go=rx || err_exit "umask u=rws,go=rx failed"
574887Schinif	[[ $(umask -S) != u=rwx,g=rx,o=rx ]]
584887Schinthen	err_exit 'umask -S incorrect'
594887Schinfi
604887Schinpwd=$PWD
614887Schin[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL
6210898Sroland.mainz@nrubsig.orgcd $tmp || { err_exit "cd $tmp failed"; exit 1; }
638462SApril.Chin@Sun.COMum=$(umask -S)
648462SApril.Chin@Sun.COM( umask 0777; > foobar )
658462SApril.Chin@Sun.COMrm -f foobar
668462SApril.Chin@Sun.COM> foobar
678462SApril.Chin@Sun.COM[[ -r foobar ]] || err_exit 'umask not being restored after subshell'
688462SApril.Chin@Sun.COMumask "$um"
698462SApril.Chin@Sun.COMrm -f foobar
704887Schin# optimizer bug test
714887Schin> foobar
724887Schinfor i in 1 2
734887Schindo      print foobar*
744887Schin        rm -f foobar
7510898Sroland.mainz@nrubsig.orgdone > out
7610898Sroland.mainz@nrubsig.orgif      [[ "$(<out)"  != "foobar"$'\n'"foobar*" ]]
774887Schinthen    print -u2 "optimizer bug with file expansion"
784887Schinfi
7910898Sroland.mainz@nrubsig.orgrm -f out foobar
804887Schinmkdir dir
814887Schinif	[[ $(print */) != dir/ ]]
824887Schinthen	err_exit 'file expansion with trailing / not working'
834887Schinfi
844887Schinif	[[ $(print *) != dir ]]
854887Schinthen	err_exit 'file expansion with single file not working'
864887Schinfi
874887Schinprint hi > .foo
884887Schinif	[[ $(print *) != dir ]]
894887Schinthen	err_exit 'file expansion leading . not working'
904887Schinfi
914887Schindate > dat1 || err_exit "date > dat1 failed"
924887Schintest -r dat1 || err_exit "dat1 is not readable"
934887Schinx=dat1
944887Schincat <$x > dat2 || err_exit "cat < $x > dat2 failed"
954887Schincat dat1 dat2 | cat  | cat | cat > dat3 || err_exit "cat pipe failed"
964887Schincat > dat4 <<!
974887Schin$(date)
984887Schin!
994887Schincat dat1 dat2 | cat  | cat | cat > dat5 &
1004887Schinwait $!
1014887Schinset -- dat*
1024887Schinif	(( $# != 5 ))
1034887Schinthen	err_exit "dat* matches only $# files"
1044887Schinfi
10510898Sroland.mainz@nrubsig.orgif	(command > foo\\abc) 2> /dev/null
1064887Schinthen	set -- foo*
1074887Schin	if	[[ $1 != 'foo\abc' ]]
1084887Schin	then	err_exit 'foo* does not match foo\abc'
1094887Schin	fi
1104887Schinfi
1114887Schinif ( : > TT* && : > TTfoo ) 2>/dev/null
1124887Schinthen	set -- TT*
1134887Schin	if	(( $# < 2 ))
1144887Schin	then	err_exit 'TT* not expanding when file TT* exists'
1154887Schin	fi
1164887Schinfi
1174887Schincd ~- || err_exit "cd back failed"
11810898Sroland.mainz@nrubsig.orgcat > $tmp/script <<- !
1194887Schin	#! $SHELL
1204887Schin	print -r -- \$0
1214887Schin!
12210898Sroland.mainz@nrubsig.orgchmod 755 $tmp/script
12310898Sroland.mainz@nrubsig.orgif	[[ $($tmp/script) != "$tmp/script" ]]
1244887Schinthen	err_exit '$0 not correct for #! script'
1254887Schinfi
1264887Schinbar=foo
1274887Schineval foo=\$bar
1284887Schinif	[[ $foo != foo ]]
1294887Schinthen	err_exit 'eval foo=\$bar not working'
1304887Schinfi
1314887Schinbar='foo=foo\ bar'
1324887Schineval $bar
1334887Schinif	[[ $foo != 'foo bar' ]]
1344887Schinthen	err_exit 'eval foo=\$bar, with bar="foo\ bar" not working'
1354887Schinfi
1364887Schincd /tmp
1374887Schincd ../../tmp || err_exit "cd ../../tmp failed"
1384887Schinif	[[ $PWD != /tmp ]]
1394887Schinthen	err_exit 'cd ../../tmp is not /tmp'
1404887Schinfi
1414887Schin( sleep 2; cat <<!
1424887Schinfoobar
1434887Schin!
14410898Sroland.mainz@nrubsig.org) | cat > $tmp/foobar &
1454887Schinwait $!
14610898Sroland.mainz@nrubsig.orgfoobar=$( < $tmp/foobar)
1474887Schinif	[[ $foobar != foobar ]]
1484887Schinthen	err_exit "$foobar is not foobar"
1494887Schinfi
1504887Schin{
1514887Schin	print foo
1524887Schin	/bin/echo bar
1534887Schin	print bam
15410898Sroland.mainz@nrubsig.org} > $tmp/foobar
15510898Sroland.mainz@nrubsig.orgif	[[ $( < $tmp/foobar) != $'foo\nbar\nbam' ]]
15610898Sroland.mainz@nrubsig.orgthen	err_exit "output file pointer not shared correctly"
1574887Schinfi
15810898Sroland.mainz@nrubsig.orgcat > $tmp/foobar <<\!
1594887Schin	print foo
1604887Schin	/bin/echo bar
1614887Schin	print bam
1624887Schin!
16310898Sroland.mainz@nrubsig.orgchmod +x $tmp/foobar
16410898Sroland.mainz@nrubsig.orgif	[[ $($tmp/foobar) != $'foo\nbar\nbam' ]]
16510898Sroland.mainz@nrubsig.orgthen	err_exit "script not working"
1664887Schinfi
16710898Sroland.mainz@nrubsig.orgif	[[ $($tmp/foobar | /bin/cat) != $'foo\nbar\nbam' ]]
16810898Sroland.mainz@nrubsig.orgthen	err_exit "script | cat not working"
1694887Schinfi
17010898Sroland.mainz@nrubsig.orgif	[[ $( $tmp/foobar) != $'foo\nbar\nbam' ]]
17110898Sroland.mainz@nrubsig.orgthen	err_exit "output file pointer not shared correctly"
1724887Schinfi
17310898Sroland.mainz@nrubsig.orgrm -f $tmp/foobar
1744887Schinx=$( (print foo) ; (print bar) )
1754887Schinif	[[ $x != $'foo\nbar' ]]
1764887Schinthen	err_exit " ( (print foo);(print bar ) failed"
1774887Schinfi
1784887Schinx=$( (/bin/echo foo) ; (print bar) )
1794887Schinif	[[ $x != $'foo\nbar' ]]
1804887Schinthen	err_exit " ( (/bin/echo);(print bar ) failed"
1814887Schinfi
1824887Schinx=$( (/bin/echo foo) ; (/bin/echo bar) )
1834887Schinif	[[ $x != $'foo\nbar' ]]
1844887Schinthen	err_exit " ( (/bin/echo);(/bin/echo bar ) failed"
1854887Schinfi
18610898Sroland.mainz@nrubsig.orgcat > $tmp/script <<\!
1874887Schinif	[[ -p /dev/fd/0 ]]
1884887Schinthen	builtin cat
1894887Schin	cat - > /dev/null
1904887Schin	[[ -p /dev/fd/0 ]] && print ok
1914887Schinelse	print no
1924887Schinfi
1934887Schin!
19410898Sroland.mainz@nrubsig.orgchmod +x $tmp/script
19510898Sroland.mainz@nrubsig.orgcase $( (print) | $tmp/script;:) in
1964887Schinok)	;;
1974887Schinno)	err_exit "[[ -p /dev/fd/0 ]] fails for standard input pipe" ;;
1984887Schin*)	err_exit "builtin replaces standard input pipe" ;;
1994887Schinesac
20010898Sroland.mainz@nrubsig.orgprint 'print $0' > $tmp/script
20110898Sroland.mainz@nrubsig.orgprint ". $tmp/script" > $tmp/scriptx
20210898Sroland.mainz@nrubsig.orgchmod +x $tmp/scriptx
20310898Sroland.mainz@nrubsig.orgif	[[ $($tmp/scriptx) != $tmp/scriptx ]]
2044887Schinthen	err_exit '$0 not correct for . script'
2054887Schinfi
20610898Sroland.mainz@nrubsig.orgcd $tmp || { err_exit "cd $tmp failed"; exit 1; }
20710898Sroland.mainz@nrubsig.orgprint ./b > ./a; print ./c > b; print ./d > c; print ./e > d; print "echo \"hello there\"" > e
2084887Schinchmod 755 a b c d e
2094887Schinx=$(./a)
2104887Schinif	[[ $x != "hello there" ]]
21110898Sroland.mainz@nrubsig.orgthen	err_exit "nested scripts failed"
2124887Schinfi
2134887Schinx=$( (./a) | cat)
2144887Schinif	[[ $x != "hello there" ]]
21510898Sroland.mainz@nrubsig.orgthen	err_exit "scripts in subshells fail"
2164887Schinfi
2174887Schincd ~- || err_exit "cd back failed"
2184887Schinx=$( (/bin/echo foo) 2> /dev/null )
2194887Schinif	[[ $x != foo ]]
2204887Schinthen	err_exit "subshell in command substitution fails"
2214887Schinfi
2224887Schinexec 1>&-
2234887Schinx=$(print hello)
2244887Schinif	[[ $x != hello ]]
2254887Schinthen	err_exit "command subsitution with stdout closed failed"
2264887Schinfi
2274887Schincd $pwd
2284887Schinx=$(cat <<\! | $SHELL
2294887Schin/bin/echo | /bin/cat
2304887Schin/bin/echo hello
2314887Schin!
2324887Schin)
2334887Schinif	[[ $x != $'\n'hello ]]
2344887Schinthen	err_exit "$SHELL not working when standard input is a pipe"
2354887Schinfi
2364887Schinx=$( (/bin/echo hello) 2> /dev/null )
2374887Schinif	[[ $x != hello ]]
2384887Schinthen	err_exit "subshell in command substitution with 1 closed fails"
2394887Schinfi
24010898Sroland.mainz@nrubsig.orgcat > $tmp/script <<- \!
2414887Schinread line 2> /dev/null
2424887Schinprint done
2434887Schin!
24410898Sroland.mainz@nrubsig.orgif	[[ $($SHELL $tmp/script <&-) != done ]]
2454887Schinthen	err_exit "executing script with 0 closed fails"
2464887Schinfi
2474887Schintrap '' INT
24810898Sroland.mainz@nrubsig.orgcat > $tmp/script <<- \!
2494887Schintrap 'print bad' INT
2504887Schinkill -s INT $$
2514887Schinprint good
2524887Schin!
25310898Sroland.mainz@nrubsig.orgchmod +x $tmp/script
25410898Sroland.mainz@nrubsig.orgif	[[ $($SHELL  $tmp/script) != good ]]
2554887Schinthen	err_exit "traps ignored by parent not ignored"
2564887Schinfi
2574887Schintrap - INT
25810898Sroland.mainz@nrubsig.orgcat > $tmp/script <<- \!
2594887Schinread line
2604887Schin/bin/cat
2614887Schin!
26210898Sroland.mainz@nrubsig.orgif	[[ $($SHELL $tmp/script <<!
2634887Schinone
2644887Schintwo
2654887Schin!
2664887Schin)	!= two ]]
2674887Schinthen	err_exit "standard input not positioned correctly"
2684887Schinfi
2694887Schinword=$(print $'foo\nbar' | { read line; /bin/cat;})
2704887Schinif	[[ $word != bar ]]
2714887Schinthen	err_exit "pipe to { read line; /bin/cat;} not working"
2724887Schinfi
2734887Schinword=$(print $'foo\nbar' | ( read line; /bin/cat) )
2744887Schinif	[[ $word != bar ]]
2754887Schinthen	err_exit "pipe to ( read line; /bin/cat) not working"
2764887Schinfi
2774887Schinif	[[ $(print x{a,b}y) != 'xay xby' ]]
2784887Schinthen	err_exit 'brace expansion not working'
2794887Schinfi
2804887Schinif	[[ $(for i in foo bar
2814887Schin	  do ( tgz=$(print $i)
2824887Schin	  print $tgz)
2834887Schin	  done) != $'foo\nbar' ]]
2844887Schinthen	err_exit 'for loop subshell optimizer bug'
2854887Schinfi
2864887Schinunset a1
2874887Schinoptbug()
2884887Schin{
2894887Schin	set -A a1  foo bar bam
2904887Schin	integer i
2914887Schin	for ((i=0; i < 3; i++))
2924887Schin	do
2934887Schin		(( ${#a1[@]} < 2 )) && return 0
2944887Schin		set -- "${a1[@]}"
2954887Schin		shift
2964887Schin		set -A a1 -- "$@"
2974887Schin	done
2984887Schin	return 1
2994887Schin}
3004887Schinoptbug ||  err_exit 'array size optimzation bug'
3018462SApril.Chin@Sun.COMwait # not running --pipefail which would interfere with subsequent tests
3024887Schin: $(jobs -p) # required to clear jobs for next jobs -p (interactive side effect)
3034887Schinsleep 20 &
3048462SApril.Chin@Sun.COMpids=$!
3054887Schinif	[[ $(jobs -p) != $! ]]
30610898Sroland.mainz@nrubsig.orgthen	err_exit 'jobs -p not reporting a background job'
3074887Schinfi
3084887Schinsleep 20 &
3098462SApril.Chin@Sun.COMpids="$pids $!"
3104887Schinfoo()
3114887Schin{
3124887Schin	set -- $(jobs -p)
3134887Schin	(( $# == 2 )) || err_exit "$# jobs not reported -- 2 expected"
3144887Schin}
3154887Schinfoo
3168462SApril.Chin@Sun.COMkill $pids
3178462SApril.Chin@Sun.COM
3188462SApril.Chin@Sun.COM[[ $( (trap 'print alarm' ALRM; sleep 4) & sleep 2; kill -ALRM $!; sleep 2; wait) == alarm ]] || err_exit 'ALRM signal not working'
3194887Schin[[ $($SHELL -c 'trap "" HUP; $SHELL -c "(sleep 2;kill -HUP $$)& sleep 4;print done"') != done ]] && err_exit 'ignored traps not being ignored'
3204887Schin[[ $($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'
3214887Schincommand exec 3<> /dev/null
3224887Schinif	cat /dev/fd/3 >/dev/null 2>&1
3234887Schinthen	[[ $($SHELL -c 'cat <(print foo)' 2> /dev/null) == foo ]] || err_exit 'process substitution not working'
32410898Sroland.mainz@nrubsig.org	[[ $($SHELL -c  $'tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<-  \!!!
3254887Schin	line0
3264887Schin	line1
3274887Schin	line2
3284887Schin	!!!
3294887Schin	wait
33010898Sroland.mainz@nrubsig.org	cat '$tmp/scriptx 2> /dev/null)  == line1 ]] || err_exit '>() process substitution fails'
33110898Sroland.mainz@nrubsig.org	> $tmp/scriptx
3324887Schin	[[ $($SHELL -c  $'
3334887Schin	for i in 1
33410898Sroland.mainz@nrubsig.org	do	tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null  <<-  \!!!
3354887Schin		line0
3364887Schin		line1
3374887Schin		line2
3384887Schin		!!!
3394887Schin	done
3404887Schin	wait
34110898Sroland.mainz@nrubsig.org	cat '$tmp/scriptx 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop'
3424887Schin	[[ $({ $SHELL -c 'cat <(for i in x y z; do print $i; done)';} 2> /dev/null) == $'x\ny\nz' ]] ||
3434887Schin		err_exit 'process substitution of compound commands not working'
3444887Schinfi
3454887Schin[[ $($SHELL -r 'command -p :' 2>&1) == *restricted* ]]  || err_exit 'command -p not restricted'
34610898Sroland.mainz@nrubsig.orgprint cat >  $tmp/scriptx
34710898Sroland.mainz@nrubsig.orgchmod +x $tmp/scriptx
34810898Sroland.mainz@nrubsig.org[[ $($SHELL -c "print foo | $tmp/scriptx ;:" 2> /dev/null ) == foo ]] || err_exit 'piping into script fails'
3494887Schin[[ $($SHELL -c 'X=1;print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 1 ]] || err_exit 'x=1;${x:=$(..."...")} failure'
3504887Schin[[ $($SHELL -c 'print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 0 ]] || err_exit '${x:=$(..."...")} failure'
3518462SApril.Chin@Sun.COMexec 3<&-
3524887Schinif	[[ -d /dev/fd  && -w /dev/fd/3 ]]
3534887Schinthen	[[ $(cat <(print hello) ) == hello ]] || err_exit "process substitution not working outside for or while loop"
3544887Schin	$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"
3554887Schinfi
3564887Schinexec 3> /dev/null
35710898Sroland.mainz@nrubsig.orgprint 'print foo "$@"' > $tmp/scriptx
35810898Sroland.mainz@nrubsig.org[[ $( print "($tmp/scriptx bar)" | $SHELL 2>/dev/null) == 'foo bar' ]] || err_exit 'script pipe to shell fails'
35910898Sroland.mainz@nrubsig.orgprint "#! $SHELL" > $tmp/scriptx
36010898Sroland.mainz@nrubsig.orgprint 'print  -- $0' >> $tmp/scriptx
36110898Sroland.mainz@nrubsig.orgchmod +x $tmp/scriptx
36210898Sroland.mainz@nrubsig.org[[ $($tmp/scriptx) == $tmp/scriptx ]] || err_exit  "\$0 is $0 instead of $tmp/scriptx"
36310898Sroland.mainz@nrubsig.orgcat > $tmp/scriptx <<- \EOF
3648462SApril.Chin@Sun.COM	myfilter() { x=$(print ok | cat); print  -r -- $SECONDS;}
3658462SApril.Chin@Sun.COM	set -o pipefail
3668462SApril.Chin@Sun.COM	sleep 3 | myfilter
3678462SApril.Chin@Sun.COMEOF
36810898Sroland.mainz@nrubsig.org(( $($SHELL $tmp/scriptx) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang'
3694887Schinexec 3<&-
3704887Schin( typeset -r foo=bar) 2> /dev/null || err_exit 'readonly variables set in a subshell cannot unset'
3718462SApril.Chin@Sun.COM$SHELL -c 'x=${ print hello;}; [[ $x == hello ]]' 2> /dev/null || err_exit '${ command;} not supported'
3728462SApril.Chin@Sun.COM$SHELL 2> /dev/null <<- \EOF || err_exit 'multiline ${...} command substitution not supported'
3738462SApril.Chin@Sun.COM	x=${
3748462SApril.Chin@Sun.COM		print hello
3758462SApril.Chin@Sun.COM	}
3768462SApril.Chin@Sun.COM	[[ $x == hello ]]
3778462SApril.Chin@Sun.COMEOF
3788462SApril.Chin@Sun.COM$SHELL 2> /dev/null <<- \EOF || err_exit '${...} command substitution with side effects not supported '
3798462SApril.Chin@Sun.COM	y=bye
3808462SApril.Chin@Sun.COM	x=${
3818462SApril.Chin@Sun.COM		y=hello
3828462SApril.Chin@Sun.COM		print hello
3838462SApril.Chin@Sun.COM	}
3848462SApril.Chin@Sun.COM	[[ $y == $x ]]
3858462SApril.Chin@Sun.COMEOF
3868462SApril.Chin@Sun.COM$SHELL   2> /dev/null <<- \EOF || err_exit 'nested ${...} command substitution not supported'
3878462SApril.Chin@Sun.COM	x=${
3888462SApril.Chin@Sun.COM		print ${ print hello;} $(print world)
3898462SApril.Chin@Sun.COM	}
3908462SApril.Chin@Sun.COM	[[ $x == 'hello world' ]]
3918462SApril.Chin@Sun.COMEOF
3928462SApril.Chin@Sun.COM$SHELL   2> /dev/null <<- \EOF || err_exit 'terminating } is not a reserved word with ${ command }'
3938462SApril.Chin@Sun.COM	x=${	{ print -n } ; print -n hello ; }  ; print ' world' }
3948462SApril.Chin@Sun.COM	[[ $x == '}hello world' ]]
3958462SApril.Chin@Sun.COMEOF
3968462SApril.Chin@Sun.COM$SHELL   2> /dev/null <<- \EOF || err_exit '${ command;}xxx not working'
3978462SApril.Chin@Sun.COM	f()
3988462SApril.Chin@Sun.COM	{
3998462SApril.Chin@Sun.COM		print foo
4008462SApril.Chin@Sun.COM	}
4018462SApril.Chin@Sun.COM	[[ ${ f;}bar == foobar ]]
4028462SApril.Chin@Sun.COMEOF
4038462SApril.Chin@Sun.COM
4048462SApril.Chin@Sun.COMunset foo
40510898Sroland.mainz@nrubsig.org[[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset'
40610898Sroland.mainz@nrubsig.org[[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset'
4078462SApril.Chin@Sun.COM[[ $(print  "[${ print foo }]") == '[foo]' ]] || err_exit '${...} not working when } is followed by ]'
4088462SApril.Chin@Sun.COM[[ $(print  "${ print "[${ print foo }]" }") == '[foo]' ]] || err_exit 'nested ${...} not working when } is followed by ]'
4098462SApril.Chin@Sun.COMunset foo
4108462SApril.Chin@Sun.COMfoo=$(false) > /dev/null && err_exit 'failed command substitution with redirection not returning false'
4118462SApril.Chin@Sun.COMexpected=foreback
4128462SApril.Chin@Sun.COMgot=$(print -n fore;(sleep 2;print back)&)
4138462SApril.Chin@Sun.COM[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'"
4148462SApril.Chin@Sun.COM
41510898Sroland.mainz@nrubsig.orgbinfalse=$(whence -p false)
41610898Sroland.mainz@nrubsig.orgfor false in false $binfalse
4178462SApril.Chin@Sun.COMdo	x=$($false) && err_exit "x=\$($false) should fail"
4188462SApril.Chin@Sun.COM	$($false) && err_exit "\$($false) should fail"
4198462SApril.Chin@Sun.COM	$($false) > /dev/null && err_exit "\$($false) > /dev/null should fail"
4208462SApril.Chin@Sun.COMdone
42110898Sroland.mainz@nrubsig.orgif	env x-a=y >/dev/null 2>&1
42210898Sroland.mainz@nrubsig.orgthen	[[ $(env 'x-a=y'  $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved'
42310898Sroland.mainz@nrubsig.orgfi
42410898Sroland.mainz@nrubsig.orgfloat s=SECONDS
42510898Sroland.mainz@nrubsig.orgsleep=$(whence -p sleep)
42610898Sroland.mainz@nrubsig.orgfor i in 1 2
42710898Sroland.mainz@nrubsig.orgdo      print $i
42810898Sroland.mainz@nrubsig.orgdone | while read sec; do ( $sleep $sec; $sleep $sec) done
42910898Sroland.mainz@nrubsig.org(( (SECONDS-s)  < 4)) && err_exit '"command | while read...done" finishing too fast'
43010898Sroland.mainz@nrubsig.orgs=SECONDS
43110898Sroland.mainz@nrubsig.orgset -o pipefail
43210898Sroland.mainz@nrubsig.orgfor ((i=0; i < 30; i++))
43310898Sroland.mainz@nrubsig.orgdo	print hello
43410898Sroland.mainz@nrubsig.org	sleep .1
43510898Sroland.mainz@nrubsig.orgdone |  $sleep 1
43610898Sroland.mainz@nrubsig.org(( (SECONDS-s) < 2 )) || err_exit 'early termination not causing broken pipe'
43710898Sroland.mainz@nrubsig.org[[ $({ trap 'print trap' 0; print -n | $(whence -p cat); } & wait $!) == trap ]] || err_exit 'trap on exit not getting triggered'
43810898Sroland.mainz@nrubsig.orgvar=$({ trap 'print trap' ERR; print -n | $binfalse; } & wait $!)
43910898Sroland.mainz@nrubsig.org[[ $var == trap ]] || err_exit 'trap on ERR not getting triggered'
44010898Sroland.mainz@nrubsig.org
44110898Sroland.mainz@nrubsig.orgexp=
44210898Sroland.mainz@nrubsig.orggot=$(
44310898Sroland.mainz@nrubsig.org	function fun
44410898Sroland.mainz@nrubsig.org	{
44510898Sroland.mainz@nrubsig.org		$binfalse && echo FAILED
44610898Sroland.mainz@nrubsig.org	}
44710898Sroland.mainz@nrubsig.org	: works if this line deleted : |
44810898Sroland.mainz@nrubsig.org	fun
44910898Sroland.mainz@nrubsig.org	: works if this line deleted :
45010898Sroland.mainz@nrubsig.org)
45110898Sroland.mainz@nrubsig.org[[ $got == $exp ]] || err_exit "pipe to function with conditional fails -- expected '$exp', got '$got'"
45210898Sroland.mainz@nrubsig.orggot=$(
45310898Sroland.mainz@nrubsig.org	: works if this line deleted : |
45410898Sroland.mainz@nrubsig.org	{ $binfalse && echo FAILED; }
45510898Sroland.mainz@nrubsig.org	: works if this line deleted :
45610898Sroland.mainz@nrubsig.org)
45710898Sroland.mainz@nrubsig.org[[ $got == $exp ]] || err_exit "pipe to { ... } with conditional fails -- expected '$exp', got '$got'"
45810898Sroland.mainz@nrubsig.org
45910898Sroland.mainz@nrubsig.orggot=$(
46010898Sroland.mainz@nrubsig.org	: works if this line deleted : |
46110898Sroland.mainz@nrubsig.org	( $binfalse && echo FAILED )
46210898Sroland.mainz@nrubsig.org	: works if this line deleted :
46310898Sroland.mainz@nrubsig.org)
46410898Sroland.mainz@nrubsig.org[[ $got == $exp ]] || err_exit "pipe to ( ... ) with conditional fails -- expected '$exp', got '$got'"
46510898Sroland.mainz@nrubsig.org
46610898Sroland.mainz@nrubsig.org( $SHELL -c 'trap : DEBUG; x=( $foo); exit 0') 2> /dev/null  || err_exit 'trap DEBUG fails'
46710898Sroland.mainz@nrubsig.org
468*12068SRoger.Faulkner@Oracle.COMtrue=$(whence -p true)
469*12068SRoger.Faulkner@Oracle.COMset -o pipefail
470*12068SRoger.Faulkner@Oracle.COMfloat start=$SECONDS end
471*12068SRoger.Faulkner@Oracle.COMfor ((i=0; i < 2; i++))
472*12068SRoger.Faulkner@Oracle.COMdo	print foo
473*12068SRoger.Faulkner@Oracle.COM	sleep 1.5
474*12068SRoger.Faulkner@Oracle.COMdone | { read; $true; end=$SECONDS ;}
475*12068SRoger.Faulkner@Oracle.COM(( (SECONDS-start) < 1 )) && err_exit "pipefail not waiting for pipe to finish"
476*12068SRoger.Faulkner@Oracle.COMset +o pipefail
477*12068SRoger.Faulkner@Oracle.COM(( (SECONDS-start) > 2 )) &&  err_exit "pipefail causing /bin/true to wait for other end of pipe"
478*12068SRoger.Faulkner@Oracle.COM
479*12068SRoger.Faulkner@Oracle.COM
480*12068SRoger.Faulkner@Oracle.COM{ env A__z=C+SHLVL $SHELL -c : ;} 2> /dev/null || err_exit "SHLVL with wrong attribute fails"
481*12068SRoger.Faulkner@Oracle.COM
4824887Schinexit $((Errors))
483