1######################################################################## 2# # 3# This software is part of the ast package # 4# Copyright (c) 1982-2007 AT&T Knowledge Ventures # 5# and is licensed under the # 6# Common Public License, Version 1.0 # 7# by AT&T Knowledge Ventures # 8# # 9# A copy of the License is available at # 10# http://www.opensource.org/licenses/cpl1.0.txt # 11# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # 12# # 13# Information and Software Systems Research # 14# AT&T Research # 15# Florham Park NJ # 16# # 17# David Korn <dgk@research.att.com> # 18# # 19######################################################################## 20function err_exit 21{ 22 print -u2 -n "\t" 23 print -u2 -r ${Command}[$1]: "${@:2}" 24 let Errors+=1 25} 26alias err_exit='err_exit $LINENO' 27 28# test shell builtin commands 29Command=${0##*/} 30integer Errors=0 31builtin getconf 32: ${foo=bar} || err_exit ": failed" 33[[ $foo = bar ]] || err_exit ": side effects failed" 34set -- - foobar 35[[ $# = 2 && $1 = - && $2 = foobar ]] || err_exit "set -- - foobar failed" 36set -- -x foobar 37[[ $# = 2 && $1 = -x && $2 = foobar ]] || err_exit "set -- -x foobar failed" 38getopts :x: foo || err_exit "getopts :x: returns false" 39[[ $foo = x && $OPTARG = foobar ]] || err_exit "getopts :x: failed" 40OPTIND=1 41getopts :r:s var -r 42if [[ $var != : || $OPTARG != r ]] 43then err_exit "'getopts :r:s var -r' not working" 44fi 45OPTIND=1 46getopts :d#u var -d 100 47if [[ $var != d || $OPTARG != 100 ]] 48then err_exit "'getopts :d#u var -d 100' not working var=$var" 49fi 50OPTIND=1 51while getopts 'ab' option -a -b 52do [[ $OPTIND == $((OPTIND)) ]] || err_exit "OPTIND optimization bug" 53done 54 55USAGE=$'[-][S:server?Operate on the specified \asubservice\a:]:[subservice:=pmserver] 56 { 57 [p:pmserver] 58 [r:repserver] 59 [11:notifyd] 60 }' 61set pmser p rep r notifyd -11 62while (( $# > 1 )) 63do OPTIND=1 64 getopts "$USAGE" OPT -S $1 65 [[ $OPT == S && $OPTARG == $2 ]] || err_exit "OPT=$OPT OPTARG=$OPTARG -- expected OPT=S OPTARG=$2" 66 shift 2 67done 68 69false ${foo=bar} && err_exit "false failed" 70read <<! 71hello world 72! 73[[ $REPLY = 'hello world' ]] || err_exit "read builtin failed" 74print x:y | IFS=: read a b 75if [[ $a != x ]] 76then err_exit "IFS=: read ... not working" 77fi 78read <<! 79hello \ 80world 81! 82[[ $REPLY = 'hello world' ]] || err_exit "read continuation failed" 83read -d x <<! 84hello worldxfoobar 85! 86[[ $REPLY = 'hello world' ]] || err_exit "read builtin failed" 87read <<\! 88hello \ 89 world \ 90 91! 92[[ $REPLY == 'hello world' ]] || err_exit "read continuation2 failed" 93print "one\ntwo" | { read line 94 print $line | /bin/cat > /dev/null 95 read line 96} 97read <<\! 98\ 99a\ 100\ 101\ 102b 103! 104if [[ $REPLY != ab ]] 105then err_exit "read multiple continuation failed" 106fi 107if [[ $line != two ]] 108then err_exit "read from pipeline failed" 109fi 110line=two 111read line < /dev/null 112if [[ $line != "" ]] 113then err_exit "read from /dev/null failed" 114fi 115if [[ $(print -R -) != - ]] 116then err_exit "print -R not working correctly" 117fi 118if [[ $(print -- -) != - ]] 119then err_exit "print -- not working correctly" 120fi 121print -f "hello%nbar\n" size > /dev/null 122if (( size != 5 )) 123then err_exit "%n format of printf not working" 124fi 125print -n -u2 2>&1- 126[[ -w /dev/fd/1 ]] || err_exit "2<&1- with built-ins has side effects" 127x=$0 128if [[ $(eval 'print $0') != $x ]] 129then err_exit '$0 not correct for eval' 130fi 131unset x 132readonly x 133set -- $(readonly) 134if [[ " $@ " != *" x "* ]] 135then err_exit 'unset readonly variables are not displayed' 136fi 137if [[ $( for i in foo bar 138 do print $i 139 continue 10 140 done 141 ) != $'foo\nbar' ]] 142then err_exit 'continue breaks out of loop' 143fi 144(continue bad 2>/dev/null && err_exit 'continue bad should return an error') 145(break bad 2>/dev/null && err_exit 'break bad should return an error') 146(continue 0 2>/dev/null && err_exit 'continue 0 should return an error') 147(break 0 2>/dev/null && err_exit 'break 0 should return an error') 148breakfun() { break;} 149continuefun() { continue;} 150for fun in break continue 151do if [[ $( for i in foo 152 do ${fun}fun 153 print $i 154 done 155 ) != foo ]] 156 then err_exit "$fun call in ${fun}fun breaks out of for loop" 157 fi 158done 159if [[ $(print -f "%b" "\a\n\v\b\r\f\E\03\\oo") != $'\a\n\v\b\r\f\E\03\\oo' ]] 160then err_exit 'print -f "%b" not working' 161fi 162if [[ $(print -f "%P" "[^x].*b$") != '*[!x]*b' ]] 163then err_exit 'print -f "%P" not working' 164fi 165if [[ $(abc: for i in foo bar;do print $i;break abc;done) != foo ]] 166then err_exit 'break labels not working' 167fi 168if [[ $(command -v if) != if ]] 169then err_exit 'command -v not working' 170fi 171read -r var <<\! 172 173! 174if [[ $var != "" ]] 175then err_exit "read -r of blank line not working" 176fi 177mkdir -p /tmp/ksh$$/a/b/c 2>/dev/null || err_exit "mkdir -p failed" 178$SHELL -c "cd /tmp/ksh$$/a/b; cd c" 2>/dev/null || err_exit "initial script relative cd fails" 179rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" 180trap 'print HUP' HUP 181if [[ $(trap) != "trap -- 'print HUP' HUP" ]] 182then err_exit '$(trap) not working' 183fi 184if [[ $(trap -p HUP) != 'print HUP' ]] 185then err_exit '$(trap -p HUP) not working' 186fi 187[[ $($SHELL -c 'trap "print ok" SIGTERM; kill -s SIGTERM $$' 2> /dev/null) == ok 188 ]] || err_exit 'SIGTERM not recognized' 189[[ $($SHELL -c 'trap "print ok" sigterm; kill -s sigterm $$' 2> /dev/null) == ok 190 ]] || err_exit 'SIGTERM not recognized' 191${SHELL} -c 'kill -1 -$$' 2> /dev/null 192[[ $(kill -l $?) == HUP ]] || err_exit 'kill -1 -pid not working' 193${SHELL} -c 'kill -1 -$$' 2> /dev/null 194[[ $(kill -l $?) == HUP ]] || err_exit 'kill -n1 -pid not working' 195${SHELL} -c 'kill -s HUP -$$' 2> /dev/null 196[[ $(kill -l $?) == HUP ]] || err_exit 'kill -HUP -pid not working' 197n=123 198typeset -A base 199base[o]=8# 200base[x]=16# 201base[X]=16# 202for i in d i o u x X 203do if (( $(( ${base[$i]}$(printf "%$i" $n) )) != n )) 204 then err_exit "printf %$i not working" 205 fi 206done 207if [[ $( trap 'print done' EXIT) != done ]] 208then err_exit 'trap on EXIT not working' 209fi 210if [[ $( trap 'print done' EXIT; trap - EXIT) == done ]] 211then err_exit 'trap on EXIT not being cleared' 212fi 213if [[ $(type test) != 'test is a shell builtin' ]] 214then err_exit 'whence -v test not a builtin' 215fi 216builtin -d test 217if [[ $(type test) == *builtin* ]] 218then err_exit 'whence -v test after builtin -d incorrect' 219fi 220typeset -Z3 percent=$(printf '%o\n' "'%'") 221forrmat=\\${percent}s 222if [[ $(printf "$forrmat") != %s ]] 223then err_exit "printf $forrmat not working" 224fi 225if (( $(printf 'x\0y' | wc -c) != 3 )) 226then err_exit 'printf \0 not working' 227fi 228if [[ $(printf "%bx%s\n" 'f\to\cbar') != $'f\to' ]] 229then err_exit 'printf %bx%s\n not working' 230fi 231alpha=abcdefghijklmnop 232if [[ $(printf "%10.*s\n" 5 $alpha) != ' abcde' ]] 233then err_exit 'printf %10.%s\n not working' 234fi 235float x2=.0000625 236if [[ $(printf "%10.5E\n" x2) != 6.25000E-05 ]] 237then err_exit 'printf "%10.5E" not normalizing correctly' 238fi 239x2=.000000001 240if [[ $(printf "%g\n" x2 2>/dev/null) != 1e-09 ]] 241then err_exit 'printf "%g" not working correctly' 242fi 243#FIXME#($SHELL read -s foobar <<\! 244#FIXME#testing 245#FIXME#! 246#FIXME#) 2> /dev/null || err_exit ksh read -s var fails 247if [[ $(printf +3 2>/dev/null) != +3 ]] 248then err_exit 'printf is not processing formats beginning with + correctly' 249fi 250if printf "%d %d\n" 123bad 78 >/dev/null 2>/dev/null 251then err_exit "printf not exiting non-zero with conversion errors" 252fi 253if [[ $(trap --version 2> /dev/null;print done) != done ]] 254then err_exit 'trap builtin terminating after --version' 255fi 256if [[ $(set --version 2> /dev/null;print done) != done ]] 257then err_exit 'set builtin terminating after --veresion' 258fi 259unset -f foobar 260function foobar 261{ 262 print 'hello world' 263} 264OPTIND=1 265if [[ $(getopts $'[+?X\ffoobar\fX]' v --man 2>&1) != *'Xhello world'X* ]] 266then err_exit '\f...\f not working in getopts usage strings' 267fi 268if [[ $(printf '%H\n' $'<>"& \'\tabc') != '<>"& '	abc' ]] 269then err_exit 'printf %H not working' 270fi 271if [[ $(printf '%R %R %R %R\n' 'a.b' '*.c' '^' '!(*.*)') != '^a\.b$ \.c$ ^\^$ ^(.*\..*)!$' ]] 272then err_exit 'printf %R not working' 273fi 274if [[ $(printf '%..:c\n' abc) != a:b:c ]] 275then err_exit "printf '%..:c' not working" 276fi 277if [[ $(printf '%..*c\n' : abc) != a:b:c ]] 278then err_exit "printf '%..*c' not working" 279fi 280if [[ $(printf '%..:s\n' abc def ) != abc:def ]] 281then err_exit "printf '%..:s' not working" 282fi 283if [[ $(printf '%..*s\n' : abc def) != abc:def ]] 284then err_exit "printf '%..*s' not working" 285fi 286[[ $(printf '%q\n') == '' ]] || err_exit 'printf "%q" with missing arguments' 287# we won't get hit by the one second boundary twice, right? 288[[ $(printf '%T\n' now) == "$(date)" ]] || 289[[ $(printf '%T\n' now) == "$(date)" ]] || 290err_exit 'printf "%T" now' 291behead() 292{ 293 read line 294 left=$(cat) 295} 296print $'line1\nline2' | behead 297if [[ $left != line2 ]] 298then err_exit "read reading ahead on a pipe" 299fi 300read -n1 y <<! 301abc 302! 303if [[ $y != a ]] 304then err_exit 'read -n1 not working' 305fi 306print -n $'{ read -r line;print $line;}\nhello' > /tmp/ksh$$ 307chmod 755 /tmp/ksh$$ 308trap 'rm -rf /tmp/ksh$$' EXIT 309if [[ $($SHELL < /tmp/ksh$$) != hello ]] 310then err_exit 'read of incomplete line not working correctly' 311fi 312set -f 313set -- * 314if [[ $1 != '*' ]] 315then err_exit 'set -f not working' 316fi 317unset pid1 pid2 318false & 319pid1=$! 320pid2=$( 321 wait $pid1 322 (( $? == 127 )) || err_exit "job known to subshell" 323 print $! 324) 325wait $pid1 326(( $? == 1 )) || err_exit "wait not saving exit value" 327wait $pid2 328(( $? == 127 )) || err_exit "subshell job known to parent" 329set --noglob 330ifs=$IFS 331IFS=, 332set -- $(getconf LIBPATH) 333IFS=$ifs 334env= 335for v 336do IFS=: 337 set -- $v 338 IFS=$ifs 339 eval [[ \$$2 ]] && env="$env $2=\"\$$2\"" 340done 341set --glob 342if [[ $(foo=bar; eval foo=\$foo $env exec -c \$SHELL -c \'print \$foo\') != bar ]] 343then err_exit '"name=value exec -c ..." not working' 344fi 345$SHELL -c 'OPTIND=-1000000; getopts a opt -a' 2> /dev/null 346[[ $? == 1 ]] || err_exit 'getopts with negative OPTIND not working' 347getopts 'n#num' opt -n 3 348[[ $OPTARG == 3 ]] || err_exit 'getopts with numerical arguments failed' 349if [[ $($SHELL -c $'printf \'%2$s %1$s\n\' world hello') != 'hello world' ]] 350then err_exit 'printf %2$s %1$s not working' 351fi 352((n=0)) 353((n++)); ARGC[$n]=1 ARGV[$n]="" 354((n++)); ARGC[$n]=2 ARGV[$n]="-a" 355((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2" 356((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x" 357((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x y" 358for ((i=1; i<=n; i++)) 359do set -- ${ARGV[$i]} 360 OPTIND=0 361 while getopts -a tst "av:" OPT 362 do : 363 done 364 if [[ $OPTIND != ${ARGC[$i]} ]] 365 then err_exit "\$OPTIND after getopts loop incorrect -- got $OPTIND, expected ${ARGC[$i]}" 366 fi 367done 368unset a 369{ read -N3 a; read -N1 b;} <<! 370abcdefg 371! 372[[ $a == abc ]] || err_exit 'read -N3 here-document not working' 373[[ $b == d ]] || err_exit 'read -N1 here-document not working' 374read -n3 a <<! 375abcdefg 376! 377[[ $a == abc ]] || err_exit 'read -n3 here-document not working' 378(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;} 379[[ $a == abc ]] || err_exit 'read -N3 from pipe not working' 380[[ $b == d ]] || err_exit 'read -N1 from pipe not working' 381(print -n a;sleep 1; print -n bcde) |read -n3 a 382[[ $a == a ]] || err_exit 'read -n3 from pipe not working' 383rm -f /tmp/fifo$$ 384if mkfifo /tmp/fifo$$ 2> /dev/null 385then (print -n a; sleep 1;print -n bcde) > /tmp/fifo$$ & 386 { 387 read -u5 -n3 -t2 a || err_exit 'read -n3 from fifo timedout' 388 read -u5 -n1 -t2 b || err_exit 'read -n1 from fifo timedout' 389 } 5< /tmp/fifo$$ 390 [[ $a == a ]] || err_exit 'read -n3 from fifo not working' 391 rm -f /tmp/fifo$$ 392 mkfifo /tmp/fifo$$ 2> /dev/null 393 (print -n a; sleep 1;print -n bcde) > /tmp/fifo$$ & 394 { 395 read -u5 -N3 -t2 a || err_exit 'read -N3 from fifo timed out' 396 read -u5 -N1 -t2 b || err_exit 'read -N1 from fifo timedout' 397 } 5< /tmp/fifo$$ 398 [[ $a == abc ]] || err_exit 'read -N3 from fifo not working' 399 [[ $b == d ]] || err_exit 'read -N1 from fifo not working' 400fi 401rm -f /tmp/fifo$$ 402function longline 403{ 404 integer i 405 for((i=0; i < $1; i++)) 406 do print argument$i 407 done 408} 409# test command -x option 410integer sum=0 n=10000 411if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1 412then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) 2> /dev/null) 413 do ((sum += $i)) 414 done 415 (( sum == n )) || err_exit "command -x processed only $sum arguments" 416 command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1 417 [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x' 418fi 419# test command -x option with extra arguments 420integer sum=0 n=10000 421if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1 422then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) one two three) #2> /dev/null) 423 do ((sum += $i)) 424 done 425 (( sum > n )) || err_exit "command -x processed only $sum arguments" 426 (( (sum-n)%3==0 )) || err_exit "command -x processed only $sum arguments" 427 (( sum == n+3)) && err_exit "command -x processed only $sum arguments" 428 command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1 429 [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x' 430fi 431# test for debug trap 432[[ $(typeset -i i=0 433 trap 'print $i' DEBUG 434 while (( i <2)) 435 do (( i++)) 436 done) == $'0\n0\n1\n1\n2' ]] || err_exit "DEBUG trap not working" 437getconf UNIVERSE - ucb 438[[ $($SHELL -c 'echo -3') == -3 ]] || err_exit "echo -3 not working in ucb universe" 439typeset -F3 start_x=SECONDS total_t delay=0.02 440typeset reps=50 leeway=5 441sleep $(( 2 * leeway * reps * delay )) | 442for (( i=0 ; i < reps ; i++ )) 443do read -N1 -t $delay 444done 445(( total_t = SECONDS - start_x )) 446if (( total_t > leeway * reps * delay )) 447then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too long" 448elif (( total_t < reps * delay )) 449then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too fast" 450fi 451exit $((Errors)) 452