#! /bin/sh
#
# This file contains support shell routines and steps common to all
# runtests scripts.
#
# Find MPIRUN
#
# Some people don't include "." in their path (! in case an ls trojan horse,
# I guess - if someone does that to you, you have bigger problems).  This
# code tests to see if you have a path to mpirun; if not, it tries ./mpirun.
#
# One particular problem is having multiple mpiruns in the path.  An
# absolute path for mpirun will fix many problems
FindMPIRUN () {
    if [ -z "$MPICH_USE_LIB_MPIRUN" -a ! -x "$mpirun" ] ; then
        IFS="${IFS= 	}"; saveifs="$IFS"; IFS="${IFS}:"
        for dir in $PATH ; do 
            if [ -x $dir/mpirun ] ; then
	        if [ -n "${MPICH_VERSION}" ] ; then
		    # Test that we've found the correct mpirun
		    if strings $dir/mpirun | grep "MPIRUN for MPICH" > /dev/null ; then
		        :
		    else
		        # echo "$dir/mpirun isn't for MPICH"
		        continue
		    fi
	        fi
                mpirun="mpirun"
                break
             fi
        done
        IFS="$saveifs"
    fi
    if [ -z "$mpirun" -a -x "./mpirun" ] ; then
        mpirun=./mpirun
    fi
    #
    if [ -z "$mpirun" ] ; then
        echo "No mpirun in path.  Testing can not proceed."
        exit 1
    fi
}

# MakeExe program-name
MakeExe() {
    if [ -s $STOPFILE ] ; then 
        echo "Found stopfile $STOPFILE; exiting"
	exit 0
    fi
    if [ ! -x $1 ] ; then
	$MAKE $1
        if [ ! -x $1 ] ; then 
	    if [ "$MPITEST_CONTINUE" = "always" ] ; then
	        echo "Could not build executable $1; skipping this test"
	    else 
	        echo "Could not build executable $1; aborting tests"
	        exit 1
	    fi
        fi
    fi
}

# CleanExe program-name
CleanExe() {
    if [ $makeeach = 1 ] ; then
	/bin/rm -f $1 $1.o
    fi
}

# Output marker
OutTime() {
    if [ $quiet = 0 ] ; then
	if [ -z "$hostname" ] ; then
	    hostname=`hostname`
	fi
	d=`date`
	echo "$hostname : $d"
    fi
}

# Do an "on the fly" check for problems.
# Checkout testname difffile
# difffile may be empty, in which case stdout is used.
# If $writesummaryfile is yes, output the results to $summaryfile.
# Use XML-style output for the summary file:
# <MPITEST>
# <NAME NAME="" STATUS="PASS"|"FAIL">
# <WORKDIR>directory</WORKDIR>
# <TESTDIFF>
#    text from different
# </TESTDIFF>
# </MPITEST>
#
# We'd also like to support 
# <NP>$np</NP>
# but we don't have that information when this routine is called
CheckOutput() {
    bfile=$1
    difffile=$2
    fileok="no"
    if [ ! -s ${bfile}.out ] ; then
        echo "No output file ${bfile}.out!"
    else
	cmpfile=""
        # Handle Fortran systems that generate stop statements
        rm -f ${bfile}.tout
	grep -v 'FORTRAN STOP' ${bfile}.out |
	grep -v '^Charm++: scheduler running in netpoll mode.' |
	grep -v '^Charm++> cpu topology info is being gathered.' |
	grep -v '^Charm++> Running on ' > ${bfile}.tout
	for stdfile in $srcdir/${bfile}.std $srcdir/${bfile}.std2 \
			$srcdir/std/${bfile}.std ${bfile}.stdo ; do
	    if [ -z "$cmpfile" -a -s "$stdfile" ] ; then
		cmpfile=$stdfile
	    fi
	    if test -s $stdfile && diff -b ${bfile}.tout $stdfile > /dev/null ; then
		fileok=yes
		break;
	    fi
	done
	if [ $fileok = "no" ] ; then
	    if [ -n "$difffile" ] ; then
   	        if [ -n "$cmpfile" ] ; then
                    echo "Differences in ${bfile}.out" >> ${difffile}
	            diff -bu ${bfile}.tout $cmpfile >> ${difffile}
	        else
                    echo "Cannot find a file to compare against for test ${bfile}.out"
	        fi
	    else
   	        if [ -n "$cmpfile" ] ; then
                    echo "Differences in ${bfile}.out"
	            diff -bu ${bfile}.tout $cmpfile
	        else
                    echo "Cannot find a file to compare against for test ${bfile}.out"
	        fi
            fi
	    nodiff=0
	fi
	if [ "$writesummaryfile" = "yes" ] ; then
	    if [ $fileok = "yes" ] ; then 
	        passed=pass
	    else
		passed=fail
	    fi
	    mydir=`pwd`
	    cat >>$summaryfile <<EOF
<MPITEST>
<NAME>$bfile</NAME>
<WORKDIR>$mydir</WORKDIR>
<STATUS>$passed</STATUS>
EOF
            if [ -n "$np" ] ; then
		echo "<NP>$np</NP>" >> $summaryfile
            fi
	    if [ $fileok = "no" ] ; then
	        echo "<TESTDIFF>" >> $summaryfile
	        if [ ! -s ${bfile}.out ] ; then
	            echo "No output file" >>$summaryfile
	        else
		    if [ -z "$cmpfile" ] ; then 
		        cmpfile="/dev/null"
		    fi
	            diff -b ${bfile}.tout $cmpfile | \
		    sed -e 's/&/-AMP-amp;/g' -e 's/</-AMP-lt;/g' \
			-e 's/>/-AMP-gt;/g' | \
		    sed -e 's/-AMP-/\&/g' >> $summaryfile
	        fi
	        echo "</TESTDIFF>" >> $summaryfile
	    fi
	    if [ -s "$bfile.tbk" ] ; then
	        echo "<TRACEBACK>" >> $summaryfile
		echo "$bfile.tbk" >>$summaryfile
		echo "</TRACEBACK>" >> $summaryfile
	    fi
	    echo "</MPITEST>" >> $summaryfile
	fi
        rm -f ${bfile}.tout
    fi
}

# Runtest pgm-name np marker-test args outfiles
# filename.tbk is a traceback file.  Use a tool like pardump $1 > $1.tbk
# to get such files
RunTest() {
    OutTime
    pgm=$1
    np=$2
    testfiles="$testfiles $pgm.out"
    /bin/rm -f $pgm.out $pgm.tbk
    MakeExe $1
    if [ ! -x $pgm ] ; then
        # If no executable, put the make data into $1.out
        $MAKE $pgm > $pgm.out 2>&1 
    else
        mname=$3
        if [ -z "$mname" ] ; then mname="*** $1 ***" ; fi
        echo "$mname" >> $pgm.out
        echo "$mname"
        mvarg=""
        if [ -n "$5" ] ; then rm -f $5 ; 
            if [ -n "$MPIRUNMVBACK" ] ; then mvarg="$MPIRUNMVBACK \"$5\"" ; fi 
        fi
        # The eval is necessary to ensure that the mvarg value is properly
        # tokenized.  The ./$1 ensures that the program will be found,
        # even if . is not in the PATH.
        
        eval ./charmrun ./$pgm $4 ++local ++quiet +p$np  </dev/null >> $pgm.out 2>&1
        if [ -n "$5" ] ; then 
            for file in $5 ; do 
                if [ -s $file ] ; then 
                    cat $file >> $pgm.out ; rm -f $file 
                fi
            done
        fi
        echo "$mname" >> $pgm.out
        if [ ! -s $srcdir/$pgm.std -a ! -s $pgm.stdo ] ; then
            # We don't need a special file if the output is just "No Errors"
            cat >>$pgm.stdo <<EOF
$mname
 No Errors
$mname
EOF
        fi
        if [ "$CheckOutputWhileRunning" = "yes" -o "$check_at_once" = 1 ] ; then
            CheckOutput $pgm
        fi
        CleanExe $pgm
    #ipcs
    fi
    np=""
}

#
# Check the output of the programs against the "standard" output.  The 
# possible files are:
#   $srcdir/file.std
#   $srcdir/file.std2
#   file.stdo     
# The last one is an automatically generated file for those programs
# that simply produce a " No errors" output.
CheckAllOutput ()
{
    difffile=$1
    /bin/rm -f ${difffile}
    nodiff=1
    for file in $testfiles ; do
	bfile=`basename $file .out`
	CheckOutput $bfile ${difffile}
    done
    if [ -s ${difffile} ] ; then
        cat ${difffile}
    elif [ $nodiff = 1 ] ; then
        echo "-- No differences found; test successful"
    fi
}
