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 28Command=${0##*/} 29integer Errors=0 30# RANDOM 31if (( RANDOM==RANDOM || $RANDOM==$RANDOM )) 32then err_exit RANDOM variable not working 33fi 34# SECONDS 35sleep 3 36if (( SECONDS < 2 )) 37then err_exit SECONDS variable not working 38fi 39# _ 40set abc def 41if [[ $_ != def ]] 42then err_exit _ variable not working 43fi 44# ERRNO 45#set abc def 46#rm -f foobar# 47#ERRNO= 48#2> /dev/null < foobar# 49#if (( ERRNO == 0 )) 50#then err_exit ERRNO variable not working 51#fi 52# PWD 53if [[ ! $PWD -ef . ]] 54then err_exit PWD variable not working 55fi 56# PPID 57if [[ $($SHELL -c 'print $PPID') != $$ ]] 58then err_exit PPID variable not working 59fi 60# OLDPWD 61old=$PWD 62cd / 63if [[ $OLDPWD != $old ]] 64then err_exit OLDPWD variable not working 65fi 66cd $old || err_exit cd failed 67# REPLY 68read <<-! 69 foobar 70 ! 71if [[ $REPLY != foobar ]] 72then err_exit REPLY variable not working 73fi 74integer save=$LINENO 75# LINENO 76LINENO=10 77# 78# These lines intentionally left blank 79# 80if (( LINENO != 13)) 81then err_exit LINENO variable not working 82fi 83LINENO=save+10 84IFS=: 85x=a::b::c 86if [[ $x != a::b::c ]] 87then err_exit "Word splitting on constants" 88fi 89set -- $x 90if [[ $# != 5 ]] 91then err_exit ":: doesn't separate null arguments " 92fi 93set x 94if x$1=0 2> /dev/null 95then err_exit "x\$1=value treated as an assignment" 96fi 97# check for attributes across subshells 98typeset -i x=3 99y=1/0 100if ( typeset x=y) 2> /dev/null 101then print -u2 "attributes not passed to subshells" 102fi 103unset x 104function x.set 105{ 106 nameref foo=${.sh.name}.save 107 foo=${.sh.value} 108 .sh.value=$0 109} 110x=bar 111if [[ $x != x.set ]] 112then err_exit 'x.set does not override assignment' 113fi 114x.get() 115{ 116 nameref foo=${.sh.name}.save 117 .sh.value=$foo 118} 119 120if [[ $x != bar ]] 121then err_exit 'x.get does not work correctly' 122fi 123typeset +n foo 124unset foo 125foo=bar 126( 127 unset foo 128 set +u 129 if [[ $foo != '' ]] 130 then err_exit '$foo not null after unset in subsehll' 131 fi 132) 133if [[ $foo != bar ]] 134then err_exit 'unset foo in subshell produces side effect ' 135fi 136unset foo 137if [[ $( { : ${foo?hi there} ; } 2>&1) != *'hi there' ]] 138then err_exit '${foo?hi there} with foo unset does not print hi there on 2' 139fi 140x=$0 141set foobar 142if [[ ${@:0} != "$x foobar" ]] 143then err_exit '${@:0} not expanding correctly' 144fi 145set -- 146if [[ ${*:0:1} != "$0" ]] 147then err_exit '${@:0} not expanding correctly' 148fi 149ACCESS=0 150function COUNT.set 151{ 152 (( ACCESS++ )) 153} 154COUNT=0 155(( COUNT++ )) 156if (( COUNT != 1 || ACCESS!=2 )) 157then err_exit " set discipline failure COUNT=$COUNT ACCESS=$ACCESS" 158fi 159LANG=C > /dev/null 2>&1 160if [[ $LANG != C ]] 161then err_exit "C locale not working" 162fi 163unset RANDOM 164unset -n foo 165foo=junk 166function foo.get 167{ 168 .sh.value=stuff 169 unset -f foo.get 170} 171if [[ $foo != stuff ]] 172then err_exit "foo.get discipline not working" 173fi 174if [[ $foo != junk ]] 175then err_exit "foo.get discipline not working after unset" 176fi 177# special variables 178set -- 1 2 3 4 5 6 7 8 9 10 179sleep 1000 & 180if [[ $(print -r -- ${#10}) != 2 ]] 181then err_exit '${#10}, where ${10}=10 not working' 182fi 183for i in @ '*' ! '#' - '?' '$' 184do false 185 eval foo='$'$i bar='$'{$i} 186 if [[ ${foo} != "${bar}" ]] 187 then err_exit "\$$i not equal to \${$i}" 188 fi 189 command eval bar='$'{$i%?} 2> /dev/null || err_exit "\${$i%?} gives syntax error" 190 if [[ $i != [@*] && ${foo%?} != "$bar" ]] 191 then err_exit "\${$i%?} not correct" 192 fi 193 command eval bar='$'{$i#?} 2> /dev/null || err_exit "\${$i#?} gives syntax error" 194 if [[ $i != [@*] && ${foo#?} != "$bar" ]] 195 then err_exit "\${$i#?} not correct" 196 fi 197 command eval foo='$'{$i} bar='$'{#$i} || err_exit "\${#$i} gives synta 198x error" 199 if [[ $i != @([@*]) && ${#foo} != "$bar" ]] 200 then err_exit "\${#$i} not correct" 201 fi 202done 203kill $! 204unset x 205CDPATH=/ 206x=$(cd tmp) 207if [[ $x != /tmp ]] 208then err_exit 'CDPATH does not display new directory' 209fi 210mkdir /tmp/ksh$$ 211CDPATH=/: 212x=$(cd /tmp;cd ksh$$) 213if [[ $x ]] 214then err_exit 'CDPATH displays new directory when not used' 215fi 216x=$(cd tmp/ksh$$) 217if [[ $x != /tmp/ksh$$ ]] 218then err_exit "CDPATH tmp/ksh$$ does not display new directory" 219fi 220cd / 221rm -rf /tmp/ksh$$ 222TMOUT=100 223(TMOUT=20) 224if (( TMOUT !=100 )) 225then err_exit 'setting TMOUT in subshell affects parent' 226fi 227unset y 228function setdisc # var 229{ 230 eval function $1.get' 231 { 232 .sh.value=good 233 } 234 ' 235} 236y=bad 237setdisc y 238if [[ $y != good ]] 239then err_exit 'setdisc function not working' 240fi 241integer x=$LINENO 242: $'\ 243' 244if (( LINENO != x+3 )) 245then err_exit '\<newline> gets linenumber count wrong' 246fi 247set -- 248set -- "${@-}" 249if (( $# !=1 )) 250then err_exit '"${@-}" not expanding to null string' 251fi 252for i in : % + / 3b '**' '***' '@@' '{' '[' '}' !! '*a' '@a' '$foo' 253do (eval : \${"$i"} 2> /dev/null) && err_exit "\${$i} not an syntax error" 254done 255unset IFS 256( IFS=' ' ; read -r a b c <<-! 257 x y z 258 ! 259 if [[ $b ]] 260 then err_exit 'IFS=" " not causing adjacent space to be null string' 261 fi 262) 263read -r a b c <<-! 264x y z 265! 266if [[ $b != y ]] 267then err_exit 'IFS not restored after subshell' 268fi 269 270# The next part generates 3428 IFS set/read tests. 271 272unset IFS x 273function split 274{ 275 i=$1 s=$2 r=$3 276 IFS=': ' 277 set -- $i 278 IFS=' ' 279 g="[$#]" 280 while : 281 do case $# in 282 0) break ;; 283 esac 284 g="$g($1)" 285 shift 286 done 287 case "$g" in 288 "$s") ;; 289 *) err_exit "IFS=': '; set -- '$i'; expected '$s' got '$g'" ;; 290 esac 291 print "$i" | IFS=": " read arg rem; g="($arg)($rem)" 292 case "$g" in 293 "$r") ;; 294 *) err_exit "IFS=': '; read '$i'; expected '$r' got '$g'" ;; 295 esac 296} 297for str in \ 298 '-' \ 299 'a' \ 300 '- -' \ 301 '- a' \ 302 'a -' \ 303 'a b' \ 304 '- - -' \ 305 '- - a' \ 306 '- a -' \ 307 '- a b' \ 308 'a - -' \ 309 'a - b' \ 310 'a b -' \ 311 'a b c' 312do 313 IFS=' ' 314 set x $str 315 shift 316 case $# in 317 0) continue ;; 318 esac 319 f1=$1 320 case $f1 in 321 '-') f1='' ;; 322 esac 323 shift 324 case $# in 325 0) for d0 in '' ' ' 326 do 327 for d1 in '' ' ' ':' ' :' ': ' ' : ' 328 do 329 case $f1$d1 in 330 '') split "$d0$f1$d1" "[0]" "()()" ;; 331 ' ') ;; 332 *) split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;; 333 esac 334 done 335 done 336 continue 337 ;; 338 esac 339 f2=$1 340 case $f2 in 341 '-') f2='' ;; 342 esac 343 shift 344 case $# in 345 0) for d0 in '' ' ' 346 do 347 for d1 in ' ' ':' ' :' ': ' ' : ' 348 do 349 case ' ' in 350 $f1$d1|$d1$f2) continue ;; 351 esac 352 for d2 in '' ' ' ':' ' :' ': ' ' : ' 353 do 354 case $f2$d2 in 355 '') split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;; 356 ' ') ;; 357 *) split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;; 358 esac 359 done 360 done 361 done 362 continue 363 ;; 364 esac 365 f3=$1 366 case $f3 in 367 '-') f3='' ;; 368 esac 369 shift 370 case $# in 371 0) for d0 in '' ' ' 372 do 373 for d1 in ':' ' :' ': ' ' : ' 374 do 375 case ' ' in 376 $f1$d1|$d1$f2) continue ;; 377 esac 378 for d2 in ' ' ':' ' :' ': ' ' : ' 379 do 380 case $f2$d2 in 381 ' ') continue ;; 382 esac 383 case ' ' in 384 $f2$d2|$d2$f3) continue ;; 385 esac 386 for d3 in '' ' ' ':' ' :' ': ' ' : ' 387 do 388 case $f3$d3 in 389 '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; 390 ' ') ;; 391 *) x=$f2$d2$f3$d3 392 x=${x#' '} 393 x=${x%' '} 394 split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" 395 ;; 396 esac 397 done 398 done 399 done 400 done 401 continue 402 ;; 403 esac 404done 405unset IFS 406 407if [[ $( (print ${12345:?}) 2>&1) != *12345* ]] 408then err_exit 'Incorrect error message with ${12345?}' 409fi 410unset foobar 411if [[ $( (print ${foobar:?}) 2>&1) != *foobar* ]] 412then err_exit 'Incorrect error message with ${foobar?}' 413fi 414unset bar 415if [[ $( (print ${bar:?bam}) 2>&1) != *bar*bam* ]] 416then err_exit 'Incorrect error message with ${foobar?}' 417fi 418{ $SHELL -c ' 419function foo 420{ 421 typeset SECONDS=0 422 sleep 1.5 423 print $SECONDS 424 425} 426x=$(foo) 427(( x >1 && x < 2 )) 428' 429} 2> /dev/null || err_exit 'SECONDS not working in function' 430trap 'rm -f /tmp/script$$ /tmp/out$$' EXIT 431cat > /tmp/script$$ <<-\! 432 posixfun() 433 { 434 unset x 435 nameref x=$1 436 print -r -- "$x" 437 } 438 function fun 439 { 440 nameref x=$1 441 print -r -- "$x" 442 } 443 if [[ $1 ]] 444 then file=${.sh.file} 445 else print -r -- "${.sh.file}" 446 fi 447! 448chmod +x /tmp/script$$ 449. /tmp/script$$ 1 450[[ $file == /tmp/script$$ ]] || err_exit ".sh.file not working for dot scripts" 451[[ $($SHELL /tmp/script$$) == /tmp/script$$ ]] || err_exit ".sh.file not working for scripts" 452[[ $(posixfun .sh.file) == /tmp/script$$ ]] || err_exit ".sh.file not working for posix functions" 453[[ $(fun .sh.file) == /tmp/script$$ ]] || err_exit ".sh.file not working for functions" 454[[ $(posixfun .sh.fun) == posixfun ]] || err_exit ".sh.fun not working for posix functions" 455[[ $(fun .sh.fun) == fun ]] || err_exit ".sh.fun not working for functions" 456[[ $(posixfun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for posix functions" 457[[ $(fun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for functions" 458( 459 [[ $(posixfun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for posix functions in subshells" 460 [[ $(fun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for functions in subshells" 461 (( .sh.subshell == 1 )) || err_exit ".sh.subshell not working in a subshell" 462) 463TIMEFORMAT='this is a test' 464[[ $({ { time :;} 2>&1;}) == "$TIMEFORMAT" ]] || err_exit 'TIMEFORMAT not working' 465: ${.sh.version} 466[[ $(alias integer) == *.sh.* ]] && err_exit '.sh. prefixed to alias name' 467: ${.sh.version} 468[[ $(whence rm) == *.sh.* ]] && err_exit '.sh. prefixed to tracked alias name' 469: ${.sh.version} 470[[ $(cd /bin;env | grep PWD) == *.sh.* ]] && err_exit '.sh. prefixed to PWD' 471# unset discipline bug fix 472dave=dave 473function dave.unset 474{ 475 unset dave 476} 477unset dave 478[[ $(typeset +f) == *dave.* ]] && err_exit 'unset discipline not removed' 479print 'print ${VAR}' > /tmp/script$$ 480VAR=foo /tmp/script$$ > /tmp/out$$ 481[[ $(</tmp/out$$) == foo ]] || err_exit 'environment variables not passed to scripts' 482( 483 unset dave 484 function dave.append 485 { 486 .sh.value+=$dave 487 dave= 488 } 489 dave=foo; dave+=bar 490 [[ $dave == barfoo ]] || exit 2 491) 2> /dev/null 492case $? in 4930) ;; 4941) err_exit 'append discipline not implemented';; 495*) err_exit 'append discipline not working';; 496esac 497.sh.foobar=hello 498{ 499 function .sh.foobar.get 500 { 501 .sh.value=world 502 } 503} 2> /dev/null || err_exit "Can't add get discipline to .sh.foobar" 504[[ ${.sh.foobar} == world ]] || err_exit 'get discipline for .sh.foobar not working' 505x='a|b' 506IFS='|' 507set -- $x 508[[ $2 == b ]] || err_exit '$2 should be b after set' 509exec 3>&2 2> /dev/null 510set -x 511( IFS= ) 2> /dev/null 512set +x 513exec 2>&3- 514set -- $x 515[[ $2 == b ]] || err_exit '$2 should be b after subshell' 516: & pid=$! 517( : & ) 518[[ $pid == $! ]] || err_exit '$! value not preserved across subshells' 519unset foo 520typeset -A foo 521function foo.set 522{ 523 case ${.sh.subscript} in 524 bar) if ((.sh.value > 1 )) 525 then .sh.value=5 526 foo[barrier_hit]=yes 527 fi 528 ;; 529 barrier_hit) 530 if [[ ${.sh.value} = yes ]] 531 then foo[barrier_not_hit]=no 532 else foo[barrier_not_hit]=yes 533 fi 534 ;; 535 esac 536} 537foo[barrier_hit]=no 538foo[bar]=1 539(( foo[bar] == 1 )) || err_exit 'foo[bar] should be 1' 540[[ ${foo[barrier_hit]} == no ]] || err_exit 'foo[barrier_hit] should be no' 541[[ ${foo[barrier_not_hit]} == yes ]] || err_exit 'foo[barrier_not_hit] should be yes' 542foo[barrier_hit]=no 543foo[bar]=2 544(( foo[bar] == 5 )) || err_exit 'foo[bar] should be 5' 545[[ ${foo[barrier_hit]} == yes ]] || err_exit 'foo[barrier_hit] should be yes' 546[[ ${foo[barrier_not_hit]} == no ]] || err_exit 'foo[barrier_not_hit] should be no' 547unset x 548typeset -i x 549function x.set 550{ 551 typeset sub=${.sh.subscript} 552 (( sub > 0 )) && (( x[sub-1]= x[sub-1] + .sh.value )) 553} 554x[0]=0 x[1]=1 x[2]=2 x[3]=3 555[[ ${x[@]} == '12 8 5 3' ]] || err_exit 'set discipline for indexed array not working correctly' 556((SECONDS=3*4)) 557(( SECONDS < 12 || SECONDS > 12.1 )) && err_exit "SECONDS is $SECONDS and should be close to 12" 558exit $((Errors)) 559