#!/usr/local/bin/perl -w
use strict;
my $DOC = <<"EOF";
Usage: $0
Run first:
- ../oracle_package
- events
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:
- /steps.txt_-
Header:
- SuiteNum, >= 1
- TstNum, >= 0 (to be consistent with ../JaymieTestCaseGenerator.java)
- StepNum, >= 1
- EventNum, >= 0, events.EventNum
- Cov, 1 if SuiteNum:TstNum:StepNum covers the fault, 0 otherwise (from /result.txt-- see oracle_package). If the fault has faults.InMethod=0, then Cov=1 whenever any line in its java file is covered. In this case, be careful: only the earliest step with Cov=1 can be trusted-- the rest with Cov=1 may not have actually covered the fault.
- Det, 1 if SuiteNum:TstNum:StepNum detects the fault, 0 if it does not, -1 if the fault is supposedly detected but it hasn't been covered yet (from /result.txt-- see oracle_package)
- LinesExec, # line executions at SuiteNum:TstNum:StepNum for clean version (if a line is executed 4 times, this counts as 4 executions)
- LinesExecBefore, sum of LinesExec for steps preceding SuiteNum:TstNum:StepNum
- LinesCov, # unique lines executed at SuiteNum:TstNum:StepNum for clean version
- NewLinesCov, # unique lines executed at SuiteNum:TstNum:StepNum for clean version that have not been executed in any previous step of SuiteNum:TstNum
- LinesCovBefore, sum of NewLinesCov for steps preceding SuiteNum:TstNum:StepNum
- ExecDiff, 1 if the line executions for SuiteNum:TstNum:StepNum for the clean and mutant versions differ, 0 otherwise
- CovDiff, 1 if the unique lines covered for SuiteNum:TstNum:StepNum for the clean and mutant versions differ, 0 otherwise
Lists information about each test step executed for a pair (SuiteNum=faults.FaultNum). Cov considers faulty lines
with faults.InMethod=0, whereas LinesExec, LinesExecBefore, LinesCov,
NewLinesCov, LinesCovBefore, ExecDiff, and CovDiff do not count lines
outside of methods.
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/steps.txt_$first-$last";
if (-e $out_file) {
die "$out_file already exists\n";
}
my $TMP = '/tmp/strecker';
my %event_nums; # key = Window x Component x Action, value = EventNum
my $events_file = "$table_dir/events.txt";
open(EVENTS, $events_file) or die "Couldn't read $events_file\n";
my $head = ;
while () {
chomp;
m/^(\d+)\s+"(.+)"\s+"(.+)"\s+"(.+)"/;
my ($event_num, $window, $component, $action) = ($1, $2, $3, $4);
$event_nums{$window}{$component}{$action} = $event_num;
}
close(EVENTS);
my %steps; # key = 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/result.txt" "$pkg_num/cov-cln/*" "$pkg_num/cov-mut/*" "$pkg_num/tst/*" "$pkg_num/tst_len.txt"`;
my $result_file = "$TMP/$pkg_num/result.txt";
my $cov_cln_dir = "$TMP/$pkg_num/cov-cln";
my $cov_mut_dir = "$TMP/$pkg_num/cov-mut";
my $tst_dir = "$TMP/$pkg_num/tst";
my $tst_len = `cat $TMP/$pkg_num/tst_len.txt`; chomp $tst_len;
my $suite_num = $pkg_num;
my %tst_cov; # key = TstNum, value = 1 or 0 (some step of tst has Cov=1?)
open(RES, $result_file) or die "Couldn't read $result_file\n";
my $head = ;
while () {
chomp;
my @data = split;
my $tst_num = shift @data;
for (my $step_num = 1; $step_num <= $tst_len; $step_num++) {
$steps{$suite_num}{$tst_num}{$step_num}{'Cov'} = $data[$step_num - 1];
$steps{$suite_num}{$tst_num}{$step_num}{'Det'} = $data[$step_num - 1 + $tst_len];
if ($data[$step_num - 1] == 1) {
$tst_cov{$tst_num} = 1;
}
}
}
close(RES);
foreach my $tst_file (<$tst_dir/*>) {
my $tst_num = `basename $tst_file`; chomp $tst_num; $tst_num =~ s/\.tst$//;
open(TST, $tst_file) or die "Couldn't read $tst_file\n";
my $window, my $component, my $action;
my $step_num = 1;
while () {
chomp;
if (m|(.*)|) {
$window = $1;
} elsif (m|(.*)|) {
$component = $1;
} elsif (m|(.*)|) {
$action = $1;
if (! defined $event_nums{$window}{$component}{$action}) {
die "No EventNum for Window=$window x Component=$component x Action=$action in $tst_file\n";
}
$steps{$suite_num}{$tst_num}{$step_num++}{'EventNum'} = $event_nums{$window}{$component}{$action};
}
}
close(TST);
if (--$step_num != $tst_len) {
die "Expecting $tst_len steps in $tst_file but found $step_num\n";
}
my %prev_cov_lines = ();
my $tmp_file = "$TMP/last_step_cov.txt";
for ($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 $lines_exec = 0, my $new_lines_cov = 0;
my @exec_lines = (), my %cov_lines = ();
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);
$lines_exec += $times;
push @exec_lines, "$file:$line=$times";
$cov_lines{"$file:$line"} = 1;
if (! $prev_cov_lines{"$file:$line"}) {
$prev_cov_lines{"$file:$line"} = 1;
$new_lines_cov++;
}
}
}
close(COVCLN);
if ($step_num == $tst_len) {
`rm $tmp_file`;
}
$steps{$suite_num}{$tst_num}{$step_num}{'LinesExec'} = $lines_exec;
$steps{$suite_num}{$tst_num}{$step_num}{'LinesCov'} = scalar(keys %cov_lines);
$steps{$suite_num}{$tst_num}{$step_num}{'NewLinesCov'} = $new_lines_cov;
if ($step_num == 1) {
$steps{$suite_num}{$tst_num}{$step_num}{'LinesExecBefore'} = 0;
$steps{$suite_num}{$tst_num}{$step_num}{'LinesCovBefore'} = 0;
} else {
$steps{$suite_num}{$tst_num}{$step_num}{'LinesExecBefore'} = $steps{$suite_num}{$tst_num}{$step_num - 1}{'LinesExecBefore'} + $steps{$suite_num}{$tst_num}{$step_num - 1}{'LinesExec'};
$steps{$suite_num}{$tst_num}{$step_num}{'LinesCovBefore'} = $steps{$suite_num}{$tst_num}{$step_num - 1}{'LinesCovBefore'} + $steps{$suite_num}{$tst_num}{$step_num - 1}{'NewLinesCov'};
}
my $cov_mut_file;
if ($step_num < $tst_len) {
$cov_mut_file = "$cov_mut_dir/$tst_num.txt-$step_num";
} else {
if (-e "$cov_mut_dir/$tst_num.txt-$tst_len" || -e "$cov_mut_dir/$tst_num.txt" || -e "$cov_mut_dir/$tst_num.txt-final") {
my $existing_files = '';
foreach my $f (("$cov_mut_dir/$tst_num.txt-$tst_len", "$cov_mut_dir/$tst_num.txt", "$cov_mut_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_mut_file = $tmp_file;
}
my $exec_diff, my $cov_diff;
if (-e $cov_mut_file) {
my @mut_exec_lines = (), my %mut_cov_lines = ();
open(COVMUT, $cov_mut_file) or die "Couldn't read $cov_mut_file\n";
while () {
chomp;
if (m/^(.+)\s+(\d+)\s+(\d+)$/) {
my ($file, $line, $times) = ($1, $2, $3);
push @mut_exec_lines, "$file:$line=$times";
$mut_cov_lines{"$file:$line"} = 1;
}
}
close(COVMUT);
if ($step_num == $tst_len) {
`rm $tmp_file`;
}
@exec_lines = sort @exec_lines;
@mut_exec_lines = sort @mut_exec_lines;
$exec_diff = $#exec_lines != $#mut_exec_lines ? 1 : 0;
for (my $i = 0; ! $exec_diff && $i <= $#exec_lines; $i++) {
if ($exec_lines[$i] ne $mut_exec_lines[$i]) {
$exec_diff = 1;
}
}
$cov_diff = scalar(keys %cov_lines) != scalar(keys %mut_cov_lines) ? 1 : 0;
if (! $cov_diff) {
foreach my $cl (keys %cov_lines) {
if (! $mut_cov_lines{$cl}) {
$cov_diff = 1;
last;
}
}
}
} else {
if ($tst_cov{$tst_num}) {
$exec_diff = scalar(@exec_lines) != 0 ? 1 : 0;
$cov_diff = scalar(keys %cov_lines) != 0 ? 1 : 0;
} else {
$exec_diff = 0;
$cov_diff = 0;
}
}
$steps{$suite_num}{$tst_num}{$step_num}{'ExecDiff'} = $exec_diff;
$steps{$suite_num}{$tst_num}{$step_num}{'CovDiff'} = $cov_diff;
}
}
`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 TstNum StepNum EventNum Cov Det LinesExec LinesExecBefore LinesCov NewLinesCov LinesCovBefore ExecDiff CovDiff\n";
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];
push @lines, "$suite_num $tst_num $step_num $steps{$suite_num}{$tst_num}{$step_num}{'EventNum'} $steps{$suite_num}{$tst_num}{$step_num}{'Cov'} $steps{$suite_num}{$tst_num}{$step_num}{'Det'} $steps{$suite_num}{$tst_num}{$step_num}{'LinesExec'} $steps{$suite_num}{$tst_num}{$step_num}{'LinesExecBefore'} $steps{$suite_num}{$tst_num}{$step_num}{'LinesCov'} $steps{$suite_num}{$tst_num}{$step_num}{'NewLinesCov'} $steps{$suite_num}{$tst_num}{$step_num}{'LinesCovBefore'} $steps{$suite_num}{$tst_num}{$step_num}{'ExecDiff'} $steps{$suite_num}{$tst_num}{$step_num}{'CovDiff'}\n";
}
}
}
open(OUT, ">$out_file") or die "Couldn't write to $out_file\n";
print OUT @lines;
close(OUT);