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 307c2fbfb3SApril Chin 3134f9b3eeSRoland Mainztmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; } 3234f9b3eeSRoland Mainztrap "cd /; rm -rf $tmp" EXIT 3334f9b3eeSRoland Mainz 347c2fbfb3SApril Chin[[ ${.sh.version} == "$KSH_VERSION" ]] || err_exit '.sh.version != KSH_VERSION' 357c2fbfb3SApril Chinunset ss 3634f9b3eeSRoland Mainz[[ ${@ss} ]] && err_exit '${@ss} should be empty string when ss is unset' 3734f9b3eeSRoland Mainz[[ ${!ss} == ss ]] || err_exit '${!ss} should be ss when ss is unset' 3834f9b3eeSRoland Mainz[[ ${#ss} == 0 ]] || err_exit '${#ss} should be 0 when ss is unset' 39da2e3ebdSchin# RANDOM 40da2e3ebdSchinif (( RANDOM==RANDOM || $RANDOM==$RANDOM )) 41da2e3ebdSchinthen err_exit RANDOM variable not working 42da2e3ebdSchinfi 43da2e3ebdSchin# SECONDS 44da2e3ebdSchinsleep 3 45da2e3ebdSchinif (( SECONDS < 2 )) 46da2e3ebdSchinthen err_exit SECONDS variable not working 47da2e3ebdSchinfi 48da2e3ebdSchin# _ 49da2e3ebdSchinset abc def 50da2e3ebdSchinif [[ $_ != def ]] 51da2e3ebdSchinthen err_exit _ variable not working 52da2e3ebdSchinfi 53da2e3ebdSchin# ERRNO 54da2e3ebdSchin#set abc def 55da2e3ebdSchin#rm -f foobar# 56da2e3ebdSchin#ERRNO= 57da2e3ebdSchin#2> /dev/null < foobar# 58da2e3ebdSchin#if (( ERRNO == 0 )) 59da2e3ebdSchin#then err_exit ERRNO variable not working 60da2e3ebdSchin#fi 61da2e3ebdSchin# PWD 62da2e3ebdSchinif [[ ! $PWD -ef . ]] 6334f9b3eeSRoland Mainzthen err_exit PWD variable failed, not equivalent to . 64da2e3ebdSchinfi 65da2e3ebdSchin# PPID 6634f9b3eeSRoland Mainzexp=$$ 6734f9b3eeSRoland Mainzgot=${ $SHELL -c 'print $PPID'; } 6834f9b3eeSRoland Mainzif [[ ${ $SHELL -c 'print $PPID'; } != $$ ]] 6934f9b3eeSRoland Mainzthen err_exit "PPID variable failed -- expected '$exp', got '$got'" 70da2e3ebdSchinfi 71da2e3ebdSchin# OLDPWD 72da2e3ebdSchinold=$PWD 73da2e3ebdSchincd / 74da2e3ebdSchinif [[ $OLDPWD != $old ]] 7534f9b3eeSRoland Mainzthen err_exit "OLDPWD variable failed -- expected '$old', got '$OLDPWD'" 76da2e3ebdSchinfi 77da2e3ebdSchincd $old || err_exit cd failed 78da2e3ebdSchin# REPLY 79da2e3ebdSchinread <<-! 80da2e3ebdSchin foobar 81da2e3ebdSchin ! 82da2e3ebdSchinif [[ $REPLY != foobar ]] 83da2e3ebdSchinthen err_exit REPLY variable not working 84da2e3ebdSchinfi 85da2e3ebdSchininteger save=$LINENO 86da2e3ebdSchin# LINENO 87da2e3ebdSchinLINENO=10 88da2e3ebdSchin# 89da2e3ebdSchin# These lines intentionally left blank 90da2e3ebdSchin# 91da2e3ebdSchinif (( LINENO != 13)) 92da2e3ebdSchinthen err_exit LINENO variable not working 93da2e3ebdSchinfi 94da2e3ebdSchinLINENO=save+10 95da2e3ebdSchinIFS=: 96da2e3ebdSchinx=a::b::c 97da2e3ebdSchinif [[ $x != a::b::c ]] 9834f9b3eeSRoland Mainzthen err_exit "word splitting on constants" 99da2e3ebdSchinfi 100da2e3ebdSchinset -- $x 101da2e3ebdSchinif [[ $# != 5 ]] 102da2e3ebdSchinthen err_exit ":: doesn't separate null arguments " 103da2e3ebdSchinfi 104da2e3ebdSchinset x 105da2e3ebdSchinif x$1=0 2> /dev/null 106da2e3ebdSchinthen err_exit "x\$1=value treated as an assignment" 107da2e3ebdSchinfi 108da2e3ebdSchin# check for attributes across subshells 109da2e3ebdSchintypeset -i x=3 110da2e3ebdSchiny=1/0 111b30d1939SAndy Fiddamanif ( x=y ) 2> /dev/null 1127c2fbfb3SApril Chinthen err_exit "attributes not passed to subshells" 113da2e3ebdSchinfi 114da2e3ebdSchinunset x 115da2e3ebdSchinfunction x.set 116da2e3ebdSchin{ 117da2e3ebdSchin nameref foo=${.sh.name}.save 118da2e3ebdSchin foo=${.sh.value} 119da2e3ebdSchin .sh.value=$0 120da2e3ebdSchin} 121da2e3ebdSchinx=bar 122da2e3ebdSchinif [[ $x != x.set ]] 123da2e3ebdSchinthen err_exit 'x.set does not override assignment' 124da2e3ebdSchinfi 125da2e3ebdSchinx.get() 126da2e3ebdSchin{ 127da2e3ebdSchin nameref foo=${.sh.name}.save 128da2e3ebdSchin .sh.value=$foo 129da2e3ebdSchin} 130da2e3ebdSchin 131da2e3ebdSchinif [[ $x != bar ]] 132da2e3ebdSchinthen err_exit 'x.get does not work correctly' 133da2e3ebdSchinfi 134da2e3ebdSchintypeset +n foo 135da2e3ebdSchinunset foo 136da2e3ebdSchinfoo=bar 137da2e3ebdSchin( 138da2e3ebdSchin unset foo 139da2e3ebdSchin set +u 140da2e3ebdSchin if [[ $foo != '' ]] 141da2e3ebdSchin then err_exit '$foo not null after unset in subsehll' 142da2e3ebdSchin fi 143da2e3ebdSchin) 144da2e3ebdSchinif [[ $foo != bar ]] 145da2e3ebdSchinthen err_exit 'unset foo in subshell produces side effect ' 146da2e3ebdSchinfi 147da2e3ebdSchinunset foo 148da2e3ebdSchinif [[ $( { : ${foo?hi there} ; } 2>&1) != *'hi there' ]] 149da2e3ebdSchinthen err_exit '${foo?hi there} with foo unset does not print hi there on 2' 150da2e3ebdSchinfi 151da2e3ebdSchinx=$0 152da2e3ebdSchinset foobar 153da2e3ebdSchinif [[ ${@:0} != "$x foobar" ]] 154da2e3ebdSchinthen err_exit '${@:0} not expanding correctly' 155da2e3ebdSchinfi 156da2e3ebdSchinset -- 157da2e3ebdSchinif [[ ${*:0:1} != "$0" ]] 158da2e3ebdSchinthen err_exit '${@:0} not expanding correctly' 159da2e3ebdSchinfi 160da2e3ebdSchinACCESS=0 161da2e3ebdSchinfunction COUNT.set 162da2e3ebdSchin{ 163da2e3ebdSchin (( ACCESS++ )) 164da2e3ebdSchin} 165da2e3ebdSchinCOUNT=0 166da2e3ebdSchin(( COUNT++ )) 167da2e3ebdSchinif (( COUNT != 1 || ACCESS!=2 )) 168da2e3ebdSchinthen err_exit " set discipline failure COUNT=$COUNT ACCESS=$ACCESS" 169da2e3ebdSchinfi 170da2e3ebdSchinLANG=C > /dev/null 2>&1 171da2e3ebdSchinif [[ $LANG != C ]] 172da2e3ebdSchinthen err_exit "C locale not working" 173da2e3ebdSchinfi 174da2e3ebdSchinunset RANDOM 175da2e3ebdSchinunset -n foo 176da2e3ebdSchinfoo=junk 177da2e3ebdSchinfunction foo.get 178da2e3ebdSchin{ 17934f9b3eeSRoland Mainz .sh.value=stuff 180da2e3ebdSchin unset -f foo.get 181da2e3ebdSchin} 182da2e3ebdSchinif [[ $foo != stuff ]] 183da2e3ebdSchinthen err_exit "foo.get discipline not working" 184da2e3ebdSchinfi 185da2e3ebdSchinif [[ $foo != junk ]] 186da2e3ebdSchinthen err_exit "foo.get discipline not working after unset" 187da2e3ebdSchinfi 188da2e3ebdSchin# special variables 189da2e3ebdSchinset -- 1 2 3 4 5 6 7 8 9 10 190da2e3ebdSchinsleep 1000 & 191da2e3ebdSchinif [[ $(print -r -- ${#10}) != 2 ]] 192da2e3ebdSchinthen err_exit '${#10}, where ${10}=10 not working' 193da2e3ebdSchinfi 194da2e3ebdSchinfor i in @ '*' ! '#' - '?' '$' 195da2e3ebdSchindo false 196da2e3ebdSchin eval foo='$'$i bar='$'{$i} 197da2e3ebdSchin if [[ ${foo} != "${bar}" ]] 198da2e3ebdSchin then err_exit "\$$i not equal to \${$i}" 199da2e3ebdSchin fi 200da2e3ebdSchin command eval bar='$'{$i%?} 2> /dev/null || err_exit "\${$i%?} gives syntax error" 201da2e3ebdSchin if [[ $i != [@*] && ${foo%?} != "$bar" ]] 202da2e3ebdSchin then err_exit "\${$i%?} not correct" 203da2e3ebdSchin fi 204da2e3ebdSchin command eval bar='$'{$i#?} 2> /dev/null || err_exit "\${$i#?} gives syntax error" 205da2e3ebdSchin if [[ $i != [@*] && ${foo#?} != "$bar" ]] 206da2e3ebdSchin then err_exit "\${$i#?} not correct" 207da2e3ebdSchin fi 208da2e3ebdSchin command eval foo='$'{$i} bar='$'{#$i} || err_exit "\${#$i} gives synta 209da2e3ebdSchinx error" 210da2e3ebdSchin if [[ $i != @([@*]) && ${#foo} != "$bar" ]] 211da2e3ebdSchin then err_exit "\${#$i} not correct" 212da2e3ebdSchin fi 213da2e3ebdSchindone 214da2e3ebdSchinkill $! 215da2e3ebdSchinunset x 216da2e3ebdSchinCDPATH=/ 21734f9b3eeSRoland Mainzx=$(cd ${tmp#/}) 21834f9b3eeSRoland Mainzif [[ $x != $tmp ]] 219da2e3ebdSchinthen err_exit 'CDPATH does not display new directory' 220da2e3ebdSchinfi 221da2e3ebdSchinCDPATH=/: 22234f9b3eeSRoland Mainzx=$(cd ${tmp%/*}; cd ${tmp##*/}) 223da2e3ebdSchinif [[ $x ]] 224da2e3ebdSchinthen err_exit 'CDPATH displays new directory when not used' 225da2e3ebdSchinfi 22634f9b3eeSRoland Mainzx=$(cd ${tmp#/}) 22734f9b3eeSRoland Mainzif [[ $x != $tmp ]] 22834f9b3eeSRoland Mainzthen err_exit "CDPATH ${tmp#/} does not display new directory" 229da2e3ebdSchinfi 230da2e3ebdSchinTMOUT=100 231da2e3ebdSchin(TMOUT=20) 232da2e3ebdSchinif (( TMOUT !=100 )) 233da2e3ebdSchinthen err_exit 'setting TMOUT in subshell affects parent' 234da2e3ebdSchinfi 235da2e3ebdSchinunset y 236da2e3ebdSchinfunction setdisc # var 237da2e3ebdSchin{ 238da2e3ebdSchin eval function $1.get' 239da2e3ebdSchin { 240da2e3ebdSchin .sh.value=good 241da2e3ebdSchin } 242da2e3ebdSchin ' 243da2e3ebdSchin} 244da2e3ebdSchiny=bad 245da2e3ebdSchinsetdisc y 246da2e3ebdSchinif [[ $y != good ]] 247da2e3ebdSchinthen err_exit 'setdisc function not working' 248da2e3ebdSchinfi 249da2e3ebdSchininteger x=$LINENO 250da2e3ebdSchin: $'\ 251da2e3ebdSchin' 252da2e3ebdSchinif (( LINENO != x+3 )) 253da2e3ebdSchinthen err_exit '\<newline> gets linenumber count wrong' 254da2e3ebdSchinfi 255da2e3ebdSchinset -- 256da2e3ebdSchinset -- "${@-}" 257da2e3ebdSchinif (( $# !=1 )) 258da2e3ebdSchinthen err_exit '"${@-}" not expanding to null string' 259da2e3ebdSchinfi 2607c2fbfb3SApril Chinfor i in : % + / 3b '**' '***' '@@' '{' '[' '}' !! '*a' '$foo' 261da2e3ebdSchindo (eval : \${"$i"} 2> /dev/null) && err_exit "\${$i} not an syntax error" 262da2e3ebdSchindone 263da2e3ebdSchinunset IFS 264da2e3ebdSchin( IFS=' ' ; read -r a b c <<-! 265da2e3ebdSchin x y z 266da2e3ebdSchin ! 267da2e3ebdSchin if [[ $b ]] 268da2e3ebdSchin then err_exit 'IFS=" " not causing adjacent space to be null string' 269da2e3ebdSchin fi 270da2e3ebdSchin) 271da2e3ebdSchinread -r a b c <<-! 272da2e3ebdSchinx y z 273da2e3ebdSchin! 274da2e3ebdSchinif [[ $b != y ]] 275da2e3ebdSchinthen err_exit 'IFS not restored after subshell' 276da2e3ebdSchinfi 277da2e3ebdSchin 278da2e3ebdSchin# The next part generates 3428 IFS set/read tests. 279da2e3ebdSchin 280da2e3ebdSchinunset IFS x 281da2e3ebdSchinfunction split 282da2e3ebdSchin{ 283da2e3ebdSchin i=$1 s=$2 r=$3 284da2e3ebdSchin IFS=': ' 285da2e3ebdSchin set -- $i 286da2e3ebdSchin IFS=' ' 287da2e3ebdSchin g="[$#]" 288da2e3ebdSchin while : 289da2e3ebdSchin do case $# in 290da2e3ebdSchin 0) break ;; 291da2e3ebdSchin esac 292da2e3ebdSchin g="$g($1)" 293da2e3ebdSchin shift 294da2e3ebdSchin done 295da2e3ebdSchin case "$g" in 296da2e3ebdSchin "$s") ;; 297da2e3ebdSchin *) err_exit "IFS=': '; set -- '$i'; expected '$s' got '$g'" ;; 298da2e3ebdSchin esac 299da2e3ebdSchin print "$i" | IFS=": " read arg rem; g="($arg)($rem)" 300da2e3ebdSchin case "$g" in 301da2e3ebdSchin "$r") ;; 302da2e3ebdSchin *) err_exit "IFS=': '; read '$i'; expected '$r' got '$g'" ;; 303da2e3ebdSchin esac 304da2e3ebdSchin} 305da2e3ebdSchinfor str in \ 306da2e3ebdSchin '-' \ 307da2e3ebdSchin 'a' \ 308da2e3ebdSchin '- -' \ 309da2e3ebdSchin '- a' \ 310da2e3ebdSchin 'a -' \ 311da2e3ebdSchin 'a b' \ 312da2e3ebdSchin '- - -' \ 313da2e3ebdSchin '- - a' \ 314da2e3ebdSchin '- a -' \ 315da2e3ebdSchin '- a b' \ 316da2e3ebdSchin 'a - -' \ 317da2e3ebdSchin 'a - b' \ 318da2e3ebdSchin 'a b -' \ 319da2e3ebdSchin 'a b c' 320da2e3ebdSchindo 321da2e3ebdSchin IFS=' ' 322da2e3ebdSchin set x $str 323da2e3ebdSchin shift 324da2e3ebdSchin case $# in 325da2e3ebdSchin 0) continue ;; 326da2e3ebdSchin esac 327da2e3ebdSchin f1=$1 328da2e3ebdSchin case $f1 in 329da2e3ebdSchin '-') f1='' ;; 330da2e3ebdSchin esac 331da2e3ebdSchin shift 332da2e3ebdSchin case $# in 333da2e3ebdSchin 0) for d0 in '' ' ' 334da2e3ebdSchin do 335da2e3ebdSchin for d1 in '' ' ' ':' ' :' ': ' ' : ' 336da2e3ebdSchin do 337da2e3ebdSchin case $f1$d1 in 338da2e3ebdSchin '') split "$d0$f1$d1" "[0]" "()()" ;; 339da2e3ebdSchin ' ') ;; 340da2e3ebdSchin *) split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;; 341da2e3ebdSchin esac 342da2e3ebdSchin done 343da2e3ebdSchin done 344da2e3ebdSchin continue 345da2e3ebdSchin ;; 346da2e3ebdSchin esac 347da2e3ebdSchin f2=$1 348da2e3ebdSchin case $f2 in 349da2e3ebdSchin '-') f2='' ;; 350da2e3ebdSchin esac 351da2e3ebdSchin shift 352da2e3ebdSchin case $# in 353da2e3ebdSchin 0) for d0 in '' ' ' 354da2e3ebdSchin do 355da2e3ebdSchin for d1 in ' ' ':' ' :' ': ' ' : ' 356da2e3ebdSchin do 357da2e3ebdSchin case ' ' in 358da2e3ebdSchin $f1$d1|$d1$f2) continue ;; 359da2e3ebdSchin esac 360da2e3ebdSchin for d2 in '' ' ' ':' ' :' ': ' ' : ' 361da2e3ebdSchin do 362da2e3ebdSchin case $f2$d2 in 363da2e3ebdSchin '') split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;; 364da2e3ebdSchin ' ') ;; 365da2e3ebdSchin *) split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;; 366da2e3ebdSchin esac 367da2e3ebdSchin done 368da2e3ebdSchin done 369da2e3ebdSchin done 370da2e3ebdSchin continue 371da2e3ebdSchin ;; 372da2e3ebdSchin esac 373da2e3ebdSchin f3=$1 374da2e3ebdSchin case $f3 in 375da2e3ebdSchin '-') f3='' ;; 376da2e3ebdSchin esac 377da2e3ebdSchin shift 378da2e3ebdSchin case $# in 379da2e3ebdSchin 0) for d0 in '' ' ' 380da2e3ebdSchin do 381da2e3ebdSchin for d1 in ':' ' :' ': ' ' : ' 382da2e3ebdSchin do 383da2e3ebdSchin case ' ' in 384da2e3ebdSchin $f1$d1|$d1$f2) continue ;; 385da2e3ebdSchin esac 386da2e3ebdSchin for d2 in ' ' ':' ' :' ': ' ' : ' 387da2e3ebdSchin do 388da2e3ebdSchin case $f2$d2 in 389da2e3ebdSchin ' ') continue ;; 390da2e3ebdSchin esac 391da2e3ebdSchin case ' ' in 392da2e3ebdSchin $f2$d2|$d2$f3) continue ;; 393da2e3ebdSchin esac 394da2e3ebdSchin for d3 in '' ' ' ':' ' :' ': ' ' : ' 395da2e3ebdSchin do 396da2e3ebdSchin case $f3$d3 in 397da2e3ebdSchin '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; 398da2e3ebdSchin ' ') ;; 399da2e3ebdSchin *) x=$f2$d2$f3$d3 400da2e3ebdSchin x=${x#' '} 401da2e3ebdSchin x=${x%' '} 402da2e3ebdSchin split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" 403da2e3ebdSchin ;; 404da2e3ebdSchin esac 405da2e3ebdSchin done 406da2e3ebdSchin done 407da2e3ebdSchin done 408da2e3ebdSchin done 409da2e3ebdSchin continue 410da2e3ebdSchin ;; 411da2e3ebdSchin esac 412da2e3ebdSchindone 413da2e3ebdSchinunset IFS 414da2e3ebdSchin 415da2e3ebdSchinif [[ $( (print ${12345:?}) 2>&1) != *12345* ]] 41634f9b3eeSRoland Mainzthen err_exit 'incorrect error message with ${12345?}' 417da2e3ebdSchinfi 418da2e3ebdSchinunset foobar 419da2e3ebdSchinif [[ $( (print ${foobar:?}) 2>&1) != *foobar* ]] 42034f9b3eeSRoland Mainzthen err_exit 'incorrect error message with ${foobar?}' 421da2e3ebdSchinfi 422da2e3ebdSchinunset bar 423da2e3ebdSchinif [[ $( (print ${bar:?bam}) 2>&1) != *bar*bam* ]] 42434f9b3eeSRoland Mainzthen err_exit 'incorrect error message with ${foobar?}' 425da2e3ebdSchinfi 426da2e3ebdSchin{ $SHELL -c ' 427da2e3ebdSchinfunction foo 428da2e3ebdSchin{ 429da2e3ebdSchin typeset SECONDS=0 430da2e3ebdSchin sleep 1.5 431da2e3ebdSchin print $SECONDS 43234f9b3eeSRoland Mainz 433da2e3ebdSchin} 434da2e3ebdSchinx=$(foo) 43534f9b3eeSRoland Mainz(( x >1 && x < 2 )) 436da2e3ebdSchin' 437da2e3ebdSchin} 2> /dev/null || err_exit 'SECONDS not working in function' 43834f9b3eeSRoland Mainzcat > $tmp/script <<-\! 439da2e3ebdSchin posixfun() 440da2e3ebdSchin { 441da2e3ebdSchin unset x 442da2e3ebdSchin nameref x=$1 443da2e3ebdSchin print -r -- "$x" 444da2e3ebdSchin } 445da2e3ebdSchin function fun 446da2e3ebdSchin { 447da2e3ebdSchin nameref x=$1 448da2e3ebdSchin print -r -- "$x" 449da2e3ebdSchin } 450da2e3ebdSchin if [[ $1 ]] 451da2e3ebdSchin then file=${.sh.file} 452da2e3ebdSchin else print -r -- "${.sh.file}" 453da2e3ebdSchin fi 454da2e3ebdSchin! 45534f9b3eeSRoland Mainzchmod +x $tmp/script 45634f9b3eeSRoland Mainz. $tmp/script 1 45734f9b3eeSRoland Mainz[[ $file == $tmp/script ]] || err_exit ".sh.file not working for dot scripts" 45834f9b3eeSRoland Mainz[[ $($SHELL $tmp/script) == $tmp/script ]] || err_exit ".sh.file not working for scripts" 45934f9b3eeSRoland Mainz[[ $(posixfun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for posix functions" 46034f9b3eeSRoland Mainz[[ $(fun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for functions" 461da2e3ebdSchin[[ $(posixfun .sh.fun) == posixfun ]] || err_exit ".sh.fun not working for posix functions" 462da2e3ebdSchin[[ $(fun .sh.fun) == fun ]] || err_exit ".sh.fun not working for functions" 463da2e3ebdSchin[[ $(posixfun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for posix functions" 464da2e3ebdSchin[[ $(fun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for functions" 465da2e3ebdSchin( 466da2e3ebdSchin [[ $(posixfun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for posix functions in subshells" 467da2e3ebdSchin [[ $(fun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for functions in subshells" 468da2e3ebdSchin (( .sh.subshell == 1 )) || err_exit ".sh.subshell not working in a subshell" 469da2e3ebdSchin) 470da2e3ebdSchinTIMEFORMAT='this is a test' 471da2e3ebdSchin[[ $({ { time :;} 2>&1;}) == "$TIMEFORMAT" ]] || err_exit 'TIMEFORMAT not working' 472da2e3ebdSchin: ${.sh.version} 473da2e3ebdSchin[[ $(alias integer) == *.sh.* ]] && err_exit '.sh. prefixed to alias name' 474da2e3ebdSchin: ${.sh.version} 475da2e3ebdSchin[[ $(whence rm) == *.sh.* ]] && err_exit '.sh. prefixed to tracked alias name' 476da2e3ebdSchin: ${.sh.version} 4777c2fbfb3SApril Chin[[ $(cd /bin;env | grep PWD=) == *.sh.* ]] && err_exit '.sh. prefixed to PWD' 478da2e3ebdSchin# unset discipline bug fix 479da2e3ebdSchindave=dave 480da2e3ebdSchinfunction dave.unset 481da2e3ebdSchin{ 482da2e3ebdSchin unset dave 483da2e3ebdSchin} 484da2e3ebdSchinunset dave 485da2e3ebdSchin[[ $(typeset +f) == *dave.* ]] && err_exit 'unset discipline not removed' 4867c2fbfb3SApril Chin 487b30d1939SAndy Fiddamanx=$( 488b30d1939SAndy Fiddaman dave=dave 489b30d1939SAndy Fiddaman function dave.unset 490b30d1939SAndy Fiddaman { 491b30d1939SAndy Fiddaman print dave.unset 492b30d1939SAndy Fiddaman } 493b30d1939SAndy Fiddaman) 494b30d1939SAndy Fiddaman[[ $x == dave.unset ]] || err_exit 'unset discipline not called with subset completion' 495b30d1939SAndy Fiddaman 49634f9b3eeSRoland Mainzprint 'print ${VAR}' > $tmp/script 4977c2fbfb3SApril Chinunset VAR 49834f9b3eeSRoland MainzVAR=new $tmp/script > $tmp/out 49934f9b3eeSRoland Mainzgot=$(<$tmp/out) 5007c2fbfb3SApril Chin[[ $got == new ]] || err_exit "previously unset environment variable not passed to script, expected 'new', got '$got'" 5017c2fbfb3SApril Chin[[ ! $VAR ]] || err_exit "previously unset environment variable set after script, expected '', got '$VAR'" 5027c2fbfb3SApril Chinunset VAR 5037c2fbfb3SApril ChinVAR=old 50434f9b3eeSRoland MainzVAR=new $tmp/script > $tmp/out 50534f9b3eeSRoland Mainzgot=$(<$tmp/out) 5067c2fbfb3SApril Chin[[ $got == new ]] || err_exit "environment variable covering local variable not passed to script, expected 'new', got '$got'" 5077c2fbfb3SApril Chin[[ $VAR == old ]] || err_exit "previously set local variable changed after script, expected 'old', got '$VAR'" 5087c2fbfb3SApril Chinunset VAR 5097c2fbfb3SApril Chinexport VAR=old 51034f9b3eeSRoland MainzVAR=new $tmp/script > $tmp/out 51134f9b3eeSRoland Mainzgot=$(<$tmp/out) 5127c2fbfb3SApril Chin[[ $got == new ]] || err_exit "environment variable covering environment variable not passed to script, expected 'new', got '$got'" 5137c2fbfb3SApril Chin[[ $VAR == old ]] || err_exit "previously set environment variable changed after script, expected 'old', got '$VAR'" 5147c2fbfb3SApril Chin 515da2e3ebdSchin( 516da2e3ebdSchin unset dave 517da2e3ebdSchin function dave.append 518da2e3ebdSchin { 519da2e3ebdSchin .sh.value+=$dave 520da2e3ebdSchin dave= 521da2e3ebdSchin } 522da2e3ebdSchin dave=foo; dave+=bar 523da2e3ebdSchin [[ $dave == barfoo ]] || exit 2 52434f9b3eeSRoland Mainz) 2> /dev/null 525da2e3ebdSchincase $? in 526da2e3ebdSchin0) ;; 527da2e3ebdSchin1) err_exit 'append discipline not implemented';; 528da2e3ebdSchin*) err_exit 'append discipline not working';; 529da2e3ebdSchinesac 530da2e3ebdSchin.sh.foobar=hello 531da2e3ebdSchin{ 532da2e3ebdSchin function .sh.foobar.get 533da2e3ebdSchin { 534da2e3ebdSchin .sh.value=world 53534f9b3eeSRoland Mainz } 53634f9b3eeSRoland Mainz} 2> /dev/null || err_exit "cannot add get discipline to .sh.foobar" 537da2e3ebdSchin[[ ${.sh.foobar} == world ]] || err_exit 'get discipline for .sh.foobar not working' 538da2e3ebdSchinx='a|b' 539da2e3ebdSchinIFS='|' 540da2e3ebdSchinset -- $x 541da2e3ebdSchin[[ $2 == b ]] || err_exit '$2 should be b after set' 542da2e3ebdSchinexec 3>&2 2> /dev/null 543da2e3ebdSchinset -x 544da2e3ebdSchin( IFS= ) 2> /dev/null 545da2e3ebdSchinset +x 546da2e3ebdSchinexec 2>&3- 547da2e3ebdSchinset -- $x 548da2e3ebdSchin[[ $2 == b ]] || err_exit '$2 should be b after subshell' 549da2e3ebdSchin: & pid=$! 550da2e3ebdSchin( : & ) 551da2e3ebdSchin[[ $pid == $! ]] || err_exit '$! value not preserved across subshells' 552da2e3ebdSchinunset foo 553da2e3ebdSchintypeset -A foo 554da2e3ebdSchinfunction foo.set 555da2e3ebdSchin{ 556da2e3ebdSchin case ${.sh.subscript} in 557da2e3ebdSchin bar) if ((.sh.value > 1 )) 558da2e3ebdSchin then .sh.value=5 559da2e3ebdSchin foo[barrier_hit]=yes 560da2e3ebdSchin fi 561da2e3ebdSchin ;; 562da2e3ebdSchin barrier_hit) 563b30d1939SAndy Fiddaman if [[ ${.sh.value} == yes ]] 564da2e3ebdSchin then foo[barrier_not_hit]=no 565da2e3ebdSchin else foo[barrier_not_hit]=yes 566da2e3ebdSchin fi 567da2e3ebdSchin ;; 568da2e3ebdSchin esac 569da2e3ebdSchin} 57034f9b3eeSRoland Mainzfoo[barrier_hit]=no 571da2e3ebdSchinfoo[bar]=1 572da2e3ebdSchin(( foo[bar] == 1 )) || err_exit 'foo[bar] should be 1' 573da2e3ebdSchin[[ ${foo[barrier_hit]} == no ]] || err_exit 'foo[barrier_hit] should be no' 574da2e3ebdSchin[[ ${foo[barrier_not_hit]} == yes ]] || err_exit 'foo[barrier_not_hit] should be yes' 57534f9b3eeSRoland Mainzfoo[barrier_hit]=no 576da2e3ebdSchinfoo[bar]=2 577da2e3ebdSchin(( foo[bar] == 5 )) || err_exit 'foo[bar] should be 5' 578da2e3ebdSchin[[ ${foo[barrier_hit]} == yes ]] || err_exit 'foo[barrier_hit] should be yes' 579da2e3ebdSchin[[ ${foo[barrier_not_hit]} == no ]] || err_exit 'foo[barrier_not_hit] should be no' 580da2e3ebdSchinunset x 581da2e3ebdSchintypeset -i x 582da2e3ebdSchinfunction x.set 583da2e3ebdSchin{ 584da2e3ebdSchin typeset sub=${.sh.subscript} 585da2e3ebdSchin (( sub > 0 )) && (( x[sub-1]= x[sub-1] + .sh.value )) 586da2e3ebdSchin} 587da2e3ebdSchinx[0]=0 x[1]=1 x[2]=2 x[3]=3 588da2e3ebdSchin[[ ${x[@]} == '12 8 5 3' ]] || err_exit 'set discipline for indexed array not working correctly' 58934f9b3eeSRoland Mainzfloat seconds 590da2e3ebdSchin((SECONDS=3*4)) 59134f9b3eeSRoland Mainzseconds=SECONDS 59234f9b3eeSRoland Mainz(( seconds < 12 || seconds > 12.1 )) && err_exit "SECONDS is $seconds and should be close to 12" 5937c2fbfb3SApril Chinunset a 5947c2fbfb3SApril Chinfunction a.set 5957c2fbfb3SApril Chin{ 5967c2fbfb3SApril Chin print -r -- "${.sh.name}=${.sh.value}" 5977c2fbfb3SApril Chin} 5987c2fbfb3SApril Chin[[ $(a=1) == a=1 ]] || err_exit 'set discipline not working in subshell assignment' 5997c2fbfb3SApril Chin[[ $(a=1 :) == a=1 ]] || err_exit 'set discipline not working in subshell command' 6007c2fbfb3SApril Chin 6017c2fbfb3SApril Chin[[ ${.sh.subshell} == 0 ]] || err_exit '${.sh.subshell} should be 0' 6027c2fbfb3SApril Chin( 6037c2fbfb3SApril Chin [[ ${.sh.subshell} == 1 ]] || err_exit '${.sh.subshell} should be 1' 6047c2fbfb3SApril Chin ( 6057c2fbfb3SApril Chin [[ ${.sh.subshell} == 2 ]] || err_exit '${.sh.subshell} should be 2' 6067c2fbfb3SApril Chin ) 6077c2fbfb3SApril Chin) 6087c2fbfb3SApril Chin 6097c2fbfb3SApril Chinset -- {1..32768} 6107c2fbfb3SApril Chin(( $# == 32768 )) || err_exit "\$# failed -- expected 32768, got $#" 6117c2fbfb3SApril Chinset -- 6127c2fbfb3SApril Chin 6137c2fbfb3SApril Chinunset r v x 6147c2fbfb3SApril Chinpath=$PATH 6157c2fbfb3SApril Chinx=foo 6167c2fbfb3SApril Chinfor v in EDITOR VISUAL OPTIND CDPATH FPATH PATH ENV LINENO RANDOM SECONDS _ 6177c2fbfb3SApril Chindo nameref r=$v 6187c2fbfb3SApril Chin unset $v 6197c2fbfb3SApril Chin if ( $SHELL -c "unset $v; : \$$v" ) 2>/dev/null 6207c2fbfb3SApril Chin then [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'" 6217c2fbfb3SApril Chin r=$x 6227c2fbfb3SApril Chin [[ $r == $x ]] || err_exit "$v=$x failed -- expected '$x', got '$r'" 6237c2fbfb3SApril Chin else err_exit "unset $v; : \$$v failed" 6247c2fbfb3SApril Chin fi 6257c2fbfb3SApril Chindone 62634f9b3eeSRoland Mainz 62734f9b3eeSRoland Mainzx=x 6287c2fbfb3SApril Chinfor v in LC_ALL LC_CTYPE LC_MESSAGES LC_COLLATE LC_NUMERIC 6297c2fbfb3SApril Chindo nameref r=$v 6307c2fbfb3SApril Chin unset $v 6317c2fbfb3SApril Chin [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'" 6327c2fbfb3SApril Chin d=$($SHELL -c "$v=$x" 2>&1) 6337c2fbfb3SApril Chin [[ $d ]] || err_exit "$v=$x failed -- expected locale diagnostic" 63434f9b3eeSRoland Mainz { g=$( r=$x; print -- $r ); } 2>/dev/null 63534f9b3eeSRoland Mainz [[ $g == '' ]] || err_exit "$v=$x failed -- expected '', got '$g'" 63634f9b3eeSRoland Mainz { g=$( r=C; r=$x; print -- $r ); } 2>/dev/null 63734f9b3eeSRoland Mainz [[ $g == 'C' ]] || err_exit "$v=C; $v=$x failed -- expected 'C', got '$g'" 6387c2fbfb3SApril Chindone 6397c2fbfb3SApril ChinPATH=$path 6407c2fbfb3SApril Chin 64134f9b3eeSRoland Mainzcd $tmp 64234f9b3eeSRoland Mainz 64334f9b3eeSRoland Mainzprint print -n zzz > zzz 64434f9b3eeSRoland Mainzchmod +x zzz 64534f9b3eeSRoland Mainzexp='aaazzz' 64634f9b3eeSRoland Mainzgot=$($SHELL -c 'unset SHLVL; print -n aaa; ./zzz' 2>&1) >/dev/null 2>&1 64734f9b3eeSRoland Mainz[[ $got == "$exp" ]] || err_exit "unset SHLVL causes script failure -- expected '$exp', got '$got'" 64834f9b3eeSRoland Mainz 64934f9b3eeSRoland Mainzmkdir glean 65034f9b3eeSRoland Mainzfor cmd in date ok 65134f9b3eeSRoland Mainzdo exp="$cmd ok" 65234f9b3eeSRoland Mainz rm -f $cmd 65334f9b3eeSRoland Mainz print print $exp > glean/$cmd 65434f9b3eeSRoland Mainz chmod +x glean/$cmd 65534f9b3eeSRoland Mainz got=$(CDPATH=:.. $SHELL -c "PATH=:/bin:/usr/bin; date > /dev/null; cd glean && ./$cmd" 2>&1) 65634f9b3eeSRoland Mainz [[ $got == "$exp" ]] || err_exit "cd with CDPATH after PATH change failed -- expected '$exp', got '$got'" 65734f9b3eeSRoland Mainzdone 65834f9b3eeSRoland Mainz 6593e14f97fSRoger A. Faulknerv=LC_CTYPE 6603e14f97fSRoger A. Faulknerunset $v 6613e14f97fSRoger A. Faulkner[[ -v $v ]] && err_exit "unset $v; [[ -v $v ]] failed" 6623e14f97fSRoger A. Faulknereval $v=C 6633e14f97fSRoger A. Faulkner[[ -v $v ]] || err_exit "$v=C; [[ -v $v ]] failed" 6643e14f97fSRoger A. Faulkner 6653e14f97fSRoger A. Faulknercmd='set --nounset; unset foo; : ${!foo*}' 6663e14f97fSRoger A. Faulkner$SHELL -c "$cmd" 2>/dev/null || err_exit "'$cmd' exit status $?, expected 0" 6673e14f97fSRoger A. Faulkner 668b30d1939SAndy FiddamanSHLVL=1 669b30d1939SAndy Fiddamanlevel=$($SHELL -c $'$SHELL -c \'print -r "$SHLVL"\'') 670b30d1939SAndy Fiddaman[[ $level == 3 ]] || err_exit "SHLVL should be 3 not $level" 671b30d1939SAndy Fiddaman 672b30d1939SAndy Fiddaman[[ $($SHELL -c '{ x=1; : ${x.};print ok;}' 2> /dev/null) == ok ]] || err_exit '${x.} where x is a simple variable causes shell to abort' 673b30d1939SAndy Fiddaman 674b30d1939SAndy Fiddaman$SHELL -c 'unset .sh' 2> /dev/null 675b30d1939SAndy Fiddaman[[ $? == 1 ]] || err_exit 'unset .sh should return 1' 676b30d1939SAndy Fiddaman 677*5b8dd251SAndy Fiddaman# Keep the list in sync (minus ".sh") with shtab_variables[] in 678*5b8dd251SAndy Fiddaman# src/cmd/ksh93/data/variables.c Note: as long as changing $PATH forks a 679*5b8dd251SAndy Fiddaman# virtual subshell, "PATH" should also be excluded below. 680*5b8dd251SAndy Fiddamanset -- \ 681*5b8dd251SAndy Fiddaman "PS1" \ 682*5b8dd251SAndy Fiddaman "PS2" \ 683*5b8dd251SAndy Fiddaman "IFS" \ 684*5b8dd251SAndy Fiddaman "PWD" \ 685*5b8dd251SAndy Fiddaman "HOME" \ 686*5b8dd251SAndy Fiddaman "MAIL" \ 687*5b8dd251SAndy Fiddaman "REPLY" \ 688*5b8dd251SAndy Fiddaman "SHELL" \ 689*5b8dd251SAndy Fiddaman "EDITOR" \ 690*5b8dd251SAndy Fiddaman "MAILCHECK" \ 691*5b8dd251SAndy Fiddaman "RANDOM" \ 692*5b8dd251SAndy Fiddaman "ENV" \ 693*5b8dd251SAndy Fiddaman "HISTFILE" \ 694*5b8dd251SAndy Fiddaman "HISTSIZE" \ 695*5b8dd251SAndy Fiddaman "HISTEDIT" \ 696*5b8dd251SAndy Fiddaman "HISTCMD" \ 697*5b8dd251SAndy Fiddaman "FCEDIT" \ 698*5b8dd251SAndy Fiddaman "CDPATH" \ 699*5b8dd251SAndy Fiddaman "MAILPATH" \ 700*5b8dd251SAndy Fiddaman "PS3" \ 701*5b8dd251SAndy Fiddaman "OLDPWD" \ 702*5b8dd251SAndy Fiddaman "VISUAL" \ 703*5b8dd251SAndy Fiddaman "COLUMNS" \ 704*5b8dd251SAndy Fiddaman "LINES" \ 705*5b8dd251SAndy Fiddaman "PPID" \ 706*5b8dd251SAndy Fiddaman "_" \ 707*5b8dd251SAndy Fiddaman "TMOUT" \ 708*5b8dd251SAndy Fiddaman "SECONDS" \ 709*5b8dd251SAndy Fiddaman "LINENO" \ 710*5b8dd251SAndy Fiddaman "OPTARG" \ 711*5b8dd251SAndy Fiddaman "OPTIND" \ 712*5b8dd251SAndy Fiddaman "PS4" \ 713*5b8dd251SAndy Fiddaman "FPATH" \ 714*5b8dd251SAndy Fiddaman "LANG" \ 715*5b8dd251SAndy Fiddaman "LC_ALL" \ 716*5b8dd251SAndy Fiddaman "LC_COLLATE" \ 717*5b8dd251SAndy Fiddaman "LC_CTYPE" \ 718*5b8dd251SAndy Fiddaman "LC_MESSAGES" \ 719*5b8dd251SAndy Fiddaman "LC_NUMERIC" \ 720*5b8dd251SAndy Fiddaman "FIGNORE" \ 721*5b8dd251SAndy Fiddaman "KSH_VERSION" \ 722*5b8dd251SAndy Fiddaman "JOBMAX" \ 723*5b8dd251SAndy Fiddaman ".sh.edchar" \ 724*5b8dd251SAndy Fiddaman ".sh.edcol" \ 725*5b8dd251SAndy Fiddaman ".sh.edtext" \ 726*5b8dd251SAndy Fiddaman ".sh.edmode" \ 727*5b8dd251SAndy Fiddaman ".sh.name" \ 728*5b8dd251SAndy Fiddaman ".sh.subscript" \ 729*5b8dd251SAndy Fiddaman ".sh.value" \ 730*5b8dd251SAndy Fiddaman ".sh.version" \ 731*5b8dd251SAndy Fiddaman ".sh.dollar" \ 732*5b8dd251SAndy Fiddaman ".sh.match" \ 733*5b8dd251SAndy Fiddaman ".sh.command" \ 734*5b8dd251SAndy Fiddaman ".sh.file" \ 735*5b8dd251SAndy Fiddaman ".sh.fun" \ 736*5b8dd251SAndy Fiddaman ".sh.lineno" \ 737*5b8dd251SAndy Fiddaman ".sh.subshell" \ 738*5b8dd251SAndy Fiddaman ".sh.level" \ 739*5b8dd251SAndy Fiddaman ".sh.stats" \ 740*5b8dd251SAndy Fiddaman ".sh.math" \ 741*5b8dd251SAndy Fiddaman ".sh.pool" \ 742*5b8dd251SAndy Fiddaman ".sh.pid" \ 743*5b8dd251SAndy Fiddaman "SHLVL" \ 744*5b8dd251SAndy Fiddaman "CSWIDTH" 745*5b8dd251SAndy Fiddaman 746*5b8dd251SAndy Fiddaman# ... upper/lowercase test 747*5b8dd251SAndy Fiddaman$SHELL -c ' 748*5b8dd251SAndy Fiddaman typeset -u upper 749*5b8dd251SAndy Fiddaman typeset -l lower 750*5b8dd251SAndy Fiddaman errors=0 751*5b8dd251SAndy Fiddaman PS1=/dev/null/test_my_case_too 752*5b8dd251SAndy Fiddaman PS2=$PS1 PS3=$PS1 PS4=$PS1 OPTARG=$PS1 IFS=$PS1 FPATH=$PS1 FIGNORE=$PS1 CSWIDTH=$PS1 753*5b8dd251SAndy Fiddaman for var 754*5b8dd251SAndy Fiddaman do case $var in 755*5b8dd251SAndy Fiddaman RANDOM | HISTCMD | _ | SECONDS | LINENO | JOBMAX | .sh.stats) 756*5b8dd251SAndy Fiddaman # these are expected to fail below as their values change; just test against crashing 757*5b8dd251SAndy Fiddaman typeset -u "$var" 758*5b8dd251SAndy Fiddaman typeset -l "$var" 759*5b8dd251SAndy Fiddaman continue ;; 760*5b8dd251SAndy Fiddaman esac 761*5b8dd251SAndy Fiddaman nameref val=$var 762*5b8dd251SAndy Fiddaman upper=$val 763*5b8dd251SAndy Fiddaman lower=$val 764*5b8dd251SAndy Fiddaman typeset -u "$var" 765*5b8dd251SAndy Fiddaman if [[ $val != "$upper" ]] 766*5b8dd251SAndy Fiddaman then echo " $0: typeset -u does not work on special variable $var" \ 767*5b8dd251SAndy Fiddaman "(expected $(printf %q "$upper"), got $(printf %q "$val"))" >&2 768*5b8dd251SAndy Fiddaman let errors++ 769*5b8dd251SAndy Fiddaman fi 770*5b8dd251SAndy Fiddaman typeset -l "$var" 771*5b8dd251SAndy Fiddaman if [[ $val != "$lower" ]] 772*5b8dd251SAndy Fiddaman then echo " $0: typeset -l does not work on special variable $var" \ 773*5b8dd251SAndy Fiddaman "(expected $(printf %q "$lower"), got $(printf %q "$val"))" >&2 774*5b8dd251SAndy Fiddaman let errors++ 775*5b8dd251SAndy Fiddaman fi 776*5b8dd251SAndy Fiddaman done 777*5b8dd251SAndy Fiddaman exit $((errors + 1)) 778*5b8dd251SAndy Fiddaman' changecase_test "$@" PATH # do include PATH here as well 779*5b8dd251SAndy Fiddaman(((e = $?) == 1)) || err_exit "typeset -l/-u doesn't work on special variables" \ 780*5b8dd251SAndy Fiddaman "(exit status $e$( ((e>128)) && print -n / && kill -l "$e"))" 781*5b8dd251SAndy Fiddaman 782b30d1939SAndy Fiddamanexit $((Errors<125?Errors:125)) 783