#!/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;

my $force_cygwin = 0;

BEGIN {
	my $dir = dirname($0);
	push @INC, $dir;
}

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

use TestGlue;

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

#if($iswindows == 1) {
#	if($iscygwin == 1) {
#		out("Entering remote_task using cygwin perl");
#	} else {
#		out("Entering remote_task using active state perl");
#	}
#}

TestGlue::setup_test_environment();

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

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;
}


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("REMOTE_TASK.$$ 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.
out("Setting _condor_TOOL_TIMEOUT_MULTIPLIER=4");
$ENV{_condor_TOOL_TIMEOUT_MULTIPLIER}="4";

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

############################################################
##
##
## Here we examine some requirements which we know about
## now and in the futue we already have a list for personals
## but we could expand those into our new more general way.
##
## The new list Test_Requirements file
## has the base test name separated by a colon to a commma
## separated list of requirements
##
## claasad_cache-basic : cygwin
##
## So we look for our test to have requirements by reading the file
## and if we find it we split the requirements into an array
## and then process the array of requirements.
##
############################################################

my @testrequirements = ();
my $commalist = "";
my %requirements = ();
my $line = "";

open(TR,"<Test_Requirements") or die "Failed to open:Test_Requirements:$!\n";
while(<TR>) {
	TestGlue::fullchomp($_);
	$line = $_;
	if($line =~ /\s*$testname\s*:\s*(.*)/) {
		$commalist = $1;
		@testrequirements = split /,/, $commalist;
		foreach my $need (@testrequirements) {
			out("$testname needs: $need");
			if(exists $requirements{$need}) {
				die "Requirement:$need already exists\n"
			} else {
				$requirements{$need} = 1;
				out("set need for:$need");
			}
		}
	}
}
close(TR);

# does this test need a personal?
#my $need = DoesTestNeedPersonal($testname);
if (exists $requirements{personal}) {
    out("'$testname' requires a personal HTCondor, starting one now.");
    StartTestPersonal($testname);
} else {
#    out("'$testname' does not require a personal HTCondor");
}

# Now that we stash all debug messages, we'll only dump them all
# when the test fails. This will be debugs at all levels.

# 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`;
    if ($perlver =~ /This is (perl .*)$/m) { $perlver = $1; }
    out("First perl is $perlver.");
    if ( !(exists $requirements{cygwin})) {
        out("attempting to run tests using current perl");
		if ($ENV{PATH} =~ /[a-z]:\\condor\\bin;/i) {
            out("removing base condor from the path");
            my $tmppath = $ENV{PATH};
            $tmppath =~ s/[a-z]:\\condor\\bin;//i;
            if ($^O =~ /MSWin32/) {
	       		if ($tmppath =~ /[a-z]:\\cygwin\\bin;/i) {
                    out("removing cygwin from the path");
					#out("Before removal:$tmppath\n");
                    $tmppath =~ s/[a-z]:\\cygwin\\bin;//ig;
				}
	    	}
            #out("new PATH=$tmppath");
            $ENV{PATH} = $tmppath;
        }
    } elsif (!($perlver =~ /cygwin/i)) {
        out("Adding cygwin to the front of the path to force the use of cygwin perl.");
        $ENV{PATH} = "c:\\cygwin\\bin;$ENV{PATH}";
		out("new PATH=$ENV{PATH}");

        $perlver = `$perl_exe -version`;
		if ($perlver =~ /This is (perl .*)$/m) { $perlver = $1; }
        out("First perl is now $perlver.");
        if (!($perlver =~ /cygwin/i)) {
            die "cygwin perl not found!\n";
        }
    }
    #my $newpath = join("\n", split(';',$ENV{PATH}));
    #out("PATH is now\n$newpath");
}

# alternative arguments for batch test...
#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");

out("RUNNING batch_test.pl -t '$testname'\n---------");
my $batchteststatus = system("$perl_exe batch_test.pl -d $compiler -t $testname");
print "---------\n"; # we print here rather than using out() in order to bracket the batch test output with ----- above and below.
my @returns = TestGlue::ProcessReturn($batchteststatus);

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

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

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

if(exists $requirements{personal}) {
	my $exit_status = 0;
	out("Stopping personal HTCondor for '$testname'");
	$exit_status = StopTestPersonal($testname);
	if($exit_status == 1) {
		print "Failing test due to either a core file or ERRORs in Log(s)\n";
		print "a couple other possibilities. look at CondorTest::EndTest\n";
		# done in EndTest
        #CondorTest::RegisterResult(0,"test_name",$testname);
		$batchteststatus = $exit_status;
    } else {
		# will go with currrent value in $batchteststatus
        #CondorTest::RegisterResult(1,"test_name",$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);

out("Looking for run.out file");
out("compiler_path:$compiler_path run_out:$run_out run_out_path:$run_out_path compiler_path:$compiler_path");
out("test_out:$test_out test_out_path:$test_out_path test_err:$test_err test_err_path:$test_err_path");
#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("WTF 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("No test output... Test 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("Printing test output...\n\n----- Start of $run_out -----");
        while(<RES>) {
            print "$_";
        }
        close RES;
        print "\n----- End of $run_out -----\n";
    }
    else {
        out("Printing test output...  ERROR: failed to open $run_out_path: $!");
    }
}


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

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

sub ProcessTestRequirements
{
	my $requirementslist = "Test_Requirements";
}

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>) {
		TestGlue::fullchomp($_);
		$line = $_;
		if($test =~ /$line/) {
			return($test);
		}
	}
	return($ret);
}

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

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 {
	my $exit_status = 0;
	$exit_status = CondorTest::EndTest("no_exit");
	return($exit_status);
}


