#! /usr/bin/env perl

BEGIN
{
    push(@INC, $ENV{'GLOBUS_LOCATION'} . '/lib/perl');
}

use Globus::Core::Paths;
use IO::File;
use Sys::Hostname;
use Test;
use File::Path;
use File::Compare;

my (@tests, @todo) = ();
my $contact = $ENV{CONTACT_STRING};
my $testtmp = &make_tmpdir();
my $testdatadir = "$ENV{GLOBUS_LOCATION}/share/globus_gram_job_manager_test";
my $verbose = 0;

my @test_cases=qw(
    stdio001 stdio002 stdio003 stdio004 stdio005
    stdio006 stdio007 stdio008 stdio009 stdio010
    stdio011 stdio012 stdio013 stdio014 stdio015
    stdio016 stdio017 stdio018 stdio019
);

sub test_rsl
{
    my $testname = shift;
    my $additional_rsl = shift;
    my $testrsl = "$testname.rsl";
    my $additionalrslfile = "$testtmp/$testname.rsl";
    my $test_rsl_fp = new IO::File("$testdatadir/$testrsl", '<');
    my $out_rsl_fp = new IO::File($additionalrslfile, '>');
    my $rsl_list;
    my $out_count;
    my $all_rsl;

    $rsl_list = join('', <$test_rsl_fp>);
    $rsl_list =~ s/&//;
    $rsl_list =~ m/\(\*\s+(\d+)\s+\*\)/;
    $out_count = $1;

    $test_rsl_fp->close();

    $out_rsl_fp->print('&');
    $all_rsl = '&';

    # need to put the RSL substitutions in the additional RSL
    # before the main RSL clauses
    if($additional_rsl ne '')
    {
	$out_rsl_fp->print($additional_rsl . "\n");
	$all_rsl .= "$additional_rsl\n";
    }
    $out_rsl_fp->print($rsl_list);
    $all_rsl .= $rsl_list;
    
    $out_rsl_fp->close();

    if($verbose)
    {
	print "# Submitting job\n";

	foreach(split(/\n/, $all_rsl))
	{
	    print "#    $_\n";
	}
    }

    system("globusrun -s -r \"$contact\" -f $additionalrslfile");

    $rc = $? >> 8;

    if($rc != 0)
    {
	for(my $i = 0; $i < $out_count; $i++)
	{
	    my $out_name = sprintf("%s.%03d",
	                           "$testtmp/$testname.out.",
				   $i+1);
	    my $err_name = sprintf("%s.%03d",
	                           "$testtmp/$testname.err.",
				   $i+1);
            my $canonical_out = "$testdatadir/$testname.out";
            my $canonical_err = "$testdatadir/$testname.err";

	    if(File::Compare::compare($out_name, $canonical_out) != 0)
	    {
		$rc = sprintf("comparison of output file %d failed", $i+1);
		last;
	    }
	    if(File::Compare::compare($err_name, $canonical_err) != 0)
	    {
		$rc = sprintf("comparison of error file %d failed", $i+1);
		last;
	    }
	}
    }

    ok("$testname:$rc", "$testname:0");
}

foreach(@test_cases)
{
    my $testtmprsl
        = "(rsl_substitution = "
        . "   (TEST_STDOUT \\\"$testtmp/$_.out\\\")"
        . "   (TEST_STDERR \\\"$testtmp/$_.err\\\")"
	. "   (TEST_FTP_PREFIX \\\"gsiftp://". hostname . "/%2F\\\")"
	. ")";
    push(@tests, "test_rsl(\"$_\", \"$testtmprsl\")");
}
if(@ARGV)
{
    my @doit;

    $verbose = 1;

    foreach(@ARGV)
    {
        if(/^(\d+)-(\d+)$/)
        {
            foreach($1 .. $2)
            {
               push(@doit, $_);
            }
        }
        elsif(/^(\d+)$/)
        {
            push(@doit, $1);
        }
    }
    plan tests => scalar(@doit);

    foreach (@doit)
    {
        eval "&$tests[$_-1]";
    }
}
else
{
    plan tests => scalar(@tests), todo => \@todo;

    foreach (@tests)
    {
	eval "&$_";
    }
}

sub make_tmpdir
{
    my $root;
    my $suffix = '/gram_jobmanager_test_';
    my $created = 0;
    my $tmpname;
    my @acceptable = split(//, "abcdefghijklmnopqrstuvwxyz".
			       "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
			       "0123456789");
    if(exists($ENV{TMPDIR}))
    {
	$root = $ENV{TMPDIR};
    }
    else
    {
	$root = '/tmp';
    }
    while($created == 0)
    {
	$tmpname = $root . $suffix .
	           $acceptable[rand() * $#acceptable] .
	           $acceptable[rand() * $#acceptable] .
	           $acceptable[rand() * $#acceptable] .
	           $acceptable[rand() * $#acceptable] .
	           $acceptable[rand() * $#acceptable] .
	           $acceptable[rand() * $#acceptable];
	$created = mkdir($tmpname, 0700);
	if($created)
	{
	    if(-l $tmpname or ! -d $tmpname or ! -o $tmpname)
	    {
		$created = 0;
	    }
	}
    }
    return $tmpname;
}

END
{
    if(-d $testtmp and -o $testtmp)
    {
	File::Path::rmtree($testtmp);
    }
}
