File Coverage

blib/lib/Test/Apocalypse/Dependencies.pm
Criterion Covered Total %
statement 32 95 33.6
branch 0 32 0.0
condition 0 12 0.0
subroutine 12 13 92.3
pod 0 1 0.0
total 44 153 28.7


line stmt bran cond sub pod time code
1             #
2             # This file is part of Test-Apocalypse
3             #
4             # This software is copyright (c) 2014 by Apocalypse.
5             #
6             # This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #
9 39     39   2249171 use strict; use warnings;
  39     39   82  
  39         1945  
  39         272  
  39         80  
  39         2491  
10             package Test::Apocalypse::Dependencies;
11             $Test::Apocalypse::Dependencies::VERSION = '1.003';
12             BEGIN {
13 39     39   545 $Test::Apocalypse::Dependencies::AUTHORITY = 'cpan:APOCAL';
14             }
15              
16             # ABSTRACT: Plugin to check for metadata dependencies
17              
18 39     39   156 use Test::More;
  39         178  
  39         303  
19 39     39   32104 use File::Slurp 9999.13;
  39         329738  
  39         2729  
20 39     39   18108 use YAML::Any 0.72;
  39         39116  
  39         195  
21 39     39   127385 use JSON::Any 1.25;
  39         685777  
  39         196  
22 39     39   90686 use File::Find::Rule 0.32;
  39         7797  
  39         233  
23 39     39   19279 use Perl::PrereqScanner 1.000;
  39         17642735  
  39         390  
24 39     39   26147 use Test::Deep 0.108;
  39         244508  
  39         6637  
25 39     39   276 use CPAN::Meta::Requirements 2.113640;
  39         669  
  39         235  
26              
27 38     38   152 sub _do_automated { 0 }
28              
29             sub do_test {
30             # load the metadata
31 0     0 0   my $runtime_req;
32             my $test_req;
33 0           my $provides;
34 0 0         if ( -e 'META.json' ) {
    0          
35 0           my $file = read_file( 'META.json' );
36 0           my $metadata = JSON::Any->new->Load( $file );
37 0           $runtime_req = $metadata->{'prereqs'}{'runtime'}{'requires'};
38 0           $test_req = $metadata->{'prereqs'}{'test'}{'requires'};
39 0 0         $provides = $metadata->{'provides'} if exists $metadata->{'provides'};
40             } elsif ( -e 'META.yml' ) {
41 0           my $file = read_file( 'META.yml' );
42 0           my $metadata = Load( $file );
43 0           $runtime_req = $metadata->{'requires'};
44 0 0         $provides = $metadata->{'provides'} if exists $metadata->{'provides'};
45             } else {
46 0           die 'No META.(json|yml) found!';
47             }
48              
49             # Okay, scan the files
50 0           my $found_runtime = CPAN::Meta::Requirements->new;
51 0           my $found_test = CPAN::Meta::Requirements->new;
52 0           foreach my $file ( File::Find::Rule->file()->name( qr/\.pm$/ )->in( 'lib' ) ) {
53 0           $found_runtime->add_requirements( Perl::PrereqScanner->new->scan_file( $file ) );
54             }
55              
56             # scan the test dir only if we have test metadata
57 0 0         if ( defined $test_req ) {
58 0           foreach my $file ( File::Find::Rule->file()->name( qr/\.(pm|t|pl)$/ )->in( 't' ) ) {
59 0           $found_test->add_requirements( Perl::PrereqScanner->new->scan_file( $file ) );
60             }
61             }
62              
63             # Okay, the spec says that anything already in the runtime req shouldn't be listed in test req
64             # That means we need to "fake" the prereq and make sure the comparison is OK
65 0 0         if ( defined $test_req ) {
66 0           my %temp = %{ $found_test->as_string_hash };
  0            
67 0           foreach my $mod ( keys %temp ) {
68 0 0 0       if ( ! exists $test_req->{ $mod } and exists $runtime_req->{ $mod } ) {
69             # don't copy runtime_req's version because it might be different and cmp_deeply will complain!
70 0           $test_req->{ $mod } = $temp{ $mod };
71             }
72             }
73             }
74              
75             # We remove any prereqs that we provided in the package
76 0 0         if ( defined $provides ) {
77 0           foreach my $p ( keys %$provides ) {
78 0           $found_runtime->clear_requirement( $p );
79 0           $found_test->clear_requirement( $p );
80             }
81             }
82              
83             # Thanks to PoCo::SmokeBox::Uploads::Rsync's use of PoCo::Generic, we have to do this
84             # Mangle the found version to the required one if it was 0
85             {
86 0           my %temp = %{ $found_runtime->as_string_hash };
  0            
  0            
87 0           foreach my $p ( keys %temp ) {
88 0 0 0       if ( $runtime_req->{ $p } ne '0' and $temp{ $p } eq '0' ) {
89 0           $found_runtime->clear_requirement( $p );
90 0           $found_runtime->add_minimum( $p => $runtime_req->{ $p } );
91             }
92             }
93             }
94              
95             # Do the same for the test stuff
96 0 0         if ( defined $test_req ) {
97 0           my %temp = %{ $found_test->as_string_hash };
  0            
98 0           foreach my $p ( keys %temp ) {
99 0 0 0       if ( $test_req->{ $p } ne '0' and $temp{ $p } eq '0' ) {
100 0           $found_test->clear_requirement( $p );
101 0           $found_test->add_minimum( $p => $runtime_req->{ $p } );
102             }
103             }
104             }
105              
106             # remove 'perl' dep - we check it in MinimumVersion anyway
107 0 0         delete $runtime_req->{'perl'} if exists $runtime_req->{'perl'};
108 0 0 0       delete $test_req->{'perl'} if defined $test_req and exists $test_req->{'perl'};
109 0           $found_runtime->clear_requirement( 'perl' );
110 0           $found_test->clear_requirement( 'perl' );
111              
112             # Convert version objects to regular or we'll get something like this:
113             # Compared $data->{"Test\:\:NoPlan"}
114             # got : 'v0.0.6'
115             # expect : '0.0.6'
116 0           $found_runtime = $found_runtime->as_string_hash;
117 0           $found_runtime->{ $_ } =~ s/^v// for keys %$found_runtime;
118 0           $runtime_req->{ $_ } =~ s/^v// for keys %$runtime_req;
119              
120             # Do the actual comparison!
121 0 0         if ( defined $test_req ) {
122 0           plan tests => 2;
123              
124 0           $found_test = $found_test->as_string_hash;
125 0           $found_test->{ $_ } =~ s/^v// for keys %$found_test;
126 0           $test_req->{ $_ } =~ s/^v// for keys %$test_req;
127              
128             # TODO interesting, somewhere deep in the build chain it auto-upgraded Test::More version...
129             # I had 0.88 set but somehow 0.96 was in the META.yml argh!
130 0 0         if ( $found_test->{'Test::More'} ne $test_req->{'Test::More'} ) {
131 0           diag( 'Found weird Test::More version mismatch, ignoring it! (' . $found_test->{'Test::More'} . ' vs ' . $test_req->{'Test::More'} . ')' );
132 0           $found_test->{'Test::More'} = $test_req->{'Test::More'};
133             }
134             } else {
135 0           plan tests => 1;
136             }
137              
138 0           cmp_deeply( $found_runtime, $runtime_req, "Runtime requires" );
139 0 0         cmp_deeply( $found_test, $test_req, "Test requires" ) if defined $test_req;
140              
141 0           return;
142             }
143              
144             1;
145              
146             __END__
147              
148             =pod
149              
150             =encoding UTF-8
151              
152             =for :stopwords Apocalypse Niebur Ryan metadata
153              
154             =for Pod::Coverage do_test
155              
156             =head1 NAME
157              
158             Test::Apocalypse::Dependencies - Plugin to check for metadata dependencies
159              
160             =head1 VERSION
161              
162             This document describes v1.003 of Test::Apocalypse::Dependencies - released October 24, 2014 as part of Test-Apocalypse.
163              
164             =head1 DESCRIPTION
165              
166             Loads the metadata and uses L<Perl::PrereqScanner> to look for dependencies and compares the lists.
167              
168             =head1 SEE ALSO
169              
170             Please see those modules/websites for more information related to this module.
171              
172             =over 4
173              
174             =item *
175              
176             L<Test::Apocalypse|Test::Apocalypse>
177              
178             =back
179              
180             =head1 AUTHOR
181              
182             Apocalypse <APOCAL@cpan.org>
183              
184             =head1 COPYRIGHT AND LICENSE
185              
186             This software is copyright (c) 2014 by Apocalypse.
187              
188             This is free software; you can redistribute it and/or modify it under
189             the same terms as the Perl 5 programming language system itself.
190              
191             The full text of the license can be found in the
192             F<LICENSE> file included with this distribution.
193              
194             =head1 DISCLAIMER OF WARRANTY
195              
196             THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
197             APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
198             HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
199             OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
200             THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
201             PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
202             IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
203             ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
204              
205             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
206             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
207             THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
208             GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
209             USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
210             DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
211             PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
212             EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
213             SUCH DAMAGES.
214              
215             =cut