1da2e3ebdSchin######################################################################## 2da2e3ebdSchin# # 3da2e3ebdSchin# This software is part of the ast package # 4*3e14f97fSRoger A. Faulkner# Copyright (c) 1982-2010 AT&T Intellectual Property # 5da2e3ebdSchin# and is licensed under the # 6da2e3ebdSchin# Common Public License, Version 1.0 # 77c2fbfb3SApril Chin# by AT&T Intellectual Property # 8da2e3ebdSchin# # 9da2e3ebdSchin# A copy of the License is available at # 10da2e3ebdSchin# http://www.opensource.org/licenses/cpl1.0.txt # 11da2e3ebdSchin# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # 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 367c2fbfb3SApril Chin[[ ${@ss} ]] && err_exit '${@ss} should be empty string when ss is unset' 377c2fbfb3SApril Chin[[ ${!ss} == ss ]] || err_exit '${!ss} should be ss when ss is unset' 387c2fbfb3SApril Chin[[ ${#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 111da2e3ebdSchinif ( typeset 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{ 179da2e3ebdSchin .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 432da2e3ebdSchin 433da2e3ebdSchin} 434da2e3ebdSchinx=$(foo) 435da2e3ebdSchin(( 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 48734f9b3eeSRoland Mainzprint 'print ${VAR}' > $tmp/script 4887c2fbfb3SApril Chinunset VAR 48934f9b3eeSRoland MainzVAR=new $tmp/script > $tmp/out 49034f9b3eeSRoland Mainzgot=$(<$tmp/out) 4917c2fbfb3SApril Chin[[ $got == new ]] || err_exit "previously unset environment variable not passed to script, expected 'new', got '$got'" 4927c2fbfb3SApril Chin[[ ! $VAR ]] || err_exit "previously unset environment variable set after script, expected '', got '$VAR'" 4937c2fbfb3SApril Chinunset VAR 4947c2fbfb3SApril ChinVAR=old 49534f9b3eeSRoland MainzVAR=new $tmp/script > $tmp/out 49634f9b3eeSRoland Mainzgot=$(<$tmp/out) 4977c2fbfb3SApril Chin[[ $got == new ]] || err_exit "environment variable covering local variable not passed to script, expected 'new', got '$got'" 4987c2fbfb3SApril Chin[[ $VAR == old ]] || err_exit "previously set local variable changed after script, expected 'old', got '$VAR'" 4997c2fbfb3SApril Chinunset VAR 5007c2fbfb3SApril Chinexport VAR=old 50134f9b3eeSRoland MainzVAR=new $tmp/script > $tmp/out 50234f9b3eeSRoland Mainzgot=$(<$tmp/out) 5037c2fbfb3SApril Chin[[ $got == new ]] || err_exit "environment variable covering environment variable not passed to script, expected 'new', got '$got'" 5047c2fbfb3SApril Chin[[ $VAR == old ]] || err_exit "previously set environment variable changed after script, expected 'old', got '$VAR'" 5057c2fbfb3SApril Chin 506da2e3ebdSchin( 507da2e3ebdSchin unset dave 508da2e3ebdSchin function dave.append 509da2e3ebdSchin { 510da2e3ebdSchin .sh.value+=$dave 511da2e3ebdSchin dave= 512da2e3ebdSchin } 513da2e3ebdSchin dave=foo; dave+=bar 514da2e3ebdSchin [[ $dave == barfoo ]] || exit 2 515da2e3ebdSchin) 2> /dev/null 516da2e3ebdSchincase $? in 517da2e3ebdSchin0) ;; 518da2e3ebdSchin1) err_exit 'append discipline not implemented';; 519da2e3ebdSchin*) err_exit 'append discipline not working';; 520da2e3ebdSchinesac 521da2e3ebdSchin.sh.foobar=hello 522da2e3ebdSchin{ 523da2e3ebdSchin function .sh.foobar.get 524da2e3ebdSchin { 525da2e3ebdSchin .sh.value=world 526da2e3ebdSchin } 52734f9b3eeSRoland Mainz} 2> /dev/null || err_exit "cannot add get discipline to .sh.foobar" 528da2e3ebdSchin[[ ${.sh.foobar} == world ]] || err_exit 'get discipline for .sh.foobar not working' 529da2e3ebdSchinx='a|b' 530da2e3ebdSchinIFS='|' 531da2e3ebdSchinset -- $x 532da2e3ebdSchin[[ $2 == b ]] || err_exit '$2 should be b after set' 533da2e3ebdSchinexec 3>&2 2> /dev/null 534da2e3ebdSchinset -x 535da2e3ebdSchin( IFS= ) 2> /dev/null 536da2e3ebdSchinset +x 537da2e3ebdSchinexec 2>&3- 538da2e3ebdSchinset -- $x 539da2e3ebdSchin[[ $2 == b ]] || err_exit '$2 should be b after subshell' 540da2e3ebdSchin: & pid=$! 541da2e3ebdSchin( : & ) 542da2e3ebdSchin[[ $pid == $! ]] || err_exit '$! value not preserved across subshells' 543da2e3ebdSchinunset foo 544da2e3ebdSchintypeset -A foo 545da2e3ebdSchinfunction foo.set 546da2e3ebdSchin{ 547da2e3ebdSchin case ${.sh.subscript} in 548da2e3ebdSchin bar) if ((.sh.value > 1 )) 549da2e3ebdSchin then .sh.value=5 550da2e3ebdSchin foo[barrier_hit]=yes 551da2e3ebdSchin fi 552da2e3ebdSchin ;; 553da2e3ebdSchin barrier_hit) 554da2e3ebdSchin if [[ ${.sh.value} = yes ]] 555da2e3ebdSchin then foo[barrier_not_hit]=no 556da2e3ebdSchin else foo[barrier_not_hit]=yes 557da2e3ebdSchin fi 558da2e3ebdSchin ;; 559da2e3ebdSchin esac 560da2e3ebdSchin} 561da2e3ebdSchinfoo[barrier_hit]=no 562da2e3ebdSchinfoo[bar]=1 563da2e3ebdSchin(( foo[bar] == 1 )) || err_exit 'foo[bar] should be 1' 564da2e3ebdSchin[[ ${foo[barrier_hit]} == no ]] || err_exit 'foo[barrier_hit] should be no' 565da2e3ebdSchin[[ ${foo[barrier_not_hit]} == yes ]] || err_exit 'foo[barrier_not_hit] should be yes' 566da2e3ebdSchinfoo[barrier_hit]=no 567da2e3ebdSchinfoo[bar]=2 568da2e3ebdSchin(( foo[bar] == 5 )) || err_exit 'foo[bar] should be 5' 569da2e3ebdSchin[[ ${foo[barrier_hit]} == yes ]] || err_exit 'foo[barrier_hit] should be yes' 570da2e3ebdSchin[[ ${foo[barrier_not_hit]} == no ]] || err_exit 'foo[barrier_not_hit] should be no' 571da2e3ebdSchinunset x 572da2e3ebdSchintypeset -i x 573da2e3ebdSchinfunction x.set 574da2e3ebdSchin{ 575da2e3ebdSchin typeset sub=${.sh.subscript} 576da2e3ebdSchin (( sub > 0 )) && (( x[sub-1]= x[sub-1] + .sh.value )) 577da2e3ebdSchin} 578da2e3ebdSchinx[0]=0 x[1]=1 x[2]=2 x[3]=3 579da2e3ebdSchin[[ ${x[@]} == '12 8 5 3' ]] || err_exit 'set discipline for indexed array not working correctly' 58034f9b3eeSRoland Mainzfloat seconds 581da2e3ebdSchin((SECONDS=3*4)) 58234f9b3eeSRoland Mainzseconds=SECONDS 58334f9b3eeSRoland Mainz(( seconds < 12 || seconds > 12.1 )) && err_exit "SECONDS is $seconds and should be close to 12" 5847c2fbfb3SApril Chinunset a 5857c2fbfb3SApril Chinfunction a.set 5867c2fbfb3SApril Chin{ 5877c2fbfb3SApril Chin print -r -- "${.sh.name}=${.sh.value}" 5887c2fbfb3SApril Chin} 5897c2fbfb3SApril Chin[[ $(a=1) == a=1 ]] || err_exit 'set discipline not working in subshell assignment' 5907c2fbfb3SApril Chin[[ $(a=1 :) == a=1 ]] || err_exit 'set discipline not working in subshell command' 5917c2fbfb3SApril Chin 5927c2fbfb3SApril Chin[[ ${.sh.subshell} == 0 ]] || err_exit '${.sh.subshell} should be 0' 5937c2fbfb3SApril Chin( 5947c2fbfb3SApril Chin [[ ${.sh.subshell} == 1 ]] || err_exit '${.sh.subshell} should be 1' 5957c2fbfb3SApril Chin ( 5967c2fbfb3SApril Chin [[ ${.sh.subshell} == 2 ]] || err_exit '${.sh.subshell} should be 2' 5977c2fbfb3SApril Chin ) 5987c2fbfb3SApril Chin) 5997c2fbfb3SApril Chin 6007c2fbfb3SApril Chinset -- {1..32768} 6017c2fbfb3SApril Chin(( $# == 32768 )) || err_exit "\$# failed -- expected 32768, got $#" 6027c2fbfb3SApril Chinset -- 6037c2fbfb3SApril Chin 6047c2fbfb3SApril Chinunset r v x 6057c2fbfb3SApril Chinpath=$PATH 6067c2fbfb3SApril Chinx=foo 6077c2fbfb3SApril Chinfor v in EDITOR VISUAL OPTIND CDPATH FPATH PATH ENV LINENO RANDOM SECONDS _ 6087c2fbfb3SApril Chindo nameref r=$v 6097c2fbfb3SApril Chin unset $v 6107c2fbfb3SApril Chin if ( $SHELL -c "unset $v; : \$$v" ) 2>/dev/null 6117c2fbfb3SApril Chin then [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'" 6127c2fbfb3SApril Chin r=$x 6137c2fbfb3SApril Chin [[ $r == $x ]] || err_exit "$v=$x failed -- expected '$x', got '$r'" 6147c2fbfb3SApril Chin else err_exit "unset $v; : \$$v failed" 6157c2fbfb3SApril Chin fi 6167c2fbfb3SApril Chindone 61734f9b3eeSRoland Mainz 61834f9b3eeSRoland Mainzx=x 6197c2fbfb3SApril Chinfor v in LC_ALL LC_CTYPE LC_MESSAGES LC_COLLATE LC_NUMERIC 6207c2fbfb3SApril Chindo nameref r=$v 6217c2fbfb3SApril Chin unset $v 6227c2fbfb3SApril Chin [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'" 6237c2fbfb3SApril Chin d=$($SHELL -c "$v=$x" 2>&1) 6247c2fbfb3SApril Chin [[ $d ]] || err_exit "$v=$x failed -- expected locale diagnostic" 62534f9b3eeSRoland Mainz { g=$( r=$x; print -- $r ); } 2>/dev/null 62634f9b3eeSRoland Mainz [[ $g == '' ]] || err_exit "$v=$x failed -- expected '', got '$g'" 62734f9b3eeSRoland Mainz { g=$( r=C; r=$x; print -- $r ); } 2>/dev/null 62834f9b3eeSRoland Mainz [[ $g == 'C' ]] || err_exit "$v=C; $v=$x failed -- expected 'C', got '$g'" 6297c2fbfb3SApril Chindone 6307c2fbfb3SApril ChinPATH=$path 6317c2fbfb3SApril Chin 63234f9b3eeSRoland Mainzcd $tmp 63334f9b3eeSRoland Mainz 63434f9b3eeSRoland Mainzprint print -n zzz > zzz 63534f9b3eeSRoland Mainzchmod +x zzz 63634f9b3eeSRoland Mainzexp='aaazzz' 63734f9b3eeSRoland Mainzgot=$($SHELL -c 'unset SHLVL; print -n aaa; ./zzz' 2>&1) >/dev/null 2>&1 63834f9b3eeSRoland Mainz[[ $got == "$exp" ]] || err_exit "unset SHLVL causes script failure -- expected '$exp', got '$got'" 63934f9b3eeSRoland Mainz 64034f9b3eeSRoland Mainzmkdir glean 64134f9b3eeSRoland Mainzfor cmd in date ok 64234f9b3eeSRoland Mainzdo exp="$cmd ok" 64334f9b3eeSRoland Mainz rm -f $cmd 64434f9b3eeSRoland Mainz print print $exp > glean/$cmd 64534f9b3eeSRoland Mainz chmod +x glean/$cmd 64634f9b3eeSRoland Mainz got=$(CDPATH=:.. $SHELL -c "PATH=:/bin:/usr/bin; date > /dev/null; cd glean && ./$cmd" 2>&1) 64734f9b3eeSRoland Mainz [[ $got == "$exp" ]] || err_exit "cd with CDPATH after PATH change failed -- expected '$exp', got '$got'" 64834f9b3eeSRoland Mainzdone 64934f9b3eeSRoland Mainz 650*3e14f97fSRoger A. Faulknerv=LC_CTYPE 651*3e14f97fSRoger A. Faulknerunset $v 652*3e14f97fSRoger A. Faulkner[[ -v $v ]] && err_exit "unset $v; [[ -v $v ]] failed" 653*3e14f97fSRoger A. Faulknereval $v=C 654*3e14f97fSRoger A. Faulkner[[ -v $v ]] || err_exit "$v=C; [[ -v $v ]] failed" 655*3e14f97fSRoger A. Faulkner 656*3e14f97fSRoger A. Faulknercmd='set --nounset; unset foo; : ${!foo*}' 657*3e14f97fSRoger A. Faulkner$SHELL -c "$cmd" 2>/dev/null || err_exit "'$cmd' exit status $?, expected 0" 658*3e14f97fSRoger A. Faulkner 659da2e3ebdSchinexit $((Errors)) 660