mirror of
https://github.com/webmin/webmin.git
synced 2026-06-05 12:50:23 +01:00
91 lines
2.7 KiB
Perl
91 lines
2.7 KiB
Perl
#!/usr/local/bin/perl
|
|
# Verify every .pl and .cgi in the tree parses (perl -c).
|
|
#
|
|
# Catches syntax and `use` breakage from bulk refactors without having
|
|
# to load every page in a browser. The test is the first line of defence
|
|
# for the "we changed thousands of files mechanically, did anything
|
|
# break" question.
|
|
#
|
|
# Skipped:
|
|
# - $file.pl when a sibling $file (no .pl) exists. Webmin uses .pl as
|
|
# the Polish translation suffix, so config.info.pl, module.info.pl,
|
|
# etc. are data files, not Perl.
|
|
# - Files that fail only because of a missing CPAN module. The file
|
|
# itself parses, but `use Foo::Bar` can't resolve at compile time.
|
|
# Treated as a skip so missing optional deps don't gate the suite.
|
|
# Set WEBMIN_COMPILE_T_STRICT=1 to turn these into failures.
|
|
#
|
|
# Speed: ~12 seconds for the full tree (~3.4k files). Narrow with
|
|
# WEBMIN_COMPILE_T_FILTER=<regex> when iterating on one module.
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Test::More;
|
|
use File::Find;
|
|
use File::Basename qw(dirname);
|
|
use File::Spec;
|
|
use Cwd qw(abs_path);
|
|
|
|
my $root = abs_path(File::Spec->catdir(dirname(__FILE__), '..'));
|
|
chdir($root) or die "chdir($root): $!";
|
|
|
|
my $filter = $ENV{WEBMIN_COMPILE_T_FILTER};
|
|
my $strict = $ENV{WEBMIN_COMPILE_T_STRICT};
|
|
|
|
my @files;
|
|
find({
|
|
no_chdir => 1,
|
|
wanted => sub {
|
|
return if -d;
|
|
# .pl and .cgi files, plus extensionless files in bin/ with a
|
|
# perl shebang. The shebang check keeps us from compile-checking
|
|
# arbitrary non-perl files just because they share a directory.
|
|
my $name = $File::Find::name;
|
|
my $is_pl_or_cgi = $name =~ /\.(pl|cgi)\z/;
|
|
my $is_bin_dotless = $name =~ m{^\./bin/([^/]+)\z} && $1 !~ /\./;
|
|
return unless $is_pl_or_cgi || $is_bin_dotless;
|
|
# Skip the Polish translations that share the .pl suffix.
|
|
if ($is_pl_or_cgi && $name =~ m{(.+)\.pl\z}) {
|
|
my $base = $1;
|
|
return if -f "$base";
|
|
}
|
|
# For extensionless bin/ scripts, require a perl shebang.
|
|
if ($is_bin_dotless) {
|
|
open(my $fh, '<', $name) or return;
|
|
my $shebang = <$fh>;
|
|
close($fh);
|
|
return unless defined $shebang && $shebang =~ /^#!.*\bperl\b/;
|
|
}
|
|
push(@files, $name);
|
|
},
|
|
}, '.');
|
|
|
|
@files = sort @files;
|
|
@files or BAIL_OUT("found no .pl/.cgi/bin scripts under $root");
|
|
|
|
if ($filter) {
|
|
@files = grep { /$filter/ } @files;
|
|
@files or do { diag("filter '$filter' matched zero files"); plan skip_all => "no files match filter"; };
|
|
}
|
|
|
|
diag("compile-checking " . scalar(@files) . " files");
|
|
|
|
for my $f (@files) {
|
|
my $rel = $f;
|
|
$rel =~ s{^\./}{};
|
|
my $out = qx{perl -I. -c -- "$rel" 2>&1};
|
|
if ($out =~ /\bsyntax OK\b/) {
|
|
pass("$rel compiles");
|
|
}
|
|
elsif (!$strict && $out =~ /Can't locate (\S+\.pm) in \@INC/) {
|
|
SKIP: { skip("$rel: missing optional CPAN module $1", 1); }
|
|
}
|
|
else {
|
|
fail("$rel compiles");
|
|
diag($out);
|
|
}
|
|
}
|
|
|
|
done_testing();
|
|
|