1: ksh regression test harness : 2 3USAGE_LICENSE="[-author?David Korn <dgk@research.att.com>][-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2000-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html]" 4 5command=shtests 6 7setslocale='*@(locale).sh' 8timesensitive='*@(options|sigchld|subshell).sh' 9valgrindflags='--xml=yes --log-file=/dev/null --track-origins=yes --read-var-info=yes' 10 11USAGE=$' 12[-s8? 13@(#)$Id: shtests (AT&T Research) 2012-05-29 $ 14] 15'$USAGE_LICENSE$' 16[+NAME?shtests - ksh regression test harness] 17[+DESCRIPTION?\bshtests\b is the \bksh\b(1) regression test harness for 18 \b$SHELL\b or \bksh\b if \bSHELL\b is not defined and exported. If 19 none of the \b--posix --utf8 --compile\b options are specified then 20 all three are enabled.] 21[+INPUT FILES?\bshtests\b regression test files are shell scripts that 22 run in an environment controlled by \bshtests\b. An identification 23 message is printed before and after each test on the standard output. 24 The default environment settings are:] 25 { 26 [+unset LANG] 27 [+unset LC_ALL] 28 [+LC_NUMERIC=C?\b.\b radix point assumed by all test scripts.] 29 [+VMALLOC_OPTIONS=abort?\bvmalloc\b(1) arena checking enabled 30 with \babort(2)\b on error.] 31 } 32[c:compile?Run test scripts using \bshcomp\b(1).] 33[d:debug?Enable \bshtests\b execution trace.] 34[l:locale?Disable \b--utf8\b and run the \b--posix\b and \b--compile\b 35 tests, if enabled, in the locale of the caller. This may cause invalid 36 regressions, especially for locales where \b.\b is not the radix 37 point.] 38[p:posix?Run the test scripts in the posix/C locale.] 39[t!:time?Include the current date/time in the test identification 40 messages.] 41[u:utf8?Run the test scripts in the ast-specific C.UTF-8 locale.] 42[v!:vmalloc_options?Run tests with \bVMALLOC_OPTIONS=abort\b. Test 43 script names matching \b'$timesensitive$'\b are run with 44 \bVMALLOC_OPTIONS\b unset.] 45[V:valgrind?Set \b--novmalloc_options\b and run the test scripts with 46 \bvalgrind\b(1) on \bksh\b. If \b$SHELL-g\b exists and is executable 47 than it is used instead of \b$SHELL\b.] 48[x:trace?Enable script execution trace.] 49 50[ test.sh ... ] [ name=value ... ] 51 52[+SEE ALSO?\bksh\b(1), \bregress\b(1), \brt\b(1)] 53' 54 55function usage 56{ 57 OPTIND=0 58 getopts -a $command "$USAGE" OPT '--??long' 59 exit 2 60} 61 62function valxml 63{ 64 typeset state=INIT data dir file fn line what 65 integer errors=0 66 67 #print === $1 ===; cat $1; print === === 68 while read data 69 do case $state in 70 INIT) case $data in 71 '<error>') 72 state=ERROR 73 ;; 74 esac 75 ;; 76 ERROR) case $data in 77 '<kind>'Leak*'</kind>') 78 state=SKIP 79 ;; 80 '<kind>'*'</kind>') 81 state=KEEP 82 what=UNKNOWN 83 ;; 84 esac 85 ;; 86 FRAME) case $data in 87 '<dir>'*'</dir>') 88 dir=${data#'<dir>'} 89 dir=${dir%'</dir>'} 90 ;; 91 '<file>'*'</file>') 92 file=${data#'<file>'} 93 file=${file%'</file>'} 94 ;; 95 '<fn>'*'</fn>') 96 fn=${data#'<fn>'} 97 fn=${fn%'</fn>'} 98 ;; 99 '<line>'*'</line>') 100 line=${data#'<line>'} 101 line=${line%'</line>'} 102 ;; 103 '</frame>') 104 [[ $dir ]] && dir+=/ 105 dir+=$file 106 [[ $dir ]] && dir+=: 107 [[ $line ]] && dir+=$line: 108 [[ $fn ]] && dir+=$fn 109 [[ $dir ]] && echo $'\t '$dir 110 state=KEEP 111 ;; 112 esac 113 ;; 114 KEEP) case $data in 115 '<auxwhat>'*'</auxwhat>') 116 what=${data#'<auxwhat>'} 117 what=${what%'</auxwhat>'} 118 echo $'\t'"$what" 119 ;; 120 '<frame>') 121 state=FRAME 122 dir= 123 file= 124 fn= 125 line= 126 ;; 127 '<what>Syscall param mount(type) points to unaddressable byte(s)</what>') 128 state=SKIP 129 ;; 130 '<what>'*'</what>') 131 (( errors++ )) 132 what=${data#'<what>'} 133 what=${what%'</what>'} 134 echo $'\n\t'"$what" 135 ;; 136 '<xwhat>') 137 state=WHAT 138 ;; 139 '</error>') 140 state=INIT 141 ;; 142 esac 143 ;; 144 SKIP) case $data in 145 '</error>') 146 state=INIT 147 ;; 148 esac 149 ;; 150 WHAT) case $data in 151 '<text>'*'</text>') 152 (( errors++ )) 153 what=${data#'<text>'} 154 what=${what%'</text>'} 155 echo $'\n\t'"$what" 156 ;; 157 '</xwhat>') 158 state=KEEP 159 ;; 160 esac 161 ;; 162 esac 163 done < "$1" 164 (( errors )) && echo 165 return $errors 166} 167 168unset DISPLAY ENV FIGNORE HISTFILE 169trap + PIPE # unadvertized -- set SIGPIPE to SIG_DFL # 170 171integer compile=-1 posix=-1 utf8=-1 172integer debug=0 locale=0 time=1 173typeset vmalloc_options=abort trace= valgrind= 174vmalloc_options= #XXX# until multi-region vmalloc trace fixed #XXX# 175 176while getopts -a $command "$USAGE" OPT 177do case $OPT in 178 c) if (( $OPTARG )) 179 then compile=2 180 else compile=0 181 fi 182 ;; 183 d) debug=$OPTARG 184 ;; 185 l) locale=$OPTARG 186 ;; 187 p) posix=$OPTARG 188 ;; 189 t) time=$OPTARG 190 ;; 191 u) utf8=$OPTARG 192 ;; 193 v) if (( OPTARG )) 194 then vmalloc_options=abort 195 else vmalloc_options= 196 fi 197 ;; 198 V) valgrind="${VALGRIND:-valgrind} ${VALGRINDFLAGS:-$valgrindflags}" 199 vmalloc_options= 200 ;; 201 x) trace=-x 202 ;; 203 *) usage 204 ;; 205 esac 206done 207shift $OPTIND-1 208 209if (( debug )) || [[ $trace ]] 210then export PS4=':$LINENO: ' 211 if (( debug )) 212 then set -x 213 fi 214fi 215 216while [[ $1 == *=* ]] 217do eval export "$1" 218 shift 219done 220 221if (( compile <= 0 && posix <= 0 && utf8 <= 0 )) 222then (( compile )) && compile=1 223 (( posix )) && posix=1 224 (( utf8 )) && utf8=1 225fi 226(( compile < 0 )) && compile=0 227(( posix < 0 )) && posix=0 228(( utf8 < 0 )) && utf8=0 229if (( locale )) 230then utf8=0 231 if [[ $LC_ALL ]] 232 then export LANG=$LC_ALL 233 fi 234else unset LANG LC_ALL 235 export LC_NUMERIC=C 236fi 237if [[ $VMALLOC_OPTIONS ]] 238then vmalloc_options=$VMALLOC_OPTIONS 239else VMALLOC_OPTIONS=$vmalloc_options 240fi 241[[ $VMALLOC_OPTIONS ]] || timesensitive=. 242export PATH PWD SHCOMP SHELL VMALLOC_OPTIONS 243PWD=$(pwd) 244SHELL=${SHELL-ksh} 245case $0 in 246/*) d=$(dirname $0);; 247*/*) d=$PWD/$(dirname $0);; 248*) d=$PWD;; 249esac 250case $SHELL in 251/*) ;; 252*/*) SHELL=$d/$SHELL;; 253*) SHELL=$(whence $SHELL);; 254esac 255PATH=/bin:/usr/bin 256if [[ -d /usr/ucb ]] 257then PATH=$PATH:/usr/ucb 258fi 259PATH=$PATH:$d 260if [[ $INSTALLROOT && -r $INSTALLROOT/bin/.paths ]] 261then PATH=$INSTALLROOT/bin:$PATH 262fi 263if [[ ${SHELL%/*} != $INSTALLROOT/bin ]] 264then PATH=${SHELL%/*}:$PATH 265fi 266if [[ ! $SHCOMP ]] 267then s=${SHELL:##*sh} 268 s=${SHELL:%/*}/shcomp$s 269 if [[ -x $s ]] 270 then SHCOMP=$s 271 elif [[ -x ${s%-g} ]] 272 then SHCOMP=${s%-g} 273 else SHCOMP=shcomp 274 fi 275fi 276if (( compile )) 277then if whence $SHCOMP > /dev/null 278 then tmp=$(mktemp -dt) || { echo mktemp -dt failed >&2; exit 1; } 279 trap "cd /; rm -rf $tmp" EXIT 280 elif (( compile > 1 )) 281 then echo $0: --compile: $SHCOMP not found >&2 282 exit 1 283 else compile=0 284 fi 285fi 286if [[ $valgrind ]] 287then if [[ -x $SHELL-g ]] 288 then SHELL=$SHELL-g 289 fi 290 if [[ ! $tmp ]] 291 then tmp=$(mktemp -dt) || { echo mktemp -dt failed >&2; exit 1; } 292 trap "cd /; rm -rf $tmp" EXIT 293 fi 294 valxml=$tmp/valgrind.xml 295 valgrind+=" --xml-file=$valxml" 296fi 297typeset -A tests 298for i in ${*-*.sh} 299do if [[ ! -r $i ]] 300 then echo $0: $i: not found >&2 301 continue 302 fi 303 t=$(grep -c err_exit $i) 304 if (( t > 2 )) 305 then (( t = t - 2 )) 306 fi 307 tests[$i]=$t 308 T=test 309 if (( t != 1 )) 310 then T=${T}s 311 fi 312 u=${i##*/} 313 u=${u%.sh} 314 if [[ $i == $timesensitive ]] 315 then VMALLOC_OPTIONS= 316 fi 317 if (( posix || utf8 )) 318 then locales= 319 (( posix )) && locales+=" ${LANG:-C}" 320 [[ $utf8 == 0 || $i == $setslocale ]] || locales+=" C.UTF-8" 321 for lang in $locales 322 do o=$u 323 if [[ $lang == C ]] 324 then lang= 325 else o="$o($lang)" 326 lang=LANG=$lang 327 fi 328 echo test $o begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} 329 E=error 330 eval $lang \$valgrind \$SHELL \$trace \$i 331 e=$? 332 if [[ $valgrind ]] 333 then valxml $valxml 334 (( e += $? )) 335 fi 336 if (( e == 0 )) 337 then echo test $o passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]" 338 else e=$? 339 if (( e != 1 )) 340 then E=${E}s 341 fi 342 echo test $o failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]" 343 fi 344 done 345 fi 346 if (( compile )) 347 then c=$tmp/shcomp-$u.ksh 348 o="$u(shcomp)" 349 echo test $o begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} 350 E=error 351 if $SHCOMP $i > $c 352 then if $valgrind $SHELL $trace $c 353 then echo test $o passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]" 354 else e=$? 355 if (( e != 1 )) 356 then E=${E}s 357 fi 358 echo test $o failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]" 359 fi 360 else e=$? 361 t=1 362 T=test 363 echo test $o failed to compile ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T 1 $E ]" 364 fi 365 if [[ $i == $timesensitive ]] 366 then VMALLOC_OPTIONS=$vmalloc_options 367 fi 368 fi 369done 370