1 ########################################################################
3 # This software is part of the ast package #
4 # Copyright (c) 1982-2010 AT&T Intellectual Property #
5 # and is licensed under the #
6 # Common Public License, Version 1.0 #
7 # by AT&T Intellectual Property #
9 # A copy of the License is available at #
10 # http://www.opensource.org/licenses/cpl1.0.txt #
11 # (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) #
13 # Information and Software Systems Research #
17 # David Korn <dgk@research.att.com> #
19 ########################################################################
23 print
-u2 -r ${Command}[$1]: "${@:2}"
26 alias err_exit
='err_exit $LINENO'
31 tmp
=$
(mktemp
-dt) ||
{ err_exit mktemp
-dt failed
; exit 1; }
32 trap "cd /; rm -rf $tmp" EXIT
34 # test basic file operations like redirection, pipes, file expansion
53 [[ $g == $2 ]] || err_exit
"umask 0; umask $1 failed -- expected $2, got $g"
56 umask u
=rwx
,go
=rx || err_exit
"umask u=rws,go=rx failed"
57 if [[ $
(umask -S) != u
=rwx
,g
=rx
,o
=rx
]]
58 then err_exit
'umask -S incorrect'
61 [[ $SHELL != /* ]] && SHELL
=$pwd/$SHELL
62 cd $tmp ||
{ err_exit
"cd $tmp failed"; exit 1; }
64 ( umask 0777; > foobar
)
67 [[ -r foobar
]] || err_exit
'umask not being restored after subshell'
76 if [[ "$(<out)" != "foobar"$
'\n'"foobar*" ]]
77 then print
-u2 "optimizer bug with file expansion"
81 if [[ $
(print
*/) != dir
/ ]]
82 then err_exit
'file expansion with trailing / not working'
84 if [[ $
(print
*) != dir
]]
85 then err_exit
'file expansion with single file not working'
88 if [[ $
(print
*) != dir
]]
89 then err_exit
'file expansion leading . not working'
91 date > dat1 || err_exit
"date > dat1 failed"
92 test -r dat1 || err_exit
"dat1 is not readable"
94 cat <$x > dat2 || err_exit
"cat < $x > dat2 failed"
95 cat dat1 dat2 |
cat |
cat |
cat > dat3 || err_exit
"cat pipe failed"
99 cat dat1 dat2 |
cat |
cat |
cat > dat5
&
103 then err_exit
"dat* matches only $# files"
105 if (command > foo
\\abc
) 2> /dev
/null
107 if [[ $1 != 'foo\abc' ]]
108 then err_exit
'foo* does not match foo\abc'
111 if ( : > TT
* && : > TTfoo
) 2>/dev
/null
114 then err_exit
'TT* not expanding when file TT* exists'
117 cd ~
- || err_exit
"cd back failed"
118 cat > $tmp/script <<- !
122 chmod 755 $tmp/script
123 if [[ $($tmp/script) != "$tmp/script" ]]
124 then err_exit '$0 not correct for #! script'
129 then err_exit 'eval foo=\$bar not working'
133 if [[ $foo != 'foo bar' ]]
134 then err_exit 'eval foo=\$bar, with bar="foo\ bar" not working'
137 cd ../../tmp || err_exit "cd ../../tmp failed"
138 if [[ $PWD != /tmp ]]
139 then err_exit 'cd ../../tmp is not /tmp'
144 ) | cat > $tmp/foobar &
146 foobar=$( < $tmp/foobar)
147 if [[ $foobar != foobar ]]
148 then err_exit "$foobar is not foobar"
155 if [[ $( < $tmp/foobar) != $'foo\nbar\nbam' ]]
156 then err_exit "output file pointer not shared correctly"
158 cat > $tmp/foobar <<\!
164 if [[ $($tmp/foobar) != $'foo\nbar\nbam' ]]
165 then err_exit "script not working"
167 if [[ $($tmp/foobar | /bin/cat) != $'foo\nbar\nbam' ]]
168 then err_exit "script | cat not working"
170 if [[ $( $tmp/foobar) != $'foo\nbar\nbam' ]]
171 then err_exit "output file pointer not shared correctly"
174 x=$( (print foo) ; (print bar) )
175 if [[ $x != $'foo\nbar' ]]
176 then err_exit " ( (print foo);(print bar ) failed"
178 x=$( (/bin/echo foo) ; (print bar) )
179 if [[ $x != $'foo\nbar' ]]
180 then err_exit " ( (/bin/echo);(print bar ) failed"
182 x=$( (/bin/echo foo) ; (/bin/echo bar) )
183 if [[ $x != $'foo\nbar' ]]
184 then err_exit " ( (/bin/echo);(/bin/echo bar ) failed"
186 cat > $tmp/script <<\!
187 if [[ -p /dev/fd/0 ]]
190 [[ -p /dev
/fd
/0 ]] && print ok
195 case $
( (print
) |
$tmp/script;:) in
197 no
) err_exit
"[[ -p /dev/fd/0 ]] fails for standard input pipe" ;;
198 *) err_exit
"builtin replaces standard input pipe" ;;
200 print
'print $0' > $tmp/script
201 print
". $tmp/script" > $tmp/scriptx
202 chmod +x
$tmp/scriptx
203 if [[ $
($tmp/scriptx
) != $tmp/scriptx
]]
204 then err_exit
'$0 not correct for . script'
206 cd $tmp ||
{ err_exit
"cd $tmp failed"; exit 1; }
207 print .
/b
> .
/a
; print .
/c
> b
; print .
/d
> c
; print .
/e
> d
; print
"echo \"hello there\"" > e
210 if [[ $x != "hello there" ]]
211 then err_exit
"nested scripts failed"
214 if [[ $x != "hello there" ]]
215 then err_exit
"scripts in subshells fail"
217 cd ~
- || err_exit
"cd back failed"
218 x
=$
( (/bin
/echo foo
) 2> /dev
/null
)
220 then err_exit
"subshell in command substitution fails"
225 then err_exit
"command subsitution with stdout closed failed"
228 x
=$
(cat <<\
! |
$SHELL
233 if [[ $x != $
'\n'hello
]]
234 then err_exit
"$SHELL not working when standard input is a pipe"
236 x
=$
( (/bin
/echo hello
) 2> /dev
/null
)
238 then err_exit
"subshell in command substitution with 1 closed fails"
240 cat > $tmp/script <<- \!
241 read line 2> /dev/null
244 if [[ $($SHELL $tmp/script <&-) != done ]]
245 then err_exit
"executing script with 0 closed fails"
248 cat > $tmp/script <<- \!
254 if [[ $($SHELL $tmp/script) != good ]]
255 then err_exit "traps ignored by parent not ignored"
258 cat > $tmp/script <<- \!
262 if [[ $($SHELL $tmp/script <<!
267 then err_exit "standard input not positioned correctly"
269 word=$(print $'foo\nbar' | { read line; /bin/cat;})
270 if [[ $word != bar ]]
271 then err_exit "pipe to { read line; /bin/cat;} not working"
273 word=$(print $'foo\nbar' | ( read line; /bin/cat) )
274 if [[ $word != bar ]]
275 then err_exit "pipe to ( read line; /bin/cat) not working"
277 if [[ $(print x{a,b}y) != 'xay xby' ]]
278 then err_exit 'brace expansion not working'
280 if [[ $(for i in foo bar
283 done) != $'foo\nbar' ]]
284 then err_exit 'for loop subshell optimizer bug'
289 set -A a1 foo bar bam
291 for ((i=0; i < 3; i++))
293 (( ${#a1[@]} < 2 )) && return 0
300 optbug || err_exit 'array size optimzation bug'
301 wait # not running --pipefail which would interfere with subsequent tests
302 : $(jobs -p) # required to clear jobs for next jobs -p (interactive side effect)
305 if [[ $(jobs -p) != $! ]]
306 then err_exit 'jobs -p not reporting a background job'
313 (( $# == 2 )) || err_exit "$# jobs not reported -- 2 expected"
318 [[ $( (trap 'print alarm' ALRM; sleep 4) & sleep 2; kill -ALRM $!; sleep 2; wait) == alarm ]] || err_exit 'ALRM signal not working'
319 [[ $($SHELL -c 'trap "" HUP; $SHELL -c "(sleep 2;kill -HUP $$)& sleep 4;print done"') != done ]] && err_exit 'ignored traps not being ignored'
320 [[ $($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'
321 command exec 3<> /dev/null
322 if cat /dev/fd/3 >/dev/null 2>&1
323 then [[ $($SHELL -c 'cat <(print foo)' 2> /dev/null) == foo ]] || err_exit 'process substitution not working'
324 [[ $($SHELL -c $'tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \
!!!
330 cat '$tmp/scriptx 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails'
334 do tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
341 cat '$tmp/scriptx 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop'
342 [[ $({ $SHELL -c 'cat <(for i in x y z; do print $i; done)';} 2> /dev/null) == $'x\ny\nz' ]] ||
343 err_exit 'process substitution of compound commands not working'
345 [[ $($SHELL -r 'command -p :' 2>&1) == *restricted* ]] || err_exit 'command -p not restricted'
346 print cat > $tmp/scriptx
347 chmod +x $tmp/scriptx
348 [[ $($SHELL -c "print foo | $tmp/scriptx ;:" 2> /dev/null ) == foo ]] || err_exit 'piping into script fails'
349 [[ $($SHELL -c 'X=1;print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 1 ]] || err_exit 'x=1;${x:=$(..."...")} failure'
350 [[ $($SHELL -c 'print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 0 ]] || err_exit '${x:=$(..."...")} failure'
352 if [[ -d /dev
/fd
&& -w /dev
/fd
/3 ]]
353 then [[ $
(cat <(print hello
) ) == hello
]] || err_exit
"process substitution not working outside for or while loop"
354 $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"
357 print
'print foo "$@"' > $tmp/scriptx
358 [[ $
( print
"($tmp/scriptx bar)" |
$SHELL 2>/dev
/null
) == 'foo bar' ]] || err_exit
'script pipe to shell fails'
359 print
"#! $SHELL" > $tmp/scriptx
360 print
'print -- $0' >> $tmp/scriptx
361 chmod +x
$tmp/scriptx
362 [[ $
($tmp/scriptx
) == $tmp/scriptx
]] || err_exit
"\$0 is $0 instead of $tmp/scriptx"
363 cat > $tmp/scriptx
<<- \EOF
364 myfilter() { x=$(print ok | cat); print -r -- $SECONDS;}
368 (( $($SHELL $tmp/scriptx) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang'
370 ( typeset
-r foo
=bar
) 2> /dev
/null || err_exit
'readonly variables set in a subshell cannot unset'
371 $SHELL -c 'x=${ print hello;}; [[ $x == hello ]]' 2> /dev
/null || err_exit
'${ command;} not supported'
372 $SHELL 2> /dev
/null
<<- \EOF || err_exit 'multiline ${...} command substitution not supported'
378 $SHELL 2> /dev/null <<- \
EOF || err_exit '${...} command substitution with side effects not supported '
386 $SHELL 2> /dev/null <<- \EOF || err_exit 'nested ${...} command substitution not supported'
388 print ${ print hello;} $(print world)
390 [[ $x == 'hello world' ]]
392 $SHELL 2> /dev/null <<- \EOF || err_exit 'terminating } is not a reserved word with ${ command }'
393 x=${ { print -n } ; print -n hello ; } ; print ' world' }
394 [[ $x == '}hello world' ]]
396 $SHELL 2> /dev/null <<- \EOF || err_exit '${ command;}xxx not working'
401 [[ ${ f;}bar == foobar ]]
405 [[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset'
406 [[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset'
407 [[ $(print "[${ print foo }]") == '[foo]' ]] || err_exit '${...} not working when } is followed by ]'
408 [[ $(print "${ print "[${ print foo }]" }") == '[foo]' ]] || err_exit 'nested ${...} not working when } is followed by ]'
410 foo=$(false) > /dev/null && err_exit 'failed command substitution with redirection not returning false'
412 got=$(print -n fore;(sleep 2;print back)&)
413 [[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'"
415 binfalse=$(whence -p false)
416 for false in false $binfalse
417 do x=$($false) && err_exit "x=\$($false) should fail"
418 $($false) && err_exit "\$($false) should fail"
419 $($false) > /dev/null && err_exit "\$($false) > /dev/null should fail"
421 if env x-a=y >/dev/null 2>&1
422 then [[ $(env 'x-a=y' $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved'
425 sleep=$(whence -p sleep)
428 done | while read sec; do ( $sleep $sec; $sleep $sec) done
429 (( (SECONDS-s) < 4)) && err_exit '"command | while read...done" finishing too fast'
432 for ((i=0; i < 30; i++))
436 (( (SECONDS-s) < 2 )) || err_exit 'early termination not causing broken pipe'
437 [[ $({ trap 'print trap' 0; print -n | $(whence -p cat); } & wait $!) == trap ]] || err_exit 'trap on exit not getting triggered'
438 var=$({ trap 'print trap' ERR; print -n | $binfalse; } & wait $!)
439 [[ $var == trap ]] || err_exit 'trap on ERR not getting triggered'
445 $binfalse && echo FAILED
447 : works if this line deleted : |
449 : works if this line deleted :
451 [[ $got == $exp ]] || err_exit "pipe to function with conditional fails -- expected '$exp', got '$got'"
453 : works if this line deleted : |
454 { $binfalse && echo FAILED; }
455 : works if this line deleted :
457 [[ $got == $exp ]] || err_exit "pipe to { ... } with conditional fails -- expected '$exp', got '$got'"
460 : works if this line deleted : |
461 ( $binfalse && echo FAILED )
462 : works if this line deleted :
464 [[ $got == $exp ]] || err_exit "pipe to ( ... ) with conditional fails -- expected '$exp', got '$got'"
466 ( $SHELL -c 'trap : DEBUG; x=( $foo); exit 0') 2> /dev/null || err_exit 'trap DEBUG fails'
468 true=$(whence -p true)
470 float start=$SECONDS end
471 for ((i=0; i < 2; i++))
474 done | { read; $true; end=$SECONDS ;}
475 (( (SECONDS-start) < 1 )) && err_exit "pipefail not waiting for pipe to finish"
477 (( (SECONDS-start) > 2 )) && err_exit "pipefail causing /bin/true to wait for other end of pipe"
480 { env A__z=C+SHLVL $SHELL -c : ;} 2> /dev/null || err_exit "SHLVL with wrong attribute fails"