Plugin testing framework.
git-svn-id: https://svn.perl.org/qpsmtpd/trunk@313 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
parent
0b16ec9418
commit
9224e436bb
@ -63,6 +63,18 @@ sub config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub config_dir {
|
||||||
|
my ($self, $config) = @_;
|
||||||
|
my $configdir = ($ENV{QMAIL} || '/var/qmail') . '/control';
|
||||||
|
my ($name) = ($0 =~ m!(.*?)/([^/]+)$!);
|
||||||
|
$configdir = "$name/config" if (-e "$name/config/$config");
|
||||||
|
return $configdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub plugin_dir {
|
||||||
|
my ($name) = ($0 =~ m!(.*?)/([^/]+)$!);
|
||||||
|
my $dir = "$name/plugins";
|
||||||
|
}
|
||||||
|
|
||||||
sub get_qmail_config {
|
sub get_qmail_config {
|
||||||
my ($self, $config, $type) = @_;
|
my ($self, $config, $type) = @_;
|
||||||
@ -70,9 +82,7 @@ sub get_qmail_config {
|
|||||||
if ($self->{_config_cache}->{$config}) {
|
if ($self->{_config_cache}->{$config}) {
|
||||||
return wantarray ? @{$self->{_config_cache}->{$config}} : $self->{_config_cache}->{$config}->[0];
|
return wantarray ? @{$self->{_config_cache}->{$config}} : $self->{_config_cache}->{$config}->[0];
|
||||||
}
|
}
|
||||||
my $configdir = ($ENV{QMAIL} || '/var/qmail') . '/control';
|
my $configdir = $self->config_dir($config);
|
||||||
my ($name) = ($0 =~ m!(.*?)/([^/]+)$!);
|
|
||||||
$configdir = "$name/config" if (-e "$name/config/$config");
|
|
||||||
|
|
||||||
my $configfile = "$configdir/$config";
|
my $configfile = "$configdir/$config";
|
||||||
|
|
||||||
@ -112,7 +122,7 @@ sub _config_from_file {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub _compile {
|
sub _compile {
|
||||||
my ($plugin, $package, $file) = @_;
|
my ($self, $plugin, $package, $file) = @_;
|
||||||
|
|
||||||
my $sub;
|
my $sub;
|
||||||
open F, $file or die "could not open $file: $!";
|
open F, $file or die "could not open $file: $!";
|
||||||
@ -124,6 +134,15 @@ sub _compile {
|
|||||||
|
|
||||||
my $line = "\n#line 1 $file\n";
|
my $line = "\n#line 1 $file\n";
|
||||||
|
|
||||||
|
if ($self->{_test_mode}) {
|
||||||
|
if (open(F, "t/plugin_tests/$plugin")) {
|
||||||
|
local $/ = undef;
|
||||||
|
$sub .= "#line 1 t/plugin_tests/$plugin\n";
|
||||||
|
$sub .= <F>;
|
||||||
|
close F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
my $eval = join(
|
my $eval = join(
|
||||||
"\n",
|
"\n",
|
||||||
"package $package;",
|
"package $package;",
|
||||||
@ -131,6 +150,7 @@ sub _compile {
|
|||||||
"require Qpsmtpd::Plugin;",
|
"require Qpsmtpd::Plugin;",
|
||||||
'use vars qw(@ISA);',
|
'use vars qw(@ISA);',
|
||||||
'@ISA = qw(Qpsmtpd::Plugin);',
|
'@ISA = qw(Qpsmtpd::Plugin);',
|
||||||
|
($self->{_test_mode} ? 'use Test::More;' : ''),
|
||||||
"sub plugin_name { qq[$plugin] }",
|
"sub plugin_name { qq[$plugin] }",
|
||||||
$line,
|
$line,
|
||||||
$sub,
|
$sub,
|
||||||
@ -149,42 +169,43 @@ sub _compile {
|
|||||||
sub load_plugins {
|
sub load_plugins {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
$self->{hooks} ||= {};
|
$self->log(LOGERROR, "Plugins already loaded") if $self->{hooks};
|
||||||
|
$self->{hooks} = {};
|
||||||
|
|
||||||
my @plugins = $self->config('plugins');
|
my @plugins = $self->config('plugins');
|
||||||
|
|
||||||
my ($name) = ($0 =~ m!(.*?)/([^/]+)$!);
|
my $dir = $self->plugin_dir;
|
||||||
my $dir = "$name/plugins";
|
|
||||||
$self->log(LOGNOTICE, "loading plugins from $dir");
|
$self->log(LOGNOTICE, "loading plugins from $dir");
|
||||||
|
|
||||||
$self->_load_plugins($dir, @plugins);
|
@plugins = $self->_load_plugins($dir, @plugins);
|
||||||
|
|
||||||
|
return @plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _load_plugins {
|
sub _load_plugins {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($dir, @plugins) = @_;
|
my ($dir, @plugins) = @_;
|
||||||
|
|
||||||
|
my @ret;
|
||||||
for my $plugin (@plugins) {
|
for my $plugin (@plugins) {
|
||||||
$self->log(LOGINFO, "Loading $plugin");
|
$self->log(LOGINFO, "Loading $plugin");
|
||||||
($plugin, my @args) = split /\s+/, $plugin;
|
($plugin, my @args) = split /\s+/, $plugin;
|
||||||
|
|
||||||
if (lc($plugin) eq '$include') {
|
if (lc($plugin) eq '$include') {
|
||||||
my $inc = shift @args;
|
my $inc = shift @args;
|
||||||
my $config_dir = ($ENV{QMAIL} || '/var/qmail') . '/control';
|
my $config_dir = $self->config_dir($inc);
|
||||||
my ($name) = ($0 =~ m!(.*?)/([^/]+)$!);
|
|
||||||
$config_dir = "$name/config" if (-e "$name/config/$inc");
|
|
||||||
if (-d "$config_dir/$inc") {
|
if (-d "$config_dir/$inc") {
|
||||||
$self->log(LOGDEBUG, "Loading include dir: $config_dir/$inc");
|
$self->log(LOGDEBUG, "Loading include dir: $config_dir/$inc");
|
||||||
opendir(DIR, "$config_dir/$inc") || die "opendir($config_dir/$inc): $!";
|
opendir(DIR, "$config_dir/$inc") || die "opendir($config_dir/$inc): $!";
|
||||||
my @plugconf = sort grep { -f $_ } map { "$config_dir/$inc/$_" } grep { !/^\./ } readdir(DIR);
|
my @plugconf = sort grep { -f $_ } map { "$config_dir/$inc/$_" } grep { !/^\./ } readdir(DIR);
|
||||||
closedir(DIR);
|
closedir(DIR);
|
||||||
foreach my $f (@plugconf) {
|
foreach my $f (@plugconf) {
|
||||||
$self->_load_plugins($dir, $self->_config_from_file($f, "plugins"));
|
push @ret, $self->_load_plugins($dir, $self->_config_from_file($f, "plugins"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif (-f "$config_dir/$inc") {
|
elsif (-f "$config_dir/$inc") {
|
||||||
$self->log(LOGDEBUG, "Loading include file: $config_dir/$inc");
|
$self->log(LOGDEBUG, "Loading include file: $config_dir/$inc");
|
||||||
$self->_load_plugins($dir, $self->_config_from_file("$config_dir/$inc", "plugins"));
|
push @ret, $self->_load_plugins($dir, $self->_config_from_file("$config_dir/$inc", "plugins"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->log(LOGCRIT, "CRITICAL PLUGIN CONFIG ERROR: Include $config_dir/$inc not found");
|
$self->log(LOGCRIT, "CRITICAL PLUGIN CONFIG ERROR: Include $config_dir/$inc not found");
|
||||||
@ -209,13 +230,16 @@ sub _load_plugins {
|
|||||||
my $package = "Qpsmtpd::Plugin::$plugin_name";
|
my $package = "Qpsmtpd::Plugin::$plugin_name";
|
||||||
|
|
||||||
# don't reload plugins if they are already loaded
|
# don't reload plugins if they are already loaded
|
||||||
_compile($plugin_name, $package, "$dir/$plugin") unless
|
$self->_compile($plugin_name, $package, "$dir/$plugin") unless
|
||||||
defined &{"${package}::register"};
|
defined &{"${package}::register"};
|
||||||
|
|
||||||
my $plug = $package->new();
|
my $plug = $package->new();
|
||||||
|
push @ret, $plug;
|
||||||
$plug->_register($self, @args);
|
$plug->_register($self, @args);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return @ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub transaction {
|
sub transaction {
|
||||||
|
@ -4,6 +4,7 @@ use Carp qw(croak);
|
|||||||
use base qw(Qpsmtpd::SMTP);
|
use base qw(Qpsmtpd::SMTP);
|
||||||
use Test::More;
|
use Test::More;
|
||||||
use Qpsmtpd::Constants;
|
use Qpsmtpd::Constants;
|
||||||
|
use Test::Qpsmtpd::Plugin;
|
||||||
|
|
||||||
sub new_conn {
|
sub new_conn {
|
||||||
ok(my $smtpd = __PACKAGE__->new(), "new");
|
ok(my $smtpd = __PACKAGE__->new(), "new");
|
||||||
@ -65,9 +66,46 @@ sub input {
|
|||||||
alarm $timeout;
|
alarm $timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub config_dir {
|
||||||
|
'./config';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub plugin_dir {
|
||||||
|
'./plugins';
|
||||||
|
}
|
||||||
|
|
||||||
|
sub log {
|
||||||
|
my ($self, $trace, @log) = @_;
|
||||||
|
my $level = Qpsmtpd::TRACE_LEVEL();
|
||||||
|
$level = $self->init_logger unless defined $level;
|
||||||
|
diag(join(" ", $$, @log)) if $trace <= $level;
|
||||||
|
}
|
||||||
|
|
||||||
# sub run
|
# sub run
|
||||||
# sub disconnect
|
# sub disconnect
|
||||||
|
|
||||||
|
sub run_plugin_tests {
|
||||||
|
my $self = shift;
|
||||||
|
$self->{_test_mode} = 1;
|
||||||
|
my @plugins = $self->load_plugins();
|
||||||
|
# First count test number
|
||||||
|
my $num_tests = 0;
|
||||||
|
foreach my $plugin (@plugins) {
|
||||||
|
$plugin->register_tests();
|
||||||
|
$num_tests += $plugin->total_tests();
|
||||||
|
}
|
||||||
|
|
||||||
|
require Test::Builder;
|
||||||
|
my $Test = Test::Builder->new();
|
||||||
|
|
||||||
|
$Test->plan( tests => $num_tests );
|
||||||
|
|
||||||
|
# Now run them
|
||||||
|
|
||||||
|
foreach my $plugin (@plugins) {
|
||||||
|
$plugin->run_tests();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
|
41
t/Test/Qpsmtpd/Plugin.pm
Normal file
41
t/Test/Qpsmtpd/Plugin.pm
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# $Id$
|
||||||
|
|
||||||
|
package Test::Qpsmtpd::Plugin;
|
||||||
|
1;
|
||||||
|
|
||||||
|
# Additional plugin methods used during testing
|
||||||
|
package Qpsmtpd::Plugin;
|
||||||
|
|
||||||
|
use Test::More;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
sub register_tests {
|
||||||
|
# Virtual base method - implement in plugin
|
||||||
|
}
|
||||||
|
|
||||||
|
sub register_test {
|
||||||
|
my ($plugin, $test, $num_tests) = @_;
|
||||||
|
$num_tests = 1 unless defined($num_tests);
|
||||||
|
# print STDERR "Registering test $test ($num_tests)\n";
|
||||||
|
push @{$plugin->{_tests}}, { name => $test, num => $num_tests };
|
||||||
|
}
|
||||||
|
|
||||||
|
sub total_tests {
|
||||||
|
my ($plugin) = @_;
|
||||||
|
my $total = 0;
|
||||||
|
foreach my $t (@{$plugin->{_tests}}) {
|
||||||
|
$total += $t->{num};
|
||||||
|
}
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub run_tests {
|
||||||
|
my ($plugin) = @_;
|
||||||
|
foreach my $t (@{$plugin->{_tests}}) {
|
||||||
|
my $method = $t->{name};
|
||||||
|
diag "Running $method tests for plugin " . $plugin->plugin_name;
|
||||||
|
$plugin->$method();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
10
t/plugin_tests.t
Normal file
10
t/plugin_tests.t
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use lib 't';
|
||||||
|
use Test::Qpsmtpd;
|
||||||
|
|
||||||
|
my $qp = Test::Qpsmtpd->new();
|
||||||
|
|
||||||
|
$qp->run_plugin_tests();
|
||||||
|
|
9
t/plugin_tests/check_badrcptto
Normal file
9
t/plugin_tests/check_badrcptto
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
sub register_tests {
|
||||||
|
my $self = shift;
|
||||||
|
$self->register_test("foo", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub foo {
|
||||||
|
ok(1);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user