#!/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 lib "$ENV{BASE_DIR}/condor_tests";

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

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

push @INC, "$ENV{BASE_DIR}/condor_tests";

#foreach my $path (@INC) {
	#print "INC: $path\n";
#}

require CondorTest;
require CondorPersonal;
require CondorUtils;
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} =~ /_win/i) {
#    my $perlver = `$perl_exe -version`;
#    print $perlver;
#    if ( !$force_cygwin ) {
#        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");

# does this test need a personal?
my $need = "";
$need = DoesTestNeedPersonal($testname);

my $iswindows = CondorUtils::is_windows();
my $iscygwin  = CondorUtils::is_cygwin_perl();

# lets try to find needed windows initializations

# remove . from path
#CleanFromPath(".");
# yet add in base dir of all tests and compiler directories
 #$ENV{PATH} = $ENV{PATH} . ":" . $BaseDir;
# add 64 bit  location for java
#if($iswindows == 1) {
	#$ENV{PATH} = $ENV{PATH} . ":/cygdrive/c/windows/sysnative:c:\\windows\\sysnative";
#}

if($need ne "") {
	print "Test $testname DOES require a personal\n";
	StartTestPersonal($testname);
} else {
	print "Test $testname does not require a personal\n";
}


# Now that we stash all debug messages, we'll only dump them all
# when the test fails. This will be debugs at all levels.
#system("$perl_exe batch_test.pl -d $compiler -t $testname -b --isolated -v");
#system("$perl_exe batch_test.pl -d $compiler -t $testname -b --isolated");
# must use cygwin perl on Windows for batch_test.pl
my $perl_exe = "perl";
if ($ENV{NMI_PLATFORM} =~ /_win/i) {
    my $perlver = `$perl_exe -version`;
    print $perlver;
    if ( !$force_cygwin ) {
        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 $batchteststatus = system("$perl_exe batch_test.pl -d $compiler -t $testname");

my @returns = TestGlue::ProcessReturn($batchteststatus);

$batchteststatus = $returns[0];
my $signal = $returns[1];

if($signal != 0) {
	print "a signal error was involved:$signal\n";
}

# figure out here if the test passed or failed.  
my $teststatus;
if( $batchteststatus != 0 ) {
	CondorTest::RegisterResult(0,"test_name",$testname);
}

if($need ne "") {
	print "Stopping personal for test:$testname\n";
	CondorTest::RegisterResult(1,"test_name",$testname);
	StopTestPersonal($testname);
}

######################################################################
# 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);

print "Looking for run.out file\n";
print "compiler_path:$compiler_path run_out:$run_out run_out_path:$run_out_path compiler_path:$compiler_path\n";
print "test_out:$test_out test_out_path:$test_out_path test_err:$test_err test_err_path:$test_err_path\n";
print "Here now:\n";
system("pwd;ls -lh $run_out_path");

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: $!");
#}

print "********************** EXIT REMOTE_TASK: Status:$batchteststatus ******************\n";
exit $batchteststatus;

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

sub DoesTestNeedPersonal {
	my $test = shift;
	my $ret = "";
	my $personallist = "personal_list";

	open(PL,"<$personallist") or die "Can not open $personallist:$!\n";
	my $line = "";
	while(<PL>) {
		CondorUtils::fullchomp($_);
		$line = $_;
		if($test =~ /$line/) {
			return($test);
		}
	}
	return($ret);
}

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

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


sub StartTestPersonal {
	my $test = shift;

	my $firstappend_condor_config = '
    	DAEMON_LIST = MASTER,SCHEDD,COLLECTOR,NEGOTIATOR,STARTD
    	ALL_DEBUG = D_ALWAYS
	';

	my $configfile = CondorTest::CreateLocalConfig($firstappend_condor_config,"remotetask$test");

	CondorTest::StartCondorWithParams(
    	condor_name => "remotetask$test",
    	fresh_local => "TRUE",
    	condorlocalsrc => "$configfile",
		test_glue => "TRUE",
	);
}

sub showEnv {
	foreach my $env (sort keys %ENV) {
		print "$env: $ENV{$env}\n";
	}
}

sub StopTestPersonal {
	CondorTest::EndTest("no_exit");
}


