File Coverage

blib/lib/Dist/Zilla/Plugin/Test/Compile.pm
Criterion Covered Total %
statement 54 59 91.5
branch 13 14 92.8
condition 3 3 100.0
subroutine 13 13 100.0
pod 0 4 0.0
total 83 93 89.2


line stmt bran cond sub pod time code
1             #
2             # This file is part of Dist-Zilla-Plugin-Test-Compile
3             #
4             # This software is copyright (c) 2009 by Jérôme Quelin.
5             #
6             # This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #
9 17     17   46139373 use strict;
  17         44  
  17         465  
10 17     17   78 use warnings;
  17         33  
  17         878  
11             package Dist::Zilla::Plugin::Test::Compile; # git description: v2.057-4-g2b42df1
12             # vim: set ts=8 sts=4 sw=4 tw=115 et :
13             # ABSTRACT: Common tests to check syntax of your modules, using only core modules
14             # KEYWORDS: plugin test compile verify validate load modules scripts
15              
16             our $VERSION = '2.058';
17              
18 17     17   96 use Moose;
  17         34  
  17         99  
19 17     17   89810 use Path::Tiny;
  17         34  
  17         904  
20 17     17   96 use Sub::Exporter::ForMethods 'method_installer'; # method_installer returns a sub.
  17         33  
  17         156  
21             use Data::Section 0.004 # fixed header_re
22 17     17   3509     { installer => method_installer }, '-setup';
  17         384  
  17         112  
23 17     17   11854 use Dist::Zilla::Dist::Builder ();
  17         35  
  17         1323  
24              
25             with (
26                 'Dist::Zilla::Role::FileGatherer',
27                 'Dist::Zilla::Role::FileMunger',
28                 'Dist::Zilla::Role::TextTemplate',
29                 'Dist::Zilla::Role::FileFinderUser' => {
30                     method => 'found_module_files',
31                     finder_arg_names => [ 'module_finder' ],
32                     default_finders => [ ':InstallModules' ],
33                 },
34                 'Dist::Zilla::Role::FileFinderUser' => {
35                     method => 'found_script_files',
36                     finder_arg_names => [ 'script_finder' ],
37                     default_finders => [
38                         eval { Dist::Zilla::Dist::Builder->VERSION('5.038'); 1 }
39                             ? ':PerlExecFiles'
40                             : ':ExecFiles'
41                     ],
42                 },
43                 'Dist::Zilla::Role::PrereqSource',
44             );
45              
46 17     17   113 use Moose::Util::TypeConstraints qw(enum role_type);
  17         30  
  17         203  
47 17     17   7605 use namespace::autoclean;
  17         34  
  17         229  
48              
49             # -- attributes
50              
51             has fake_home => ( is=>'ro', isa=>'Bool', default=>0 );
52             has needs_display => ( is=>'ro', isa=>'Bool', default=>0 );
53             has fail_on_warning => ( is=>'ro', isa=>enum([qw(none author all)]), default=>'author' );
54             has bail_out_on_fail => ( is=>'ro', isa=>'Bool', default=>0 );
55             has xt_mode => ( is=>'ro', isa=>'Bool', default=>0 );
56              
57             has filename => (
58                 is => 'ro', isa => 'Str',
59                 lazy => 1,
60                 default => sub { return ($_[0]->xt_mode ? 'xt/author' : 't') . '/00-compile.t' },
61             );
62              
63             has phase => (
64                 is => 'ro', isa => 'Str',
65                 lazy => 1,
66                 default => sub { return $_[0]->xt_mode ? 'develop' : 'test' },
67             );
68              
69             sub mvp_multivalue_args { qw(skips files switches) }
70 20     20 0 3387 sub mvp_aliases { return { skip => 'skips', file => 'files', switch => 'switches' } }
71              
72             has skips => (
73                 isa => 'ArrayRef[Str]',
74                 traits => ['Array'],
75                 handles => { skips => 'sort' },
76                 lazy => 1,
77                 default => sub { [] },
78             );
79              
80             has files => (
81                 isa => 'ArrayRef[Str]',
82                 traits => ['Array'],
83                 handles => { files => 'sort' },
84                 lazy => 1,
85                 default => sub { [] },
86             );
87              
88             has switches => (
89                 isa => 'ArrayRef[Str]',
90                 traits => ['Array'],
91                 handles => { switches => 'elements' },
92                 lazy => 1,
93                 default => sub { [] },
94             );
95              
96             has _test_more_version => (
97                 is => 'ro', isa => 'Str',
98                 init_arg => undef,
99                 lazy => 1,
100                 default => sub { shift->bail_out_on_fail ? '0.94' : '0' },
101             );
102              
103             # note that these two attributes could conceivably be settable via dist.ini,
104             # to avoid us using filefinders at all.
105             has _module_filenames => (
106                 isa => 'ArrayRef[Str]',
107                 traits => ['Array'],
108                 handles => { _module_filenames => 'sort' },
109                 lazy => 1,
110                 default => sub { [ map { $_->name } @{shift->found_module_files} ] },
111             );
112             has _script_filenames => (
113                 isa => 'ArrayRef[Str]',
114                 traits => ['Array'],
115                 handles => { _script_filenames => 'sort' },
116                 lazy => 1,
117                 default => sub { [ map { $_->name } @{shift->found_script_files} ] },
118             );
119              
120             around dump_config => sub
121             {
122                 my ($orig, $self) = @_;
123                 my $config = $self->$orig;
124              
125                 $config->{+__PACKAGE__} = {
126                     module_finder => [ sort @{ $self->module_finder } ],
127                     script_finder => [ sort @{ $self->script_finder } ],
128                     skips => [ sort $self->skips ],
129                     (map { $_ => $self->$_ ? 1 : 0 } qw(fake_home needs_display bail_out_on_fail)),
130                     (map { $_ => $self->$_ } qw(filename fail_on_warning bail_out_on_fail phase)),
131                     switch => [ $self->switches ],
132                     blessed($self) ne __PACKAGE__ ? ( version => $VERSION ) : (),
133                 };
134                 return $config;
135             };
136              
137             sub register_prereqs
138             {
139 20     20 0 28533     my $self = shift;
140              
141 20 100       600     return unless $self->phase;
142              
143 19 100       475     $self->zilla->register_prereqs(
144                     {
145                         phase => $self->phase,
146                         type => 'requires',
147                     },
148                     'Test::More' => $self->_test_more_version,
149                     'File::Spec' => '0',
150                     'IPC::Open3' => 0,
151                     'IO::Handle' => 0,
152                     $self->fake_home ? ( 'File::Temp' => '0' ) : (),
153                 );
154             }
155              
156             has _file => (
157                 is => 'rw', isa => role_type('Dist::Zilla::Role::File'),
158             );
159              
160             sub gather_files
161             {
162 20     20 0 1028561     my $self = shift;
163              
164 20         1394     require Dist::Zilla::File::InMemory;
165              
166                 $self->add_file( $self->_file(
167                     Dist::Zilla::File::InMemory->new(
168                         name => $self->filename,
169 20         220370             content => ${$self->section_data('test-compile')},
  20         127  
170                     ))
171                 );
172 20         12420     return;
173             }
174              
175             sub munge_file
176             {
177 92     92 0 48208     my ($self, $file) = @_;
178              
179 92 100       2402     return unless $file == $self->_file;
180              
181 20         716     my @skips = map {; qr/$_/ } $self->skips;
  0         0  
182              
183 20         776     my @more_files = $self->files;
184              
185             # we strip the leading lib/, and convert win32 \ to /, so the %INC entry
186             # is correct - to avoid potentially loading the file again later
187 20         820     my @module_filenames = map { path($_)->relative('lib')->stringify } $self->_module_filenames;
  23         1021  
188 20 100       6982     push @module_filenames, grep { /\.pm/i } @more_files if @more_files;
  1         6  
189              
190                 @module_filenames = grep {
191 20 50       64         (my $module = $_) =~ s{[/\\]}{::}g;
  0         0  
192 0         0         $module =~ s/\.pm$//;
193 0         0         not grep { $module =~ $_ } @skips
  0         0  
194                 } @module_filenames if @skips;
195              
196             # pod never returns true when loaded
197 20         53     @module_filenames = grep { !/\.pod$/ } @module_filenames;
  24         94  
198              
199 20         866     my @script_filenames = $self->_script_filenames;
200 20 100       95     push @script_filenames, grep { !/\.pm/i } @more_files if @more_files;
  1         5  
201              
202 20         151     $self->log_debug('adding module ' . $_) foreach @module_filenames;
203 20         7267     $self->log_debug('adding script ' . $_) foreach @script_filenames;
204              
205 20 100 100     3525     $file->content(
206                     $self->fill_in_string(
207                         $file->content,
208                         {
209                             dist => \($self->zilla),
210                             plugin => \$self,
211                             test_more_version => \($self->_test_more_version),
212                             module_filenames => \@module_filenames,
213                             script_filenames => \@script_filenames,
214                             fake_home => \($self->fake_home),
215                             needs_display => \($self->needs_display),
216                             bail_out_on_fail => \($self->bail_out_on_fail),
217                             fail_on_warning => \(
218                                 $self->fail_on_warning eq 'author' && $self->filename =~ m{^xt/author/}
219                                 ? 'all'
220                                 : $self->fail_on_warning),
221                             switches => \[$self->switches],
222                         }
223                     )
224                 );
225              
226 20         82417     return;
227             }
228              
229             __PACKAGE__->meta->make_immutable;
230              
231             #pod =pod
232             #pod
233             #pod =for Pod::Coverage::TrustPod
234             #pod mvp_multivalue_args
235             #pod mvp_aliases
236             #pod register_prereqs
237             #pod gather_files
238             #pod munge_file
239             #pod
240             #pod =head1 SYNOPSIS
241             #pod
242             #pod In your F<dist.ini>:
243             #pod
244             #pod [Test::Compile]
245             #pod skip = Test$
246             #pod fake_home = 1
247             #pod needs_display = 1
248             #pod fail_on_warning = author
249             #pod bail_out_on_fail = 1
250             #pod switch = -M-warnings=numeric ; like "no warnings 'numeric'
251             #pod
252             #pod =head1 DESCRIPTION
253             #pod
254             #pod This is a L<Dist::Zilla> plugin that runs at the L<gather files|Dist::Zilla::Role::FileGatherer> stage,
255             #pod providing a test file (configurable, defaulting to F<t/00-compile.t>).
256             #pod
257             #pod This test will find all modules and scripts in your distribution, and try to
258             #pod compile them one by one. This means it's a bit slower than loading them
259             #pod all at once, but it will catch more errors.
260             #pod
261             #pod The generated test is guaranteed to only depend on modules that are available
262             #pod in core. Most options only require perl 5.6.2; the C<bail_out_on_fail> option
263             #pod requires the version of L<Test::More> that shipped with perl 5.12 (but the
264             #pod test still runs on perl 5.6).
265             #pod
266             #pod This plugin accepts the following options:
267             #pod
268             #pod =head1 CONFIGURATION OPTIONS
269             #pod
270             #pod =head2 C<filename>
271             #pod
272             #pod The name of the generated file. Defaults to F<t/00-compile.t>
273             #pod
274             #pod =head2 C<phase>
275             #pod
276             #pod The phase for which to register prerequisites. Defaults
277             #pod to C<test>. Setting this to a false value will disable prerequisite
278             #pod registration.
279             #pod
280             #pod =head2 C<skip>
281             #pod
282             #pod A regex to skip compile test for B<modules> matching it. The
283             #pod match is done against the module name (C<Foo::Bar>), not the file path
284             #pod (F<lib/Foo/Bar.pm>). This option can be repeated to specify multiple regexes.
285             #pod
286             #pod =head2 C<file>
287             #pod
288             #pod A filename to also test, in addition to any files found
289             #pod earlier. It will be tested as a module if it ends with C<.pm> or C<.PM>,
290             #pod and as a script otherwise.
291             #pod Module filenames should be relative to F<lib>; others should be relative to
292             #pod the base of the repository.
293             #pod This option can be repeated to specify multiple additional files.
294             #pod
295             #pod =head2 C<fake_home>
296             #pod
297             #pod =for stopwords cpantesters
298             #pod
299             #pod A boolean to indicate whether to fake C<< $ENV{HOME} >>.
300             #pod This may be needed if your module unilaterally creates stuff in the user's home directory:
301             #pod indeed, some cpantesters will smoke test your distribution with a read-only home
302             #pod directory. Defaults to false.
303             #pod
304             #pod =head2 C<needs_display>
305             #pod
306             #pod A boolean to indicate whether to skip the compile test
307             #pod on non-Win32 systems when C<< $ENV{DISPLAY} >> is not set. Defaults to false.
308             #pod
309             #pod =head2 C<fail_on_warning>
310             #pod
311             #pod A string to indicate when to add a test for
312             #pod warnings during compilation checks. Possible values are:
313             #pod
314             #pod =over 4
315             #pod
316             #pod =item * C<none>: do not test for warnings
317             #pod
318             #pod =item * C<author>: test for warnings only when AUTHOR_TESTING is set
319             #pod (default, and recommended)
320             #pod
321             #pod =item * C<all>: always test for warnings (not recommended, as this can prevent
322             #pod installation of modules when upstream dependencies exhibit warnings in a new
323             #pod Perl release)
324             #pod
325             #pod =back
326             #pod
327             #pod =head2 C<bail_out_on_fail>
328             #pod
329             #pod A boolean to indicate whether the test will BAIL_OUT
330             #pod of all subsequent tests when compilation failures are encountered. Defaults to false.
331             #pod
332             #pod =head2 C<module_finder>
333             #pod
334             #pod =for stopwords FileFinder
335             #pod
336             #pod This is the name of a L<FileFinder|Dist::Zilla::Role::FileFinder> for finding
337             #pod modules to check. The default value is C<:InstallModules>; this option can be
338             #pod used more than once. F<.pod> files are always skipped.
339             #pod
340             #pod Other predefined finders are listed in
341             #pod L<Dist::Zilla::Role::FileFinderUser/default_finders>.
342             #pod You can define your own with the
343             #pod L<[FileFinder::ByName]|Dist::Zilla::Plugin::FileFinder::ByName> and
344             #pod L<[FileFinder::Filter]|Dist::Zilla::Plugin::FileFinder::Filter> plugins.
345             #pod
346             #pod =head2 C<script_finder>
347             #pod
348             #pod =for stopwords executables
349             #pod
350             #pod Just like C<module_finder>, but for finding scripts. The default value is
351             #pod C<:PerlExecFiles> (when available; otherwise C<:ExecFiles>)
352             #pod -- see also L<Dist::Zilla::Plugin::ExecDir>, to make sure these
353             #pod files are properly marked as executables for the installer.
354             #pod
355             #pod =head2 C<xt_mode>
356             #pod
357             #pod When true, the default C<filename> becomes F<xt/author/00-compile.t> and the
358             #pod default C<dependency> phase becomes C<develop>.
359             #pod
360             #pod =head2 C<switch>
361             #pod
362             #pod Use this option to pass a command-line switch (e.g. C<-d:Confess>, C<-M-warnings=numeric>) to the command that
363             #pod tests the module or script. Can be used more than once. See L<perlrun> for more on constructing these switches.
364             #pod
365             #pod =head1 RUNTIME ENVIRONMENT OPTIONS
366             #pod
367             #pod If the environment variable C<$PERL_COMPILE_TEST_DEBUG> is set to a true option when the test is run, the command
368             #pod to test each file will be printed as a C<diag>.
369             #pod
370             #pod =head1 SEE ALSO
371             #pod
372             #pod =for :list
373             #pod * L<Test::NeedsDisplay>
374             #pod * L<Test::Script>
375             #pod
376             #pod =cut
377              
378             =pod
379            
380             =encoding UTF-8
381            
382             =head1 NAME
383            
384             Dist::Zilla::Plugin::Test::Compile - Common tests to check syntax of your modules, using only core modules
385            
386             =head1 VERSION
387            
388             version 2.058
389            
390             =head1 SYNOPSIS
391            
392             In your F<dist.ini>:
393            
394             [Test::Compile]
395             skip = Test$
396             fake_home = 1
397             needs_display = 1
398             fail_on_warning = author
399             bail_out_on_fail = 1
400             switch = -M-warnings=numeric ; like "no warnings 'numeric'
401            
402             =head1 DESCRIPTION
403            
404             This is a L<Dist::Zilla> plugin that runs at the L<gather files|Dist::Zilla::Role::FileGatherer> stage,
405             providing a test file (configurable, defaulting to F<t/00-compile.t>).
406            
407             This test will find all modules and scripts in your distribution, and try to
408             compile them one by one. This means it's a bit slower than loading them
409             all at once, but it will catch more errors.
410            
411             The generated test is guaranteed to only depend on modules that are available
412             in core. Most options only require perl 5.6.2; the C<bail_out_on_fail> option
413             requires the version of L<Test::More> that shipped with perl 5.12 (but the
414             test still runs on perl 5.6).
415            
416             This plugin accepts the following options:
417            
418             =for Pod::Coverage::TrustPod mvp_multivalue_args
419             mvp_aliases
420             register_prereqs
421             gather_files
422             munge_file
423            
424             =head1 CONFIGURATION OPTIONS
425            
426             =head2 C<filename>
427            
428             The name of the generated file. Defaults to F<t/00-compile.t>
429            
430             =head2 C<phase>
431            
432             The phase for which to register prerequisites. Defaults
433             to C<test>. Setting this to a false value will disable prerequisite
434             registration.
435            
436             =head2 C<skip>
437            
438             A regex to skip compile test for B<modules> matching it. The
439             match is done against the module name (C<Foo::Bar>), not the file path
440             (F<lib/Foo/Bar.pm>). This option can be repeated to specify multiple regexes.
441            
442             =head2 C<file>
443            
444             A filename to also test, in addition to any files found
445             earlier. It will be tested as a module if it ends with C<.pm> or C<.PM>,
446             and as a script otherwise.
447             Module filenames should be relative to F<lib>; others should be relative to
448             the base of the repository.
449             This option can be repeated to specify multiple additional files.
450            
451             =head2 C<fake_home>
452            
453             =for stopwords cpantesters
454            
455             A boolean to indicate whether to fake C<< $ENV{HOME} >>.
456             This may be needed if your module unilaterally creates stuff in the user's home directory:
457             indeed, some cpantesters will smoke test your distribution with a read-only home
458             directory. Defaults to false.
459            
460             =head2 C<needs_display>
461            
462             A boolean to indicate whether to skip the compile test
463             on non-Win32 systems when C<< $ENV{DISPLAY} >> is not set. Defaults to false.
464            
465             =head2 C<fail_on_warning>
466            
467             A string to indicate when to add a test for
468             warnings during compilation checks. Possible values are:
469            
470             =over 4
471            
472             =item * C<none>: do not test for warnings
473            
474             =item * C<author>: test for warnings only when AUTHOR_TESTING is set
475             (default, and recommended)
476            
477             =item * C<all>: always test for warnings (not recommended, as this can prevent
478             installation of modules when upstream dependencies exhibit warnings in a new
479             Perl release)
480            
481             =back
482            
483             =head2 C<bail_out_on_fail>
484            
485             A boolean to indicate whether the test will BAIL_OUT
486             of all subsequent tests when compilation failures are encountered. Defaults to false.
487            
488             =head2 C<module_finder>
489            
490             =for stopwords FileFinder
491            
492             This is the name of a L<FileFinder|Dist::Zilla::Role::FileFinder> for finding
493             modules to check. The default value is C<:InstallModules>; this option can be
494             used more than once. F<.pod> files are always skipped.
495            
496             Other predefined finders are listed in
497             L<Dist::Zilla::Role::FileFinderUser/default_finders>.
498             You can define your own with the
499             L<[FileFinder::ByName]|Dist::Zilla::Plugin::FileFinder::ByName> and
500             L<[FileFinder::Filter]|Dist::Zilla::Plugin::FileFinder::Filter> plugins.
501            
502             =head2 C<script_finder>
503            
504             =for stopwords executables
505            
506             Just like C<module_finder>, but for finding scripts. The default value is
507             C<:PerlExecFiles> (when available; otherwise C<:ExecFiles>)
508             -- see also L<Dist::Zilla::Plugin::ExecDir>, to make sure these
509             files are properly marked as executables for the installer.
510            
511             =head2 C<xt_mode>
512            
513             When true, the default C<filename> becomes F<xt/author/00-compile.t> and the
514             default C<dependency> phase becomes C<develop>.
515            
516             =head2 C<switch>
517            
518             Use this option to pass a command-line switch (e.g. C<-d:Confess>, C<-M-warnings=numeric>) to the command that
519             tests the module or script. Can be used more than once. See L<perlrun> for more on constructing these switches.
520            
521             =head1 RUNTIME ENVIRONMENT OPTIONS
522            
523             If the environment variable C<$PERL_COMPILE_TEST_DEBUG> is set to a true option when the test is run, the command
524             to test each file will be printed as a C<diag>.
525            
526             =head1 SEE ALSO
527            
528             =over 4
529            
530             =item *
531            
532             L<Test::NeedsDisplay>
533            
534             =item *
535            
536             L<Test::Script>
537            
538             =back
539            
540             =head1 SUPPORT
541            
542             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Dist-Zilla-Plugin-Test-Compile>
543             (or L<bug-Dist-Zilla-Plugin-Test-Compile@rt.cpan.org|mailto:bug-Dist-Zilla-Plugin-Test-Compile@rt.cpan.org>).
544            
545             There is also a mailing list available for users of this distribution, at
546             L<http://dzil.org/#mailing-list>.
547            
548             There is also an irc channel available for users of this distribution, at
549             L<C<#distzilla> on C<irc.perl.org>|irc://irc.perl.org/#distzilla>.
550            
551             =head1 AUTHORS
552            
553             =over 4
554            
555             =item *
556            
557             Jérôme Quelin <jquelin@gmail.com>
558            
559             =item *
560            
561             Karen Etheridge <ether@cpan.org>
562            
563             =back
564            
565             =head1 CONTRIBUTORS
566            
567             =for stopwords Ahmad M. Zawawi Olivier Mengué Kent Fredric Jesse Luehrs David Golden Randy Stauner Harley Pig Graham Knop fayland Peter Shangov Chris Weyl Ricardo SIGNES Marcel Gruenauer
568            
569             =over 4
570            
571             =item *
572            
573             Ahmad M. Zawawi <ahmad.zawawi@gmail.com>
574            
575             =item *
576            
577             Olivier Mengué <dolmen@cpan.org>
578            
579             =item *
580            
581             Kent Fredric <kentnl@cpan.org>
582            
583             =item *
584            
585             Jesse Luehrs <doy@tozt.net>
586            
587             =item *
588            
589             David Golden <dagolden@cpan.org>
590            
591             =item *
592            
593             Randy Stauner <rwstauner@cpan.org>
594            
595             =item *
596            
597             Harley Pig <harleypig@gmail.com>
598            
599             =item *
600            
601             Graham Knop <haarg@haarg.org>
602            
603             =item *
604            
605             fayland <fayland@gmail.com>
606            
607             =item *
608            
609             Peter Shangov <pshangov@yahoo.com>
610            
611             =item *
612            
613             Chris Weyl <cweyl@alumni.drew.edu>
614            
615             =item *
616            
617             Ricardo SIGNES <rjbs@cpan.org>
618            
619             =item *
620            
621             Marcel Gruenauer <hanekomu@gmail.com>
622            
623             =back
624            
625             =head1 COPYRIGHT AND LICENCE
626            
627             This software is copyright (c) 2009 by Jérôme Quelin.
628            
629             This is free software; you can redistribute it and/or modify it under
630             the same terms as the Perl 5 programming language system itself.
631            
632             =cut
633              
634             __DATA__
635             ___[ test-compile ]___
636             use 5.006;
637             use strict;
638             use warnings;
639            
640             # this test was generated with {{ ref $plugin }} {{ $plugin->VERSION }}
641            
642             use Test::More{{ $test_more_version ? " $test_more_version" : '' }};
643             {{
644             $needs_display ? <<'CODE' : ''
645             # Skip all tests if you need a display for this test and $ENV{DISPLAY} is not set
646             if (not $ENV{DISPLAY} and $^O ne 'MSWin32') {
647             plan skip_all => 'Needs DISPLAY';
648             }
649             CODE
650             }}
651             plan tests => {{
652             my $count = @module_filenames + @script_filenames;
653             $count += 1 if $fail_on_warning eq 'all';
654             $count .= ' + ($ENV{AUTHOR_TESTING} ? 1 : 0)' if $fail_on_warning eq 'author';
655             $count;
656             }};
657            
658             my @module_files = (
659             {{ join(",\n", map { " '" . $_ . "'" } map { s/'/\\'/g; $_ } sort @module_filenames) }}
660             );
661            
662             {{
663             @script_filenames
664             ? 'my @scripts = (' . "\n"
665             . join(",\n", map { " '" . $_ . "'" } map { s/'/\\'/g; $_ } sort @script_filenames)
666             . "\n" . ');'
667             : ''
668             }}
669            
670             {{
671             $fake_home ? <<'CODE' : '# no fake home requested';
672             # fake home for cpan-testers
673             use File::Temp;
674             local $ENV{HOME} = File::Temp::tempdir( CLEANUP => 1 );
675             CODE
676             }}
677            
678             my @switches = (
679             -d 'blib' ? '-Mblib' : '-Ilib',
680             {{ @$switches ? ' ' . join(' ', map { q{'} . $_ . q{',} } @$switches) . "\n" : '' }});
681            
682             use File::Spec;
683             use IPC::Open3;
684             use IO::Handle;
685            
686             open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!";
687            
688             my @warnings;
689             for my $lib (@module_files)
690             {
691             # see L<perlfaq8/How can I capture STDERR from an external command?>
692             my $stderr = IO::Handle->new;
693            
694             diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} }
695             $^X, @switches, '-e', "require q[$lib]"))
696             if $ENV{PERL_COMPILE_TEST_DEBUG};
697            
698             my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]");
699             binmode $stderr, ':crlf' if $^O eq 'MSWin32';
700             my @_warnings = <$stderr>;
701             waitpid($pid, 0);
702             is($?, 0, "$lib loaded ok");
703            
704             shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/
705             and not eval { +require blib; blib->VERSION('1.01') };
706            
707             if (@_warnings)
708             {
709             warn @_warnings;
710             push @warnings, @_warnings;
711             }
712             }
713            
714             {{
715             @script_filenames ? <<'CODE' : '';
716             foreach my $file (@scripts)
717             { SKIP: {
718             open my $fh, '<', $file or warn("Unable to open $file: $!"), next;
719             my $line = <$fh>;
720            
721             close $fh and skip("$file isn't perl", 1) unless $line =~ /^#!\s*(?:\S*perl\S*)((?:\s+-\w*)*)(?:\s*#.*)?$/;
722             @switches = (@switches, split(' ', $1)) if $1;
723            
724             close $fh and skip("$file uses -T; not testable with PERL5LIB", 1)
725             if grep { $_ eq '-T' } @switches and $ENV{PERL5LIB};
726            
727             my $stderr = IO::Handle->new;
728            
729             diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} }
730             $^X, @switches, '-c', $file))
731             if $ENV{PERL_COMPILE_TEST_DEBUG};
732            
733             my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-c', $file);
734             binmode $stderr, ':crlf' if $^O eq 'MSWin32';
735             my @_warnings = <$stderr>;
736             waitpid($pid, 0);
737             is($?, 0, "$file compiled ok");
738            
739             shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/
740             and not eval { +require blib; blib->VERSION('1.01') };
741            
742             # in older perls, -c output is simply the file portion of the path being tested
743             if (@_warnings = grep { !/\bsyntax OK$/ }
744             grep { chomp; $_ ne (File::Spec->splitpath($file))[2] } @_warnings)
745             {
746             warn @_warnings;
747             push @warnings, @_warnings;
748             }
749             } }
750            
751             CODE
752             }}
753            
754             {{
755             ($fail_on_warning ne 'none'
756             ? q{is(scalar(@warnings), 0, 'no warnings found')} . "\n"
757             . q{ or diag 'got warnings: ', }
758             . ( $test_more_version > 0.82
759             ? q{explain(\@warnings)}
760             : q{( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) )}
761             )
762             : '# no warning checks')
763             .
764             ($fail_on_warning eq 'author'
765             ? ' if $ENV{AUTHOR_TESTING};'
766             : ';')
767             }}
768            
769             {{
770             $bail_out_on_fail
771             ? 'BAIL_OUT("Compilation problems") if !Test::More->builder->is_passing;'
772             : '';
773             }}
774