File Coverage

blib/lib/Test/PureASCII.pm
Criterion Covered Total %
statement 97 150 64.6
branch 41 100 41.0
condition 7 24 29.1
subroutine 12 15 80.0
pod 3 7 42.8
total 160 296 54.0


line stmt bran cond sub pod time code
1             package Test::PureASCII;
2              
3             our $VERSION = '0.02';
4              
5 1     1   31928 use strict;
  1         3  
  1         54  
6 1     1   8 use warnings;
  1         2  
  1         38  
7              
8 1     1   3829 use Test::Builder;
  1         33292  
  1         36  
9 1     1   10 use File::Spec;
  1         3  
  1         80  
10              
11             my $test = Test::Builder->new;
12              
13             our @TESTED;
14              
15             sub import {
16 1     1   7 my $self = shift;
17 1         3 my $caller = caller;
18              
19 1         3 for my $func ( qw( file_is_pure_ascii all_perl_files_are_pure_ascii all_files_are_pure_ascii) ) {
20 1     1   5 no strict 'refs';
  1         2  
  1         1960  
21 3         7 *{$caller."::".$func} = \&$func;
  3         13  
22             }
23              
24 1         5 $test->exported_to($caller);
25 1         11 $test->plan(@_);
26             }
27              
28             sub _skip_file_p {
29 1     1   2 my %opts;
30 1 50       4 %opts = %{shift @_} if ref $_[0] eq 'HASH';
  1         5  
31 1 50       7 if (defined(my $skip = $opts{skip})) {
32 0         0 my $file = shift;
33 0 0       0 for my $s (ref $skip eq 'ARRAY' ? @$skip : $skip) {
34 0 0       0 if (ref $s eq 'Regexp') {
35 0 0       0 return 1 if $file =~ $s;
36             }
37             else {
38 0 0       0 return 1 if $file eq $s;
39             }
40             }
41             }
42 1         5 return 0;
43             }
44              
45             sub _make_error {
46 0     0   0 my ($bad, $error, $ln, $file) = @_;
47 0         0 my @chars = map sprintf("0x%02x", ord $_), split //, $bad;
48 0         0 my $chars = join(', ', @chars);
49 0 0       0 my $s = @chars > 1 ? ' sequence' : '';
50 0         0 ' ' . sprintf($error, $s, $chars) . " at line $ln in $file";
51             }
52              
53             sub file_is_pure_ascii {
54 1     1 1 3 my %opts;
55 1 50       6 %opts = %{shift @_} if ref $_[0] eq 'HASH';
  1         4  
56 1         2 my $skip_data = $opts{skip_data};
57 1         2 my $forbid_control = $opts{forbid_control};
58 1         2 my $forbid_cr = $opts{forbid_cr};
59 1         2 my $forbid_tab = $opts{forbid_tab};
60 1         2 my $require_crlf = $opts{require_crlf};
61              
62 1         2 my $file = shift;
63              
64 1 50       4 _skip_file_p(\%opts, $file) and return 1;
65              
66 1 50       5 my $name = @_ ? shift : "Pure ASCII test for $file";
67              
68 1         2 push @TESTED, $file;
69             # $test->diag("FILE: $file");
70              
71 1         2 my $fh;
72 1 50       40 unless (open $fh, '<', $file) {
73 0         0 $test->ok(0, $name);
74 0         0 $test->diag(" unable to open '$file': $!");
75 0         0 return 0;
76             }
77 1         8 binmode $fh, ':bytes';
78              
79 1         2 my $failed = 0;
80 1         29 while (<$fh>) {
81             # $test->diag("line $.: $_");
82 365 100       641 next if /\bpa_test_ignore\b/;
83 364 100       572 last if /\bpa_test_end\b/;
84 363 50       648 if (my ($lines) = /pa_test_skip_lines\(\d+\)/) {
85 0         0 <$fh> for 1..$lines;
86 0         0 next;
87             }
88              
89 363         328 my @errors;
90 363 50       860 /([^\x00-\x7f]+)/ and
91             push @errors, _make_error($1, "non ASCII character%s %s",
92             $., $file);
93 363 50 33     654 $forbid_control and /([\x00-\x08\x0b-\x1F])/ and
94             push @errors, _make_error($1, "forbidden control character%s %s",
95             $., $file);
96 363 50 33     659 $forbid_tab and /([\x09])/ and
97             push @errors, _make_error($1, "forbidden tab character%s %s",
98             $., $file);
99 363 50 33     652 $forbid_cr and /([\x0d])/ and
100             push @errors, _make_error($1, "forbidden CR character%s %s",
101             $., $file);
102 363 50 33     653 $require_crlf and /(\x0d(?!\x0a)|(?
103             push @errors, _make_error($a, "forbidden end of line character%s %s",
104             $., $file);
105              
106 363 50       603 if (@errors) {
107 0 0       0 $test->ok(0, $name) unless $failed;
108 0         0 $test->diag($_) for @errors;
109 0         0 $failed = 1;
110             }
111              
112 363 50 33     1203 last if ($skip_data and /^__DATA__$/);
113             }
114 1 50       25 unless (close $fh) {
115 0 0       0 $test->ok(0, $name) unless $failed;
116 0         0 $test->diag(" unable to read from '$file': $!");
117 0         0 return 0;
118             }
119 1 50       13 $failed ? 0 : $test->ok(1, $name);
120             }
121              
122             sub all_perl_files_are_pure_ascii {
123 1     1 1 7 my %opts;
124 1 50       5 %opts = %{shift @_} if ref $_[0] eq 'HASH';
  0         0  
125              
126 1         5 my @files = all_perl_files(\%opts, @_);
127              
128 1         10 $test->plan( tests => scalar @files );
129              
130 1         166 my $ok = 1;
131 1         4 foreach my $file (@files) {
132 1 50       5 file_is_pure_ascii(\%opts, $file) or undef $ok;
133             }
134 1         529 return $ok;
135             }
136              
137             sub all_files_are_pure_ascii {
138 0     0 1 0 my %opts;
139 0 0       0 %opts = %{shift @_} if ref $_[0] eq 'HASH';
  0         0  
140              
141 0         0 my @files = all_files(\%opts, @_);
142 0         0 $test->plan( tests => scalar @files );
143              
144 0         0 my $ok = 1;
145 0         0 foreach my $file (@files) {
146 0 0       0 file_is_pure_ascii(\%opts, $file) or undef $ok;
147             }
148 0         0 return $ok;
149             }
150              
151             sub all_perl_files {
152 1     1 0 2 my %opts;
153 1 50       5 %opts = %{shift @_} if ref $_[0] eq 'HASH';
  1         4  
154              
155 1 50       8 my @queue = @_ ? @_ : starting_points();
156 1         3 my @perl = ();
157              
158 1         5 while ( @queue ) {
159 23         38 my $file = shift @queue;
160 23 100       297 if ( -d $file ) {
161 14 50       305 opendir my $dh, $file or next;
162 14         161 my @newfiles = readdir $dh;
163 14         120 closedir $dh;
164              
165 14         170 @newfiles = File::Spec->no_upwards( @newfiles );
166 14 50 33     24 @newfiles = grep { $_ ne "CVS" and $_ ne ".svn" and !/~$/ } @newfiles;
  22         158  
167              
168 14         24 foreach my $newfile (@newfiles) {
169 22         182 my $filename = File::Spec->catfile( $file, $newfile );
170 22 100       336 if ( -f $filename ) {
171 9         41 push @queue, $filename;
172             }
173             else {
174 13         87 push @queue, File::Spec->catdir( $file, $newfile );
175             }
176             }
177             }
178 23 100       315 if ( -f $file ) {
179 9 100       18 push @perl, $file if is_perl( $file );
180             }
181             }
182 1         4 return @perl;
183             }
184              
185             sub all_files {
186 0     0 0 0 my %opts;
187 0 0       0 %opts = %{shift @_} if ref $_[0] eq 'HASH';
  0         0  
188              
189 0 0       0 my @queue = @_ ? @_ : '.';
190 0         0 my @all = ();
191              
192 0         0 while ( @queue ) {
193 0         0 my $file = shift @queue;
194 0 0       0 if ( -d $file ) {
195 0 0       0 opendir my $dh, $file or next;
196 0         0 my @newfiles = readdir $dh;
197 0         0 closedir $dh;
198              
199 0         0 @newfiles = File::Spec->no_upwards( @newfiles );
200 0 0 0     0 @newfiles = grep { $_ ne "CVS" and $_ ne ".svn" and !/~$/ } @newfiles;
  0         0  
201              
202 0         0 foreach my $newfile (@newfiles) {
203 0         0 my $filename = File::Spec->catfile( $file, $newfile );
204 0 0       0 if ( -f $filename ) {
205 0         0 push @queue, $filename;
206             }
207             else {
208 0         0 push @queue, File::Spec->catdir( $file, $newfile );
209             }
210             }
211             }
212 0 0       0 push @all, $file if -f $file
213             }
214 0         0 return @all;
215             }
216              
217             sub starting_points {
218 1 50   1 0 25 return 'blib' if -e 'blib';
219 0         0 return 'lib';
220             }
221              
222             sub is_perl {
223 9     9 0 14 my $file = shift;
224              
225 9 50       23 return 1 if $file =~ /\.PL$/;
226 9 100       29 return 1 if $file =~ /\.p(l|m|od)$/;
227 8 50       18 return 1 if $file =~ /\.t$/;
228              
229 8 50       256 open my $fh, $file or return;
230 8         134 my $first = <$fh>;
231 8         72 close $fh;
232              
233 8 50 33     38 return 1 if defined $first && ($first =~ /^#!.*perl/);
234              
235 8         42 return;
236             }
237              
238              
239             1;
240              
241             __END__