1######################################################################## 2# # 3# This software is part of the ast package # 4# Copyright (c) 1982-2008 AT&T Intellectual Property # 5# and is licensed under the # 6# Common Public License, Version 1.0 # 7# by AT&T Intellectual Property # 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 OPT -d 16177 47if [[ $OPT != d || $OPTARG != 16177 ]] 48then err_exit "'getopts :d#u OPT=d OPTARG=16177' failed -- OPT=$OPT OPTARG=$OPTARG" 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 131$SHELL -c 'read x <<< hello' 2> /dev/null || err_exit 'syntax <<< not recognized' 132($SHELL -c 'read x[1] <<< hello') 2> /dev/null || err_exit 'read x[1] not working' 133unset x 134readonly x 135set -- $(readonly) 136if [[ " $@ " != *" x "* ]] 137then err_exit 'unset readonly variables are not displayed' 138fi 139if [[ $( for i in foo bar 140 do print $i 141 continue 10 142 done 143 ) != $'foo\nbar' ]] 144then err_exit 'continue breaks out of loop' 145fi 146(continue bad 2>/dev/null && err_exit 'continue bad should return an error') 147(break bad 2>/dev/null && err_exit 'break bad should return an error') 148(continue 0 2>/dev/null && err_exit 'continue 0 should return an error') 149(break 0 2>/dev/null && err_exit 'break 0 should return an error') 150breakfun() { break;} 151continuefun() { continue;} 152for fun in break continue 153do if [[ $( for i in foo 154 do ${fun}fun 155 print $i 156 done 157 ) != foo ]] 158 then err_exit "$fun call in ${fun}fun breaks out of for loop" 159 fi 160done 161if [[ $(print -f "%b" "\a\n\v\b\r\f\E\03\\oo") != $'\a\n\v\b\r\f\E\03\\oo' ]] 162then err_exit 'print -f "%b" not working' 163fi 164if [[ $(print -f "%P" "[^x].*b\$") != '*[!x]*b' ]] 165then err_exit 'print -f "%P" not working' 166fi 167if [[ $(abc: for i in foo bar;do print $i;break abc;done) != foo ]] 168then err_exit 'break labels not working' 169fi 170if [[ $(command -v if) != if ]] 171then err_exit 'command -v not working' 172fi 173read -r var <<\! 174 175! 176if [[ $var != "" ]] 177then err_exit "read -r of blank line not working" 178fi 179mkdir -p /tmp/ksh$$/a/b/c 2>/dev/null || err_exit "mkdir -p failed" 180$SHELL -c "cd /tmp/ksh$$/a/b; cd c" 2>/dev/null || err_exit "initial script relative cd fails" 181rm -r /tmp/ksh$$ || err_exit "rm -r /tmp/ksh$$ failed" 182trap 'print HUP' HUP 183if [[ $(trap) != "trap -- 'print HUP' HUP" ]] 184then err_exit '$(trap) not working' 185fi 186if [[ $(trap -p HUP) != 'print HUP' ]] 187then err_exit '$(trap -p HUP) not working' 188fi 189[[ $($SHELL -c 'trap "print ok" SIGTERM; kill -s SIGTERM $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized' 190[[ $($SHELL -c 'trap "print ok" sigterm; kill -s sigterm $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized' 191[[ $($SHELL -c '( trap "" TERM);kill $$;print bad' == bad) ]] 2> /dev/null && err_exit 'trap ignored in subshell causes it to be ignored by parent' 192${SHELL} -c 'kill -1 -$$' 2> /dev/null 193[[ $(kill -l $?) == HUP ]] || err_exit 'kill -1 -pid not working' 194${SHELL} -c 'kill -1 -$$' 2> /dev/null 195[[ $(kill -l $?) == HUP ]] || err_exit 'kill -n1 -pid not working' 196${SHELL} -c 'kill -s HUP -$$' 2> /dev/null 197[[ $(kill -l $?) == HUP ]] || err_exit 'kill -HUP -pid not working' 198n=123 199typeset -A base 200base[o]=8# 201base[x]=16# 202base[X]=16# 203for i in d i o u x X 204do if (( $(( ${base[$i]}$(printf "%$i" $n) )) != n )) 205 then err_exit "printf %$i not working" 206 fi 207done 208if [[ $( trap 'print done' EXIT) != done ]] 209then err_exit 'trap on EXIT not working' 210fi 211if [[ $( trap 'print done' EXIT; trap - EXIT) == done ]] 212then err_exit 'trap on EXIT not being cleared' 213fi 214if [[ $(type test) != 'test is a shell builtin' ]] 215then err_exit 'whence -v test not a builtin' 216fi 217builtin -d test 218if [[ $(type test) == *builtin* ]] 219then err_exit 'whence -v test after builtin -d incorrect' 220fi 221typeset -Z3 percent=$(printf '%o\n' "'%'") 222forrmat=\\${percent}s 223if [[ $(printf "$forrmat") != %s ]] 224then err_exit "printf $forrmat not working" 225fi 226if (( $(printf 'x\0y' | wc -c) != 3 )) 227then err_exit 'printf \0 not working' 228fi 229if [[ $(printf "%bx%s\n" 'f\to\cbar') != $'f\to' ]] 230then err_exit 'printf %bx%s\n not working' 231fi 232alpha=abcdefghijklmnop 233if [[ $(printf "%10.*s\n" 5 $alpha) != ' abcde' ]] 234then err_exit 'printf %10.%s\n not working' 235fi 236float x2=.0000625 237if [[ $(printf "%10.5E\n" x2) != 6.25000E-05 ]] 238then err_exit 'printf "%10.5E" not normalizing correctly' 239fi 240x2=.000000001 241if [[ $(printf "%g\n" x2 2>/dev/null) != 1e-09 ]] 242then err_exit 'printf "%g" not working correctly' 243fi 244#FIXME#($SHELL read -s foobar <<\! 245#FIXME#testing 246#FIXME#! 247#FIXME#) 2> /dev/null || err_exit ksh read -s var fails 248if [[ $(printf +3 2>/dev/null) != +3 ]] 249then err_exit 'printf is not processing formats beginning with + correctly' 250fi 251if printf "%d %d\n" 123bad 78 >/dev/null 2>/dev/null 252then err_exit "printf not exiting non-zero with conversion errors" 253fi 254if [[ $(trap --version 2> /dev/null;print done) != done ]] 255then err_exit 'trap builtin terminating after --version' 256fi 257if [[ $(set --version 2> /dev/null;print done) != done ]] 258then err_exit 'set builtin terminating after --veresion' 259fi 260unset -f foobar 261function foobar 262{ 263 print 'hello world' 264} 265OPTIND=1 266if [[ $(getopts $'[+?X\ffoobar\fX]' v --man 2>&1) != *'Xhello world'X* ]] 267then err_exit '\f...\f not working in getopts usage strings' 268fi 269if [[ $(printf '%H\n' $'<>"& \'\tabc') != '<>"& '	abc' ]] 270then err_exit 'printf %H not working' 271fi 272if [[ $(printf '%R %R %R %R\n' 'a.b' '*.c' '^' '!(*.*)') != '^a\.b$ \.c$ ^\^$ ^(.*\..*)!$' ]] 273then err_exit 'printf %R not working' 274fi 275if [[ $(printf '%..:c\n' abc) != a:b:c ]] 276then err_exit "printf '%..:c' not working" 277fi 278if [[ $(printf '%..*c\n' : abc) != a:b:c ]] 279then err_exit "printf '%..*c' not working" 280fi 281if [[ $(printf '%..:s\n' abc def ) != abc:def ]] 282then err_exit "printf '%..:s' not working" 283fi 284if [[ $(printf '%..*s\n' : abc def) != abc:def ]] 285then err_exit "printf '%..*s' not working" 286fi 287[[ $(printf '%q\n') == '' ]] || err_exit 'printf "%q" with missing arguments' 288# we won't get hit by the one second boundary twice, right? 289[[ $(printf '%T\n' now) == "$(date)" ]] || 290[[ $(printf '%T\n' now) == "$(date)" ]] || 291err_exit 'printf "%T" now' 292behead() 293{ 294 read line 295 left=$(cat) 296} 297print $'line1\nline2' | behead 298if [[ $left != line2 ]] 299then err_exit "read reading ahead on a pipe" 300fi 301print -n $'{ read -r line;print $line;}\nhello' > /tmp/ksh$$ 302chmod 755 /tmp/ksh$$ 303trap 'rm -rf /tmp/ksh$$' EXIT 304if [[ $($SHELL < /tmp/ksh$$) != hello ]] 305then err_exit 'read of incomplete line not working correctly' 306fi 307set -f 308set -- * 309if [[ $1 != '*' ]] 310then err_exit 'set -f not working' 311fi 312unset pid1 pid2 313false & 314pid1=$! 315pid2=$( 316 wait $pid1 317 (( $? == 127 )) || err_exit "job known to subshell" 318 print $! 319) 320wait $pid1 321(( $? == 1 )) || err_exit "wait not saving exit value" 322wait $pid2 323(( $? == 127 )) || err_exit "subshell job known to parent" 324set --noglob 325ifs=$IFS 326IFS=, 327set -- $(getconf LIBPATH) 328IFS=$ifs 329env= 330for v 331do IFS=: 332 set -- $v 333 IFS=$ifs 334 eval [[ \$$2 ]] && env="$env $2=\"\$$2\"" 335done 336set --glob 337if [[ $(foo=bar; eval foo=\$foo $env exec -c \$SHELL -c \'print \$foo\') != bar ]] 338then err_exit '"name=value exec -c ..." not working' 339fi 340$SHELL -c 'OPTIND=-1000000; getopts a opt -a' 2> /dev/null 341[[ $? == 1 ]] || err_exit 'getopts with negative OPTIND not working' 342getopts 'n#num' opt -n 3 343[[ $OPTARG == 3 ]] || err_exit 'getopts with numerical arguments failed' 344if [[ $($SHELL -c $'printf \'%2$s %1$s\n\' world hello') != 'hello world' ]] 345then err_exit 'printf %2$s %1$s not working' 346fi 347val=$(( 'C' )) 348set -- \ 349 "'C" $val 0 \ 350 "'C'" $val 0 \ 351 '"C' $val 0 \ 352 '"C"' $val 0 \ 353 "'CX" $val 1 \ 354 "'CX'" $val 1 \ 355 "'C'X" $val 1 \ 356 '"CX' $val 1 \ 357 '"CX"' $val 1 \ 358 '"C"X' $val 1 359while (( $# >= 3 )) 360do arg=$1 val=$2 code=$3 361 shift 3 362 for fmt in '%d' '%g' 363 do out=$(printf "$fmt" "$arg" 2>/dev/null) 364 err=$(printf "$fmt" "$arg" 2>&1 >/dev/null) 365 printf "$fmt" "$arg" >/dev/null 2>&1 366 ret=$? 367 [[ $out == $val ]] || err_exit "printf $fmt $arg failed -- expected $val, got $out" 368 if (( $code )) 369 then [[ $err ]] || err_exit "printf $fmt $arg failed, error message expected" 370 else [[ $err ]] && err_exit "$err: printf $fmt $arg failed, error message not expected -- got '$err'" 371 fi 372 (( $ret == $code )) || err_exit "printf $fmt $arg failed -- expected exit code $code, got $ret" 373 done 374done 375((n=0)) 376((n++)); ARGC[$n]=1 ARGV[$n]="" 377((n++)); ARGC[$n]=2 ARGV[$n]="-a" 378((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2" 379((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x" 380((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x y" 381for ((i=1; i<=n; i++)) 382do set -- ${ARGV[$i]} 383 OPTIND=0 384 while getopts -a tst "av:" OPT 385 do : 386 done 387 if [[ $OPTIND != ${ARGC[$i]} ]] 388 then err_exit "\$OPTIND after getopts loop incorrect -- expected ${ARGC[$i]}, got $OPTIND" 389 fi 390done 391options=ab:c 392optarg=foo 393set -- -a -b $optarg -c bar 394while getopts $options opt 395do case $opt in 396 a|c) [[ $OPTARG ]] && err_exit "getopts $options \$OPTARG for flag $opt failed, expected \"\", got \"$OPTARG\"" ;; 397 b) [[ $OPTARG == $optarg ]] || err_exit "getopts $options \$OPTARG failed -- \"$optarg\" expected, got \"$OPTARG\"" ;; 398 *) err_exit "getopts $options failed -- got flag $opt" ;; 399 esac 400done 401function longline 402{ 403 integer i 404 for((i=0; i < $1; i++)) 405 do print argument$i 406 done 407} 408# test command -x option 409integer sum=0 n=10000 410if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1 411then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) 2> /dev/null) 412 do ((sum += $i)) 413 done 414 (( sum == n )) || err_exit "command -x processed only $sum arguments" 415 command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1 416 [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x' 417fi 418# test command -x option with extra arguments 419integer sum=0 n=10000 420if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1 421then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) one two three) #2> /dev/null) 422 do ((sum += $i)) 423 done 424 (( sum > n )) || err_exit "command -x processed only $sum arguments" 425 (( (sum-n)%3==0 )) || err_exit "command -x processed only $sum arguments" 426 (( sum == n+3)) && err_exit "command -x processed only $sum arguments" 427 command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1 428 [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x' 429fi 430# test for debug trap 431[[ $(typeset -i i=0 432 trap 'print $i' DEBUG 433 while (( i <2)) 434 do (( i++)) 435 done) == $'0\n0\n1\n1\n2' ]] || err_exit "DEBUG trap not working" 436getconf UNIVERSE - ucb 437[[ $($SHELL -c 'echo -3') == -3 ]] || err_exit "echo -3 not working in ucb universe" 438typeset -F3 start_x=SECONDS total_t delay=0.02 439typeset reps=50 leeway=5 440sleep $(( 2 * leeway * reps * delay )) | 441for (( i=0 ; i < reps ; i++ )) 442do read -N1 -t $delay 443done 444(( total_t = SECONDS - start_x )) 445if (( total_t > leeway * reps * delay )) 446then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too long" 447elif (( total_t < reps * delay )) 448then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too fast" 449fi 450$SHELL -c 'sleep $(printf "%a" .95)' 2> /dev/null || err_exit "sleep doesn't except %a format constants" 451$SHELL -c 'test \( ! -e \)' 2> /dev/null ; [[ $? == 1 ]] || err_exit 'test \( ! -e \) not working' 452[[ $(ulimit) == "$(ulimit -fS)" ]] || err_exit 'ulimit is not the same as ulimit -fS' 453tmpfile=${TMP-/tmp}/ksh$$.2 454trap 'rm -f /tmp/ksh$$ "$tmpfile"' EXIT 455print $'\nprint -r -- "${.sh.file} ${LINENO} ${.sh.lineno}"' > $tmpfile 456[[ $( . "$tmpfile") == "$tmpfile 2 1" ]] || err_exit 'dot command not working' 457print -r -- "'xxx" > $tmpfile 458[[ $($SHELL -c ". $tmpfile"$'\n print ok' 2> /dev/null) == ok ]] || err_exit 'syntax error in dot command affects next command' 459 460float sec=$SECONDS del=4 461exec 3>&2 2>/dev/null 462$SHELL -c "( sleep 1; kill -ALRM \$\$ ) & sleep $del" 2> /dev/null 463exitval=$? 464(( sec = SECONDS - sec )) 465exec 2>&3- 466(( exitval )) && err_exit "sleep doesn't exit 0 with ALRM interupt" 467(( sec > (del - 1) )) || err_exit "ALRM signal causes sleep to terminate prematurely -- expected 3 sec, got $sec" 468 469exit $((Errors)) 470