File Coverage

blib/lib/Test/EOL.pm
Criterion Covered Total %
statement 78 119 65.5
branch 25 54 46.3
condition 19 40 47.5
subroutine 16 21 76.1
pod 2 2 100.0
total 140 236 59.3


line stmt bran cond sub pod time code
1             package Test::EOL; # git description: v2.01-2-g00e2666
2             # ABSTRACT: Check the correct line endings in your project
3              
4 3     3   93713 use strict;
  3         28  
  3         86  
5 3     3   19 use warnings;
  3         6  
  3         117  
6              
7             our $VERSION = '2.02';
8              
9 3     3   1364 use Test::Builder;
  3         121963  
  3         93  
10 3     3   22 use File::Spec;
  3         7  
  3         76  
11 3     3   16 use File::Find;
  3         6  
  3         236  
12 3     3   20 use Cwd qw/ cwd /;
  3         6  
  3         812  
13              
14             our $PERL = $^X || 'perl';
15             our $UNTAINT_PATTERN = qr|^([-+@\w./:\\]+)$|;
16             our $PERL_PATTERN = qr/^#!.*perl/;
17              
18             my %file_find_arg = ($] <= 5.006) ? () : (
19             untaint => 1,
20             untaint_pattern => $UNTAINT_PATTERN,
21             untaint_skip => 1,
22             );
23              
24             my $Test = Test::Builder->new;
25              
26             my $no_plan;
27              
28             sub import {
29 3     3   25 my $self = shift;
30 3         6 my $caller = caller;
31             {
32 3     3   25 no strict 'refs';
  3         6  
  3         4881  
  3         6  
33 3         5 *{$caller.'::eol_unix_ok'} = \&eol_unix_ok;
  3         17  
34 3         7 *{$caller.'::all_perl_files_ok'} = \&all_perl_files_ok;
  3         13  
35             }
36 3         15 $Test->exported_to($caller);
37              
38 3 50 33     37 if ($_[0] && $_[0] eq 'no_plan') {
39 0         0 shift;
40 0         0 $no_plan = 1;
41             }
42 3         16 $Test->plan(@_);
43             }
44              
45             sub _all_perl_files {
46 2     2   27 my @all_files = _all_files(@_);
47 2 50 33     6 return grep { _is_perl_module($_) || _is_perl_script($_) || _is_pod_file($_) } @all_files;
  2         8  
48             }
49              
50             sub _all_files {
51 3 50   3   2535 my @base_dirs = @_ ? @_ : cwd();
52 3 100       20 my $options = pop(@base_dirs) if ref $base_dirs[-1] eq 'HASH';
53 3         15 my @found;
54             my $want_sub = sub {
55 27     27   248 my @chunks = ('', File::Spec->splitdir($File::Find::name));
56              
57 27 100 100     611 return $File::Find::prune = 1 if -d $File::Find::name and
      100        
58             ( $chunks[-1] eq 'CVS' # cvs
59             or $chunks[-1] eq '.svn' # subversion
60             or ($chunks[-2] eq 'blib' and $chunks[-1] eq 'libdoc') # pod doc
61             or ($chunks[-2] eq 'blib' and $chunks[-1] =~ /^man[0-9]$/) # pod doc
62             or $chunks[-1] eq 'inc'); # Module::Install
63              
64 22 100       201 return if $chunks[-1] eq 'Build'; # autogenerated Build script
65 21 100 66     1260 return unless (-f $File::Find::name && -r _);
66              
67 9         23 shift @chunks;
68 9         299 push @found, File::Spec->catfile(@chunks);
69 3         38 };
70 3         55 my $find_arg = {
71             %file_find_arg,
72             wanted => $want_sub,
73             no_chdir => 1,
74             };
75 3         530 find( $find_arg, @base_dirs);
76 3         90 return File::Spec->no_upwards(@found);
77             }
78              
79             # Formats various human invisible symbols
80             # to similar visible ones.
81             # Perhaps ^M or something like that
82             # would be more appropriate?
83              
84             sub _show_whitespace {
85 0     0   0 my $string = shift;
86 0         0 $string =~ s/\r/[\\r]/g;
87 0         0 $string =~ s/\t/[\\t]/g;
88 0         0 $string =~ s/ /[\\s]/g;
89 0         0 return $string;
90             }
91              
92             # Format a line record for diagnostics.
93              
94             sub _debug_line {
95 0     0   0 my ( $options, $line ) = @_;
96 0         0 $line->[2] =~ s/\n\z//g;
97             return "line $line->[1]: $line->[0]" . (
98 0 0       0 $options->{show_lines} ? qq{: } . _show_whitespace( $line->[2] ) : q{}
99             );
100             }
101              
102             sub eol_unix_ok {
103 7     7 1 1898 my $file = shift;
104 7         10 my $test_txt;
105 7 100       24 $test_txt = shift if !ref $_[0];
106 7   66     47 $test_txt ||= "No incorrect line endings in '$file'";
107 7 100       21 my $options = shift if ref $_[0] eq 'HASH';
108 7   100     27 $options ||= {
109             trailing_whitespace => 0,
110             all_reasons => 0,
111             };
112 7         19 $file = _module_to_path($file);
113              
114 7 50       253 open my $fh, $file or do { $Test->ok(0, $test_txt); $Test->diag("Could not open $file: $!"); return; };
  0         0  
  0         0  
  0         0  
115             # Windows-- , default is :crlf, which hides \r\n -_-
116 7         54 binmode( $fh, ':raw' );
117 7         13 my $line = 0;
118 7         13 my @fails;
119 7         103 while (<$fh>) {
120 963         1080 $line++;
121 963 50 66     2455 if ( !$options->{trailing_whitespace} && /(\r+)$/ ) {
122 0         0 my $match = $1;
123 0         0 push @fails, [ _show_whitespace( $match ) , $line , $_ ];
124             }
125 963 50 66     1617 if ( $options->{trailing_whitespace} && /([ \t]*\r+|[ \t]+)$/ ) {
126 0         0 my $match = $1;
127 0         0 push @fails, [ _show_whitespace($match), $line , $_ ];
128             }
129             # Minor short-circuit for people who don't need the whole file scanned
130             # once there's an err.
131 963 50 33     2248 last if( @fails > 0 && !$options->{all_reasons} );
132             }
133 7 50       24 if( @fails ){
134 0         0 $Test->ok( 0, $test_txt . " on " . _debug_line({ show_lines => 0 } , $fails[0] ) );
135 0 0 0     0 if ( $options->{all_reasons} || 1 ){
136 0         0 $Test->diag( " Problem Lines: ");
137 0         0 for ( @fails ){
138 0         0 $Test->diag(_debug_line({ show_lines => 1 } , $_ ) );
139             }
140             }
141 0         0 return 0;
142             }
143 7         45 $Test->ok(1, $test_txt);
144 7         2807 return 1;
145             }
146             sub all_perl_files_ok {
147 2 50   2 1 3880 my $options = shift if ref $_[0] eq 'HASH';
148 2         38 my @files = _all_perl_files( @_ );
149 2         12 _make_plan();
150 2         283 foreach my $file ( @files ) {
151 2         8 eol_unix_ok($file, $options);
152             }
153             }
154              
155             sub _is_perl_module {
156 2 50   2   45 $_[0] =~ /\.pm$/i || $_[0] =~ /::/;
157             }
158              
159             sub _is_pod_file {
160 0     0   0 $_[0] =~ /\.pod$/i;
161             }
162              
163             sub _is_perl_script {
164 0     0   0 my $file = shift;
165 0 0       0 return 1 if $file =~ /\.pl$/i;
166 0 0       0 return 1 if $file =~ /\.t$/;
167 0 0       0 open (my $fh, $file) or return;
168 0         0 my $first = <$fh>;
169 0 0 0     0 return 1 if defined $first && ($first =~ $PERL_PATTERN);
170 0         0 return;
171             }
172              
173             sub _module_to_path {
174 7     7   12 my $file = shift;
175 7 50       27 return $file unless ($file =~ /::/);
176 0         0 my @parts = split /::/, $file;
177 0         0 my $module = File::Spec->catfile(@parts) . '.pm';
178 0         0 foreach my $dir (@INC) {
179 0         0 my $candidate = File::Spec->catfile($dir, $module);
180 0 0 0     0 next unless (-e $candidate && -f _ && -r _);
      0        
181 0         0 return $candidate;
182             }
183 0         0 return $file;
184             }
185              
186             sub _make_plan {
187 2 50   2   12 return if $no_plan;
188 2 50       29 unless ($Test->has_plan) {
189 2         832 $Test->plan( 'no_plan' );
190             }
191 2         606 $Test->expected_tests;
192             }
193              
194             sub _untaint {
195 0     0     my @untainted = map { ($_ =~ $UNTAINT_PATTERN) } @_;
  0            
196 0 0         return wantarray ? @untainted : $untainted[0];
197             }
198              
199             1;
200              
201             __END__