#!/usr/local/bin/perl -w
use strict; 

my $DOC = <<"EOF"; 
Usage: $0 <table dir> <pkg dir> <first> <last> <app dir>

Run first: 
- steps

Args: 
- <table dir>
- <pkg dir>, contains packages processed by oracle_package
- <first>, <last>, package/suite numbers such that packages/suites <pkg dir>/<first>.zip through <pkg dir>/<last>.zip will be processed by this script
- <app dir>, contains bin-ins/coverage.em

Constants: 
- <tmp dir> 
- <emma dir>

Affects: 
- <table dir>/suites.txt_<first>-<last>

Header: 
- SuiteNum, >= 1, corresponds to FaultNum
- TstLen, max of steps.StepNum for SuiteNum
- Events, TstLen * (max of steps.TstNum + 1) for SuiteNum
- E2Cov, # event pairs covered 
- E3Cov, # event triples covered 
- ClassCov, % classes covered
- MethodCov, % methods covered
- BlockCov, % blocks covered 
- LineCov, % lines covered
- Cov, max of steps.Cov for SuiteNum
- Det, max of 0 and steps.Det for SuiteNum

Lists information about each <test suite, fault pair> (SuiteNum=FaultNum). 
EOF
;

if (@ARGV != 5) {
    print $DOC; 
    exit 1;
}

my ($table_dir, $pkg_dir, $first, $last, $app_dir) = @ARGV; 
$table_dir =~ s|/$||; 
$pkg_dir =~ s|/$||; 
$app_dir =~ s|/$||; 
my $out_file = "$table_dir/suites.txt_$first-$last"; 
if (-e $out_file) {
    die "$out_file already exists\n"; 
}
my $TMP = '/tmp/strecker'; 
my $EMMA_DIR = '/skollhomes/strecker'; 

my %suites;  # key = SuiteNum
my @curr_tst = (), my @curr_suite = (); 
my $prev_tst_num = 0, my $prev_suite_num = $first; 
$suites{$first}{'Cov'} = 0; 
$suites{$first}{'Det'} = 0; 
my $steps_file = "$table_dir/steps.txt"; 
open(STEPS, $steps_file) or die "Couldn't read $steps_file\n"; 
my $head = <STEPS>; 
while (<STEPS>) {  # Assumes rows sorted by SuiteNum then TstNum then StepNum and >1 row per SuiteNum
    chomp; 
    my ($suite_num, $tst_num, $step_num, $event_num, $cov, $det) = split; 
    next  if ($suite_num < $first); 
    if (eof(STEPS)) {
	push @curr_tst, $event_num; 
	if ($cov) {
	    $suites{$suite_num}{'Cov'} = 1; 
	}
	if ($det) {
	    $suites{$suite_num}{'Det'} = 1; 
	}
    }
    if ($prev_tst_num != $tst_num || eof(STEPS)) {
	my @curr_tst_copy = @curr_tst; 
	push @curr_suite, \@curr_tst_copy; 
	@curr_tst = (); 
	$prev_tst_num = $tst_num; 
    }
    if ($prev_suite_num != $suite_num || eof(STEPS)) {
	my $tst_len, my %e2cov, my %e3cov; 
	foreach my $tst_ref (@curr_suite) {
	    my @tst = @$tst_ref; 
	    if (defined $tst_len && $tst_len != scalar(@tst)) {
		die "Differing test-case lengths for SuiteNum=$suite_num\n"; 
	    }
	    $tst_len = scalar(@tst); 
	    for (my $i = 0; $i <= $#tst - 1; $i++) {
		$e2cov{$tst[$i] . ',' . $tst[$i+1]} = 1; 
	    }
	    for (my $i = 0; $i <= $#tst - 2; $i++) {
		$e3cov{$tst[$i] . ',' . $tst[$i+1] . ',' . $tst[$i+2]} = 1; 
	    }
	}
	$suites{$prev_suite_num}{'TstLen'} = $tst_len; 
	$suites{$prev_suite_num}{'Events'} = $tst_len * scalar(@curr_suite); 
	$suites{$prev_suite_num}{'E2Cov'} = scalar(keys %e2cov); 
	$suites{$prev_suite_num}{'E3Cov'} = scalar(keys %e3cov); 
	last  if ($suite_num > $last || eof(STEPS)); 
	@curr_suite = (); 
	$suites{$suite_num}{'Cov'} = 0; 
	$suites{$suite_num}{'Det'} = 0; 
	$prev_suite_num = $suite_num; 
    } 
    push @curr_tst, $event_num; 
    if ($cov) {
	$suites{$suite_num}{'Cov'} = 1; 
    }
    if ($det) {
	$suites{$suite_num}{'Det'} = 1; 
    }
}
close(STEPS); 


for (my $pkg_num = $first; $pkg_num <= $last; $pkg_num++) {
    if (-e "$TMP/$pkg_num") {
        `chmod -R u+w $TMP/$pkg_num`; 
	`rm -r $TMP/$pkg_num`; 
	if ($?) {
	    die "Couldn't do rm -r $TMP/$pkg_num\n"; 
	}
    }
    `unzip -q -d $TMP $pkg_dir/$pkg_num.zip "$pkg_num/cov-cln/*.ec"`; 
    my $cov_cln_dir = "$TMP/$pkg_num/cov-cln"; 
    my $report_file = "$TMP/report.xml"; 
    if (-e $report_file) {
	`chmod -R u+w $report_file`; 
	`rm -r $report_file`; 
	if ($?) {
	    die "Couldn't do rm -r $report_file\n"; 
	}
    }
    my $suite_num = $pkg_num; 

    my $ec_file_args = ''; 
    foreach my $ec_file (<$cov_cln_dir/*>) {
	$ec_file_args .= "-in $ec_file "; 
    }
    `java -cp $EMMA_DIR/emma.jar emma report $ec_file_args -in $app_dir/bin-ins/coverage.em -r xml -Dreport.xml.out.file=$report_file -Dreport.depth=all`; 
    open(REPORT, $report_file) or die "Couldn't read $report_file\n"; 
    while (<REPORT>) {
	chomp; 
	if (m|<coverage type="class, %" value=".*%\s+\((.*)/(.*)\)|) {
	    $suites{$suite_num}{'ClassCov'} = $1/$2; 
	} elsif (m|<coverage type="method, %" value=".*%\s+\((.*)/(.*)\)|) {
	    $suites{$suite_num}{'MethodCov'} = $1/$2; 
	} elsif (m|<coverage type="block, %" value=".*%\s+\((.*)/(.*)\)|) {
	    $suites{$suite_num}{'BlockCov'} = $1/$2; 
	} elsif (m|<coverage type="line, %" value=".*%\s+\((.*)/(.*)\)|) {
	    $suites{$suite_num}{'LineCov'} = $1/$2; 
	} 
    }
    close(REPORT); 
    `rm $report_file`; 
    if ($?) {
	die "Couldn't do rm $report_file\n"; 
    }

    `chmod -R u+w $TMP/$pkg_num`; 
    `rm -r $TMP/$pkg_num`; 
    if ($?) {
        die "Couldn't do rm -r $TMP/$pkg_num\n"; 
    }
}

my @lines; 
push @lines, "SuiteNum TstLen Events E2Cov E3Cov ClassCov MethodCov BlockCov LineCov Cov Det\n"; 
my @sorted_keys = sort {$a <=> $b} keys %suites; 
for (my $i = 0; $i <= $#sorted_keys; $i++) {
    my $suite_num = $sorted_keys[$i]; 
    push @lines, "$suite_num $suites{$suite_num}{'TstLen'} $suites{$suite_num}{'Events'} $suites{$suite_num}{'E2Cov'} $suites{$suite_num}{'E3Cov'} $suites{$suite_num}{'ClassCov'} $suites{$suite_num}{'MethodCov'} $suites{$suite_num}{'BlockCov'} $suites{$suite_num}{'LineCov'} $suites{$suite_num}{'Cov'} $suites{$suite_num}{'Det'}\n"; 
}

open(OUT, ">$out_file") or die "Couldn't write to $out_file\n"; 
print OUT @lines; 
close(OUT); 
