#!/usr/bin/perl
#
#  This is a perl script to execute a single test driver program.  The script
#  will examine the return value of the test driver and capture STDOUT, STDERR
#  to files.  If the return value of the test driver is not zero, the test is
#  deemed a failure.  STDOUT and STDERR files will be place in a subdirectory
#  named temp and the files will be compared with verified STDOUT, STDERR files
#  in a subdirectory named verified.
#
#  Assumptions:  A verified subdirectory with STDOUT, STDERR files exists for 
#                the test driver specified in the arguements.
#
#  Return values:
#                 Bit mapped values
#                 0    Test run successfull and all tests passed
#                 1    Verified directory did not exist
#                 2    Verified STDOUT file did not exist
#                 4    Verified STDERR file did not exist
#                 8    STDOUT files did not compare
#                16    STDERR files did not compare
#                32    Test driver doesn't exist or is not executable
#            
#  SYNOSIS:  runTest testDriverName
#
#  $Revison:  $  $Name: not supported by cvs2svn $
#  $Date: 2004-04-27 01:47:20 $
#
#  Copyright 2004 Maui High Performance Computering Center, University of Hawaii
#
################################################################################

# Initialize exit value
$exitValue = 0;

# Set up the PSLIB_ROOT environment variable if the user doesn't have it set
if ( ! $ENV{'PSLIB_ROOT'}) {
    # Use the directory directly above test
    $PSLIB_ROOT = `cd ..;pwd`;
    # Remove newline for the end of path returned
    chomp($PSLIB_ROOT);
    # Set the environment variable
    $ENV{'PSLIB_ROOT'} = $PSLIB_ROOT;
    # Display message that PSLIB_ROOT not found and set to 
    print("PSLIB_ROOT not found: set to $PSLIB_ROOT\n");
}

# Add PSLIB_ROOT/lib to LD_LIBRARY_PATH and DYLD_LIBRARY_PATH environment vars
$ENV{'LD_LIBRARY_PATH'} = "$ENV{'PSLIB_ROOT'}/lib:$ENV{'LD_LIBRARY_PATH'}";
$ENV{'DYLD_LIBRARY_PATH'} = "$ENV{'PSLIB_ROOT'}/lib:$ENV{'DYLD_LIBRARY_PATH'}";

# Get test driver name from arguement list
$testFile = $ARGV[0];

# Check if a temp directory already exists in the current work directory
if ( !( -e "temp" )) {
   # Create temp directory to store STDOUT, STDERR files during test run
   `mkdir temp`;
   # Display message of new directory created
   print("Creating temp directory\n");
}

# Check if a verified directory exists in the current work directory
if ( !( -e "verified" )) {
    # Display message that verified subdirectory doesn't exist
    print("Verified directory doesn't exist.  Need verified STDOUT, STDERR files.\n");
    # Exit script since the test cannot be run with verified files
    exit(1);
}

# Check if the test driver file exists and is executable
if ( (-e $testFile) && (-x $testFile) ) {

    # Display message the test driver is being executed
    print("--- Executing test driver: $testFile\n");

    # Invoke the test driver
    system("./$testFile 1> temp/$testFile.stdout 2> temp/$testFile.stderr");

    # Check the return value of the test driver.  A value other than 0
    # indicates failure of the test driver unless the test driver is name
    # with a leading 'a' which indicates the test driver is expecting an
    # abort condition to terminate the driver.
    if ( ( $? != 0  && ( $testFile !~ /^A/i)) || 
         ( $? == 0  && ( $testFile =~ /^A/i)) ) {

        # Display failure message with return value to user
        if ( $? != 0 && ( $testFile !~ /^A/i) ) {
            print("Failed - Test Driver expected 0 return value (Return value $?)\n");
        } elsif ( $? == 0 && ( $testFile =~ /^A/i) ) {
            print("Failed - Test Driver expected abort (Return value $?)\n");
        }
    } else {
  
        # Test driver succeeded.
        
        # Check for existence of verified STDOUT files
        if ( !( -e "verified/$testFile.stdout") ) {
            
            # Display message to user that verified STDOUT file doesn't exist
            print("Verified file $testFile.stdout doesn't exist.  Test stopped.\n");
            
            # Set exit value bit 1 to indicate proper failure
            $exitValue |= 2;
        } else {

            # Verified STDOUT file exists
            
            # Open the STDOUT file for reading
            open(OUTFILE, "< temp/$testFile.stdout");
            # Open mod file to place filtered STDOUT
            open(MODFILE, ">temp/$testFile.stdout.mod");
            # Replace the variable date, time and host information with constants
            while( <OUTFILE> ) {
                s/\d+:\d+:\d+/ <DATE> /;
                s/\s+\d+:\d+:\d+\w/ <TIME> /;
                s/\|\S+\|/<HOST>| /;
                print MODFILE ($_);
            }
            # Close mod file
            close(MODFILE);
            # Close STDERR file
            close(OUTFILE);

            # Open the STDERR file for reading 
            open(OUTFILE, "< temp/$testFile.stderr");
            # Open mod file to place filtered STDERR
            open(MODFILE, "> temp/$testFile.stderr.mod");
            # Replace the variable date, time and host information with constants
            while( <OUTFILE> ) {
                s/\d+:\d+:\d+/ <DATE> /;
                s/\s+\d+:\d+:\d+\w/ <TIME> /;
                s/\|\S+\|/<HOST>| /;
                print MODFILE ($_);
            }
            # Close mod file
            close(MODFILE);
            # Close STDERR file
            close(OUTFILE);

            # Perform difference on the STDOUT files
            $diffstdout = `diff verified/$testFile.stdout temp/$testFile.stdout.mod`;

            # Check the return value of the difference
            if ( $? != 0 ) {
   
                # Difference of STDOUT files failed

                # Display message of the failure of difference to user
                print("Failed - STDOUT difference\n$diffstdout\n");
  
                # Exit value to indicate STDOUT did not compare
                $exitValue |= 8;
            } else {

                # STDOUT file compared successfully
                
                # Check for the existence of verified STDERR file
                if ( !( -e "verified/$testFile.stderr") ) {

                    # Display message to user that STDOUT file doesn't exist
                    print("Verified file $testFile.stderr doesn't exist.  Test stopped.\n");

                    $exitValue |= 4;
                } else {

                    # Perform difference on the STDERR files
                    $diffstderr = `diff verified/$testFile.stderr temp/$testFile.stderr.mod`;

                    # Check the return value of the difference
                    if ( $? != 0 ) {

                        # Difference of STDERR files failed

                        # Display message of the failure of difference to user
                        print("Failed - STDERR difference\n$diffstderr\n");

                        # Exit value set to indicate STDERR did not compare
                        $exitValue |= 16;
                    } else {

                        # Test driver passed, STDOUT, STDERR files compared
                    
                        # Display message test was successful
                        print("Test successful\n");
                    }
                }
            } 
        }
    }
} else {
    # Since test driver doesn't exist or is not executable then display 
    # message to user.
    print("Need to specify an executable test file within directory.\n");
    
    # Exit value set to indicate test driver doesn't exist or not executable
    $exitValue |= 32;
}

# Exit for the script with exit vale
exit($exitValue);

