#! /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.
##
##**************************************************************

use CondorTest;
use CondorUtils;


my $testname = "job_hgq_negfail_basic_van";

#testreq: personal
my $config = <<CONDOR_TESTREQ_CONFIG;
# This was a hack to allow the test pool and harness pool to
# coexist peacefully on my sandbox.  I dont think they are needed
# in a "real" testing environment:
#COLLECTOR_ARGS = -p 42424
#COLLECTOR_HOST = $(CONDOR_HOST):0
#COLLECTOR_ADDRESS_FILE = $(LOG)/.collector_address

DAEMON_LIST = MASTER,SCHEDD,COLLECTOR,NEGOTIATOR,STARTD
SCHEDD_INTERVAL	= 30
NEGOTIATOR_INTERVAL = 20

# turn off preemption
MAXJOBRETIREMENTTIME = 3600 * 24
PREEMPT = False
PREEMPTION_REQUIREMENTS = False
RANK = 0
NEGOTIATOR_CONSIDER_PREEMPTION = False

# no slot weights
NEGOTIATOR_USE_SLOT_WEIGHTS = FALSE

NUM_CPUS = 40
use FEATURE : StaticSlots

# turn on round-robin for this test, since we are testing
# an overlapping-effective-pool scenario
HFS_ROUND_ROBIN_RATE = 1.0

# turn on multiple allocation rounds, since we are testing
# slot rejection scenario as well
HFS_MAX_ALLOCATION_ROUNDS = 3

GROUP_NAMES = a, b, a.a, a.b, b.a, b.b

GROUP_QUOTA_DYNAMIC_a = 0.5
GROUP_QUOTA_DYNAMIC_b = 0.5
GROUP_QUOTA_DYNAMIC_a.a = 0.5
GROUP_QUOTA_DYNAMIC_a.b = 0.5
GROUP_QUOTA_DYNAMIC_b.a = 0.5
GROUP_QUOTA_DYNAMIC_b.b = 0.5

# Have "a" and "b" subtrees manage their quota independently
GROUP_ACCEPT_SURPLUS = TRUE
GROUP_ACCEPT_SURPLUS_a = FALSE
GROUP_ACCEPT_SURPLUS_b = FALSE

CONDOR_TESTREQ_CONFIG
#endtestreq


# trip whitespace from beginning and end of a string
sub trimws($) {
    my $string = shift;
    $string =~ s/^\s+//;
    $string =~ s/\s+$//;
    return $string;
}


my $test_passed = 0;
my $pre_execution = 1;


sub timed_callback {
	my @addarray = ();
	my @sorted = ();
	my @unsorted = ();
	my %testhash = ();

    if ($test_passed) {
        # if we already detected that the test passed, we are 
		# no longer wanting a call back
        # jobs aren't running yet, we can skip this callback.
        return;
    }
    if ($pre_execution) {
        #  propogate the call backs till done
		# hmm no running events
		#runToolNTimes("condor_status",1,1);
		#runToolNTimes("condor_q",1,1);
		CondorTest::debug("Re fire callback - in pre_execution\n",2);
		CondorTest::RegisterTimed($testname, \&timed_callback, 15);
        return;
    }

    #my $stat = `condor_q -format "%s\n" AccountingGroup -constraint "JobStatus == 2" | sort | uniq -c`;
	my @slines = ();
	my $stat = runCondorTool("condor_q -af AccountingGroup -constraint \"JobStatus == 2\"",\@adarray,2,{emit_output=>0});;
	foreach my $ad (@adarray) {
		fullchomp($ad);
		#print "push:$ad\n";
		push @unsorted, $ad;
	}
	@sorted = sort { $a cmp $b } @unsorted; # first we sort, then we count
	my $sortedsize = @sorted;
	#print "sorted size:$sortedsize\n";
	foreach my $group (@sorted) {
		#print "Group:$group\n";
		if(exists $testhash{$group}) {
			$testhash{$group} += 1;
			#print "bump group:$group:$testhash{$group}\n";
		} else {
			$testhash{$group} = 1;
			#print "new group:$group:$testhash{$group}\n";
		}
	}
	my $tst = "";
	foreach my $key (sort keys %testhash) {
		#print "Looking at $key=$testhash{$key}\n";
		$tst = $tst . " $testhash{$key} $key";
	}

	CondorTest::debug("Have: $tst Looking for: - 20 a.a.user 5 b.a.user 5 b.b.user-\n",2);
    if ($tst == " 20 a.a.user 5 b.a.user 5 b.b.user") {
		CondorTest::debug("we detected the expected pattern of running jobs: $tst\n",1);
        $test_passed = 1;
        # we found what we were looking for: now we want to clear the que
        # so the test can finish, because some of the submitted jobs will
        # never run by design.
        runcmd("condor_rm -all",{emit_output=>0});
    } else {
        print "Haven't seen expected output yet.  What I saw was:$tst\n";
		# Call backs only fire once now
		CondorTest::debug("Re fire callback - end of this call back\n",2);
		CondorTest::RegisterTimed($testname, \&timed_callback, 15);
        #print $stat;
        # if this check failed, wait a little:
        sleep(5);
    }
}

sub execute_callback {
	CondorTest::debug("Got to execute_callback\n",2);
    if ($pre_execution) {
        # only do this once, to let all jobs have a chance to spin up
		CondorTest::debug("sleeping once\n",2);
        sleep(10);
    }
    # flag that jobs have started
    $pre_execution = 0;
	CondorTest::debug("pre_execution: $pre_execution\n",2);
}

sub exit_callback {
    # by this time we had better have seen the running job pattern we were looking for
    unless ($test_passed) {
        die "Failed to find expected pattern of running jobs";
    }
}

sub imageupdated {
}


my $job_log = "$testname.log";

# submit jobs
my $submit_body = "
universe = vanilla
executable = x_sleep.pl
log = $job_log
output = $testname.out
error = $testname.err
notification = never
arguments = 3600
# group 'a.a' should be able to use slots unused by 'a.b'
# set up requirements to stay out of lower slots (used by b.a and b.b)
Requirements = (SlotID > 10)
+AccountingGroup = \"a.a.user\"
queue 20
# set up jobs for 'a.b' to fail:
Requirements = False
+AccountingGroup = \"a.b.user\"
queue 10
# set up 'b.a' and 'b.b' to compete
Requirements = (SlotID <= 10)
+AccountingGroup = \"b.a.user\"
queue 10
+AccountingGroup = \"b.b.user\"
queue 10
";

my $submit_filename = CondorTest::TempFileName("$testname.submit");
open(SUBMIT, ">$submit_filename") || die "Failed to open $submit_filename\n";
print SUBMIT $submit_body;
close(SUBMIT);


my $on_evictedwithoutcheckpoint = sub {
	CondorTest::debug("Evicted Without Checkpoint from removing jobs.\n",2);
};

CondorTest::RegisterEvictedWithoutCheckpoint($testname, $on_evictedwithoutcheckpoint);
CondorTest::RegisterTimed($testname, \&timed_callback, 15);
CondorTest::RegisterExecute($testname, \&execute_callback);
CondorTest::RegisterImageUpdated($testname, \&imageupdated);

CondorTest::RegisterExited($testname, \&exit_callback);
CondorTest::RegisterExitedSuccess($testname, \&exit_callback);
CondorTest::RegisterAbort($testname, \&exit_callback);

# Ensure previous runs leftovers don't cause us grief.
unlink($job_log);

if (CondorTest::RunTest($testname, $submit_filename, 0)) {
    CondorTest::debug("$testname: SUCCESS\n",1);
	CondorTest::RegisterResult(1, test_name, $testname);
	CondorTest::EndTest();
} else {
	CondorTest::RegisterResult(0, test_name, $testname);
	CondorTest::EndTest();
}
