package tests::PluginManagerTest;
use strict;
use base qw/ Lire::Test::TestCase /;
use Lire::PluginManager;
use Lire::DlfAnalyser;
use Lire::Utils qw/tempdir create_file /;
use File::Path qw/mkpath rmtree/;
use File::Basename;
use Cwd qw/realpath/;
use Lire::Test::Mock;
sub set_up {
my $self = $_[0];
$self->SUPER::set_up();
$self->{'_old_mgr'} = $Lire::PluginManager::instance;
$Lire::PluginManager::instance = $self->{'mgr'}=new Lire::PluginManager();
$self->{'tmpdir'} = tempdir( "PluginManager_XXXXXX", 'CLEANUP' => 1 );
return;
}
sub tear_down {
my $self = $_[0];
$self->SUPER::tear_down();
$Lire::PluginManager::instance = $self->{'_old_mgr'};
rmtree( $self->{'tmpdir'} );
return;
}
sub test_instance {
my $self = $_[0];
$self->assert_str_equals( $self->{'mgr'},
Lire::PluginManager->instance() );
}
sub test_check_type {
my $self = $_[0];
local %Lire::PluginManager::plugin_types =
( 'a_type' => 'Package', 'b_type' => 'AnotherPackage' );
$self->assert( Lire::PluginManager::check_type( 'a_type' ) );
$self->assert_dies( qr/missing 'type' parameter/,
sub { Lire::PluginManager::check_type( undef ) } );
$self->assert_dies( qr/'type' parameter should be one of 'a_type' or 'b_type': 'bad'/,
sub { Lire::PluginManager::check_type( 'bad' ) } );
}
sub test_plugin_names {
my $self = $_[0];
my $mgr = $self->{'mgr'};
%{$mgr->{'output_format'}} = ( 'test1' => undef, 'test2' => undef );
$self->assert_deep_equals( [ 'test1', 'test2' ],
[ sort @{ $mgr->plugin_names( 'output_format' )} ] );
$self->assert_deep_equals( [ 'test1', 'test2' ],
[ sort @{ Lire::PluginManager->plugin_names( 'output_format' )} ] );
}
sub test_plugins {
my $self = $_[0];
my $mgr = $self->{'mgr'};
%{$mgr->{'output_format'}} = ( 'test1' => 1, 'test2' => 2 );
$self->assert_deep_equals( [ 1, 2 ],
[ sort @{ $mgr->plugins( 'output_format' )} ] );
$self->assert_deep_equals( [ 1, 2 ],
[ sort @{ Lire::PluginManager->plugins( 'output_format' )} ] );
}
sub test_has_plugin {
my $self = $_[0];
my $mgr = $self->{'mgr'};
%{$mgr->{'output_format'}} = ( 'test1' => 1, 'test2' => 2 );
$self->assert( ! $mgr->has_plugin( 'dlf_converter', 'not_there' ) );
$self->assert( Lire::PluginManager->has_plugin( 'output_format', 'test1' ) );
}
sub test_get_plugin {
my $self = $_[0];
my $mgr = $self->{'mgr'};
%{$mgr->{'output_format'}} = ( 'test1' => 1, 'test2' => 2 );
$self->assert_num_equals( 1, $mgr->get_plugin( 'output_format', 'test1' ) );
$self->assert_num_equals( 2, Lire::PluginManager->get_plugin( 'output_format', 'test2' ) );
$self->assert_dies( qr/no 'dlf_converter' plugin 'test3' registered/,
sub { $mgr->get_plugin( 'dlf_converter', 'test3' ) } );
}
sub test_register_plugin {
my $self = $_[0];
my $mgr = $self->{'mgr'};
$mgr->{'dlf_converter'}{'test'} = 1;
my $plugin = new Lire::Test::Mock( 'Lire::Plugin', 'name' => 'test',
'type' => 'dlf_converter' );
$self->assert_dies( qr/'dlf_converter' plugin should be a 'Lire::DlfConverter' instance: 'Class::Inner/,
sub { $mgr->register_plugin( $plugin ) } );
my $test = new Lire::Test::Mock( 'Lire::DlfConverter', 'name' => 'test',
'type' => 'dlf_converter' );
$self->assert_dies( qr/there is already a 'dlf_converter' plugin registered under name 'test'/,
sub { $mgr->register_plugin( $test ) } );
my $unknown_type = new Lire::Test::Mock( 'Lire::DlfConverter',
'name' => 'test1',
'type' => 'bad_type' );
$self->assert_dies( qr/plugin 'test1' has an unknown type: 'bad_type'/,
sub { $mgr->register_plugin( $unknown_type ) } );
my $test2 = new Lire::Test::Mock( 'Lire::DlfConverter', 'name' => 'test2',
'type' => 'dlf_converter' );
Lire::PluginManager->register_plugin( $test2 );
$self->assert_str_equals( $test2, $mgr->{'dlf_converter'}{'test2'} );
}
sub test_unregister_plugin {
my $self = $_[0];
my $mgr = $self->{'mgr'};
%{$mgr->{'output_format'}} = ( 'test1' => 1, 'test2' => 2 );
$mgr->unregister_plugin( 'output_format', 'test1' );
$self->assert_null( $mgr->{'output_format'}{'test1'} );
Lire::PluginManager->unregister_plugin( 'output_format', 'test2' );
$self->assert_null( $mgr->{'output_format'}{'test2'} );
$self->assert_dies( qr/no 'dlf_converter' plugin 'test3' registered/,
sub { $mgr->unregister_plugin( 'dlf_converter', 'test3' ) } );
}
sub test_register_default_plugins {
my $self = $_[0];
mkpath( [ $self->{'tmpdir'} . "/dir1",
$self->{'tmpdir'} . "/dir2",
], 0, 0755 ) == 2
or $self->error( "mkpath failed: $!\n" );
create_file( "$self->{'tmpdir'}/dir1/failing", 'die "error here\n"' );
create_file( "$self->{'tmpdir'}/dir2/a_plugin", <<EOF );
package converter;
use base qw/Lire::DlfConverter/;
use Lire::PluginManager;
sub name { 'test' }
sub type { 'dlf_converter' }
Lire::PluginManager->register_plugin( bless {}, 'converter' );
return;
EOF
my @warn = ();
local $SIG{'__WARN__'} = sub { push @warn, join( "", @_ )};
$self->{'cfg'}{'plugins_init_path'} = [ "$self->{'tmpdir'}/dir1",
"$self->{'tmpdir'}/dir2" ];
no warnings 'redefine';
local *Lire::PluginManager::_load_dlf_adapters =
sub { $_[0]{'_load_dlf_adapters'} = 1 };
local *Lire::PluginManager::_create_old_dlf_adapters =
sub { $_[0]{'_create_old_dlf_adapters'} = 1 };
Lire::PluginManager->register_default_plugins();
$self->annotate( @warn );
$self->assert_isa( 'Lire::DlfConverter',
$self->{'mgr'}{'dlf_converter'}{'test'} );
$self->assert_num_equals( 1, scalar @warn );
$self->assert_matches( qr!error in initialiser '$self->{'tmpdir'}/dir1/failing': error here!,
$warn[0] );
$self->assert_num_equals( 1, $self->{'mgr'}{'_load_dlf_adapters'} );
$self->assert_num_equals( 1, $self->{'mgr'}{'_create_old_dlf_adapters'} );
}
sub test_init_files {
my $self = $_[0];
my $dirs = [ $self->{'tmpdir'} . "/dir1",
$self->{'tmpdir'} . "/dir2",
$self->{'tmpdir'} . "/dir1",
];
mkpath( $dirs, 0, 0755 ) == 2
or $self->error( "mkpath failed: $!\n" );
my @files = ( $self->{'tmpdir'} . "/dir1/test",
$self->{'tmpdir'} . "/dir1/test3",
$self->{'tmpdir'} . "/dir2/test2",
);
foreach my $f ( @files ) {
create_file( $f );
}
$self->assert_deep_equals( \@files,
Lire::PluginManager->_init_files( $dirs ) );
}
sub test_load_dlf_adapters {
my $self = $_[0];
my $dirs = [ $self->{'tmpdir'} . "/dlf_converters1",
$self->{'tmpdir'} . "/dlf_converters2" ];
mkpath( $dirs, 0, 0755 ) == 2
or $self->error( "mkpath failed: $!\n" );
$self->{'cfg'}{'lr_converters_init_path'} = $dirs;
create_file( $self->{'tmpdir'} . "/dlf_converters1/test1" );
chmod 0000, $self->{'tmpdir'} . "/dlf_converters1/test1"
or $self->error( "chmod failed: $!\n" );
create_file( $self->{'tmpdir'} . "/dlf_converters1/test2", <<'EOF' );
use strict;
$x = 1;
EOF
create_file( $self->{'tmpdir'} . "/dlf_converters1/test3", <<'EOF' );
package Converter;
use base qw/Lire::DlfConverter/;
sub new {
bless { 'name' => $_[1] }, $_[0];
}
sub name { $_[0]{'name'} };
return ( new Converter( 'test1' ), new Converter( 'test2' ) );
EOF
create_file( $self->{'tmpdir'} . "/dlf_converters2/test4", <<'EOF' );
return bless {}, "Test";
EOF
my @msg = ();
local $SIG{'__WARN__'} = sub { push @msg, join "", @_;
$self->annotate( $msg[-1] ); };
$self->{'mgr'}->_load_dlf_adapters();
# Reset the permission, so it can be deleted with rmtree()
chmod 0644, $self->{'tmpdir'} . "/dlf_converters1/test1"
or $self->error( "chmod failed: $!\n" );
$self->assert( @msg == 3, "expected 3 warnings" );
$self->assert_matches( qr/error reading DLF converter/, $msg[0] );
$self->assert_matches( qr/error while running initializer/, $msg[1] );
$self->assert_matches( qr/didn't return a Lire::DlfConverter/, $msg[2] );
$self->assert_isa( 'Converter', $self->{'mgr'}{'dlf_converter'}{'test1'} );
$self->assert_isa( 'Converter', $self->{'mgr'}{'dlf_converter'}{'test2'} );
}
sub test_parse_map_file {
my $self = $_[0];
my $address_file = $self->{'tmpdir'} . "/address.cf";
create_file ( $address_file, <<EOF );
# A comment
service superservice # with comment
service1 schema1
line with an error
# More comment
EOF
my @msg = ();
local $SIG{'__WARN__'} = sub { push @msg, join "", @_ };
my $services = $self->{'mgr'}->_parse_old_map_file( $address_file );
$self->annotate( join "\n", @msg );
$self->assert( @msg == 1, "expected one warning, got " . scalar @msg );
$self->assert_matches( qr/can't parse line 5/, $msg[0] );
$self->assert_deep_equals( { 'service' => 'superservice',
'service1' => 'schema1',
}, $services );
}
sub test_create_old_dlf_adapters {
my $self = $_[0];
my $address_file = $self->{'tmpdir'} . "/address.cfg";
$self->{'cfg'}{'lr_old_convertors_dir'} = $self->{'tmpdir'};
$self->{'cfg'}{'lr_old_address_file'} = $address_file;
create_file( "$self->{'tmpdir'}/service12dlf" );
create_file( "$self->{'tmpdir'}/service22dlf" );
create_file( "$self->{'tmpdir'}/service42dlf" );
chmod( 0755, map { "$self->{'tmpdir'}/" . $_ . "2dlf" } qw/service1 service2/) == 2
or $self->error( "chmod failed" );
create_file( $address_file, <<EOF );
service1 test # Good
service2 unknown # Bad superservice
service3 test # service32dlf doesn't exist
service4 test # not executable
EOF
$self->{'cfg'}{'lr_schemas_path'} = [ realpath(dirname( __FILE__ )) . "/schemas" ];
my @msg = ();
local $SIG{'__WARN__'} = sub { my $m = join "", @_;
$self->annotate( $m);
push @msg, $m; };
$self->{'mgr'}->_create_old_dlf_adapters();
@msg = sort @msg;
my @warnings = ( qr/can't find executable service32dlf/,
qr/can't find executable service42dlf/,
qr/invalid superservice/
);
$self->assert_num_equals( scalar @msg, scalar @warnings );
for ( my $i=0; $i < @warnings; $i++ ) {
$self->assert_matches( $warnings[$i], $msg[$i] );
}
my @converters = ( "service1" );
$self->assert_isa( 'Lire::OldDlfAdapter',
$self->{'mgr'}{'dlf_converter'}{'service1'} );
}
sub set_up_fake_analysers {
my $self = $_[0];
$self->{'mgr'}{'dlf_analyser'}{'extended'} =
new Lire::Test::Mock( 'Lire::DlfAnalyser', 'name' => 'extended',
'src_schema' => 'test',
'dst_schema' => 'test-extended' );
$self->{'mgr'}{'dlf_analyser'}{'extended2'} =
new Lire::Test::Mock( 'Lire::DlfAnalyser', 'name' => 'extended2',
'src_schema' => 'test',
'dst_schema' => 'test-extended', );
$self->{'mgr'}{'dlf_analyser'}{'derived'} =
new Lire::Test::Mock( 'Lire::DlfAnalyser',
'name' => 'derived',
'src_schema' => 'test-derived',
'dst_schema' => 'another-schema' );
return;
}
sub test_analysers_by_src {
my $self = $_[0];
$self->set_up_fake_analysers();
$self->assert_deep_equals( [], $self->{'mgr'}->analysers_by_src( 'wawa' ));
my @analysers = sort { $a->name() cmp $b->name() }
@{$self->{'mgr'}->analysers_by_src( 'test' )};
$self->assert_deep_equals( [ $self->{'mgr'}{'dlf_analyser'}{'extended'},
$self->{'mgr'}{'dlf_analyser'}{'extended2'}],
\@analysers );
}
sub test_analysers_by_dst {
my $self = $_[0];
$self->set_up_fake_analysers();
$self->assert_deep_equals( [], $self->{'mgr'}->analysers_by_dst( 'wawa' ));
my @analysers = sort { $a->name() cmp $b->name() }
@{$self->{'mgr'}->analysers_by_dst( 'test-extended' )};
$self->assert_deep_equals( [ $self->{'mgr'}{'dlf_analyser'}{'extended'},
$self->{'mgr'}{'dlf_analyser'}{'extended2'}],
\@analysers );
}
1;
syntax highlighted by Code2HTML, v. 0.9.1