#!/usr/bin/env perl
##**************************************************************
##
## Copyright (C) 1990-2007, 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.
##
##**************************************************************

package MyChimera;
require 5.005;			# don't use 5.x.y string
use strict;
use File::Spec;			# standard module
use File::Basename;		# standard module
use File::Temp qw(tempfile);	# 5.6.1 standard module

use Exporter;
use lib dirname($0);

use MyCommon;
use MyJavaVM qw(check4jar $java $java_home $classpath);

# declare prototypes before exporting them
sub check_chimera();
use vars qw(@ISA @EXPORT @EXPORT_OK);

@ISA = qw(Exporter);
@EXPORT = qw(ListTests RunTests);
@EXPORT_OK = qw();

sub run_class($$$) {
    # purpose: start a java class
    # paramtr: $class (IN): the name of the class to run
    #          $args (IN): array ref with CLI arguments
    #          $defs (IN): array ref with additional property definitions
    # returns: [0]: the return value as exit code
    #          [1]: first line of output...
    my $class = shift || die "assert: class is invalid\n";
    my $args = shift || [];
    my $defs = shift || [];

    my $cli = "$java \"-Dvds.home=\\\$VDS_HOME\"";
    foreach my $arg ( @$defs ) { $cli .= " \"-D$arg\"" };
    $cli .= " $class";
    foreach my $arg ( @$args ) { $cli .= " $arg" };

    my @output = `$cli 2>&1`;
    if ( $? == 0 ) {
	print "OK: Successfully ran class $class\n";
    } else {
	my $rv = $? >> 8;
	print "FAILURE! exit code $rv\n";
	print "Unable to run class $class. This bodes very ill.\n";
	print "# ", join("\n# ",@output), "\n";
    }
    ( $?, @output );
}

sub InitTests( ) {
    ResultInit( "chimera" );
}

sub RunTests() {
    # purpose: check out local Java installation
    # paramtr: -
    # returns: undef on error, true otherwise

    # Have we run already?
    if ( TestRan( "chimera" ) ) {
	return 0;
    }

    # Skip?
    if ( ! TestEnabled( "chimera" ) ) {
	return 0;
    }

    # Did Java run & pass?
    if ( ! TestRan( "javavm" ) )
    {
	# If it's already scheduled to be run, reset done & return..
	if ( TestEnabled( "javavm" ) ) {
	    $main::Done = 0;
	    return 0;
	}

	# Find out if the user want's to run it...
	print "\nSorry, but you must run the java test in order to initialize some\n";
	print "variables for the Chimera test. Say skip to skip the Chimera test, too.\n";
	unless ( wait_enter('[enter to run or say skip] ') =~ /skip/i ) {
	    TestEnable( "javavm", 1 );
	}
	return 0;
    }
    # How'd it do?
    my $JavaRes = GetResult( "javavm" );
    if ( $JavaRes->{Status} < 0 ) {
	print "\nThe Java test suite failed, skipping Chimera.\n";
	return 0;
    }

    # Set the status name
    SetTestName( "chimera" );
    SetTestRan( 1 );

    #
    # check for $VDS_HOME
    #
    my $vdshome = $ENV{'VDS_HOME'};
    if ( defined $vdshome ) {
	print "OK: VDS_HOME=$vdshome\n";
    } else {
	print "FAILURE!\n";
	print "You need to set the VDS_HOME variable, before you can run Chimera stuff.\n";
	return Ret( -1, "VDS_HOME not set" );
    }

    my $bindir = File::Spec->catfile($vdshome,'bin');
    if ( -d $bindir ) {
	print "OK: Found $bindir directory\n";
    } else {
	print "FAILURE!\n";
	print "Though VDS_HOME is set, its $bindir points into Nirwana.\n";
	return Ret( -1, "$bindir invalid" );
    }

    if ( grep( /$bindir/, File::Spec->path ) > 0 ) {
	print "OK: $bindir is part of your PATH.\n";
    } else {
	print "WARNING: $bindir is not part of your PATH.\n";
	# add to PATH so that next test finds it
	$ENV{PATH} .= ":$bindir";
    }

    #
    # check for all Chimera binaries
    #
    foreach my $exe ( qw(deletevdc gencdag gendax insertvdc replica-catalog 
			 replica-catalog-init searchvdc test-version updatevdc 
			 vdlt2vdlx vdlx2vdlt shplanner) ) {
	my $prg = find_exec($exe);
	unless ( defined $prg ) {
	    print "FAILURE!\n";
	    print "Unable to find the location of $exe. Please make extra sure that\n";
	    print "your Chimera installation is complete, e.g. comes from the VDT.\n";
	    return Ret( -1, "No $exe" );
	} else {
	    print "OK: Found $prg\n";
	}
    }

    print "\nYour executables are all there. Let\'s check for the libraries.\n";
    wait_enter;

    #
    # check for Chimera required 3rd party jars
    #
    foreach my $jar ( qw(antlrall.jar java-getopt-*.jar xercesImpl.jar) ) {
	my $result = check4jar($jar);
	if ( -r $result ) {
	    print "OK: Found $result\n";
	} else {
	    print "WARNING: Missing $jar\n";
	}
    }

    # check for Chimera jar
    my $developer;
    my $chimera = check4jar('chimera.jar');
    if ( defined $chimera ) {
	print "OK: Found $chimera\n";
    } else {
	# not found, are we developers?
	$developer=1;
	$chimera = (grep( /$vdshome/, split(/:/,$MyJavaVM::classpath) ))[0];
	if ( defined $chimera ) {
	    print "OK: Found $chimera in CLASSPATH\n";

	    # extra check: Are the libs compiled?
	    my $class = File::Spec->catfile( $chimera, 'org', 'griphyn', 'vdl', 'Chimera.class' );
	    if ( -r $class ) {
		print "OK: Your development distribution is in a compiled state\n";
	    } else {
		print "WARNING: You are missing essential class files. You appear to be a\n";
		print "developer. I will try to compile the java sources for you...\n";

		# need to compile Chimera
		my $here = File::Spec->curdir;
		chdir( $chimera );
		my $result = system( 'make-class.sh' );
		chdir( $here );
		print "\n";
		if ( $result != 0 ) {
		    print "Failure! exit code @{[$result >> 8]}\n";
		    print "I am unable to compile Chimera, and I don't have the chimera.jar file.\n";
		    print "I don\'t think that I can run any Chimera binary.\n";
		    return Ret( -1, "exit code @{[$result >> 8]}" );
		}
	    }
	} else {
	    print "\nFailure!\n";
	    print "I found neither the chimera.jar file, nor the VDS_HOME in your\n";
	    print "CLASSPATH. I don\'t think that I can run Chimera successfully.\n";
	    return Ret( -1, "No chimera.jar/VDS_HOME" );
	}
    }

    # create a hello world in VDLt
    my ($fh,$fn) = tempfile( 'testXXXXXX', DIR => ($ENV{TMP} || '/tmp') );
    unless ( defined $fh ) {
	print "FAILURE!\n";
	print "Unable to create a temporary file to store some VDLt.\n";
	print "Maybe the TMP directory does not work?\n";
	return Ret( -1, "Can't create temp file for VDL" );
    }

    print $fh "TR hw( output f )\n{\n";
    print $fh "  argument = \"Hello World!\";\n";
    print $fh '  argument stdout = ${f};', "\n}\n";
    print $fh 'DV d1->hw( f=@{output:"out.txt"} );', "\n";
    close($fh);
    print "OK: Created VDLt file\n";

    my ($result,$xml,$db,$dax);
    (undef,$xml) = tempfile( 'testXXXXXX', DIR => ($ENV{TMP} || '/tmp') );
    my $result = system( File::Spec->catfile( $ENV{'VDS_HOME'}, 'bin', 'vdlt2vdlx' ),
			 $fn, $xml );
    unlink($fn);

    if ( $result != 0 ) {
	unlink($xml);
	print "Failure! ", $result==-1 ? "$!\n" : "exit code @{[$result >> 8]}\n";
	print "I am unable to execute the VDLt to VDLx converter correctly.\n";
	print "You might want to check, if you can run it manually.\n";
	return Ret( -1, "Can't execute VDL or VDLx" );
    } else {
	print "OK: Converted VDLt to VDLx\n";
    }

    # add file to own personal database
    (undef,$db) = tempfile( 'testXXXXXX', DIR => ($ENV{TMP} || '/tmp') );
    unlink($db);
    $result = system( File::Spec->catfile( $ENV{'VDS_HOME'}, 'bin', 'insertvdc' ) .
		      " -d $db $xml >>/dev/null 2>&1" );
    unlink($xml);

    if ( $result != 0 ) {
	unlink($db);
	print "Failure! ", $result==-1 ? "$!\n" : "exit code @{[$result >> 8]}\n";
	print "I am unable to add the hello world data to a temp. database\n";
	print "You might want to check, if you can run it manually.\n";
	return Ret( -1, "Can't add \"hello world\" to temp database" );	
    } else {
	print "OK: Inserted VDLx into temporary database\n";
    }

    # run abstract planner
    (undef,$dax) = tempfile( 'testXXXXXX', DIR => ($ENV{TMP} || '/tmp') );
    $result = system( File::Spec->catfile( $ENV{'VDS_HOME'}, 'bin', 'gendax' ) .
		      " -d $db -l hw -o $xml -f out.txt >>/dev/null 2>&1" );
    unlink( $db, "$db.0", "$db.nr" );

    if ( $result != 0 ) {
	unlink($dax);
	print "Failure! ", $result==-1 ? "$!\n" : "exit code @{[$result >> 8]}\n";
	print "I am unable to run the abstract planner. This is not good.\n";
	print "I am at loss, why things fail now. Do you use NFS?\n";
	return Ret( -1, "Can't run abstract planner" );
    } else {
	print "OK: Ran abstract planner successfully\n";
    }

    print "\nFIXME: Add shell planner and run shell plan.\n";
    unlink($dax);

    print "\nYou did come far. Your Chimera actually might do the trick.\n";
    wait_enter;

    # return the perl way
    return 0;
}

1;
