File Coverage

blib/lib/Test/EOF.pm
Criterion Covered Total %
statement 73 99 73.7
branch 26 54 48.1
condition 4 11 36.3
subroutine 15 16 93.7
pod 1 2 50.0
total 119 182 65.3


line stmt bran cond sub pod time code
1 1     1   21130 use 5.10.1;
  1         4  
2 1     1   6 use strict;
  1         1  
  1         26  
3 1     1   5 use warnings;
  1         1  
  1         55  
4              
5             package Test::EOF;
6              
7             our $VERSION = '0.0803'; # VERSION
8             # ABSTRACT: Check correct end of files in a project.
9              
10 1     1   5 use Cwd qw/cwd/;
  1         2  
  1         55  
11 1     1   5 use File::Find;
  1         2  
  1         70  
12 1     1   798 use File::ReadBackwards;
  1         2846  
  1         29  
13 1     1   6 use Test::Builder;
  1         2  
  1         68  
14              
15             my $perlstart = qr/^#!.*perl/;
16             my $test = Test::Builder->new;
17              
18             sub import {
19 1     1   7 my $self = shift;
20 1         3 my $caller = caller;
21             {
22 1     1   5 no strict 'refs';
  1         1  
  1         1131  
  1         2  
23 1         2 *{ $caller.'::all_perl_files_ok'} = \&all_perl_files_ok;
  1         5  
24             }
25 1         6 $test->exported_to($caller);
26 1         9 $test->plan(@_);
27             }
28              
29             sub all_perl_files_ok {
30 2 100   2 1 22 my $options = ref $_[0] eq 'HASH' ? shift : ref $_[-1] eq 'HASH' ? pop : {};
    50          
31 2         7 my @files = _all_perl_files(@_);
32              
33 2         13 $test->expected_tests;
34              
35             # no need to check then...
36 2 50 66     27 if(exists $options->{'minimum_newlines'} && $options->{'minimum_newlines'} <= 0) {
37 0         0 return 1;
38             }
39              
40 2         4 foreach my $file (@files) {
41 2         5 _check_perl_file($file, $options);
42             }
43             }
44              
45             sub _check_perl_file {
46 2     2   3 my $file = shift;
47 2         20 my $options = shift;
48              
49 2   100     12 $options->{'minimum_newlines'} ||= 1;
50 2 50 0     5 if(!exists $options->{'maximum_newlines'}) {
    0          
51 2         6 $options->{'maximum_newlines'} = $options->{'minimum_newlines'} + 3;
52             }
53             elsif(exists $options->{'maximum_newlines'} && $options->{'maximum_newlines'} < $options->{'minimum_newlines'}) {
54 0         0 $options->{'maximum_newlines'} = $options->{'minimum_newlines'};
55             }
56              
57 2 50       6 if($options->{'strict'}) {
58 0         0 $options->{'minimum_newlines'} = 1;
59 0         0 $options->{'maximum_newlines'} = 1;
60             }
61              
62 2         6 $file = _module_to_path($file);
63              
64 2 50       14 my $reader = File::ReadBackwards->new($file) or return;
65              
66 2         132 my $linecount = 0;
67              
68             LINE:
69 2         11 while(my $line = $reader->readline) {
70 7 50       387 ++$linecount if $line =~ m{\v$};
71 7 100       32 next LINE if $line =~ m{^\v$};
72 2         5 last LINE;
73             }
74              
75 2 50       10 if($linecount < $options->{'minimum_newlines'}) {
    50          
76 0         0 my $wanted = make_wanted($options);
77 0         0 $test->ok(0, "Not enough line breaks (had $linecount, wanted $wanted) at the end of $file");
78 0         0 return 0;
79             }
80             elsif($linecount > $options->{'maximum_newlines'}) {
81 0         0 my $wanted = make_wanted($options);
82 0         0 $test->ok(0, "Too many line breaks (had $linecount, wanted $wanted) at the end of $file ");
83 0         0 return 0;
84             }
85 2         12 $test->ok(1, "Just the right number of line breaks at the end of $file");
86 2         635 return 1;
87              
88             }
89              
90             sub make_wanted {
91 0     0 0 0 my $options = shift;
92 0 0       0 return $options->{'minimum_newlines'} if $options->{'minimum_newlines'} == $options->{'maximum_newlines'};
93 0         0 return sprintf "%d to %d" => $options->{'minimum_newlines'}, $options->{'maximum_newlines'};
94             }
95              
96             sub _all_perl_files {
97 2 50   2   9 my @base_dirs = @_ ? @_ : cwd();
98 2         4 my @found;
99              
100             my $wants = sub {
101 4 50   4   18 return if $File::Find::dir =~ m{ [\\/]? (?:CVS|\.svn) [\\/] }x;
102 4 50       9 return if $File::Find::dir =~ m{ [\\/]? blib [\\/] (?: libdoc | man\d) $ }x;
103 4 50       13 return if $File::Find::dir =~ m{ [\\/]? inc }x;
104 4 50       13 return if $File::Find::name =~ m{ Build $ }xi;
105 4 100       279 return unless -f -r $File::Find::name;
106 2         44 push @found => File::Spec->no_upwards($File::Find::name);
107 2         9 };
108 2         7 my $find_arg = {
109             wanted => $wants,
110             no_chdir => 1,
111             };
112              
113 2         183 find($find_arg, @base_dirs);
114              
115 2 50       5 my @perls = grep { _is_perl($_) || _is_perl($_) } @found;
  2         5  
116              
117 2         15 return @perls;
118             }
119              
120             sub _is_perl {
121 2     2   3 my $file = shift;
122              
123             # module
124 2 100       12 return 1 if $file =~ m{\.pm$}i;
125 1 50       4 return 1 if $file =~ m{::};
126              
127             # script
128 1 50       8 return 1 if $file =~ m{\.pl}i;
129 1 50       8 return 1 if $file =~ m{\.t$};
130              
131 0 0       0 open my $fh, '<', $file or return;
132 0         0 my $first = <$fh>;
133 0 0 0     0 if(defined $first && $first =~ $perlstart) {
134 0         0 close $fh;
135 0         0 return 1;
136             }
137              
138             # nope
139 0         0 return;
140             }
141              
142             sub _module_to_path {
143 2     2   3 my $file = shift;
144 2 50       7 return $file unless $file =~ m{::};
145 0           my @parts = split /::/ => $file;
146 0           my $module = File::Spec->catfile(@parts) . '.pm';
147              
148             CANDIDATE:
149 0           foreach my $dir (@INC) {
150 0           my $candidate = File::Spec->catfile($dir, $module);
151 0 0         next CANDIDATE if !-e -f -r $candidate;
152 0           return $candidate;
153             }
154 0           return $file;
155             }
156              
157             1;
158              
159             __END__