Update to new website style
[fateserver.git] / report.cgi
1 #! /usr/bin/perl
2 #
3 # Copyright (c) 2011 Mans Rullgard <mans@mansr.com>
4 #
5 # Permission to use, copy, modify, and distribute this software for any
6 # purpose with or without fee is hereby granted, provided that the above
7 # copyright notice and this permission notice appear in all copies.
8 #
9 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17 use strict;
18 use warnings;
19
20 use POSIX qw/asctime/;
21 use CGI qw/param/;
22 use HTML::Entities;
23 use MIME::Base64;
24 use FATE;
25
26 my $req_slot = param 'slot';
27 my $req_time = param 'time';
28
29 my $slotdir = "$fatedir/$req_slot";
30 my $repdir = "$slotdir/$req_time";
31 my $report = "$repdir/report.xz";
32
33 open R, '-|', "unxz -c $report" or fail 'Requsted report not found';
34
35 my $hdr  = split_header scalar <R> or fail 'Invalid report';
36 my $conf = split_config scalar <R> or fail 'Invalid report';
37 $$hdr{version} eq '0'              or fail 'Bad report version';
38
39 my %pass;
40 my %fail;
41
42 while (<R>) {
43     my $rec = split_rec $_;
44     ${$$rec{status}? \%fail: \%pass}{$$rec{name}} = $rec;
45 }
46
47 close R;
48
49 my $npass = keys %pass;
50 my $nfail = keys %fail;
51 my $ntest = $npass + $nfail;
52
53 my $rep = load_summary $req_slot, $req_time;
54 my $lastpass = load_lastpass $req_slot;
55
56 my $owner;
57 if (open O, "$slotdir/owner") {
58     chomp($owner = <O>);
59     close O;
60 }
61
62 # main text
63
64 print "Content-type: text/html\r\n";
65
66 if ($ENV{HTTP_ACCEPT_ENCODING} =~ /gzip/) {
67     print "Content-Encoding: gzip\r\n\r\n";
68     open STDOUT, '|-', 'gzip';
69 } else {
70     print "\r\n";
71 }
72
73 head1;
74 print "<title>FATE: $$hdr{slot} $$hdr{rev}</title>\n";
75 print <<EOF;
76 <script type="text/javascript">
77   function toggle(id) {
78       var e = document.getElementById(id);
79       e.style.display = e.style.display == 'table-row' ? 'none' : 'table-row';
80   }
81   function hide(id) {
82       var e = document.getElementById(id);
83       e.style.display = 'none';
84   }
85   function show_diff(name) {
86       hide(name + '-err');
87       toggle(name + '-diff');
88   }
89   function show_err(name) {
90       hide(name + '-diff');
91       toggle(name + '-err');
92   }
93 </script>
94 EOF
95 head2;
96 print "$$hdr{slot} $$hdr{rev}";
97 head3;
98
99 start 'table', id => 'config';
100 trow 'Architecture',  $$conf{arch};
101 trow 'Variant',       $$conf{subarch};
102 trow 'CPU',           $$conf{cpu};
103 trow 'OS',            $$conf{os};
104 trow 'Owner',         $owner if $owner;
105 trow 'Compiler',      $$conf{cc};
106 trow 'Configuration', '<code>' . $$conf{config} . '</code>';
107 trow 'Comment',       $$hdr{comment};
108 start 'tr';
109 td   'Revision';
110 if ($gitweb and $$hdr{rev} =~ /(N-)?(.*)/) {
111     start 'td';
112     anchor $$hdr{rev}, href => "$gitweb;a=commit;h=$2";
113     end 'td';
114 } else {
115     td $$hdr{rev};
116 }
117 end 'tr';
118 trow 'Date',          asctime gmtime parse_date $$hdr{date};
119 trow 'Status',        $npass? "$npass / $ntest" : "$$hdr{errstr} ($$hdr{status})";
120 trow 'Warnings',      $$rep{nwarn};
121 start 'tr';
122 td 'Logs';
123 start 'td';
124 while (my $logfile = glob "$repdir/*.log.gz") {
125     my ($log) = $logfile =~ m!^$repdir/([a-z_.-]+)\.log\.gz$! or next;
126     anchor $log, href => href slot=>$$hdr{slot}, time=>$$hdr{date}, log=>$log;
127     print "\n";
128 }
129 end 'td';
130 end 'tr';
131 end;
132
133 start 'div', class => 'table-responsive';
134 start 'table', id => 'tests', class => 'table';
135 if ($nfail) {
136     start 'thead';
137     start 'tr', class => 'fail';
138     if ($nfail eq 1) {
139         th "$nfail failed test", colspan => 3;
140     } else {
141         th "$nfail failed tests", colspan => 3;
142     }
143     th 'Status', class => 'errcode';
144     th 'Last good rev', class => 'lastpass';
145     end 'tr';
146     end 'thead';
147     start 'tbody';
148     for my $n (sort keys %fail) {
149         my $rec = $fail{$n};
150         my $test = $$rec{name};
151         my $diff = encode_entities decode_base64($$rec{diff}), '<>&"';
152         my $err  = encode_entities decode_base64($$rec{stderr}), '<>&"';
153         if ($diff =~ /^--- /) {
154             $diff =~ s!^--- .*$!<span class="diff-old">$&</span>!gm;
155             $diff =~ s!^\+\+\+ .*$!<span class="diff-new">$&</span>!gm;
156             $diff =~ s!^\@\@.*\@\@.*$!<span class="diff-hnk">$&</span>!gm;
157             $diff =~ s!^-.*$!<span class="diff-del">$&</span>!gm;
158             $diff =~ s!^\+.*$!<span class="diff-add">$&</span>!gm;
159             $diff =~ s!^ .*$!<span class="diff-nop">$&</span>!gm;
160         }
161         if ($diff =~ /^\s*$/) {
162             $diff = '<em>No diff output recorded</em>';
163         }
164         start 'tr', class => 'alt hilight';
165         td "diff",    class => 'toggle', onclick => "show_diff('$test')";
166         td "stderr",  class => 'toggle', onclick => "show_err('$test')";
167         td $test;
168         td $$rec{status}, class => 'errcode';
169         if ($$lastpass{$n} and $gitweb) {
170             my ($old, $new);
171             $$lastpass{$n}{rev} =~ /(N-)?(.*)/ and $old = $2;
172             $$hdr{rev}          =~ /(N-)?(.*)/ and $new = $2;
173             if ($old and $new) {
174                 start 'td';
175                 anchor $$lastpass{$n}{rev}, href => "$gitweb;a=shortlog;h=$new;hp=$old";
176                 end 'td';
177             } else {
178                 td $$lastpass{$n}{rev};
179             }
180         } else {
181             td $$lastpass{$n}? $$lastpass{$n}{rev} : 'n / a';
182         }
183         end 'tr';
184         trowa { style => 'display: none' }, ''; # nee
185         start 'tr', id => "$test-diff", class => 'diff';
186         td "<pre>$diff</pre>", colspan => 5;
187         end 'tr';
188         trowa { style => 'display: none' }, '';
189         start 'tr', id => "$test-err",  class => 'diff';
190         td "<pre>$err</pre>",  colspan => 5;
191         end 'tr';
192     }
193     end 'tbody';
194 } elsif ($ntest) {
195     start 'tr', class => 'pass'; th 'All tests successful', colspan => 3; end;
196 } else {
197     my $class = $$hdr{status}? 'fail' : 'pass';
198     start 'tr', class => $class; th 'No tests were run',    colspan => 3; end;
199 }
200 end 'table';
201 end 'div';
202
203 footer;