1BEGIN {
2    unshift @INC, 't/lib';
3}
4
5use strict;
6use Test::More tests => 31;
7
8use Data::Dumper;
9use File::Temp;
10use Cwd;
11use Parse::CPAN::Meta;
12
13require ExtUtils::MM_Any;
14
15sub in_dir(&;$) {
16    my $code = shift;
17    my $dir = shift || File::Temp->newdir;
18
19    # chdir to the new directory
20    my $orig_dir = cwd();
21    chdir $dir or die "Can't chdir to $dir: $!";
22
23    # Run the code, but trap the error so we can chdir back
24    my $return;
25    my $ok = eval { $return = $code->(); 1; };
26    my $err = $@;
27
28    # chdir back
29    chdir $orig_dir or die "Can't chdir to $orig_dir: $!";
30
31    # rethrow if necessary
32    die $err unless $ok;
33
34    return $return;
35}
36
37sub mymeta_ok {
38    my($have, $want, $name) = @_;
39
40    local $Test::Builder::Level = $Test::Builder::Level + 1;
41
42    my $have_gen = delete $have->{generated_by};
43    my $want_gen = delete $want->{generated_by};
44    my $have_url = delete $have->{'meta-spec'}->{url};
45    my $want_url = delete $want->{'meta-spec'}->{url};
46
47    is_deeply $have, $want, $name;
48    like $have_gen, qr{CPAN::Meta}, "CPAN::Meta mentioned in the generated_by";
49    like $have_url, qr{CPAN::Meta::Spec}, "CPAN::Meta::Spec mentioned in meta-spec URL";
50
51    return;
52}
53
54my $new_mm = sub {
55    return bless { ARGS => {@_}, @_ }, 'ExtUtils::MM_Any';
56};
57
58{
59    my $mm = $new_mm->(
60        DISTNAME        => 'Foo-Bar',
61        VERSION         => 1.23,
62        PM              => {
63            "Foo::Bar"          => 'lib/Foo/Bar.pm',
64        },
65    );
66
67    is_deeply {$mm->metafile_data}, {
68        name            => 'Foo-Bar',
69        version         => 1.23,
70        abstract        => 'unknown',
71        author          => [],
72        license         => 'unknown',
73        dynamic_config  => 1,
74        distribution_type       => 'module',
75
76        configure_requires      => {
77            'ExtUtils::MakeMaker'       => 0,
78        },
79        build_requires      => {
80            'ExtUtils::MakeMaker'       => 0,
81        },
82
83        no_index        => {
84            directory           => [qw(t inc)],
85        },
86
87        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
88        'meta-spec'  => {
89            url         => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
90            version     => 1.4
91        },
92    };
93
94
95    is_deeply {$mm->metafile_data({}, { no_index => { directory => [qw(foo)] } })}, {
96        name            => 'Foo-Bar',
97        version         => 1.23,
98        abstract        => 'unknown',
99        author          => [],
100        license         => 'unknown',
101        dynamic_config  => 1,
102        distribution_type       => 'module',
103
104        configure_requires      => {
105            'ExtUtils::MakeMaker'       => 0,
106        },
107        build_requires      => {
108            'ExtUtils::MakeMaker'       => 0,
109        },
110
111        no_index        => {
112            directory           => [qw(t inc foo)],
113        },
114
115        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
116        'meta-spec'  => {
117            url         => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
118            version     => 1.4
119        },
120    }, 'rt.cpan.org 39348';
121}
122
123
124{
125    my $mm = $new_mm->(
126        DISTNAME        => 'Foo-Bar',
127        VERSION         => 1.23,
128        AUTHOR          => ['Some Guy'],
129        PREREQ_PM       => {
130            Foo                 => 2.34,
131            Bar                 => 4.56,
132        },
133    );
134
135    is_deeply {$mm->metafile_data(
136        {
137            configure_requires => {
138                Stuff   => 2.34
139            },
140            wobble      => 42
141        },
142        {
143            no_index    => {
144                package => "Thing"
145            },
146            wibble      => 23
147        },
148    )},
149    {
150        name            => 'Foo-Bar',
151        version         => 1.23,
152        abstract        => 'unknown',
153        author          => ['Some Guy'],
154        license         => 'unknown',
155        dynamic_config  => 1,
156        distribution_type       => 'script',
157
158        configure_requires      => {
159            Stuff       => 2.34,
160        },
161        build_requires      => {
162            'ExtUtils::MakeMaker'       => 0,
163        },
164
165        requires       => {
166            Foo                 => 2.34,
167            Bar                 => 4.56,
168        },
169
170        no_index        => {
171            directory           => [qw(t inc)],
172            package             => 'Thing',
173        },
174
175        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
176        'meta-spec'  => {
177            url         => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
178            version     => 1.4
179        },
180
181        wibble  => 23,
182        wobble  => 42,
183    };
184}
185
186
187# Test MIN_PERL_VERSION meta-spec 1.4
188{
189    my $mm = $new_mm->(
190        DISTNAME        => 'Foo-Bar',
191        VERSION         => 1.23,
192        PM              => {
193            "Foo::Bar"          => 'lib/Foo/Bar.pm',
194        },
195        MIN_PERL_VERSION => 5.006,
196    );
197
198    is_deeply {$mm->metafile_data}, {
199        name            => 'Foo-Bar',
200        version         => 1.23,
201        abstract        => 'unknown',
202        author          => [],
203        license         => 'unknown',
204        dynamic_config  => 1,
205        distribution_type       => 'module',
206
207        configure_requires      => {
208            'ExtUtils::MakeMaker'       => 0,
209        },
210        build_requires      => {
211            'ExtUtils::MakeMaker'       => 0,
212        },
213
214        requires        => {
215            perl        => '5.006',
216        },
217
218        no_index        => {
219            directory           => [qw(t inc)],
220        },
221
222        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
223        'meta-spec'  => {
224            url         => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
225            version     => 1.4
226        },
227    }, 'MIN_PERL_VERSION meta-spec 1.4';
228}
229
230# Test MIN_PERL_VERSION meta-spec 2.0
231{
232    my $mm = $new_mm->(
233        DISTNAME        => 'Foo-Bar',
234        VERSION         => 1.23,
235        PM              => {
236            "Foo::Bar"          => 'lib/Foo/Bar.pm',
237        },
238        MIN_PERL_VERSION => 5.006,
239    );
240
241    is_deeply {
242        $mm->metafile_data(
243                {}, {
244                'meta-spec' => {
245                url     => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
246                version => 2
247                } } )
248    }, {
249        name            => 'Foo-Bar',
250        version         => 1.23,
251        abstract        => 'unknown',
252        author          => [],
253        license         => 'unknown',
254        dynamic_config  => 1,
255        distribution_type       => 'module',
256
257        prereqs => {
258            configure       => {
259                requires    => {
260                    'ExtUtils::MakeMaker'   => 0,
261                },
262            },
263            build           => {
264                requires    => {
265                    'ExtUtils::MakeMaker'   => 0,
266                },
267            },
268            runtime         => {
269                requires    => {
270                    'perl'  => '5.006',
271                },
272            },
273        },
274
275        no_index        => {
276            directory           => [qw(t inc)],
277        },
278
279        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
280        'meta-spec'  => {
281
282            url     => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
283            version => 2
284        },
285    }, 'MIN_PERL_VERSION meta-spec 2.0';
286}
287
288# Test MIN_PERL_VERSION meta-spec 1.4
289{
290    my $mm = $new_mm->(
291        DISTNAME        => 'Foo-Bar',
292        VERSION         => 1.23,
293        PM              => {
294            "Foo::Bar"          => 'lib/Foo/Bar.pm',
295        },
296        MIN_PERL_VERSION => 5.006,
297        PREREQ_PM => {
298            'Foo::Bar'  => 1.23,
299        },
300    );
301
302    is_deeply {$mm->metafile_data}, {
303        name            => 'Foo-Bar',
304        version         => 1.23,
305        abstract        => 'unknown',
306        author          => [],
307        license         => 'unknown',
308        dynamic_config  => 1,
309        distribution_type       => 'module',
310
311        configure_requires      => {
312            'ExtUtils::MakeMaker'       => 0,
313        },
314        build_requires      => {
315            'ExtUtils::MakeMaker'       => 0,
316        },
317
318        requires        => {
319            perl        => '5.006',
320            'Foo::Bar'  => 1.23,
321        },
322
323        no_index        => {
324            directory           => [qw(t inc)],
325        },
326
327        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
328        'meta-spec'  => {
329            url         => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
330            version     => 1.4
331        },
332    }, 'MIN_PERL_VERSION and PREREQ_PM meta-spec 1.4';
333}
334
335# Test CONFIGURE_REQUIRES meta-spec 1.4
336{
337    my $mm = $new_mm->(
338        DISTNAME        => 'Foo-Bar',
339        VERSION         => 1.23,
340        CONFIGURE_REQUIRES => {
341            "Fake::Module1" => 1.01,
342        },
343        PM              => {
344            "Foo::Bar"          => 'lib/Foo/Bar.pm',
345        },
346    );
347
348    is_deeply {$mm->metafile_data}, {
349        name            => 'Foo-Bar',
350        version         => 1.23,
351        abstract        => 'unknown',
352        author          => [],
353        license         => 'unknown',
354        dynamic_config  => 1,
355        distribution_type       => 'module',
356
357        configure_requires      => {
358            'Fake::Module1'     => 1.01,
359        },
360        build_requires      => {
361            'ExtUtils::MakeMaker'   => 0,
362        },
363
364        no_index        => {
365            directory           => [qw(t inc)],
366        },
367
368        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
369        'meta-spec'  => {
370            url         => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
371            version     => 1.4
372        },
373    },'CONFIGURE_REQUIRES meta-spec 1.4';
374}
375
376# Test CONFIGURE_REQUIRES meta-spec 2.0
377{
378    my $mm = $new_mm->(
379        DISTNAME        => 'Foo-Bar',
380        VERSION         => 1.23,
381        CONFIGURE_REQUIRES => {
382            "Fake::Module1" => 1.01,
383        },
384        PM              => {
385            "Foo::Bar"      => 'lib/Foo/Bar.pm',
386        },
387    );
388
389    is_deeply {
390        $mm->metafile_data(
391                {}, {
392                'meta-spec' => {
393                url     => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
394                version => 2
395                } } )
396    }, {
397        name            => 'Foo-Bar',
398        version         => 1.23,
399        abstract        => 'unknown',
400        author          => [],
401        license         => 'unknown',
402        dynamic_config  => 1,
403        distribution_type       => 'module',
404
405        prereqs => {
406            configure       => {
407                requires    => {
408                    'Fake::Module1'         => 1.01,
409                },
410            },
411            build           => {
412                requires    => {
413                    'ExtUtils::MakeMaker'   => 0,
414                },
415            },
416        },
417
418        no_index        => {
419            directory           => [qw(t inc)],
420        },
421
422        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
423        'meta-spec'  => {
424            url         => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
425            version     => 2
426        },
427    },'CONFIGURE_REQUIRES meta-spec 2.0';
428}
429
430
431# Test BUILD_REQUIRES meta-spec 1.4
432{
433    my $mm = $new_mm->(
434        DISTNAME        => 'Foo-Bar',
435        VERSION         => 1.23,
436        BUILD_REQUIRES => {
437            "Fake::Module1" => 1.01,
438        },
439        PM              => {
440            "Foo::Bar"          => 'lib/Foo/Bar.pm',
441        },
442    );
443
444    is_deeply {$mm->metafile_data}, {
445        name            => 'Foo-Bar',
446        version         => 1.23,
447        abstract        => 'unknown',
448        author          => [],
449        license         => 'unknown',
450        dynamic_config  => 1,
451        distribution_type       => 'module',
452
453        configure_requires      => {
454            'ExtUtils::MakeMaker'   => 0,
455        },
456        build_requires      => {
457            'Fake::Module1'         => 1.01,
458        },
459
460        no_index        => {
461            directory           => [qw(t inc)],
462        },
463
464        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
465        'meta-spec'  => {
466            url         => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
467            version     => 1.4
468        },
469    },'BUILD_REQUIRES meta-spec 1.4';
470}
471
472# Test BUILD_REQUIRES meta-spec 2.0
473{
474    my $mm = $new_mm->(
475        DISTNAME        => 'Foo-Bar',
476        VERSION         => 1.23,
477        BUILD_REQUIRES => {
478            "Fake::Module1" => 1.01,
479        },
480        PM              => {
481            "Foo::Bar"          => 'lib/Foo/Bar.pm',
482        },
483        META_MERGE => { "meta-spec" => { version => 2 }},
484    );
485
486    is_deeply {
487        $mm->metafile_data(
488                {}, {
489                'meta-spec' => {
490                url     => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
491                version => 2
492                } } )
493    }, {
494        name            => 'Foo-Bar',
495        version         => 1.23,
496        abstract        => 'unknown',
497        author          => [],
498        license         => 'unknown',
499        dynamic_config  => 1,
500        distribution_type       => 'module',
501
502        prereqs => {
503            configure       => {
504                requires    => {
505                    'ExtUtils::MakeMaker'   => 0,
506                },
507            },
508            build           => {
509                requires    => {
510                    'Fake::Module1'         => 1.01,
511                },
512            },
513        },
514
515        no_index        => {
516            directory           => [qw(t inc)],
517        },
518
519        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
520        'meta-spec'  => {
521            url         => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
522            version     => 2
523        },
524    },'BUILD_REQUIRES meta-spec 2.0';
525}
526
527# Test TEST_REQUIRES meta-spec 1.4
528{
529    my $mm = $new_mm->(
530        DISTNAME        => 'Foo-Bar',
531        VERSION         => 1.23,
532        TEST_REQUIRES => {
533            "Fake::Module1"     => 1.01,
534        },
535        PM              => {
536            "Foo::Bar"          => 'lib/Foo/Bar.pm',
537        },
538    );
539
540    is_deeply {$mm->metafile_data}, {
541        name            => 'Foo-Bar',
542        version         => 1.23,
543        abstract        => 'unknown',
544        author          => [],
545        license         => 'unknown',
546        dynamic_config  => 1,
547        distribution_type       => 'module',
548
549        configure_requires      => {
550            'ExtUtils::MakeMaker'       => 0,
551        },
552        build_requires      => {
553            'ExtUtils::MakeMaker'       => 0,
554            'Fake::Module1'             => 1.01,
555        },
556
557        no_index        => {
558            directory           => [qw(t inc)],
559        },
560
561        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
562        'meta-spec'  => {
563            url         => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
564            version     => 1.4
565        },
566    },'TEST_REQUIRES meta-spec 1.4';
567}
568
569# Test TEST_REQUIRES meta-spec 2.0
570{
571    my $mm = $new_mm->(
572        DISTNAME        => 'Foo-Bar',
573        VERSION         => 1.23,
574        TEST_REQUIRES => {
575            "Fake::Module1"     => 1.01,
576        },
577        PM              => {
578            "Foo::Bar"          => 'lib/Foo/Bar.pm',
579        },
580        META_MERGE => { "meta-spec" => { version => 2 }},
581    );
582
583    is_deeply {
584        $mm->metafile_data(
585                {}, {
586                'meta-spec' => {
587                url     => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
588                version => 2
589                } } )
590    }, {
591        name            => 'Foo-Bar',
592        version         => 1.23,
593        abstract        => 'unknown',
594        author          => [],
595        license         => 'unknown',
596        dynamic_config  => 1,
597        distribution_type       => 'module',
598
599        prereqs => {
600            configure       => {
601                requires    => {
602                    'ExtUtils::MakeMaker'   => 0,
603                },
604            },
605            build           => {
606                requires    => {
607                    'ExtUtils::MakeMaker'   => 0,
608                },
609            },
610            test            => {
611                requires    => {
612                    "Fake::Module1"         => 1.01,
613                },
614            },
615        },
616
617        no_index        => {
618            directory           => [qw(t inc)],
619        },
620
621        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
622        'meta-spec'  => {
623            url         => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
624            version     => 2
625        },
626    },'TEST_REQUIRES meta-spec 2.0';
627}
628
629
630# Test _REQUIRES key priority over META_ADD
631
632{
633    my $mm = $new_mm->(
634        DISTNAME        => 'Foo-Bar',
635        VERSION         => 1.23,
636        BUILD_REQUIRES => {
637            "Fake::Module1" => 1.01,
638        },
639        META_ADD => (my $meta_add = { build_requires => {}, configure_requires => {} }),
640        PM              => {
641            "Foo::Bar"          => 'lib/Foo/Bar.pm',
642        },
643    );
644
645    is_deeply {$mm->metafile_data($meta_add)}, {
646        name            => 'Foo-Bar',
647        version         => 1.23,
648        abstract        => 'unknown',
649        author          => [],
650        license         => 'unknown',
651        dynamic_config  => 1,
652        distribution_type       => 'module',
653
654        configure_requires      => { },
655        build_requires          => { },
656
657        no_index        => {
658            directory           => [qw(t inc)],
659        },
660
661        generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
662        'meta-spec'  => {
663            url         => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
664            version     => 1.4
665        },
666    },'META.yml data (META_ADD wins)';
667
668
669    # Yes, this is all hard coded.
670    require CPAN::Meta;
671    my $want_mymeta = {
672        name            => 'ExtUtils-MakeMaker',
673        version         => '6.57_07',
674        abstract        => 'Create a module Makefile',
675        author          => ['Michael G Schwern <schwern@pobox.com>'],
676        license         => ['perl_5'],
677        dynamic_config  => 0,
678
679        prereqs => {
680            runtime => {
681                requires => {
682                    "DirHandle"         => 0,
683                    "File::Basename"    => 0,
684                    "File::Spec"        => "0.8",
685                    "Pod::Man"          => 0,
686                    "perl"              => "5.006",
687                },
688            },
689            configure => {
690                requires => {
691                    'ExtUtils::MakeMaker'   => 0,
692                },
693            },
694            build    => {
695                requires => {
696                    'Fake::Module1'       => 1.01,
697                },
698            },
699        },
700
701        release_status => 'testing',
702        resources => {
703            license     =>  [ 'http://dev.perl.org/licenses/' ],
704            homepage    =>  'http://makemaker.org',
705            bugtracker  =>  { web => 'http://rt.cpan.org/NoAuth/Bugs.html?Dist=ExtUtils-MakeMaker' },
706            repository  =>  { url => 'http://github.com/Perl-Toolchain-Gang/ExtUtils-MakeMaker' },
707            x_MailingList => 'makemaker@perl.org',
708        },
709
710        no_index        => {
711            directory           => [qw(t inc)],
712            package             => ["DynaLoader", "in"],
713        },
714
715        generated_by => "ExtUtils::MakeMaker version 6.5707, CPAN::Meta::Converter version 2.110580",
716        'meta-spec'  => {
717            url         => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
718            version     => 2,
719        },
720    };
721
722    mymeta_ok $mm->mymeta("t/META_for_testing.json"),
723              $want_mymeta,
724              'MYMETA JSON data (BUILD_REQUIRES wins)';
725
726    mymeta_ok $mm->mymeta("t/META_for_testing.yml"),
727              $want_mymeta,
728              'MYMETA YAML data (BUILD_REQUIRES wins)';
729}
730
731{
732    my $mm = $new_mm->(
733        DISTNAME            => 'Foo-Bar',
734        VERSION             => 1.23,
735        CONFIGURE_REQUIRES  => { "Fake::Module0" => 0.99 },
736        BUILD_REQUIRES      => { "Fake::Module1" => 1.01 },
737        TEST_REQUIRES       => { "Fake::Module2" => 1.23 },
738    );
739
740    my $meta = $mm->mymeta('t/META_for_testing.json');
741    is($meta->{configure_requires}, undef, "no configure_requires in v2 META");
742    is($meta->{build_requires}, undef, "no build_requires in v2 META");
743    is_deeply(
744        $meta->{prereqs}{configure}{requires},
745        { "Fake::Module0" => 0.99 },
746        "configure requires are one thing in META v2...",
747    );
748
749    is_deeply(
750        $meta->{prereqs}{build}{requires},
751        { "Fake::Module1" => 1.01 },
752        "build requires are one thing in META v2...",
753    );
754
755    is_deeply(
756        $meta->{prereqs}{test}{requires},
757        { "Fake::Module2" => 1.23 },
758        "...and test requires are another",
759    );
760}
761
762note "CPAN::Meta bug using the module version instead of the meta spec version"; {
763    my $mm = $new_mm->(
764        NAME      => 'GD::Barcode::Code93',
765        AUTHOR    => 'Chris DiMartino',
766        ABSTRACT  => 'Code 93 implementation of GD::Barcode family',
767        PREREQ_PM => {
768            'GD::Barcode' => 0,
769            'GD'          => 0
770        },
771        VERSION   => '1.4',
772    );
773
774    my $meta = $mm->mymeta("t/META_for_testing_tricky_version.yml");
775    is $meta->{'meta-spec'}{version}, 2, "internally, our MYMETA struct is v2";
776
777    in_dir {
778        $mm->write_mymeta($meta);
779        ok -e "MYMETA.yml";
780        ok -e "MYMETA.json";
781
782        my $meta_yml = Parse::CPAN::Meta->load_file("MYMETA.yml");
783        is $meta_yml->{'meta-spec'}{version}, 1.4, "MYMETA.yml correctly downgraded to 1.4";
784
785        my $meta_json = Parse::CPAN::Meta->load_file("MYMETA.json");
786        cmp_ok $meta_json->{'meta-spec'}{version}, ">=", 2, "MYMETA.json at 2 or better";
787    };
788}
789
790
791note "A bad license string"; {
792    my $mm = $new_mm->(
793        DISTNAME  => 'Foo::Bar',
794        VERSION   => '1.4',
795        LICENSE   => 'death and retribution',
796    );
797
798    in_dir {
799        my $meta = $mm->mymeta;
800        $mm->write_mymeta($meta);
801
802        my $meta_yml = Parse::CPAN::Meta->load_file("MYMETA.yml");
803        is $meta_yml->{license}, "unknown", "in yaml";
804
805        my $meta_json = Parse::CPAN::Meta->load_file("MYMETA.json");
806        is_deeply $meta_json->{license}, ["unknown"], "in json";
807    };
808}
809