#!/usr/bin/perl
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# This program is distributed with GNU Go, a Go program. #
# #
# Write gnugo@gnu.org or see http://www.gnu.org/software/gnugo/ #
# for more information. #
# #
# Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 #
# and 2008 by the Free Software Foundation. #
# #
# This program is free software; you can redistribute it and/or #
# modify it under the terms of the GNU General Public License #
# as published by the Free Software Foundation - version 3 #
# or (at your option) any later version. #
# #
# This program is distributed in the hope that it will be #
# useful, but WITHOUT ANY WARRANTY; without even the implied #
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR #
# PURPOSE. See the GNU General Public License in file COPYING #
# for more details. #
# #
# You should have received a copy of the GNU General Public #
# License along with this program; if not, write to the Free #
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, #
# Boston, MA 02111, USA. #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Here is a perlscript regress.plx.
#
# It parses the XML files created by regress.pl and generates HTML.
# It is designed to be run as a CGI script.
#BEGIN {
# use CGI::Carp qw(carpout);
# my $errfile = "C:/temp/web.err";
# #open (WEBERR, ">$errfile") or die "Couldn't open $errfile.";
# carpout(STDOUT);
#}
#
use strict;
use warnings;
use CGI qw/:standard/;
use CGI::Carp 'fatalsToBrowser';
use FindBin;
use lib "$FindBin::Bin/../interface";
use GoImage::Stone;
use HTML::Entities ;#qw/encode_entity/;
#set $name to whatever this script is called in the URL.
#eg, if you access it from http://example.com/regress/
#then set $name = ""
my $name = "regress.plx";
my $debug=2;
my %colors = ("ALIVE", "green",
"DEAD", "cyan",
"CRITICAL", "red",
"UNKNOWN", "yellow",
"UNCHECKED", "magenta");
my $query = new CGI;
my ($tstfile, $num, $sortby, $sgf, $reset, $trace, $bycat,
$unexpected, $slow, $special, $move, $small);
($tstfile, $num) = ($query->query_string() =~ /keywords=(.*)%3A(.*)/);
if (!$tstfile) {
$tstfile = $query->param("tstfile");
$num = $query->param("num");
$sortby = $query->param("sortby");
$sgf = $query->param("sgf");
$reset = $query->param("reset");
$trace = $query->param("trace");
$bycat = $query->param("bycat");
$unexpected = $query->param("unexpected");
$slow = $query->param("slow");
$special = $query->param("special");
$move = $query->param("move");
$small = $query->param("small");
}
sub sgfFile(%);
#print "HTTP/1.0 200 OK\r\n";
print "Content-type: " .
do {
my $plain = $trace;
if ($sgf) { "application/x-go-sgf" }
elsif ($plain) { "text/plain" }
else {"text/html"; }
} . "\r\n\r\n";
if ($tstfile) {
$tstfile = $1 if $tstfile =~ /(.*)\.tst$/;
}
if ($tstfile && !($tstfile =~ /^[a-zA-Z0-9_]+$/)) {
print "bad test file: $tstfile\n";
exit;
}
if ($reset) {
unlink glob("html/*.html");# or die "couldn't delete html files: $!";
unlink glob("html/*/*.html");# or die "couldn't delete html/* files: $!";
unlink "html/one.perldata";# or die "couldn't delete data file";
print "Cleaned up!
\n";
}
if ($trace) {
open (TRACER, "html/$tstfile.tst/$num.trace") or
do {print "Couldn't find trace file: $!"; exit;};
while () {
print;
}
close TRACER;
exit;
}
my %points;
unless ($tstfile) {
#CASE 1 - main index
if (!-e "html/index.html") {
createIndex();
} else {
print STDERR "Cached!\n";
}
if ($bycat) {
printbycategory();
exit;
}
if ($unexpected) {
printunexpected();
exit;
}
if ($slow) {
printslow();
exit;
}
if ($special) {
printspecial();
exit;
}
if (-z "html/index.html") {
print "Yikes - index missing - please reset!";
exit;
}
open (TESTFILE, "html/index.html") or do {print "$! ".__LINE__; confess "$!"};
while () {
print;
}
close TESTFILE;
exit;
}
my %fullHash;
#use Data::Dumper;
sub insinglequote {
my $s = shift;
$s =~ s@\\@\\\\@g;
$s =~ s@'@\\'@g;
return "'$s'";
}
sub FastDump {
my ($h) = @_;
open (FILE, ">html/one.perldata.new") or confess "can't open";
print FILE "\$VAR1 = [\n {\n";
#print FILE Dumper([\%h]) or confess "couldn't print";
foreach my $k1 (sort keys %{$h}) {
print FILE " '$k1' =>\n {\n";
foreach my $k2 (sort keys %{%{$h}->{$k1}}) {
print FILE " '$k2' => " . insinglequote(%{$h}->{$k1}->{$k2}) . ",\n";
}
print FILE " },\n";
}
print FILE " }\n ];";
close FILE or confess "can't close";
}
sub createIndex {
my %h;
foreach my $file (glob("html/*.tst/*.xml")) {
my ($tst, $prob) = $file =~ m@html.(.*).tst.(.*).xml@;
open (FILE, "$file");
local $/; undef($/);
my $content = ;
close FILE;
$h{"$tst:$prob"} = game_parse($content, 0);
delete $h{"$tst:$prob"}->{gtp_all};
}
FastDump(\%h);
#print "DONE!\n";
#return;
#our $VAR1;
#do "html/one.perldata" or confess "can't do perldata";
#my %h = %{$VAR1->[0]};
open I, ">html/index.html";
print I qq@
Regression test summary -
Regression test summary -
Program: _CMDLINE_TBD_
View by category
View unexpected results
file | passed | PASSED | failed | FAILED |
@;
my @pflist = ("passed", "PASSED", "failed", "FAILED");
my %totHash;
@totHash{@pflist} = (0,0,0,0);
sub byfilebynum {
my ($fileA,$numA) = $a =~ /(.*):(.*)/;
my ($fileB,$numB) = $b =~ /(.*):(.*)/;
$fileA cmp $fileB or $numA <=> $numB;
}
my $curfile = "";
my %subTotHash;
foreach my $k1 (sort byfilebynum keys %h) { #$k1 = filename
if ($k1 !~ /^$curfile:/) {
if ($curfile ne "") {
#New file = print old totals
print I qq@\n $curfile | \n@;
foreach my $k2 (@pflist) {
my $c = @{$subTotHash{$k2}}; #i.e. length of array.
$totHash{$k2} += $c;
if ($k2 !~ /passed/ and $c) {
print I " $c: \n";
foreach (sort {$a<=>$b} @{$subTotHash{$k2}}) {
print I qq@ $_\n@;
}
print I " | \n";
} else {
print I " $c | \n";
}
}
print I qq@
@;
}
#prepare for next file.
($curfile) = $k1 =~ /(.*):/;
@subTotHash{@pflist} = ([],[],[],[]);
}
push @{$subTotHash{$h{$k1}{status}}}, $h{$k1}{num};
}
#direct copy from above - don't miss last time through - HACK!
if ($curfile ne "") {
#New file = print old totals
print I qq@\n $curfile | \n@;
foreach my $k2 (@pflist) {
my $c = @{$subTotHash{$k2}}; #i.e. length of array.
$totHash{$k2} += $c;
if ($k2 !~ /passed/ and $c) {
print I " $c: \n";
foreach (sort {$a<=>$b} @{$subTotHash{$k2}}) {
print I qq@ $_\n@;
}
print I " | \n";
} else {
print I " $c | \n";
}
}
print I qq@
@;
}
print I "\n Total | \n";
foreach (@pflist) {
print I " $totHash{$_} | \n";
}
print I "
\n";
print I "
\n";
close I;
}
sub bypPfF {
pPfFtonum($a) <=> pPfFtonum($b);
}
sub pPfFtonum {
$_ = shift;
s/FAILED/4/; s/failed/3/; s/PASSED/2/; s/passed/1/;
$_;
}
sub fptonum {
$_ = shift;
s/FAILED/1/; s/failed/3/; s/PASSED/2/; s/passed/4/; s///; s@@@;
$_;
}
my @counters = qw/connection_node owl_node reading_node trymove/;
if ($move) {
#CASE 2a - move detail - extract interesting info from trace file.
if (!$num) {
print "Must provide num if providing move.
";
exit;
}
print qq@
$tstfile:$num move $move
\n@;
open (FILE, "html/$tstfile.tst/$num.trace") or die "couldn't open trace file $tstfile, $num: $!.";
#local $/; undef($/);
#my $content = ;
#close FILE;
my $blank=1;
my $inpattern=0;
$move = uc($move);
print "\n";
while () {
if (/^$move[^0-9]/ ||
/[^A-Za-z0-9]$move[^0-9]/ ||
$inpattern && /^\.\.\./) {
print encode_entities($_);
$blank=0;
$inpattern ||= /^pattern.*at $move/;
} else {
print "\n" unless $blank;
$blank++;
$inpattern=0;
}
}
print "
\n";
exit;
}
if ($num) {
#CASE 2 - problem detail.
if ($sgf && -e "html/$tstfile.tst/$num.sgf") {
open (SGFFILE, "html/$tstfile.tst/$num.sgf") or confess "couldn't open file";
while () {
print;
}
close SGFFILE;
exit;
}
open (FILE, "html/$tstfile.tst/$num.xml") or die "couldn't open xml file\n";
local $/; undef($/);
my $content = ;
close FILE;
my %attribs = %{game_parse($content, 1)};
if ($sgf) {
foreach (sort keys %attribs) {
# print "$_: $attribs{$_}\n";
}
sgfFile(%attribs);
exit;
}
print qq@
$tstfile:$num details.
\n@;
print qq@\n@;
print qq@
number: | $attribs{"num"} | |
cputime: | $attribs{"cputime"} |
status: | $attribs{"status"} | |
$counters[0]: | $attribs{"$counters[0]_counter"} |
correct: | $attribs{"correct"} | |
$counters[1]: | $attribs{"$counters[1]_counter"} |
answer: | $attribs{"answer"} | |
$counters[2]: | $attribs{"$counters[2]_counter"} |
gtp: | $attribs{"gtp_command"} | |
$counters[3]: | $attribs{"$counters[3]_counter"} |
category: | $attribs{"category"} |
severity: | $attribs{"severity"} |
description: | $attribs{"description"} |
\n\n@;
print qq@
\n\n@;
print qq@
@;
print qq@ dragon_status | owl_status\n@;
my $boardsize = $attribs{"boardsize"}; #need to add to export.
my $colorboard;
$colorboard .= "\n"
. colorboard_letter_row($boardsize). "\n";
for (my $j = $boardsize; $j > 0; $j--) {
my $jA = $j;
$jA .= " " if ($j <= 9);
$colorboard .= " \n $j | \n";
for (my $i = 1; $i <= $boardsize; $i++) {
my $iA = ord('A') + $i - 1;
if ($iA >= ord('I')) { $iA++; }
$iA = chr($iA);
my $coord = $iA.$j;
my $bw = pval($coord, "stone");
my $img_pix_size = 25;
my $dragonletter = pval($coord, "dragon_letter");
my $dragoncolor = $colors{pval($coord, "dragon_status")};
my $owlcolor = $colors{pval($coord, "owl_status")};
my $owlletter = $dragonletter;
my $alt = "";
my ($markcolor, $known, $try) = ("", pval($coord, "known"), pval($coord, "try"));
$markcolor = "magenta" if ($known and $known eq "wrong");
$markcolor = "green" if ($known and $known eq "right");
$markcolor = "cyan" if ($try and $try eq "right");
$markcolor = "red" if ($try and $try eq "wrong");
my $question = pval($coord, "question");
if ($question) {
$dragonletter .= "*";
$owlletter = "";
$dragoncolor = "blue" unless $dragoncolor;
}
my $score = pval($coord, "move_value");
if ($score) {
# FIXME: Should round this, not truncate it.
# Also, should remove trailing "." if not necessary.
$dragonletter = substr($score, 0,3);
$dragoncolor = "blue";
$owlletter="";
$alt = "whack";
}
my $colorboard_imgsrc = createPngFile($bw, $img_pix_size, "", $dragonletter, $dragoncolor, $owlletter, $owlcolor, $markcolor);
$colorboard .= qq@ @ .
qq@ | \n@;
}
$colorboard .= " $j | \n \n";
}
$colorboard .= colorboard_letter_row($boardsize);
$colorboard .= "\n \n";
print $colorboard;
print qq@ |
\n\n\n\n
green=alive
cyan=dead
red=critical
yellow=unknown
magenta=unchecked
|
@;
my $gtpall = $attribs{gtp_all};
$gtpall =~ s/
//mg;
$gtpall =~ s/\s+$//mg;
$gtpall =~ m@loadsgf\s+ ((?:\w|[-+.\\/])+) [ \t]* (\d*) @x
or $gtpall =~m/(.*?)/; #Problems!!!!
my $cmdline = "gq -l $1 " . ($2 ? "-L $2 " : "");
if ($gtpall =~ m@ .* (owl_attack|owl_defend|dragon_status) \s* ([A-Z]\d{1,2}) \s* $ @x) {
$cmdline .= "--decide-dragon $2 -o x.sgf" ;
} elsif ($gtpall =~ m@ .* (reg_genmove\s+[whiteblack]*) \s* $@x) {
$cmdline .= "-t -w -d0x101800";
} elsif ($gtpall =~ m@ .* (attack|defend) \s* ([A-Z]\d{1,2}) \s* $ @x) {
$cmdline .= "--decide-string $2 -o x.sgf";
} else {
$cmdline .= "
(directive unrecognized)";
}
print qq@
\n\n@;
print qq@\n@;
print qq@ CMD Line Hint: | $cmdline |
\n@;
print qq@ Full GTP: | $attribs{gtp_all} |
\n
\n@;
print "\n\n";
# print %attribs;
} else {
if ($small) {
summaryDiagrams();
}
#CASE 3 - test file summary.
# if (!-e "html/$tstfile.tst/index.html") {
summarizeTestFile();
# } else {
# print "Cached:
";
# }
# open (TESTFILE, "html/$tstfile.tst/index.html") or (print "$! ".__LINE__, die);
# while () {
# print;
# }
# close TESTFILE;
}
sub summaryDiagrams {
my $content;
foreach my $curfile (glob("html/$tstfile.tst/*.xml"))
{
%points = {};
$curfile =~ s/html.$tstfile.tst.(.*xml)/$1/;
local $/;
undef($/);
open(FILE, "html/$tstfile.tst/$curfile");
$content = ;
close FILE;
my %attribs = %{game_parse($content, 1)};
print qq@
$tstfile:$attribs{num}\n@;
my $boardsize = $attribs{"boardsize"}; #need to add to export.
my $colorboard;
$colorboard .= "\n"
. "\n";
my $img_pix_size = 9;
for (my $j = $boardsize; $j > 0; $j--) {
my $jA = $j;
$jA .= " " if ($j <= 9);
$colorboard .= "\n";
for (my $i = 1; $i <= $boardsize; $i++) {
my $iA = ord('A') + $i - 1;
if ($iA >= ord('I')) { $iA++; }
$iA = chr($iA);
my $coord = $iA.$j;
my $bw = pval($coord, "stone");
my $alt = "";
my $colorboard_imgsrc = createPngFile($bw, $img_pix_size, "", "","","","", "");
$colorboard .= qq@ @ .
qq@ | \n@;
}
$colorboard .= "
\n";
}
#$colorboard .= colorboard_letter_row($boardsize);
$colorboard .= "\n
\n";
print $colorboard;
}
exit;
}
my %files;
sub summarizeTestFile {
unless ($sortby) { $sortby = "filepos"; }
# open (TF, "> html/$tstfile.tst/index.html")
# or print "couldn't open for output; $!\n", die;
*TF = *STDOUT;
print TF qq@
$tstfile regression results - _VERSION_
\n@;
print TF "\n";
print TF "$tstfile regression results - _VERSION_
\n";
print TF qq@
line |
number |
result |
expected |
got |
gtp |
cputime |
owl_node |
reading_node |
1000*time/owl_node |
\n@;
my @files = glob("html/$tstfile.tst/*.xml");
foreach my $curfile (@files) {
$curfile =~ s/html.$tstfile.tst.(.*xml)/$1/;
local $/;
undef($/);
open(FILE, "html/$tstfile.tst/$curfile");
my $content = ;
close FILE;
my $gtp_all = $1
if $content =~ m@(.*?)@s;
my $gtp = escapeHTML($1)
if $content =~ m@(.*?)@s;
my $result = $1
if $content =~ m@(.*?)@s;
my $got = $1
if $content =~ m@(.*?)@s;
my $cputime = $1
if $content =~ m@]*owl_node="?(\d+)@s;
my $reading_node = $1
if $content =~ m@]*reading_node="?(\d+)@s;
$cputime =~ s/0*$//;
$files{$curfile} = {
gtp_all => $gtp_all,
gtp => $gtp,
filepos => $filepos,
num => $num,
expected => $expected,
got => $got,
result => $result,
cputime => $cputime,
owl_node => $owl_node,
reading_node => $reading_node,
msperowl => ($owl_node ? 1000*$cputime/ $owl_node : 0),
}
}
sub byfilepos { $files{$a}{"filepos"} <=> $files{$b}{"filepos"}; }
sub bynum { $files{$a}{"num"} <=> $files{$b}{"num"}; }
sub byresult {
fptonum($files{$a}{"result"}) <=> fptonum($files{$b}{"result"})
or byfilepos();
}
sub bycputime {
$files{$b}{cputime} <=> $files{$a}{cputime}
or byfilepos();
}
sub byowl_node {
$files{$b}{owl_node} <=> $files{$a}{owl_node}
or byfilepos();
}
sub byreading_node {
$files{$b}{reading_node} <=> $files{$a}{reading_node}
or byfilepos();
}
sub bymsperowl {
$files{$b}{msperowl} <=> $files{$a}{msperowl}
or byfilepos();
}
sub filesby {
$_ = shift;
return byfilepos if /filepos/i;
return bynum if /num/i;
return byresult if /result/i;
return bycputime if /cputime/i;
return byowl_node if /owl_node/i || /owlnode/i;
return bymsperowl if /msperowl/i;
return byreading_node if /reading_node/i || /readingnode/i;
$files{$a}{$_} <=> $files{$b}{$_};
}
my %totals = (cputime=>0, owl_node=>0);
foreach my $curfile (sort {filesby($sortby)} keys %files) {
my %h = %{$files{$curfile}};
my $numURL = qq@$h{num}@;
my $r = $h{result};
$r =~ s@^([A-Z]*)$@$1@;
print TF "$h{filepos} | $numURL | $r | $h{expected} | "
. "$h{got} | $h{gtp} | $h{cputime} | $h{owl_node} | "
. "$h{reading_node} | "
. "".sprintf("%.2f",$h{msperowl})." |
\n";
$totals{cputime} += $h{cputime};
$totals{owl_node} += $h{owl_node};
$totals{reading_node} += $h{reading_node};
}
print TF "Total | | | | "
. " | | $totals{cputime} | $totals{owl_node} | "
. "$totals{reading_node} | "
." ".sprintf("%.2f",1000*$totals{cputime}/($totals{owl_node}+.0001))." |
\n";
print TF "
";
#close TF;
}
sub pval {
my ($coord, $attrib) = @_;
if ($points{$coord}) {
# print "$coord $attrib
\n";
if ($points{$coord} =~ m@$attrib="(.*?)"@) {
# if ($attrib eq 'stone') {
# print "$attrib=$1
\n";
#}
return $1;
} else {
return "";
}
} else {
return "";
}
}
sub game_parse {
my $content = shift;
my $details = shift;
my %attribs;
$attribs{"num"} = $1
if $content =~ m@(.*?)@s;
$attribs{"answer"} = $1
if $content =~ m@(.*?)@s;
$attribs{"gtp_all"} = $1
if $content =~ m@(.*?)@s;
$attribs{"description"} = $1
if $content =~ m@(.*?)@s;
$attribs{"category"} = $1
if $content =~ m@(.*?)@s;
$attribs{"severity"} = $1
if $content =~ m@(.*?)@s;
$attribs{"gtp_command"} = $1
if $content =~ m@(.*?)@s;
$attribs{"cputime"} = $1
if $content =~ m@]*size=(\d+)@s;
foreach (@counters) {
$attribs{$_."_counter"} = $1
if $content =~ m@]*$_="?(\d+)@s;
}
return \%attribs unless $details;
$content =~ s@.*?@@s) {
my $pattr = $1;
if ($pattr =~ m@coord="(.*?)"@s) {
$points{$1} = $pattr;
} else {
print "MISSING coord: " . encode($content) . "
" .
encode($pattr);
die;
}
}
return \%attribs;
}
sub colorboard_letter_row {
my $boardsize = shift;
my $ret = "
\n | \n";
for (my $i = 1; $i <= $boardsize; $i++) {
my $iA = ord('A') + $i - 1;
if ($iA >= ord('I')) { $iA++; }
$iA = chr($iA);
$ret .= " $iA | \n";
}
$ret .= " | \n
";
}
sub sgfFile(%) {
my %attribs = shift;
my $boardsize = $attribs{"boardsize"}; #need to add to export.
my $ret="";
$ret .= "(;\nFF[4]GM[1]SZ[$boardsize]\nAP[regress.plx]\n";
for (my $j = $boardsize; $j > 0; $j--) {
my $jA = $j;
$jA .= " " if ($j <= 9);
for (my $i = 1; $i <= $boardsize; $i++) {
my $iA = ord('A') + $i - 1;
if ($iA >= ord('I')) { $iA++; }
$iA = chr($iA);
my $coord = $iA.$j;
my $bw = pval($coord, "stone");
if ($bw eq "black") {
$ret .= "AB\[" . GTPtoSGF($coord, $boardsize) . "]";
} elsif ($bw eq "white") {
$ret .= "AW\[" . GTPtoSGF($coord, $boardsize) . "]";
}
}
}
$ret.=")";
$ret =~ s/((A[BW]\[..\]){12})/$1\n/g;
print $ret;
}
sub GTPtoSGF {
local $_ = shift;
my $boardsize = shift;
if (! /([A-Z])([0-9]{1,2})/) {
return ;
}
$_ = ord($1) - ord("A") + 1;
if ($_ > (ord("I") - ord("A") + 1)) { $_--; }
chr(ord("a") + $_ - 1) . chr(ord("a") + $boardsize - $2);
}
sub printslow {
our $VAR1;
do "html/one.perldata.new" or confess "can't do perldata";
my %h = %{$VAR1->[0]};
my $by_cputime =
sub {
$h{$b}->{cputime} <=> $h{$a}->{cputime}
or $a cmp $b;
};
print qq@
Slow results - GNU Go
\n@;
print "Slow results
";
print "";
print "Problem | Status | CPU Time |
\n";
my $i = 0;
foreach my $k (sort $by_cputime keys %h) {
$i++;
last if $i > 50;
print qq@$k | $h{$k}->{status} | @;
print qq@ $h{$k}->{cputime} |
@;
my ($p, $n) = $k =~ /(\w+):(\d+)/;
open (F, "html/$p.tst/$n.trace") or do {print "Missing trace file for $k
"; next;};
my $first=1;
while () {
my $line = $_;
if ($line =~ /^owl_.*\d{6} nodes/) {
print qq@ | | @ if $first-- > 0;
print qq@$line @;
}
}
print qq@ |
@ if $first < 1;
close F;
}
print "
\n";
}
sub printspecial {
our $VAR1;
do "html/one.perldata.new" or confess "can't do perldata";
my %h = %{$VAR1->[0]};
my (%special);
my $sfile = "special";
print qq@
Special results - GNU Go
\n@;
print "Special results
";
print "";
print "Problem | Status | cputime |
\n";
if (-e $sfile) {
open (BF, $sfile);
while () {
if (/^((\w+):(\d+))/) {
print qq@$1 | $h{$1}->{status} | @ .
qq@$h{$1}->{cputime} |
\n@;
}
}
close(BF);
}
print qq@
@;
}
sub printunexpected{
my (%breakage);
if (-e 'BREAKAGE.local') {
open (BF, 'BREAKAGE.local');
while () {
if (my ($bfile, $bpf) = $_ =~ /^(\w+:\d+)\s+(FAILED|PASSED)/i) {
$breakage{lc $bfile} = $bpf;
}
}
close(BF);
}
our $VAR1;
do "html/one.perldata.new" or confess "can't do perldata";
my %h = %{$VAR1->[0]};
my @fails; my @ufails;
my @passes; my @upasses;
print qq@
Unexpected results - GNU Go
\n@;
print "Unexpected results
";
sub bynamenumber {
my ($aname, $anumber) = $a =~ /(.*):(.*)/;
my ($bname, $bnumber) = $b =~ /(.*):(.*)/;
$aname cmp $bname or
$anumber <=> $bnumber or
$a cmp $b;
}
foreach my $k (sort bynamenumber keys %h) {
my $status = %{$h{$k}}->{status};
defined $status or do { warn "missing status for $k"; next;};
if ($status eq 'FAILED') {
unless (defined ($breakage{lc $k}) and $breakage{lc $k}eq 'FAILED') {
push @ufails, $k;
}
} elsif ($status eq 'PASSED') {
unless (defined ($breakage{lc $k}) and $breakage{lc $k} eq 'PASSED') {
push @upasses, $k;
}
} elsif ($status eq 'passed') {
if (defined ($breakage{lc $k})) {
push @passes, $k;
}
} elsif ($status eq 'failed') {
if (defined ($breakage{lc $k})) {
push @fails, $k;
}
}
}
print "\n";
print qq@FAILS | @.scalar(@ufails).qq@ |
\n@;
print qq@fails | @.scalar(@fails).qq@ |
\n@;
print qq@PASSES | @.scalar(@upasses).qq@ |
\n@;
print qq@passes | @.scalar(@passes).qq@ |
\n@;
print qq@pass : fail | @.
sprintf("%.2f : 1", ((@upasses + @passes) / (@ufails + @fails + .001))).
qq@ |
\n@;
print "
\n";
print "";
print "Problem | Status |
\n";
foreach (@ufails) {
print qq@$_ | FAILED |
\n@;
}
foreach (@fails) {
print qq@$_ | failed |
\n@;
}
foreach (@upasses) {
print qq@$_ | PASSED |
\n@;
}
foreach (@passes) {
print qq@$_ | passed |
\n@;
}
print "
\n";
print "\n";
}
sub printbycategory {
our $VAR1;
do "html/one.perldata.new" or confess "can't do perldata";
my %hash = %{$VAR1->[0]};
my %fails;
foreach my $k (keys %hash) {
my $status = $hash{$k}{status};
$fails{$k} = $hash{$k} if $status =~ /failed/i;
}
my $by_cat =
sub {
defined $fails{$a}{file}
or do {
print '$a:'."$a\n";
confess "missing file";
};
my $ca = $fails{$a}{category};
my $cb = $fails{$b}{category};
defined $ca or $ca = 0;
defined $cb or $cb = 0;
if ($ca ne "" and $cb eq "") { return -1; }
if ($ca eq "" and $cb ne "") { return 1; }
$ca ne "" or $ca = $fails{$a}{file};
$cb ne "" or $cb = $fails{$b}{file};
uc ($ca) cmp uc($cb)
or
do {
my $sa = $fails{$a}{severity};
my $sb = $fails{$b}{severity};
#print '$sa <=> $sb :' . "$sa <=> $sb ($ca, $cb)" , "\n"
# if defined $sa and defined $sb and ($sa ne "") and ($sb ne "");
defined $sa or $sa = 5;
defined $sb or $sb = 5;
if ($sa eq "") {$sa = 5};
if ($sb eq "") {$sb = 5};
-($sa <=> $sb);
}
or
do {
my $fa = $fails{$a}{file};
my $fb = $fails{$b}{file};
$fa cmp $fb;
}
or
do {
my $na = $fails{$a}{num};
my $nb = $fails{$b}{num};
$na <=> $nb;
}
};
sub getcat(%) {
my %h = %{shift()};
$h{category} or $h{file};
}
sub getsev(%) {
my %h = %{shift()};
my $s = $h{severity};
defined $s or do {return 5};
$s ne "" or do {return 5};
no warnings qw/numeric/;
$s+0;
}
print qq@
Failures by category - GNU Go
\n@;
print "Failures by category
";
print qq@main index@;
print "";
print "Category | Severity | Problem | \n";
my $cat = "";
my $sev = "";
foreach my $k (sort $by_cat keys %fails) {
if (uc(getcat($fails{$k})) ne $cat) {
$cat = uc(getcat($fails{$k}));
print "
\n";
print "$cat | \n";
$sev = "";
}
if (($sev eq "") or $sev != getsev($fails{$k})) {
print "
\n | " if ($sev ne "");
$sev = getsev($fails{$k});
print "$sev | \n";
}
print qq@$k  \n@;
}
print " |
\n";
print "\n";
}