File Coverage

blib/lib/Test/Smoke/Database/DB.pm
Criterion Covered Total %
statement 48 188 25.5
branch 7 102 6.8
condition 0 53 0.0
subroutine 14 20 70.0
pod 3 10 30.0
total 72 373 19.3


line stmt bran cond sub pod time code
1             package Test::Smoke::Database::DB;
2              
3             # Test::Smoke::Database::DB
4             # Copyright 2003 A.Barbet alian@alianwebserver.com. All rights reserved.
5             # $Date: 2004/04/19 17:49:35 $
6             # $Log: DB.pm,v $
7             # Revision 1.10 2004/04/19 17:49:35 alian
8             # fix on warnings
9             #
10             # Revision 1.9 2004/04/14 22:35:43 alian
11             # display address of cgi at end of run
12             #
13             # Revision 1.8 2003/11/07 17:34:53 alian
14             # Change display at import
15             #
16             # Revision 1.7 2003/09/16 15:41:50 alian
17             # - Update parsing to parse 5.6.1 report
18             # - Change display for lynx
19             # - Add top smokers
20             #
21             # Revision 1.6 2003/08/19 10:37:24 alian
22             # Release 1.14:
23             # - FORMAT OF DATABASE UPDATED ! (two cols added, one moved).
24             # - Add a 'version' field to filter/parser (Eg: All perl-5.8.1 report)
25             # - Use the field 'date' into filter/parser (Eg: All report after 07/2003)
26             # - Add an author field to parser, and a smoker HTML page about recent
27             # smokers and their available config.
28             # - Change how nbte (number of failed tests) is calculate
29             # - Graph are done by month, no longuer with patchlevel
30             # - Only rewrite cc if gcc. Else we lost solaris info
31             # - Remove ccache info for have less distinct compiler
32             # - Add another report to tests
33             # - Update FAQ.pod for last Test::Smoke version
34             # - Save only wanted headers for each nntp articles (and save From: field).
35             # - Move away last varchar field from builds to data
36             #
37             # Revision 1.5 2003/08/15 15:10:42 alian
38             # Set osver here is not needed
39             #
40             # Revision 1.4 2003/08/14 08:48:35 alian
41             # Don't save line with only t | ? | -
42             #
43             # Revision 1.3 2003/08/08 14:27:59 alian
44             # Update POD documentation
45             #
46             # Revision 1.2 2003/08/07 18:01:44 alian
47             # Update read_all to speed up requests
48             #
49             # Revision 1.1 2003/08/06 18:50:41 alian
50             # New interfaces with DB.pm & Display.pm
51             #
52              
53 3     3   20 use Carp;
  3         7  
  3         205  
54 3     3   19 use strict;
  3         6  
  3         118  
55 3     3   15 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  3         5  
  3         440  
56 3     3   18 use DBI;
  3         7  
  3         129  
57 3     3   19 use Data::Dumper;
  3         4  
  3         156  
58 3     3   16 use Carp qw(cluck);
  3         25  
  3         147  
59 3     3   17 use File::Basename;
  3         5  
  3         303  
60 3     3   3695 use Sys::Hostname;
  3         4127  
  3         459  
61             require Exporter;
62              
63             @ISA = qw(Exporter);
64             @EXPORT = qw();
65             $VERSION = ('$Revision: 1.10 $ ' =~ /(\d+\.\d+)/)[0];
66 3     3   20 use vars qw/$debug $verbose $limit/;
  3         6  
  3         9265  
67             #$limite = 0;
68              
69             #------------------------------------------------------------------------------
70             # new
71             #------------------------------------------------------------------------------
72             sub new {
73 1     1 1 3 my $class = shift;
74 1         3 my $self = {};
75 1         3 my $indexer = shift;
76 1         3 bless $self, $class;
77 1         8 $self->{DBH} = $indexer->{DBH};
78 1         4 $self->{CGI} = $indexer->{opts}->{cgi};
79 1 50       5 $debug = ($indexer->{opts}->{debug} ? 1 : 0);
80 1 50       4 $verbose = ($indexer->{opts}->{verbose} ? 1 : 0);
81 1         3 $limit = $indexer->{opts}->{limit};
82 1         4 return $self;
83             }
84              
85             #------------------------------------------------------------------------------
86             # DESTROY
87             #------------------------------------------------------------------------------
88             sub DESTROY {
89 1 50   1   1388 $_[0]->{DBH}->disconnect if ($_[0]->{DBH});
90 1 50       127 if ($verbose) {
91 0   0     0 print scalar(localtime),": Over. Consult result at:\nhttp://",
92             ($ENV{SERVER_NAME} || hostname()),"/cgi-bin/smoke_db.cgi\n";
93             }
94             }
95              
96             #------------------------------------------------------------------------------
97             # rundb
98             #------------------------------------------------------------------------------
99             sub rundb(\%\%) {
100 0     0 1 0 my ($self,$cmd,$nochomp) = @_;
101 0         0 my $ret = 1;
102 0         0 foreach (split(/;/, $cmd)) {
103 0 0       0 $_=~s/\n//g if (!$nochomp);
104 0 0 0     0 next if (!$_ or $_ eq ';');
105 0 0       0 print "mysql <-\t$_\n" if ($debug);
106 0 0       0 if (!$self->{DBH}->do($_)) {
107 0         0 print STDERR "Error $_: $DBI::errstr!\n";
108 0         0 $ret = 0;
109             }
110             }
111 0         0 return $ret;
112             }
113              
114             #------------------------------------------------------------------------------
115             # read_all
116             #------------------------------------------------------------------------------
117             sub read_all(\%) {
118 1     1 1 4 my $self = shift;
119 1         4 my $cgi = $self->{CGI};
120 1 50       7 return {} if (!$self->{DBH});
121 0         0 my ($req,%h2);
122              
123             # $a is SQL restriction on database
124 0         0 my $a;
125 0 0       0 if ($cgi->param('smoke')) { $a.="smoke =".$cgi->param('smoke'); }
  0         0  
126 0         0 else { $a.="smoke >=$limit"; }
127 0         0 foreach my $o ('cc','ccver','os','osver','archi','date','version') {
128 0   0     0 my $v = $cgi->param($o) || $cgi->param($o.'_fil')
129             || $cgi->cookie($o) || undef;
130 0 0 0     0 next if (!$v or $v eq 'All');
131 0 0       0 $a.=" and " if ($a);
132 0 0       0 if ($o eq 'date') { $a.="$o>'$v' "; }
  0         0  
133 0         0 else { $a.="$o='$v' "; }
134             }
135              
136             # Select id of build for failure & details
137 0         0 my $list_id;
138 0 0 0     0 if ($cgi->param('failure') || ($cgi->param('last'))) {
139 0         0 my $req = "select id from builds ";
140 0 0       0 $req.="where $a" if ($a);
141 0   0     0 my $ref_lid = $self->{DBH}->selectcol_arrayref($req) ||
142             print "On $req: $DBI::errstr\n";
143 0         0 $list_id = join("," , @$ref_lid);
144             }
145              
146             # Failure
147 0         0 my (%failure, %matrix);
148 0 0 0     0 if ($cgi->param('failure') || $cgi->param('last')) {
149 0         0 $req = "select idbuild,matrix";
150 0 0       0 $req.=",failure" if ($cgi->param('failure'));
151 0         0 $req.=" from data";
152 0 0       0 if ($list_id) { $req.=" where idbuild in (".$list_id.")"; }
  0         0  
153 0   0     0 my $ref_failure = $self->{DBH}->selectall_arrayref($req) ||
154             print "On $req: $DBI::errstr\n";
155 0         0 foreach my $ra (@$ref_failure) {
156 0         0 $matrix{$ra->[0]} = $ra->[1];
157 0 0       0 $failure{$ra->[0]} = $ra->[2] if $cgi->param('failure');
158             }
159             }
160              
161             # Detailed results
162 0 0       0 if ($cgi->param('last')) {
163 0         0 $req = "select idbuild,configure,result from configure ";
164 0 0       0 if ($list_id) { $req.=" where idbuild in (".$list_id.")"; }
  0         0  
165 0   0     0 my $ref_result = $self->{DBH}->selectall_arrayref($req) ||
166             print "On $req: $DBI::errstr\n";
167 0         0 foreach my $ra (@$ref_result) {
168 0         0 $h2{$ra->[0]}{$ra->[1]} = $ra->[2];
169             }
170             }
171              
172             # Each times, read config
173 0         0 $req = <
174             select id,os,osver,archi,cc,ccver,date,smoke,nbc,nbco,
175             nbcm,nbcf,nbcc,nbte
176             from builds
177             EOF
178 0 0       0 $req.="where $a" if ($a);
179 0         0 my $st = $self->{DBH}->prepare($req);
180 0 0       0 $st->execute || print STDERR $req,"
";
181 0         0 my %h;
182 0         0 while (my ($id,$os,$osver,$archi,$cc,$ccver,$date,$smoke,$nbc,$nbco,
183             $nbcm,$nbcf,$nbcc,$nbte)=
184             $st->fetchrow_array) {
185 0         0 $os=lc($os);
186 0         0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{date}=$date;
187 0         0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{id} = $id;
188 0         0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{nbc} = $nbc;
189 0         0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{nbco} = $nbco;
190 0         0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{nbcf} = $nbcf;
191 0         0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{nbcc} = $nbcc;
192 0         0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{nbcm} = $nbcm;
193 0         0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{nbte} = $nbte;
194 0         0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{nbtt} =
195             $nbcf + $nbcm + $nbco + $nbcc;
196             # $failure
197 0 0       0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{failure} =
198             $failure{$id} if ($failure{$id});
199             # build
200 0 0       0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{build} = $h2{$id}
201             if $h2{$id};
202             # matrix
203 0 0       0 $h{$os}{$osver}{$archi}{$cc}{$ccver}{$smoke}{matrix} = $matrix{$id}
204             if $matrix{$id};
205             }
206 0         0 $st->finish;
207 0         0 return \%h;
208             }
209              
210              
211             #------------------------------------------------------------------------------
212             # read_smokers
213             #------------------------------------------------------------------------------
214             sub read_smokers(\%) {
215 0     0 0 0 my $self = shift;
216 0         0 my %smokers;
217 0         0 my $req =" select distinct author from builds where date > DATE_SUB(NOW(), INTERVAL 6 MONTH)";
218 0   0     0 my $ref = $self->{DBH}->selectcol_arrayref($req) || return undef;
219 0         0 foreach (@$ref) {
220 0         0 $req = "select distinct os,osver,archi,cc,ccver, count(*) from builds where author='$_' ".
221             " and date > DATE_SUB(NOW(), INTERVAL 6 MONTH) group by 1,2,3,4,5 order by 1,2,3,4,5";
222 0   0     0 $smokers{$_} = $self->{DBH}->selectall_arrayref($req) || return undef;
223             }
224 0         0 return \%smokers;
225             }
226              
227             #------------------------------------------------------------------------------
228             # read_top_smokers
229             #------------------------------------------------------------------------------
230             sub read_top_smokers{
231 0     0 0 0 my $self = shift;
232 0   0     0 my $lim = shift || 20;
233 0         0 my $req = "select distinct author,count(*) from builds where date ".
234             "group by 1 order by 2 desc limit $lim";
235 0   0     0 return $self->{DBH}->selectall_arrayref($req) || undef;
236             }
237              
238             #------------------------------------------------------------------------------
239             # distinct
240             #------------------------------------------------------------------------------
241             sub distinct(\%$) {
242 0     0 0 0 my ($self, $col)=@_;
243 0         0 my $req = "select distinct $col from builds where smoke>=$limit
244             order by $col";
245 0   0     0 return $self->{DBH}->selectcol_arrayref($req) || undef;
246             }
247              
248             #------------------------------------------------------------------------------
249             # nb
250             #------------------------------------------------------------------------------
251             sub nb(\%) {
252 1     1 0 4 my $self = shift;
253 1         3 my $req = "select count(*) from builds";
254 1 50       5 $req .=" where smoke >= $limit" if $limit;
255 1         20 return $self->one_shot($req);
256             }
257              
258             #------------------------------------------------------------------------------
259             # last50
260             #------------------------------------------------------------------------------
261             sub last50(\%) {
262 0     0 0 0 my $self = shift;
263 0         0 my $req = 'select max(smoke)-50 from builds';
264 0         0 return $self->one_shot($req);
265             }
266              
267             #------------------------------------------------------------------------------
268             # one_shot
269             #------------------------------------------------------------------------------
270             sub one_shot(\%$) {
271 1     1 0 3 my ($self, $req) = @_;
272 1 50       11 return if (!$self->{DBH});
273 0   0       my $row_ary = $self->{DBH}->selectrow_arrayref($req) || return undef;
274 0 0         print STDERR $req,"\n", Data::Dumper->Dump([$row_ary]) if $debug;
275 0   0       return $row_ary->[0] || undef;
276             }
277              
278             #------------------------------------------------------------------------------
279             # add_to_db
280             #------------------------------------------------------------------------------
281             sub add_to_db(\%\%) {
282 0     0 0   my ($self, $ref)=@_;
283 0 0 0       return if (!ref($ref) || ref($ref) ne 'HASH' || !$ref->{os});
      0        
284 0           my ($nbco, $nbcf, $nbcm, $nbcc)=(0,0,0,0);
285 0   0       my ($cc,$ccf,$f,$r) = ($ref->{cc}||' ',$ref->{ccver} || ' ',
      0        
286             $ref->{failure},$ref->{report});
287 0 0         foreach ($cc,$ccf,$f,$r) { if ($_) { s/'/\\'/g; s/^\s*//g; }}
  0            
  0            
  0            
288             # Count make test ok / build fail in make / configure fail / make test fail
289 0           foreach my $c (keys %{$$ref{build}}) {
  0            
290 0           foreach (split(/ /,$$ref{build}{$c})) {
291 0 0         if ($_ eq 'O') { $nbco++; }
  0 0          
    0          
    0          
292 0           elsif ($_ eq 'F') { $nbcf++; }
293 0           elsif ($_ eq 'm') { $nbcm++; }
294 0           elsif ($_ eq 'c') { $nbcc++; }
295             }
296             }
297 0 0 0       my $pass = (($nbcf || $nbcm || $nbcc) ? 0 : 1);
298 0 0         printf( "\t =>%25s %s %5s (%s) %s\n",
    0          
299             $ref->{os}." ".$ref->{osver}, ($pass ? "PASS" : "FAIL"),
300             $ref->{version}, basename($ref->{file}), $ref->{date}) if $verbose;
301             # Ajout des infos sur le host
302 0 0         my $v2 = ($ref->{matrix} ? join("|", @{$ref->{matrix}}) : '');
  0            
303 0           my $req = "INSERT INTO builds(";
304 0 0         $req.= 'id,' if ($ref->{id});
305 0           $req.= "os,osver,cc,ccver,date,smoke,version,author,nbc,nbco,nbcf,nbcm,nbcc,nbte,archi) ".
306             "VALUES (";
307 0 0         $req.= "$ref->{id}," if ($ref->{id});
308 0           $req.= <
309             '$ref->{os}',
310             '$ref->{osver}',
311             '$cc',
312             '$ccf',
313             EOF
314 0 0         $req.= ($ref->{date} ? "'$ref->{date}'" : 'NOW()');
315 0           $req.= <
316             ,$ref->{smoke},
317             '$ref->{version}','
318             EOF
319 0 0         $req.= ($ref->{author} ? $ref->{author} : 'anonymous');
320 0           $req.= <
321             ',$ref->{nbc},
322             $nbco,
323             $nbcf,
324             $nbcm,
325             $nbcc,
326             $ref->{nbte},
327             '$ref->{archi}')
328             EOF
329              
330 0 0         print STDERR $req if $debug;
331 0           my $st = $self->{DBH}->prepare($req);
332 0 0         if (!$st->execute) {
333 0           print STDERR "SQL: $req\n", Data::Dumper->Dump([$ref]);
334 0           cluck($DBI::errstr);
335 0           return;
336             }
337             # id du test
338 0           my $id = $st->{'mysql_insertid'};
339 0           $ref->{id}=$id;
340 0 0         print STDERR Data::Dumper->Dump([$ref]) if $debug;
341              
342             # Ajout des details des erreurs
343 0 0         $r = ' ' if (!$r);
344 0 0         $f = ' ' if (!$f);
345 0           $req = <
346             INSERT INTO data(idbuild,failure,matrix)
347             VALUES ($id, '$f','$v2')
348             EOF
349 0 0         $self->rundb($req,1) || print STDERR "On $req\n";
350              
351             # Ajout des options du configure
352 0           foreach my $config (keys %{$$ref{build}}) {
  0            
353 0           my $co = $config; $co=~s/'/\\'/g;
  0            
354 0           my $v = $$ref{build}{$config};
355 0           $v=~s/'/\\'/g;
356 0           $req = <
357             INSERT INTO configure (idbuild,configure,result)
358             VALUES ($id,'$co','$v')
359             EOF
360             # print $req,"\n";
361 0 0         $self->rundb($req,1) or print STDERR "On $req\n";
362             }
363 0 0         return ($DBI::errstr ? 0 : 1);
364             }
365              
366             __END__