#!/usr/local/bin/perl -w
use strict;
my $DOC = <<"EOF";
Usage: $0
Run first:
- faults
- steps
Args:
-
- , contains packages processed by oracle_package
- , , package/suite numbers such that packages/suites /.zip through /.zip will be processed by this script
Constants:
-
Affects:
- /fault_cov_instances.txt
Header:
- SuiteNum, >= 1
- TstNum, >= 0
- StepNum, >= 1
- FaultNum, >= 1
- TimesExec, # times faulty line executed at SuiteNum:TstNum:StepNum for clean version (1 if faults.InMethod=0 for FaultNum)
Lists each instance in which the line where fault FaultNum is located
is covered by some test case in the pool (not just in the suite with
SuiteNum=FaultNum). When faults.InMethod=0 for FaultNum, only the
_earliest_ step of each test case where some line of the fault's java
file is covered is included in this list. This is different from how
steps.Cov is calculated! For steps.Cov, _every_ step of the test case
where some line of the fault's java file is covered has steps.Cov=1.
This script uses a ton of memory. It can crash if you try to process
too many packages.
EOF
;
if (@ARGV != 4) {
print $DOC;
exit 1;
}
my ($table_dir, $pkg_dir, $first, $last) = @ARGV;
$table_dir =~ s|/$||;
$pkg_dir =~ s|/$||;
my $out_file = "$table_dir/fault_cov_instances.txt_$first-$last";
if (-e $out_file) {
die "$out_file already exists\n";
}
my $TMP = '/tmp/strecker';
my %faults; # key = FaultNum
my %faults_at_line; # key = Line, value = array of FaultNums with InMethod=1
my %faults_at_file; # key = Line, value = array of FaultNums with InMethod=0
my $faults_file = "$table_dir/faults.txt";
open(FAULTS, $faults_file) or die "Couldn't read $faults_file\n";
my $head = ;
while () {
chomp;
my ($fault_num, $line, $mut_type, $in_method) = split;
$faults{$fault_num}{'Line'} = $line;
$faults{$fault_num}{'InMethod'} = $in_method;
if ($in_method) {
if (! defined $faults_at_line{$line}) {
$faults_at_line{$line} = [];
}
push @{$faults_at_line{$line}}, $fault_num;
} else {
my ($file) = split(/:/, $line);
if (! defined $faults_at_file{$file}) {
$faults_at_file{$file} = [];
}
push @{$faults_at_file{$file}}, $fault_num;
}
}
close(FAULTS);
my %steps; # key = SuiteNum x TstNum x StepNum, value = 1
my %tst_lens; # key = SuiteNum, value = max(StepNum) for SuiteNum
my %max_tst_nums; # key = SuiteNum, value = max(TstNum) for SuiteNum
my $steps_file = "$table_dir/steps.txt";
open(STEPS, $steps_file) or die "Couldn't read $steps_file\n";
$head = ;
while () {
chomp;
my ($suite_num, $tst_num, $step_num) = split;
if ($first <= $suite_num && $suite_num <= $last) {
$steps{$suite_num}{$tst_num}{$step_num} = 1;
if (! defined $tst_lens{$suite_num} || $tst_lens{$suite_num} < $step_num) {
$tst_lens{$suite_num} = $step_num;
}
if (! defined $max_tst_nums{$suite_num} || $max_tst_nums{$suite_num} < $tst_num) {
$max_tst_nums{$suite_num} = $tst_num;
}
}
}
close(STEPS);
my %fault_cov_instances; # key = FaultNum x SuiteNum x TstNum x StepNum
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/*.txt*"`;
my $cov_cln_dir = "$TMP/$pkg_num/cov-cln";
my $suite_num = $pkg_num;
my $tst_len = $tst_lens{$suite_num};
for (my $tst_num = 0; $tst_num <= $max_tst_nums{$suite_num}; $tst_num++) {
my %faults_at_prev_steps; # only includes faults with InMethod=0
### BEGIN cloned from steps ###
my $tmp_file = "$TMP/last_step_cov.txt";
for (my $step_num = 1; $step_num <= $tst_len; $step_num++) {
my $cov_cln_file;
if ($step_num < $tst_len) {
$cov_cln_file = "$cov_cln_dir/$tst_num.txt-$step_num";
} else {
my $existing_files = '';
foreach my $f (("$cov_cln_dir/$tst_num.txt-$tst_len", "$cov_cln_dir/$tst_num.txt", "$cov_cln_dir/$tst_num.txt-final")) {
$existing_files .= "$f " if (-e $f);
}
`cat $existing_files > $tmp_file`;
if ($?) {
die "Couldn't do cat $existing_files > $tmp_file: error $?\n";
}
$cov_cln_file = $tmp_file;
}
my @faults_at_step;
open(COVCLN, $cov_cln_file) or die "Couldn't read $cov_cln_file\n";
while () {
chomp;
if (m/^(.+)\s+(\d+)\s+(\d+)$/) {
my ($file, $line, $times) = ($1, $2, $3);
foreach my $fault_num (@{$faults_at_line{"$file:$line"}}) {
if (! defined $fault_cov_instances{$fault_num}{$suite_num}{$tst_num}{$step_num}{'TimesExec'}) {
$fault_cov_instances{$fault_num}{$suite_num}{$tst_num}{$step_num}{'TimesExec'} = 0;
}
$fault_cov_instances{$fault_num}{$suite_num}{$tst_num}{$step_num}{'TimesExec'} += $times;
push @faults_at_step, $fault_num;
}
foreach my $fault_num (@{$faults_at_file{$file}}) {
if (! $faults_at_prev_steps{$fault_num}) {
$fault_cov_instances{$fault_num}{$suite_num}{$tst_num}{$step_num}{'TimesExec'} = 1;
push @faults_at_step, $fault_num;
$faults_at_prev_steps{$fault_num} = 1;
}
}
}
}
close(COVCLN);
if ($step_num == $tst_len) {
`rm $tmp_file`;
}
}
### END cloned from steps ###
}
`chmod -R u+w $TMP/$pkg_num`;
`rm -r $TMP/$pkg_num`;
if ($?) {
die "Couldn't do rm -r $TMP/$pkg_num\n";
}
}
open(OUT, ">$out_file") or die "Couldn't write to $out_file\n";
print OUT "SuiteNum TstNum StepNum FaultNum TimesExec\n";
my @sorted_faults = sort {$a <=> $b} keys %fault_cov_instances;
my @sorted_suites = sort {$a <=> $b} keys %steps;
for (my $suite_ind = 0; $suite_ind <= $#sorted_suites; $suite_ind++) {
my $suite_num = $sorted_suites[$suite_ind];
my @sorted_tsts = sort {$a <=> $b} keys %{$steps{$suite_num}};
for (my $tst_ind = 0; $tst_ind <= $#sorted_tsts; $tst_ind++) {
my $tst_num = $sorted_tsts[$tst_ind];
my @sorted_steps = sort {$a <=> $b} keys %{$steps{$suite_num}{$tst_num}};
for (my $step_ind = 0; $step_ind <= $#sorted_steps; $step_ind++) {
my $step_num = $sorted_steps[$step_ind];
for (my $fault_ind = 0; $fault_ind <= $#sorted_faults; $fault_ind++) {
my $fault_num = $sorted_faults[$fault_ind];
if (defined $fault_cov_instances{$fault_num}{$suite_num}{$tst_num}{$step_num}) {
print OUT "$suite_num $tst_num $step_num $fault_num $fault_cov_instances{$fault_num}{$suite_num}{$tst_num}{$step_num}{'TimesExec'}\n";
}
}
}
}
}
close(OUT);
print "Finished!\n";
exit 0;