#! /bin/sh
#
# Run some of the tests.  If any arguments are provided, pass them to the
# test programs.
#
# -mvhome is needed for the ANL SP, and is ignored by others
args="-mvhome"
device=ch_gm
if [ "$device" = "ch_p4mpd" ] ; then
    args=""
fi
STOPFILE=$HOME/.stopmpichtests
#
# 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
mpirun="/usr/rels/mpich-1.2..4pre2/bin/mpirun"
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 "" ] ; 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
#
# Here is the location of the MPICH version of mpirun
if [ -z "$mpirun" -a -x ./bin/mpirun ] ; then 
    mpirun="./bin/mpirun"
fi
if [ -z "$mpirun" ] ; then
    echo "No mpirun in path.  Testing can not proceed."
    exit 1
fi
#
# If the programs are not available, run make.
runtests=1
makeeach=0
check_at_once=1
quiet=0
MAKE="make --no-print-directory"
check_canrun=0
# Using shifts should  remove args from the list.
for arg in "$@" ; do
    case $arg in 
	-checkonly)
	shift
	runtests=0
	;;
        -margs=*)
	shift
	margs=`echo $arg | sed 's/-margs=//'`
	args="$args $margs"
	;;
	-echo)
	shift
	set -x
	;;
	-check)
	check_canrun=1
	;;
	-quiet)
	shift
	quiet=1
	;;
	-small)
	shift
	makeeach=1
	;;
	-atend)
	shift
	check_at_once=0
	;;
	-help|-u)
	shift
	echo "runtests [-checkonly] [-margs='...'] [-atend] [-check]"
	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."
	echo "If -atend is used, the success of the tests is checked only"
	echo "at the end of the test rather than also after each test."
	echo "If -check is used, only a single simple test is run; this"
	echo "is used to check that mpirun can run an MPI program."
	exit 1
	;;
	*)
	if test -n "$arg" ; then
	    echo "Passing remaining arguments to programs ($*)"
	    break
        fi
	;;
    esac
done

# MakeExe program-name
MakeExe() {
    if [ -s $STOPFILE ] ; then 
        echo "Found stopfile; exiting"
	exit 0
    fi
    if [ ! -x $1 ] ; then
	$MAKE $1
        if [ ! -x $1 ] ; then 
	    echo "Could not build executable $1; aborting tests"
	    exit 1
        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.
CheckOutput() {
  if [ $check_at_once = 1 ] ; then
    stdfile=/usr/rels/mpich-1.2..4pre2/examples/test/pt2pt/$1.std
    if [ ! -s $1.out ] ; then
        echo "No output file $1.out!"
    elif [ -s $stdfile ] ; then
        stdfile2=${stdfile}2
        if diff -b $1.out $stdfile > /dev/null ; then
	    true
	elif [ -s $stdfile2 ] ; then 
	    # check for alternate in case configuration has fewer datatypes
	    if diff -b $1.out $stdfile2 > /dev/null ; then
	        true
            else
	        echo "Differences in $1.out"
	        diff -b $1.out $stdfile
	        nodiff=0
	    fi
        else
	    echo "Differences in $1.out"
	    diff -b $1.out $stdfile
	fi
    else
        echo "Can not find file $stdfile to compare against for test $1"
    fi
  fi
}

# Runtest pgm-name np marker-test args outfiles
RunTest() {
    OutTime
    testfiles="$testfiles $1.out"
    /bin/rm -f $1.out
    MakeExe $1
    mname=$3
    if [ -z "$mname" ] ; then mname="*** $1 ***" ; fi
    echo "$mname" >> $1.out
    echo "$mname"
    mvarg=""
    if [ -n "$5" ] ; then rm -f $5 ; 
	if [ "$device" != "ch_p4mpd" ] ; then
            if [ -n "-mvback" ] ; then mvarg="-mvback \"$5\"" ;
fi 
	fi
    fi
    # The eval is necessary to ensure that the mvarg value is properly
    # tokenized.
    eval $mpirun $args -np $2 $mvarg $1 $4 </dev/null >> $1.out 2>&1
    if [ -n "$5" ] ; then 
        for file in $5 ; do 
            if [ -s $file ] ; then 
                cat $file >> $1.out ; rm -f $file 
            fi
        done
    fi
    echo "$mname" >> $1.out
    CheckOutput $1
    CleanExe $1
}

# If cannot run test, do that and exit
if [ $check_canrun = 1 ] ; then
    MakeExe third
    /bin/rm -f third.out
    echo '*** Testing Unexpected messages ***' >> third.out
if [ "$device" = "ch_p4mpd" ] ; then
    $mpirun -np 2 third >> third.out
else
    $mpirun $args -np 2 third </dev/null >> third.out 2>&1
fi
    echo '*** Testing Unexpected messages ***' >> third.out
    srcdir=/usr/rels/mpich-1.2..4pre2/examples/test/pt2pt
    if diff -b third.out ${srcdir}/third.std > /dev/null ; then
	rc=0
    else
	echo "Failed to run simple program!"
	echo "Output from run attempt was"
	cat third.out
        echo "mpirun program was $mpirun"
	rc=1
    fi
    CleanExe third
    /bin/rm -f third.out 
    exit $rc
fi

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

testfiles=""
if [ $runtests = 1 ] ; then
echo '**** Testing MPI Point-to-point routines ****'

if [ "$device" != "ch_p4mpd" ] ; then
RunTest sendrecv 2 "**** Testing MPI_Send and MPI_Recv ****" "" "sendrecv-0.out sendrecv-1.out"
fi 

RunTest sendrecv2 2 "**** Testing MPI_Send and MPI_Recv (2) ****"

RunTest sendrecv3 2 "**** Testing MPI_Send and MPI_Recv (3) ****"

RunTest sendrecv4 2 "**** Testing MPI_Send and MPI_Recv (4) ****"

if [ "$device" != "ch_p4mpd" ] ; then
RunTest bsendtest 2 "**** Testing MPI_Bsend and MPI_Recv (4) ****" "" "bsendtest-0.out bsendtest-1.out"
fi 

if [ "$device" != "ch_p4mpd" ] ; then
RunTest isndrcv 2 "**** Testing MPI_Isend and MPI_Irecv ****" "" "isndrcv-0.out isndrcv-1.out"
fi

RunTest irsend 2 "**** Testing MPI_Irsend ****"

RunTest irsendinit 2 "**** Testing MPI_Rsend_init ****"

RunTest longmsgs 2 "**** Testing long messages ****"

RunTest testsome 2 "**** Testing MPI_Testsome/Testany/Waitsome ****"

RunTest testall 2 "**** Testing MPI_Testall ****"

RunTest cancel 2 "**** Checking MPI_Cancel (Irecv's) ****"

RunTest cancel2 2 "**** Checking MPI_Cancel (Persistent Recv's) ****"

if [ "$device" != "ch_gm" ] ; then
RunTest cancel3 2 "**** Checking MPI_Cancel (Persistent Send's) ****"
fi

RunTest cancelmessages 2 "**** Checking MPI_Cancel (short/eager/rndv) ****"

if [ "$device" != "ch_gm" ] ; then
RunTest cancelibm 2 "**** Checking MPI_Cancel (successful/nonsuccessful) ****"
fi

RunTest sndrcv 2 "**** Testing MPI_Sendrecv ****"

RunTest sndrcvrep 2 "**** Testing MPI_Sendrecv_replace ****"

RunTest sndrcvrpl2 2 "**** Testing MPI_Sendrecv_replace (long) ****"

RunTest getelm 2 "**** Testing MPI_Get_elements ****"

if [ "$device" != "ch_p4mpd" ] ; then
RunTest overtake 2 "**** Verifying that messages are non-overtaking ****" "" "overtake-0.out overtake-1.out"
fi

RunTest ssendtest 2 "**** Verifying ssend ****"

RunTest ssendtest2 2 "**** Verifying ssend (2) ****"

RunTest issendtest 2 "**** Verifying Issend ****" "" "issendtest-1.out"

RunTest issend2 2 "**** Verifying Issend (2) ****"

RunTest reqcreate 1 "**** Checking the request creation routines ****"

RunTest reqfree 2 "**** Checking request free ****"

RunTest typebase 1 "**** Checking the type (sizes) routines ****"

RunTest typecreate 1 "**** Checking the type creation routines ****"

if [ "$device" != "ch_p4mpd" ] ; then
RunTest typetest 2 "**** Checking the type routines ****" "" "typetest-0.out typetest-1.out"
fi

RunTest typeub 2 "**** Checking the type routines: MPI_UB ****"

RunTest typeub2 1 "**** Checking the type routines: MPI_UB(2) ****"

RunTest typeub3 1 "**** Checking the type routines: MPI_UB(3) ****"

RunTest dtypelife 2 "**** Checking the type routines: MPI_Type_free ****"

RunTest dataalign 2 "**** Checking the type alignment ****"

RunTest dtyperecv 2 "**** Checking the type recv ****"

RunTest commit 1 "**** Checking the type routines: MPI_Type_commit ****"

RunTest third 2 "*** Testing Unexpected messages ***"

RunTest fourth 4 "*** Testing Irecv/Isend/Wait ***"

RunTest fifth 4 "*** Testing Irecv/Isend/Waitall ***"

RunTest sixth 2 "*** Testing attribute manipulation ***"

RunTest nblock 4 "*** Testing Isend/Irecv (large numbers) ***"

RunTest nbtest 4 "*** Testing Isend/Probe/Recv (large numbers) ***"

RunTest sendmany 8 "*** Testing Send (many procs) ***"

RunTest order 2 "*** Testing Recv ordering ***"

RunTest sendorder 2 "**** Checking Message Ordering ****"

RunTest exittest 3 "**** Checking Exit Processing ****"

RunTest trunc 2 "*** Testing Message truncation ***"

RunTest truncmult 2 '*** Testing Message trunction in multiple completions ***'

RunTest nullproc 2 "*** Testing handling of MPI_PROC_NULL ***"

RunTest relrank 2 "*** Testing handling of relative rank ***"

RunTest hvectest 2 "*** Testing Vector type ***"

RunTest hvectest2 2 "*** Testing struct type for vectors (MPI_UB) ***"

RunTest hvec 2 "*** Testing Type_Hvector ***"

RunTest hindexed 1 "*** Testing Type_Hindexed ***"

RunTest probe 2 "*** Testing Probe and Get_count ***"

RunTest probe1 2 "*** Testing Iprobe and Get_count ***"

RunTest self 1 "*** Testing send to self ***"

RunTest testtest1 2 "*** Testing MPI_Test ***"

RunTest persistent 4 "*** Testing MPI_Recv_init ***"

RunTest persist 4 "*** Testing MPI_Startall/Request_free ***"

RunTest persist2 4 "*** Testing MPI_Startall(Bsend)/Request_free ***"

RunTest waitall 4 "*** Testing MPI_Waitall ***"

RunTest waitall2 2 "*** Testing MPI_Waitall (order) ***"

RunTest waitany 4 "*** Testing MPI_Waitany ***"

RunTest pack 2 "*** Testing MPI_Pack ***"

RunTest flood 2 "**** Testing large messages ****"

#RunTest flood2 2 "**** Testing large numbers of messages ****"
#
# Run Fortran tests ONLY if Fortran available
if [ 1 = 1 ] ; then 
    echo "FORTRAN TESTS"
    #
    #echo "*** secondf ***" >> pt2pt.out
    #$mpirun $args -np 2 secondf "$@" >> pt2pt.out 2>&1
    #
    RunTest allpair 2 "*** Testing pt-2-pt from Fortran ***"

    RunTest allpair2 2 "*** Testing pt-2-pt from Fortran (many calls) ***"
    #
    OutTime
    testfiles="$testfiles structf.out"
    /bin/rm -f structf.out
    MakeExe structf
    echo '*** Testing Type_struct from Fortran ***'
    echo '*** Testing Type_struct from Fortran ***' >> structf.out
    # This is tricky.  Because of a bug in IRIX64, we need to direct 
    # input from /dev/null (so that we can know that we need a new process
    # group).  This should be ok for everyone, but SunOS 4.1.4 tends to
    # panic (!!) in this case.  Since both behaviors represent broken
    # operating systems, we test for ARCH=IRIX64 
    if [ "LINUX" = "IRIX64" ] ; then 
      $mpirun $args -np 2 structf "$@" >> structf.out 2>&1 < /dev/null
    else
      $mpirun $args -np 2 structf "$@" >> structf.out 2>&1
    fi
    echo '*** Testing Type_struct from Fortran ***' >> structf.out
    CheckOutput structf
    CleanExe structf
    #
    RunTest send1 2 "*** Testing pt-2-pt from Fortran (2) ***"
    #
#    testfiles="$testfiles pingpong.out"
#    /bin/rm -f pingpong.out
#    MakeExe pingpong
#    echo '*** Testing pt-2-pt from Fortran (3) ***'
#    echo '*** Testing pt-2-pt from Fortran (3) ***' >> pingpong.out
#    $mpirun $args -np 2 pingpong "$@" >> pingpong.out 2>&1
#    echo '*** Testing pt-2-pt from Fortran (3) ***' >> pingpong.out
#    CheckOutput pingpong
#    CleanExe pingpong
    #
    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 pt2pt.diff
nodiff=1
srcdir=/usr/rels/mpich-1.2..4pre2/examples/test/pt2pt
for file in $testfiles ; do
    stdfile=$srcdir/`basename $file .out`.std
    # if basename is sendrecv or isndrcv, then we may want to test 
    # with .std2 as well.  We should really separate out the long double
    # tests ...
    if [ -s $stdfile ] ; then
	stdfile2=${stdfile}2
        if diff -b $file $stdfile > /dev/null ; then
	    true
	elif [ -s $stdfile2 ] ; then 
	    # check for alternate in case configuration has fewer datatypes
	    if diff -b $file $stdfile2 > /dev/null ; then
	        true
            else
	        echo "Differences in `basename $file .out`" >> pt2pt.diff
	        diff -b $file $stdfile >> pt2pt.diff
	        nodiff=0
	    fi
        else
	    echo "Differences in `basename $file .out`" >> pt2pt.diff
	    diff -b $file $stdfile >> pt2pt.diff
	    nodiff=0
	fi
    else
        echo "Cannot find file $stdfile to compare against for test `basename $file .out`"
	nodiff=0
    fi
done
if [ -s pt2pt.diff ] ; then
   cat pt2pt.diff
elif [ $nodiff = 1 ] ; then
   echo "-- No differences found; test successful"
fi
exit 0

