X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2Fmetadata.t;h=f21465175f9e450dc1202ea7cd4a50d1d527d1da;hb=e6454d7f17b0f2b4d1892c8ad4e008e7f340a1e0;hp=942cc622aa512fa4d2db20aa9d92cd801c0fd05c;hpb=81ce8c826e1a168a78e7ab6be41ecddd3df38199;p=p5sagit%2FModule-Metadata.git diff --git a/t/metadata.t b/t/metadata.t index 942cc62..f214651 100644 --- a/t/metadata.t +++ b/t/metadata.t @@ -3,14 +3,19 @@ # vim:ts=8:sw=2:et:sta:sts=2 use strict; -use lib 't/lib'; +use warnings; +use Test::More; use IO::File; -use MBTest; +use File::Spec; +use File::Temp; +use File::Basename; +use Cwd (); +use File::Path; my $undef; # parse various module $VERSION lines -# these will be reversed later to create %modules +# format: expected version => code snippet my @modules = ( $undef => <<'---', # no $VERSION line package Simple; @@ -209,70 +214,175 @@ package Simple v1.2.3_4 { 1; } --- + '0' => <<'---', # set from separately-initialised variable +package Simple; + our $CVSVERSION = '$Revision: 1.7 $'; + our ($VERSION) = ($CVSVERSION =~ /(\d+\.\d+)/); +} +--- +); + +# format: expected package name => code snippet +my @pkg_names = ( + [ 'Simple' ] => <<'---', # package NAME +package Simple; +--- + [ 'Simple::Edward' ] => <<'---', # package NAME::SUBNAME +package Simple::Edward; +--- + [ 'Simple::Edward::' ] => <<'---', # package NAME::SUBNAME:: +package Simple::Edward::; +--- + [ "Simple'Edward" ] => <<'---', # package NAME'SUBNAME +package Simple'Edward; +--- + [ "Simple'Edward::" ] => <<'---', # package NAME'SUBNAME:: +package Simple'Edward::; +--- + [ 'Simple::::Edward' ] => <<'---', # package NAME::::SUBNAME +package Simple::::Edward; +--- + [ '::Simple::Edward' ] => <<'---', # package ::NAME::SUBNAME +package ::Simple::Edward; +--- + [ 'main' ] => <<'---', # package NAME:SUBNAME (fail) +package Simple:Edward; +--- + [ 'main' ] => <<'---', # package NAME' (fail) +package Simple'; +--- + [ 'main' ] => <<'---', # package NAME::SUBNAME' (fail) +package Simple::Edward'; +--- + [ 'main' ] => <<'---', # package NAME''SUBNAME (fail) +package Simple''Edward; +--- + [ 'main' ] => <<'---', # package NAME-SUBNAME (fail) +package Simple-Edward; +--- ); -my %modules = reverse @modules; -plan tests => 52 + 2 * keys( %modules ); +# 2 tests per each pair of @modules, @pkg_names entry +plan tests => 63 + ( @modules ) + ( @pkg_names ); require_ok('Module::Metadata'); -# class method C -my $module = Module::Metadata->find_module_by_name( - 'Module::Metadata' ); -ok( -e $module, 'find_module_by_name() succeeds' ); +{ + # class method C + my $module = Module::Metadata->find_module_by_name( + 'Module::Metadata' ); + ok( -e $module, 'find_module_by_name() succeeds' ); +} ######################### -my $tmp = MBTest->tmpdir; - -use DistGen; -my $dist = DistGen->new( dir => $tmp ); -$dist->regen; +BEGIN { + my $cwd = File::Spec->rel2abs(Cwd::cwd); + sub original_cwd { return $cwd } +} -$dist->chdir_in; +# Setup a temp directory +sub tmpdir { + my (@args) = @_; + my $dir = $ENV{PERL_CORE} ? original_cwd : File::Spec->tmpdir; + return File::Temp::tempdir('MMD-XXXXXXXX', CLEANUP => 0, DIR => $dir, @args); +} +my $tmp; +BEGIN { $tmp = tmpdir; diag "using temp dir $tmp"; } -# fail on invalid module name -my $pm_info = Module::Metadata->new_from_module( - 'Foo::Bar', inc => [] ); -ok( !defined( $pm_info ), 'fail if can\'t find module by module name' ); +END { + die "tests failed; leaving temp dir $tmp behind" + if $ENV{AUTHOR_TESTING} and not Test::Builder->new->is_passing; + diag "removing temp dir $tmp"; + chdir original_cwd; + File::Path::remove_tree($tmp); +} +# generates a new distribution: +# files => { relative filename => $content ... } +# returns the name of the distribution (not including version), +# and the absolute path name to the dist. +{ + my $test_num = 0; + sub new_dist { + my %opts = @_; + + my $distname = 'Simple' . $test_num++; + my $distdir = File::Spec->catdir($tmp, $distname); + note "using dist $distname in $distdir"; + + File::Path::mkpath($distdir) or die "failed to create '$distdir'"; + + foreach my $rel_filename (keys %{$opts{files}}) + { + my $abs_filename = File::Spec->catfile($distdir, $rel_filename); + my $dirname = File::Basename::dirname($abs_filename); + unless (-d $dirname) { + File::Path::mkpath($dirname) or die "Can't create '$dirname'"; + } + + note "creating $abs_filename"; + my $fh = IO::File->new(">$abs_filename") or die "Can't write '$abs_filename'\n"; + print $fh $opts{files}{$rel_filename}; + close $fh; + } -# fail on invalid filename -my $file = File::Spec->catfile( 'Foo', 'Bar.pm' ); -$pm_info = Module::Metadata->new_from_file( $file, inc => [] ); -ok( !defined( $pm_info ), 'fail if can\'t find module by file name' ); + chdir $distdir; + return ($distname, $distdir); + } +} +{ + # fail on invalid module name + my $pm_info = Module::Metadata->new_from_module( + 'Foo::Bar', inc => [] ); + ok( !defined( $pm_info ), 'fail if can\'t find module by module name' ); +} -# construct from module filename -$file = File::Spec->catfile( 'lib', split( /::/, $dist->name ) ) . '.pm'; -$pm_info = Module::Metadata->new_from_file( $file ); -ok( defined( $pm_info ), 'new_from_file() succeeds' ); +{ + # fail on invalid filename + my $file = File::Spec->catfile( 'Foo', 'Bar.pm' ); + my $pm_info = Module::Metadata->new_from_file( $file, inc => [] ); + ok( !defined( $pm_info ), 'fail if can\'t find module by file name' ); +} -# construct from filehandle -my $handle = IO::File->new($file); -$pm_info = Module::Metadata->new_from_handle( $handle, $file ); -ok( defined( $pm_info ), 'new_from_handle() succeeds' ); -$pm_info = Module::Metadata->new_from_handle( $handle ); -is( $pm_info, undef, "new_from_handle() without filename returns undef" ); -close($handle); +{ + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => "package Simple;\n" }); + + # construct from module filename + my $pm_info = Module::Metadata->new_from_file( $file ); + ok( defined( $pm_info ), 'new_from_file() succeeds' ); + + # construct from filehandle + my $handle = IO::File->new($file); + $pm_info = Module::Metadata->new_from_handle( $handle, $file ); + ok( defined( $pm_info ), 'new_from_handle() succeeds' ); + $pm_info = Module::Metadata->new_from_handle( $handle ); + is( $pm_info, undef, "new_from_handle() without filename returns undef" ); + close($handle); +} -# construct from module name, using custom include path -$pm_info = Module::Metadata->new_from_module( - $dist->name, inc => [ 'lib', @INC ] ); -ok( defined( $pm_info ), 'new_from_module() succeeds' ); +{ + # construct from module name, using custom include path + my $pm_info = Module::Metadata->new_from_module( + 'Simple', inc => [ 'lib', @INC ] ); + ok( defined( $pm_info ), 'new_from_module() succeeds' ); +} -foreach my $module ( sort keys %modules ) { - my $expected = $modules{$module}; +# iterate through @modules pairwise +my $test_case = 0; +while (++$test_case and my ($expected_version, $code) = splice @modules, 0, 2 ) { SKIP: { skip( "No our() support until perl 5.6", 2 ) - if $] < 5.006 && $module =~ /\bour\b/; + if $] < 5.006 && $code =~ /\bour\b/; skip( "No package NAME VERSION support until perl 5.11.1", 2 ) - if $] < 5.011001 && $module =~ /package\s+[\w\:\']+\s+v?[0-9._]+/; + if $] < 5.011001 && $code =~ /package\s+[\w\:\']+\s+v?[0-9._]+/; - $dist->change_file( 'lib/Simple.pm', $module ); - $dist->regen; + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => $code }); my $warnings = ''; local $SIG{__WARN__} = sub { $warnings .= $_ for @_ }; @@ -281,25 +391,44 @@ foreach my $module ( sort keys %modules ) { # Test::Builder will prematurely numify objects, so use this form my $errs; my $got = $pm_info->version; - if ( defined $expected ) { - ok( $got eq $expected, - "correct module version (expected '$expected')" ) - or $errs++; - } else { - ok( !defined($got), - "correct module version (expected undef)" ) - or $errs++; - } - is( $warnings, '', 'no warnings from parsing' ) or $errs++; - diag "Got: '$got'\nModule contents:\n$module" if $errs; + + is( + $got, + $expected_version, + "case $test_case: correct module version (" + . (defined $expected_version? "'$expected_version'" : 'undef') + . ')' + ) + or $errs++; + + is( $warnings, '', "case $test_case: no warnings from parsing" ) or $errs++; + diag "Got: '$got'\nModule contents:\n$code" if $errs; } } -# revert to pristine state -$dist->regen( clean => 1 ); +$test_case = 0; +while (++$test_case and my ($expected_name, $code) = splice @pkg_names, 0, 2) { + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => $code }); + + my $warnings = ''; + local $SIG{__WARN__} = sub { $warnings .= $_ for @_ }; + my $pm_info = Module::Metadata->new_from_file( $file ); + + # Test::Builder will prematurely numify objects, so use this form + my $errs; + my @got = $pm_info->packages_inside(); + is_deeply( \@got, $expected_name, + "case $test_case: correct package names (expected '" . join(', ', @$expected_name) . "')" ) + or $errs++; + is( $warnings, '', "case $test_case: no warnings from parsing" ) or $errs++; + diag "Got: '" . join(', ', @got) . "'\nModule contents:\n$code" if $errs; +} -# Find each package only once -$dist->change_file( 'lib/Simple.pm', <<'---' ); +{ + # Find each package only once + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); package Simple; $VERSION = '1.23'; package Error::Simple; @@ -307,50 +436,49 @@ $VERSION = '2.34'; package Simple; --- -$dist->regen; - -$pm_info = Module::Metadata->new_from_file( $file ); - -my @packages = $pm_info->packages_inside; -is( @packages, 2, 'record only one occurence of each package' ); + my $pm_info = Module::Metadata->new_from_file( $file ); + my @packages = $pm_info->packages_inside; + is( @packages, 2, 'record only one occurence of each package' ); +} -# Module 'Simple.pm' does not contain package 'Simple'; -# constructor should not complain, no default module name or version -$dist->change_file( 'lib/Simple.pm', <<'---' ); +{ + # Module 'Simple.pm' does not contain package 'Simple'; + # constructor should not complain, no default module name or version + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); package Simple::Not; $VERSION = '1.23'; --- -$dist->regen; -$pm_info = Module::Metadata->new_from_file( $file ); + my $pm_info = Module::Metadata->new_from_file( $file ); -is( $pm_info->name, undef, 'no default package' ); -is( $pm_info->version, undef, 'no version w/o default package' ); + is( $pm_info->name, undef, 'no default package' ); + is( $pm_info->version, undef, 'no version w/o default package' ); +} -# Module 'Simple.pm' contains an alpha version -# constructor should report first $VERSION found -$dist->change_file( 'lib/Simple.pm', <<'---' ); +{ + # Module 'Simple.pm' contains an alpha version + # constructor should report first $VERSION found + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); package Simple; $VERSION = '1.23_01'; $VERSION = eval $VERSION; --- -$dist->regen; -$pm_info = Module::Metadata->new_from_file( $file ); + my $pm_info = Module::Metadata->new_from_file( $file ); -is( $pm_info->version, '1.23_01', 'alpha version reported'); + is( $pm_info->version, '1.23_01', 'alpha version reported'); -# NOTE the following test has be done this way because Test::Builder is -# too smart for our own good and tries to see if the version object is a -# dual-var, which breaks with alpha versions: -# Argument "1.23_0100" isn't numeric in addition (+) at -# /usr/lib/perl5/5.8.7/Test/Builder.pm line 505. + # NOTE the following test has be done this way because Test::Builder is + # too smart for our own good and tries to see if the version object is a + # dual-var, which breaks with alpha versions: + # Argument "1.23_0100" isn't numeric in addition (+) at + # /usr/lib/perl5/5.8.7/Test/Builder.pm line 505. -ok( $pm_info->version > 1.23, 'alpha version greater than non'); - -# revert to pristine state -$dist->regen( clean => 1 ); + ok( $pm_info->version > 1.23, 'alpha version greater than non'); +} # parse $VERSION lines scripts for package main my @scripts = ( @@ -404,18 +532,18 @@ $::VERSION = 0.01; my ( $i, $n ) = ( 1, scalar( @scripts ) ); foreach my $script ( @scripts ) { - $dist->change_file( 'bin/simple.plx', $script ); - $dist->regen; - $pm_info = Module::Metadata->new_from_file( - File::Spec->catfile( 'bin', 'simple.plx' ) ); + my $file = File::Spec->catfile('bin', 'simple.plx'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => $script } ); + my $pm_info = Module::Metadata->new_from_file( $file ); is( $pm_info->version, '0.01', "correct script version ($i of $n)" ); $i++; } - -# examine properties of a module: name, pod, etc -$dist->change_file( 'lib/Simple.pm', <<'---' ); +{ + # examine properties of a module: name, pod, etc + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); package Simple; $VERSION = '0.01'; package Simple::Ex; @@ -434,44 +562,42 @@ You can find me on the IRC channel =cut --- -$dist->regen; -$pm_info = Module::Metadata->new_from_module( - $dist->name, inc => [ 'lib', @INC ] ); + my $pm_info = Module::Metadata->new_from_module( + 'Simple', inc => [ 'lib', @INC ] ); -is( $pm_info->name, 'Simple', 'found default package' ); -is( $pm_info->version, '0.01', 'version for default package' ); + is( $pm_info->name, 'Simple', 'found default package' ); + is( $pm_info->version, '0.01', 'version for default package' ); -# got correct version for secondary package -is( $pm_info->version( 'Simple::Ex' ), '0.02', - 'version for secondary package' ); + # got correct version for secondary package + is( $pm_info->version( 'Simple::Ex' ), '0.02', + 'version for secondary package' ); -my $filename = $pm_info->filename; -ok( defined( $filename ) && -e $filename, - 'filename() returns valid path to module file' ); + my $filename = $pm_info->filename; + ok( defined( $filename ) && -e $filename, + 'filename() returns valid path to module file' ); -@packages = $pm_info->packages_inside; -is( @packages, 2, 'found correct number of packages' ); -is( $packages[0], 'Simple', 'packages stored in order found' ); + my @packages = $pm_info->packages_inside; + is( @packages, 2, 'found correct number of packages' ); + is( $packages[0], 'Simple', 'packages stored in order found' ); -# we can detect presence of pod regardless of whether we are collecting it -ok( $pm_info->contains_pod, 'contains_pod() succeeds' ); + # we can detect presence of pod regardless of whether we are collecting it + ok( $pm_info->contains_pod, 'contains_pod() succeeds' ); -my @pod = $pm_info->pod_inside; -is_deeply( \@pod, [qw(NAME AUTHOR)], 'found all pod sections' ); + my @pod = $pm_info->pod_inside; + is_deeply( \@pod, [qw(NAME AUTHOR)], 'found all pod sections' ); -is( $pm_info->pod('NONE') , undef, - 'return undef() if pod section not present' ); + is( $pm_info->pod('NONE') , undef, + 'return undef() if pod section not present' ); -is( $pm_info->pod('NAME'), undef, - 'return undef() if pod section not collected' ); + is( $pm_info->pod('NAME'), undef, + 'return undef() if pod section not collected' ); -# collect_pod -$pm_info = Module::Metadata->new_from_module( - $dist->name, inc => [ 'lib', @INC ], collect_pod => 1 ); + # collect_pod + $pm_info = Module::Metadata->new_from_module( + 'Simple', inc => [ 'lib', @INC ], collect_pod => 1 ); -{ my %pod; for my $section (qw(NAME AUTHOR)) { my $content = $pm_info->pod( $section ); @@ -499,8 +625,36 @@ EXPECTED } { + # test things that look like POD, but aren't + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); +package Simple; + +=YES THIS STARTS POD + +our $VERSION = '999'; + +=cute + +our $VERSION = '666'; + +=cut + +*foo +=*no_this_does_not_start_pod; + +our $VERSION = '1.23'; + +--- + my $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); + is( $pm_info->name, 'Simple', 'found default package' ); + is( $pm_info->version, '1.23', 'version for default package' ); +} + +{ # Make sure processing stops after __DATA__ - $dist->change_file( 'lib/Simple.pm', <<'---' ); + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); package Simple; $VERSION = '0.01'; __DATA__ @@ -508,9 +662,8 @@ __DATA__ foo(); }; --- - $dist->regen; - $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); + my $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); is( $pm_info->name, 'Simple', 'found default package' ); is( $pm_info->version, '0.01', 'version for default package' ); my @packages = $pm_info->packages_inside; @@ -519,15 +672,15 @@ __DATA__ { # Make sure we handle version.pm $VERSIONs well - $dist->change_file( 'lib/Simple.pm', <<'---' ); + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); package Simple; $VERSION = version->new('0.60.' . (qw$Revision: 128 $)[1]); package Simple::Simon; $VERSION = version->new('0.61.' . (qw$Revision: 129 $)[1]); --- - $dist->regen; - $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); + my $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); is( $pm_info->name, 'Simple', 'found default package' ); is( $pm_info->version, '0.60.128', 'version for default package' ); my @packages = $pm_info->packages_inside; @@ -537,7 +690,9 @@ $VERSION = version->new('0.61.' . (qw$Revision: 129 $)[1]); # check that package_versions_from_directory works -$dist->change_file( 'lib/Simple.pm', <<'---' ); +{ + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); package Simple; $VERSION = '0.01'; package Simple::Ex; @@ -562,23 +717,22 @@ Simple Simon =cut --- -$dist->regen; -my $exp_pvfd = { - 'Simple' => { - 'file' => 'Simple.pm', - 'version' => '0.01' - }, - 'Simple::Ex' => { - 'file' => 'Simple.pm', - 'version' => '0.02' - } -}; + my $exp_pvfd = { + 'Simple' => { + 'file' => 'Simple.pm', + 'version' => '0.01' + }, + 'Simple::Ex' => { + 'file' => 'Simple.pm', + 'version' => '0.02' + } + }; -my $got_pvfd = Module::Metadata->package_versions_from_directory('lib'); + my $got_pvfd = Module::Metadata->package_versions_from_directory('lib'); -is_deeply( $got_pvfd, $exp_pvfd, "package_version_from_directory()" ) - or diag explain $got_pvfd; + is_deeply( $got_pvfd, $exp_pvfd, "package_version_from_directory()" ) + or diag explain $got_pvfd; { my $got_provides = Module::Metadata->provides(dir => 'lib', version => 2); @@ -613,22 +767,29 @@ is_deeply( $got_pvfd, $exp_pvfd, "package_version_from_directory()" ) is_deeply( $got_provides, $exp_provides, "provides()" ) or diag explain $got_provides; } +} # Check package_versions_from_directory with regard to case-sensitivity { - $dist->change_file( 'lib/Simple.pm', <<'---' ); + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); package simple; $VERSION = '0.01'; --- - $dist->regen; - $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); + my $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); is( $pm_info->name, undef, 'no default package' ); is( $pm_info->version, undef, 'version for default package' ); is( $pm_info->version('simple'), '0.01', 'version for lower-case package' ); is( $pm_info->version('Simple'), undef, 'version for capitalized package' ); + ok( $pm_info->is_indexable(), 'an indexable package is found' ); + ok( $pm_info->is_indexable('simple'), 'the simple package is indexable' ); + ok( !$pm_info->is_indexable('Simple'), 'the Simple package would not be indexed' ); +} - $dist->change_file( 'lib/Simple.pm', <<'---' ); +{ + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); package simple; $VERSION = '0.01'; package Simple; @@ -636,12 +797,28 @@ $VERSION = '0.02'; package SiMpLe; $VERSION = '0.03'; --- - $dist->regen; - $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); + my $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); is( $pm_info->name, 'Simple', 'found default package' ); is( $pm_info->version, '0.02', 'version for default package' ); is( $pm_info->version('simple'), '0.01', 'version for lower-case package' ); is( $pm_info->version('Simple'), '0.02', 'version for capitalized package' ); is( $pm_info->version('SiMpLe'), '0.03', 'version for mixed-case package' ); + ok( $pm_info->is_indexable('simple'), 'the simple package is indexable' ); + ok( $pm_info->is_indexable('Simple'), 'the Simple package is indexable' ); +} + +{ + my $file = File::Spec->catfile('lib', 'Simple.pm'); + my ($dist_name, $dist_dir) = new_dist(files => { $file => <<'---' } ); +package ## hide from PAUSE + simple; +$VERSION = '0.01'; +--- + + my $pm_info = Module::Metadata->new_from_file('lib/Simple.pm'); + is( $pm_info->name, undef, 'no package names found' ); + ok( !$pm_info->is_indexable('simple'), 'the simple package would not be indexed' ); + ok( !$pm_info->is_indexable('Simple'), 'the Simple package would not be indexed' ); + ok( !$pm_info->is_indexable(), 'no indexable package is found' ); }