Alister West

home is where your code is ...

Test Perl Module Compliation

Usually perl modules are tested first with a t/00modules.t file. The same approach should be used for scripts (t/00scripts.t) to make sure cgi's and others compile before you try to use them.

t/00modules.t

#!/usr/bin/env perl

=head1 NAME

    t/00modules.t - Basic Module and validation tests

=head1 DESCRIPTION

    This runs several tests on modules
        - Checks Syntax
        - Checks Module name matches Path
        - Checks inhouse modules have a header

=head1 AUTHOR

    Alister West (2010)

=cut

use strict;
use warnings;

use File::Find;

# Setup
use FindBin qw/$Bin/;
require "$Bin/env.pl";

use Test::More qw/no_plan/;

# ---------------------------------------------------------------------------
# Check Modules

my @libs = qw{ /usr/lib/gpanel };

foreach my $basedir (@libs) {
    # Find modules
    my @modules;
    find(
        sub { push @modules, $File::Find::name if $File::Find::name =~ /\.pm$/ },
        $basedir
    );

    # Remove base path
    $_ =~ s{$basedir/}{} for @modules;

    foreach my $module (@modules) {

        diag("$module\n");

        check_syntax($basedir, $module);
        check_package_name($basedir, $module);

        # Specific tests for Gossamer internal libs.
        next unless $module =~ m/GT|GPanel/;
        check_for_header($basedir, $module);
    }
}

# ---------------------------------------------------------------------------

sub slurp {
    # Slurp.pm
    local( $/, @ARGV ) = ( wantarray ? $/ : undef, @_ );
    return <ARGV>;
}

# ---------------------------------------------------------------------------

sub check_syntax {

    # perl -wc My::Module.pm

    my ($basedir,$module) = @_;

    # print "DEBUG: perl -I$basedir -wc $basedir/$module 2>&1\n" if $DEBUG;
    my @output = `perl -I$basedir -wc $basedir/$module 2>&1`;

    # final line should indicate module is syntactically correct
    is(
        $output[-1],
        "$basedir/$module syntax OK\n",
        "$basedir/$module syntax OK",
    );
}

# ---------------------------------------------------------------------------

sub check_package_name {

    # Check package agrees with filename.
    # Could use Module::File here - but would have to install it or include it.

    my ($basedir,$module) = @_;

    my ($package) = $module =~ m/(.*)\.pm/;
    $package =~ s{ / }{ :: }gxms;

    my $file_content = slurp("$basedir/$module");

    # First matched 'package' declaration should match filename.
    $file_content =~ m{ ^ \s* package \s+ (.+?) ; \s* $ }xms;
    my $declared_package = $1;

    is(
        $declared_package,
        $package,
        "$module should contain package $package",
    );
}

# ---------------------------------------------------------------------------

sub check_for_header {

    # Check we have header
    # t/module_header.t has more specific testing.

    my ($basedir,$module) = @_;

    my ($package) = $module =~ m/(.*)\.pm/;
    $package =~ s,/,::,g;

    my $content = slurp("$basedir/$module");

    # Grab header
    my ($module_header) =  $content =~ m/(# ={40}=+.*={40}=+)/ms;

    TODO: {
        local $TODO = "Put in header block.";
        ok($module_header, "$package needs header block");
    }
}

t/00scripts.t

#!/usr/bin/env perl

use FindBin qw/$Bin/;
require "$Bin/env.pl";

use Test::More qw/no_plan/;

my @bindirs = qw{ /var/gpanel/virtual_admin  /var/gpanel/server_admin };

foreach my $basedir (@bindirs)  {

    my @scripts;
    find( sub { push @scripts, $File::Find::name }, $basedir );

    # Remove base path
    $_ =~ s{$basedir/}{} for @scripts;

    foreach my $file (@scripts) {
        my @output = `perl -wc $basedir/$file 2>&1`;

        # final line should indicate module is syntactically correct
        is(
            $output[-1],
            "$basedir/$file syntax OK\n",
            "$basedir/$file syntax OK",
        );

        # cgi scripts should not be group/world writeable
        if ($file =~ /\.cgi$/) {
            # say +(stat "$basedir/$file")[2];
            my $perms = (stat "$basedir/$file")[2] & 07777;
            is( sprintf("%04o", $perms), "0755", "chmod 0755 $file" );
        }
    }

}
By Alister West