line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test::Strict; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Test::Strict - Check syntax, presence of use strict; and test coverage |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 VERSION |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Version 0.52 |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 SYNOPSIS |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
C lets you check the syntax, presence of C |
14
|
|
|
|
|
|
|
and presence C |
15
|
|
|
|
|
|
|
It report its results in standard L fashion: |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
use Test::Strict tests => 3; |
18
|
|
|
|
|
|
|
syntax_ok( 'bin/myscript.pl' ); |
19
|
|
|
|
|
|
|
strict_ok( 'My::Module', "use strict; in My::Module" ); |
20
|
|
|
|
|
|
|
warnings_ok( 'lib/My/Module.pm' ); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
Module authors can include the following in a t/strict.t |
23
|
|
|
|
|
|
|
and have C automatically find and check |
24
|
|
|
|
|
|
|
all perl files in a module distribution: |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
use Test::Strict; |
27
|
|
|
|
|
|
|
all_perl_files_ok(); # Syntax ok and use strict; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
or |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
use Test::Strict; |
32
|
|
|
|
|
|
|
all_perl_files_ok( @mydirs ); |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
C can also enforce a minimum test coverage |
35
|
|
|
|
|
|
|
the test suite should reach. |
36
|
|
|
|
|
|
|
Module authors can include the following in a t/cover.t |
37
|
|
|
|
|
|
|
and have C automatically check the test coverage: |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
use Test::Strict; |
40
|
|
|
|
|
|
|
all_cover_ok( 80 ); # at least 80% coverage |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
or |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
use Test::Strict; |
45
|
|
|
|
|
|
|
all_cover_ok( 80, 't/' ); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 DESCRIPTION |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
The most basic test one can write is "does it compile ?". |
50
|
|
|
|
|
|
|
This module tests if the code compiles and play nice with L modules. |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Another good practice this module can test is to "use strict;" in all perl files. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
By setting a minimum test coverage through C, a code author |
55
|
|
|
|
|
|
|
can ensure his code is tested above a preset level of I throughout the development cycle. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
Along with L, this module can provide the first tests to setup for a module author. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
This module should be able to run under the -T flag for perl >= 5.6. |
60
|
|
|
|
|
|
|
All paths are untainted with the following pattern: C |
61
|
|
|
|
|
|
|
controlled by C<$Test::Strict::UNTAINT_PATTERN>. |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=cut |
64
|
|
|
|
|
|
|
|
65
|
5
|
|
|
5
|
|
227660
|
use strict; use warnings; |
|
5
|
|
|
5
|
|
34
|
|
|
5
|
|
|
|
|
122
|
|
|
5
|
|
|
|
|
21
|
|
|
5
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
128
|
|
66
|
5
|
|
|
5
|
|
121
|
use 5.006; |
|
5
|
|
|
|
|
14
|
|
67
|
5
|
|
|
5
|
|
25
|
use Test::Builder; |
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
96
|
|
68
|
5
|
|
|
5
|
|
20
|
use File::Spec; |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
144
|
|
69
|
5
|
|
|
5
|
|
2016
|
use FindBin qw($Bin); |
|
5
|
|
|
|
|
4525
|
|
|
5
|
|
|
|
|
574
|
|
70
|
5
|
|
|
5
|
|
30
|
use File::Find; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
218
|
|
71
|
5
|
|
|
5
|
|
24
|
use Config; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
1204
|
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
our $COVER; |
74
|
|
|
|
|
|
|
our $VERSION = '0.52'; |
75
|
|
|
|
|
|
|
our $PERL = $^X || 'perl'; |
76
|
|
|
|
|
|
|
our $COVERAGE_THRESHOLD = 50; # 50% |
77
|
|
|
|
|
|
|
our $UNTAINT_PATTERN = qr|^(.*)$|; |
78
|
|
|
|
|
|
|
our $PERL_PATTERN = qr/^#!.*perl/; |
79
|
|
|
|
|
|
|
our $CAN_USE_WARNINGS = ($] >= 5.006); |
80
|
|
|
|
|
|
|
our $TEST_SYNTAX = 1; # Check compile |
81
|
|
|
|
|
|
|
our $TEST_STRICT = 1; # Check use strict; |
82
|
|
|
|
|
|
|
our $TEST_WARNINGS = 0; # Check use warnings; |
83
|
|
|
|
|
|
|
our $TEST_SKIP = []; # List of files to skip check |
84
|
|
|
|
|
|
|
our $DEVEL_COVER_OPTIONS = '+ignore,".Test.Strict\b"'; |
85
|
|
|
|
|
|
|
our $DEVEL_COVER_DB = 'cover_db'; |
86
|
|
|
|
|
|
|
my $IS_WINDOWS = $^O =~ /MSwin/i; |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
my $Test = Test::Builder->new; |
89
|
|
|
|
|
|
|
my $updir = File::Spec->updir(); |
90
|
|
|
|
|
|
|
my %file_find_arg = ($] <= 5.006) ? () |
91
|
|
|
|
|
|
|
: ( |
92
|
|
|
|
|
|
|
untaint => 1, |
93
|
|
|
|
|
|
|
untaint_pattern => $UNTAINT_PATTERN, |
94
|
|
|
|
|
|
|
untaint_skip => 1, |
95
|
|
|
|
|
|
|
); |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub import { |
98
|
4
|
|
|
4
|
|
28
|
my $self = shift; |
99
|
4
|
|
|
|
|
8
|
my $caller = caller; |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
{ |
102
|
5
|
|
|
5
|
|
62
|
no strict 'refs'; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
12706
|
|
|
4
|
|
|
|
|
5
|
|
103
|
4
|
|
|
|
|
9
|
*{$caller.'::strict_ok'} = \&strict_ok; |
|
4
|
|
|
|
|
18
|
|
104
|
4
|
|
|
|
|
8
|
*{$caller.'::warnings_ok'} = \&warnings_ok; |
|
4
|
|
|
|
|
11
|
|
105
|
4
|
|
|
|
|
6
|
*{$caller.'::syntax_ok'} = \&syntax_ok; |
|
4
|
|
|
|
|
11
|
|
106
|
4
|
|
|
|
|
7
|
*{$caller.'::all_perl_files_ok'} = \&all_perl_files_ok; |
|
4
|
|
|
|
|
11
|
|
107
|
4
|
|
|
|
|
7
|
*{$caller.'::all_cover_ok'} = \&all_cover_ok; |
|
4
|
|
|
|
|
9
|
|
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
4
|
|
|
|
|
16
|
$Test->exported_to($caller); |
111
|
4
|
|
|
|
|
37
|
$Test->plan(@_); |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
## |
115
|
|
|
|
|
|
|
## _all_perl_files( @dirs ) |
116
|
|
|
|
|
|
|
## Returns a list of perl files in @dir |
117
|
|
|
|
|
|
|
## if @dir is not provided, it searches from one dir level above |
118
|
|
|
|
|
|
|
## |
119
|
|
|
|
|
|
|
sub _all_perl_files { |
120
|
2
|
|
|
2
|
|
9
|
my @all_files = _all_files(@_); |
121
|
2
|
100
|
|
|
|
6
|
return grep { _is_perl_module($_) || _is_perl_script($_) } @all_files; |
|
42
|
|
|
|
|
80
|
|
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub _all_files { |
125
|
2
|
100
|
|
2
|
|
23
|
my @base_dirs = @_ ? @_ |
126
|
|
|
|
|
|
|
: File::Spec->catdir($Bin, $updir); |
127
|
2
|
|
|
|
|
4
|
my @found; |
128
|
|
|
|
|
|
|
my $want_sub = sub { |
129
|
|
|
|
|
|
|
#return if ($File::Find::dir =~ m![\\/]?CVS[\\/]|[\\/]?.svn[\\/]!); # Filter out cvs or subversion dirs/ |
130
|
|
|
|
|
|
|
#return if ($File::Find::dir =~ m![\\/]?blib[\\/]libdoc$!); # Filter out pod doc in dist |
131
|
|
|
|
|
|
|
#return if ($File::Find::dir =~ m![\\/]?blib[\\/]man\d$!); # Filter out pod doc in dist |
132
|
66
|
100
|
66
|
66
|
|
1307
|
if (-d $File::Find::name && |
|
|
|
100
|
|
|
|
|
133
|
|
|
|
|
|
|
($_ eq 'CVS' || $_ eq '.svn' || $_ eq '.git' || # Filter out cvs or git or subversion dirs |
134
|
|
|
|
|
|
|
$File::Find::name =~ m!(?:^|[\\/])blib[\\/]libdoc$! || # Filter out pod doc in dist |
135
|
|
|
|
|
|
|
$File::Find::name =~ m!(?:^|[\\/])blib[\\/]man\d$!) # Filter out pod doc in dist |
136
|
|
|
|
|
|
|
) { |
137
|
2
|
|
|
|
|
5
|
$File::Find::prune = 1; |
138
|
2
|
|
|
|
|
13
|
return; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
64
|
100
|
66
|
|
|
2241
|
return unless (-f $File::Find::name && -r _); |
142
|
43
|
50
|
|
|
|
114
|
return if ($File::Find::name =~ m!\.#.+?[\d\.]+$!); # Filter out CVS backup files (.#file.revision) |
143
|
43
|
|
|
|
|
665
|
push @found, File::Spec->canonpath( File::Spec->no_upwards( $File::Find::name ) ); |
144
|
2
|
|
|
|
|
16
|
}; |
145
|
|
|
|
|
|
|
|
146
|
2
|
|
|
|
|
24
|
my $find_arg = { |
147
|
|
|
|
|
|
|
%file_find_arg, |
148
|
|
|
|
|
|
|
wanted => $want_sub, |
149
|
|
|
|
|
|
|
no_chdir => 1, |
150
|
|
|
|
|
|
|
}; |
151
|
2
|
|
|
|
|
281
|
find( $find_arg, @base_dirs); # Find all potential file candidates |
152
|
|
|
|
|
|
|
|
153
|
2
|
|
50
|
|
|
7
|
my $files_to_skip = $TEST_SKIP || []; |
154
|
2
|
|
|
|
|
5
|
my %skip = map { $_ => undef } @$files_to_skip; |
|
1
|
|
|
|
|
5
|
|
155
|
2
|
|
|
|
|
5
|
return grep { ! exists $skip{$_} } @found; # Exclude files to skip |
|
43
|
|
|
|
|
70
|
|
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head1 FUNCTIONS |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head2 syntax_ok( $file [, $text] ) |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Run a syntax check on C<$file> by running C with an external perl interpreter. |
163
|
|
|
|
|
|
|
The external perl interpreter path is stored in C<$Test::Strict::PERL> which can be modified. |
164
|
|
|
|
|
|
|
You may prefer C from L to syntax test a module. |
165
|
|
|
|
|
|
|
For a module, the path (lib/My/Module.pm) or the name (My::Module) can be both used. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=cut |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub syntax_ok { |
170
|
20
|
|
|
20
|
1
|
76
|
my $file = shift; |
171
|
20
|
|
66
|
|
|
116
|
my $test_txt = shift || "Syntax check $file"; |
172
|
|
|
|
|
|
|
|
173
|
20
|
|
|
|
|
69
|
$file = _module_to_path($file); |
174
|
20
|
50
|
33
|
|
|
433
|
unless (-f $file && -r _) { |
175
|
0
|
|
|
|
|
0
|
$Test->ok( 0, $test_txt ); |
176
|
0
|
|
|
|
|
0
|
$Test->diag( "File $file not found or not readable" ); |
177
|
0
|
|
|
|
|
0
|
return; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
20
|
|
|
|
|
84
|
my $is_script = _is_perl_script($file); |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# Set the environment to compile the script or module |
183
|
20
|
|
|
|
|
321
|
require Config; |
184
|
20
|
|
50
|
|
|
867
|
my $inc = join($Config::Config{path_sep}, @INC) || ''; |
185
|
20
|
|
|
|
|
94
|
$file = _untaint($file); |
186
|
20
|
|
|
|
|
54
|
my $perl_bin = _untaint($PERL); |
187
|
20
|
50
|
|
|
|
126
|
local $ENV{PATH} = _untaint($ENV{PATH}) if $ENV{PATH}; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# Add the -t -T switches if they are set in the #! line |
190
|
20
|
|
|
|
|
36
|
my $switch = ''; |
191
|
20
|
100
|
100
|
|
|
84
|
$switch = _taint_switch($file) || '' if $is_script; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# Compile and check for errors |
194
|
20
|
|
|
|
|
34
|
my $eval = do { |
195
|
20
|
|
|
|
|
108
|
local $ENV{PERL5LIB} = $inc; |
196
|
20
|
|
|
|
|
1318307
|
`$perl_bin -c$switch \"$file\" 2>&1`; |
197
|
|
|
|
|
|
|
}; |
198
|
20
|
|
|
|
|
454
|
$file = quotemeta($file); |
199
|
20
|
|
|
|
|
2162
|
my $ok = $eval =~ qr!$file syntax OK!ms; |
200
|
20
|
|
|
|
|
686
|
$Test->ok($ok, $test_txt); |
201
|
20
|
50
|
|
|
|
30195
|
unless ($ok) { |
202
|
0
|
|
|
|
|
0
|
$Test->diag( $eval ); |
203
|
|
|
|
|
|
|
} |
204
|
20
|
|
|
|
|
440
|
return $ok; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=head2 strict_ok( $file [, $text] ) |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Check if C<$file> contains a C |
210
|
|
|
|
|
|
|
C |
211
|
|
|
|
|
|
|
use Modern::Perl is also accepted. |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
This is a pretty naive test which may be fooled in some edge cases. |
214
|
|
|
|
|
|
|
For a module, the path (lib/My/Module.pm) or the name (My::Module) can be both used. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=cut |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub strict_ok { |
219
|
26
|
|
|
26
|
1
|
7792
|
my $file = shift; |
220
|
26
|
|
66
|
|
|
310
|
my $test_txt = shift || "use strict $file"; |
221
|
26
|
|
|
|
|
268
|
$file = _module_to_path($file); |
222
|
26
|
50
|
|
|
|
1452
|
open my $fh, '<', $file or do { $Test->ok(0, $test_txt); $Test->diag("Could not open $file: $!"); return; }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
223
|
26
|
|
|
|
|
183
|
my $ok = _strict_ok($fh); |
224
|
26
|
|
|
|
|
134
|
$Test->ok($ok, $test_txt); |
225
|
26
|
|
|
|
|
7327
|
return $ok; |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub _module_rx { |
229
|
39
|
|
|
39
|
|
281
|
my (@module_names) = @_; |
230
|
39
|
|
|
|
|
1566
|
my $names = join '|', map quotemeta, reverse sort @module_names; |
231
|
|
|
|
|
|
|
# TODO: improve this matching (e.g. see TODO test) |
232
|
39
|
|
|
|
|
2867
|
return qr/\buse\s+(?:$names)(?:[;\s]|$)/; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub _strict_ok { |
236
|
28
|
|
|
28
|
|
456202
|
my ($in) = @_; |
237
|
28
|
|
|
|
|
103
|
my $strict_module_rx = _module_rx( modules_enabling_strict() ); |
238
|
28
|
|
|
|
|
87
|
local $_; |
239
|
28
|
|
|
|
|
46
|
my $pod; |
240
|
28
|
|
|
|
|
539
|
while (<$in>) { |
241
|
257
|
100
|
|
|
|
1304
|
next if (/^\s*#/); # Skip comments |
242
|
239
|
100
|
|
|
|
502
|
$pod = 0, next if /^=(cut|back|end)/; |
243
|
233
|
100
|
|
|
|
428
|
$pod = 1, next if /^=\S+/; |
244
|
218
|
100
|
|
|
|
365
|
next if $pod; # skip pod |
245
|
47
|
50
|
|
|
|
89
|
last if (/^\s*(__END__|__DATA__)/); # End of code |
246
|
47
|
100
|
|
|
|
560
|
return 1 if $_ =~ $strict_module_rx; |
247
|
23
|
100
|
100
|
|
|
106
|
if (/\buse\s+(5\.\d+)/ and $1 >= 5.012) { |
248
|
2
|
|
|
|
|
108
|
return 1; |
249
|
|
|
|
|
|
|
} |
250
|
21
|
100
|
66
|
|
|
91
|
if (/\buse\s+v5\.(\d+)/ and $1 >= 12) { |
251
|
1
|
|
|
|
|
9
|
return 1; |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
} |
254
|
1
|
|
|
|
|
18
|
return; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=head2 modules_enabling_strict |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
Experimental. Returning a list of modules and pragmata that enable strict. |
260
|
|
|
|
|
|
|
To modify this list, change C<@Test::Strict::MODULES_ENABLING_STRICT>. |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
List taken from L v95 |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=cut |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
our @MODULES_ENABLING_STRICT = qw( |
267
|
|
|
|
|
|
|
strict |
268
|
|
|
|
|
|
|
Any::Moose |
269
|
|
|
|
|
|
|
Catmandu::Sane |
270
|
|
|
|
|
|
|
Class::Spiffy |
271
|
|
|
|
|
|
|
Coat |
272
|
|
|
|
|
|
|
common::sense |
273
|
|
|
|
|
|
|
Dancer |
274
|
|
|
|
|
|
|
HTML::FormHandler::Moose |
275
|
|
|
|
|
|
|
HTML::FormHandler::Moose::Role |
276
|
|
|
|
|
|
|
Mo |
277
|
|
|
|
|
|
|
Modern::Perl |
278
|
|
|
|
|
|
|
Mojo::Base |
279
|
|
|
|
|
|
|
Moo |
280
|
|
|
|
|
|
|
Moo::Role |
281
|
|
|
|
|
|
|
MooX |
282
|
|
|
|
|
|
|
Moose |
283
|
|
|
|
|
|
|
Moose::Exporter |
284
|
|
|
|
|
|
|
Moose::Role |
285
|
|
|
|
|
|
|
MooseX::Declare |
286
|
|
|
|
|
|
|
MooseX::Role::Parameterized |
287
|
|
|
|
|
|
|
MooseX::Types |
288
|
|
|
|
|
|
|
Mouse |
289
|
|
|
|
|
|
|
Mouse::Role |
290
|
|
|
|
|
|
|
perl5 |
291
|
|
|
|
|
|
|
perl5i::1 |
292
|
|
|
|
|
|
|
perl5i::2 |
293
|
|
|
|
|
|
|
perl5i::latest |
294
|
|
|
|
|
|
|
Role::Tiny |
295
|
|
|
|
|
|
|
Spiffy |
296
|
|
|
|
|
|
|
strictures |
297
|
|
|
|
|
|
|
Test::Most |
298
|
|
|
|
|
|
|
Test::Roo |
299
|
|
|
|
|
|
|
Test::Roo::Role |
300
|
|
|
|
|
|
|
); |
301
|
|
|
|
|
|
|
|
302
|
28
|
|
|
28
|
1
|
760
|
sub modules_enabling_strict { return @MODULES_ENABLING_STRICT } |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=head2 modules_enabling_warnings |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
Experimental. Returning a list of modules and pragmata that enable warnings |
307
|
|
|
|
|
|
|
To modify this list, change C<@Test::Strict::MODULES_ENABLING_WARNINGS>. |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
List taken from L v95 |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=cut |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
our @MODULES_ENABLING_WARNINGS = qw( |
314
|
|
|
|
|
|
|
warnings |
315
|
|
|
|
|
|
|
Any::Moose |
316
|
|
|
|
|
|
|
Catmandu::Sane |
317
|
|
|
|
|
|
|
Class::Spiffy |
318
|
|
|
|
|
|
|
Coat |
319
|
|
|
|
|
|
|
common::sense |
320
|
|
|
|
|
|
|
Dancer |
321
|
|
|
|
|
|
|
HTML::FormHandler::Moose |
322
|
|
|
|
|
|
|
HTML::FormHandler::Moose::Role |
323
|
|
|
|
|
|
|
Mo |
324
|
|
|
|
|
|
|
Modern::Perl |
325
|
|
|
|
|
|
|
Mojo::Base |
326
|
|
|
|
|
|
|
Moo |
327
|
|
|
|
|
|
|
Moo::Role |
328
|
|
|
|
|
|
|
MooX |
329
|
|
|
|
|
|
|
Moose |
330
|
|
|
|
|
|
|
Moose::Exporter |
331
|
|
|
|
|
|
|
Moose::Role |
332
|
|
|
|
|
|
|
MooseX::Declare |
333
|
|
|
|
|
|
|
MooseX::Role::Parameterized |
334
|
|
|
|
|
|
|
MooseX::Types |
335
|
|
|
|
|
|
|
Mouse |
336
|
|
|
|
|
|
|
Mouse::Role |
337
|
|
|
|
|
|
|
perl5 |
338
|
|
|
|
|
|
|
perl5i::1 |
339
|
|
|
|
|
|
|
perl5i::2 |
340
|
|
|
|
|
|
|
perl5i::latest |
341
|
|
|
|
|
|
|
Role::Tiny |
342
|
|
|
|
|
|
|
Spiffy |
343
|
|
|
|
|
|
|
strictures |
344
|
|
|
|
|
|
|
Test::Most |
345
|
|
|
|
|
|
|
Test::Roo |
346
|
|
|
|
|
|
|
Test::Roo::Role |
347
|
|
|
|
|
|
|
); |
348
|
|
|
|
|
|
|
|
349
|
11
|
|
|
11
|
1
|
122
|
sub modules_enabling_warnings { return @MODULES_ENABLING_WARNINGS } |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head2 warnings_ok( $file [, $text] ) |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
Check if warnings have been turned on. |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
If C<$file> is a module, check if it contains a C or C |
356
|
|
|
|
|
|
|
or C or C statement. use Modern::Perl is also accepted. |
357
|
|
|
|
|
|
|
If the perl version is <= 5.6, this test is skipped (C appeared in perl 5.6). |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
If C<$file> is a script, check if it starts with C<#!...perl -w>. |
360
|
|
|
|
|
|
|
If the -w is not found and perl is >= 5.6, check for a C or C |
361
|
|
|
|
|
|
|
or C or C statement. use Modern::Perl is also accepted. |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
This is a pretty naive test which may be fooled in some edge cases. |
364
|
|
|
|
|
|
|
For a module, the path (lib/My/Module.pm) or the name (My::Module) can be both used. |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=cut |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub warnings_ok { |
369
|
11
|
|
|
11
|
1
|
4124
|
my $file = shift; |
370
|
11
|
|
66
|
|
|
128
|
my $test_txt = shift || "use warnings $file"; |
371
|
|
|
|
|
|
|
|
372
|
11
|
|
|
|
|
93
|
$file = _module_to_path($file); |
373
|
11
|
|
|
|
|
51
|
my $is_module = _is_perl_module( $file ); |
374
|
11
|
|
|
|
|
44
|
my $is_script = _is_perl_script( $file ); |
375
|
11
|
50
|
100
|
|
|
65
|
if (!$is_script and $is_module and ! $CAN_USE_WARNINGS) { |
|
|
|
66
|
|
|
|
|
376
|
0
|
|
|
|
|
0
|
$Test->skip(); |
377
|
0
|
|
|
|
|
0
|
$Test->diag("This version of perl ($]) does not have use warnings - perl 5.6 or higher is required"); |
378
|
0
|
|
|
|
|
0
|
return; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
11
|
50
|
|
|
|
356
|
open my $fh, '<', $file or do { $Test->ok(0, $test_txt); $Test->diag("Could not open $file: $!"); return; }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
382
|
11
|
|
|
|
|
113
|
my $ok = _warnings_ok($is_script, $fh); |
383
|
11
|
|
|
|
|
54
|
$Test->ok($ok, $test_txt); |
384
|
11
|
|
|
|
|
3154
|
return $ok |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
# TODO unite with _strict_ok |
388
|
|
|
|
|
|
|
sub _warnings_ok { |
389
|
11
|
|
|
11
|
|
48
|
my ($is_script, $in) = @_; |
390
|
11
|
|
|
|
|
25
|
my $warnings_module_rx = _module_rx( modules_enabling_warnings() ); |
391
|
11
|
|
|
|
|
48
|
local $_; |
392
|
11
|
|
|
|
|
168
|
while (<$in>) { |
393
|
13
|
100
|
100
|
|
|
215
|
if ($. == 1 and $is_script and $_ =~ $PERL_PATTERN) { |
|
|
|
100
|
|
|
|
|
394
|
6
|
100
|
|
|
|
35
|
if (/\s+-\w*[wW]/) { |
395
|
5
|
|
|
|
|
25
|
return 1; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
} |
398
|
8
|
50
|
|
|
|
15
|
last unless $CAN_USE_WARNINGS; |
399
|
8
|
100
|
|
|
|
22
|
next if (/^\s*#/); # Skip comments |
400
|
7
|
50
|
|
|
|
27
|
next if (/^\s*=.+/ .. /^\s*=(cut|back|end)/); # Skip pod |
401
|
7
|
50
|
|
|
|
14
|
last if (/^\s*(__END__|__DATA__)/); # End of code |
402
|
7
|
100
|
|
|
|
70
|
return 1 if $_ =~ $warnings_module_rx; |
403
|
|
|
|
|
|
|
} |
404
|
0
|
|
|
|
|
0
|
return; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
=head2 all_perl_files_ok( [ @directories ] ) |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
Applies C and C to all perl files found in C<@directories> (and sub directories). |
410
|
|
|
|
|
|
|
If no <@directories> is given, the starting point is one level above the current running script, |
411
|
|
|
|
|
|
|
that should cover all the files of a typical CPAN distribution. |
412
|
|
|
|
|
|
|
A perl file is *.pl or *.pm or *.t or a file starting with C<#!...perl> |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
If the test plan is defined: |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
use Test::Strict tests => 18; |
417
|
|
|
|
|
|
|
all_perl_files_ok(); |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
the total number of files tested must be specified. |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
You can control which tests are run on each perl site through: |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
$Test::Strict::TEST_SYNTAX (default = 1) |
424
|
|
|
|
|
|
|
$Test::Strict::TEST_STRICT (default = 1) |
425
|
|
|
|
|
|
|
$Test::Strict::TEST_WARNINGS (default = 0) |
426
|
|
|
|
|
|
|
$Test::Strict::TEST_SKIP (default = []) "Trusted" files to skip |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=cut |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
sub all_perl_files_ok { |
431
|
2
|
|
|
2
|
1
|
10796
|
my @files = _all_perl_files( @_ ); |
432
|
|
|
|
|
|
|
|
433
|
2
|
|
|
|
|
10
|
_make_plan(); |
434
|
2
|
|
|
|
|
198
|
foreach my $file ( @files ) { |
435
|
17
|
50
|
|
|
|
184
|
syntax_ok( $file ) if $TEST_SYNTAX; |
436
|
17
|
50
|
|
|
|
252
|
strict_ok( $file ) if $TEST_STRICT; |
437
|
17
|
100
|
|
|
|
163
|
warnings_ok( $file ) if $TEST_WARNINGS; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
=head2 all_cover_ok( [coverage_threshold [, @t_dirs]] ) |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
This will run all the tests in @t_dirs |
444
|
|
|
|
|
|
|
(or current script's directory if @t_dirs is undef) |
445
|
|
|
|
|
|
|
under L |
446
|
|
|
|
|
|
|
and calculate the global test coverage of the code loaded by the tests. |
447
|
|
|
|
|
|
|
If the test coverage is greater or equal than C, it is a pass, |
448
|
|
|
|
|
|
|
otherwise it's a fail. The default coverage threshold is 50 |
449
|
|
|
|
|
|
|
(meaning 50% of the code loaded has been covered by test). |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
The threshold can be modified through C<$Test::Strict::COVERAGE_THRESHOLD>. |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
You may want to select which files are selected for code |
454
|
|
|
|
|
|
|
coverage through C<$Test::Strict::DEVEL_COVER_OPTIONS>, |
455
|
|
|
|
|
|
|
see L for the list of available options. |
456
|
|
|
|
|
|
|
The default is '+ignore,"/Test/Strict\b"'. |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
The path to C utility can be modified through C<$Test::Strict::COVER>. |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
The 50% threshold is a completely arbitrary value, which should not be considered |
461
|
|
|
|
|
|
|
as a good enough coverage. |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
The total coverage is the return value of C. |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=cut |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
sub all_cover_ok { |
468
|
0
|
|
|
0
|
1
|
0
|
my $cover_bin = _cover_path(); |
469
|
0
|
0
|
|
|
|
0
|
die "ERROR: Cover binary not found, please install Devel::Cover.\n" |
470
|
|
|
|
|
|
|
unless (defined $cover_bin); |
471
|
|
|
|
|
|
|
|
472
|
0
|
|
0
|
|
|
0
|
my $threshold = shift || $COVERAGE_THRESHOLD; |
473
|
0
|
0
|
0
|
|
|
0
|
my @dirs = @_ ? @_ |
474
|
|
|
|
|
|
|
: (File::Spec->splitpath( $0 ))[1] || '.'; |
475
|
0
|
|
0
|
|
|
0
|
my @all_files = grep { ! /$0$/o && $0 !~ /$_$/ } |
476
|
0
|
|
|
|
|
0
|
grep { _is_perl_script($_) } |
|
0
|
|
|
|
|
0
|
|
477
|
|
|
|
|
|
|
_all_files(@dirs); |
478
|
0
|
|
|
|
|
0
|
_make_plan(); |
479
|
|
|
|
|
|
|
|
480
|
0
|
|
|
|
|
0
|
my $perl_bin = _untaint($PERL); |
481
|
0
|
0
|
|
|
|
0
|
local $ENV{PATH} = _untaint($ENV{PATH}) if $ENV{PATH}; |
482
|
0
|
0
|
0
|
|
|
0
|
if ($IS_WINDOWS and ! -d $DEVEL_COVER_DB) { |
483
|
0
|
0
|
|
|
|
0
|
mkdir $DEVEL_COVER_DB or warn "$DEVEL_COVER_DB: $!"; |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
|
486
|
0
|
|
|
|
|
0
|
my $res = `$cover_bin -delete 2>&1`; |
487
|
0
|
0
|
|
|
|
0
|
if ($?) { |
488
|
0
|
|
|
|
|
0
|
$Test->skip(); |
489
|
0
|
|
|
|
|
0
|
$Test->diag("Cover at $cover_bin got error $?: $res"); |
490
|
0
|
|
|
|
|
0
|
return; |
491
|
|
|
|
|
|
|
} |
492
|
0
|
|
|
|
|
0
|
foreach my $file ( @all_files ) { |
493
|
0
|
|
|
|
|
0
|
$file = _untaint($file); |
494
|
0
|
|
|
|
|
0
|
`$perl_bin -MDevel::Cover=$DEVEL_COVER_OPTIONS $file`; |
495
|
0
|
|
|
|
|
0
|
$Test->ok(! $?, "Coverage captured from $file" ); |
496
|
|
|
|
|
|
|
} |
497
|
0
|
|
|
|
|
0
|
$Test->ok(my $cover = `$cover_bin 2>&1`, "Got cover"); |
498
|
|
|
|
|
|
|
|
499
|
0
|
|
|
|
|
0
|
my ($total) = ($cover =~ /^\s*Total.+?([\d\.]+)\s*$/m); |
500
|
0
|
|
|
|
|
0
|
$Test->ok( $total >= $threshold, "coverage = ${total}% > ${threshold}%"); |
501
|
0
|
|
|
|
|
0
|
return $total; |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
sub _is_perl_module { |
505
|
56
|
100
|
|
56
|
|
269
|
return 0 if $_[0] =~ /\~$/; |
506
|
55
|
100
|
|
|
|
344
|
$_[0] =~ /\.pm$/i || $_[0] =~ /::/; |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
sub _is_perl_script { |
511
|
74
|
|
|
74
|
|
201
|
my $file = shift; |
512
|
|
|
|
|
|
|
|
513
|
74
|
100
|
|
|
|
276
|
return 0 if $file =~ /\~$/; |
514
|
73
|
100
|
|
|
|
292
|
return 1 if $file =~ /\.pl$/i; |
515
|
58
|
100
|
|
|
|
203
|
return 1 if $file =~ /\.t$/; |
516
|
34
|
50
|
|
|
|
925
|
open my $fh, '<', $file or return; |
517
|
34
|
|
|
|
|
434
|
my $first = <$fh>; |
518
|
34
|
50
|
66
|
|
|
263
|
return 1 if defined $first && ($first =~ $PERL_PATTERN); |
519
|
34
|
|
|
|
|
433
|
return; |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
## |
523
|
|
|
|
|
|
|
## Returns the taint switches -tT in the #! line of a perl script |
524
|
|
|
|
|
|
|
## |
525
|
|
|
|
|
|
|
sub _taint_switch { |
526
|
16
|
|
|
16
|
|
28
|
my $file = shift; |
527
|
|
|
|
|
|
|
|
528
|
16
|
50
|
|
|
|
503
|
open my $fh, '<', $file or return; |
529
|
16
|
|
|
|
|
210
|
my $first = <$fh>; |
530
|
16
|
100
|
|
|
|
335
|
$first =~ /^#!.*\bperl.*\s-\w*([Tt]+)/ or return; |
531
|
2
|
|
|
|
|
35
|
return $1; |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
## |
535
|
|
|
|
|
|
|
## Return the path of a module |
536
|
|
|
|
|
|
|
## |
537
|
|
|
|
|
|
|
sub _module_to_path { |
538
|
57
|
|
|
57
|
|
116
|
my $file = shift; |
539
|
|
|
|
|
|
|
|
540
|
57
|
|
|
|
|
215
|
my @parts = split /::/, $file; |
541
|
57
|
|
|
|
|
703
|
my $module = File::Spec->catfile(@parts) . '.pm'; |
542
|
57
|
|
|
|
|
306
|
foreach my $dir (@INC) { |
543
|
609
|
|
|
|
|
4161
|
my $candidate = File::Spec->catfile($dir, $module); |
544
|
609
|
50
|
66
|
|
|
6629
|
next unless (-e $candidate && -f _ && -r _); |
|
|
|
66
|
|
|
|
|
545
|
2
|
|
|
|
|
18
|
return $candidate; |
546
|
|
|
|
|
|
|
} |
547
|
55
|
|
|
|
|
199
|
return $file; # non existing file - error is catched elsewhere |
548
|
|
|
|
|
|
|
} |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
sub _cover_path { |
552
|
1
|
50
|
|
1
|
|
72
|
return $COVER if defined $COVER; |
553
|
|
|
|
|
|
|
|
554
|
1
|
50
|
|
|
|
5
|
my $os_separator = $IS_WINDOWS ? ';' : ':'; |
555
|
1
|
|
|
|
|
17
|
foreach ((split /$os_separator/, $ENV{PATH}), @Config{qw(bin sitedir scriptdir)} ) { |
556
|
12
|
|
100
|
|
|
140
|
my $path = $_ || '.'; |
557
|
12
|
|
|
|
|
79
|
my $path_cover = File::Spec->catfile($path, 'cover'); |
558
|
12
|
50
|
|
|
|
26
|
if ($IS_WINDOWS) { |
559
|
0
|
0
|
0
|
|
|
0
|
next unless (-f $path_cover && -r _); |
560
|
|
|
|
|
|
|
} |
561
|
|
|
|
|
|
|
else { |
562
|
12
|
50
|
|
|
|
169
|
next unless -x $path_cover; |
563
|
|
|
|
|
|
|
} |
564
|
0
|
|
|
|
|
0
|
return $COVER = _untaint($path_cover); |
565
|
|
|
|
|
|
|
} |
566
|
1
|
|
|
|
|
7
|
return; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
sub _make_plan { |
571
|
2
|
50
|
|
2
|
|
13
|
unless ($Test->has_plan) { |
572
|
0
|
|
|
|
|
0
|
$Test->plan( 'no_plan' ); |
573
|
|
|
|
|
|
|
} |
574
|
2
|
|
|
|
|
255
|
$Test->expected_tests; |
575
|
|
|
|
|
|
|
} |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
sub _untaint { |
578
|
60
|
|
|
60
|
|
109
|
my @untainted = map {($_ =~ $UNTAINT_PATTERN)} @_; |
|
60
|
|
|
|
|
494
|
|
579
|
|
|
|
|
|
|
wantarray ? @untainted |
580
|
60
|
50
|
|
|
|
351
|
: $untainted[0]; |
581
|
|
|
|
|
|
|
} |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
=head1 CAVEATS |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
For C to work properly, it is strongly advised to install the most recent version of L |
586
|
|
|
|
|
|
|
and use perl 5.8.1 or above. |
587
|
|
|
|
|
|
|
In the case of a C scenario, C re-run all the tests in a separate perl interpreter, |
588
|
|
|
|
|
|
|
this may lead to some side effects. |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
=head1 SEE ALSO |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
L, L. L, L |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
=head1 REPOSITORY |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
L |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
=head1 AUTHOR |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
Pierre Denis, C<< >>. |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
=head1 MAINTAINER |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
L |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
Currently maintained by Mohammad S Anwar (MANWAR), C<< >> |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
=head1 COPYRIGHT |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
Copyright 2005, 2010 Pierre Denis, All Rights Reserved. |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
You may use, modify, and distribute this package under the |
613
|
|
|
|
|
|
|
same terms as Perl itself. |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
=cut |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
1; |