diff --git a/lib/Zonemaster/Engine/Test.pm b/lib/Zonemaster/Engine/Test.pm index 967994a96..fcee53131 100644 --- a/lib/Zonemaster/Engine/Test.pm +++ b/lib/Zonemaster/Engine/Test.pm @@ -27,6 +27,8 @@ use File::ShareDir qw[dist_file]; use File::Slurp qw[read_file]; use Scalar::Util qw[blessed]; use POSIX qw[strftime]; +use Carp; +use List::MoreUtils qw(any); =head1 NAME @@ -136,6 +138,53 @@ sub _log_versions { =over +=item install() + + Zonemaster::Engine::Test->install_custom_test_module('My::Module'); + +Installs a custom module outside of the C namespace. +This module must be a modules that implements the same interface as the modules +in that namespace (ie. C C etc). + +The effective profile will be updated to include all test cases from the custom +module. + +=back + +=cut + +sub install_custom_test_module { + my ( $class, $module ) = @_; + + $module->import(); + + # get list of cases to be added + my @cases = keys( %{$module->metadata} ); + + my $profile = Zonemaster::Engine::Profile->effective; + + # check there isn't a collission between one of the new cases and an + # existing case + foreach my $case ( @cases ) { + if ( any { $_ eq $case } @{$profile->{profile}->{test_cases}} ) { + carp sprintf "case '%s' already exists", $case ; + return undef; + } + } + + # add the module + push @all_test_modules, $module; + + # append cases to the profile + push @{$profile->{profile}->{test_cases}}, @cases; + + return 1; +} + +=pod + +=over + =item modules() my @modules_array = modules(); @@ -197,7 +246,7 @@ sub run_all_for { if ( Zonemaster::Engine::Test::Basic->can_continue( $zone, @results ) and Zonemaster::Engine->can_continue() ) { foreach my $mod ( __PACKAGE__->modules ) { - my $module = "Zonemaster::Engine::Test::$mod"; + my $module = ( $mod =~ /::/ ? $mod : "Zonemaster::Engine::Test::$mod" ); info( MODULE_VERSION => { module => $module, version => $module->version } ); my @res = eval { $module->all( $zone ) }; if ( $@ ) { @@ -259,7 +308,7 @@ sub run_module { if ( Zonemaster::Engine->can_continue() ) { if ( $module ) { - my $m = "Zonemaster::Engine::Test::$module"; + my $m = ( $module =~ /::/ ? $module : "Zonemaster::Engine::Test::$module" ); info( MODULE_VERSION => { module => $m, version => $m->version } ); push @res, eval { $m->all( $zone ) }; if ( $@ ) { @@ -323,7 +372,7 @@ sub run_one { if ( Zonemaster::Engine->can_continue() ) { if ( $module ) { - my $m = "Zonemaster::Engine::Test::$module"; + my $m = ( $module =~ /::/ ? $module : "Zonemaster::Engine::Test::$module" ); if ( $m->metadata->{$test} and Zonemaster::Engine::Util::should_run_test( $test ) ) { info( MODULE_VERSION => { module => $m, version => $m->version } ); push @res, eval { $m->$test( $zone ) }; diff --git a/t/custom.module b/t/custom.module new file mode 100755 index 000000000..fabb8737c --- /dev/null +++ b/t/custom.module @@ -0,0 +1,63 @@ +package My::Module; +use strict; +use vars qw($VERSION %TAG_DESCRIPTIONS); +use Zonemaster::Engine::Util; +use Locale::TextDomain qw(Zonemaster-Engine); +use warnings; + +$VERSION = q{1.0.0}; + +%TAG_DESCRIPTIONS = ( + TEST_CASE_START => sub { __x('TEST_CASE_START {testcase}.', @_) }, + TEST_CASE_END => sub { __x('TEST_CASE_END {testcase}.', @_) }, + THIS_IS_A_TEST => sub { __x('THIS IS A TEST.', @_) }, +); + +sub version { + return $VERSION; +} + +sub metadata { + my ( $class ) = @_; + return { + test01 => [qw( + TEST_CASE_START + TEST_CASE_END + THIS_IS_A_TEST + )], + }; +} + +sub tag_descriptions { + return \%TAG_DESCRIPTIONS; +} + +sub all { + my ( $class, $zone ) = @_; + + my @results; + + push @results, $class->test01( $zone ) if Zonemaster::Engine::Util::should_run_test(q{test01}); + + return @results; +} + +sub test01 { + my ( $class, $zone ) = @_; + + my @results; + + push(@results, _emit_log(TEST_CASE_START => {testcase => q{test01}})); + + push(@results, _emit_log(THIS_IS_A_TEST => {})); + + push(@results, _emit_log(TEST_CASE_END => {testcase => q{test01}})); + + return @results; +} + +sub _emit_log { + return Zonemaster::Engine->logger->add(@_[0..1], __PACKAGE__); +} + +1; diff --git a/t/custom.t b/t/custom.t new file mode 100644 index 000000000..d60f78ca1 --- /dev/null +++ b/t/custom.t @@ -0,0 +1,35 @@ +use Cwd qw(abs_path); +use List::Util qw(any); +use File::Spec; +use File::Basename qw(dirname); +use Test::More; +use strict; +use warnings; + +BEGIN { + use_ok( q{Zonemaster::Engine} ); + use_ok( q{Zonemaster::Engine::Nameserver} ); +} + +my $module = 'My::Module'; + +my $modfile = abs_path( File::Spec->catfile( + dirname( __FILE__ ), + 'custom.module' +) ); + +require_ok $modfile; + +$module->import(); + +Zonemaster::Engine::Test->install_custom_test_module( $module ); + +ok any { $_ eq $module } Zonemaster::Engine::Test->modules(); + +my @results = Zonemaster::Engine->test_module( $module, q{example.com} ); + +ok scalar @results > 0; + +ok scalar ( grep { 'THIS_IS_A_TEST' eq $_->tag } @results ) > 0; + +done_testing;