File Coverage

blib/lib/Test/MinimumVersion.pm
Criterion Covered Total %
statement 72 91 79.1
branch 10 24 41.6
condition 9 30 30.0
subroutine 15 20 75.0
pod 6 6 100.0
total 112 171 65.5


line stmt bran cond sub pod time code
1 1     1   61840 use v5.8;
  1         12  
2 1     1   5 use strict;
  1         1  
  1         28  
3 1     1   5 use warnings;
  1         1  
  1         53  
4             package Test::MinimumVersion;
5             $Test::MinimumVersion::VERSION = '0.101083';
6             # ABSTRACT: does your code require newer perl than you think?
7 1     1   6 use base 'Exporter';
  1         1  
  1         130  
8              
9             #pod =head1 SYNOPSIS
10             #pod
11             #pod Example F:
12             #pod
13             #pod #!perl
14             #pod use Test::MinimumVersion;
15             #pod all_minimum_version_ok('5.008');
16             #pod
17             #pod =cut
18              
19 1     1   414 use CPAN::Meta;
  1         28387  
  1         34  
20 1     1   491 use File::Find::Rule;
  1         6908  
  1         6  
21 1     1   433 use File::Find::Rule::Perl;
  1         6965  
  1         8  
22 1     1   509 use Perl::MinimumVersion 1.32; # numerous bugfies
  1         218950  
  1         57  
23 1     1   8 use version 0.70;
  1         13  
  1         7  
24              
25 1     1   79 use Test::Builder;
  1         2  
  1         726  
26             @Test::MinimumVersion::EXPORT = qw(
27             minimum_version_ok
28             all_minimum_version_ok
29             all_minimum_version_from_metayml_ok
30             all_minimum_version_from_metajson_ok
31             all_minimum_version_from_mymetayml_ok
32             all_minimum_version_from_mymetajson_ok
33             );
34              
35             sub import {
36 1     1   9 my($self) = shift;
37 1         3 my $pack = caller;
38              
39 1         5 my $Test = Test::Builder->new;
40              
41 1         13 $Test->exported_to($pack);
42 1         40 $Test->plan(@_);
43              
44 1         2074 $self->export_to_level(1, $self, @Test::MinimumVersion::EXPORT);
45             }
46              
47             sub _objectify_version {
48 4     4   8 my ($version) = @_;
49 4 100       9 $version = eval { $version->isa('version') }
  4         43  
50             ? $version
51             : version->new($version);
52             }
53              
54             #pod =func minimum_version_ok
55             #pod
56             #pod minimum_version_ok($file, $version);
57             #pod
58             #pod This test passes if the given file does not seem to require any version of perl
59             #pod newer than C<$version>, which may be given as a version string or a version
60             #pod object.
61             #pod
62             #pod =cut
63              
64             sub minimum_version_ok {
65 3     3 1 798 my ($file, $version) = @_;
66              
67 3         16 my $Test = Test::Builder->new;
68              
69 3         22 $version = _objectify_version($version);
70              
71 3         20 my $pmv = Perl::MinimumVersion->new($file);
72              
73 3 50       8926 unless (defined $pmv) {
74 0         0 $Test->ok(0, $file);
75 0         0 $Test->diag(
76             "$file could not be parsed: " . PPI::Document->errstr
77             );
78 0         0 return;
79             }
80              
81 3   50     13 my $explicit_minimum = $pmv->minimum_explicit_version || 0;
82 3   50     1105 my $minimum = $pmv->minimum_syntax_version($explicit_minimum) || 0;
83              
84 3 50 33     31033 my $is_syntax = 1
85             if $minimum and $minimum > $explicit_minimum;
86              
87 3 50 33     17 $minimum = $explicit_minimum
88             if $explicit_minimum and $explicit_minimum > $minimum;
89              
90 3         12 my %min = $pmv->version_markers;
91              
92 3 50       35367 if ($minimum <= $version) {
93 3         32 $Test->ok(1, $file);
94             } else {
95 0         0 $Test->ok(0, $file);
96 0 0       0 $Test->diag(
97             "$file requires $minimum "
98             . ($is_syntax ? 'due to syntax' : 'due to explicit requirement')
99             );
100              
101 0 0 0     0 if ($is_syntax and my $markers = $min{ $minimum }) {
102 0         0 $Test->diag("version markers for $minimum:");
103 0         0 $Test->diag("- $_ ") for @$markers;
104             }
105             }
106             }
107              
108             #pod =func all_minimum_version_ok
109             #pod
110             #pod all_minimum_version_ok($version, \%arg);
111             #pod
112             #pod Given either a version string or a L object, this routine produces a
113             #pod test plan (if there is no plan) and tests each relevant file with
114             #pod C.
115             #pod
116             #pod Relevant files are found by L.
117             #pod
118             #pod C<\%arg> is optional. Valid arguments are:
119             #pod
120             #pod paths - in what paths to look for files; defaults to (bin, script, t, lib,
121             #pod xt/smoke, and any .pm or .PL files in the current working
122             #pod directory) if it contains files, they will be checked
123             #pod no_plan - do not plan the tests about to be run
124             #pod skip - files to skip; this can be useful in weird cases like gigantic
125             #pod files, files falsely detected as Perl, or code that uses
126             #pod a source filter; this should be an arrayref of filenames
127             #pod
128             #pod =cut
129              
130             sub all_minimum_version_ok {
131 1     1 1 2648 my ($version, $arg) = @_;
132 1   50     4 $arg ||= {};
133             $arg->{paths} ||= [
134 1   50     135 qw(bin script lib t xt/smoke),
135             glob("*.pm"),
136             glob("*.PL"),
137             ];
138              
139 1   50     5 $arg->{skip} ||= [];
140              
141 1         6 my $Test = Test::Builder->new;
142              
143 1         6 $version = _objectify_version($version);
144              
145 1         3 my @perl_files;
146 1         2 for my $path (@{ $arg->{paths} }) {
  1         3  
147 5 50 33     1732 if (-f $path and -s $path) {
    100          
148 0         0 push @perl_files, $path;
149             } elsif (-d $path) {
150 1         12 push @perl_files, File::Find::Rule->perl_file->in($path);
151             }
152             }
153              
154 1         4 my %skip = map {; $_ => 1 } @{ $arg->{skip} };
  1         6  
  1         4  
155 1         3 @perl_files = grep {; ! $skip{$_} } @perl_files;
  2         6  
156              
157 1 50 33     10 unless ($Test->has_plan or $arg->{no_plan}) {
158 1         148 $Test->plan(tests => scalar @perl_files);
159             }
160              
161 1         499 minimum_version_ok($_, $version) for @perl_files;
162             }
163              
164             #pod =func all_minimum_version_from_metayml_ok
165             #pod
166             #pod all_minimum_version_from_metayml_ok(\%arg);
167             #pod
168             #pod This routine checks F for an entry in F for F. If no
169             #pod META.yml file or no perl version is found, all tests are skipped. If a version
170             #pod is found, the test proceeds as if C had been called
171             #pod with that version.
172             #pod
173             #pod =cut
174              
175             sub __version_from_meta {
176 2     2   4981 my ($fn) = @_;
177              
178 2         16 my $meta = CPAN::Meta->load_file($fn, { lazy_validation => 1 })->as_struct;
179 2         47823 my $version = $meta->{prereqs}{runtime}{requires}{perl};
180             }
181              
182             sub __from_meta {
183 0     0     my ($fn, $arg) = @_;
184 0   0       $arg ||= {};
185              
186 0           my $Test = Test::Builder->new;
187              
188 0 0 0       $Test->plan(skip_all => "$fn could not be found")
189             unless -f $fn and -r _;
190              
191 0 0         $Test->plan(skip_all => "no minimum perl version could be determined")
192             unless my $version = __version_from_meta($fn);
193              
194 0           all_minimum_version_ok($version, $arg);
195             }
196              
197             sub all_minimum_version_from_metayml_ok {
198 0     0 1   __from_meta('META.yml', @_);
199             }
200              
201             #pod =func all_minimum_version_from_metajson_ok
202             #pod
203             #pod all_minimum_version_from_metajson_ok(\%arg);
204             #pod
205             #pod This routine checks F for an entry in F for F. If
206             #pod no META.json file or no perl version is found, all tests are skipped. If a
207             #pod version is found, the test proceeds as if C had been
208             #pod called with that version.
209             #pod
210             #pod =cut
211              
212 0     0 1   sub all_minimum_version_from_metajson_ok { __from_meta('META.json', @_); }
213              
214             #pod =func all_minimum_version_from_mymetayml_ok
215             #pod
216             #pod all_minimum_version_from_mymetayml_ok(\%arg);
217             #pod
218             #pod This routine checks F for an entry in F for F. If
219             #pod no MYMETA.yml file or no perl version is found, all tests are skipped. If a
220             #pod version is found, the test proceeds as if C had been
221             #pod called with that version.
222             #pod
223             #pod =cut
224              
225 0     0 1   sub all_minimum_version_from_mymetayml_ok { __from_meta('MYMETA.yml', @_); }
226              
227             #pod =func all_minimum_version_from_mymetajson_ok
228             #pod
229             #pod all_minimum_version_from_mymetajson_ok(\%arg);
230             #pod
231             #pod This routine checks F for an entry in F for F. If
232             #pod no MYMETA.json file or no perl version is found, all tests are skipped. If a
233             #pod version is found, the test proceeds as if C had been
234             #pod called with that version.
235             #pod
236             #pod =cut
237              
238 0     0 1   sub all_minimum_version_from_mymetajson_ok { __from_meta('MYMETA.json', @_); }
239              
240             1;
241              
242             __END__