File Coverage

blib/lib/CPAN/Mini/Tested.pm
Criterion Covered Total %
statement 92 116 79.3
branch 26 50 52.0
condition 9 35 25.7
subroutine 20 23 86.9
pod 3 3 100.0
total 150 227 66.0


line stmt bran cond sub pod time code
1             package CPAN::Mini::Tested;
2              
3 6     6   209863 use 5.006;
  6         23  
  6         271  
4 6     6   32 use strict;
  6         10  
  6         208  
5 6     6   30 use warnings;
  6         154  
  6         1502  
6              
7             our $VERSION = '0.23';
8              
9             #--------------------------------------------------------------------------
10              
11             ###########################################################################
12             # Inheritence
13              
14 6     6   37 use base 'CPAN::Mini';
  6         13  
  6         26343  
15              
16             ###########################################################################
17             # Modules
18              
19 6     6   1356506 use Cache::Simple::TimedExpiry 0.22;
  6         4683  
  6         180  
20 6     6   113 use Config;
  6         12  
  6         221  
21 6     6   27261 use DBI;
  6         151482  
  6         500  
22 6     6   8788 use DBD::SQLite 1.00;
  6         70242  
  6         227  
23 6     6   55 use File::Basename qw( basename );
  6         15  
  6         509  
24 6     6   6055 use File::Spec::Functions qw( catfile );
  6         6965  
  6         506  
25 6     6   5634 use LWP::Simple qw( mirror RC_OK RC_NOT_MODIFIED );
  6         167843  
  6         69  
26 6     6   10903 use Regexp::Assemble 0.06;
  6         129022  
  6         9364  
27              
28             ###########################################################################
29             # Variables
30              
31             my $TESTDB = 'cpanstats.db';
32             my $TESTURL = 'http://devel.cpantesters.org/cpanstats.db';
33              
34             #--------------------------------------------------------------------------
35              
36             ###########################################################################
37             # Public Interface
38              
39             sub file_allowed {
40 0     0 1 0 my ($self, $file) = @_;
41 0 0       0 return (basename($file) eq $TESTDB) ? 1 :
42             CPAN::Mini::file_allowed($self, $file);
43             }
44              
45             sub mirror_indices {
46 0     0 1 0 my $self = shift;
47              
48 0 0       0 warn "test_db_arch is deprecated" if(defined $self->{test_db_arch});
49              
50 0   0     0 $self->{test_db_file} ||= catfile($self->{local}, $TESTDB);
51 0         0 my $local_file = $self->{test_db_file};
52              
53             # test_db_age < 0, do not update it
54              
55 0         0 my $test_db_age = $self->{test_db_age};
56 0 0       0 $test_db_age = 1, unless (defined $test_db_age);
57              
58 0 0 0     0 if ( $self->{force}
      0        
      0        
      0        
59             || !-e $local_file
60             || ( $test_db_age >= 0
61             && -e $local_file
62             && -M $local_file > $test_db_age) ) {
63              
64 0         0 $self->trace($TESTDB);
65 0   0     0 my $db_src = $self->{test_db_src} || $TESTURL;
66 0         0 my $status = mirror($db_src, $local_file);
67              
68 0 0       0 if ($status == RC_OK) {
    0          
69 0         0 $self->trace(" ... updated\n");
70             } elsif ($status == RC_NOT_MODIFIED) {
71 0         0 $self->trace(" ... up to date\n");
72             } else {
73 0         0 warn "\n$db_src: $status\n";
74 0         0 return;
75             }
76             }
77              
78 0 0       0 $self->_connect() if (-r $local_file);
79              
80 0         0 return CPAN::Mini::mirror_indices($self);
81             }
82              
83             sub clean_unmirrored {
84 0     0 1 0 my $self = shift;
85 0         0 $self->_disconnect();
86 0         0 return CPAN::Mini::clean_unmirrored($self);
87             }
88              
89             ###########################################################################
90             # Private Methods
91              
92             sub _dbh {
93 3     3   8 my $self = shift;
94 3         350 return $self->{test_db};
95             }
96              
97             sub _sth {
98 18     18   21 my $self = shift;
99 18         70 return $self->{test_db_sth};
100             }
101              
102             sub _connect {
103 1     1   25 my ($self, $database) = @_;
104              
105 1   33     15 $database ||= $self->{test_db_file};
106 1 50       60 die "Cannot find database file" unless (-r $database);
107              
108 1 50       21 $self->{test_db} = DBI->connect(
109             "DBI:SQLite:dbname=".$database, "", "", {
110             RaiseError => 1,
111 1 50       6 %{$self->{test_db_conn} || { }},
112             },
113             ) or die "Unable to connect: ", $DBI::errstr;
114              
115             # TODO: support for additional reports fields such as perl version
116              
117 1 50       1997 $self->{test_db_sth} =
118             $self->_dbh->prepare( qq{
119             SELECT COUNT(id)
120             FROM cpanstats
121             WHERE status='PASS'
122             AND dist=?
123             AND version=?
124             AND osname=?
125             }) or die "Unable to create prepare statement: ", $self->_dbh->errstr;
126              
127 1         625 return 1;
128             }
129              
130             sub _disconnect {
131 1     1   5 my $self = shift;
132 1 50       6 if ($self->_dbh) {
133 1 50       8 $self->_sth->finish if ($self->_sth);
134 1         4 $self->_dbh->disconnect;
135             }
136 1         8 return 1;
137             }
138              
139             sub _check_db {
140 16     16   30 my ($self, $dist, $ver, $osname) = @_;
141              
142 16         34 my $sth = $self->_sth;
143 16 50       36 die "Not connected to the database\n" unless ($sth);
144              
145 16         1690 $sth->execute($dist, $ver, $osname);
146 16         229 my $row = $sth->fetch;
147              
148 16 50       129 return $row->[0] if($row);
149 0         0 return 0;
150             }
151              
152             sub _reset_cache {
153 6     6   2352 my $self = shift;
154 6 100       26 $self->{test_db_cache} = undef, if ($self->{test_db_cache});
155 6         55 $self->{test_db_cache} = Cache::Simple::TimedExpiry->new;
156 6   50     76 $self->{test_db_cache}->expire_after($self->{test_db_cache_expiry} || 300);
157             }
158              
159             sub _passed {
160 29     29   1830 my ($self, $path) = @_;
161              
162             # CPAN::Mini 0.36 no longer calls the filter routine multiple times
163             # per module, but it will for packages with multiple modules. So we
164             # cache the results, but only for a limited time.
165              
166 29 100       92 $self->_reset_cache unless (defined $self->{test_db_cache});
167              
168 29 100       75 if ($self->{test_db_exceptions}) {
169              
170 5 100       16 if (ref($self->{test_db_exceptions}) eq "CODE") {
171 1 50       2 return 1, if ( &{ $self->{test_db_exceptions} }($path) );
  1         5  
172             } else {
173 4         34 my $re = new Regexp::Assemble;
174              
175 4 100 33     304 if (ref($self->{test_db_exceptions}) eq "ARRAY") {
    50          
176 2         3 $re->add( @{ $self->{test_db_exceptions} } );
  2         9  
177             } elsif ( (!ref($self->{test_db_exceptions})) || (ref($self->{test_db_exceptions}) eq "Regexp") ) {
178 2         10 $re->add( $self->{test_db_exceptions} );
179             } else {
180 0         0 die "Unknown test_db_exception type: ", ref($self->{test_db_exceptions});
181             }
182              
183 4 100       792 return 1, if ($path =~ $re->re);
184             }
185             }
186              
187 25 100       260 return $self->{test_db_cache}->fetch($path) if ($self->{test_db_cache}->has_key($path));
188              
189 12         152 my $count = 0;
190              
191 12         435 my $distver = basename($path);
192 12         33 $distver =~ s/\.(tar\.gz|tar\.bz2|zip)$//;
193              
194 12         23 my $x = rindex($distver, '-');
195 12         21 my $dist = substr($distver, 0, $x);
196 12         21 my $ver = substr($distver, $x+1);
197              
198 12   33     36 $self->{test_db_os} ||= $Config{osname};
199              
200 12 100       32 if (ref($self->{test_db_os}) eq 'ARRAY') {
201 6         9 my @archs = @{ $self->{test_db_os} };
  6         17  
202 6   100     40 while ( (!$count) && (my $arch = shift @archs) ) {
203 10         26 $count += $self->_check_db($dist, $ver, $arch);
204             }
205             } else {
206 6         22 $count += $self->_check_db($dist, $ver, $self->{test_db_os});
207             }
208              
209 12         48 $self->{test_db_cache}->set($path, $count);
210              
211 12         215 return $count;
212             }
213              
214             # TODO: if filtering in CPAN::Mini is changed to allow paths to be
215             # munged, then we can add the option to fall back to the latest
216             # version which passes tests.
217              
218             sub _filter_module {
219 12     12   2849 my ($self, $args) = @_;
220 12   66     39 return CPAN::Mini::_filter_module($self, $args)
221             || (!$self->_passed($args->{path}));
222             }
223              
224             1;
225              
226             __END__