App-cpan2arch
view release on metacpan or search on metacpan
xt/boilerplate.t view on Meta::CPAN
#!perl
#
# Test to ensure that no boilerplate text generated by Module::Starter::Plugin::MyGuts
# is left in the distribution files.
#
# NOTE:
# To see verbose output in correct order, use yath or run:
# prove -l xt/boilerplate.t --merge -v
use v5.42.0;
use strict;
use warnings;
use Test2::V1 qw<
note
diag
pass
fail
>;
use re qw< eval >;
#use DDP output => 'stdout';
sub not_in_file_ok
{
my $filename = shift;
note("FILENAME: $filename\n\n");
open my $fh, '<', $filename or die "Failed to open $filename for reading: $!";
my $file = do { local $/ = undef; <$fh> }; # Slurp entire file.
close $fh or die $!;
my $desc;
my @regex_type;
my @readme_rgx = (
'The\ README\ is\ used\ to\ introduce\ the\ module\ and\ provide\ instructions\ on\
how\ to\ install\ the\ module\,\ any\ machine\ dependencies\ it\ may\ have\ \(for\
example\ C\ compilers\ and\ installed\ libraries\)\ and\ any\ other\ information\
that\ should\ be\ provided\ before\ the\ module\ is\ installed\.\
\
A\ README\ file\ is\ required\ for\ CPAN\ modules\ since\ CPAN\ extracts\ the\ README\
file\ from\ a\ module\ distribution\ so\ that\ people\ browsing\ the\ archive\
can\ use\ it\ to\ get\ an\ idea\ of\ the\ module\'s\ uses\.\ It\ is\ usually\ a\ good\ idea\
to\ provide\ version\ information\ here\ so\ that\ people\ can\ decide\ whether\
fixes\ for\ the\ module\ are\ worth\ downloading\.\
(?{ $desc = "introduction" })',
);
my @changes_rgx = (
'v1\.0\.0\ \ \ \ YYYY\-MM\-DD\ HH\:MM\:SSZ\
\ \ \ \ \ \ \ \ \ \ \-\ Initial\ release\
(?{ $desc = "changelog" })',
);
my @modules_rgx = (
'sub\ function1\ \(\)\
\{\
\}\
(?{ $desc = "stub function1 definition" })',
'sub\ function2\ \(\)\
\{\
\}\
(?{ $desc = "stub function2 definition" })',
'[^ \n]+ - new\ abstract(?{ $desc = "POD NAME" })',
'Quick\ summary\ of\ what\ the\ module\ does\.\
\
With\ brief\ examples\:\
\
\ \ \ \ \#\ Procedural\
\
\ \ \ \ use\ App\:\:cpan2arch\ qw\<\ function\ \>\;\
\
\ \ \ \ my\ \$foo\ \=\ function\(\.\.\.\)\;\
\ \ \ \ \.\.\.\
\
\ \ \ \ \#\ OOP\
\
\ \ \ \ use\ App\:\:cpan2arch\;\
\
\ \ \ \ my\ \$foo\ \=\ App\:\:cpan2arch\-\>new\;\
\ \ \ \ \$foo\-\>method\(\.\.\.\)\;\
\ \ \ \ \.\.\.\
xt/boilerplate.t view on Meta::CPAN
);
foreach ($filename) {
if (/\AREADME\z/) { push @regex_type, @readme_rgx }
elsif (/\AChanges\z/) { push @regex_type, @changes_rgx }
elsif (/\.pm\z/) { push @regex_type, @modules_rgx }
else { die "$filename is not supported" }
}
#p @regex_type;
#note("\n");
# Concat and compile the regexes.
my $joined = join '|', @regex_type;
my $regex = qr{^(?> $joined )}mx;
#note("REGEX:\n");
#p $regex;
#note("\n");
my $c = 0;
# Scan the file with its respective regex type.
while (1) {
# Boilerplate
if ( $file =~ /\G$regex/gc ) {
my $end = '';
++$c;
note("MATCH:\n$c '$&'\n");
fail("$filename contains $desc boilerplate text");
# Count lines of a multiline match.
my $nl = $& =~ tr{\n}{};
if ( $nl > 1 ) {
$nl += $c - 1;
$end = ',' . $nl;
}
diag("$desc appears on lines ${c}$end");
note("\n");
$c = $nl;
}
# Generic line (forwards scanner line-by-line).
elsif ( $file =~ /\G([^\n]*+)\n/gc ) {
++$c;
#note("$c '$1'");
}
# End of file.
if ( $file =~ /\G\z/ ) {
pass("$filename contains no boilerplate text") unless defined $desc;
note("\n");
last;
}
}
}
not_in_file_ok('README');
not_in_file_ok('Changes');
not_in_file_ok('lib/App/cpan2arch.pm');
T2->done_testing;
( run in 1.588 second using v1.01-cache-2.11-cpan-9581c071862 )