#!/usr/bin/perl -w
use lib qw(t/lib);
use Test::More tests => 59;
use Config;
my $has_version_pm = eval 'use version; 1';
my $version_pm_VERSION = $has_version_pm ? 'version'->VERSION : 0;
my $Mod_Info_VERSION = '0.33';
# 0.280 vith version.pm, 0.28 without, except for development versions
my $Mod_Info_Pack_VERSION = !$has_version_pm ? '0.33' : # 0.3101
$has_version_pm && $version_pm_VERSION > '0.72' ? '0.33' : # 0.3101
'0.33'; # 0.310001
my @old5lib = defined $ENV{PERL5LIB} ? ($ENV{PERL5LIB}) : ();
$ENV{PERL5LIB} = join $Config{path_sep}, 'blib/lib', @old5lib;
use_ok('Module::Info');
my @expected_subs = qw(
new_from_file
new_from_module
new_from_loaded
all_installed
_find_all_installed
name
version
inc_dir
file
is_core
packages_inside
package_versions
modules_required
modules_used
_file2mod
subroutines
superclasses
die_on_compilation_error
_call_B
_get_extra_arguments
subroutines_called
dynamic_method_calls
safe
AUTOLOAD
use_version
);
my @unsafe_subs = qw(
_eval
_call_perl
_is_win95
_is_macos_classic
);
my @safe_subs = qw(
_eval
_call_perl
_create_compartment
);
can_ok('Module::Info', @expected_subs);
my $mod_info = Module::Info->new_from_file('lib/Module/Info.pm');
isa_ok($mod_info, 'Module::Info', 'new_from_file');
ok( !$mod_info->name, ' has no name' );
$mod_info->name('Module::Info');
ok( $mod_info->name, ' name set' );
is( $mod_info->version, $Mod_Info_VERSION, ' version()' );
ok( !$mod_info->inc_dir, ' has no inc_dir' );
is( $mod_info->file, File::Spec->rel2abs('lib/Module/Info.pm'),
' file()');
ok( !$mod_info->is_core, ' not a core module' );
SKIP: {
skip "Only works on 5.6.1 and up.", 8 unless $] >= 5.006001;
@expected_subs = ( ( map "Module::Info::$_", @expected_subs ),
( map "Module::Info::Safe::$_", @safe_subs ),
( map "Module::Info::Unsafe::$_", @unsafe_subs ) );
my @packages = $mod_info->packages_inside;
is( @packages, 3, 'Found three packages inside' );
is_deeply( [sort @packages],
[sort qw(Module::Info Module::Info::Safe Module::Info::Unsafe)],
' and its what we want' );
my %versions = $mod_info->package_versions;
is( keys %versions, 3, '1 package with package_versions()');
is( $versions{Module::Info}, $Mod_Info_Pack_VERSION, 'version is correct');
my %subs = $mod_info->subroutines;
is( keys %subs, @expected_subs, 'Found all the subroutines' );
is_deeply( [sort keys %subs],
[sort @expected_subs], ' names' );
my @mods = $mod_info->modules_used;
my @expected = qw(strict File::Spec Config
Carp IPC::Open3 vars Safe);
push @expected, 'Exporter' if grep /^Exporter$/, @mods;
# many old versions of these modules loaded the Exporter:
is( @mods, @expected, 'Found all modules used' );
is_deeply( [sort @mods], [sort @expected],
' the right ones' );
}
$mod_info = Module::Info->new_from_module('Module::Info');
isa_ok($mod_info, 'Module::Info', 'new_from_module');
is( $mod_info->name, 'Module::Info', ' name()' );
is( $mod_info->version, $Mod_Info_VERSION, ' version()' );
is( $mod_info->inc_dir, File::Spec->rel2abs('blib/lib'),
' inc_dir' );
is( $mod_info->file, File::Spec->rel2abs('blib/lib/Module/Info.pm'),
' file()');
ok( !$mod_info->is_core, ' not a core module' );
# Grab the core version of Text::Soundex and hope it hasn't been
# deleted.
@core_inc = map { File::Spec->canonpath($_) }
($Config{installarchlib}, $Config{installprivlib},
$Config{archlib}, $Config{privlib});
$mod_info = Module::Info->new_from_module('Text::Soundex', @core_inc);
if( $mod_info ) {
is( $mod_info->name, 'Text::Soundex', ' name()' );
# dunno what the version will be, 5.004's had none.
ok( grep($mod_info->inc_dir eq $_, @core_inc), ' inc_dir()' );
is( $mod_info->file,
File::Spec->catfile( $mod_info->inc_dir, 'Text', 'Soundex.pm' ),
' file()');
ok( $mod_info->is_core, ' core module' );
} else {
$mod_info = Module::Info->new_from_module('Text::Soundex');
ok( $mod_info, 'could load Text::Soundex' );
ok( $mod_info, 'could load Text::Soundex' );
ok( $mod_info, 'could load Text::Soundex' );
ok( $mod_info, 'could load Text::Soundex' );
}
$mod_info = Module::Info->new_from_loaded('Module::Info');
isa_ok($mod_info, 'Module::Info', 'new_from_module');
is( $mod_info->name, 'Module::Info', ' name()' );
is( $mod_info->version, $Mod_Info_VERSION, ' version()' );
is( $mod_info->inc_dir, File::Spec->rel2abs('blib/lib'),
' inc_dir' );
is( $mod_info->file, File::Spec->rel2abs('blib/lib/Module/Info.pm'),
' file()');
ok( !$mod_info->is_core, ' not a core module' );
@modules = Module::Info->all_installed('Module::Info');
ok( @modules, 'all_installed() returned something' );
ok( !(grep { !defined $_ || !$_->isa('Module::Info') } @modules),
" they're all Module::Info objects"
);
# I have no idea how many I'm going to get, so I'll only play with the
# first one. It's the current one.
$mod_info = $modules[0];
isa_ok($mod_info, 'Module::Info', 'all_installed');
is( $mod_info->name, 'Module::Info', ' name()' );
is( $mod_info->version, $Mod_Info_VERSION, ' version()' );
ok( !$mod_info->is_core, ' not a core module' );
# Ensure that code refs in @INC are skipped.
my @mods = Module::Info->all_installed('Module::Info', (@INC, sub { die }));
ok( @modules, 'all_installed() returned something' );
ok( !(grep { !defined $_ || !$_->isa('Module::Info') } @modules),
" they're all Module::Info objects"
);
$mod_info = Module::Info->new_from_loaded('this_module_does_not_exist');
is( $mod_info, undef, 'new_from_loaded' );
SKIP: {
skip "Only works on 5.6.1 and up.", 17 unless $] >= 5.006001;
my $module = Module::Info->new_from_file('t/lib/Foo.pm');
my @packages = $module->packages_inside;
is( @packages, 2, 'Found two packages inside' );
ok( eq_set(\@packages, [qw(Foo Bar)]), " they're right" );
my %versions = $module->package_versions;
is( keys %versions, 2, '2 packages with package_versions()');
is( $versions{Foo}, '7.254', 'version is correct');
is( $versions{Bar}, undef, 'no version present');
my %subs = $module->subroutines;
is( keys %subs, 2, 'Found two subroutine' );
ok( exists $subs{'Foo::wibble'}, ' its right' );
my($start, $end) = @{$subs{'Foo::wibble'}}{qw(start end)};
print "# start $start, end $end\n";
is( $start, 21, ' start line' );
is( $end, 22, ' end line' );
my @mods = $module->modules_used;
is( @mods, 8, 'modules_used' );
is_deeply( [sort @mods],
[sort qw(strict vars Carp Exporter t/lib/Bar.pm t/lib/NotHere.pm
t/lib/Foo.pm lib)] );
$module->name('Foo');
my @isa = $module->superclasses;
is( @isa, 3, 'isa' );
is_deeply( [sort @isa], [sort qw(This That What::Ever)] );
my @calls = sort { $a->{line} <=> $b->{line} }
$module->subroutines_called;
my $startline = 25;
my @expected_calls = ({
line => $startline,
class => undef,
type => 'function',
name => 'wibble'
},
{
line => $startline + 1,
class => undef,
type => 'symbolic function',
name => undef,
},
{
line => $startline + 2,
class => 'Foo',
type => 'class method',
name => 'wibble',
},
{
line => $startline + 3,
class => undef,
type => 'object method',
name => 'wibble',
},
{
line => $startline + 5,
class => undef,
type => 'object method',
name => 'wibble',
},
{
line => $startline + 7,
class => 'Foo',
type => 'dynamic class method',
name => undef,
},
{
line => $startline + 8,
class => undef,
type => 'dynamic object method',
name => undef,
},
{
line => $startline + 9,
class => undef,
type => 'dynamic object method',
name => undef,
},
{
line => $startline + 10,
class => 'Foo',
type => 'dynamic class method',
name => undef,
},
{
line => $startline + 14,
class => undef,
type => 'object method',
name => 'wibble'
},
{
line => $startline + 17,
class => undef,
type => 'function',
name => 'wibble'
},
{
line => $startline + 30,
class => undef,
type => 'function',
name => 'croak'
},
{
line => $startline + 33,
class => undef,
type => 'function',
name => 'wibble'
},
);
is_deeply(\@calls, \@expected_calls, 'subroutines_called');
is_deeply([$module->dynamic_method_calls],
[grep $_->{type} =~ /dynamic/, @expected_calls]);
$module = Module::Info->new_from_file('t/lib/Bar.pm');
@mods = $module->modules_used;
is( @mods, 3, 'modules_used with complex BEGIN block' );
is_deeply( sort @mods,
(sort qw(Cwd Carp strict)) );
}