BATsh
view release on metacpan or search on metacpan
t/0007-extcmd-env.t view on Meta::CPAN
my ($mode) = @_;
my $root = File::Spec->catdir($FindBin::Bin, File::Spec->updir);
my @hits;
# Directories scanned (relative to the distribution root), plus the
# top-level README. Covers executable code (t/, eg/), the module
# POD samples (lib/), and the 21-language reference docs (doc/), so a
# non-portable inline-Perl one-liner cannot be reintroduced anywhere.
my @relfiles;
for my $sub ('t', 'eg', 'doc', 'lib', 'lib/BATsh') {
my $dir = File::Spec->catdir($root, split(m{/}, $sub));
next unless -d $dir;
local *EE_DIR;
next unless opendir(EE_DIR, $dir);
my @names = sort grep { $_ !~ /\A\./ } readdir(EE_DIR);
closedir(EE_DIR);
for my $name (@names) {
# Only canonical source files; skip backups / editor files
# (e.g. *-OLD, *-OLD2, *.bak, *~) that may sit in the tree.
my $ok = 0;
if ($sub eq 't') { $ok = ($name =~ /\.t\z/) }
elsif ($sub eq 'eg') { $ok = ($name =~ /\.(?:batsh|pl)\z/) }
elsif ($sub eq 'doc') { $ok = ($name =~ /\.txt\z/) }
else { $ok = ($name =~ /\.pm\z/) } # lib, lib/BATsh
next unless $ok;
push @relfiles, "$sub/$name";
}
}
push @relfiles, 'README';
for my $rel (@relfiles) {
# This regression file documents the hazards in prose on purpose,
# so it must not scan itself.
next if $rel =~ /0007-extcmd-env\.t\z/;
my $path = File::Spec->catfile($root, split(m{/}, $rel));
next unless -f $path;
local *EE_FH;
next unless open(EE_FH, $path);
my $lineno = 0;
while (<EE_FH>) {
$lineno++;
my $line = $_;
$line =~ s/[\r\n]+\z//;
# Skip full-line comments (Perl/SH '#', CMD '::' / 'REM') so
# prose that merely mentions perl one-liners is ignored.
next if $line =~ /\A\s*#/;
next if $line =~ /\A\s*::/;
next if $line =~ /\A\s*(?:REM|rem)\b/;
# Normalise escaped quotes from .t string literals.
my $eff = $line;
$eff =~ s/\\"/"/g;
$eff =~ s/\\'/'/g;
my $bad = 0;
if ($mode eq 'SQ') {
# perl <flags ending in e> followed by a single quote
$bad = 1 if $eff =~ /\bperl\b[^|<>;&`]*?-\w*e\b\s*'/;
}
else {
# perl <flags ending in e> "double-quoted-code"
if ($eff =~ /\bperl\b[^|<>;&`]*?-\w*e\b\s*"([^"]*)"/) {
my $code = $1;
$bad = 1 if $code =~ /\$[A-Za-z_0-9{]/;
}
}
push @hits, "$rel:$lineno: $line" if $bad;
}
close(EE_FH);
}
return @hits;
}
sub _capture {
my ($code) = @_;
my $tmpfile = File::Spec->catfile(
File::Spec->tmpdir(), "batsh_cap7_$$\.tmp");
open(_CAP_OLD, '>&STDOUT') or return '';
open(_CAP_FH, ">$tmpfile") or do { open(STDOUT, '>&_CAP_OLD'); return '' };
open(STDOUT, '>&_CAP_FH');
close(_CAP_FH);
eval { $code->() };
open(STDOUT, '>&_CAP_OLD');
close(_CAP_OLD);
my $buf = '';
if (open(_CAP_RFH, "< $tmpfile")) {
local $/;
$buf = <_CAP_RFH>;
close(_CAP_RFH);
}
unlink $tmpfile;
$buf = '' unless defined $buf;
return $buf;
}
print "1.." . scalar(@tests) . "\n";
my ($run, $fail) = (0, 0);
sub _ok {
my ($ok, $name) = @_;
$run++; $fail++ unless $ok;
$name = '' unless defined $name;
print +($ok ? '' : 'not ') . "ok $run - $name\n";
}
$_->() for @tests;
END { $? = 1 if $fail }
( run in 0.633 second using v1.01-cache-2.11-cpan-364913b4093 )