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 shell builtin commands 35da2e3ebdSchinbuiltin getconf 36da2e3ebdSchin: ${foo=bar} || err_exit ": failed" 37b30d1939SAndy Fiddaman[[ $foo == bar ]] || err_exit ": side effects failed" 38da2e3ebdSchinset -- - foobar 39b30d1939SAndy Fiddaman[[ $# == 2 && $1 == - && $2 == foobar ]] || err_exit "set -- - foobar failed" 40da2e3ebdSchinset -- -x foobar 41b30d1939SAndy Fiddaman[[ $# == 2 && $1 == -x && $2 == foobar ]] || err_exit "set -- -x foobar failed" 42da2e3ebdSchingetopts :x: foo || err_exit "getopts :x: returns false" 43b30d1939SAndy Fiddaman[[ $foo == x && $OPTARG == foobar ]] || err_exit "getopts :x: failed" 44da2e3ebdSchinOPTIND=1 45da2e3ebdSchingetopts :r:s var -r 46da2e3ebdSchinif [[ $var != : || $OPTARG != r ]] 47da2e3ebdSchinthen err_exit "'getopts :r:s var -r' not working" 48da2e3ebdSchinfi 49da2e3ebdSchinOPTIND=1 507c2fbfb3SApril Chingetopts :d#u OPT -d 16177 517c2fbfb3SApril Chinif [[ $OPT != d || $OPTARG != 16177 ]] 527c2fbfb3SApril Chinthen err_exit "'getopts :d#u OPT=d OPTARG=16177' failed -- OPT=$OPT OPTARG=$OPTARG" 53da2e3ebdSchinfi 54da2e3ebdSchinOPTIND=1 55da2e3ebdSchinwhile getopts 'ab' option -a -b 56da2e3ebdSchindo [[ $OPTIND == $((OPTIND)) ]] || err_exit "OPTIND optimization bug" 57da2e3ebdSchindone 58da2e3ebdSchin 59da2e3ebdSchinUSAGE=$'[-][S:server?Operate on the specified \asubservice\a:]:[subservice:=pmserver] 60da2e3ebdSchin { 61da2e3ebdSchin [p:pmserver] 62da2e3ebdSchin [r:repserver] 63da2e3ebdSchin [11:notifyd] 64da2e3ebdSchin }' 65da2e3ebdSchinset pmser p rep r notifyd -11 66da2e3ebdSchinwhile (( $# > 1 )) 67da2e3ebdSchindo OPTIND=1 68da2e3ebdSchin getopts "$USAGE" OPT -S $1 69da2e3ebdSchin [[ $OPT == S && $OPTARG == $2 ]] || err_exit "OPT=$OPT OPTARG=$OPTARG -- expected OPT=S OPTARG=$2" 70da2e3ebdSchin shift 2 71da2e3ebdSchindone 72da2e3ebdSchin 73da2e3ebdSchinfalse ${foo=bar} && err_exit "false failed" 74da2e3ebdSchinread <<! 75da2e3ebdSchinhello world 76da2e3ebdSchin! 77b30d1939SAndy Fiddaman[[ $REPLY == 'hello world' ]] || err_exit "read builtin failed" 78da2e3ebdSchinprint x:y | IFS=: read a b 79da2e3ebdSchinif [[ $a != x ]] 80da2e3ebdSchinthen err_exit "IFS=: read ... not working" 81da2e3ebdSchinfi 82da2e3ebdSchinread <<! 83da2e3ebdSchinhello \ 84da2e3ebdSchinworld 85da2e3ebdSchin! 86b30d1939SAndy Fiddaman[[ $REPLY == 'hello world' ]] || err_exit "read continuation failed" 87da2e3ebdSchinread -d x <<! 88da2e3ebdSchinhello worldxfoobar 89da2e3ebdSchin! 90b30d1939SAndy Fiddaman[[ $REPLY == 'hello world' ]] || err_exit "read builtin failed" 91da2e3ebdSchinread <<\! 92da2e3ebdSchinhello \ 93da2e3ebdSchin world \ 94da2e3ebdSchin 95da2e3ebdSchin! 96da2e3ebdSchin[[ $REPLY == 'hello world' ]] || err_exit "read continuation2 failed" 97da2e3ebdSchinprint "one\ntwo" | { read line 98da2e3ebdSchin print $line | /bin/cat > /dev/null 99da2e3ebdSchin read line 100da2e3ebdSchin} 101da2e3ebdSchinread <<\! 102da2e3ebdSchin\ 103da2e3ebdSchina\ 104da2e3ebdSchin\ 105da2e3ebdSchin\ 106da2e3ebdSchinb 107da2e3ebdSchin! 108da2e3ebdSchinif [[ $REPLY != ab ]] 109da2e3ebdSchinthen err_exit "read multiple continuation failed" 110da2e3ebdSchinfi 111da2e3ebdSchinif [[ $line != two ]] 112da2e3ebdSchinthen err_exit "read from pipeline failed" 113da2e3ebdSchinfi 114da2e3ebdSchinline=two 115da2e3ebdSchinread line < /dev/null 116da2e3ebdSchinif [[ $line != "" ]] 117da2e3ebdSchinthen err_exit "read from /dev/null failed" 118da2e3ebdSchinfi 119da2e3ebdSchinif [[ $(print -R -) != - ]] 120da2e3ebdSchinthen err_exit "print -R not working correctly" 121da2e3ebdSchinfi 122da2e3ebdSchinif [[ $(print -- -) != - ]] 123da2e3ebdSchinthen err_exit "print -- not working correctly" 124da2e3ebdSchinfi 125da2e3ebdSchinprint -f "hello%nbar\n" size > /dev/null 126da2e3ebdSchinif (( size != 5 )) 127da2e3ebdSchinthen err_exit "%n format of printf not working" 128da2e3ebdSchinfi 129da2e3ebdSchinprint -n -u2 2>&1- 130da2e3ebdSchin[[ -w /dev/fd/1 ]] || err_exit "2<&1- with built-ins has side effects" 131da2e3ebdSchinx=$0 132da2e3ebdSchinif [[ $(eval 'print $0') != $x ]] 133da2e3ebdSchinthen err_exit '$0 not correct for eval' 134da2e3ebdSchinfi 1357c2fbfb3SApril Chin$SHELL -c 'read x <<< hello' 2> /dev/null || err_exit 'syntax <<< not recognized' 1367c2fbfb3SApril Chin($SHELL -c 'read x[1] <<< hello') 2> /dev/null || err_exit 'read x[1] not working' 137da2e3ebdSchinunset x 138da2e3ebdSchinreadonly x 139da2e3ebdSchinset -- $(readonly) 140da2e3ebdSchinif [[ " $@ " != *" x "* ]] 141da2e3ebdSchinthen err_exit 'unset readonly variables are not displayed' 142da2e3ebdSchinfi 143da2e3ebdSchinif [[ $( for i in foo bar 144da2e3ebdSchin do print $i 145da2e3ebdSchin continue 10 146da2e3ebdSchin done 147da2e3ebdSchin ) != $'foo\nbar' ]] 148da2e3ebdSchinthen err_exit 'continue breaks out of loop' 149da2e3ebdSchinfi 150da2e3ebdSchin(continue bad 2>/dev/null && err_exit 'continue bad should return an error') 151da2e3ebdSchin(break bad 2>/dev/null && err_exit 'break bad should return an error') 152da2e3ebdSchin(continue 0 2>/dev/null && err_exit 'continue 0 should return an error') 153da2e3ebdSchin(break 0 2>/dev/null && err_exit 'break 0 should return an error') 154da2e3ebdSchinbreakfun() { break;} 155da2e3ebdSchincontinuefun() { continue;} 156da2e3ebdSchinfor fun in break continue 157da2e3ebdSchindo if [[ $( for i in foo 158da2e3ebdSchin do ${fun}fun 159da2e3ebdSchin print $i 160da2e3ebdSchin done 161da2e3ebdSchin ) != foo ]] 162da2e3ebdSchin then err_exit "$fun call in ${fun}fun breaks out of for loop" 163da2e3ebdSchin fi 164da2e3ebdSchindone 165da2e3ebdSchinif [[ $(print -f "%b" "\a\n\v\b\r\f\E\03\\oo") != $'\a\n\v\b\r\f\E\03\\oo' ]] 166da2e3ebdSchinthen err_exit 'print -f "%b" not working' 167da2e3ebdSchinfi 1687c2fbfb3SApril Chinif [[ $(print -f "%P" "[^x].*b\$") != '*[!x]*b' ]] 169da2e3ebdSchinthen err_exit 'print -f "%P" not working' 170da2e3ebdSchinfi 171b30d1939SAndy Fiddamanif [[ $(print -f "%(pattern)q" "[^x].*b\$") != '*[!x]*b' ]] 172b30d1939SAndy Fiddamanthen err_exit 'print -f "%(pattern)q" not working' 173b30d1939SAndy Fiddamanfi 174da2e3ebdSchinif [[ $(abc: for i in foo bar;do print $i;break abc;done) != foo ]] 175da2e3ebdSchinthen err_exit 'break labels not working' 176da2e3ebdSchinfi 177da2e3ebdSchinif [[ $(command -v if) != if ]] 178da2e3ebdSchinthen err_exit 'command -v not working' 179da2e3ebdSchinfi 180da2e3ebdSchinread -r var <<\! 18134f9b3eeSRoland Mainz 182da2e3ebdSchin! 183da2e3ebdSchinif [[ $var != "" ]] 184da2e3ebdSchinthen err_exit "read -r of blank line not working" 185da2e3ebdSchinfi 18634f9b3eeSRoland Mainzmkdir -p $tmp/a/b/c 2>/dev/null || err_exit "mkdir -p failed" 18734f9b3eeSRoland Mainz$SHELL -c "cd $tmp/a/b; cd c" 2>/dev/null || err_exit "initial script relative cd fails" 18834f9b3eeSRoland Mainz 18934f9b3eeSRoland Mainztrap 'print TERM' TERM 19034f9b3eeSRoland Mainzexp=$'trap -- \'print TERM\' TERM\ntrap -- \'cd /; rm -rf '$tmp$'\' EXIT' 19134f9b3eeSRoland Mainzgot=$(trap) 19234f9b3eeSRoland Mainz[[ $got == $exp ]] || err_exit "\$(trap) failed -- expected \"$exp\", got \"$got\"" 19334f9b3eeSRoland Mainzexp='print TERM' 19434f9b3eeSRoland Mainzgot=$(trap -p TERM) 19534f9b3eeSRoland Mainz[[ $got == $exp ]] || err_exit "\$(trap -p TERM) failed -- expected \"$exp\", got \"$got\"" 19634f9b3eeSRoland Mainz 1977c2fbfb3SApril Chin[[ $($SHELL -c 'trap "print ok" SIGTERM; kill -s SIGTERM $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized' 1987c2fbfb3SApril Chin[[ $($SHELL -c 'trap "print ok" sigterm; kill -s sigterm $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized' 1997c2fbfb3SApril Chin[[ $($SHELL -c '( trap "" TERM);kill $$;print bad' == bad) ]] 2> /dev/null && err_exit 'trap ignored in subshell causes it to be ignored by parent' 200da2e3ebdSchin${SHELL} -c 'kill -1 -$$' 2> /dev/null 20134f9b3eeSRoland Mainz[[ $(kill -l $?) == HUP ]] || err_exit 'kill -1 -pid not working' 202da2e3ebdSchin${SHELL} -c 'kill -1 -$$' 2> /dev/null 20334f9b3eeSRoland Mainz[[ $(kill -l $?) == HUP ]] || err_exit 'kill -n1 -pid not working' 204da2e3ebdSchin${SHELL} -c 'kill -s HUP -$$' 2> /dev/null 20534f9b3eeSRoland Mainz[[ $(kill -l $?) == HUP ]] || err_exit 'kill -HUP -pid not working' 206da2e3ebdSchinn=123 207da2e3ebdSchintypeset -A base 208da2e3ebdSchinbase[o]=8# 209da2e3ebdSchinbase[x]=16# 210da2e3ebdSchinbase[X]=16# 211da2e3ebdSchinfor i in d i o u x X 212da2e3ebdSchindo if (( $(( ${base[$i]}$(printf "%$i" $n) )) != n )) 213da2e3ebdSchin then err_exit "printf %$i not working" 214da2e3ebdSchin fi 215da2e3ebdSchindone 216*89af4c7bSAndy Fiddamanif [[ $(printf -eexist) != -eexist ]] 217*89af4c7bSAndy Fiddamanthen err_exit 'printf -eexist ... not working' 218*89af4c7bSAndy Fiddamanfi 219*89af4c7bSAndy Fiddamanif [[ $(printf -- "%s" foo) != foo ]] 220*89af4c7bSAndy Fiddamanthen err_exit 'printf -- not working' 221*89af4c7bSAndy Fiddamanfi 222*89af4c7bSAndy Fiddamanif [[ $(printf -- --) != -- ]] 223*89af4c7bSAndy Fiddamanthen err_exit 'printf -- -- ... not working' 224*89af4c7bSAndy Fiddamanfi 225*89af4c7bSAndy Fiddamanif [[ $(printf -- -eexist) != -eexist ]] 226*89af4c7bSAndy Fiddamanthen err_exit 'printf -- -eexist. not working' 227*89af4c7bSAndy Fiddamanfi 228da2e3ebdSchinif [[ $( trap 'print done' EXIT) != done ]] 229da2e3ebdSchinthen err_exit 'trap on EXIT not working' 230da2e3ebdSchinfi 231da2e3ebdSchinif [[ $( trap 'print done' EXIT; trap - EXIT) == done ]] 232da2e3ebdSchinthen err_exit 'trap on EXIT not being cleared' 233da2e3ebdSchinfi 234b30d1939SAndy Fiddamanif [[ $(LC_MESSAGES=C type test) != 'test is a shell builtin' ]] 235da2e3ebdSchinthen err_exit 'whence -v test not a builtin' 236da2e3ebdSchinfi 237da2e3ebdSchinbuiltin -d test 238da2e3ebdSchinif [[ $(type test) == *builtin* ]] 239da2e3ebdSchinthen err_exit 'whence -v test after builtin -d incorrect' 240da2e3ebdSchinfi 241da2e3ebdSchintypeset -Z3 percent=$(printf '%o\n' "'%'") 242da2e3ebdSchinforrmat=\\${percent}s 243da2e3ebdSchinif [[ $(printf "$forrmat") != %s ]] 244da2e3ebdSchinthen err_exit "printf $forrmat not working" 245da2e3ebdSchinfi 246da2e3ebdSchinif (( $(printf 'x\0y' | wc -c) != 3 )) 247da2e3ebdSchinthen err_exit 'printf \0 not working' 248da2e3ebdSchinfi 249da2e3ebdSchinif [[ $(printf "%bx%s\n" 'f\to\cbar') != $'f\to' ]] 250da2e3ebdSchinthen err_exit 'printf %bx%s\n not working' 251da2e3ebdSchinfi 252da2e3ebdSchinalpha=abcdefghijklmnop 253da2e3ebdSchinif [[ $(printf "%10.*s\n" 5 $alpha) != ' abcde' ]] 254da2e3ebdSchinthen err_exit 'printf %10.%s\n not working' 255da2e3ebdSchinfi 256da2e3ebdSchinfloat x2=.0000625 257da2e3ebdSchinif [[ $(printf "%10.5E\n" x2) != 6.25000E-05 ]] 258da2e3ebdSchinthen err_exit 'printf "%10.5E" not normalizing correctly' 259da2e3ebdSchinfi 260da2e3ebdSchinx2=.000000001 261da2e3ebdSchinif [[ $(printf "%g\n" x2 2>/dev/null) != 1e-09 ]] 262da2e3ebdSchinthen err_exit 'printf "%g" not working correctly' 263da2e3ebdSchinfi 264da2e3ebdSchin#FIXME#($SHELL read -s foobar <<\! 265da2e3ebdSchin#FIXME#testing 266da2e3ebdSchin#FIXME#! 267da2e3ebdSchin#FIXME#) 2> /dev/null || err_exit ksh read -s var fails 268da2e3ebdSchinif [[ $(printf +3 2>/dev/null) != +3 ]] 269da2e3ebdSchinthen err_exit 'printf is not processing formats beginning with + correctly' 270da2e3ebdSchinfi 271da2e3ebdSchinif printf "%d %d\n" 123bad 78 >/dev/null 2>/dev/null 272da2e3ebdSchinthen err_exit "printf not exiting non-zero with conversion errors" 273da2e3ebdSchinfi 274da2e3ebdSchinif [[ $(trap --version 2> /dev/null;print done) != done ]] 275da2e3ebdSchinthen err_exit 'trap builtin terminating after --version' 276da2e3ebdSchinfi 277da2e3ebdSchinif [[ $(set --version 2> /dev/null;print done) != done ]] 278da2e3ebdSchinthen err_exit 'set builtin terminating after --veresion' 279da2e3ebdSchinfi 280da2e3ebdSchinunset -f foobar 281da2e3ebdSchinfunction foobar 282da2e3ebdSchin{ 283da2e3ebdSchin print 'hello world' 284da2e3ebdSchin} 285da2e3ebdSchinOPTIND=1 286da2e3ebdSchinif [[ $(getopts $'[+?X\ffoobar\fX]' v --man 2>&1) != *'Xhello world'X* ]] 287da2e3ebdSchinthen err_exit '\f...\f not working in getopts usage strings' 288da2e3ebdSchinfi 28934f9b3eeSRoland Mainzif [[ $(printf '%H\n' $'<>"& \'\tabc') != '<>"& '	abc' ]] 290da2e3ebdSchinthen err_exit 'printf %H not working' 291da2e3ebdSchinfi 292b30d1939SAndy Fiddamanif [[ $(printf '%(html)q\n' $'<>"& \'\tabc') != '<>"& '	abc' ]] 293b30d1939SAndy Fiddamanthen err_exit 'printf %(html)q not working' 294b30d1939SAndy Fiddamanfi 295b30d1939SAndy Fiddamanif [[ $( printf 'foo://ab_c%(url)q\n' $'<>"& \'\tabc') != 'foo://ab_c%3C%3E%22%26%20%27%09abc' ]] 296b30d1939SAndy Fiddamanthen err_exit 'printf %(url)q not working' 297b30d1939SAndy Fiddamanfi 29834f9b3eeSRoland Mainzif [[ $(printf '%R %R %R %R\n' 'a.b' '*.c' '^' '!(*.*)') != '^a\.b$ \.c$ ^\^$ ^(.*\..*)!$' ]] 299b30d1939SAndy Fiddamanthen err_exit 'printf %T not working' 300b30d1939SAndy Fiddamanfi 301b30d1939SAndy Fiddamanif [[ $(printf '%(ere)q %(ere)q %(ere)q %(ere)q\n' 'a.b' '*.c' '^' '!(*.*)') != '^a\.b$ \.c$ ^\^$ ^(.*\..*)!$' ]] 302b30d1939SAndy Fiddamanthen err_exit 'printf %(ere)q not working' 303da2e3ebdSchinfi 304da2e3ebdSchinif [[ $(printf '%..:c\n' abc) != a:b:c ]] 30534f9b3eeSRoland Mainzthen err_exit "printf '%..:c' not working" 306da2e3ebdSchinfi 307da2e3ebdSchinif [[ $(printf '%..*c\n' : abc) != a:b:c ]] 30834f9b3eeSRoland Mainzthen err_exit "printf '%..*c' not working" 309da2e3ebdSchinfi 310da2e3ebdSchinif [[ $(printf '%..:s\n' abc def ) != abc:def ]] 31134f9b3eeSRoland Mainzthen err_exit "printf '%..:s' not working" 312da2e3ebdSchinfi 313da2e3ebdSchinif [[ $(printf '%..*s\n' : abc def) != abc:def ]] 31434f9b3eeSRoland Mainzthen err_exit "printf '%..*s' not working" 315da2e3ebdSchinfi 316da2e3ebdSchin[[ $(printf '%q\n') == '' ]] || err_exit 'printf "%q" with missing arguments' 317da2e3ebdSchin# we won't get hit by the one second boundary twice, right? 318da2e3ebdSchin[[ $(printf '%T\n' now) == "$(date)" ]] || 319da2e3ebdSchin[[ $(printf '%T\n' now) == "$(date)" ]] || 320da2e3ebdSchinerr_exit 'printf "%T" now' 321da2e3ebdSchinbehead() 322da2e3ebdSchin{ 323da2e3ebdSchin read line 324da2e3ebdSchin left=$(cat) 325da2e3ebdSchin} 326da2e3ebdSchinprint $'line1\nline2' | behead 327da2e3ebdSchinif [[ $left != line2 ]] 32834f9b3eeSRoland Mainzthen err_exit "read reading ahead on a pipe" 329da2e3ebdSchinfi 33034f9b3eeSRoland Mainzread -n1 y <<! 33134f9b3eeSRoland Mainzabc 33234f9b3eeSRoland Mainz! 33334f9b3eeSRoland Mainzexp=a 33434f9b3eeSRoland Mainzif [[ $y != $exp ]] 33534f9b3eeSRoland Mainzthen err_exit "read -n1 failed -- expected '$exp', got '$y'" 33634f9b3eeSRoland Mainzfi 33734f9b3eeSRoland Mainzprint -n $'{ read -r line;print $line;}\nhello' > $tmp/script 33834f9b3eeSRoland Mainzchmod 755 $tmp/script 33934f9b3eeSRoland Mainzif [[ $($SHELL < $tmp/script) != hello ]] 340da2e3ebdSchinthen err_exit 'read of incomplete line not working correctly' 341da2e3ebdSchinfi 342da2e3ebdSchinset -f 343da2e3ebdSchinset -- * 344da2e3ebdSchinif [[ $1 != '*' ]] 345da2e3ebdSchinthen err_exit 'set -f not working' 346da2e3ebdSchinfi 347da2e3ebdSchinunset pid1 pid2 348da2e3ebdSchinfalse & 349da2e3ebdSchinpid1=$! 350da2e3ebdSchinpid2=$( 351da2e3ebdSchin wait $pid1 352da2e3ebdSchin (( $? == 127 )) || err_exit "job known to subshell" 353da2e3ebdSchin print $! 354da2e3ebdSchin) 355da2e3ebdSchinwait $pid1 356da2e3ebdSchin(( $? == 1 )) || err_exit "wait not saving exit value" 357da2e3ebdSchinwait $pid2 358da2e3ebdSchin(( $? == 127 )) || err_exit "subshell job known to parent" 359da2e3ebdSchinenv= 36034f9b3eeSRoland Mainzv=$(getconf LIBPATH) 36134f9b3eeSRoland Mainzfor v in ${v//,/ } 36234f9b3eeSRoland Mainzdo v=${v#*:} 36334f9b3eeSRoland Mainz v=${v%%:*} 36434f9b3eeSRoland Mainz eval [[ \$$v ]] && env="$env $v=\"\$$v\"" 365da2e3ebdSchindone 366da2e3ebdSchinif [[ $(foo=bar; eval foo=\$foo $env exec -c \$SHELL -c \'print \$foo\') != bar ]] 367da2e3ebdSchinthen err_exit '"name=value exec -c ..." not working' 368da2e3ebdSchinfi 369da2e3ebdSchin$SHELL -c 'OPTIND=-1000000; getopts a opt -a' 2> /dev/null 370da2e3ebdSchin[[ $? == 1 ]] || err_exit 'getopts with negative OPTIND not working' 371da2e3ebdSchingetopts 'n#num' opt -n 3 372da2e3ebdSchin[[ $OPTARG == 3 ]] || err_exit 'getopts with numerical arguments failed' 373da2e3ebdSchinif [[ $($SHELL -c $'printf \'%2$s %1$s\n\' world hello') != 'hello world' ]] 374da2e3ebdSchinthen err_exit 'printf %2$s %1$s not working' 375da2e3ebdSchinfi 3767c2fbfb3SApril Chinval=$(( 'C' )) 3777c2fbfb3SApril Chinset -- \ 3787c2fbfb3SApril Chin "'C" $val 0 \ 3797c2fbfb3SApril Chin "'C'" $val 0 \ 3807c2fbfb3SApril Chin '"C' $val 0 \ 3817c2fbfb3SApril Chin '"C"' $val 0 \ 3827c2fbfb3SApril Chin "'CX" $val 1 \ 3837c2fbfb3SApril Chin "'CX'" $val 1 \ 3847c2fbfb3SApril Chin "'C'X" $val 1 \ 3857c2fbfb3SApril Chin '"CX' $val 1 \ 3867c2fbfb3SApril Chin '"CX"' $val 1 \ 3877c2fbfb3SApril Chin '"C"X' $val 1 3887c2fbfb3SApril Chinwhile (( $# >= 3 )) 3897c2fbfb3SApril Chindo arg=$1 val=$2 code=$3 3907c2fbfb3SApril Chin shift 3 3917c2fbfb3SApril Chin for fmt in '%d' '%g' 3927c2fbfb3SApril Chin do out=$(printf "$fmt" "$arg" 2>/dev/null) 3937c2fbfb3SApril Chin err=$(printf "$fmt" "$arg" 2>&1 >/dev/null) 3947c2fbfb3SApril Chin printf "$fmt" "$arg" >/dev/null 2>&1 3957c2fbfb3SApril Chin ret=$? 39634f9b3eeSRoland Mainz [[ $out == $val ]] || err_exit "printf $fmt $arg failed -- expected '$val', got '$out'" 3977c2fbfb3SApril Chin if (( $code )) 3987c2fbfb3SApril Chin then [[ $err ]] || err_exit "printf $fmt $arg failed, error message expected" 3997c2fbfb3SApril Chin else [[ $err ]] && err_exit "$err: printf $fmt $arg failed, error message not expected -- got '$err'" 4007c2fbfb3SApril Chin fi 4017c2fbfb3SApril Chin (( $ret == $code )) || err_exit "printf $fmt $arg failed -- expected exit code $code, got $ret" 4027c2fbfb3SApril Chin done 4037c2fbfb3SApril Chindone 404da2e3ebdSchin((n=0)) 405da2e3ebdSchin((n++)); ARGC[$n]=1 ARGV[$n]="" 406da2e3ebdSchin((n++)); ARGC[$n]=2 ARGV[$n]="-a" 407da2e3ebdSchin((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2" 408da2e3ebdSchin((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x" 409da2e3ebdSchin((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x y" 410da2e3ebdSchinfor ((i=1; i<=n; i++)) 411da2e3ebdSchindo set -- ${ARGV[$i]} 412da2e3ebdSchin OPTIND=0 413da2e3ebdSchin while getopts -a tst "av:" OPT 414da2e3ebdSchin do : 415da2e3ebdSchin done 416da2e3ebdSchin if [[ $OPTIND != ${ARGC[$i]} ]] 4177c2fbfb3SApril Chin then err_exit "\$OPTIND after getopts loop incorrect -- expected ${ARGC[$i]}, got $OPTIND" 418da2e3ebdSchin fi 419da2e3ebdSchindone 4207c2fbfb3SApril Chinoptions=ab:c 4217c2fbfb3SApril Chinoptarg=foo 4227c2fbfb3SApril Chinset -- -a -b $optarg -c bar 4237c2fbfb3SApril Chinwhile getopts $options opt 4247c2fbfb3SApril Chindo case $opt in 4257c2fbfb3SApril Chin a|c) [[ $OPTARG ]] && err_exit "getopts $options \$OPTARG for flag $opt failed, expected \"\", got \"$OPTARG\"" ;; 4267c2fbfb3SApril Chin b) [[ $OPTARG == $optarg ]] || err_exit "getopts $options \$OPTARG failed -- \"$optarg\" expected, got \"$OPTARG\"" ;; 4277c2fbfb3SApril Chin *) err_exit "getopts $options failed -- got flag $opt" ;; 4287c2fbfb3SApril Chin esac 4297c2fbfb3SApril Chindone 43034f9b3eeSRoland Mainz 431b30d1939SAndy Fiddaman[[ $($SHELL 2> /dev/null -c 'readonly foo; getopts a: foo -a blah; echo foo') == foo ]] || err_exit 'getopts with readonly variable causes script to abort' 432b30d1939SAndy Fiddaman 43334f9b3eeSRoland Mainzunset a 43434f9b3eeSRoland Mainz{ read -N3 a; read -N1 b;} <<! 43534f9b3eeSRoland Mainzabcdefg 43634f9b3eeSRoland Mainz! 43734f9b3eeSRoland Mainzexp=abc 43834f9b3eeSRoland Mainz[[ $a == $exp ]] || err_exit "read -N3 here-document failed -- expected '$exp', got '$a'" 43934f9b3eeSRoland Mainzexp=d 44034f9b3eeSRoland Mainz[[ $b == $exp ]] || err_exit "read -N1 here-document failed -- expected '$exp', got '$b'" 44134f9b3eeSRoland Mainzread -n3 a <<! 44234f9b3eeSRoland Mainzabcdefg 44334f9b3eeSRoland Mainz! 44434f9b3eeSRoland Mainzexp=abc 44534f9b3eeSRoland Mainz[[ $a == $exp ]] || err_exit "read -n3 here-document failed -- expected '$exp', got '$a'" 44634f9b3eeSRoland Mainz#(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;} 44734f9b3eeSRoland Mainz#[[ $a == $exp ]] || err_exit "read -N3 from pipe failed -- expected '$exp', got '$a'" 44834f9b3eeSRoland Mainz#exp=d 44934f9b3eeSRoland Mainz#[[ $b == $exp ]] || err_exit "read -N1 from pipe failed -- expected '$exp', got '$b'" 45034f9b3eeSRoland Mainz#(print -n a;sleep 1; print -n bcde) | read -n3 a 45134f9b3eeSRoland Mainz#exp=a 45234f9b3eeSRoland Mainz#[[ $a == $exp ]] || err_exit "read -n3 from pipe failed -- expected '$exp', got '$a'" 45334f9b3eeSRoland Mainz#rm -f $tmp/fifo 45434f9b3eeSRoland Mainz#if mkfifo $tmp/fifo 2> /dev/null 45534f9b3eeSRoland Mainz#then (print -n a; sleep 1;print -n bcde) > $tmp/fifo & 45634f9b3eeSRoland Mainz# { 45734f9b3eeSRoland Mainz# read -u5 -n3 -t2 a || err_exit 'read -n3 from fifo timedout' 45834f9b3eeSRoland Mainz# read -u5 -n1 -t2 b || err_exit 'read -n1 from fifo timedout' 45934f9b3eeSRoland Mainz# } 5< $tmp/fifo 46034f9b3eeSRoland Mainz# exp=a 46134f9b3eeSRoland Mainz# [[ $a == $exp ]] || err_exit "read -n3 from fifo failed -- expected '$exp', got '$a'" 46234f9b3eeSRoland Mainz# rm -f $tmp/fifo 46334f9b3eeSRoland Mainz# mkfifo $tmp/fifo 2> /dev/null 46434f9b3eeSRoland Mainz# (print -n a; sleep 1;print -n bcde) > $tmp/fifo & 46534f9b3eeSRoland Mainz# { 46634f9b3eeSRoland Mainz# read -u5 -N3 -t2 a || err_exit 'read -N3 from fifo timed out' 46734f9b3eeSRoland Mainz# read -u5 -N1 -t2 b || err_exit 'read -N1 from fifo timedout' 46834f9b3eeSRoland Mainz# } 5< $tmp/fifo 46934f9b3eeSRoland Mainz# exp=abc 47034f9b3eeSRoland Mainz# [[ $a == $exp ]] || err_exit "read -N3 from fifo failed -- expected '$exp', got '$a'" 47134f9b3eeSRoland Mainz# exp=d 47234f9b3eeSRoland Mainz# [[ $b == $exp ]] || err_exit "read -N1 from fifo failed -- expected '$exp', got '$b'" 47334f9b3eeSRoland Mainz#fi 47434f9b3eeSRoland Mainz#rm -f $tmp/fifo 47534f9b3eeSRoland Mainz 476da2e3ebdSchinfunction longline 477da2e3ebdSchin{ 478da2e3ebdSchin integer i 479da2e3ebdSchin for((i=0; i < $1; i++)) 480da2e3ebdSchin do print argument$i 481da2e3ebdSchin done 482da2e3ebdSchin} 483da2e3ebdSchin# test command -x option 484da2e3ebdSchininteger sum=0 n=10000 485da2e3ebdSchinif ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1 486da2e3ebdSchinthen for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) 2> /dev/null) 487da2e3ebdSchin do ((sum += $i)) 488da2e3ebdSchin done 489da2e3ebdSchin (( sum == n )) || err_exit "command -x processed only $sum arguments" 490da2e3ebdSchin command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1 491da2e3ebdSchin [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x' 492da2e3ebdSchinfi 493da2e3ebdSchin# test command -x option with extra arguments 494da2e3ebdSchininteger sum=0 n=10000 495da2e3ebdSchinif ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1 496da2e3ebdSchinthen for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) one two three) #2> /dev/null) 497da2e3ebdSchin do ((sum += $i)) 498da2e3ebdSchin done 499da2e3ebdSchin (( sum > n )) || err_exit "command -x processed only $sum arguments" 500da2e3ebdSchin (( (sum-n)%3==0 )) || err_exit "command -x processed only $sum arguments" 501da2e3ebdSchin (( sum == n+3)) && err_exit "command -x processed only $sum arguments" 502da2e3ebdSchin command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1 503da2e3ebdSchin [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x' 504da2e3ebdSchinfi 505da2e3ebdSchin# test for debug trap 506da2e3ebdSchin[[ $(typeset -i i=0 507da2e3ebdSchin trap 'print $i' DEBUG 508da2e3ebdSchin while (( i <2)) 509da2e3ebdSchin do (( i++)) 510da2e3ebdSchin done) == $'0\n0\n1\n1\n2' ]] || err_exit "DEBUG trap not working" 511da2e3ebdSchingetconf UNIVERSE - ucb 512da2e3ebdSchin[[ $($SHELL -c 'echo -3') == -3 ]] || err_exit "echo -3 not working in ucb universe" 513da2e3ebdSchintypeset -F3 start_x=SECONDS total_t delay=0.02 514da2e3ebdSchintypeset reps=50 leeway=5 515b30d1939SAndy Fiddamansleep $(( 2 * leeway * reps * delay )) | 516b30d1939SAndy Fiddamanfor (( i=0 ; i < reps ; i++ )) 517b30d1939SAndy Fiddamando read -N1 -t $delay 518b30d1939SAndy Fiddamandone 519b30d1939SAndy Fiddaman(( total_t = SECONDS - start_x )) 520b30d1939SAndy Fiddamanif (( total_t > leeway * reps * delay )) 521b30d1939SAndy Fiddamanthen err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too long" 522b30d1939SAndy Fiddamanelif (( total_t < reps * delay )) 523b30d1939SAndy Fiddamanthen err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too fast" 524b30d1939SAndy Fiddamanfi 525b30d1939SAndy Fiddaman$SHELL -c 'sleep $(printf "%a" .95)' 2> /dev/null || err_exit "sleep doesn't except %a format constants" 526b30d1939SAndy Fiddaman$SHELL -c 'test \( ! -e \)' 2> /dev/null ; [[ $? == 1 ]] || err_exit 'test \( ! -e \) not working' 5277c2fbfb3SApril Chin[[ $(ulimit) == "$(ulimit -fS)" ]] || err_exit 'ulimit is not the same as ulimit -fS' 52834f9b3eeSRoland Mainztmpfile=$tmp/file.2 5297c2fbfb3SApril Chinprint $'\nprint -r -- "${.sh.file} ${LINENO} ${.sh.lineno}"' > $tmpfile 5307c2fbfb3SApril Chin[[ $( . "$tmpfile") == "$tmpfile 2 1" ]] || err_exit 'dot command not working' 5317c2fbfb3SApril Chinprint -r -- "'xxx" > $tmpfile 5327c2fbfb3SApril Chin[[ $($SHELL -c ". $tmpfile"$'\n print ok' 2> /dev/null) == ok ]] || err_exit 'syntax error in dot command affects next command' 5337c2fbfb3SApril Chin 534b30d1939SAndy Fiddamanfloat sec=$SECONDS del=4 535b30d1939SAndy Fiddamanexec 3>&2 2>/dev/null 536b30d1939SAndy Fiddaman$SHELL -c "( sleep 1; kill -ALRM \$\$ ) & sleep $del" 2> /dev/null 537b30d1939SAndy Fiddamanexitval=$? 538b30d1939SAndy Fiddaman(( sec = SECONDS - sec )) 539b30d1939SAndy Fiddamanexec 2>&3- 540b30d1939SAndy Fiddaman(( exitval )) && err_exit "sleep doesn't exit 0 with ALRM interupt" 541b30d1939SAndy Fiddaman(( sec > (del - 1) )) || err_exit "ALRM signal causes sleep to terminate prematurely -- expected 3 sec, got $sec" 54234f9b3eeSRoland Mainztypeset -r z=3 54334f9b3eeSRoland Mainzy=5 54434f9b3eeSRoland Mainzfor i in 123 z %x a.b.c 54534f9b3eeSRoland Mainzdo ( unset $i) 2>/dev/null && err_exit "unset $i should fail" 54634f9b3eeSRoland Mainzdone 54734f9b3eeSRoland Mainza=() 54834f9b3eeSRoland Mainzfor i in y y y[8] t[abc] y.d a.b a 54934f9b3eeSRoland Mainzdo unset $i || print -u2 "err_exit unset $i should not fail" 55034f9b3eeSRoland Mainzdone 55134f9b3eeSRoland Mainz[[ $($SHELL -c 'y=3; unset 123 y;print $?$y') == 1 ]] 2> /dev/null || err_exit 'y is not getting unset with unset 123 y' 55234f9b3eeSRoland Mainz[[ $($SHELL -c 'trap foo TERM; (trap;(trap) )') == 'trap -- foo TERM' ]] || err_exit 'traps not getting reset when subshell is last process' 5537c2fbfb3SApril Chin 554b30d1939SAndy Fiddamann=$(printf "%b" 'a\0b\0c' | wc -c) 555b30d1939SAndy Fiddaman(( n == 5 )) || err_exit '\0 not working with %b format with printf' 556b30d1939SAndy Fiddaman 557b30d1939SAndy Fiddamant=$(ulimit -t) 558b30d1939SAndy Fiddaman[[ $($SHELL -c 'ulimit -v 15000 2>/dev/null; ulimit -t') == "$t" ]] || err_exit 'ulimit -v changes ulimit -t' 559b30d1939SAndy Fiddaman 560b30d1939SAndy Fiddaman$SHELL 2> /dev/null -c 'cd ""' && err_exit 'cd "" not producing an error' 561b30d1939SAndy Fiddaman[[ $($SHELL 2> /dev/null -c 'cd "";print hi') != hi ]] && err_exit 'cd "" should not terminate script' 562b30d1939SAndy Fiddaman 563b30d1939SAndy Fiddamanbincat=$(whence -p cat) 564b30d1939SAndy Fiddamanbuiltin cat 565b30d1939SAndy Fiddamanout=$tmp/seq.out 566b30d1939SAndy Fiddamanseq 11 >$out 567b30d1939SAndy Fiddamancmp -s <(print -- "$($bincat<( $bincat $out ) )") <(print -- "$(cat <( cat $out ) )") || err_exit "builtin cat differs from $bincat" 568b30d1939SAndy Fiddaman 569b30d1939SAndy Fiddaman[[ $($SHELL -c '{ printf %R "["; print ok;}' 2> /dev/null) == ok ]] || err_exit $'\'printf %R "["\' causes shell to abort' 570b30d1939SAndy Fiddaman 571b30d1939SAndy Fiddamanv=$( $SHELL -c $' 572b30d1939SAndy Fiddaman trap \'print "usr1"\' USR1 573b30d1939SAndy Fiddaman trap exit USR2 574b30d1939SAndy Fiddaman sleep 1 && { 575b30d1939SAndy Fiddaman kill -USR1 $$ && sleep 1 576b30d1939SAndy Fiddaman kill -0 $$ 2>/dev/null && kill -USR2 $$ 577b30d1939SAndy Fiddaman } & 578b30d1939SAndy Fiddaman sleep 2 | read 579b30d1939SAndy Fiddaman echo done 580b30d1939SAndy Fiddaman' ) 2> /dev/null 581b30d1939SAndy Fiddaman[[ $v == $'usr1\ndone' ]] || err_exit 'read not terminating when receiving USR1 signal' 582b30d1939SAndy Fiddaman 583b30d1939SAndy Fiddamanmkdir $tmp/tmpdir1 584b30d1939SAndy Fiddamancd $tmp/tmpdir1 585b30d1939SAndy Fiddamanpwd=$PWD 586b30d1939SAndy Fiddamancd ../tmpdir1 587b30d1939SAndy Fiddaman[[ $PWD == "$pwd" ]] || err_exit 'cd ../tmpdir1 causes directory to change' 588b30d1939SAndy Fiddamancd "$pwd" 589b30d1939SAndy Fiddamanmv $tmp/tmpdir1 $tmp/tmpdir2 590b30d1939SAndy Fiddamancd .. 2> /dev/null || err_exit 'cannot change directory to .. after current directory has been renamed' 591b30d1939SAndy Fiddaman[[ $PWD == "$tmp" ]] || err_exit 'after "cd $tmp/tmpdir1; cd .." directory is not $tmp' 592b30d1939SAndy Fiddaman 593b30d1939SAndy Fiddamancd "$tmp" 594b30d1939SAndy Fiddamanmkdir $tmp/tmpdir2/foo 595b30d1939SAndy Fiddamanpwd=$PWD 596b30d1939SAndy Fiddamancd $tmp/tmpdir2/foo 597b30d1939SAndy Fiddamanmv $tmp/tmpdir2 $tmp/tmpdir1 598b30d1939SAndy Fiddamancd ../.. 2> /dev/null || err_exit 'cannot change directory to ../.. after current directory has been renamed' 599b30d1939SAndy Fiddaman[[ $PWD == "$tmp" ]] || err_exit 'after "cd $tmp/tmpdir2; cd ../.." directory is not $tmp' 600b30d1939SAndy Fiddamancd "$tmp" 601b30d1939SAndy Fiddamanrm -rf tmpdir1 602b30d1939SAndy Fiddaman 603b30d1939SAndy Fiddamancd /etc 604b30d1939SAndy Fiddamancd .. 605b30d1939SAndy Fiddaman[[ $(pwd) == / ]] || err_exit 'cd /etc;cd ..;pwd is not /' 606b30d1939SAndy Fiddamancd /etc 607b30d1939SAndy Fiddamancd ../.. 608b30d1939SAndy Fiddaman[[ $(pwd) == / ]] || err_exit 'cd /etc;cd ../..;pwd is not /' 609b30d1939SAndy Fiddamancd /etc 610b30d1939SAndy Fiddamancd .././.. 611b30d1939SAndy Fiddaman[[ $(pwd) == / ]] || err_exit 'cd /etc;cd .././..;pwd is not /' 612b30d1939SAndy Fiddamancd /usr/bin 613b30d1939SAndy Fiddamancd ../.. 614b30d1939SAndy Fiddaman[[ $(pwd) == / ]] || err_exit 'cd /usr/bin;cd ../..;pwd is not /' 615b30d1939SAndy Fiddamancd /usr/bin 616b30d1939SAndy Fiddamancd .. 617b30d1939SAndy Fiddaman[[ $(pwd) == /usr ]] || err_exit 'cd /usr/bin;cd ..;pwd is not /usr' 618b30d1939SAndy Fiddamancd "$tmp" 619b30d1939SAndy Fiddamanif mkdir $tmp/t1 620b30d1939SAndy Fiddamanthen ( 621b30d1939SAndy Fiddaman cd $tmp/t1 622b30d1939SAndy Fiddaman > real_t1 623b30d1939SAndy Fiddaman ( 624b30d1939SAndy Fiddaman cd .. 625b30d1939SAndy Fiddaman mv t1 t2 626b30d1939SAndy Fiddaman mkdir t1 627b30d1939SAndy Fiddaman ) 628b30d1939SAndy Fiddaman [[ -f real_t1 ]] || err_exit 'real_t1 not found after parent directory renamed in subshell' 629b30d1939SAndy Fiddaman ) 630b30d1939SAndy Fiddamanfi 631b30d1939SAndy Fiddamancd "$tmp" 632b30d1939SAndy Fiddaman 633b30d1939SAndy Fiddaman$SHELL +E -i <<- \! && err_exit 'interactive shell should not exit 0 after false' 634b30d1939SAndy Fiddaman false 635b30d1939SAndy Fiddaman exit 636b30d1939SAndy Fiddaman! 637b30d1939SAndy Fiddaman 638b30d1939SAndy Fiddamanif kill -L > /dev/null 2>&1 639b30d1939SAndy Fiddamanthen [[ $(kill -l HUP) == "$(kill -L HUP)" ]] || err_exit 'kill -l and kill -L are not the same when given a signal name' 640b30d1939SAndy Fiddaman [[ $(kill -l 9) == "$(kill -L 9)" ]] || err_exit 'kill -l and kill -L are not the same when given a signal number' 641b30d1939SAndy Fiddaman [[ $(kill -L) == *'9) KILL'* ]] || err_exit 'kill -L output does not contain 9) KILL' 642b30d1939SAndy Fiddamanfi 643b30d1939SAndy Fiddaman 644b30d1939SAndy Fiddamanunset ENV 645b30d1939SAndy Fiddamanv=$($SHELL 2> /dev/null +o rc -ic $'getopts a:bc: opt --man\nprint $?') 646b30d1939SAndy Fiddaman[[ $v == 2* ]] || err_exit 'getopts --man does not exit 2 for interactive shells' 647b30d1939SAndy Fiddaman 648b30d1939SAndy Fiddamanread baz <<< 'foo\\\\bar' 649b30d1939SAndy Fiddaman[[ $baz == 'foo\\bar' ]] || err_exit 'read of foo\\\\bar not getting foo\\bar' 650b30d1939SAndy Fiddaman 651b30d1939SAndy Fiddaman: ~root 652b30d1939SAndy Fiddaman[[ $(builtin) == *.sh.tilde* ]] && err_exit 'builtin contains .sh.tilde' 653b30d1939SAndy Fiddaman 654b30d1939SAndy Fiddamanexit $((Errors<125?Errors:125)) 655