diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/cmd/INIT/mktest.sh | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/cmd/INIT/mktest.sh')
-rwxr-xr-x | src/cmd/INIT/mktest.sh | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/src/cmd/INIT/mktest.sh b/src/cmd/INIT/mktest.sh new file mode 100755 index 0000000..f24183e --- /dev/null +++ b/src/cmd/INIT/mktest.sh @@ -0,0 +1,641 @@ +######################################################################## +# # +# This software is part of the ast package # +# Copyright (c) 1994-2011 AT&T Intellectual Property # +# and is licensed under the # +# Eclipse Public License, Version 1.0 # +# by AT&T Intellectual Property # +# # +# A copy of the License is available at # +# http://www.eclipse.org/org/documents/epl-v10.html # +# (with md5 checksum b35adb5213ca9657e911e9befb180842) # +# # +# Information and Software Systems Research # +# AT&T Research # +# Florham Park NJ # +# # +# Glenn Fowler <gsf@research.att.com> # +# # +######################################################################## +: mktest - generate regress or shell regression test scripts + +command=mktest +stdin=8 +stdout=9 +PREFIX=test +STYLE=regress +WIDTH=80 + +eval "exec $stdout>&1" + +case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in +0123) ARGV0="-a $command" + USAGE=$' +[-? +@(#)$Id: mktest (AT&T Labs Research) 2010-08-11 $ +] +'$USAGE_LICENSE$' +[+NAME?mktest - generate a regression test scripts] +[+DESCRIPTION?\bmktest\b generates regression test scripts from test + template commands in the \aunit\a.\brt\b file. The generated test + script writes temporary output to '$PREFIX$'\aunit\a.tmp and compares + it to the expected output in '$PREFIX$'\aunit\a.out. Run the test + script with the \b--accept\b option to (re)generate the + '$PREFIX$'\aunit\a.out.] +[s:style?The script style:]:[style:='$STYLE$'] + { + [+regress?\bregress\b(1) command input.] + [+shell?Standalone test shell script.] + } +[w:width?Set the output format width to approximately + \awidth\a.]:[width:='$WIDTH$'] + +unit.rt [ unit [ arg ... ] ] + +[+INPUT FILES?The regression test command file \aunit\a\b.rt\b is a + \bksh\b(1) script that makes calls to the following functions:] + { + [+DATA \afile\a [ - | [ options ]] data]]?Create input data + \afile\a that is empty (-) or contains \adata\a subject to + \bprint\b(1) \aoptions\a or that is a copy of the DATA command + standard input. Set \afile\a to \b-\b to name the standard + input.] + [+DIAGNOSTICS?Diagnostic messages of unspecified format are + expected.] + [+DO \acommand\a [ \aarg\a ... ]]?Execute \acommand\a if the + current test is active.] + [+EXEC [ \aarg\a ... ]]?Run the command under test with + optional arguments. If the standard input is not specified then + the standard input of the previous EXEC is used. The standard + input of the first EXEC in a TEST group is an empty regular + file.] + [+EXPORT \aname\a=\avalue\a ...?Export list for subsequent + commands in the TEST group or for all TEST groups if before + the first TEST group.] + [+IGNORESPACE [ 0 | 1 ] + ?Ignore space differences when comparing expected output.] + [+KEEP \apattern\a ...?File match patterns of files to retain + between TEST groups.] + [+NOTE \acomment\a?\acomment\a is added to the current test + script.] + [+PROG \acommand\a [ \aarg\a ... ]]?Run \acommand\a with + optional arguments.] + [+TEST [ \anumber\a ]] [ \adescription\a ... ]]?Define a new + test group with optional \anumber\a and \adescripion\a.] + [+TWD [ \adir\a ... ]]?Set the temporary test dir to \adir\a. + The default is \aunit\a\b.tmp\b, where \aunit\a is the test + input file sans directory and suffix. If \adir\a matches \b/*\b + then it is the directory name; if \adir\a is non-null then the + prefix \b${TMPDIR:-/tmp}\b is added; otherwise if \adir\a is + omitted then + \b${TMPDIR:-/tmp}/tst-\b\aunit\a-$$-$RANDOM.\b\aunit\a is + used.] + [+UMASK [ \amask\a ]]?Run subsequent tests with \bumask\b(1) + \amask\a. If \amask\a is omitted then the original \bumask\b is + used.] + [+UNIT \acommand\a [ \aarg\a ... ]]?Define the command and + optional default arguments to be tested. \bUNIT\b explicitly + overrides the default command name derived from the test script + file name.] + [+WIDTH \awidth\a?Set the output format width to approximately + \awidth\a.] + } +[+SEE ALSO?\bregress\b(1), \bksh\b(1)] +' + ;; +*) ARGV0="" + USAGE='s: unit.rt [ arg ... ]' + ;; +esac + +typeset ARG SCRIPT UNIT TEMP=${TMPDIR:-/tmp}/$command.$$.tmp WORK +typeset IO INPUT INPUT_N OUTPUT OUTPUT_N ERROR ERROR_N KEEP +typeset -C STATE +typeset -A DATA STATE.RESET REMOVE FORMAT +integer KEEP_UNIT=0 SCRIPT_UNIT=0 TEST=0 CODE=0 EXIT=0 ACCEPT=0 DIAGNOSTICS=0 code + +while getopts $ARGV0 "$USAGE" OPT +do case $OPT in + s) case $OPTARG in + regress|shell) + STYLE=$OPTARG + ;; + *) print -u2 -r -- $command: --style=$OPTARG: regress or shell expected + exit 1 + ;; + esac + ;; + w) WIDTH=$OPTARG + ;; + *) OPTIND=0 + getopts $ARGV0 "$USAGE" OPT '-?' + exit 2 + ;; + esac +done +shift $OPTIND-1 + +typeset SINGLE= quote='%${SINGLE}..${WIDTH}q' + +if [[ $1 == - ]] +then shift +fi +if (( ! $# )) +then + print -u2 -r -- $command: test command script path expected + exit 1 +fi +SCRIPT=$1 +shift +if [[ ! -r $SCRIPT ]] +then print -u2 -r -- $command: $SCRIPT: cannot read + exit 1 +fi +(ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0 +if (( $# )) +then set -A UNIT -- "$@" + KEEP_UNIT=1 +else ARG=${SCRIPT##*/} + set -A UNIT -- "${ARG%.*}" +fi +WORK=${UNIT[0]}.tmp +rm -rf $WORK +mkdir $WORK || exit +export PATH=$PWD:$PATH + +function LINE +{ + if [[ $STYLE == regress ]] + then print -u$stdout + fi +} + +function NOTE +{ + case $STYLE in + regress)LINE + print -u$stdout -r -- '#' "$@" + ;; + shell) print -u$stdout -r -f ": $QUOTE"$'\n' -- "$*" + ;; + esac +} + +function UNIT +{ + (( KEEP_UNIT )) || set -A UNIT -- "$@" + case $STYLE in + regress)LINE + print -u$stdout -r -f $'UNIT' + for ARG in "$@" + do print -u$stdout -r -f " $QUOTE" -- "$ARG" + done + print -u$stdout + ;; + shell) print -u$stdout -r -f $'set x' + for ARG in "$@" + do print -u$stdout -r -f " $QUOTE" -- "$ARG" + done + print -u$stdout + print -u$stdout shift + ;; + esac +} + +function TEST +{ + typeset i + typeset -A REM + if (( ${#STATE.RESET[@]} )) + then unset ${!STATE.RESET[@]} + case $STYLE in + shell) print -u$stdout -r -- unset ${!STATE.RESET[@]} ;; + esac + unset STATE.RESET + typeset -A STATE.RESET + fi + if (( ${#REMOVE[@]} )) + then rm -f -- "${!REMOVE[@]}" + case $STYLE in + shell) print -u$stdout -r -f $'rm -f' + for i in ${!REMOVE[@]} + do print -u$stdout -r -f " $QUOTE" "$i" + done + print -u$stdout + ;; + esac + for i in ${!REMOVE[@]} + do unset REMOVE[$i] + done + fi + rm -rf $WORK/* + if [[ $1 == +([0-9]) ]] + then TEST=${1##0} + shift + else ((TEST++)) + fi + LINE + case $STYLE in + regress)print -u$stdout -r -f "TEST %02d $QUOTE"$'\n' -- $TEST "$*" + ;; + shell) print -u$stdout -r -f ": TEST %02d $QUOTE"$'\n' -- $TEST "$*" + ;; + esac + : > $TEMP.INPUT > $TEMP.in + INPUT= + INPUT_N= + OUTPUT= + OUTPUT_N= + ERROR= + ERROR_N= + UMASK=$UMASK_ORIG + UMASK_DONE=$UMASK + CODE=0 +} + +function TWD +{ + case $STYLE in + regress)LINE + print -u$stdout -r -f $'TWD' + for ARG in "$@" + do print -u$stdout -r -f " $QUOTE" -- "$ARG" + done + print -u$stdout + ;; + esac +} + +function RUN +{ + typeset i n p op unit sep output=1 error=1 exitcode=1 + op=$1 + shift + while : + do case $1 in + ++NOOUTPUT) output= ;; + ++NOERROR) error= ;; + ++NOEXIT) exitcode= ;; + ++*) print -u2 -r -- $command: $0: $1: unknown option; exit 1 ;; + *) break ;; + esac + shift + done + if [[ $op == PROG ]] + then unit=$1 + shift + elif (( ! ${#UNIT[@]} )) + then print -u2 -r -- $command: $SCRIPT: UNIT statement or operand expected + exit 1 + fi + LINE + case $STYLE in + regress)if [[ $op == PROG ]] + then print -u$stdout -r -f $'\t'"$op"$'\t'"$unit" + sep=$' ' + else print -u$stdout -r -f $'\t'"$op" + sep=$'\t' + fi + for ARG in "$@" + do LC_CTYPE=C print -u$stdout -r -f "$sep$QUOTE" -- "$ARG" + sep=$' ' + done + print -u$stdout + [[ ${DATA[-]} || /dev/fd/0 -ef /dev/fd/$stdin ]] || cat > $TEMP.in + IO=$(cat $TEMP.in; print :) + if [[ $IO == ?*$'\n:' ]] + then IO=${IO%??} + n= + else IO=${IO%?} + n=-n + fi + { + [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK + cd $WORK + if [[ $op == PROG ]] + then "$unit" "$@" + code=$? + else "${UNIT[@]}" "$@" + code=$? + fi + cd .. + [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG + } < $TEMP.in > $TEMP.out 2> $TEMP.err + if [[ $IO != "$INPUT" || $n != "$INPUT_N" ]] + then INPUT=$IO + INPUT_N=$n + if [[ ${FORMAT[-]} ]] + then print -u$stdout -n -r -- $'\t\tINPUT' + print -u$stdout -r -f " $QUOTE" -- "${FORMAT[-]}" + print -u$stdout -r -f " $QUOTE" -- - + unset FORMAT[-] + else print -u$stdout -n -r -- $'\t\tINPUT' $n - + [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO" + fi + print -u$stdout + unset DATA[-] + fi + for i in ${!DATA[@]} + do if [[ ${FORMAT[$i]} ]] + then print -u$stdout -n -r -- $'\t\tINPUT' + print -u$stdout -r -f " $QUOTE" -- "${FORMAT[$i]}" + print -u$stdout -r -f " $QUOTE" -- "$i" + unset FORMAT[$i] + else case $i in + -) p=$TEMP.in ;; + *) p=$WORK/$i ;; + esac + IO=$(cat $p; print :) + if [[ $IO == ?*$'\n:' ]] + then IO=${IO%??} + n= + else IO=${IO%?} + n=-n + fi + print -u$stdout -n -r -- $'\t\tINPUT' $n + print -u$stdout -r -f " $QUOTE" -- "$i" + [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO" + fi + print -u$stdout + unset DATA[$i] + done + IO=$(cat $TEMP.out; print :) + if [[ $IO == ?*$'\n:' ]] + then IO=${IO%??} + n= + else IO=${IO%?} + n=-n + fi + if [[ $IO != "$OUTPUT" || $n != "$OUTPUT_N" ]] + then OUTPUT=$IO + OUTPUT_N=$n + if [[ $output ]] + then if [[ ! -s $TEMP.out ]] + then print -u$stdout -n -r -- $'\t\tOUTPUT' - + elif cmp -s $TEMP.in $TEMP.out + then OUTPUT=not-$OUTPUT + print -u$stdout -n -r -- $'\t\tSAME OUTPUT INPUT' + else print -u$stdout -n -r -- $'\t\tOUTPUT' $n - + [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO" + fi + print -u$stdout + fi + fi + IO=$(cat $TEMP.err; print :) + IO=${IO//$command\[*([0-9])\]:\ .\[*([0-9])\]:\ @(EXEC|PROG)\[*([0-9])\]:\ /} + if [[ $IO == ?*$'\n:' ]] + then IO=${IO%??} + n= + else IO=${IO%?} + n=-n + fi + if [[ $IO != "$ERROR" || $n != "$ERROR_N" ]] + then ERROR=$IO + ERROR_N=$n + if [[ $error ]] + then print -u$stdout -n -r -- $'\t\tERROR' $n - + [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO" + print -u$stdout + fi + fi + case $output:$error in + :) OUTPUT= + OUTPUT_N= + ERROR= + ERROR_N= + print -u$stdout -r -- $'\t\tIGNORE OUTPUT ERROR' + ;; + :1) OUTPUT= + OUTPUT_N= + print -u$stdout -r -- $'\t\tIGNORE OUTPUT' + ;; + 1:) ERROR= + ERROR_N= + print -u$stdout -r -- $'\t\tIGNORE ERROR' + ;; + esac + if [[ $UMASK_DONE != $UMASK ]] + then UMASK_DONE=$UMASK + print -u$stdout -r -f $'\t\tUMASK %s\n' $UMASK + fi + if (( code != CODE )) + then (( CODE=code )) + if [[ $exitcode ]] + then print -u$stdout -r -f $'\t\tEXIT %d\n' $CODE + fi + fi + ;; + shell) [[ $UMASK != $UMASK_ORIG ]] && print -u$stdout -r -f "{ umask $UMASK; " + if [[ $op == PROG ]] + then print -u$stdout -r -f $'"'"$unit"$'"' + else print -u$stdout -r -f $'"$@"' + fi + for ARG in "$@" + do print -u$stdout -r -f " $QUOTE" -- "$ARG" + done + [[ $UMASK != $UMASK_ORIG ]] && print -u$stdout -r -f "umask $UMASK_ORIG; } " + if [[ ! $output ]] + then print -u$stdout -r -f " >/dev/null" + fi + if [[ ! $error ]] + then if [[ ! $output ]] + then print -u$stdout -r -f " 2>&1" + else print -u$stdout -r -f " 2>/dev/null" + fi + fi + IO=$(cat) + if [[ $IO ]] + then print -u$stdout -r -- "<<'!TEST-INPUT!'" + print -u$stdout -r -- "$IO" + print -u$stdout -r -- !TEST-INPUT! + else print -u$stdout + fi + if [[ $exitcode ]] + then print -u$stdout -r -- $'CODE=$?\ncase $CODE in\n0) ;;\n*) echo exit status $CODE ;;\nesac' + fi + ;; + esac +} + +function DO +{ + LINE + print -r $'\t'DO "$@" +} + +function EXEC +{ + RUN EXEC "$@" +} + +function DATA +{ + typeset f p o + f=$1 + shift + case $f in + -) p=$TEMP.in ;; + *) p=$WORK/$f ;; + esac + case $1 in + '') cat ;; + -) ;; + *) print -r "$@" ;; + esac > $p + DATA[$f]=1 + if (( $# == 1 )) && [[ $1 == -?* ]] + then FORMAT[$f]=$1 + else FORMAT[$f]= + fi + if [[ $f != $KEEP ]] + then REMOVE[$f]=1 + fi + if [[ $STYLE == shell ]] + then { + print -r -f "cat > $QUOTE <<'!TEST-INPUT!'"$'\n' -- "$f" + cat "$p" + print -r -- !TEST-INPUT! + } >&$stdout + fi +} + +function KEEP +{ + typeset p + for p + do if [[ $KEEP ]] + then KEEP=$KEEP'|' + fi + KEEP=$KEEP$p + done +} + +function DIAGNOSTICS +{ + LINE + case $STYLE in + regress) print -u$stdout -r $'DIAGNOSTICS' ;; + shell) DIAGNOSTICS=1 ;; + esac +} + +function EXPORT +{ + typeset x n v + LINE + case $STYLE in + regress) print -u$stdout -r -f $'EXPORT' ;; + shell) print -u$stdout -r -f $'export' ;; + esac + for x + do n=${x%%=*} + v=${x#*=} + export "$x" + print -u$stdout -r -f " %s=$QUOTE" "$n" "$v" + (( TEST )) && STATE.RESET["$n"]=1 + done + print -u$stdout +} + +function PROG +{ + RUN PROG "$@" +} + +function WIDTH +{ + WIDTH=${1:-80} + eval QUOTE='"'$quote'"' +} + +function IGNORESPACE +{ + IGNORESPACE=-b + LINE + print -u$stdout -r IGNORESPACE +} + +function UMASK # [ mask ] +{ + [[ $UMASK_ORIG ]] || UMASK_ORIG=$(umask) + UMASK=$1 + [[ $UMASK ]] || UMASK=$UMASK_ORIG +} + +trap 'CODE=$?; rm -rf $TEMP.* $WORK; exit $CODE' 0 1 2 3 15 + +typeset IGNORESPACE UMASK UMASK_ORIG UMASK_DONE +UMASK_ORIG=$(umask) +IFS=$IFS$'\n' + +print -u$stdout -r "# : : generated from $SCRIPT by $command : : #" +case $STYLE in +shell) cat <<! +ACCEPT=0 +while : +do case \$1 in + -a|--accept) + ACCEPT=1 + ;; + --help|--man) + cat 1>&2 <<!! +Usage: \\\$SHELL $PREFIX${UNIT[0]}.sh [ --accept ] [ unit ... ] + +${UNIT[0]} regression test script. Run this script to generate new +results in $PREFIX${UNIT[0]}.tmp and compare with expected results in +$PREFIX${UNIT[0]}.out. The --accept option generates $PREFIX${UNIT[0]}.tmp +and moves it to $PREFIX${UNIT[0]}.out. +!! + exit 2 + ;; + -*) echo \$0: \$1: invalid option >&2 + exit 1 + ;; + *) break + ;; + esac + shift +done +export COLUMNS=80 +{ +! + ;; +esac + +export COLUMNS=80 + +case $STYLE in +shell) SINGLE='#' + eval QUOTE='"'$quote'"' + . $SCRIPT < /dev/null | sed -e $'s,\\\\n,\n,g' -e $'s,\\\\t,\t,g' -e $'s,\\$\',\',g' + ;; +*) eval QUOTE='"'$quote'"' + : > $TEMP.INPUT > $TEMP.in + eval "exec $stdin<$TEMP.INPUT" + . $SCRIPT <&$stdin + ;; +esac + +case $STYLE in +shell) cat <<! +} > $PREFIX${UNIT[0]}.tmp 2>&1 < /dev/null +case \$ACCEPT in +0) if grep '
$' $PREFIX${UNIT[0]}.tmp >/dev/null + then mv $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.junk + sed 's/
$//' < $PREFIX${UNIT[0]}.junk > $PREFIX${UNIT[0]}.tmp + rm -f $PREFIX${UNIT[0]}.junk + fi + if cmp -s $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out + then echo ${UNIT[0]} tests PASSED + rm -f $PREFIX${UNIT[0]}.tmp + else echo ${UNIT[0]} tests FAILED + diff $IGNORESPACE $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out + fi + ;; + +*) mv $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out + ;; +esac +! + ;; +esac |