#!/usr/bin/env perl
##**************************************************************
##
## Copyright (C) 1990-2011, Condor Team, Computer Sciences Department,
## University of Wisconsin-Madison, WI.
## 
## Licensed under the Apache License, Version 2.0 (the "License"); you
## may not use this file except in compliance with the License.  You may
## obtain a copy of the License at
## 
##    http://www.apache.org/licenses/LICENSE-2.0
## 
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
##**************************************************************


######################################################################
# run a test in the Condor testsuite
# return val is the status of the test
# 0 = built and passed
# 1 = build failed
# 2 = run failed
# 3 = internal fatal error (a.k.a. die)
######################################################################

######################################################################
###### WARNING!!!  The return value of this script has special  ######
###### meaning, so you can NOT just call die().  you MUST       ######
###### use the special c_die() method so we return 3!!!!        ######
######################################################################

use strict;
use warnings;
use File::Copy;
use File::Basename;
use POSIX qw/strftime/;

print STDERR "------------------------- ENV DUMP ------------------------\n";
foreach my $key (sort { uc($a) cmp uc($b) } keys %ENV) {
    print STDERR "$key=$ENV{$key}\n";
}
print STDERR "------------------------- ENV DUMP ------------------------\n";

my $force_cygwin = 1;
my $dir = dirname($0);
unshift @INC, $dir;
require "TestGlue.pm";
TestGlue::setup_test_environment();

if( ! defined $ENV{_NMI_TASKNAME} ) {
    die "_NMI_TASKNAME not in environment, can't test anything!\n";
}
my $fulltestname = $ENV{_NMI_TASKNAME};

if( $fulltestname =~ /remote_task/) {
    die "_NMI_TASKNAME set to remote_task meaning 0 tests seen!\n";
}

if( ! $fulltestname ) {
    # if we have no task, just return success immediately
    out("No tasks specified, returning SUCCESS");
    exit 0;
}

# must use cygwin perl on Windows for batch_test.pl
my $perl_exe = "perl";
if ($ENV{NMI_PLATFORM} =~ /winnt/) {
    my $perlver = `$perl_exe -version`;
    print $perlver;
    if ( ! $force_cygwin && ($ENV{COMPUTERNAME} =~ /^EXEC\-/)) { # if new batlab
        print "attempting to run tests using current perl\n";
	if ($ENV{PATH} =~ /[a-z]:\\condor\\bin;/i) {
            print "removing base condor from the path\n";
            my $tmppath = $ENV{PATH};
            $tmppath =~ s/[a-z]:\\condor\\bin;//i;
            if ($^O =~ /MSWin32/) {
	        if ($tmppath =~ /[a-z]:\\cygwin\bin;/i) {
                    print "removing cygwin from the path\n";
                    $tmppath =~ s/[a-z]:\\cygwin\bin;//i;
		}
	    }
            print "new PATH=$tmppath\n";
            $ENV{PATH} = $tmppath;
        }
    } elsif (!($perlver =~ /cygwin/i)) {
        print "adding cygwin to the front of the path\n";
        $ENV{PATH} = "c:\\cygwin\\bin;$ENV{PATH}";
		print "PATH=$ENV{PATH}\n";

		#$perl_exe = "c:\\cygwin\\bin\\perl";
		#print "Invoking cygwin perl by explicit path ($perl_exe)\n";
        $perlver = `$perl_exe -version`;
        print $perlver;
        if (!($perlver =~ /cygwin/i)) {
            die "cygwin perl not found!\n";
        }
    }
}


my $BaseDir  = $ENV{BASE_DIR} || c_die("BASE_DIR is not in environment!\n");
my $test_dir = File::Spec->catdir($BaseDir, "condor_tests");

# iterations have numbers placed at the end of the name
# for unique db tracking in nmi for now.
if($fulltestname =~ /([\w\-\.\+]+)-\d+/) {
    my $matchingtest = $fulltestname . ".run";
    if(!(-f $matchingtest)) {
        # if we don't have a test called this, strip iterator off
        $fulltestname = $1;
    }
}


######################################################################
# get the testname and group
######################################################################

my @testinfo = split(/\./, $fulltestname);
my $testname = $testinfo[0];
my $compiler = $testinfo[1];

if( ! $testname ) {
    c_die("Invalid input for testname\n");
}

out("Testname: '$testname'");
if( not TestGlue::is_windows() ) {
    if( $compiler ) {
        out("compiler is $compiler");
    }
    else {
        $compiler = ".";
    }
}
else {
    $compiler = ".";
}

######################################################################
# run the test using batch_test.pl
######################################################################

# Some of the tests fail because the schedd fsync can take 30 seconds
# or more on busy nmi filesystems, which causes the tools to timeout.
# Up the tool timeout multipler to try to deal with this.
$ENV{_condor_TOOL_TIMEOUT_MULTIPLIER}="4";

out("RUNNING $testname");
chdir($test_dir) || c_die("Can't chdir($test_dir): $!\n");

# -b means build & test and ensures the first time that we have our testing
# personal condor configured from release generic config files.
out("About to run batch_test.pl");

system("$perl_exe batch_test.pl -d $compiler -t $testname -b");
my $batchteststatus = $?;

# figure out here if the test passed or failed.  
my $teststatus;
if( $batchteststatus != 0 ) {
    $teststatus = 2;
}
else {
    $teststatus = 0;
}

######################################################################
# print output from .run script to stdout of this task, and final exit
######################################################################

my $compiler_path = File::Spec->catpath($test_dir, $compiler);
chdir($compiler_path) || c_die("Can't chdir($compiler_path): $!\n");
my $run_out       = "$testname.run.out";
my $run_out_path  = File::Spec->catfile($compiler_path, $run_out);
my $test_out      = "$testname.out";
my $test_out_path = File::Spec->catfile($compiler_path, $test_out);
my $test_err      = "$testname.err";
my $test_err_path = File::Spec->catfile($compiler_path, $test_err);

if( ! -f $run_out_path ) {
    if( $teststatus == 0 ) {
        # if the test passed but we don't have a run.out file, we
        # should consider that some kind of weird error
        c_die("ERROR: test passed but $run_out does not exist!");
    }
    else {
        # if the test failed, this isn't suprising.  we can print it, 
        # but we should just treat it as if the test failed, not an
        # internal error. 
        out("\n\nTest failed and $run_out does not exist");
    }
}
else {
    # spit out the contents of the run.out file to the stdout of the task
    if( open(RES, '<', $run_out_path) ) {
        out("\n\n----- Start of $run_out -----");
        while(<RES>) {
            print "$_";
        }
        close RES;
        print "\n----- End of $run_out -----\n";
    }
    else {
        out("\n\nERROR: failed to open $run_out_path: $!");
    }
}

# add test.out and test.err to run output if they exist

# spit out the contents of the test.out file to the stdout of the task
if( open(RES, '<', $test_out_path) ) {
    out("\n\n----- Start of $test_out -----");
    while(<RES>) {
        print "$_";
    }
    close RES;
    print "\n----- End of $test_out -----\n";
}
else {
    out("\n\nERROR: failed to open $test_out_path: $!");
}

# spit err the contents of the test.err file to the stdout of the task
if( open(RES, '<', $test_err_path) ) {
    out("\n\n----- Start of $test_err -----");
    while(<RES>) {
        print "$_";
    }
    close RES;
    print "\n----- End of $test_err -----\n";
}
else {
    out("\n\nERROR: failed to open $test_err_path: $!");
}

exit $teststatus;

######################################################################
# helper methods
######################################################################

sub c_die {
    my($msg) = @_;
    out($msg);
    exit 3;
}

sub out {
    my ($msg) = @_;
    my $time = strftime("%y/%m/%d %H:%M:%S", localtime);
    print "$time: $msg\n";
}
