File Coverage

blib/lib/Test/EOF.pm
Criterion Covered Total %
statement 74 100 74.0
branch 26 54 48.1
condition 4 11 36.3
subroutine 15 16 93.7
pod 1 2 50.0
total 120 183 65.5


line stmt bran cond sub pod time code
1 1     1   592576 use 5.10.1;
  1         2  
  1         44  
2 1     1   4 use strict;
  1         2  
  1         29  
3 1     1   4 use warnings;
  1         5  
  1         48  
4              
5             package Test::EOF;
6              
7             our $VERSION = '0.0802'; # VERSION
8             # ABSTRACT: Check correct end of files in a project.
9              
10 1     1   4 use Cwd qw/cwd/;
  1         1  
  1         49  
11 1     1   5 use File::Find;
  1         2  
  1         56  
12 1     1   481 use File::ReadBackwards;
  1         2110  
  1         37  
13 1     1   8 use Test::Builder;
  1         1  
  1         67  
14              
15             my $perlstart = qr/^#!.*perl/;
16             my $test = Test::Builder->new;
17              
18             sub import {
19 1     1   6 my $self = shift;
20 1         2 my $caller = caller;
21             {
22 1     1   5 no strict 'refs';
  1         1  
  1         919  
  1         1  
23 1         2 *{ $caller.'::all_perl_files_ok'} = \&all_perl_files_ok;
  1         5  
24             }
25 1         4 $test->exported_to($caller);
26 1         11 $test->plan(@_);
27             }
28              
29             sub all_perl_files_ok {
30 2 100   2 1 27 my $options = ref $_[0] eq 'HASH' ? shift : ref $_[-1] eq 'HASH' ? pop : {};
    50          
31 2         9 my @files = _all_perl_files(@_);
32              
33 2         13 $test->expected_tests;
34              
35             # no need to check then...
36 2 50 66     36 if(exists $options->{'minimum_newlines'} && $options->{'minimum_newlines'} <= 0) {
37 0         0 return 1;
38             }
39              
40 2         6 foreach my $file (@files) {
41 2         6 _check_perl_file($file, $options);
42             }
43             }
44              
45             sub _check_perl_file {
46 2     2   4 my $file = shift;
47 2         3 my $options = shift;
48              
49 2   100     13 $options->{'minimum_newlines'} ||= 1;
50 2 50 0     8 if(!exists $options->{'maximum_newlines'}) {
    0          
51 2         7 $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       8 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       16 my $reader = File::ReadBackwards->new($file) or return;
65              
66 2         175 my $linecount = 0;
67              
68             LINE:
69 2         11 while(my $line = $reader->readline) {
70 7 50       539 ++$linecount if $line =~ m{\v$};
71 7 100       54 next LINE if $line =~ m{^\v$};
72 2         4 last LINE;
73             }
74              
75 2 50       13 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         16 $test->ok(1, "Just the right number of line breaks at the end of $file");
86 2         910 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         3 my @found;
99              
100             my $wants = sub {
101 4 50   4   19 return if $File::Find::dir =~ m{ [\\/]? (?:CVS|\.svn) [\\/] }x;
102 4 50       10 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       16 return if $File::Find::name =~ m{ Build $ }xi;
105 4 100       251 return unless -f -r $File::Find::name;
106 2         60 push @found => File::Spec->no_upwards($File::Find::name);
107 2         14 };
108 2         7 my $find_arg = {
109             wanted => $wants,
110             no_chdir => 1,
111             };
112              
113 2         209 find($find_arg, @base_dirs);
114              
115 2 50       4 my @perls = grep { _is_perl($_) || _is_perl($_) } @found;
  2         7  
116              
117 2         16 return @perls;
118             }
119              
120             sub _is_perl {
121 2     2   5 my $file = shift;
122              
123             # module
124 2 100       20 return 1 if $file =~ m{\.pm$}i;
125 1 50       5 return 1 if $file =~ m{::};
126              
127             # script
128 1 50       5 return 1 if $file =~ m{\.pl}i;
129 1 50       10 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   4 my $file = shift;
144 2 50       11 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__