This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add Module::Metadata as a dual-life core module
[perl5.git] / cpan / Module-Metadata / t / metadata.t
CommitLineData
e8b333e6
DG
1#!/usr/bin/perl -w
2# -*- mode: cperl; tab-width: 8; indent-tabs-mode: nil; basic-offset: 2 -*-
3# vim:ts=8:sw=2:et:sta:sts=2
4
5use strict;
6use lib 't/lib';
7use MBTest;
8
9# parse various module $VERSION lines
10# these will be reversed later to create %modules
11my @modules = (
12 '1.23' => <<'---', # declared & defined on same line with 'our'
13package Simple;
14our $VERSION = '1.23';
15---
16 '1.23' => <<'---', # declared & defined on separate lines with 'our'
17package Simple;
18our $VERSION;
19$VERSION = '1.23';
20---
21 '1.23' => <<'---', # use vars
22package Simple;
23use vars qw( $VERSION );
24$VERSION = '1.23';
25---
26 '1.23' => <<'---', # choose the right default package based on package/file name
27package Simple::_private;
28$VERSION = '0';
29package Simple;
30$VERSION = '1.23'; # this should be chosen for version
31---
32 '1.23' => <<'---', # just read the first $VERSION line
33package Simple;
34$VERSION = '1.23'; # we should see this line
35$VERSION = eval $VERSION; # and ignore this one
36---
37 '1.23' => <<'---', # just read the first $VERSION line in reopened package (1)
38package Simple;
39$VERSION = '1.23';
40package Error::Simple;
41$VERSION = '2.34';
42package Simple;
43---
44 '1.23' => <<'---', # just read the first $VERSION line in reopened package (2)
45package Simple;
46package Error::Simple;
47$VERSION = '2.34';
48package Simple;
49$VERSION = '1.23';
50---
51 '1.23' => <<'---', # mentions another module's $VERSION
52package Simple;
53$VERSION = '1.23';
54if ( $Other::VERSION ) {
55 # whatever
56}
57---
58 '1.23' => <<'---', # mentions another module's $VERSION in a different package
59package Simple;
60$VERSION = '1.23';
61package Simple2;
62if ( $Simple::VERSION ) {
63 # whatever
64}
65---
66 '1.23' => <<'---', # $VERSION checked only in assignments, not regexp ops
67package Simple;
68$VERSION = '1.23';
69if ( $VERSION =~ /1\.23/ ) {
70 # whatever
71}
72---
73 '1.23' => <<'---', # $VERSION checked only in assignments, not relational ops
74package Simple;
75$VERSION = '1.23';
76if ( $VERSION == 3.45 ) {
77 # whatever
78}
79---
80 '1.23' => <<'---', # $VERSION checked only in assignments, not relational ops
81package Simple;
82$VERSION = '1.23';
83package Simple2;
84if ( $Simple::VERSION == 3.45 ) {
85 # whatever
86}
87---
88 '1.23' => <<'---', # Fully qualified $VERSION declared in package
89package Simple;
90$Simple::VERSION = 1.23;
91---
92 '1.23' => <<'---', # Differentiate fully qualified $VERSION in a package
93package Simple;
94$Simple2::VERSION = '999';
95$Simple::VERSION = 1.23;
96---
97 '1.23' => <<'---', # Differentiate fully qualified $VERSION and unqualified
98package Simple;
99$Simple2::VERSION = '999';
100$VERSION = 1.23;
101---
102 '1.23' => <<'---', # $VERSION declared as package variable from within 'main' package
103$Simple::VERSION = '1.23';
104{
105 package Simple;
106 $x = $y, $cats = $dogs;
107}
108---
109 '1.23' => <<'---', # $VERSION wrapped in parens - space inside
110package Simple;
111( $VERSION ) = '1.23';
112---
113 '1.23' => <<'---', # $VERSION wrapped in parens - no space inside
114package Simple;
115($VERSION) = '1.23';
116---
117 '1.23' => <<'---', # $VERSION follows a spurious 'package' in a quoted construct
118package Simple;
119__PACKAGE__->mk_accessors(qw(
120 program socket proc
121 package filename line codeline subroutine finished));
122
123our $VERSION = "1.23";
124---
125 '1.23' => <<'---', # $VERSION using version.pm
126 package Simple;
127 use version; our $VERSION = version->new('1.23');
128---
129 '1.23' => <<'---', # $VERSION using version.pm and qv()
130 package Simple;
131 use version; our $VERSION = qv('1.230');
132---
133 '1.23' => <<'---', # Two version assignments, should ignore second one
134 $Simple::VERSION = '1.230';
135 $Simple::VERSION = eval $Simple::VERSION;
136---
137 '1.23' => <<'---', # declared & defined on same line with 'our'
138package Simple;
139our $VERSION = '1.23_00_00';
140---
141 '1.23' => <<'---', # package NAME VERSION
142 package Simple 1.23;
143---
144 '1.23_01' => <<'---', # package NAME VERSION
145 package Simple 1.23_01;
146---
147 'v1.2.3' => <<'---', # package NAME VERSION
148 package Simple v1.2.3;
149---
150 'v1.2_3' => <<'---', # package NAME VERSION
151 package Simple v1.2_3;
152---
153 '1.23' => <<'---', # trailing crud
154 package Simple;
155 our $VERSION;
156 $VERSION = '1.23-alpha';
157---
158 '1.23' => <<'---', # trailing crud
159 package Simple;
160 our $VERSION;
161 $VERSION = '1.23b';
162---
163 '1.234' => <<'---', # multi_underscore
164 package Simple;
165 our $VERSION;
166 $VERSION = '1.2_3_4';
167---
168 '0' => <<'---', # non-numeric
169 package Simple;
170 our $VERSION;
171 $VERSION = 'onetwothree';
172---
173);
174my %modules = reverse @modules;
175
176plan tests => 37 + 2 * keys( %modules );
177
178require_ok('Module::Metadata');
179
180my $tmp = MBTest->tmpdir;
181
182use DistGen;
183my $dist = DistGen->new( dir => $tmp );
184$dist->regen;
185
186$dist->chdir_in;
187
188#########################
189
190# class method C<find_module_by_name>
191my $module = Module::Metadata->find_module_by_name(
192 'Module::Metadata' );
193ok( -e $module, 'find_module_by_name() succeeds' );
194
195
196# fail on invalid module name
197my $pm_info = Module::Metadata->new_from_module(
198 'Foo::Bar', inc => [] );
199ok( !defined( $pm_info ), 'fail if can\'t find module by module name' );
200
201
202# fail on invalid filename
203my $file = File::Spec->catfile( 'Foo', 'Bar.pm' );
204$pm_info = Module::Metadata->new_from_file( $file, inc => [] );
205ok( !defined( $pm_info ), 'fail if can\'t find module by file name' );
206
207
208# construct from module filename
209$file = File::Spec->catfile( 'lib', split( /::/, $dist->name ) ) . '.pm';
210$pm_info = Module::Metadata->new_from_file( $file );
211ok( defined( $pm_info ), 'new_from_file() succeeds' );
212
213# construct from module name, using custom include path
214$pm_info = Module::Metadata->new_from_module(
215 $dist->name, inc => [ 'lib', @INC ] );
216ok( defined( $pm_info ), 'new_from_module() succeeds' );
217
218
219foreach my $module ( sort keys %modules ) {
220 my $expected = $modules{$module};
221 SKIP: {
222 skip( "No our() support until perl 5.6", 2 )
223 if $] < 5.006 && $module =~ /\bour\b/;
224 skip( "No package NAME VERSION support until perl 5.11.1", 2 )
225 if $] < 5.011001 && $module =~ /package\s+[\w\:\']+\s+v?[0-9._]+/;
226
227 $dist->change_file( 'lib/Simple.pm', $module );
228 $dist->regen;
229
230 my $warnings = '';
231 local $SIG{__WARN__} = sub { $warnings .= $_ for @_ };
232 my $pm_info = Module::Metadata->new_from_file( $file );
233
234 # Test::Builder will prematurely numify objects, so use this form
235 my $errs;
236 ok( $pm_info->version eq $expected,
237 "correct module version (expected '$expected')" )
238 or $errs++;
239 is( $warnings, '', 'no warnings from parsing' ) or $errs++;
240 diag "Got: '@{[$pm_info->version]}'\nModule contents:\n$module" if $errs;
241 }
242}
243
244# revert to pristine state
245$dist->regen( clean => 1 );
246
247# Find each package only once
248$dist->change_file( 'lib/Simple.pm', <<'---' );
249package Simple;
250$VERSION = '1.23';
251package Error::Simple;
252$VERSION = '2.34';
253package Simple;
254---
255
256$dist->regen;
257
258$pm_info = Module::Metadata->new_from_file( $file );
259
260my @packages = $pm_info->packages_inside;
261is( @packages, 2, 'record only one occurence of each package' );
262
263
264# Module 'Simple.pm' does not contain package 'Simple';
265# constructor should not complain, no default module name or version
266$dist->change_file( 'lib/Simple.pm', <<'---' );
267package Simple::Not;
268$VERSION = '1.23';
269---
270
271$dist->regen;
272$pm_info = Module::Metadata->new_from_file( $file );
273
274is( $pm_info->name, undef, 'no default package' );
275is( $pm_info->version, undef, 'no version w/o default package' );
276
277# Module 'Simple.pm' contains an alpha version
278# constructor should report first $VERSION found
279$dist->change_file( 'lib/Simple.pm', <<'---' );
280package Simple;
281$VERSION = '1.23_01';
282$VERSION = eval $VERSION;
283---
284
285$dist->regen;
286$pm_info = Module::Metadata->new_from_file( $file );
287
288is( $pm_info->version, '1.23_01', 'alpha version reported');
289
290# NOTE the following test has be done this way because Test::Builder is
291# too smart for our own good and tries to see if the version object is a
292# dual-var, which breaks with alpha versions:
293# Argument "1.23_0100" isn't numeric in addition (+) at
294# /usr/lib/perl5/5.8.7/Test/Builder.pm line 505.
295
296ok( $pm_info->version > 1.23, 'alpha version greater than non');
297
298# revert to pristine state
299$dist->regen( clean => 1 );
300
301# parse $VERSION lines scripts for package main
302my @scripts = (
303 <<'---', # package main declared
304#!perl -w
305package main;
306$VERSION = '0.01';
307---
308 <<'---', # on first non-comment line, non declared package main
309#!perl -w
310$VERSION = '0.01';
311---
312 <<'---', # after non-comment line
313#!perl -w
314use strict;
315$VERSION = '0.01';
316---
317 <<'---', # 1st declared package
318#!perl -w
319package main;
320$VERSION = '0.01';
321package _private;
322$VERSION = '999';
323---
324 <<'---', # 2nd declared package
325#!perl -w
326package _private;
327$VERSION = '999';
328package main;
329$VERSION = '0.01';
330---
331 <<'---', # split package
332#!perl -w
333package main;
334package _private;
335$VERSION = '999';
336package main;
337$VERSION = '0.01';
338---
339 <<'---', # define 'main' version from other package
340package _private;
341$::VERSION = 0.01;
342$VERSION = '999';
343---
344 <<'---', # define 'main' version from other package
345package _private;
346$VERSION = '999';
347$::VERSION = 0.01;
348---
349);
350
351my ( $i, $n ) = ( 1, scalar( @scripts ) );
352foreach my $script ( @scripts ) {
353 $dist->change_file( 'bin/simple.plx', $script );
354 $dist->regen;
355 $pm_info = Module::Metadata->new_from_file(
356 File::Spec->catfile( 'bin', 'simple.plx' ) );
357
358 is( $pm_info->version, '0.01', "correct script version ($i of $n)" );
359 $i++;
360}
361
362
363# examine properties of a module: name, pod, etc
364$dist->change_file( 'lib/Simple.pm', <<'---' );
365package Simple;
366$VERSION = '0.01';
367package Simple::Ex;
368$VERSION = '0.02';
369=head1 NAME
370
371Simple - It's easy.
372
373=head1 AUTHOR
374
375Simple Simon
376
377=cut
378---
379$dist->regen;
380
381$pm_info = Module::Metadata->new_from_module(
382 $dist->name, inc => [ 'lib', @INC ] );
383
384is( $pm_info->name, 'Simple', 'found default package' );
385is( $pm_info->version, '0.01', 'version for default package' );
386
387# got correct version for secondary package
388is( $pm_info->version( 'Simple::Ex' ), '0.02',
389 'version for secondary package' );
390
391my $filename = $pm_info->filename;
392ok( defined( $filename ) && -e $filename,
393 'filename() returns valid path to module file' );
394
395@packages = $pm_info->packages_inside;
396is( @packages, 2, 'found correct number of packages' );
397is( $packages[0], 'Simple', 'packages stored in order found' );
398
399# we can detect presence of pod regardless of whether we are collecting it
400ok( $pm_info->contains_pod, 'contains_pod() succeeds' );
401
402my @pod = $pm_info->pod_inside;
403is_deeply( \@pod, [qw(NAME AUTHOR)], 'found all pod sections' );
404
405is( $pm_info->pod('NONE') , undef,
406 'return undef() if pod section not present' );
407
408is( $pm_info->pod('NAME'), undef,
409 'return undef() if pod section not collected' );
410
411
412# collect_pod
413$pm_info = Module::Metadata->new_from_module(
414 $dist->name, inc => [ 'lib', @INC ], collect_pod => 1 );
415
416my $name = $pm_info->pod('NAME');
417if ( $name ) {
418 $name =~ s/^\s+//;
419 $name =~ s/\s+$//;
420}
421is( $name, q|Simple - It's easy.|, 'collected pod section' );
422
423
424{
425 # Make sure processing stops after __DATA__
426 $dist->change_file( 'lib/Simple.pm', <<'---' );
427package Simple;
428$VERSION = '0.01';
429__DATA__
430*UNIVERSAL::VERSION = sub {
431 foo();
432};
433---
434 $dist->regen;
435
436 $pm_info = Module::Metadata->new_from_file('lib/Simple.pm');
437 is( $pm_info->name, 'Simple', 'found default package' );
438 is( $pm_info->version, '0.01', 'version for default package' );
439 my @packages = $pm_info->packages_inside;
440 is_deeply(\@packages, ['Simple'], 'packages inside');
441}
442
443{
444 # Make sure we handle version.pm $VERSIONs well
445 $dist->change_file( 'lib/Simple.pm', <<'---' );
446package Simple;
447$VERSION = version->new('0.60.' . (qw$Revision: 128 $)[1]);
448package Simple::Simon;
449$VERSION = version->new('0.61.' . (qw$Revision: 129 $)[1]);
450---
451 $dist->regen;
452
453 $pm_info = Module::Metadata->new_from_file('lib/Simple.pm');
454 is( $pm_info->name, 'Simple', 'found default package' );
455 is( $pm_info->version, '0.60.128', 'version for default package' );
456 my @packages = $pm_info->packages_inside;
457 is_deeply([sort @packages], ['Simple', 'Simple::Simon'], 'packages inside');
458 is( $pm_info->version('Simple::Simon'), '0.61.129', 'version for embedded package' );
459}
460