4 # This script is the beginnings of a script to run a sequence of test
5 # programs. See the MPICH document for a description of the test
6 # strategy and requirements.
9 # Tests are controlled by a file listing test programs; if the file is
10 # a directory, then all of the programs in the directory and subdirectories
13 # To run a test, the following steps are executed
14 # Build the executable:
17 # mpiexec -n <np> ./programname >out 2>err
18 # Check the return code (non zero is failure)
19 # Check the stderr output (non empty is failure)
20 # Check the stdout output (No Errors or Test passed are the only valid
22 # Remove executable, out, err files
24 # The format of a list file is
25 # programname number-of-processes
26 # If number-of-processes is missing, $np_default is used (this is 2 but can
27 # be overridden with -np=new-value)
30 # Because these tests can take a long time to run, there is an
31 # option to cause the tests to stop is a "stopfile" is found.
32 # The stopfile can be created by a separate, watchdog process, to ensure that
33 # tests end at a certain time.
34 # The name of this file is (by default) .stoptest
35 # in the top-level run directory. The environment variable
37 # can specify a different file name.
39 # Import the mkpath command
43 $MPIMajorVersion = "3";
44 $MPIMinorVersion = "1";
45 $mpiexec = "smpirun"; # Name of mpiexec program (including path, if necessary)
46 $platformfile = "../../../../examples/platforms/small_platform_with_routers.xml";
47 $hostfile = "../../hostfile_mpich";
48 $testIsStrict = "true";
50 $np_arg = "-np"; # Name of argument to specify the number of processes
51 $err_count = 0; # Number of programs that failed.
52 $total_run = 0; # Number of programs tested
53 $total_seen = 0; # Number of programs considered for testing
54 $np_default = 2; # Default number of processes to use
55 $np_max = -1; # Maximum number of processes to use (overrides any
56 # value in the test list files. -1 is Infinity
57 $defaultTimeLimit = 180; # default timeout
59 $srcdir = "."; # Used to set the source dir for testlist files
61 $curdir = "."; # used to track the relative current directory
64 $xmloutput = 0; # Set to true to get xml output (also specify file)
65 $closeXMLOutput = 1; # Set to false to leave XML output file open to
66 # accept additional data
67 $verbose = 1; # Set to true to get more output
68 $showProgress = 0; # Set to true to get a "." with each run program.
69 $newline = "\r\n"; # Set to \r\n for Windows-friendly, \n for Unix only
70 $batchRun = 0; # Set to true to batch the execution of the tests
71 # (i.e., run them together, then test output,
72 # rather than build/run/check for each test)
73 $testCount = 0; # Used with batchRun to count tests.
74 $batrundir = "."; # Set to the directory into which to run the examples
79 $enabled_privatization = 1; # disable tests that need SMPI privatization to run
80 # TAP (Test Anything Protocol) output
87 $depth = 0; # This is used to manage multiple open list files
93 my $program_wrapper = '';
95 #---------------------------------------------------------------------------
96 # Get some arguments from the environment
97 # Currently, only the following are understood:
99 # RUNTESTS_VERBOSE (an alias for VERBOSE in case you want to
101 # RUNTESTS_SHOWPROGRESS
104 # MPITEST_PROGRAM_WRAPPER (Value is added after -np but before test
105 # executable. Tools like valgrind may be inserted
107 #---------------------------------------------------------------------------
108 if ( defined($ENV{"VERBOSE"}) || defined($ENV{"V"}) || defined($ENV{"RUNTESTS_VERBOSE"}) ) {
111 if ( defined($ENV{"RUNTESTS_SHOWPROGRESS"} ) ) {
114 if (defined($ENV{"MPITEST_STOPTEST"})) {
115 $stopfile = $ENV{"MPITEST_STOPTEST"};
118 $stopfile = `pwd` . "/.stoptest";
119 $stopfile =~ s/\r*\n*//g; # Remove any newlines (from pwd)
122 if (defined($ENV{"MPITEST_TIMEOUT"})) {
123 $defaultTimeLimit = $ENV{"MPITEST_TIMEOUT"};
126 # Define this to leave the XML output file open to receive additional data
127 if (defined($ENV{'NOXMLCLOSE'}) && $ENV{'NOXMLCLOSE'} eq 'YES') {
131 if (defined($ENV{'MPITEST_PROGRAM_WRAPPER'})) {
132 $program_wrapper = $ENV{'MPITEST_PROGRAM_WRAPPER'};
135 if (defined($ENV{'MPITEST_BATCH'})) {
136 if ($ENV{'MPITEST_BATCH'} eq 'YES' || $ENV{'MPITEST_BATCH'} eq 'yes') {
138 } elsif ($ENV{'MPITEST_BATCH'} eq 'NO' || $ENV{'MPITEST_BATCH'} eq 'no') {
142 print STDERR "Unrecognized value for MPITEST_BATCH = $ENV{'MPITEST_BATCH'}\n";
145 if (defined($ENV{'MPITEST_BATCHDIR'})) {
146 $batrundir = $ENV{'MPITEST_BATCHDIR'};
149 #---------------------------------------------------------------------------
150 # Process arguments and override any defaults
151 #---------------------------------------------------------------------------
153 if (/--?mpiexec=(.*)/) {
154 # Use mpiexec as given - it may be in the path, and
155 # we don't want to bother to try and find it.
158 elsif (/--?np=(.*)/) { $np_default = $1; }
159 elsif (/--?maxnp=(.*)/) { $np_max = $1; }
160 elsif (/--?tests=(.*)/) { $listfiles = $1; }
161 elsif (/--?platformfile=(.*)/) { $platformfile = $1; }
162 elsif (/--?hostfile=(.*)/) { $hostfile = $1; }
163 elsif (/--?srcdir=(.*)/) { $srcdir = $1;
164 $mpiexec="$mpiexec -platform ${srcdir}/$platformfile -hostfile ${srcdir}/$hostfile --log=root.thr:critical --log=smpi_kernel.thr:warning --cfg=smpi/host-speed:1e9f --cfg=smpi/async-small-thresh:65536"; }
165 elsif (/--?verbose/) { $verbose = 1; }
166 elsif (/--?showprogress/) { $showProgress = 1; }
167 elsif (/--?debug/) { $debug = 1; }
168 elsif (/--?batch/) { $batchRun = 1; }
169 elsif (/--?batchdir=(.*)/) { $batrundir = $1; }
170 elsif (/--?timeoutarg=(.*)/) { $timeoutArgPattern = $1; }
171 elsif (/--?execarg=(.*)/) { $execarg = "$execarg $1"; }
172 elsif (/--?privatization=(.*)/) {
173 print STDERR "privatization called\n";
174 $enabled_privatization = $1; }
175 elsif (/--?wrapper=(.*)/) {
176 $wrapparg = "-wrapper \"$1\"" if $1 ne "";
178 elsif (/--?xmlfile=(.*)/) {
180 if (! ($xmlfile =~ /^\//)) {
183 $xmlfullfile = $thisdir . "/" . $xmlfile ;
186 $xmlfullfile = $xmlfile;
189 open( XMLOUT, ">$xmlfile" ) || die "Cannot open $xmlfile\n";
190 my $date = `date "+%Y-%m-%d-%H-%M"`;
192 # MPISOURCE can be used to describe the source of MPI for this
194 print XMLOUT "<?xml version='1.0' ?>$newline";
195 print XMLOUT "<?xml-stylesheet href=\"TestResults.xsl\" type=\"text/xsl\" ?>$newline";
196 print XMLOUT "<MPITESTRESULTS>$newline";
197 print XMLOUT "<DATE>$date</DATE>$newline";
198 print XMLOUT "<MPISOURCE></MPISOURCE>$newline";
200 elsif (/--?noxmlclose/) {
203 elsif (/--?tapfile=(.*)/) {
205 if ($tapfile !~ m|^/|) {
208 $tapfullfile = $thisdir . "/" . $tapfile ;
211 $tapfullfile = $tapfile;
214 open( TAPOUT, ">$tapfile" ) || die "Cannot open $tapfile\n";
215 my $date = `date "+%Y-%m-%d-%H-%M"`;
217 print TAPOUT "TAP version 13\n";
218 print TAPOUT "# MPICH test suite results (TAP format)\n";
219 print TAPOUT "# date ${date}\n";
220 # we do not know at this point how many tests will be run, so do
221 # not print a test plan line like "1..450" until the very end
225 # Perform any post argument processing
227 if (! -d $batrundir) {
228 mkpath $batrundir || die "Could not create $batrundir\n";
230 open( BATOUT, ">$batrundir/runtests.batch" ) || die "Could not open $batrundir/runtests.batch\n";
233 # We must have mpiexec
234 if ("$mpiexec" eq "") {
235 print STDERR "No mpiexec found!\n";
242 if ($listfiles eq "") {
244 print STDERR "An implicit list of tests is not permitted in batch mode\n";
248 &ProcessImplicitList;
251 elsif (-d $listfiles) {
252 print STDERR "Testing by directories not yet supported\n";
255 &RunList( $listfiles );
258 if ($xmloutput && $closeXMLOutput) {
259 print XMLOUT "</MPITESTRESULTS>$newline";
264 print TAPOUT "1..$total_seen\n";
270 print "Programs created along with a runtest.batch file in $batrundir\n";
271 print "Run that script and then use checktests to summarize the results\n";
275 print "$err_count tests failed out of $total_run\n";
276 print "Failing tests : $failed_tests\n";
278 print "Details in $xmlfullfile\n";
282 print " All $total_run tests passed!\n";
285 print "TAP formatted results in $tapfullfile\n";
288 exit ($err_count > 0);
290 # ---------------------------------------------------------------------------
293 # Enter a new directory and process a list file.
294 # ProcessDir( directory-name, list-file-name )
296 my $dir = $_[0]; $dir =~ s/\/$//;
297 my $listfile = $_[1];
299 my $savecurdir = $curdir;
300 my $savesrcdir = $srcdir;
303 if (substr($srcdir,0,3) eq "../") {
304 $srcdir = "../$srcdir";
307 print "Processing directory $dir\n" if ($verbose || $debug);
310 print STDERR "only direct subdirectories allowed in list files";
314 &RunList( $listfile );
315 print "\n" if $showProgress; # Terminate line from progress output
317 $curdir = $savecurdir;
318 $srcdir = $savesrcdir;
320 # ---------------------------------------------------------------------------
321 # Run the programs listed in the file given as the argument.
322 # This file describes the tests in the format
323 # programname number-of-processes [ key=value ... ]
324 # If the second value is not given, the default value is used.
327 my $LIST = "LIST$depth"; $depth++;
328 my $listfile = $_[0];
331 my $listfileSource = $listfile;
333 print "Looking in $curdir/$listfile\n" if $debug;
334 if (! -s "$listfile" && -s "$srcdir/$curdir/$listfile" ) {
335 $listfileSource = "$srcdir/$curdir/$listfile";
337 open( $LIST, "<$listfileSource" ) ||
338 die "Could not open $listfileSource\n";
340 # Check for stop file
342 # Exit because we found a stopfile
343 print STDERR "Terminating test because stopfile $stopfile found\n";
348 # Remove any trailing newlines/returns
350 # Remove any leading whitespace
352 # Some tests require that support routines are built first
353 # This is specified with !<dir>:<target>
354 if (/^\s*\!([^:]*):(.*)/) {
355 # Hack: just execute in a subshell. This discards any
360 # List file entries have the form:
361 # program [ np [ name=value ... ] ]
362 # See files errhan/testlist, init/testlist, and spawn/testlist
363 # for examples of using the key=value form
364 my @args = split(/\s+/,$_);
365 my $programname = $args[0];
371 my $mpiexecArgs = "$execarg";
372 my $requiresStrict = "";
373 my $requiresMPIX = "";
376 my $needs_privatization = 0;
378 if ($#args >= 1) { $np = $args[1]; }
379 # Process the key=value arguments
380 for (my $i=2; $i <= $#args; $i++) {
381 if ($args[$i] =~ /([^=]+)=(.*)/) {
384 if ($key eq "resultTest") {
385 $ResultTest = $value;
387 elsif ($key eq "init") {
388 $InitForRun = $value;
390 elsif ($key eq "timeLimit") {
393 elsif ($key eq "arg") {
394 $progArgs = "$progArgs $value";
396 elsif ($key eq "mpiexecarg") {
397 $mpiexecArgs = "$mpiexecArgs $value";
399 elsif ($key eq "env") {
400 $progEnv = "$progEnv $value";
402 elsif ($key eq "mpiversion") {
403 $mpiVersion = $value;
405 elsif ($key eq "needs_privatization") {
406 $needs_privatization = $value;
408 elsif ($key eq "strict") {
409 $requiresStrict = $value
411 elsif ($key eq "mpix") {
412 $requiresMPIX = $value
414 elsif ($key eq "xfail") {
416 print STDERR "\"xfail=\" requires an argument\n";
421 print STDERR "Unrecognized key $key in $listfileSource\n";
427 if ($programname eq "") { next; }
429 # if privatization is disabled, and if the test needs it, ignore it
430 if ($needs_privatization == 1 &&
431 $enabled_privatization != 1) {
432 SkippedTest($programname, $np, $workdir, "requires SMPI privatization");
436 if ($np eq "") { $np = $np_default; }
437 if ($np_max > 0 && $np > $np_max) { $np = $np_max; }
439 # allows us to accurately output TAP test numbers without disturbing the
440 # original totals that have traditionally been reported
442 # These "unless" blocks are ugly, but permit us to honor skipping
443 # criteria for directories as well without counting directories as tests
444 # in our XML/TAP output.
445 unless (-d $programname) {
449 # If a minimum MPI version is specified, check against the
450 # available MPI. If the version is unknown, we ignore this
451 # test (thus, all tests will be run).
452 if ($mpiVersion ne "" && $MPIMajorVersion ne "unknown" &&
453 $MPIMinorVersion ne "unknown") {
454 my ($majorReq,$minorReq) = split(/\./,$mpiVersion);
455 if ($majorReq > $MPIMajorVersion or
456 ($majorReq == $MPIMajorVersion && $minorReq > $MPIMinorVersion))
458 unless (-d $programname) {
459 SkippedTest($programname, $np, $workdir, "requires MPI version $mpiVersion");
464 # Check whether strict is required by MPI but not by the
465 # test (use strict=false for tests that use non-standard extensions)
466 if (lc($requiresStrict) eq "false" && lc($testIsStrict) eq "true") {
467 unless (-d $programname) {
468 SkippedTest($programname, $np, $workdir, "non-strict test, strict MPI mode requested");
473 if (lc($testIsStrict) eq "true") {
474 # Strict MPI testing was requested, so assume that a non-MPICH MPI
475 # implementation is being tested and the "xfail" implementation
476 # assumptions do not hold.
480 if (lc($requiresMPIX) eq "true" && lc($MPIHasMPIX) eq "no") {
481 unless (-d $programname) {
482 SkippedTest($programname, $np, $workdir, "tests MPIX extensions, MPIX testing disabled");
487 if (-d $programname) {
488 # If a directory, go into the that directory and
489 # look for a new list file
490 &ProcessDir( $programname, $listfile );
494 if (&BuildMPIProgram( $programname, $xfail ) == 0) {
495 if ($batchRun == 1) {
496 &AddMPIProgram( $programname, $np, $ResultTest,
497 $InitForRun, $timeLimit, $progArgs,
498 $progEnv, $mpiexecArgs, $xfail );
501 &RunMPIProgram( $programname, $np, $ResultTest,
502 $InitForRun, $timeLimit, $progArgs,
503 $progEnv, $mpiexecArgs, $xfail );
506 elsif ($xfail ne '') {
507 # We expected to run this program, so failure to build
512 if ($batchRun == 0) {
513 &CleanUpAfterRun( $programname );
520 # This routine tries to run all of the files in the current
522 sub ProcessImplicitList {
523 # The default is to run every file in the current directory.
524 # If there are no built programs, build and run every file
525 # WARNING: This assumes that anything executable should be run as
529 open (PGMS, "ls -1 |" ) || die "Cannot list directory\n";
533 if (-d $programname) { next; } # Ignore directories
534 if ($programname eq "runtests") { next; } # Ignore self
535 if ($programname eq "checktests") { next; } # Ignore helper
536 if ($programname eq "configure") { next; } # Ignore configure script
537 if ($programname eq "config.status") { next; } # Ignore configure helper
538 if (-x $programname) { $found_exec++; }
539 if ($programname =~ /\.[cf]$/) { $found_src++; }
544 print "Found executables\n" if $debug;
545 open (PGMS, "ls -1 |" ) || die "Cannot list programs\n";
547 # Check for stop file
549 # Exit because we found a stopfile
550 print STDERR "Terminating test because stopfile $stopfile found\n";
555 if (-d $programname) { next; } # Ignore directories
556 if ($programname eq "runtests") { next; } # Ignore self
557 if (-x $programname) {
559 &RunMPIProgram( $programname, $np_default, "", "", "", "", "", "", "" );
565 print "Found source files\n" if $debug;
566 open (PGMS, "ls -1 *.c |" ) || die "Cannot list programs\n";
569 # Exit because we found a stopfile
570 print STDERR "Terminating test because stopfile $stopfile found\n";
575 # Skip messages from ls about no files
576 if (! -s $programname) { next; }
577 $programname =~ s/\.c//;
579 if (&BuildMPIProgram( $programname, "") == 0) {
580 &RunMPIProgram( $programname, $np_default, "", "", "", "", "", "", "" );
583 # We expected to run this program, so failure to build
588 &CleanUpAfterRun( $programname );
594 # ToDo: Add a way to limit the time that any particular program may run.
596 # name of program, number of processes, name of routine to check results
597 # init for testing, timelimit, and any additional program arguments
598 # If the 3rd arg is not present, the a default that simply checks that the
599 # return status is 0 and that the output is " No Errors" is used.
601 my ($programname,$np,$ResultTest,$InitForTest,$timeLimit,$progArgs,$progEnv,$mpiexecArgs,$xfail) = @_;
603 my $found_noerror = 0;
606 &RunPreMsg( $programname, $np, $curdir );
610 # Set a default timeout on tests (3 minutes for now)
611 my $timeout = $defaultTimeLimit;
612 if (defined($timeLimit) && $timeLimit =~ /^\d+$/) {
613 $timeout = $timeLimit;
615 $ENV{"MPIEXEC_TIMEOUT"} = $timeout;
617 # Run the optional setup routine. For example, the timeout tests could
618 # be set to a shorter timeout.
619 if ($InitForTest ne "") {
622 print STDOUT "Env includes $progEnv\n" if $verbose;
623 print STDOUT "$mpiexec $wrapparg $mpiexecArgs $np_arg $np $program_wrapper ./$programname $progArgs\n" if $verbose;
624 print STDOUT "." if $showProgress;
625 # Save and restore the environment if necessary before running mpiexec.
626 if ($progEnv ne "") {
628 foreach $val (split(/\s+/, $progEnv)) {
629 if ($val =~ /([^=]+)=(.*)/) {
633 print STDERR "Environment variable/value $val not in a=b form\n";
637 open ( MPIOUT, "$mpiexec $wrapparg $np_arg $np $mpiexecArgs $program_wrapper ./$programname $progArgs 2>&1 |" ) ||
638 die "Could not run ./$programname\n";
639 if ($progEnv ne "") {
642 if ($ResultTest ne "") {
643 # Read and process the output
644 ($found_error, $inline) = &$ResultTest( MPIOUT, $programname );
648 $inline = "$mpiexec $wrapparg $np_arg $np $program_wrapper ./$programname\n";
654 print STDOUT $_ if $verbose;
656 if (/FORTRAN STOP/) { next; }
658 if (m{^==[0-9]+== ?WARNING: ASan doesn't fully support} ||
659 m{^==[0-9]+== ?WARNING: ASan is ignoring requested __asan_handle_no_return: stack } ||
660 m{^False positive error reports may follow$} ||
661 m{^For details see http://code.google.com/p/address-sanitizer/issues/detail\?id=189$} ||
662 m{^For details see https://github.com/google/sanitizers/issues/189$}) {
665 if (/^\s*No [Ee]rrors\s*$/ && $found_noerror == 0) {
668 if (! /^\s*No [Ee]rrors\s*$/ && !/^\s*Test Passed\s*$/) {
669 print STDERR "Unexpected output in $programname: $_";
672 $failed_tests .= $programname;
673 $failed_tests .= " ";
678 if ($found_noerror == 0) {
679 print STDERR "Program $programname exited without No Errors\n";
682 $failed_tests .= $programname;
683 $failed_tests .= " ";
687 $rc = close ( MPIOUT );
689 # Only generate a message if we think that the program
693 $signal_num = $run_status & 127;
694 if ($run_status > 255) { $run_status >>= 8; }
695 print STDERR "Program $programname exited with non-zero status $run_status\n";
696 if ($signal_num != 0) {
697 print STDERR "Program $programname exited with signal $signal_num\n";
699 $failed_tests .= $programname;
700 $failed_tests .= " ";
707 &RunTestFailed( $programname, $np, $curdir, $inline, $xfail );
710 &RunTestPassed( $programname, $np, $curdir, $xfail );
712 &RunPostMsg( $programname, $np, $curdir );
715 # This version simply writes the mpiexec command out, with the output going
716 # into a file, and recording the output status of the run.
718 my ($programname,$np,$ResultTest,$InitForTest,$timeLimit,$progArgs,$progEnv,$mpiexecArgs, $xfail) = @_;
720 if (! -x $programname) {
721 print STDERR "Could not find $programname!";
725 if ($ResultTest ne "") {
726 # This test really needs to be run manually, with this test
727 # Eventually, we can update this to include handling in checktests.
728 print STDERR "Run $curdir/$programname with $np processes and use $ResultTest to check the results\n";
732 # Set a default timeout on tests (3 minutes for now)
733 my $timeout = $defaultTimeLimit;
734 if (defined($timeLimit) && $timeLimit =~ /^\d+$/) {
735 # On some systems, there is no effective time limit on
736 # individual mpi program runs. In that case, we may
737 # want to treat these also as "run manually".
738 $timeout = $timeLimit;
740 print BATOUT "export MPIEXEC_TIMEOUT=$timeout\n";
742 # Run the optional setup routine. For example, the timeout tests could
743 # be set to a shorter timeout.
744 if ($InitForTest ne "") {
748 # For non-MPICH versions of mpiexec, a timeout may require a different
749 # environment variable or command line option (e.g., for Cray aprun,
750 # the option -t <sec> must be given, there is no environment variable
751 # to set the timeout.
753 if (defined($timeoutArgPattern) && $timeoutArgPattern ne "") {
754 my $timeArg = $timeoutArgPattern;
755 $timeoutArg =~ s/<SEC>/$timeout/;
756 $extraArgs .= $timeoutArg
759 print STDOUT "Env includes $progEnv\n" if $verbose;
760 print STDOUT "$mpiexec $np_arg $np $extraArgs $program_wrapper ./$programname $progArgs\n" if $verbose;
761 print STDOUT "." if $showProgress;
762 # Save and restore the environment if necessary before running mpiexec.
763 if ($progEnv ne "") {
765 # save_NAME_is_set=is old name set
767 # export NAME=newvalue
769 # export NAME=oldValue (if set!)
770 print STDERR "Batch output does not permit changes to environment\n";
772 # The approach here is to move the test codes to a single directory from
773 # which they can be run; this avoids complex code to change directories
774 # and ensure that the output goes "into the right place".
776 rename $programname, "$batrundir/$programname";
777 print BATOUT "echo \"# $mpiexec $np_arg $np $extraArgs $mpiexecArgs $program_wrapper $curdir/$programname $progArgs\" > runtests.$testCount.out\n";
778 # Some programs expect to run in the same directory as the executable
779 print BATOUT "$mpiexec $np_arg $np $extraArgs $mpiexecArgs $program_wrapper ./$programname $progArgs >> runtests.$testCount.out 2>&1\n";
780 print BATOUT "echo \$? > runtests.$testCount.status\n";
784 # Return value is 0 on success, non zero on failure
785 sub BuildMPIProgram {
786 my $programname = shift;
787 if (! -x $programname) {
788 die "Could not find $programname. Aborting.\n";
791 # THE FOLLOWING IS DISABLED.
794 if ($verbose) { print STDERR "making $programname\n"; }
795 if (! -x $programname) { $remove_this_pgm = 1; }
796 else { $remove_this_pgm = 0; }
797 my $output = `make $programname 2>&1`;
799 if ($rc > 255) { $rc >>= 8; }
800 if (! -x $programname) {
801 print STDERR "Failed to build $programname; $output\n";
805 # Add a line to the summary file describing the failure
806 # This will ensure that failures to build will end up
807 # in the summary file (which is otherwise written by the
808 # RunMPIProgram step)
809 &RunPreMsg( $programname, $np, $curdir );
810 &RunTestFailed( $programname, $np, $curdir, "Failed to build $programname; $output", $xfail );
811 &RunPostMsg( $programname, $np, $curdir );
816 sub CleanUpAfterRun {
817 my $programname = $_[0];
819 # Check for that this program has exited. If it is still running,
820 # issue a warning and leave the application. Of course, this
821 # check is complicated by the lack of a standard access to the
822 # running processes for this user in Unix.
823 @stillRunning = &FindRunning( $programname );
825 if ($#stillRunning > -1) {
826 print STDERR "Some programs ($programname) may still be running:\npids = ";
827 for (my $i=0; $i <= $#stillRunning; $i++ ) {
828 print STDERR $stillRunning[$i] . " ";
831 # Remind the user that the executable remains; we leave it around
832 # to allow the programmer to debug the running program, for which
833 # the executable is needed.
834 print STDERR "The executable ($programname) will not be removed.\n";
837 if ($remove_this_pgm && $clean_pgms) {
838 unlink $programname, "$programname.o";
840 $remove_this_pgm = 0;
843 # ----------------------------------------------------------------------------
845 my $programname = $_[0];
848 my $logname = $ENV{'USER'};
850 my $rc = open PSFD, "ps auxw -U $logname 2>&1 |";
853 $rc = open PSFD, "ps -fu $logname 2>&1 |";
856 print STDERR "Could not execute ps command\n";
861 if (/$programname/) {
862 @fields = split(/\s+/);
863 my $pid = $fields[$pidloc];
864 # Check that we've found a numeric pid
865 if ($pid =~ /^\d+$/) {
866 $pids[$#pids + 1] = $pid;
874 # ----------------------------------------------------------------------------
876 # TestStatus is a special test that reports success *only* when the
877 # status return is NONZERO
880 my $programname = $_[1];
885 #print STDOUT $_ if $verbose;
887 if (/FORTRAN STOP/) { next; }
889 # ANY output is an error. We have the following output
890 # exception for the Hydra process manager.
893 print STDERR "Unexpected output in $programname: $_";
900 $rc = close ( MPIOUT );
903 $signal_num = $run_status & 127;
904 if ($run_status > 255) { $run_status >>= 8; }
907 # This test *requires* non-zero return codes
912 $inline .= "$mpiexec returned a zero status but the program returned a nonzero status\n";
914 return ($found_error,$inline);
917 # TestTimeout is a special test that reports success *only* when the
918 # status return is NONZERO and there are no processes left over.
919 # This test currently checks only for the return status.
922 my $programname = $_[1];
927 #print STDOUT $_ if $verbose;
929 if (/FORTRAN STOP/) { next; }
931 if (/[Tt]imeout/) { next; }
932 # Allow 'signaled with Interrupt' (see gforker mpiexec)
933 if (/signaled with Interrupt/) { next; }
934 # Allow 'job ending due to env var MPIEXEC_TIMEOUT' (mpd)
935 if (/job ending due to env var MPIEXEC_TIMEOUT/) { next; }
936 # Allow 'APPLICATION TIMED OUT' (hydra)
937 if (/\[mpiexec@.*\] APPLICATION TIMED OUT/) { last; }
938 # ANY output is an error (other than timeout)
940 print STDERR "Unexpected output in $programname: $_";
947 $rc = close ( MPIOUT );
950 $signal_num = $run_status & 127;
951 if ($run_status > 255) { $run_status >>= 8; }
954 # This test *requires* non-zero return codes
959 $inline .= "$mpiexec returned a zero status but the program returned a nonzero status\n";
962 # Here should go a check of the processes
963 # open( PFD, "ps -fu $LOGNAME | grep -v grep | grep $programname |" );
968 return ($found_error,$inline);
971 # TestErrFatal is a special test that reports success *only* when the
972 # status return is NONZERO; it ignores error messages
975 my $programname = $_[1];
980 #print STDOUT $_ if $verbose;
982 if (/FORTRAN STOP/) { next; }
984 # ALL output is allowed.
986 $rc = close ( MPIOUT );
989 $signal_num = $run_status & 127;
990 if ($run_status > 255) { $run_status >>= 8; }
993 # This test *requires* non-zero return codes
998 $inline .= "$mpiexec returned a zero status but the program returned a nonzero status\n";
1000 return ($found_error,$inline);
1003 # ----------------------------------------------------------------------------
1005 # RunPreMsg( programname, np, workdir ) - Call before running a program
1006 # RunTestFailed, RunTestPassed - Call after test
1007 # RunPostMsg - Call at end of each test
1010 my ($programname,$np,$workdir) = @_;
1012 print XMLOUT "<MPITEST>$newline<NAME>$programname</NAME>$newline";
1013 print XMLOUT "<NP>$np</NP>$newline";
1014 print XMLOUT "<WORKDIR>$workdir</WORKDIR>$newline";
1018 my ($programname, $np, $workdir) = @_;
1020 print XMLOUT "</MPITEST>$newline";
1024 my ($programname, $np, $workdir, $xfail) = @_;
1026 print XMLOUT "<STATUS>pass</STATUS>$newline";
1031 $xfailstr = " # TODO $xfail";
1033 print TAPOUT "ok ${total_run} - $workdir/$programname ${np}${xfailstr}\n";
1037 my $programname = shift;
1039 my $workdir = shift;
1045 # basic escapes that wreck the XML output
1046 $xout =~ s/</\*AMP\*lt;/g;
1047 $xout =~ s/>/\*AMP\*gt;/g;
1048 $xout =~ s/&/\*AMP\*amp;/g;
1049 $xout =~ s/\*AMP\*/&/g;
1050 # TODO: Also capture any non-printing characters (XML doesn't like them
1052 print XMLOUT "<STATUS>fail</STATUS>$newline";
1053 print XMLOUT "<TESTDIFF>$newline$xout</TESTDIFF>$newline";
1059 $xfailstr = " # TODO $xfail";
1061 print TAPOUT "not ok ${total_run} - $workdir/$programname ${np}${xfailstr}\n";
1062 print TAPOUT " ---\n";
1063 print TAPOUT " Directory: $workdir\n";
1064 print TAPOUT " File: $programname\n";
1065 print TAPOUT " Num-procs: $np\n";
1066 print TAPOUT " Date: \"" . localtime . "\"\n";
1068 # The following would be nice, but it leads to unfortunate formatting in
1069 # the Jenkins web output for now. Using comment lines instead, since
1070 # they are easier to read/find in a browser.
1071 ## print TAPOUT " Output: |\n";
1072 ## # using block literal format, requires that all chars are printable
1073 ## # UTF-8 (or UTF-16, but we won't encounter that)
1074 ## foreach my $line (split m/\r?\n/, $output) {
1076 ## # 4 spaces, 2 for TAP indent, 2 more for YAML block indent
1077 ## print TAPOUT " $line\n";
1080 print TAPOUT " ...\n";
1082 # Alternative to the "Output:" YAML block literal above. Do not put any
1083 # spaces before the '#', this causes some TAP parsers (including Perl's
1084 # TAP::Parser) to treat the line as "unknown" instead of a proper
1086 print TAPOUT "## Test output (expected 'No Errors'):\n";
1087 foreach my $line (split m/\r?\n/, $output) {
1089 print TAPOUT "## $line\n";
1095 my $programname = shift;
1097 my $workdir = shift;
1100 # simply omit from the XML output
1103 print TAPOUT "ok ${total_seen} - $workdir/$programname $np # SKIP $reason\n";
1107 # ----------------------------------------------------------------------------
1108 # Alternate init routines
1109 sub InitQuickTimeout {
1110 $ENV{"MPIEXEC_TIMEOUT"} = 10;