#! /usr/bin/env perl
#testreq: personal
##**************************************************************
##
## 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.
##
##**************************************************************

## This makes sure that writing the jobstate.log file works correctly.

use CondorTest;
use CondorUtils;

$cmd = 'job_dagman_jobstate_log-wrapper.dag';
$testdesc =  'Condor submit dag - jobstate.log test - scheduler U';
$testname = "job_dagman_jobstate_log";
$dagman_args = "-verbose";

@logfiles = ("job_dagman_jobstate_log-wrapper.dag.dagman.out",
	"job_dagman_jobstate_log.dag.dagman.out");

@outfiles = ("job_dagman_jobstate_log.dag.jobstate.log");

# Note: we must find these lines *in the specified order*.
# Pre script events, and POST_SCRIPT_STARTED events, are not currently
# generated in recovery mode.
@outlines = (
	'^\d+ NodeA PRE_SCRIPT_STARTED - local - 1$',
	'^\d+ NodeA PRE_SCRIPT_SUCCESS - local - 1$',
	'^\d+ NodeA SUBMIT \d+.\d local - 1$',
	'^\d+ NodeA SUBMIT \d+.\d local - 1$',
	'^\d+ NodeA JOB_FAILURE 2 local - 1$',
	'^\d+ NodeA POST_SCRIPT_STARTED \d+.0 local - 1$',
	'^\d+ NodeA POST_SCRIPT_TERMINATED \d+.0 local - 1$',
	'^\d+ NodeA POST_SCRIPT_SUCCESS \d+.0 local - 1$',
	'^\d+ NodeB PRE_SCRIPT_STARTED - viz - 2$',
	'^\d+ NodeB PRE_SCRIPT_SUCCESS - viz - 2$',
	'^\d+ NodeB SUBMIT \d+.\d viz - 2$',
	'^\d+ NodeB EXECUTE \d+.\d viz - 2$',
	'^\d+ NodeB JOB_TERMINATED \d+.\d viz - 2$',
	'^\d+ NodeB JOB_SUCCESS 0 viz - 2$',
	'^\d+ NodeB POST_SCRIPT_STARTED \d+.0 viz - 2$',
	'^\d+ NodeB POST_SCRIPT_TERMINATED \d+.0 viz - 2$',
	'^\d+ NodeB POST_SCRIPT_SUCCESS \d+.0 viz - 2$',
	'^\d+ NodeC PRE_SCRIPT_STARTED - - - 3$',
	'^\d+ NodeC PRE_SCRIPT_SUCCESS - - - 3$',
	'^\d+ NodeC SUBMIT \d+.0 - - 3$',
	'^\d+ NodeC EXECUTE \d+.0 - - 3$',
	'^\d+ NodeC JOB_TERMINATED \d+.0 - - 3$',
	'^\d+ NodeC JOB_SUCCESS 0 - - 3$',
	'^\d+ NodeC POST_SCRIPT_STARTED \d+.0 - - 3$',
	'^\d+ NodeC POST_SCRIPT_TERMINATED \d+.0 - - 3$',
	'^\d+ NodeC POST_SCRIPT_FAILURE \d+.0 - - 3$',
	'^\d+ NodeC PRE_SCRIPT_STARTED - - - 4$',
	'^\d+ NodeC PRE_SCRIPT_SUCCESS - - - 4$',
	'^\d+ NodeC SUBMIT \d+.0 - - 4$',
	'^\d+ NodeC EXECUTE \d+.0 - - 4$',
	'^\d+ NodeC JOB_TERMINATED \d+.0 - - 4$',
	'^\d+ NodeC JOB_SUCCESS 0 - - 4$',
	'^\d+ NodeC POST_SCRIPT_STARTED \d+.0 - - 4$',
	'^\d+ NodeC POST_SCRIPT_TERMINATED \d+.0 - - 4$',
	'^\d+ NodeC POST_SCRIPT_SUCCESS \d+.0 - - 4$',
	'^\d+ NodeD SUBMIT \d+.0 - - 5$',
	'^\d+ NodeD EXECUTE \d+.0 - - 5$',
	'^\d+ NodeD JOB_TERMINATED \d+.0 - - 5$',
	'^\d+ NodeD JOB_FAILURE 1 - - 5$',
	'^\d+ NodeD SUBMIT \d+.0 - - 6$',
	'^\d+ NodeD EXECUTE \d+.0 - - 6$',
	'^\d+ NodeD JOB_TERMINATED \d+.0 - - 6$',
	'^\d+ NodeD JOB_SUCCESS 0 - - 6$',
	'^\d+ NodeE SUBMIT_FAILURE - - - 7$',
	'^\d+ NodeE SUBMIT_FAILURE - - - 7$',
	'^\d+ NodeE POST_SCRIPT_STARTED - - - 7$',
	'^\d+ NodeE POST_SCRIPT_TERMINATED - - - 7$',
	'^\d+ NodeE POST_SCRIPT_SUCCESS - - - 7$');

my $killedchosen = 0;

# truly const variables in perl
sub IDLE{1};
sub HELD{5};
sub RUNNING{2};

# Get rid of any existing log files.
foreach $name (@logfiles) {
	if (-e $name) {
		runcmd("rm -f $name");
	}
}

# Get rid of any existing output files.
foreach $name (@outfiles) {
	if (-e $name) {
		runcmd("rm -f $name");
	}
}

# Remove any existing rescue DAGs.
runcmd("rm -f job_dagman_jobstate_log.dag.rescue*");

$abnormal = sub 
{
	die "Want to see only submit, execute and successful completion\n";
};

$aborted = sub 
{
	die "Abort event NOT expected\n";
};

$held = sub 
{
	die "Held event NOT expected\n";
};

$executed = sub
{
	my %info = @_;

	CondorTest::debug("Good. We need the dag to run<$info{cluster}>\n",1);
};

$submitted = sub
{
	CondorTest::debug("submitted: This test will see submit, executing and successful completion\n",1);
};

$success = sub
{
	CondorTest::debug("executed successfully\n",1);
	CondorTest::debug("Verifying output\n",1);
	$diditpass = 1;

	foreach $name (@logfiles) {
		$line = "";
		$passed = 0;
		$canopen = open(OUT,"<$name");
		if( ! (defined $canopen)) {
			CondorTest::debug("Can not open logfile<$name>:$!\n",1);
			$diditpass = 0;
		}
		while(<OUT>) {
			chomp();
			$line = $_;
			if( $line =~ /^.*EXITING WITH STATUS 0.*$/ ) {
				$passed = 1;
				CondorTest::debug("$name: $line\n",1);
			}
		}
		close(OUT);
		if($passed == 1 ) {
			;
		} else {
			CondorTest::debug("failed $name: $line\n",1);
			$diditpass = 0;
		}
	}

	foreach $name (@outfiles) {
		$outindex = 0;
		$line = "";
		$passed = 0;
		%nodeA_events = ('submit' => 0, 'exe' => 0, 'term' => 0, 'abrt' => 0, 'evict' => 0);
		$canopen = open(OUT,"<$name");
		if( ! (defined $canopen)) {
			CondorTest::debug("Can not open outfile<$name>:$!\n",1);
			$diditpass = 0;
		}
		while(<OUT>) {
			chomp();
			$line = $_;
			$target = $outlines[$outindex];

				# skip the internal dagman lines, they cause
				# too many race conditions viz-a-vis jobs
			next if ($line =~ /INTERNAL/);

				# skip a submit failed.  This (rarely) happens
				# when schedd is overloaded. dagman will retry
			next if ($line =~ /Node[^E] SUBMIT_FAILURE/);

			if ($line =~ /^\d+ NodeA EXECUTE \d+.\d local - 1$/) {
				if ($nodeA_events{'submit'} != 2) {
					CondorTest::debug("failed: line \"$line\" expects 2 submit events for NodeA\n"); last;
				} else {
					CondorTest::debug("$name: $line\n",1);
					$nodeA_events{'exe'}++;
				}
				next;
			} elsif ($line =~ /^\d+ NodeA JOB_TERMINATED \d+.\d local - 1$/) {
				if ($nodeA_events{'submit'} != 2) {
					CondorTest::debug("failed: line \"$line\" expects 2 submit events for NodeA\n"); last;
				} else {
					CondorTest::debug("$name: $line\n",1);
					$nodeA_events{'term'}++;
				}
				next;
			} elsif ($line =~ /^\d+ NodeA JOB_ABORTED \d+.\d local - 1$/) {
				if ($nodeA_events{'submit'} != 2) {
					CondorTest::debug("failed: line \"$line\" expects 2 submit events for NodeA\n"); last;
				} else {
					CondorTest::debug("$name: $line\n",1);
					$nodeA_events{'abrt'}++;
				}
				next;
			} elsif ($line =~ /^\d+ NodeA JOB_EVICTED \d+.\d local - 1$/) {
				if ($nodeA_events{'submit'} != 2) {
					CondorTest::debug("failed: line \"$line\" expects 2 submit events for NodeA\n"); last;
				} else {
					CondorTest::debug("$name: $line\n",1);
					$nodeA_events{'evict'}++;
				}
				next;
			}

			if( $line =~ /$target/ ) {
				if ( $line =~ /^\d+ NodeA SUBMIT \d+.\d local - 1$/) {
					$nodeA_events{'submit'}++;
				} elsif ($line =~ /^\d+ NodeA JOB_FAILURE 2 local - 1$/) {
					if ($nodeA_events{'exe'} != 2) {
						CondorTest::debug("failure: NodeA FAILURE event occured prior to 2 execute events\n"); last;
					}
					elsif ($nodeA_events{'term'} != 1) {
						CondorTest::debug("failure: NodeA FAILURE event occured prior to a job terminate event\n"); last;
					}
					elsif ($nodeA_events{'abrt'} != 1) {
						CondorTest::debug("failure: NodeA FAILURE event occured prior to a job abort event\n"); last;
					}
					elsif ($nodeA_events{'evict'} != 1) {
						CondorTest::debug("failure: NodeA FAILURE event occured prior to a job evict event\n"); last;
					}
				}
				CondorTest::debug("$name: $line\n",1);
				$outindex++;
				if ($outindex > $#outlines) {
					$passed = 1;
					last;
				}
			} else {
				CondorTest::debug("failed: \"extra\" output line: $line\n");
				$diditpass = 0;
			}
		}
		close(OUT);
		if($passed == 1 ) {
			;
		} else {
			CondorTest::debug("failed: missing output line $target\n",1);
			$diditpass = 0;
		}
	}

	if($diditpass == 0) {
		die "All expected files and correct output failed\n";
	}
};

CondorTest::RegisterExitedSuccess( $testname, $success);
CondorTest::RegisterExecute($testname, $executed);
CondorTest::RegisterExitedAbnormal( $testname, $abnormal );
CondorTest::RegisterAbort( $testname, $aborted );
CondorTest::RegisterHold( $testname, $held );
CondorTest::RegisterSubmit( $testname, $submitted );

if( CondorTest::RunDagTest($testname, $cmd, 0, $dagman_args) ) {
	CondorTest::debug("$testname: SUCCESS\n",1);
	exit(0);
} else {
	die "$testname: CondorTest::RunDagTest() failed\n";
}

