#!/bin/sh
# This version puts the output from each program into a separate file.
# -mvhome is needed for the ANL SP, and is ignored by others
args="-pg -mvhome"
#
# 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.
IFS="${IFS= 	}"; saveifs="$IFS"; IFS="${IFS}:"
for dir in $PATH ; do 
    if [ -x $dir/mpirun ] ; then
        mpirun="mpirun"
        break
    fi
done
IFS="$saveifs"
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
#
runtests=1
makeeach=0
quiet=0
MAKE="make"
for arg in "$@" ; do
    case $arg in 
	-checkonly )
	runtests=0
	;;
        -margs=*)
	margs=`echo $arg | sed 's/-margs=//'`
	args="$args $margs"
	;;
	-small)
	makeeach=1
	;;
	-quiet)
	shift
	quiet=1
	;;
	-help|-u)
	echo "runtests [-checkonly] [-margs='...']"
	echo "run tests in this directory.  If -checkonly set, just run"
	echo "the differences check (do NO rerun the test programs)."
	echo "If -margs is used, these options are passed to mpirun."
	echo "If -small is used, the examples are built, run, and deleted."
	exit 1
	;;
	*)
	if test -n "$arg" ; then
   	    echo "runtests: Unknown argument ($arg)"
	    exit 1
        fi
	;;
    esac
done

MakeExe() {
    if [ ! -x $1 ] ; then
	$MAKE $1
        if [ ! -x $1 ] ; then 
	    echo "Could not build executable $1; aborting tests"
	    exit 1
        fi
    fi
}
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
}

# If the programs are not available, run make.
if [ ! -x coll1 -a $makeeach = 0 ] ; then
    $MAKE default
fi

testfiles=""
if [ $runtests = 1 ] ; then
echo '**** Testing MPI Collective routines ****'

OutTime
testfiles="$testfiles barrier.out"
/bin/rm -f barrier.out barrier-0.out
MakeExe barrier
echo '*** Barrier Test ***' >> barrier.out
echo '**** Barrier Test ****'
$mpirun $args -np 4 -mvback "barrier-0.out" barrier $* >> barrier.out 2>&1
cat barrier-0.out >> barrier.out
/bin/rm -f barrier-[01234].out
echo '*** Barrier Test ***' >> barrier.out
CleanExe barrier

OutTime
testfiles="$testfiles bcast.out"
/bin/rm -f bcast.out bcast-[0-3].out
MakeExe bcast
echo '**** Broadcast Test ****'
echo '*** Broadcast Test ***' >> bcast.out
$mpirun $args -np 4 \
   -mvback "bcast-0.out bcast-1.out bcast-2.out bcast-3.out" \
	bcast $* >> bcast.out 2>&1
cat bcast-[0123].out >> bcast.out
/bin/rm -f bcast-[0123].out
echo '*** Broadcast Test ***' >> bcast.out
CleanExe bcast

OutTime
testfiles="$testfiles coll1.out"
/bin/rm -f coll1.out
MakeExe coll1
echo '**** coll1 ****'
echo '*** coll1 ***' >> coll1.out
$mpirun $args -np 4 coll1 $* >> coll1.out 2>&1
echo '*** coll1 ***' >> coll1.out
CleanExe coll1

OutTime
testfiles="$testfiles coll2.out"
/bin/rm -f coll2.out
MakeExe coll2
echo '**** coll2 ****'
echo '*** coll2 ***' >> coll2.out
$mpirun $args -np 5 coll2 $* >> coll2.out 2>&1
echo '*** coll2 ***' >> coll2.out
CleanExe coll2

OutTime
testfiles="$testfiles coll3.out"
/bin/rm -f coll3.out
MakeExe coll3
echo '**** coll3 ****'
echo '*** coll3 ***' >> coll3.out
$mpirun $args -np 5 coll3 $* >> coll3.out 2>&1
echo '*** coll3 ***' >> coll3.out
CleanExe coll3

OutTime
testfiles="$testfiles coll4.out"
/bin/rm -f coll4.out
MakeExe coll4
echo '**** coll4 ****'
echo '*** coll4 ***' >> coll4.out
$mpirun $args -np 4 coll4 $* >> coll4.out 2>&1
echo '*** coll4 ***' >> coll4.out
CleanExe coll4

OutTime
testfiles="$testfiles coll5.out"
/bin/rm -f coll5.out
MakeExe coll5
echo '**** coll5 ****'
echo '*** coll5 ***' >> coll5.out
$mpirun $args -np 4 coll5 $* >> coll5.out 2>&1
echo '*** coll5 ***' >> coll5.out
CleanExe coll5

OutTime
testfiles="$testfiles coll6.out"
/bin/rm -f coll6.out
MakeExe coll6
echo '**** coll6 ****'
echo '*** coll6 ***' >> coll6.out
$mpirun $args -np 5 coll6 $* >> coll6.out 2>&1
echo '*** coll6 ***' >> coll6.out
CleanExe coll6

OutTime
testfiles="$testfiles coll7.out"
/bin/rm -f coll7.out
MakeExe coll7
echo '**** coll7 ****'
echo '*** coll7 ***' >> coll7.out
$mpirun $args -np 5 coll7 $* >> coll7.out 2>&1
echo '*** coll7 ***' >> coll7.out
CleanExe coll7

OutTime
testfiles="$testfiles coll8.out"
/bin/rm -f coll8.out
MakeExe coll8
echo '**** coll8 ****'
echo '*** coll8 ***' >> coll8.out
$mpirun $args -np 4 coll8 $* >> coll8.out 2>&1
echo '*** coll8 ***' >> coll8.out
CleanExe coll8

OutTime
testfiles="$testfiles coll9.out"
/bin/rm -f coll9.out
MakeExe coll9
echo '**** coll9 ****'
echo '*** coll9 ***' >> coll9.out
$mpirun $args -np 4 coll9 $* >>  coll9.out 2>&1
echo '*** coll9 ***' >> coll9.out
CleanExe coll9

OutTime
testfiles="$testfiles coll10.out"
/bin/rm -f coll10.out
MakeExe coll10
echo '**** coll10 ****'
echo '*** coll10 ***' >> coll10.out
$mpirun -np 4 $args coll10 $* >> coll10.out 2>&1
echo '*** coll10 ***' >> coll10.out
CleanExe coll10

OutTime
testfiles="$testfiles coll11.out"
/bin/rm -f coll11.out
MakeExe coll11
echo '**** coll11 ****'
echo '*** coll11 ***' >> coll11.out
$mpirun -np 4 $args coll11 $* >> coll11.out 2>&1
echo '*** coll11 ***' >> coll11.out
CleanExe coll11

OutTime
testfiles="$testfiles coll12.out"
/bin/rm -f coll12.out
MakeExe coll12
echo '**** coll12 ****'
echo '*** coll12 ***' >> coll12.out
$mpirun -np 4 $args coll12 $* >> coll12.out 2>&1
echo '*** coll12 ***' >> coll12.out
CleanExe coll12

OutTime
testfiles="$testfiles coll13.out"
/bin/rm -f coll13.out
MakeExe coll13
echo '**** coll13 ****'
echo '*** coll13 ***' >> coll13.out
# coll13 is very picky about arguments
$mpirun -np 4 $args coll13 >> coll13.out 2>&1
echo '*** coll13 ***' >> coll13.out
CleanExe coll13

OutTime
testfiles="$testfiles longuser.out"
/bin/rm -f longuser.out
MakeExe longuser
echo '**** longuser ****'
echo '*** longuser ***' >> longuser.out
$mpirun -np 4 $args longuser >> longuser.out 2>&1
echo '*** longuser ***' >> longuser.out
CleanExe longuser

OutTime
# Some implementations (e.g., IBM's) forget to handle the np = 1 case.
testfiles="$testfiles longuser1.out"
/bin/rm -f longuser1.out
MakeExe longuser
echo '**** longuser (np == 1) ****'
echo '*** longuser (np == 1) ***' >> longuser1.out
$mpirun -np 1 $args longuser >> longuser1.out 2>&1
echo '*** longuser (np == 1) ***' >> longuser1.out
CleanExe longuser

#OutTime
#testfiles="$testfiles allredmany.out"
#/bin/rm -f allredmany.out
#MakeExe allredmany
#echo '**** allredmany ****'
#echo '*** allredmany ***' >> allredmany.out
#cnt=0
## Run several times to try and catch timing/race conditions in managing
## the flood of one-way messages.
#while [ $cnt -lt 20 ] ; do
#    echo "*** allredmany run $cnt ***" >> allredmany.out
#    $mpirun -np 2 $args allredmany >> allredmany.out 2>&1
#    cnt=`expr $cnt + 1`
#done
#echo '*** allredmany ***' >> allredmany.out
#CleanExe allredmany

OutTime
testfiles="$testfiles grouptest.out"
/bin/rm -f grouptest.out
MakeExe grouptest
echo '*** Grouptest ***'
echo '*** grouptest ***' >> grouptest.out
$mpirun $args -np 4 grouptest  $* >> grouptest.out 2>&1
echo '*** grouptest ***' >> grouptest.out
CleanExe grouptest

OutTime
testfiles="$testfiles allred.out"
/bin/rm -f allred.out
MakeExe allred
echo '*** Allred ***'
echo '*** Allred ***' >> allred.out
$mpirun $args -np 4 allred  $* >> allred.out 2>&1
echo '*** Allred ***' >> allred.out
CleanExe allred

OutTime
testfiles="$testfiles scatterv.out"
/bin/rm -f scatterv.out
MakeExe scatterv
echo '*** Scatterv ***'
echo '*** Scatterv ***' >> scatterv.out
$mpirun $args -np 4 scatterv  $* >> scatterv.out 2>&1
echo '*** Scatterv ***' >> scatterv.out
CleanExe scatterv

OutTime
testfiles="$testfiles redscat.out"
/bin/rm -f redscat.out
MakeExe redscat
echo '*** Reduce_scatter ***'
echo '*** Reduce_scatter ***' >> redscat.out
$mpirun $args -np 4 redscat  $* >> redscat.out 2>&1
echo '*** Reduce_scatter ***' >> redscat.out
CleanExe redscat

OutTime
testfiles="$testfiles alltoallv.out"
/bin/rm -f alltoallv.out
MakeExe alltoallv
echo '*** Alltoallv ***'
echo '*** Alltoallv ***' >> alltoallv.out
$mpirun $args -np 4 alltoallv  $* >> alltoallv.out 2>&1
echo '*** Alltoallv ***' >> alltoallv.out
CleanExe alltoallv

#
# Run Fortran tests ONLY if Fortran available
if [ 1 = 1 ] ; then 
    echo "FORTRAN TESTS"
    #
    OutTime
    testfiles="$testfiles allredf.out"
    /bin/rm -f allredf.out
    MakeExe allredf
    echo '*** Testing allreduce from Fortran ***'
    echo '*** Testing allreduce from Fortran ***' >> allredf.out
    $mpirun $args -np 4 allredf "$@" >> allredf.out 2>&1
    echo '*** Testing allreduce from Fortran ***' >> allredf.out
    CleanExe allredf
    #
    OutTime
    testfiles="$testfiles assocf.out"
    /bin/rm -f assocf.out
    MakeExe assocf
    echo '*** Testing allreduce from Fortran (2) ***'
    echo '*** Testing allreduce from Fortran (2) ***' >> assocf.out
    $mpirun $args -np 4 assocf "$@" >> assocf.out 2>&1
    echo '*** Testing allreduce from Fortran (2) ***' >> assocf.out
    CleanExe assocf
    #
    echo "END OF FORTRAN TESTS"
fi

else
    # Just run checks
    testfiles=`echo *.out`
    if test "$testfiles" = "*.out" ; then
	echo "No output files remain from previous test!"
	exit 1
    fi
fi

echo '*** Checking for differences from expected output ***'
/bin/rm -f coll.diff
nodiff=1
for file in $testfiles ; do
    stdfile=`basename $file .out`.std
    if [ -s $stdfile ] ; then
        if diff -b $file `basename $file .out`.std > /dev/null ; then
	    true
  	else
	    echo "Differences in `basename $file .out`" >> coll.diff
	    diff -b $file `basename $file .out`.std >> coll.diff
	    nodiff=0
	fi
    else
        echo "Can not find file $stdfile to compare against for test `basename $file .out`"
    fi
done
if [ -s coll.diff ] ; then
   cat coll.diff
elif [ $nodiff = 1 ] ; then
   echo "-- No differences found; test successful"
fi
exit 0
