This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

regression analysis: gdb.sum postprocessing script


Here is a Perl script I wrote to postprocess one or more gdb.sum files
and provide a complete dejagnu test outcome summary (or diff if more
than one gdb.sum files are given).  It's most useful if you want to have
a complete view of regression status between two source trees and/or if
you set up your testing to run multiple passes (to see how a test point
behaves in different passes), however you can use it just on one test
run's gdb.sum file and play around with the options to get test outcome
presented in a much organized and useful way than going through the flat
gdb.sum file.

I don't know if this is useful to keep around in the repository ...

- Jimmy Guo, guo@cup.hp.com

Index: gdbsum
/usr/local/bin/diff -c -w -L gdbsum gdbsum.orig gdbsum
*** gdbsum.orig
--- gdbsum	Wed Jan 26 16:48:40 2000
***************
*** 0 ****
--- 1,1050 ----
+ #!/usr/local/bin/perl
+ 
+ #
+ # gdbsum - smart gdb.sum filter / merge / diff utility
+ #
+ # Command line:
+ #    gdbsum [<options>] <string label> <gdb.sum> [<string label> <gdb.sum> ...]
+ #
+ #    <options>:
+ #        [-no-f/ail]         don't list FAIL
+ #        [-no-xfa/il]        don't list XFAIL
+ #        [-no-xpa/ss]        don't list XPASS
+ #        [-no-unr/esolved]   don't list UNRESOLVED
+ #        [-no-ski/pped]      don't list skipped tests
+ #        [-no-oth/er]        don't list unclassfiable outputs
+ #        [-runpass <string>] list only the run pass(es) specified in the
+ #                            space delimited run pass list (string).
+ #
+ #        - the default is to list all
+ #
+ #    <string label>       identifier for the run corresponding to <gdb.sum>
+ #    <gdb.sum>            pathname of gdb.sum file
+ #
+ #    - if one <string label> <gdb.sum> pair specified, produce filtered test
+ #      result to stdout
+ #    - if multiple <string label> <gdb.sum> pairs specified, produce a
+ #      difference of filtered test result to stdout
+ #
+ 
+ # initialize
+ #
+ &init;
+ 
+ # parse command line args
+ #
+ &parseCmdLine;
+ $do_diff = 1 if ($#sum_ids > 0);
+ 
+ # parse all gdb.sum files specified
+ #
+ $sum_seq = 0;
+ while ($sum_seq <= $#sum_ids) {
+   &parseSumFile($sum_seq, $sum_files[$sum_seq]);
+   $sum_seq++;
+ }
+ 
+ # merge all passes from multiple runs
+ #
+ $tmp = " $passes[0] ";
+ @allpasses = split(/\s+/, $passes[0]);
+ for ($sum_seq = 1; $sum_seq <= $#sum_ids; $sum_seq++) {
+   @tmps = split(/\s+/, $passes[$sum_seq]);
+   foreach $pass (@tmps) {
+     push(@allpasses, $pass)
+       if (index($tmp, " $pass ") == -1);
+   }
+   $tmp = ' '.join(" ", @allpasses).' ';
+ }
+ @allpasses = sort @allpasses;
+ 
+ # merge all tests from multiple runs
+ #
+ $tmp = " $tests[0] ";
+ @alltests = split(/\s+/, $tests[0]);
+ for ($sum_seq = 1; $sum_seq <= $#sum_ids; $sum_seq++) {
+   @tmps = split(/\s+/, $tests[$sum_seq]);
+   foreach $test (@tmps) {
+     push(@alltests, $test)
+       if (index($tmp, " $test ") == -1);
+   }
+   $tmp = ' '.join(" ", @alltests).' ';
+ }
+ @alltests = sort @alltests;
+ 
+ # print filtered / diff'd output to stdout
+ # 
+ print $errbuf if ($errbuf ne '');
+ for ($sum_seq = 0; $sum_seq <= $#sum_ids; $sum_seq++) {
+   print " <$sum_seq>:" if ($do_diff);
+   print " $sum_ids[$sum_seq]\n";
+   print "    # of expected passes            $p_cnts[$sum_seq]\n";
+   print "    # of unexpected failures        $f_cnts[$sum_seq]\n";
+   print "    # of unexpected successes       $xpa_cnts[$sum_seq]\n";
+   print "    # of expected failures          $xfa_cnts[$sum_seq]\n";
+   print "    # of unresolved testcases       $unr_cnts[$sum_seq]\n";
+   print "    # of unsupported tests          $ski_cnts[$sum_seq]\n";
+ }
+ print "\n";
+ 
+ # list 'others' first
+ #   these are usually caused by test / system problems
+ #   that need to be resolved
+ #
+ &printOthers if (! $no_other);
+ 
+ # list FAIL, XPASS, XFAIL, and UNRESOLVED test entries
+ #
+ &printEntries if (! ($no_fail && $no_xfail && no_xpass && $no_unr));
+ 
+ # list skipped tests
+ #
+ &printSkipped if (! $no_ski);
+ 
+ # done
+ #
+ exit 0;
+ 
+ 
+ #
+ # init
+ #
+ # Function:	- initialize program
+ # Accepts:	- (none)
+ # Returns:	- (initializes global variables)
+ #
+ sub init
+ {
+   $this = $0;
+   $this =~ s/^.*\/([^\/]+)$/$1/;
+ 
+   # listing options
+   #
+   $no_fail =
+     $no_xfail = 
+       $no_xpass = 
+ 	$no_unr = 
+ 	  $no_ski = 
+ 	    $no_other = 0;
+ 
+   # space delimited list of run passes to provide summary on
+   #
+   $runpass = '';
+ 
+   # gdb.sum ids
+   #
+   @sum_ids = ();
+ 
+   # gdb.sum file pathnames
+   #
+   @sum_files = ();
+ 
+   # test result anchor
+   #
+   $anchor = '=== gdb Summary ===';
+ 
+   # error message buffer
+   #
+   $errbuf = '';
+ 
+   # diff'd output?
+   #
+   $do_diff = 0;
+ 
+   # array of all multipass passes seen
+   # indexed by <sum_seq>
+   # value is space-delimited string of pass names
+   @passes = ();
+ 
+   # array of all tests seen
+   # indexed by '<sum_seq>'
+   # value is space-delimited list of test pathnames
+   #
+   @tests = ();
+ 
+   # hash of test point entries and outcome
+   # keyed by '<sum_seq> <pass> <test>'
+   # value is '<pcode> <entry_name>'
+   #
+   %entries = ();
+ 
+   # hash of unclassifiable errors
+   # keyed by '<sum_seq> <pass> <test>'
+   # value is multiline output
+   #
+   %others = ();
+ 
+   # hash of test point entries and outcome for all passes
+   # keyed by '<test>'
+   # value is '(<pcode> )+<entry_name>'
+   #
+   %allentries = ();
+ 
+   # array of all multipass passes seen in all runs
+   #
+   @allpasses = ();
+ 
+   # array of all tests seen in all runs
+   #
+   @alltests = ();
+ 
+   # array of counts of all PASS for a gdb.sum file
+   # indexed by '<sum_seq>'
+   # value is count
+   #
+   @p_cnts = ();
+ 
+   # array of counts of all FAIL for a gdb.sum file
+   # indexed by '<sum_seq>'
+   # value is count
+   #
+   @f_cnts = ();
+ 
+   # array of counts of all XPASS for a gdb.sum file
+   # indexed by '<sum_seq>'
+   # value is count
+   #
+   @xpa_cnts = ();
+ 
+   # array of counts of all XFAIL for a gdb.sum file
+   # indexed by '<sum_seq>'
+   # value is count
+   #
+   @xfa_cnts = ();
+ 
+   # array of counts of all UNRESOLVED tests for a gdb.sum file
+   # indexed by '<sum_seq>'
+   # value is count
+   #
+   @unr_cnts = ();
+ 
+   # array of counts of all skipped (unsupported) tests for a gdb.sum file
+   # indexed by '<sum_seq>'
+   # value is count
+   #
+   @ski_cnts = ();
+ }
+ 
+ #
+ # parseCmdLine
+ #
+ # Function:	- parse program command line arguments
+ # Accepts:	- (none)
+ # Returns:	- (none)
+ #
+ sub parseCmdLine
+ {
+   local($arg, $arg2, $seen_quick);
+ 
+   &usage('') if ($#ARGV < 1);
+ 
+   $seen_quick = 0;
+ 
+   while ($#ARGV >= 0) {
+     $arg = shift @ARGV;
+ 
+     if ($arg =~ /^-no-f/) {
+       if ($seen_quick) {
+ 	$errbuf .= "(warning): -quick overrides -no-fail\n";
+       } else {
+ 	$no_fail = 1;
+       }
+     } elsif ($arg =~ /^-no-xfa/) {
+       $no_xfail = 1;
+     } elsif ($arg =~ /^-no-xpa/) {
+       $no_xpass = 1;
+     } elsif ($arg =~ /^-no-unr/) {
+       $no_unr = 1;
+     } elsif ($arg =~ /^-no-ski/) {
+       $no_ski = 1;
+     } elsif ($arg =~ /^-no-oth/) {
+       $no_other = 1;
+     } elsif ($arg =~ /^-quick/) {
+       $errbuf .= "(warning): -quick overrides -no-fail\n"
+ 	if ($no_fail);
+       $no_fail = 0;
+       $no_xfail = $no_xpass = $no_unr = $no_ski = $no_other = 1;
+       $seen_quick = 1;
+     } elsif ($arg eq '-runpass') {
+       &usage("(error): need -runpass <string> argument pair")
+ 	if ($#ARGV == -1);
+       $runpass = shift @ARGV;
+       $runpass = ' '.$runpass.' ';
+     } else {
+       &usage("(error): need <string label> <gdb.sum> argument pair")
+ 	if ($#ARGV == -1);
+       $arg2 = shift @ARGV;
+       &usage("(error): cannot read gdb.sum file '$arg2'")
+ 	if ((! -f $arg2) || (! -r $arg2));
+       system("grep -q '$anchor' $arg2");
+       $rc = ($? >> 8);
+       if ($rc) {
+ 	$errbuf .= "(warning): $arg2 ($arg) incomplete, skipped ...\n";
+       } else {
+ 	push(@sum_ids, $arg);
+ 	push(@sum_files, $arg2);
+       }
+     }
+   }
+ 
+   &usage("$errbuf"."(error): need <string label> <gdb.sum> argument pair")
+     if ($#sum_ids == -1);
+ 
+   print STDERR "$this $errbuf" if ($errbuf ne '');
+ }
+ 
+ 
+ #
+ # parseSumFile
+ #
+ # Function:	- parse a gdb.sum file and stuff test result info into
+ #                 hash tables
+ # Accepts:	- sum_seq: sequence number of gdb.sum file
+ #               - sum_file: pathname of gdb.sum file
+ # Returns:	- (modifies global hash tables)
+ #
+ sub parseSumFile
+ {
+   local($sum_seq, $sum_file) = @_;
+   local($pass, $test, $testname, $entry);
+   local($skippass);
+ 
+   open(SUMFILE, $sum_file) ||
+     die "$this: (error): cannot read gdb.sum file '$sum_file'";
+ 
+   # initialize counts
+   #
+   $p_cnts[$sum_seq] =
+     $f_cnts[$sum_seq] =
+       $xpa_cnts[$sum_seq] =
+ 	$xfa_cnts[$sum_seq] =
+ 	  $unr_cnts[$sum_seq] =
+ 	    $ski_cnts[$sum_seq] = 0;
+   
+   # skip the gdb.sum header
+   #
+   $pass = ' ';
+   $test = '';
+   $skippass = 0;
+ 
+   while (<SUMFILE>) {
+     chop;
+   
+     if (/^Running pass \`(.+)\'\s+\.\.\.\s*$/) {
+       # seen a multipass pass
+       # record the pass
+       #
+       if (($runpass ne '') && (index($runpass, " $1 ") == -1)) {
+ 	$skippass = 1;
+ 	next;
+       } else {
+ 	$skippass = 0;
+ 	$pass = $1;
+ 	$passes[$sum_seq] = $pass;
+       }
+     } elsif ($skippass) {
+       # we've seen a multipass pass, and we skipped it since it's
+       # not what the user wanted us to summarize on.
+       # skip all info associated with the skipped pass until we
+       # see the next pass.
+       #
+       next;
+     } elsif (/^Running.+testsuite\/(.+)\s+\.\.\.\s*$/) {
+       # seen the first test
+       # $test is pathname of test under testsuite/
+       #
+       $test = $1;
+ 
+       # $testname is what runtest spits out, e.g.
+       #    if $test is gdb.hp/gdb.base-hp/foo.exp,
+       #    $testname is gdb.base-hp/foo.exp
+       #    (this is to handle the unexpected case where 
+       #     a directory's basename is the same as another directory's)
+       #
+       $testname = $test;
+       $testname = $1 if ($testname =~ /\/([^\/]+\/[^\/]+)$/);
+       #
+       # escape regexp characters in $testname, e.g. c++ -> c\+\+,
+       # since we need to use $testname in regexp pattern matching later on
+       #
+       $testname =~ s/\+/\\+/g;
+       $testname =~ s/\?/\\?/g;
+       $testname =~ s/\*/\\*/g;
+ 
+       # break out of loop since we've found the starting location
+       # of test result summary 
+       last;
+     }
+   }
+ 
+   # if we didn't find any test, just return
+   #
+   return if ($test eq '');
+ 
+   # if we've skipped to the end of the file without finding
+   # any pass to start on, just return.
+   #
+   return if ($skippass);
+   $skippass = 0;
+ 
+   # for no-multipass add the '1' pass identifier
+   # (this is to handle the case when multipass is not defined for the test run)
+   #
+   if ($pass eq ' ') {
+     $pass = '1';
+     $passes[$sum_seq] = $pass;
+   }
+ 
+   # initialize %tests, %entries, and %others hash table entries
+   #
+   &initTestInfo($sum_seq, $pass, $test);
+ 
+   # parse each line of test result summary until done
+   #
+   while (<SUMFILE>) {
+     chop;
+ 
+     if (/^\s*$/) {
+       # empty line, ignore
+       #
+       next;
+     } elsif (/^Running pass \`(.+)\'\s+\.\.\.\s*$/) {
+       # another multipass pass
+       #
+ 
+       # chop the last \n from %entries and %others hash table entries
+       # (this is for the last test in this multipass pass)
+       # ... we must only do this once
+       #
+       if (! $skippass) {
+ 	if (defined($entries{"$sum_seq $pass $test"})) {
+ 	  chop $entries{"$sum_seq $pass $test"};
+ 	  $ski_cnts[$sum_seq]++
+ 	    if ($entries{"$sum_seq $pass $test"} eq '');
+ 	}
+ 
+ 	if (defined($others{"$sum_seq $pass $test"})) {
+ 	  chop $others{"$sum_seq $pass $test"};
+ 	}
+       }
+ 
+       if (($runpass ne '') && (index($runpass, " $1 ") == -1)) {
+ 	$skippass = 1;
+ 	next;
+       } else {
+ 	$skippass = 0;
+ 	$pass = $1;
+ 	$passes[$sum_seq] .= ' '.$pass;
+       }
+     } elsif (/^\s+$anchor\s*$/) {
+       # end of test result body
+       #
+ 
+       # chop the last \n from %entries and %others hash table entries
+       # (this is for the last test in the whole test run)
+       # ... we must only do this once
+       #
+       if (! $skippass) {
+ 	if (defined($entries{"$sum_seq $pass $test"})) {
+ 	  chop $entries{"$sum_seq $pass $test"};
+ 	  $ski_cnts[$sum_seq]++
+ 	    if ($entries{"$sum_seq $pass $test"} eq '');
+ 	}
+ 
+ 	if (defined($others{"$sum_seq $pass $test"})) {
+ 	  chop $others{"$sum_seq $pass $test"};
+ 	}
+       }
+ 
+       # we're done parsing this file
+       #
+       last;
+     } elsif ($skippass) {
+       # we've seen a multipass pass, and we skipped it since it's
+       # not what the user wanted us to summarize on.
+       # skip all info associated with the skipped pass until we
+       # see the next pass.
+       #
+       next;
+     } elsif (/^Running.+testsuite\/(.+)\s+\.\.\.\s*$/) {
+       # another test
+       #
+ 
+       # chop the last \n from %entries and %others hash table entries
+       #
+       if (defined($entries{"$sum_seq $pass $test"})) {
+ 	chop $entries{"$sum_seq $pass $test"};
+ 	$ski_cnts[$sum_seq]++
+ 	  if ($entries{"$sum_seq $pass $test"} eq '');
+       }
+ 
+       if (defined($others{"$sum_seq $pass $test"})) {
+ 	chop $others{"$sum_seq $pass $test"};
+       }
+ 
+       # setup for the next test
+       #
+       $test = $1;
+ 
+       $testname = $test;
+       $testname = $1 if ($testname =~ /\/([^\/]+\/[^\/]+)$/);
+       $testname =~ s/\+/\\+/g;
+       $testname =~ s/\?/\\?/g;
+       $testname =~ s/\*/\\*/g;
+ 
+       &initTestInfo($sum_seq, $pass, $test);
+     } elsif (/^PASS:.*$testname: (.+)\s*$/) {
+       # PASS
+       #
+       $p_cnts[$sum_seq]++;
+       $entry = $1;
+       $entry =~ s/\s+/ /g;
+       $entries{"$sum_seq $pass $test"} .= "P $entry\n";
+     } elsif (/^FAIL:.*$testname: (.+)\s*$/) {
+       # FAIL
+       #
+       $f_cnts[$sum_seq]++;
+       $entry = $1;
+       $entry =~ s/\s+/ /g;
+       if ($entry =~ /\(timeout\)/) {
+ 	$entry =~ s/ \(timeout\)//;
+ 	$entry =~ s/\(timeout\) //;
+ 	$entries{"$sum_seq $pass $test"} .= "FTM $entry\n";
+       } else {
+ 	$entries{"$sum_seq $pass $test"} .= "F $entry\n";
+       }
+     } elsif (/^XFAIL:.*$testname: (.+)\s*$/) {
+       # XFAIL
+       #
+       $xfa_cnts[$sum_seq]++;
+       $entry = $1;
+       $entry =~ s/\s+/ /g;
+       $entry =~ s/ \(PRMS [^\)]+\)//;
+       $entry =~ s/\(PRMS [^\)]+\) //;
+       if ($entry =~ /\(timeout\)/) {
+ 	$entry =~ s/ \(timeout\)//;
+ 	$entry =~ s/\(timeout\) //;
+ 	$entries{"$sum_seq $pass $test"} .= "XTM $entry\n";
+       } else {
+ 	$entries{"$sum_seq $pass $test"} .= "XFA $entry\n";
+       }
+     } elsif (/^XPASS:.*$testname: (.+)\s*$/) {
+       # XPASS
+       #
+       $xpa_cnts[$sum_seq]++;
+       $entry = $1;
+       $entry =~ s/\s+/ /g;
+       $entry =~ s/ \(PRMS [^\)]+\)//;
+       $entry =~ s/\(PRMS [^\)]+\) //;
+       $entries{"$sum_seq $pass $test"} .= "XPA $entry\n";
+     } elsif (/^UNRESOLVED:.*$testname: (.+)\s*$/) {
+       # UNRESOLVED
+       #
+       $unr_cnts[$sum_seq]++;
+       $entry = $1;
+       $entry =~ s/\s+/ /g;
+       $entries{"$sum_seq $pass $test"} .= "UNR $entry\n";
+     } else {
+       # other unclassifiable line, e.g.
+       # verbose compilation failures, ERRORs, etc.
+       #
+       if (defined($others{"$sum_seq $pass $test"})) {
+ 	# only interested in specific test related junks, 
+ 	# in case junks are seen after a multipass id line but
+ 	# before a test id line
+ 	#
+ 	$others{"$sum_seq $pass $test"} .= $_."\n";
+       }
+     }
+   }
+ 
+   close(SUMFILE);
+ }
+ 
+ 
+ #
+ # initTestInfo
+ #
+ # Function:	- initialize test information variables
+ # Accepts:	- sum_seq: gdb.sum file sequence number
+ #               - pass: multipass pass id
+ #               - test: test pathname
+ # Returns:	- (modifies global hash tables)
+ #
+ sub initTestInfo
+ {
+   local($sum_seq, $pass, $test) = @_;
+ 
+   if (! defined($tests[$sum_seq])) {
+     $tests[$sum_seq] = $test;
+   } else {
+     $tests[$sum_seq] .= ' '.$test
+       if (index(" $tests[$sum_seq] ", " $test ") == -1);
+   }
+ 
+   $entries{"$sum_seq $pass $test"} = '';
+   $others{"$sum_seq $pass $test"} = '';
+ }
+ 
+ 
+ #
+ # printOthers
+ #
+ # Function:	- prints unclassifiable test result output
+ # Accepts:	- (none)
+ # Returns:	- (none)
+ #
+ sub printOthers
+ {
+   local($sum_seq);
+   local($seen, $othcnt, $prevbuf, $printed, $pass, $indent);
+ 
+   $indent = 8;
+   $indent += 5 if ($do_diff);
+ 
+   &printHeader("Unknown", '');
+   foreach $test (@alltests) {
+     $printed = 0;
+     foreach $pass (@allpasses) {
+       $seen = 0;
+       $othcnt = 0;
+       $prevbuf = '';
+       for ($sum_seq = 0; $sum_seq <= $#sum_ids; $sum_seq++) {
+ 	if (defined($others{"$sum_seq $pass $test"})
+ 	    &&
+ 	    ($others{"$sum_seq $pass $test"} ne '')) {
+ 	  $othcnt++;
+ 	  if ($sum_seq == 0) {	  
+ 	    $prevbuf = $others{"$sum_seq $pass $test"};
+ 	  } elsif ($prevbuf ne $others{"$sum_seq $pass $test"}) {
+ 	    $seen = 1;
+ 	    last;
+ 	  }
+ 	}
+       }
+       $seen = 1 if (($othcnt != 0)
+ 		    &&
+ 		    ((! $do_diff) || ($othcnt != $#sum_ids+1)));
+       if ($seen) {
+ 	print "$test\n" if (! $printed);
+ 	$printed = 1;
+ 	for ($sum_seq = 0; $sum_seq <= $#sum_ids; $sum_seq++) {
+ 	  if (! defined($others{"$sum_seq $pass $test"})) {
+ 	    if ($do_diff) {
+ 	      print " <$sum_seq>:";
+ 	      print &listPcodes($pass);
+ 	      print "<TEST NOT RUN>\n";
+ 	    }
+ 	  } elsif ($others{"$sum_seq $pass $test"} eq '') {
+ 	    if ($do_diff) {
+ 	      print " <$sum_seq>:";
+ 	      print &listPcodes($pass);
+ 	      print "<NO UNKNOWN OUTPUT>\n";
+ 	    }
+ 	  } else {
+ 	    print " <$sum_seq>:" if ($do_diff);
+ 	    print &listPcodes($pass);
+ 	    print join("\n".(' 'x$indent),
+ 		       split(/\n+/, $others{"$sum_seq $pass $test"}));
+ 	    print "\n";
+ 	  }
+ 	}
+ 	print "\n";
+       }
+     }
+   }
+ }
+ 
+ 
+ #
+ # printEntries
+ #
+ # Function:	- prints FAIL/XFAIL/XPASS/UNRESOLVED test entries
+ # Accepts:	- (none)
+ # Returns:	- (none)
+ #
+ sub printEntries
+ {
+   local($tmp, $test);
+ 
+   $tmp = '';
+   $tmp .= 'FAIL / ' if (! $no_fail);
+   $tmp .= 'XFAIL / ' if (! $no_xfail);
+   $tmp .= 'XPASS / ' if (! $no_xpass);
+   $tmp .= 'UNRESOLVED / ' if (! $no_xpass);
+   chop $tmp; chop $tmp; chop $tmp;
+ 
+   &printHeader($tmp,
+ 	       '(P:PASS F:FAIL FTM:FAIL/timeout XFA:XFAIL XTM:XFAIL/timeout XPA:XPASS UNR:UNRESOLVED SKI:skipped \'-\':not run)');
+ 
+   &mergeEntries;
+ 
+   foreach $test (@alltests) {
+     if ((defined($allentries{$test})) && ($allentries{$test} ne '')) {
+       print "$test\n$allentries{$test}";
+       print "\n" if (! $do_diff);
+     }
+   }
+ }
+ 
+ 
+ #
+ # printSkipped
+ #
+ # Function:	- prints skipped tests
+ # Accepts:	- (none)
+ # Returns:	- (none)
+ #
+ sub printSkipped
+ {
+   local($sum_seq);
+   local($seen, $skicnt, $pass, @pcodes);
+ 
+   &printHeader('Skipped', 'ran:Tested SKI:Skipped \'-\':Not run');
+   foreach $test (@alltests) {
+     $seen = 0;
+     foreach $pass (@allpasses) {
+       $skicnt = 0;
+       for ($sum_seq = 0; $sum_seq <= $#sum_ids; $sum_seq++) {
+ 	if ((defined($entries{"$sum_seq $pass $test"}))
+ 	    &&
+ 	    ($entries{"$sum_seq $pass $test"} eq '')) {
+ 	  $skicnt++;
+ 	}
+       }
+       $seen = 1 if (($skicnt != 0)
+ 		    &&
+ 		    ((! $do_diff) || ($skicnt != $#sum_ids+1)));
+       last if ($seen);
+     }
+     if ($seen) {
+       print "$test\n";
+       for ($sum_seq = 0; $sum_seq <= $#sum_ids; $sum_seq++) {
+ 	@pcodes = ();
+ 	foreach $pass (@allpasses) {
+ 	  if (! defined($entries{"$sum_seq $pass $test"})) {
+ 	    push(@pcodes, '-');
+ 	  } elsif ($entries{"$sum_seq $pass $test"} eq '') {
+ 	    push(@pcodes, 'SKI');
+ 	  } else {
+ 	    push(@pcodes, 'ran');
+ 	  }
+ 	}
+ 	print " <$sum_seq>:" if ($do_diff);
+ 	print &listPcodes(@pcodes);
+ 	print "\n";
+       }
+       print "\n";
+     }
+   }
+ }
+ 
+ 
+ #
+ # mergeEntries
+ #
+ # Function:	- merge %entries hash into %allentries hash for print
+ # Accepts:	- (none)
+ # Returns:	- (modifies global hash tables)
+ #
+ sub mergeEntries
+ {
+   local($sum_seq, $test, $pass);
+   local(@allentrynames);
+   local(@entrybufs, $pcode, $entryname);
+   local(%entrylookup);
+   local($failcnt, $failtmcnt, $xfailcnt, $xpasscnt, $unrcnt);
+   local($i, $j, $seen);
+   local(@pcodes);
+ 
+   foreach $test (@alltests) {
+     $allentries{$test} = '';
+ 
+     # merge all entry names from all passes of all runs for $test
+     #
+     @allentrynames = ();
+     for ($sum_seq = 0; $sum_seq <= $#sum_ids; $sum_seq++) {
+       foreach $pass (@allpasses) {
+ 	@allentrynames = &mergeEntryNames($sum_seq, $pass, $test,
+ 					  @allentrynames);
+       }
+     }
+     next if ($#allentrynames == -1);
+ 
+     # create entryname -> pcode lookup hash grouped by sum_seq and pass id
+     #
+     %entrylookup = ();
+     for ($sum_seq = 0; $sum_seq <= $#sum_ids; $sum_seq++) {    
+       foreach $pass (@allpasses) {
+ 	if (! defined($entries{"$sum_seq $pass $test"})) {
+ 	  for ($i = 0; $i <= $#allentrynames; $i++) {
+ 	    $entrylookup{"$sum_seq $pass $i $allentrynames[$i]"} = '-';
+ 	  }
+ 	} elsif ($entries{"$sum_seq $pass $test"} eq '') {
+ 	  for ($i = 0; $i <= $#allentrynames; $i++) {
+ 	    $entrylookup{"$sum_seq $pass $i $allentrynames[$i]"} = 'SKI';
+ 	  }
+ 	} else {
+ 	  @entrybufs = split(/\n+/, $entries{"$sum_seq $pass $test"});
+ 	  $i = $j = 0;
+ 	  while ($i <= $#allentrynames) {
+ 	    if ($j > $#entrybufs) {
+ 	      $entrylookup{"$sum_seq $pass $i $allentrynames[$i]"} = '-';
+ 	    } else {
+ 	      $entrybufs[$j] =~ /^([PFXATMUNRSKI\-]+) (.+)$/;
+ 	      $pcode = $1;
+ 	      $entryname = $2;
+ 	      if ($entryname ne $allentrynames[$i]) {
+ 		$entrylookup{"$sum_seq $pass $i $allentrynames[$i]"} = '-';
+ 	      } else {
+ 		$entrylookup{"$sum_seq $pass $i $allentrynames[$i]"} = $pcode;
+ 		$j++;
+ 	      }
+ 	    }
+ 	    $i++;	    
+ 	  }
+ 	}
+       }
+     }
+ 
+     # filter entries
+     #
+     for ($i = 0; $i <= $#allentrynames; $i++) {
+       $seen = 0;
+       foreach $pass (@allpasses) {
+ 	$failcnt = $failtmcnt = 
+ 	  $xfailcnt = $xfailtmcnt = 
+ 	    $xpasscnt = $unrcnt = 0;
+ 	for ($sum_seq = 0; $sum_seq <= $#sum_ids; $sum_seq++) {    
+ 	  $pcode = $entrylookup{"$sum_seq $pass $i $allentrynames[$i]"};
+ 	  if ($pcode eq 'F') {
+ 	    $failcnt++;
+ 	  } elsif ($pcode eq 'FTM') {
+ 	    $failtmcnt++;
+ 	  } elsif ($pcode eq 'XFA') {
+ 	    $xfailcnt++;
+ 	  } elsif ($pcode eq 'XFM') {
+ 	    $xfailtmcnt++;
+ 	  } elsif ($pcode eq 'XPA') {
+ 	    $xpasscnt++;
+ 	  } elsif ($pcode eq 'UNR') {
+ 	    $unrcnt++;
+ 	  }
+ 	}
+ 	if ((!$no_fail) && ($failcnt || $failtmcnt)) {
+ 	  $seen = 1 if ((! $do_diff)
+ 			||
+ 			($failcnt != 0) && ($failcnt != $#sum_ids+1)
+ 			||
+ 			($failtmcnt != 0) && ($failtmcnt != $#sum_ids+1));
+ 	}
+ 	if ((!$no_xfail) && ($xfailcnt || $xfailtmcnt)) {
+ 	  $seen = 1 if ((! $do_diff)
+ 			||
+ 			($xfailcnt != 0) && ($xfailcnt != $#sum_ids+1)
+ 			||
+ 			($xfailtmcnt != 0) && ($xfailtmcnt != $#sum_ids+1));
+ 	}
+ 	if ((!$no_xpass) && $xpasscnt) {
+ 	  $seen = 1 if ((! $do_diff) || ($xpasscnt != $#sum_ids+1));
+ 	}
+ 	if ((!$no_unr) && $unrcnt) {
+ 	  $seen =1 if ((! $do_diff) || ($unrcnt != $#sum_ids+1));
+ 	}
+ 	last if ($seen);
+       }
+ 
+       # merge pass
+       #
+       if ($seen) {
+ 	for ($sum_seq = 0; $sum_seq <= $#sum_ids; $sum_seq++) {    
+ 	  $allentries{$test} .= " <$sum_seq>:" if ($do_diff);
+ 	  @pcodes = ();
+ 	  foreach $pass (@allpasses) {
+ 	    push(@pcodes, $entrylookup{"$sum_seq $pass $i $allentrynames[$i]"});
+ 	  }
+ 	  $allentries{$test} .= &listPcodes(@pcodes);
+ 	  $allentries{$test} .= "$allentrynames[$i]\n";
+ 	}
+ 	$allentries{$test} .= "\n" if ($do_diff);
+       }
+     }
+   }
+ }
+ 
+ 
+ #
+ # mergeEntryNames
+ #
+ # Function:	- merge two list of entries into one
+ # Accepts:	- sum_seq: gdb.sum sequence number
+ #               - pass: multipass pass id
+ #               - test: test pathname
+ #               - allentrynames: array to merge into
+ # Returns:	- array of merged entry names
+ #
+ sub mergeEntryNames
+ {
+   local($sum_seq, $pass, $test, @allentrynames) = @_;
+   local(@entrynames, $entryname);
+   local($insidx, $srcidx, $dstidx, $seen);
+ 
+   @entrynames = split(/\n+/, $entries{"$sum_seq $pass $test"});
+   foreach $entryname (@entrynames) {
+     $entryname =~ s/^[^ ]+ //;
+   }
+ 
+   # initial insertion point is end of @allentrynames
+   #
+   $insidx = $#allentrynames + 1;
+ 
+   # seek insertion starting from the end of @entrynames
+   #
+   for ($srcidx = $#entrynames; $srcidx >= 0; $srcidx--) {
+     $seen = 0;
+ 
+     # look for the same item in @allentrynames
+     # starting from the last insertion point moving towards the array head
+     #
+     for ($dstidx = $insidx - 1; $dstidx >= 0; $dstidx--) {
+       if ($entrynames[$srcidx] eq $allentrynames[$dstidx]) {
+ 	# seen the same item, skip insertion
+ 	# move insertion point forward to this item
+ 	#
+ 	$seen = 1;
+ 	$insidx = $dstidx;
+ 	last;
+       }
+     }
+ 
+     if (! $seen) {
+       # no match
+       # put the entry just ahead of the last inserted item
+       #
+       splice(@allentrynames, $insidx, 0, $entrynames[$srcidx]);
+     }
+   }
+ 
+   return(@allentrynames);
+ }
+ 
+ 
+ #
+ # printHeader
+ #
+ # Function:	- print filter output header
+ # Accepts:	- section name
+ #               - legend string
+ # Returns:	- (none)
+ #
+ sub printHeader
+ {
+   local($what, $legend) = @_;
+   local($indent, $str, $i);
+ 
+   print '-'x72, "\n", " Section - $what\n";
+ 
+   $indent = 1;
+   print ' '; 
+   if ($do_diff) {
+     $indent += 5;
+     print '     ';
+   }
+ 
+   if ($legend) {
+     for ($i = 0; $i <= $#allpasses; $i++) {
+       print '|'.(' 'x((3-length($allpasses[$i]))/2)).$allpasses[$i].
+ 	(' 'x((3-length($allpasses[$i]))/2));
+       $indent += 4;
+     }
+     print '|: ';
+     $indent += 3;
+     while ((length($legend) + $indent) > 72) {
+       $str = substr($legend, 0, 72 - $indent);
+       $legend = substr($legend, 72 - $indent);
+       $i = rindex($str, ' ');
+       if (($i != -1) && ($i != length($str) - 1)) {
+ 	$legend = substr($str, $i+1).$legend;
+ 	$str = substr($str, 0, $i);
+       }
+       print "$str\n";
+       print ' 'x($indent+1);
+     }
+     print $legend;
+   } else {
+     print '|<pass_id>|: <multi-line output>';
+   }
+ 
+   print "\n", '-'x72, "\n";
+ }
+ 
+ 
+ #
+ # listPcodes
+ #
+ # Function:	- lists passcodes prefix
+ # Accepts:	- pass codes
+ # Returns:	- prefix string
+ #
+ sub listPcodes
+ {
+   local(@pcodes) = @_;
+   local($pcode);
+   local($buf);
+ 
+   $buf = ' ';
+   foreach $pcode (@pcodes) {
+     $buf .= '|'.(' 'x((3-length($pcode))/2)).$pcode.
+       (' 'x((3-length($pcode))/2));
+   }
+   $buf .= '|: ';
+ 
+   return($buf);
+ }
+ 
+  
+ #
+ # usage
+ #
+ # Function:	- prints tool usage and exits
+ # Accepts:	- error message
+ # Returns:	- exits program
+ #
+ sub usage
+ {
+   local($msg) = @_;
+ 
+   print STDERR "$this: $msg\n" if ($msg);
+ 
+   print STDERR "
+ $this - smart gdb.sum filter / merge / diff utility
+ 
+ Command line:
+    $this [<options>] <string label> <gdb.sum> [<string label> <gdb.sum> ...]
+ 
+    <options>:
+        [-no-f/ail]         don't list FAIL
+        [-no-xfa/il]        don't list XFAIL
+        [-no-xpa/ss]        don't list XPASS
+        [-no-unr/esolved]   don't list UNRESOLVED
+        [-no-ski/pped]      don't list skipped tests
+        [-no-oth/er]        don't list unclassfiable outputs
+        [-quick]            list FAIL only.
+ 
+        [-runpass <string>] list only the run pass(es) specified in the
+                            space delimited run pass list (string).
+ 
+        - the default is to list all
+ 
+    <string label>       identifier for the run corresponding to <gdb.sum>
+    <gdb.sum>            pathname of gdb.sum file
+ 
+    - if one <string label> <gdb.sum> pair specified, produce filtered test
+      result to stdout
+    - if multiple <string label> <gdb.sum> pairs specified, produce a
+      difference of filtered test result to stdout
+ 
+ ";
+ 
+   exit 1;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]