#!/bin/sh
# Copyright 2005-2006 Nanorex, Inc.  See LICENSE file for details. 

# runtest.sh description.test [--generate]
#
# runs the described test and concatenates the results
# to stdout (after removing lines which vary inconsequentially (e.g. dates)
#
# if --generate is given, the results are written to $base.out, and
#  the end structure is written to $base.xyzcmp (if the test type
#  is "struct").
#
# a description.test file looks like:
#
# comment lines, which start with a #, and are ignored
# blank lines, which are ignored
# lines containing one of the following directives:
#
# TYPE [ min | struct | dyn ]
#  Choose one of the given types of tests.  The test type controls
#  the defaults for the other directives.  Test type "min" performs
#  a minimization, and checks the program outputs, including the
#  trace file and xyz file are identical.  Test type "struct" also
#  performs a minimization, but relies on a structure comparison
#  to test for success, rather than the exact program output.
#  Test type "dyn" performs a dynamics run, and requires that output
#  be identical, as for "min".  Default value for TYPE is "min".
#
# INPUT files...
#  The listed files are copied to the temporary directory before
#  the test is run.  Defaults to the name of the description file
#  with the .test replaced by .mmp ($base.mmp).
#
# OUTPUT files...
#  The listed files contain significant data to be compared.
#  They are concatenated together, run through a sed script to
#  remove inconsequential lines, and the result goes to stdout.
#  In addition to files explicitly generated by the program
#  stdout and stderr are available.  The file exitvalue contains
#  the shell exit code $? resulting from executing the command.
#  Defaults to "exitvalue stderr stdout $base.trc $base.xyz" for
#  test types "min" and "dyn".  Defaults to "exitvalue structurematch stderr"
#  for test type "struct".
#
# PROGRAM command...
#  This is the complete command line to run (excluding io redirection).
#  Defaults to "/tmp/testsimulator -m -x $base.mmp" for test types "min" and
#  "struct".  Defaults to "/tmp/testsimulator -f100 -t300 -i10 -x $base.mmp"
#  for test type "dyn".
#
# STRUCT file
#  The listed file is compared against the $base.xyz file generated
#  by PROGRAM.  Defaults to "" for test types "min" and "dyn", and
#  no structure comparison is performed.  Defaults to "$base.xyzcmp"
#  for test type "struct".

#
###################################################
#
# NOTE: make sure you specify -x to generate a text
#  file.  Otherwise you'll end up with binary data
#  in your output file for comparison, which is
#  probably not what you wanted.
#
###################################################
#
# A minimizer test using the default command line and results
# can be performed with an empty description file.  The other
# test types can often be performed with just a TYPE directive.
#

TMPDIR=/tmp/runtest$$
DESC=$1
base=`basename $DESC .test`
dir=`dirname $DESC`
here=`pwd`

altout=$here/$dir/$base.altout

DEFAULT_INPUT="$base.mmp"
DEFAULT_OUTPUT_MIN="exitvalue stderr stdout $base.trc $base.xyz"
DEFAULT_OUTPUT_STRUCT="exitvalue structurematch stderr"
DEFAULT_PROGRAM_MIN="/tmp/testsimulator -m -x $base.mmp"
DEFAULT_PROGRAM_DYN="/tmp/testsimulator -f100 -t300 -i10 -x $base.mmp"
DEFAULT_STRUCT_MIN=""
DEFAULT_STRUCT_STRUCT="$base.xyzcmp"

ALT_OUTPUT_FOR_STRUCT="exitvalue structurematch stderr stdout $base.trc $base.xyz"

trap 'rm -rf $TMPDIR' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 24 25 26 27 28 29 30 31

USER_TYPE="min"
while read key value; do
    if [ x$key != x ]; then
	case $key in
	    TYPE)
		USER_TYPE=$value
		;;
	    INPUT)
		USER_INPUT=$value
		;;
	    OUTPUT)
		USER_OUTPUT=$value
		;;
	    PROGRAM)
		USER_PROGRAM=$value
		;;
	    STRUCT)
		USER_STRUCT=$value
		;;
	    \#*) ;;
	    *)
		echo in $DESC: unrecognized line: $key $value
		exit 1
	esac;
    fi
done < $DESC

# Note: this type of processing may not allow the user to set a directive
# to a null value.  Revisit if we need that.
case $USER_TYPE in
    min)
	INPUT=${USER_INPUT:-$DEFAULT_INPUT}
	OUTPUT=${USER_OUTPUT:-$DEFAULT_OUTPUT_MIN}
	PROGRAM=${USER_PROGRAM:-$DEFAULT_PROGRAM_MIN}
	STRUCT=${USER_STRUCT:-$DEFAULT_STRUCT_MIN}
	;;
    struct)
	INPUT=${USER_INPUT:-$DEFAULT_INPUT}
	OUTPUT=${USER_OUTPUT:-$DEFAULT_OUTPUT_STRUCT}
	PROGRAM=${USER_PROGRAM:-$DEFAULT_PROGRAM_MIN}
	STRUCT=${USER_STRUCT:-$DEFAULT_STRUCT_STRUCT}
	;;
    dyn)
	INPUT=${USER_INPUT:-$DEFAULT_INPUT}
	OUTPUT=${USER_OUTPUT:-$DEFAULT_OUTPUT_MIN}
	PROGRAM=${USER_PROGRAM:-$DEFAULT_PROGRAM_DYN}
	STRUCT=${USER_STRUCT:-$DEFAULT_STRUCT_MIN}
	;;
    fail)
	INPUT=""
	OUTPUT=""
	PROGRAM="echo fail"
	STRUCT=""
	;;
    *)
	echo in $DESC: unrecognized TYPE: $TYPE
	exit 1
	;;
esac

DO_GENERATE=false
if [ x$2 = x--generate ]; then
    outxyz=$here/$dir/$STRUCT
    outstd=$here/$dir/$base.out
    DO_GENERATE=true
fi

if [ x$STRUCT != x ]; then
    DO_STRUCT_COMPARE=true
else
    DO_STRUCT_COMPARE=false
fi

rm -rf $TMPDIR
mkdir $TMPDIR
for i in $INPUT; do
    if cp $dir/$i $TMPDIR; then
	true;
    else
	echo failed to copy $dir/$i to $TMPDIR 1>&2;
	exit 1
    fi
done

if $DO_STRUCT_COMPARE; then
    if $DO_GENERATE; then
	true;
    else
	if cp $dir/$STRUCT $TMPDIR; then
	    true;
	else
	    echo failed to copy $dir/$STRUCT to $TMPDIR 1>&2;
	    exit 1
	fi
    fi
fi

echo ======= $base.test ======= > $TMPDIR/results
cat $DESC >> $TMPDIR/results

cd $TMPDIR

$PROGRAM > stdout 2> stderr
echo $? > exitvalue

if $DO_STRUCT_COMPARE; then
    echo == structure comparison == >> stdout
    echo == structure comparison == >> stderr
    if $DO_GENERATE; then
	echo 0 > structurematch
    else
	/tmp/testsimulator -B$base.xyzcmp $base.xyz >> stdout 2>> stderr
	echo $? >> structurematch
    fi
    cp results altoutput
    for i in $ALT_OUTPUT_FOR_STRUCT; do
	echo ======= $i =======
	cat $i
    done | sed '/Date and Time: /d' >> altoutput
    cp altoutput $altout
fi

for i in $OUTPUT; do
	echo ======= $i =======
	cat $i
done | sed '/Date and Time: /d' >> results

if $DO_GENERATE; then
    cp results $outstd
    if $DO_STRUCT_COMPARE; then
	cp $base.xyz $outxyz
    fi
else
    cat results
fi

exit 0
