#!/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);