Blame test/mpi/runtests.in

Packit Service c5cf8c
#! @PERL@
Packit Service c5cf8c
# -*- Mode: perl; -*-
Packit Service c5cf8c
#
Packit Service c5cf8c
# This script is the beginnings of a script to run a sequence of test 
Packit Service c5cf8c
# programs.  See the MPICH document for a description of the test
Packit Service c5cf8c
# strategy and requirements.
Packit Service c5cf8c
#
Packit Service c5cf8c
# Description
Packit Service c5cf8c
#   Tests are controlled by a file listing test programs; if the file is
Packit Service c5cf8c
#   a directory, then all of the programs in the directory and subdirectories
Packit Service c5cf8c
#   are run
Packit Service c5cf8c
#
Packit Service c5cf8c
#   To run a test, the following steps are executed
Packit Service c5cf8c
#   Build the executable:
Packit Service c5cf8c
#      make programname
Packit Service c5cf8c
#   Run the executable
Packit Service c5cf8c
#      mpiexec -n <np> ./programname >out 2>err
Packit Service c5cf8c
#   Check the return code (non zero is failure)
Packit Service c5cf8c
#   Check the stderr output (non empty is failure)
Packit Service c5cf8c
#   Check the stdout output (No Errors or Test passed are the only valid
Packit Service c5cf8c
#      output)
Packit Service c5cf8c
#   Remove executable, out, err files
Packit Service c5cf8c
#
Packit Service c5cf8c
# The format of a list file is
Packit Service c5cf8c
# programname number-of-processes
Packit Service c5cf8c
# If number-of-processes is missing, $np_default is used (this is 2 but can
Packit Service c5cf8c
# be overridden with -np=new-value)
Packit Service c5cf8c
#
Packit Service c5cf8c
# Special feature:
Packit Service c5cf8c
# Because these tests can take a long time to run, there is an
Packit Service c5cf8c
# option to cause the tests to stop is a "stopfile" is found.
Packit Service c5cf8c
# The stopfile can be created by a separate, watchdog process, to ensure that
Packit Service c5cf8c
# tests end at a certain time.
Packit Service c5cf8c
# The name of this file is (by default) .stoptest
Packit Service c5cf8c
# in the  top-level run directory.  The environment variable
Packit Service c5cf8c
#    MPITEST_STOPTEST
Packit Service c5cf8c
# can specify a different file name.
Packit Service c5cf8c
#
Packit Service c5cf8c
# Import the mkpath command
Packit Service c5cf8c
use File::Path;
Packit Service c5cf8c
use File::Copy qw(move);
Packit Service c5cf8c
Packit Service c5cf8c
# Use high resolution timers
Packit Service c5cf8c
use Time::HiRes qw(gettimeofday tv_interval);
Packit Service c5cf8c
Packit Service c5cf8c
# Global variables
Packit Service c5cf8c
$MPIMajorVersion = "@MPI_VERSION@";
Packit Service c5cf8c
$MPIMinorVersion = "@MPI_SUBVERSION@";
Packit Service c5cf8c
$mpiexec = "@MPIEXEC@";    # Name of mpiexec program (including path, if necessary)
Packit Service c5cf8c
# ppnMax is the maximum number of processes per node.  -1 means ignore.
Packit Service c5cf8c
# ppnArg is the argument to use to mpiexec - format is "string%d"; e.g.,
Packit Service c5cf8c
# "-ppn %d"
Packit Service c5cf8c
$ppnArg  = "";
Packit Service c5cf8c
$ppnMax  = -1;
Packit Service c5cf8c
# timelimitArg is the argument to use to mpiexec to set the timelimit
Packit Service c5cf8c
# in seconds.  The format is "string%d", e.g., "-t %d" for Cray aprun
Packit Service c5cf8c
$timelimitArg="";
Packit Service c5cf8c
#
Packit Service c5cf8c
$testIsStrict = "@MPI_IS_STRICT@";
Packit Service c5cf8c
$MPIhasMPIX   = "@MPI_HAS_MPIX@";
Packit Service c5cf8c
$runxfail     = "@RUN_XFAIL@";
Packit Service c5cf8c
$np_arg  = "-n";         # Name of argument to specify the number of processes
Packit Service c5cf8c
$err_count = 0;          # Number of programs that failed.
Packit Service c5cf8c
$skip_count = 0;         # Number of programs skipped
Packit Service c5cf8c
$total_run = 0;          # Number of programs tested
Packit Service c5cf8c
$total_seen = 0;         # Number of programs considered for testing
Packit Service c5cf8c
$np_default = 2;         # Default number of processes to use
Packit Service c5cf8c
$np_max     = -1;        # Maximum number of processes to use (overrides any
Packit Service c5cf8c
                         # value in the test list files.  -1 is Infinity
Packit Service c5cf8c
$defaultTimeLimit = 180; # default timeout
Packit Service c5cf8c
$defaultTimeLimitMultiplier = 1.0; # default multiplier for timeout limit
Packit Service c5cf8c
Packit Service c5cf8c
$srcdir = ".";           # Used to set the source dir for testlist files
Packit Service c5cf8c
Packit Service c5cf8c
$curdir = ".";           # used to track the relative current directory
Packit Service c5cf8c
Packit Service c5cf8c
# Output forms
Packit Service c5cf8c
$xmloutput = 0;          # Set to true to get xml output (also specify file)
Packit Service c5cf8c
$closeXMLOutput = 1;     # Set to false to leave XML output file open to
Packit Service c5cf8c
                         # accept additional data
Packit Service c5cf8c
$verbose = 0;            # Set to true to get more output
Packit Service c5cf8c
$showProgress = 0;       # Set to true to get a "." with each run program.
Packit Service c5cf8c
$newline = "\r\n";       # Set to \r\n for Windows-friendly, \n for Unix only
Packit Service c5cf8c
$batchRun = 0;           # Set to true to batch the execution of the tests
Packit Service c5cf8c
                         # (i.e., run them together, then test output, 
Packit Service c5cf8c
                         # rather than build/run/check for each test)
Packit Service c5cf8c
$testCount = 0;          # Used with batchRun to count tests.
Packit Service c5cf8c
$batrundir = ".";        # Set to the directory into which to run the examples
Packit Service c5cf8c
Packit Service c5cf8c
# TAP (Test Anything Protocol) output
Packit Service c5cf8c
my $tapoutput = 0;
Packit Service c5cf8c
my $tapfile = '';
Packit Service c5cf8c
my $tapfullfile = '';
Packit Service c5cf8c
Packit Service c5cf8c
# Junit format output
Packit Service c5cf8c
my $junitoutput = 0;
Packit Service c5cf8c
my $junitfile = '';
Packit Service c5cf8c
my $junitfullfile = '';
Packit Service c5cf8c
Packit Service c5cf8c
$debug = 1;
Packit Service c5cf8c
Packit Service c5cf8c
$depth = 0;              # This is used to manage multiple open list files
Packit Service c5cf8c
Packit Service c5cf8c
# Build flags
Packit Service c5cf8c
$remove_this_pgm = 0;
Packit Service c5cf8c
$clean_pgms      = 1;
Packit Service c5cf8c
Packit Service c5cf8c
my $program_wrapper = '';
Packit Service c5cf8c
Packit Service c5cf8c
#---------------------------------------------------------------------------
Packit Service c5cf8c
# Get some arguments from the environment
Packit Service c5cf8c
#   Currently, only the following are understood:
Packit Service c5cf8c
#   VERBOSE
Packit Service c5cf8c
#   RUNTESTS_VERBOSE  (an alias for VERBOSE in case you want to 
Packit Service c5cf8c
#                      reserve VERBOSE)
Packit Service c5cf8c
#   RUNTESTS_SHOWPROGRESS
Packit Service c5cf8c
#   MPITEST_STOPTEST
Packit Service c5cf8c
#   MPITEST_TIMEOUT
Packit Service c5cf8c
#   MPITEST_TIMEOUT_MULTIPLIER
Packit Service c5cf8c
#   MPITEST_PROGRAM_WRAPPER (Value is added after -np but before test
Packit Service c5cf8c
#                            executable.  Tools like valgrind may be inserted
Packit Service c5cf8c
#                            this way.)
Packit Service c5cf8c
#---------------------------------------------------------------------------
Packit Service c5cf8c
if ( defined($ENV{"VERBOSE"}) || defined($ENV{"V"}) || defined($ENV{"RUNTESTS_VERBOSE"}) ) {
Packit Service c5cf8c
    $verbose = 1;
Packit Service c5cf8c
}
Packit Service c5cf8c
if ( defined($ENV{"RUNTESTS_SHOWPROGRESS"} ) ) {
Packit Service c5cf8c
    $showProgress = 1;       
Packit Service c5cf8c
}
Packit Service c5cf8c
if (defined($ENV{"MPITEST_STOPTEST"})) {
Packit Service c5cf8c
    $stopfile = $ENV{"MPITEST_STOPTEST"};
Packit Service c5cf8c
}
Packit Service c5cf8c
else {
Packit Service c5cf8c
    $stopfile = `pwd` . "/.stoptest";
Packit Service c5cf8c
    $stopfile =~ s/\r*\n*//g;    # Remove any newlines (from pwd)
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
if (defined($ENV{"MPITEST_TIMEOUT"})) {
Packit Service c5cf8c
    $defaultTimeLimit = $ENV{"MPITEST_TIMEOUT"};
Packit Service c5cf8c
}
Packit Service c5cf8c
 
Packit Service c5cf8c
if (defined($ENV{"MPITEST_TIMEOUT_MULTIPLIER"})) {
Packit Service c5cf8c
    $defaultTimeLimitMultiplier = $ENV{"MPITEST_TIMEOUT_MULTIPLIER"};
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# Define this to leave the XML output file open to receive additional data
Packit Service c5cf8c
if (defined($ENV{'NOXMLCLOSE'}) && $ENV{'NOXMLCLOSE'} eq 'YES') {
Packit Service c5cf8c
    $closeXMLOutput = 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
if (defined($ENV{'MPITEST_PROGRAM_WRAPPER'})) {
Packit Service c5cf8c
    $program_wrapper = $ENV{'MPITEST_PROGRAM_WRAPPER'};
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
if (defined($ENV{'MPITEST_BATCH'})) {
Packit Service c5cf8c
    if ($ENV{'MPITEST_BATCH'} eq 'YES' || $ENV{'MPITEST_BATCH'} eq 'yes') {
Packit Service c5cf8c
	$batchRun = 1;
Packit Service c5cf8c
    } elsif ($ENV{'MPITEST_BATCH'} eq 'NO' || $ENV{'MPITEST_BATCH'} eq 'no') {
Packit Service c5cf8c
	$batchRun = 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	print STDERR "Unrecognized value for MPITEST_BATCH = $ENV{'MPITEST_BATCH'}\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
if (defined($ENV{'MPITEST_BATCHDIR'})) {
Packit Service c5cf8c
    $batrundir = $ENV{'MPITEST_BATCHDIR'};
Packit Service c5cf8c
}
Packit Service c5cf8c
# PPN support
Packit Service c5cf8c
if (defined($ENV{'MPITEST_PPNARG'})) {
Packit Service c5cf8c
    $ppnArg = $ENV{'MPITEST_PPNARG'};
Packit Service c5cf8c
}
Packit Service c5cf8c
if (defined($ENV{'MPITEST_PPNMAX'})) {
Packit Service c5cf8c
    $ppnMax = $ENV{'MPITEST_PPNMAX'};
Packit Service c5cf8c
}
Packit Service c5cf8c
if (defined($ENV{'MPITEST_TIMELIMITARG'})) {
Packit Service c5cf8c
    $timelimitArg = $ENV{'MPITEST_TIMELIMITARG'};
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# MPI version for testing
Packit Service c5cf8c
if (defined($ENV{'MPITEST_MPIVERSION'})) {
Packit Service c5cf8c
    $_ = $ENV{'MPITEST_MPIVERSION'};
Packit Service c5cf8c
    if (/(\d+)\.(\d+)/) {
Packit Service c5cf8c
        $MPIMajorVersion = $1;
Packit Service c5cf8c
        $MPIMinorVersion = $2;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#---------------------------------------------------------------------------
Packit Service c5cf8c
# Process arguments and override any defaults
Packit Service c5cf8c
#---------------------------------------------------------------------------
Packit Service c5cf8c
foreach $_ (@ARGV) {
Packit Service c5cf8c
    if (/--?mpiexec=(.*)/) { 
Packit Service c5cf8c
	# Use mpiexec as given - it may be in the path, and 
Packit Service c5cf8c
	# we don't want to bother to try and find it.
Packit Service c5cf8c
	$mpiexec = $1; 
Packit Service c5cf8c
    }
Packit Service c5cf8c
    elsif (/--?mpiversion=(\d+)\.(\d+)/) { $MPIMajorVersion = $1;
Packit Service c5cf8c
                                           $MPIMinorVersion = $2; }
Packit Service c5cf8c
    elsif (/--?np=(\d+)/)   { $np_default = $1; }
Packit Service c5cf8c
    elsif (/--?maxnp=(\d+)/) { $np_max = $1; }
Packit Service c5cf8c
    elsif (/--?ppnarg=(.*)/) { $ppnArg = $1; }
Packit Service c5cf8c
    elsif (/--?ppn=(\d+)/)  { $ppnMax = $1; }
Packit Service c5cf8c
    elsif (/--?timelimitarg=(.*)/) { $timelimitArg = $1; }
Packit Service c5cf8c
    elsif (/--?tests=(.*)/) { $listfiles = $1; }
Packit Service c5cf8c
    elsif (/--?srcdir=(.*)/) { $srcdir = $1; }
Packit Service c5cf8c
    elsif (/--?verbose/) { $verbose = 1; }
Packit Service c5cf8c
    elsif (/--?showprogress/) { $showProgress = 1; }
Packit Service c5cf8c
    elsif (/--?debug/) { $debug = 1; }
Packit Service c5cf8c
    elsif (/--?batchdir=(.*)/) { $batrundir = $1; }
Packit Service c5cf8c
    elsif (/--?batch/) { $batchRun = 1; }
Packit Service c5cf8c
    elsif (/--?timeoutarg=(.*)/) { $timeoutArgPattern = $1; }
Packit Service c5cf8c
    elsif (/--?xmlfile=(.*)/) {
Packit Service c5cf8c
	$xmlfile   = $1;
Packit Service c5cf8c
	if (! ($xmlfile =~ /^\//)) {
Packit Service c5cf8c
	    $thisdir = `pwd`;
Packit Service c5cf8c
	    chop $thisdir;
Packit Service c5cf8c
	    $xmlfullfile = $thisdir . "/" . $xmlfile ;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	else {
Packit Service c5cf8c
	    $xmlfullfile = $xmlfile;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	$xmloutput = 1;
Packit Service c5cf8c
	open( XMLOUT, ">$xmlfile" ) || die "Cannot open $xmlfile\n";
Packit Service c5cf8c
	my $date = `date "+%Y-%m-%d-%H-%M"`;
Packit Service c5cf8c
	$date =~ s/\r?\n//;
Packit Service c5cf8c
	# MPISOURCE can be used to describe the source of MPI for this
Packit Service c5cf8c
	# test.
Packit Service c5cf8c
	print XMLOUT "$newline";
Packit Service c5cf8c
	print XMLOUT "$newline";
Packit Service c5cf8c
	print XMLOUT "<MPITESTRESULTS>$newline";
Packit Service c5cf8c
	print XMLOUT "<DATE>$date</DATE>$newline";
Packit Service c5cf8c
	print XMLOUT "<MPISOURCE>@MPI_SOURCE@</MPISOURCE>$newline";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    elsif (/--?noxmlclose/) {
Packit Service c5cf8c
	$closeXMLOutput = 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    elsif (/--?tapfile=(.*)/) {
Packit Service c5cf8c
        $tapfile = $1;
Packit Service c5cf8c
        if ($tapfile !~ m|^/|) {
Packit Service c5cf8c
            $thisdir = `pwd`;
Packit Service c5cf8c
            chomp $thisdir;
Packit Service c5cf8c
            $tapfullfile = $thisdir . "/" . $tapfile ;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        else {
Packit Service c5cf8c
            $tapfullfile = $tapfile;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        $tapoutput = 1;
Packit Service c5cf8c
        open( TAPOUT, ">$tapfile" ) || die "Cannot open $tapfile\n";
Packit Service c5cf8c
        my $date = `date "+%Y-%m-%d-%H-%M"`;
Packit Service c5cf8c
        $date =~ s/\r?\n//;
Packit Service c5cf8c
        print TAPOUT "TAP version 13\n";
Packit Service c5cf8c
        print TAPOUT "# MPICH test suite results (TAP format)\n";
Packit Service c5cf8c
        print TAPOUT "# date ${date}\n";
Packit Service c5cf8c
        # we do not know at this point how many tests will be run, so do
Packit Service c5cf8c
        # not print a test plan line like "1..450" until the very end
Packit Service c5cf8c
    }
Packit Service c5cf8c
    elsif (/--?junitfile=(.*)/) {
Packit Service c5cf8c
        $junitfile = $1;
Packit Service c5cf8c
        if ($junitfile !~ m|^/|) {
Packit Service c5cf8c
            $thisdir = `pwd`;
Packit Service c5cf8c
            chomp $thisdir;
Packit Service c5cf8c
            $junitfullfile = $thisdir . "/" . $junitfile ;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        else {
Packit Service c5cf8c
            $junitfullfile = $junitfile;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        $junitoutput = 1;
Packit Service c5cf8c
        open( JUNITOUT, ">$junitfile" ) || die "Cannot open $junitfile\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	print STDERR "Unrecognized argument $_\n";
Packit Service c5cf8c
	print STDERR "runtests [-tests=testfile] [-np=nprocesses] \
Packit Service c5cf8c
        [-maxnp=max-nprocesses] [-srcdir=location-of-tests] \
Packit Service c5cf8c
        [-ppn=max-proc-per-node] [-ppnarg=string] \
Packit Service c5cf8c
        [-timelimitarg=string] [-mpiversion=major.minor] \
Packit Service c5cf8c
        [-xmlfile=filename ] [-tapfile=filename ] \
Packit Service c5cf8c
        [-junitfile=filename ] [-noxmlclose] \
Packit Service c5cf8c
        [-verbose] [-showprogress] [-debug] [-batch]\n";
Packit Service c5cf8c
	exit(1);
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# Perform any post argument processing
Packit Service c5cf8c
if ($batchRun) {
Packit Service c5cf8c
    if (! -d $batrundir) {
Packit Service c5cf8c
	mkpath $batrundir || die "Could not create $batrundir\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    open( BATOUT, ">$batrundir/runtests.batch" ) || die "Could not open $batrundir/runtests.batch\n";
Packit Service c5cf8c
}
Packit Service c5cf8c
else {
Packit Service c5cf8c
    # We must have mpiexec
Packit Service c5cf8c
    if ("$mpiexec" eq "") {
Packit Service c5cf8c
	print STDERR "No mpiexec found!\n";
Packit Service c5cf8c
	exit(1);
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#
Packit Service c5cf8c
# Process any files
Packit Service c5cf8c
if ($listfiles eq "") {
Packit Service c5cf8c
    if ($batchRun) {
Packit Service c5cf8c
	print STDERR "An implicit list of tests is not permitted in batch mode. See README for more details\n";
Packit Service c5cf8c
	exit(1);
Packit Service c5cf8c
    } 
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	&ProcessImplicitList;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
elsif (-d $listfiles) { 
Packit Service c5cf8c
    print STDERR "Testing by directories not yet supported\n";
Packit Service c5cf8c
}
Packit Service c5cf8c
else {
Packit Service c5cf8c
    &RunList( $listfiles );
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
if ($xmloutput && $closeXMLOutput) { 
Packit Service c5cf8c
    print XMLOUT "</MPITESTRESULTS>$newline";
Packit Service c5cf8c
    close XMLOUT; 
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
if ($tapoutput) {
Packit Service c5cf8c
    print TAPOUT "1..$total_seen\n";
Packit Service c5cf8c
    close TAPOUT;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
if ($junitoutput) {
Packit Service c5cf8c
    print JUNITOUT "    <system-out></system-out>\n";
Packit Service c5cf8c
    print JUNITOUT "    <system-err></system-err>\n";
Packit Service c5cf8c
    print JUNITOUT "  </testsuite>\n";
Packit Service c5cf8c
    print JUNITOUT "</testsuites>\n";
Packit Service c5cf8c
    close JUNITOUT;
Packit Service c5cf8c
Packit Service c5cf8c
    # the second pass: insert the header
Packit Service c5cf8c
    # Note: the field "errors" is not used now, but reserved for future uses.
Packit Service c5cf8c
    open my $JUNITIN,  '<',  $junitfile      or die "Can't read old file: $!";
Packit Service c5cf8c
    open my $JUNITOUTNEW, '>', "$junitfile.new" or die "Can't write new file: $!";
Packit Service c5cf8c
    my $date = `date "+%Y-%m-%d-%H-%M"`;
Packit Service c5cf8c
    $date =~ s/\r?\n//;
Packit Service c5cf8c
    print $JUNITOUTNEW "<testsuites>\n";
Packit Service c5cf8c
    print $JUNITOUTNEW "  
Packit Service c5cf8c
    print $JUNITOUTNEW "             errors=\"0\"\n";
Packit Service c5cf8c
    print $JUNITOUTNEW "             skipped=\"$skip_count\"\n";
Packit Service c5cf8c
    print $JUNITOUTNEW "             tests=\"$total_run\"\n";
Packit Service c5cf8c
    print $JUNITOUTNEW "             date=\"${date}\"\n";
Packit Service c5cf8c
    print $JUNITOUTNEW "             name=\"summary_junit_xml\">\n";
Packit Service c5cf8c
    while( <$JUNITIN> ) {
Packit Service c5cf8c
        print $JUNITOUTNEW $_;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    close $JUNITIN;
Packit Service c5cf8c
    close $JUNITOUTNEW;
Packit Service c5cf8c
    move("$junitfile.new","$junitfile");
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# Output a summary:
Packit Service c5cf8c
if ($batchRun) {
Packit Service c5cf8c
    print "Programs created along with a runtest.batch file in $batrundir\n";
Packit Service c5cf8c
    print "Run that script and then use checktests to summarize the results\n";
Packit Service c5cf8c
}
Packit Service c5cf8c
else {
Packit Service c5cf8c
    if ($err_count) {
Packit Service c5cf8c
	print "$err_count tests failed out of $total_run\n";
Packit Service c5cf8c
	if ($xmloutput) {
Packit Service c5cf8c
	    print "Details in $xmlfullfile\n";
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	print " All $total_run tests passed!\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($tapoutput) {
Packit Service c5cf8c
        print "TAP formatted results in $tapfullfile\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($junitoutput) {
Packit Service c5cf8c
        print "JUNIT formatted results in $junitfullfile\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
#
Packit Service c5cf8c
# ---------------------------------------------------------------------------
Packit Service c5cf8c
# Routines
Packit Service c5cf8c
# 
Packit Service c5cf8c
# Enter a new directory and process a list file.  
Packit Service c5cf8c
#  ProcessDir( directory-name, list-file-name )
Packit Service c5cf8c
sub ProcessDir {
Packit Service c5cf8c
    my $dir = $_[0]; $dir =~ s/\/$//;
Packit Service c5cf8c
    my $listfile = $_[1];
Packit Service c5cf8c
    my $savedir = `pwd`;
Packit Service c5cf8c
    my $savecurdir = $curdir;
Packit Service c5cf8c
    my $savesrcdir = $srcdir;
Packit Service c5cf8c
Packit Service c5cf8c
    chop $savedir;
Packit Service c5cf8c
    if (substr($srcdir,0,3) eq "../") {
Packit Service c5cf8c
      $srcdir = "../$srcdir";
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    print "Processing directory $dir\n" if ($verbose || $debug);
Packit Service c5cf8c
    chdir $dir;
Packit Service c5cf8c
    if ($dir =~ /\//) {
Packit Service c5cf8c
	print STDERR "only direct subdirectories allowed in list files";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    $curdir .= "/$dir";
Packit Service c5cf8c
Packit Service c5cf8c
    &RunList( $listfile );
Packit Service c5cf8c
    print "\n" if $showProgress; # Terminate line from progress output
Packit Service c5cf8c
    chdir $savedir;
Packit Service c5cf8c
    $curdir = $savecurdir;
Packit Service c5cf8c
    $srcdir = $savesrcdir;
Packit Service c5cf8c
}
Packit Service c5cf8c
# ---------------------------------------------------------------------------
Packit Service c5cf8c
# Run the programs listed in the file given as the argument. 
Packit Service c5cf8c
# This file describes the tests in the format
Packit Service c5cf8c
#  programname number-of-processes [ key=value ... ]
Packit Service c5cf8c
# If the second value is not given, the default value is used.
Packit Service c5cf8c
# 
Packit Service c5cf8c
sub RunList { 
Packit Service c5cf8c
    my $LIST = "LIST$depth"; $depth++;
Packit Service c5cf8c
    my $listfile = $_[0];
Packit Service c5cf8c
    my $ResultTest = "";
Packit Service c5cf8c
    my $InitForRun = "";
Packit Service c5cf8c
    my $listfileSource = $listfile;
Packit Service c5cf8c
    my @TYPES = "";
Packit Service c5cf8c
    my $DTP_SWITCH = "@DTP_SWITCH@";
Packit Service c5cf8c
Packit Service c5cf8c
    if (! defined $ENV{"DTP_NUM_OBJS"}) {
Packit Service c5cf8c
        $ENV{"DTP_NUM_OBJS"} = "5";
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (! defined $ENV{"DTP_RUNTIME_TYPES"}) {
Packit Service c5cf8c
        @TYPES = split ' ', "MPI_INT MPI_DOUBLE";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
        @TYPES = split ' ', $ENV{"DTP_RUNTIME_TYPES"};
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    print "Looking in $curdir/$listfile\n" if $debug;
Packit Service c5cf8c
    if (! -s "$listfile" && -s "$srcdir/$curdir/$listfile" ) {
Packit Service c5cf8c
	$listfileSource = "$srcdir/$curdir/$listfile";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    open( $LIST, "<$listfileSource" ) || 
Packit Service c5cf8c
	die "Could not open $listfileSource\n";
Packit Service c5cf8c
    while (<$LIST>) {
Packit Service c5cf8c
	# Check for stop file
Packit Service c5cf8c
	if (-s $stopfile) {
Packit Service c5cf8c
	    # Exit because we found a stopfile
Packit Service c5cf8c
	    print STDERR "Terminating test because stopfile $stopfile found\n";
Packit Service c5cf8c
	    last;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	# Skip comments
Packit Service c5cf8c
	s/#.*//g;
Packit Service c5cf8c
	# Remove any trailing newlines/returns
Packit Service c5cf8c
	s/\r?\n//;
Packit Service c5cf8c
        # Remove any leading whitespace
Packit Service c5cf8c
        s/^\s*//;
Packit Service c5cf8c
	# Some tests require that support routines are built first
Packit Service c5cf8c
	# This is specified with !<dir>:<target>
Packit Service c5cf8c
	if (/^\s*\!([^:]*):(.*)/) {
Packit Service c5cf8c
	    # Hack: just execute in a subshell.  This discards any 
Packit Service c5cf8c
	    # output.
Packit Service c5cf8c
	    `cd $1 && make $2`;
Packit Service c5cf8c
	    next;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	# List file entries have the form:
Packit Service c5cf8c
	# program [ np [ name=value ... ] ]
Packit Service c5cf8c
	# See files errhan/testlist, init/testlist, and spawn/testlist
Packit Service c5cf8c
	# for examples of using the key=value form
Packit Service c5cf8c
	my @args = split(/\s+/,$_);
Packit Service c5cf8c
	my $programname = $args[0];
Packit Service c5cf8c
	my $np = "";
Packit Service c5cf8c
	my $ResultTest = "";
Packit Service c5cf8c
	my $InitForRun = "";
Packit Service c5cf8c
	my $timeLimit  = "";
Packit Service c5cf8c
	my $progArgs   = "";
Packit Service c5cf8c
	my $mpiexecArgs = "";
Packit Service c5cf8c
	my $requiresStrict = "";
Packit Service c5cf8c
	my $requiresMPIX   = "";
Packit Service c5cf8c
	my $progEnv    = "";
Packit Service c5cf8c
	my $mpiVersion = "";
Packit Service c5cf8c
        my $xfail = "";
Packit Service c5cf8c
    my $dtp_match_type = 0;
Packit Service c5cf8c
    my $dtp_test_type = "";    # this test type
Packit Service c5cf8c
    # get the type of this test
Packit Service c5cf8c
    if ($programname =~ /BASIC/) {
Packit Service c5cf8c
        $dtp_test_type = "BASIC";
Packit Service c5cf8c
    } elsif ($programname =~ /STRUCT/) {
Packit Service c5cf8c
        $dtp_test_type = "STRUCT";
Packit Service c5cf8c
    }
Packit Service c5cf8c
	if ($#args >= 1) { $np = $args[1]; }
Packit Service c5cf8c
	# Process the key=value arguments
Packit Service c5cf8c
	for (my $i=2; $i <= $#args; $i++) {
Packit Service c5cf8c
	    if ($args[$i] =~ /([^=]+)=(.*)/) {
Packit Service c5cf8c
		my $key = $1;
Packit Service c5cf8c
		my $value = $2;
Packit Service c5cf8c
		if ($key eq "resultTest") {
Packit Service c5cf8c
		    $ResultTest = $value;
Packit Service c5cf8c
		}
Packit Service c5cf8c
		elsif ($key eq "init") {
Packit Service c5cf8c
		    $InitForRun = $value;
Packit Service c5cf8c
		}
Packit Service c5cf8c
		elsif ($key eq "timeLimit") {
Packit Service c5cf8c
		    $timeLimit = $value;
Packit Service c5cf8c
		}
Packit Service c5cf8c
		elsif ($key eq "arg") {
Packit Service c5cf8c
            # match allowed datatypes here
Packit Service c5cf8c
            for my $j (@TYPES) {
Packit Service c5cf8c
                if ($value eq "-type=$j") {
Packit Service c5cf8c
                    $dtp_match_type=1;
Packit Service c5cf8c
                    break;
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            $progArgs = "$progArgs $value";
Packit Service c5cf8c
        }
Packit Service c5cf8c
		elsif ($key eq "mpiexecarg") {
Packit Service c5cf8c
		    $mpiexecArgs = "$mpiexecArgs $value";
Packit Service c5cf8c
		}
Packit Service c5cf8c
		elsif ($key eq "env") {
Packit Service c5cf8c
		    if ($progEnv eq "") {
Packit Service c5cf8c
			$progEnv = "$value";
Packit Service c5cf8c
		    }
Packit Service c5cf8c
		    else {
Packit Service c5cf8c
			$progEnv = "$progEnv $value";
Packit Service c5cf8c
		    }
Packit Service c5cf8c
		}
Packit Service c5cf8c
		elsif ($key eq "mpiversion") {
Packit Service c5cf8c
		    $mpiVersion = $value;
Packit Service c5cf8c
		}
Packit Service c5cf8c
		elsif ($key eq "strict") {
Packit Service c5cf8c
		    $requiresStrict = $value
Packit Service c5cf8c
		}
Packit Service c5cf8c
		elsif ($key eq "mpix") {
Packit Service c5cf8c
		    $requiresMPIX = $value
Packit Service c5cf8c
		}
Packit Service c5cf8c
                elsif ($key eq "xfail") {
Packit Service c5cf8c
                    if ($value eq "") {
Packit Service c5cf8c
                        print STDERR "\"xfail=\" requires an argument\n";
Packit Service c5cf8c
                    }
Packit Service c5cf8c
                    $xfail = $value;
Packit Service c5cf8c
                }
Packit Service c5cf8c
		else {
Packit Service c5cf8c
		    print STDERR "Unrecognized key $key in $listfileSource\n";
Packit Service c5cf8c
		}
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
Packit Service c5cf8c
    if ($DTP_SWITCH eq "ON") {
Packit Service c5cf8c
        # if dtpools tests are ON only run matching types for basic tests
Packit Service c5cf8c
        if ($dtp_test_type eq "BASIC" && $dtp_match_type == 0) {
Packit Service c5cf8c
            $programname = "";
Packit Service c5cf8c
        }
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        # if dtpools tests are OFF only disable dtpools tests, run the rest
Packit Service c5cf8c
        if ($dtp_test_type eq "BASIC" || $dtp_test_type eq "STRUCT") {
Packit Service c5cf8c
            $programname = "";
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
	# skip empty lines
Packit Service c5cf8c
	if ($programname eq "") { next; }
Packit Service c5cf8c
Packit Service c5cf8c
	if ($np eq "") { $np = $np_default; }
Packit Service c5cf8c
	if ($np_max > 0 && $np > $np_max) { $np = $np_max; }
Packit Service c5cf8c
Packit Service c5cf8c
        # allows us to accurately output TAP test numbers without disturbing the
Packit Service c5cf8c
        # original totals that have traditionally been reported
Packit Service c5cf8c
        #
Packit Service c5cf8c
        # These "unless" blocks are ugly, but permit us to honor skipping
Packit Service c5cf8c
        # criteria for directories as well without counting directories as tests
Packit Service c5cf8c
        # in our XML/TAP output.
Packit Service c5cf8c
        unless (-d $programname) {
Packit Service c5cf8c
            $total_seen++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
	# If a minimum MPI version is specified, check against the
Packit Service c5cf8c
	# available MPI.  If the version is unknown, we ignore this
Packit Service c5cf8c
	# test (thus, all tests will be run).  
Packit Service c5cf8c
	if ($mpiVersion ne "" && $MPIMajorVersion ne "unknown" &&
Packit Service c5cf8c
	    $MPIMinorVersion ne "unknown") {
Packit Service c5cf8c
	    my ($majorReq,$minorReq) = split(/\./,$mpiVersion);
Packit Service c5cf8c
            if ($majorReq > $MPIMajorVersion or
Packit Service c5cf8c
                ($majorReq == $MPIMajorVersion && $minorReq > $MPIMinorVersion))
Packit Service c5cf8c
            {
Packit Service c5cf8c
                unless (-d $programname) {
Packit Service c5cf8c
                    SkippedTest($programname, $np, $progArgs, $progEnv, $curdir, "requires MPI version $mpiVersion");
Packit Service c5cf8c
                }
Packit Service c5cf8c
                next;
Packit Service c5cf8c
            }
Packit Service c5cf8c
	}
Packit Service c5cf8c
	# Check whether strict is required by MPI but not by the
Packit Service c5cf8c
	# test (use strict=false for tests that use non-standard extensions)
Packit Service c5cf8c
        if (lc($requiresStrict) eq "false" && lc($testIsStrict) eq "true") {
Packit Service c5cf8c
            unless (-d $programname) {
Packit Service c5cf8c
                SkippedTest($programname, $np, $progArgs, $progEnv, $curdir, "non-strict test, strict MPI mode requested");
Packit Service c5cf8c
            }
Packit Service c5cf8c
            next;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        if (lc($testIsStrict) eq "true") {
Packit Service c5cf8c
            # Strict MPI testing was requested, so assume that a non-MPICH MPI
Packit Service c5cf8c
            # implementation is being tested and the "xfail" implementation
Packit Service c5cf8c
            # assumptions do not hold.
Packit Service c5cf8c
            $xfail = '';
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
	if ($xfail ne '' && $runxfail eq "false") {
Packit Service c5cf8c
	    # Skip xfail tests if they are not configured. Strict MPI tests that are
Packit Service c5cf8c
	    # marked xfail will still run with --enable-strictmpi.
Packit Service c5cf8c
            unless (-d $programname) {
Packit Service c5cf8c
                SkippedTest($programname, $np, $progArgs, $progEnv, $curdir, "xfail tests disabled");
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    next;
Packit Service c5cf8c
	}
Packit Service c5cf8c
Packit Service c5cf8c
        if (lc($requiresMPIX) eq "true" && lc($MPIHasMPIX) eq "no") {
Packit Service c5cf8c
            unless (-d $programname) {
Packit Service c5cf8c
                SkippedTest($programname, $np, $progArgs, $progEnv, $curdir, "tests MPIX extensions, MPIX testing disabled");
Packit Service c5cf8c
            }
Packit Service c5cf8c
            next;
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
	if (-d $programname) {
Packit Service c5cf8c
	    # If a directory, go into the that directory and 
Packit Service c5cf8c
	    # look for a new list file
Packit Service c5cf8c
	    &ProcessDir( $programname, $listfile );
Packit Service c5cf8c
	}
Packit Service c5cf8c
	else {
Packit Service c5cf8c
	    $total_run++;
Packit Service c5cf8c
	    if (&BuildMPIProgram( $programname, $xfail ) == 0) {
Packit Service c5cf8c
		if ($batchRun == 1) {
Packit Service c5cf8c
		    &AddMPIProgram( $programname, $np, $ResultTest, 
Packit Service c5cf8c
				    $InitForRun, $timeLimit, $progArgs,
Packit Service c5cf8c
				    $progEnv, $mpiexecArgs, $xfail );
Packit Service c5cf8c
		}
Packit Service c5cf8c
		else {
Packit Service c5cf8c
		    &RunMPIProgram( $programname, $np, $ResultTest, 
Packit Service c5cf8c
				    $InitForRun, $timeLimit, $progArgs, 
Packit Service c5cf8c
				    $progEnv, $mpiexecArgs, $xfail );
Packit Service c5cf8c
		}
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    elsif ($xfail eq '') {
Packit Service c5cf8c
		# We expected to run this program, so failure to build
Packit Service c5cf8c
		# is an error
Packit Service c5cf8c
		$found_error = 1;
Packit Service c5cf8c
		$err_count++;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if ($batchRun == 0) {
Packit Service c5cf8c
		&CleanUpAfterRun( $programname );
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    close( $LIST );
Packit Service c5cf8c
}
Packit Service c5cf8c
#
Packit Service c5cf8c
# This routine tries to run all of the files in the current
Packit Service c5cf8c
# directory
Packit Service c5cf8c
sub ProcessImplicitList {
Packit Service c5cf8c
    # The default is to run every file in the current directory.
Packit Service c5cf8c
    # If there are no built programs, build and run every file
Packit Service c5cf8c
    # WARNING: This assumes that anything executable should be run as
Packit Service c5cf8c
    # an MPI test.
Packit Service c5cf8c
    $found_exec = 0;
Packit Service c5cf8c
    $found_src  = 0;
Packit Service c5cf8c
    open (PGMS, "ls -1 |" ) || die "Cannot list directory\n";
Packit Service c5cf8c
    while (<PGMS>) {
Packit Service c5cf8c
	s/\r?\n//;
Packit Service c5cf8c
	$programname = $_;
Packit Service c5cf8c
	if (-d $programname) { next; }  # Ignore directories
Packit Service c5cf8c
	if ($programname eq "runtests") { next; } # Ignore self
Packit Service c5cf8c
	if ($programname eq "checktests") { next; } # Ignore helper
Packit Service c5cf8c
	if ($programname eq "configure") { next; } # Ignore configure script
Packit Service c5cf8c
	if ($programname eq "config.status") { next; } # Ignore configure helper
Packit Service c5cf8c
	if (-x $programname) { $found_exec++; }
Packit Service c5cf8c
	if ($programname =~ /\.[cf]$/) { $found_src++; } 
Packit Service c5cf8c
    }
Packit Service c5cf8c
    close PGMS;
Packit Service c5cf8c
    
Packit Service c5cf8c
    if ($found_exec) {
Packit Service c5cf8c
	print "Found executables\n" if $debug;
Packit Service c5cf8c
	open (PGMS, "ls -1 |" ) || die "Cannot list programs\n";
Packit Service c5cf8c
	while (<PGMS>) {
Packit Service c5cf8c
	    # Check for stop file
Packit Service c5cf8c
	    if (-s $stopfile) {
Packit Service c5cf8c
		# Exit because we found a stopfile
Packit Service c5cf8c
		print STDERR "Terminating test because stopfile $stopfile found\n";
Packit Service c5cf8c
		last;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    s/\r?\n//;
Packit Service c5cf8c
	    $programname = $_;
Packit Service c5cf8c
	    if (-d $programname) { next; }  # Ignore directories
Packit Service c5cf8c
	    if ($programname eq "runtests") { next; } # Ignore self
Packit Service c5cf8c
	    if (-x $programname) {
Packit Service c5cf8c
		$total_run++;
Packit Service c5cf8c
		&RunMPIProgram( $programname, $np_default, "", "", "", "", "", "", "" );
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
	close PGMS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    elsif ($found_src) { 
Packit Service c5cf8c
	print "Found source files\n" if $debug;
Packit Service c5cf8c
	open (PGMS, "ls -1 *.c |" ) || die "Cannot list programs\n";
Packit Service c5cf8c
	while (<PGMS>) {
Packit Service c5cf8c
	    if (-s $stopfile) {
Packit Service c5cf8c
		# Exit because we found a stopfile
Packit Service c5cf8c
		print STDERR "Terminating test because stopfile $stopfile found\n";
Packit Service c5cf8c
		last;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    s/\r?\n//;
Packit Service c5cf8c
	    $programname = $_;
Packit Service c5cf8c
	    # Skip messages from ls about no files
Packit Service c5cf8c
	    if (! -s $programname) { next; }
Packit Service c5cf8c
	    $programname =~ s/\.c//;
Packit Service c5cf8c
	    $total_run++;
Packit Service c5cf8c
	    if (&BuildMPIProgram( $programname, "") == 0) {
Packit Service c5cf8c
		&RunMPIProgram( $programname, $np_default, "", "", "", "", "", "", "" );
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    else {
Packit Service c5cf8c
		# We expected to run this program, so failure to build
Packit Service c5cf8c
		# is an error
Packit Service c5cf8c
		$found_error = 1;
Packit Service c5cf8c
		$err_count++;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    &CleanUpAfterRun( $programname );
Packit Service c5cf8c
	}
Packit Service c5cf8c
	close PGMS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
# Run the program.  
Packit Service c5cf8c
# ToDo: Add a way to limit the time that any particular program may run.
Packit Service c5cf8c
# The arguments are
Packit Service c5cf8c
#    name of program, number of processes, name of routine to check results
Packit Service c5cf8c
#    init for testing, timelimit, and any additional program arguments
Packit Service c5cf8c
# If the 3rd arg is not present, the a default that simply checks that the
Packit Service c5cf8c
# return status is 0 and that the output is " No Errors" is used.
Packit Service c5cf8c
sub RunMPIProgram {
Packit Service c5cf8c
    my ($programname,$np,$ResultTest,$InitForTest,$timeLimit,$progArgs,$progEnv,$mpiexecArgs,$xfail) = @_;
Packit Service c5cf8c
    my $found_error   = 0;
Packit Service c5cf8c
    my $found_noerror = 0;
Packit Service c5cf8c
    my $inline = "";
Packit Service c5cf8c
    my $extraArgs = "";
Packit Service c5cf8c
    my $runtime = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    &RunPreMsg( $programname, $np, $curdir );
Packit Service c5cf8c
Packit Service c5cf8c
    unlink "err";
Packit Service c5cf8c
Packit Service c5cf8c
    # Set a default timeout on tests (3 minutes for now)
Packit Service c5cf8c
    my $timeout = $defaultTimeLimit;
Packit Service c5cf8c
    if (defined($timeLimit) && $timeLimit =~ /^\d+$/) {
Packit Service c5cf8c
	$timeout = $timeLimit;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    $timeout *= $defaultTimeLimitMultiplier;
Packit Service c5cf8c
    $ENV{"MPIEXEC_TIMEOUT"} = $timeout;
Packit Service c5cf8c
Packit Service c5cf8c
    # Handle the ppn (processes per node) option.
Packit Service c5cf8c
    $ppnargs = "";
Packit Service c5cf8c
    if ($ppnArg ne "" && $ppnMax > 0) {
Packit Service c5cf8c
	$ppnargs = $ppnArg;
Packit Service c5cf8c
	$nn = $ppnMax;
Packit Service c5cf8c
	# Some systems require setting the number of processes per node
Packit Service c5cf8c
	# no greater than the total number of processes (e.g., aprun on Cray)
Packit Service c5cf8c
	if ($nn > $np) { $nn = $np; }
Packit Service c5cf8c
	$ppnargs =~ s/\%d/$nn/;
Packit Service c5cf8c
	$extraArgs .= " " . $ppnargs;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    # Handle the timelimit option.
Packit Service c5cf8c
    if ($timelimitArg ne "" && $timeout> 0) {
Packit Service c5cf8c
        $tlargs = "";
Packit Service c5cf8c
	$tlargs = $timelimitArg;
Packit Service c5cf8c
	$tlargs =~ s/\%d/$timeout/;
Packit Service c5cf8c
	$extraArgs .= " " . $tlargs;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    # Run the optional setup routine. For example, the timeout tests could
Packit Service c5cf8c
    # be set to a shorter timeout.
Packit Service c5cf8c
    if ($InitForTest ne "") {
Packit Service c5cf8c
	&$InitForTest();
Packit Service c5cf8c
    }
Packit Service c5cf8c
    print STDOUT "Env includes $progEnv\n" if $verbose;
Packit Service c5cf8c
    print STDOUT "$mpiexec $np_arg $np $extraArgs $mpiexecArgs $program_wrapper ./$programname $progArgs\n" if $verbose;
Packit Service c5cf8c
    print STDOUT "." if $showProgress;
Packit Service c5cf8c
    # Save and restore the environment if necessary before running mpiexec.
Packit Service c5cf8c
    if ($progEnv ne "") {
Packit Service c5cf8c
	%saveEnv = %ENV;
Packit Service c5cf8c
	foreach $val (split(/\s+/, $progEnv)) {
Packit Service c5cf8c
	    if ($val =~ /([^=]+)=(.*)/) {
Packit Service c5cf8c
		$ENV{$1} = $2;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    else {
Packit Service c5cf8c
		print STDERR "Environment variable/value $val not in a=b form\n";
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    my $start_time = gettimeofday();
Packit Service c5cf8c
    open ( MPIOUT, "$mpiexec $np_arg $np $extraArgs $mpiexecArgs $program_wrapper ./$programname $progArgs 2>&1 |" ) ||
Packit Service c5cf8c
	die "Could not run ./$programname\n";
Packit Service c5cf8c
    if ($progEnv ne "") {
Packit Service c5cf8c
	%ENV = %saveEnv;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($ResultTest ne "") {
Packit Service c5cf8c
	# Read and process the output
Packit Service c5cf8c
	($found_error, $inline) = &$ResultTest( MPIOUT, $programname );
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	if ($verbose) {
Packit Service c5cf8c
	    $inline = "$mpiexec $np_arg $np $extraArgs $mpiexecArgs $program_wrapper ./$programname\n";
Packit Service c5cf8c
	}
Packit Service c5cf8c
	else {
Packit Service c5cf8c
	    $inline = "";
Packit Service c5cf8c
	}
Packit Service c5cf8c
	while (<MPIOUT>) {
Packit Service c5cf8c
	    print STDOUT $_ if $verbose;
Packit Service c5cf8c
	    # Skip FORTRAN STOP
Packit Service c5cf8c
	    if (/FORTRAN STOP/) { next; }
Packit Service c5cf8c
	    $inline .= $_;
Packit Service c5cf8c
	    if (/^\s*No [Ee]rrors\s*$/ && $found_noerror == 0) {
Packit Service c5cf8c
		$found_noerror = 1;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	    if (! /^\s*No [Ee]rrors\s*$/ && !/^\s*Test Passed\s*$/ && !/requesting checkpoint\s*$/ && !/checkpoint completed\s*$/) {
Packit Service c5cf8c
		print STDERR "Unexpected output in $programname: $_";
Packit Service c5cf8c
		if (!$found_error) {
Packit Service c5cf8c
		    $found_error = 1;
Packit Service c5cf8c
		    $err_count ++;
Packit Service c5cf8c
		}
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
	if ($found_noerror == 0) {
Packit Service c5cf8c
	    print STDERR "Program $programname exited without No Errors\n";
Packit Service c5cf8c
	    if (!$found_error) {
Packit Service c5cf8c
		$found_error = 1;
Packit Service c5cf8c
		$err_count ++;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
	$rc = close ( MPIOUT );
Packit Service c5cf8c
	my $end_time = gettimeofday();
Packit Service c5cf8c
	$runtime = $end_time - $start_time;
Packit Service c5cf8c
	print STDOUT "Runtime: $runtime\n" if $verbose;
Packit Service c5cf8c
	if ($rc == 0) {
Packit Service c5cf8c
	    # Only generate a message if we think that the program
Packit Service c5cf8c
	    # passed the test.
Packit Service c5cf8c
	    if (!$found_error) {
Packit Service c5cf8c
		$run_status = $?;
Packit Service c5cf8c
		$signal_num = $run_status & 127;
Packit Service c5cf8c
		if ($run_status > 255) { $run_status >>= 8; }
Packit Service c5cf8c
		print STDERR "Program $programname exited with non-zero status $run_status\n";
Packit Service c5cf8c
		if ($signal_num != 0) {
Packit Service c5cf8c
		    print STDERR "Program $programname exited with signal $signal_num\n";
Packit Service c5cf8c
		}
Packit Service c5cf8c
		$found_error = 1;
Packit Service c5cf8c
		$err_count ++;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($found_error) {
Packit Service c5cf8c
        &RunTestFailed( $programname, $np, $progArgs, $progEnv, $timeout, $curdir, $inline, $xfail, $runtime );
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else { 
Packit Service c5cf8c
        &RunTestPassed( $programname, $np, $progArgs, $progEnv, $curdir, $xfail, $runtime );
Packit Service c5cf8c
    }
Packit Service c5cf8c
    &RunPostMsg( $programname, $np, $curdir );
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# This version simply writes the mpiexec command out, with the output going
Packit Service c5cf8c
# into a file, and recording the output status of the run.
Packit Service c5cf8c
sub AddMPIProgram {
Packit Service c5cf8c
    my ($programname,$np,$ResultTest,$InitForTest,$timeLimit,$progArgs,$progEnv,$mpiexecArgs, $xfail) = @_;
Packit Service c5cf8c
Packit Service c5cf8c
    if (! -x $programname) {
Packit Service c5cf8c
	print STDERR "Could not find $programname!";
Packit Service c5cf8c
	return;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if ($ResultTest ne "") {
Packit Service c5cf8c
	# This test really needs to be run manually, with this test
Packit Service c5cf8c
	# Eventually, we can update this to include handleing in checktests.
Packit Service c5cf8c
	print STDERR "Run $curdir/$programname with $np processes and use $ResultTest to check the results\n";
Packit Service c5cf8c
	return;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    # Set a default timeout on tests (3 minutes for now)
Packit Service c5cf8c
    my $timeout = $defaultTimeLimit;
Packit Service c5cf8c
    if (defined($timeLimit) && $timeLimit =~ /^\d+$/) {
Packit Service c5cf8c
	# On some systems, there is no effective time limit on 
Packit Service c5cf8c
	# individual mpi program runs.  In that case, we may
Packit Service c5cf8c
	# want to treat these also as "run manually".
Packit Service c5cf8c
	$timeout = $timeLimit;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    $timeout *= $defaultTimeLimitMultiplier;
Packit Service c5cf8c
    print BATOUT "export MPIEXEC_TIMEOUT=$timeout\n";
Packit Service c5cf8c
    
Packit Service c5cf8c
    # Run the optional setup routine. For example, the timeout tests could
Packit Service c5cf8c
    # be set to a shorter timeout.
Packit Service c5cf8c
    if ($InitForTest ne "") {
Packit Service c5cf8c
	&$InitForTest();
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    # For non-MPICH versions of mpiexec, a timeout may require a different
Packit Service c5cf8c
    # environment variable or command line option (e.g., for Cray aprun, 
Packit Service c5cf8c
    # the option -t <sec> must be given, there is no environment variable 
Packit Service c5cf8c
    # to set the timeout.
Packit Service c5cf8c
    $extraArgs = "";
Packit Service c5cf8c
    if (defined($timeoutArgPattern) && $timeoutArgPattern ne "") {
Packit Service c5cf8c
	my $timeArg = $timeoutArgPattern;
Packit Service c5cf8c
	$timeoutArg =~ s/<SEC>/$timeout/;
Packit Service c5cf8c
	$extraArgs .= $timeoutArg
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    # Handle the ppn (processes per node) option.
Packit Service c5cf8c
    $ppnargs = "";
Packit Service c5cf8c
    if ($ppnArg ne "" && $ppnMax > 0) {
Packit Service c5cf8c
	$ppnargs = $ppnArg;
Packit Service c5cf8c
	$nn = $ppnMax;
Packit Service c5cf8c
	# Some systems require setting the number of processes per node
Packit Service c5cf8c
	# no greater than the total number of processes (e.g., aprun on Cray)
Packit Service c5cf8c
	if ($nn > $np) { $nn = $np; }
Packit Service c5cf8c
	$ppnargs =~ s/\%d/$nn/;
Packit Service c5cf8c
	$extraArgs .= " " . $ppnargs;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    # Handle the timelimit option.
Packit Service c5cf8c
    if ($timelimitArg ne "" && $timeout> 0) {
Packit Service c5cf8c
        $tlargs = "";
Packit Service c5cf8c
	$tlargs = $timelimitArg;
Packit Service c5cf8c
	$tlargs =~ s/\%d/$timeout/;
Packit Service c5cf8c
	$extraArgs .= " " . $tlargs;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
    print STDOUT "Env includes $progEnv\n" if $verbose;
Packit Service c5cf8c
    print STDOUT "$mpiexec $np_arg $np $extraArgs $program_wrapper ./$programname $progArgs\n" if $verbose;
Packit Service c5cf8c
    print STDOUT "." if $showProgress;
Packit Service c5cf8c
    # Save and restore the environment if necessary before running mpiexec.
Packit Service c5cf8c
    if ($progEnv ne "") {
Packit Service c5cf8c
	# Need to fix: 
Packit Service c5cf8c
	# save_NAME_is_set=is old name set
Packit Service c5cf8c
	# save_NAME=oldValue
Packit Service c5cf8c
	# export NAME=newvalue
Packit Service c5cf8c
	# (run) 
Packit Service c5cf8c
	# export NAME=oldValue (if set!)
Packit Service c5cf8c
	print STDERR "Batch output does not permit changes to environment\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    # The approach here is to move the test codes to a single directory from
Packit Service c5cf8c
    # which they can be run; this avoids complex code to change directories
Packit Service c5cf8c
    # and ensure that the output goes "into the right place".
Packit Service c5cf8c
    $testCount++;
Packit Service c5cf8c
    rename $programname, "$batrundir/$programname";
Packit Service c5cf8c
    print BATOUT "echo \"# $mpiexec $np_arg $np $extraArgs $mpiexecArgs $program_wrapper $curdir/$programname $progArgs\" > runtests.$testCount.out\n";
Packit Service c5cf8c
    # Some programs expect to run in the same directory as the executable
Packit Service c5cf8c
    print BATOUT "$mpiexec $np_arg $np $extraArgs $mpiexecArgs $program_wrapper ./$programname $progArgs >> runtests.$testCount.out 2>&1\n";
Packit Service c5cf8c
    print BATOUT "echo \$? > runtests.$testCount.status\n";
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# 
Packit Service c5cf8c
# Return value is 0 on success, non zero on failure
Packit Service c5cf8c
sub BuildMPIProgram {
Packit Service c5cf8c
    my $programname = shift;
Packit Service c5cf8c
    my $xfail = shift;
Packit Service c5cf8c
    my $rc = 0;
Packit Service c5cf8c
    if ($verbose) { print STDERR "making $programname\n"; }
Packit Service c5cf8c
    if (! -x $programname) { $remove_this_pgm = 1; }
Packit Service c5cf8c
    else { $remove_this_pgm = 0; }
Packit Service c5cf8c
    my $output = `make $programname 2>&1;;
Packit Service c5cf8c
    $rc = $?;
Packit Service c5cf8c
    if ($rc > 255) { $rc >>= 8; }
Packit Service c5cf8c
    if (! -x $programname) {
Packit Service c5cf8c
	print STDERR "Failed to build $programname; $output\n";
Packit Service c5cf8c
	if ($rc == 0) {
Packit Service c5cf8c
	    $rc = 1;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	# Add a line to the summary file describing the failure
Packit Service c5cf8c
	# This will ensure that failures to build will end up 
Packit Service c5cf8c
	# in the summary file (which is otherwise written by the
Packit Service c5cf8c
	# RunMPIProgram step)
Packit Service c5cf8c
	&RunPreMsg( $programname, $np, $curdir );
Packit Service c5cf8c
    &RunTestFailed( $programname, $np, "", "", $timeout, $curdir, "Failed to build $programname; $output", $xfail );
Packit Service c5cf8c
	&RunPostMsg( $programname, $np, $curdir );
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return $rc;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
sub CleanUpAfterRun {
Packit Service c5cf8c
    my $programname = $_[0];
Packit Service c5cf8c
    
Packit Service c5cf8c
    # Check for that this program has exited.  If it is still running,
Packit Service c5cf8c
    # issue a warning and leave the application.  Of course, this
Packit Service c5cf8c
    # check is complicated by the lack of a standard access to the 
Packit Service c5cf8c
    # running processes for this user in Unix.
Packit Service c5cf8c
    @stillRunning = &FindRunning( $programname );
Packit Service c5cf8c
Packit Service c5cf8c
    if ($#stillRunning > -1) {
Packit Service c5cf8c
	print STDERR "Some programs ($programname) may still be running:\npids = ";
Packit Service c5cf8c
	for (my $i=0; $i <= $#stillRunning; $i++ ) {
Packit Service c5cf8c
	    print STDERR $stillRunning[$i] . " ";
Packit Service c5cf8c
	}
Packit Service c5cf8c
	print STDERR "\n";
Packit Service c5cf8c
	# Remind the user that the executable remains; we leave it around
Packit Service c5cf8c
	# to allow the programmer to debug the running program, for which
Packit Service c5cf8c
	# the executable is needed.
Packit Service c5cf8c
	print STDERR "The executable ($programname) will not be removed.\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	if ($remove_this_pgm && $clean_pgms) {
Packit Service c5cf8c
	    unlink $programname, "$programname.o";
Packit Service c5cf8c
	}
Packit Service c5cf8c
	$remove_this_pgm = 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
# ----------------------------------------------------------------------------
Packit Service c5cf8c
sub FindRunning { 
Packit Service c5cf8c
    my $programname = $_[0];
Packit Service c5cf8c
    my @pids = ();
Packit Service c5cf8c
Packit Service c5cf8c
    my $logname = $ENV{'USER'};
Packit Service c5cf8c
    my $pidloc = 1;
Packit Service c5cf8c
    my $rc = open PSFD, "ps auxw -U $logname 2>&1 |";
Packit Service c5cf8c
Packit Service c5cf8c
    if ($rc == 0) { 
Packit Service c5cf8c
	$rc = open PSFD, "ps -fu $logname 2>&1 |";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($rc == 0) {
Packit Service c5cf8c
	print STDERR "Could not execute ps command\n";
Packit Service c5cf8c
	return @pids;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    while (<PSFD>) {
Packit Service c5cf8c
	if (/$programname/) {
Packit Service c5cf8c
	    @fields = split(/\s+/);
Packit Service c5cf8c
	    my $pid = $fields[$pidloc];
Packit Service c5cf8c
	    # Check that we've found a numeric pid
Packit Service c5cf8c
	    if ($pid =~ /^\d+$/) {
Packit Service c5cf8c
		$pids[$#pids + 1] = $pid;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    close PSFD;
Packit Service c5cf8c
Packit Service c5cf8c
    return @pids;
Packit Service c5cf8c
}
Packit Service c5cf8c
# ----------------------------------------------------------------------------
Packit Service c5cf8c
#
Packit Service c5cf8c
# TestStatus is a special test that reports success *only* when the 
Packit Service c5cf8c
# status return is NONZERO
Packit Service c5cf8c
sub TestStatus {
Packit Service c5cf8c
    my $MPIOUT = $_[0];
Packit Service c5cf8c
    my $programname = $_[1];
Packit Service c5cf8c
    my $found_error = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    my $inline = "";
Packit Service c5cf8c
    while (<$MPIOUT>) {
Packit Service c5cf8c
	#print STDOUT $_ if $verbose;
Packit Service c5cf8c
	# Skip FORTRAN STOP
Packit Service c5cf8c
	if (/FORTRAN STOP/) { next; }
Packit Service c5cf8c
	$inline .= $_;
Packit Service c5cf8c
	# ANY output is an error. We have the following output
Packit Service c5cf8c
	# exception for the Hydra process manager.
Packit Service c5cf8c
	if (/=*/) { last; }
Packit Service c5cf8c
	if (! /^\s*$/) {
Packit Service c5cf8c
	    print STDERR "Unexpected output in $programname: $_";
Packit Service c5cf8c
	    if (!$found_error) {
Packit Service c5cf8c
		$found_error = 1;
Packit Service c5cf8c
		$err_count ++;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    $rc = close ( MPIOUT );
Packit Service c5cf8c
    if ($rc == 0) {
Packit Service c5cf8c
	$run_status = $?;
Packit Service c5cf8c
	$signal_num = $run_status & 127;
Packit Service c5cf8c
	if ($run_status > 255) { $run_status >>= 8; }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	# This test *requires* non-zero return codes
Packit Service c5cf8c
        if (!$found_error) {
Packit Service c5cf8c
	    $found_error = 1;
Packit Service c5cf8c
	    $err_count ++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
	$inline .= "$mpiexec returned a zero status but the program returned a nonzero status\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return ($found_error,$inline);
Packit Service c5cf8c
}
Packit Service c5cf8c
# ----------------------------------------------------------------------------
Packit Service c5cf8c
#
Packit Service c5cf8c
# TestStatusNoErrors is like TestStatus except that it also checks for " No Errors"
Packit Service c5cf8c
# This is useful for fault tolerance tests where mpiexec returns a non-zero status
Packit Service c5cf8c
# because of a failed process, but still outputs " No Errors" when the correct
Packit Service c5cf8c
# behavior is detected.
Packit Service c5cf8c
sub TestStatusNoErrors {
Packit Service c5cf8c
    my $MPIOUT = $_[0];
Packit Service c5cf8c
    my $programname = $_[1];
Packit Service c5cf8c
    my $found_error = 0;
Packit Service c5cf8c
    my $found_noerror = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    my $inline = "";
Packit Service c5cf8c
    while (<MPIOUT>) {
Packit Service c5cf8c
	print STDOUT $_ if $verbose;
Packit Service c5cf8c
	# Skip FORTRAN STOP
Packit Service c5cf8c
	if (/FORTRAN STOP/) { next; }
Packit Service c5cf8c
	$inline .= $_;
Packit Service c5cf8c
	if (/^\s*No [Ee]rrors\s*$/ && $found_noerror == 0) {
Packit Service c5cf8c
	    $found_noerror = 1;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	if (! /^\s*No [Ee]rrors\s*$/ && !/^\s*Test Passed\s*$/) {
Packit Service c5cf8c
	    print STDERR "Unexpected output in $programname: $_";
Packit Service c5cf8c
	    if (!$found_error) {
Packit Service c5cf8c
		$found_error = 1;
Packit Service c5cf8c
		$err_count ++;
Packit Service c5cf8c
	    }
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($found_noerror == 0) {
Packit Service c5cf8c
	print STDERR "Program $programname exited without No Errors\n";
Packit Service c5cf8c
	if (!$found_error) {
Packit Service c5cf8c
	    $found_error = 1;
Packit Service c5cf8c
	    $err_count ++;
Packit Service c5cf8c
	}
Packit Service c5cf8c
    }
Packit Service c5cf8c
    $rc = close ( MPIOUT );
Packit Service c5cf8c
    if ($rc == 0) {
Packit Service c5cf8c
	$run_status = $?;
Packit Service c5cf8c
	$signal_num = $run_status & 127;
Packit Service c5cf8c
	if ($run_status > 255) { $run_status >>= 8; }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	# This test *requires* non-zero return codes
Packit Service c5cf8c
        if (!$found_error) {
Packit Service c5cf8c
	    $found_error = 1;
Packit Service c5cf8c
	    $err_count ++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
	$inline .= "$mpiexec returned a zero status but the program required a non-zero status\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return ($found_error,$inline);
Packit Service c5cf8c
}
Packit Service c5cf8c
#
Packit Service c5cf8c
# TestErrFatal is a special test that reports success *only* when the 
Packit Service c5cf8c
# status return is NONZERO; it ignores error messages
Packit Service c5cf8c
sub TestErrFatal {
Packit Service c5cf8c
    my $MPIOUT = $_[0];
Packit Service c5cf8c
    my $programname = $_[1];
Packit Service c5cf8c
    my $found_error = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    my $inline = "";
Packit Service c5cf8c
    while (<$MPIOUT>) {
Packit Service c5cf8c
	#print STDOUT $_ if $verbose;
Packit Service c5cf8c
	# Skip FORTRAN STOP
Packit Service c5cf8c
	if (/FORTRAN STOP/) { next; }
Packit Service c5cf8c
	$inline .= $_;
Packit Service c5cf8c
	# ALL output is allowed.
Packit Service c5cf8c
    }
Packit Service c5cf8c
    $rc = close ( MPIOUT );
Packit Service c5cf8c
    if ($rc == 0) {
Packit Service c5cf8c
	$run_status = $?;
Packit Service c5cf8c
	$signal_num = $run_status & 127;
Packit Service c5cf8c
	if ($run_status > 255) { $run_status >>= 8; }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    else {
Packit Service c5cf8c
	# This test *requires* non-zero return codes
Packit Service c5cf8c
	if (!$found_error) {
Packit Service c5cf8c
	    $found_error = 1;
Packit Service c5cf8c
	    $err_count ++;
Packit Service c5cf8c
	}
Packit Service c5cf8c
	$inline .= "$mpiexec returned a zero status but the program returned a nonzero status\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return ($found_error,$inline);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# ----------------------------------------------------------------------------
Packit Service c5cf8c
# Output routines:
Packit Service c5cf8c
#  RunPreMsg( programname, np, workdir ) - Call before running a program
Packit Service c5cf8c
#  RunTestFailed, RunTestPassed - Call after test
Packit Service c5cf8c
#  RunPostMsg               - Call at end of each test
Packit Service c5cf8c
#
Packit Service c5cf8c
sub RunPreMsg {
Packit Service c5cf8c
    my ($programname,$np,$workdir) = @_;
Packit Service c5cf8c
    if ($xmloutput) {
Packit Service c5cf8c
	print XMLOUT "<MPITEST>$newline<NAME>$programname</NAME>$newline";
Packit Service c5cf8c
	print XMLOUT "<NP>$np</NP>$newline";
Packit Service c5cf8c
	print XMLOUT "<WORKDIR>$workdir</WORKDIR>$newline";
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
sub RunPostMsg {
Packit Service c5cf8c
    my ($programname, $np, $workdir) = @_;
Packit Service c5cf8c
    if ($xmloutput) {
Packit Service c5cf8c
	print XMLOUT "</MPITEST>$newline";
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
sub RunTestPassed {
Packit Service c5cf8c
    my ($programname, $np, $progArgs, $progEnv, $workdir, $xfail, $runtime) = @_;
Packit Service c5cf8c
    if ($xmloutput) {
Packit Service c5cf8c
	print XMLOUT "<STATUS>pass</STATUS>$newline";
Packit Service c5cf8c
    print XMLOUT "<TIME>$runtime</TIME>$newline";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($tapoutput) {
Packit Service c5cf8c
        print TAPOUT "ok ${total_run} - $workdir/$programname ${np} # time=$runtime\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($junitoutput) {
Packit Service c5cf8c
        print JUNITOUT "    <testcase name=\"${total_run} - $workdir/$programname ${np} ${progArgs} ${progEnv}\" time=\"$runtime\"></testcase>\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
sub RunTestFailed {
Packit Service c5cf8c
    my $programname = shift;
Packit Service c5cf8c
    my $np = shift;
Packit Service c5cf8c
    my $progArgs = shift;
Packit Service c5cf8c
    my $progEnv = shift;
Packit Service c5cf8c
    my $timeout = shift;
Packit Service c5cf8c
    my $workdir = shift;
Packit Service c5cf8c
    my $output = shift;
Packit Service c5cf8c
    my $xfail = shift;
Packit Service c5cf8c
    my $runtime = shift;
Packit Service c5cf8c
Packit Service c5cf8c
    if ($xmloutput) {
Packit Service c5cf8c
        my $xout = $output;
Packit Service c5cf8c
        # basic escapes that wreck the XML output
Packit Service c5cf8c
        $xout =~ s/</\*AMP\*lt;/g;
Packit Service c5cf8c
        $xout =~ s/>/\*AMP\*gt;/g;
Packit Service c5cf8c
        $xout =~ s/&/\*AMP\*amp;/g;
Packit Service c5cf8c
        $xout =~ s/\*AMP\*/&/;;
Packit Service c5cf8c
        # TODO: Also capture any non-printing characters (XML doesn't like them
Packit Service c5cf8c
        # either).
Packit Service c5cf8c
        print XMLOUT "<TIME>$runtime</TIME>$newline";
Packit Service c5cf8c
	print XMLOUT "<STATUS>fail</STATUS>$newline";
Packit Service c5cf8c
	print XMLOUT "<TESTDIFF>$newline$xout</TESTDIFF>$newline";
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if ($tapoutput) {
Packit Service c5cf8c
        my $xfailstr = '';
Packit Service c5cf8c
        if ($xfail ne '') {
Packit Service c5cf8c
            $xfailstr = " # TODO $xfail";
Packit Service c5cf8c
        }
Packit Service c5cf8c
        print TAPOUT "not ok ${total_run} - $workdir/$programname ${np}${xfailstr} # time=$runtime\n";
Packit Service c5cf8c
        print TAPOUT "  ---\n";
Packit Service c5cf8c
        print TAPOUT "  Directory: $workdir\n";
Packit Service c5cf8c
        print TAPOUT "  File: $programname\n";
Packit Service c5cf8c
        print TAPOUT "  Num-procs: $np\n";
Packit Service c5cf8c
        print TAPOUT "  Timeout: $timeout\n";
Packit Service c5cf8c
        print TAPOUT "  Date: \"" . localtime() . "\"\n";
Packit Service c5cf8c
Packit Service c5cf8c
        # The following would be nice, but it leads to unfortunate formatting in
Packit Service c5cf8c
        # the Jenkins web output for now.  Using comment lines instead, since
Packit Service c5cf8c
        # they are easier to read/find in a browser.
Packit Service c5cf8c
##        print TAPOUT "  Output: |\n";
Packit Service c5cf8c
##        # using block literal format, requires that all chars are printable
Packit Service c5cf8c
##        # UTF-8 (or UTF-16, but we won't encounter that)
Packit Service c5cf8c
##        foreach my $line (split m/\r?\n/, $output) {
Packit Service c5cf8c
##            chomp $line;
Packit Service c5cf8c
##            # 4 spaces, 2 for TAP indent, 2 more for YAML block indent
Packit Service c5cf8c
##            print TAPOUT "    $line\n";
Packit Service c5cf8c
##        }
Packit Service c5cf8c
Packit Service c5cf8c
        print TAPOUT "  ...\n";
Packit Service c5cf8c
Packit Service c5cf8c
        # Alternative to the "Output:" YAML block literal above.  Do not put any
Packit Service c5cf8c
        # spaces before the '#', this causes some TAP parsers (including Perl's
Packit Service c5cf8c
        # TAP::Parser) to treat the line as "unknown" instead of a proper
Packit Service c5cf8c
        # comment.
Packit Service c5cf8c
        print TAPOUT "## Test output (expected 'No Errors'):\n";
Packit Service c5cf8c
        foreach my $line (split m/\r?\n/, $output) {
Packit Service c5cf8c
            chomp $line;
Packit Service c5cf8c
            print TAPOUT "## $line\n";
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if ($junitoutput) {
Packit Service c5cf8c
        my $xfailstr = '';
Packit Service c5cf8c
	my $testtag = "failure";
Packit Service c5cf8c
        if ($xfail ne '') {
Packit Service c5cf8c
            $xfailstr = " # TODO $xfail";
Packit Service c5cf8c
	    $testtag  = "skipped";
Packit Service c5cf8c
        }
Packit Service c5cf8c
        print JUNITOUT "    <testcase name=\"${total_run} - $workdir/$programname ${np} ${progArgs} ${progEnv}\" time=\"$runtime\">\n";
Packit Service c5cf8c
        print JUNITOUT "      <${testtag} type=\"TestFailed\"\n";
Packit Service c5cf8c
        print JUNITOUT "               message=\"not ok ${total_run} - $workdir/$programname ${np}${xfailstr}\">
Packit Service c5cf8c
        print JUNITOUT "not ok ${total_run} - $workdir/$programname ${np}${xfailstr}\n";
Packit Service c5cf8c
        print JUNITOUT "  ---\n";
Packit Service c5cf8c
        print JUNITOUT "  Directory: $workdir\n";
Packit Service c5cf8c
        print JUNITOUT "  File: $programname\n";
Packit Service c5cf8c
        print JUNITOUT "  Num-procs: $np\n";
Packit Service c5cf8c
        print JUNITOUT "  Timeout: $timeout\n";
Packit Service c5cf8c
        print JUNITOUT "  Date: \"" . localtime() . "\"\n";
Packit Service c5cf8c
Packit Service c5cf8c
        print JUNITOUT "  ...\n";
Packit Service c5cf8c
Packit Service c5cf8c
        # Alternative to the "Output:" YAML block literal above.  Do not put any
Packit Service c5cf8c
        # spaces before the '#', this causes some JUNIT parsers (including Perl's
Packit Service c5cf8c
        # JUNIT::Parser) to treat the line as "unknown" instead of a proper
Packit Service c5cf8c
        # comment.
Packit Service c5cf8c
        print JUNITOUT "## Test output (expected 'No Errors'):\n";
Packit Service c5cf8c
        foreach my $line (split m/\r?\n/, $output) {
Packit Service c5cf8c
            chomp $line;
Packit Service c5cf8c
            print JUNITOUT "## $line\n";
Packit Service c5cf8c
        }
Packit Service c5cf8c
        print JUNITOUT "    ]]></${testtag}>\n";
Packit Service c5cf8c
        print JUNITOUT "    </testcase>\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
sub SkippedTest {
Packit Service c5cf8c
    my $programname = shift;
Packit Service c5cf8c
    my $np = shift;
Packit Service c5cf8c
    my $progArgs = shift;
Packit Service c5cf8c
    my $progEnv = shift;
Packit Service c5cf8c
    my $workdir = shift;
Packit Service c5cf8c
    my $reason = shift;
Packit Service c5cf8c
Packit Service c5cf8c
    # simply omit from the XML output
Packit Service c5cf8c
Packit Service c5cf8c
    if ($tapoutput) {
Packit Service c5cf8c
        print TAPOUT "ok ${total_seen} - $workdir/$programname $np  # SKIP $reason\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if ($junitoutput) {
Packit Service c5cf8c
        print JUNITOUT "    <testcase name=\"${total_seen} - $workdir/$programname ${np} ${progArgs} ${progEnv}\">\n";
Packit Service c5cf8c
        print JUNITOUT "      <skipped type=\"TodoTestSkipped\">\n";
Packit Service c5cf8c
        print JUNITOUT "             message=\"$reason\"></skipped>\n";
Packit Service c5cf8c
        print JUNITOUT "    </testcase>\n";
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    $skip_count++;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
# ----------------------------------------------------------------------------
Packit Service c5cf8c
# Alternate init routines
Packit Service c5cf8c
sub InitQuickTimeout {
Packit Service c5cf8c
    $ENV{"MPIEXEC_TIMEOUT"} = 10;
Packit Service c5cf8c
}