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