1BEGIN { 2 unshift @INC, 't/lib'; 3} 4 5use strict; 6use warnings; 7use Test::More; 8BEGIN { 9 eval { require CPAN::Meta; CPAN::Meta->VERSION(2.143240) } 10 or plan skip_all => 'CPAN::Meta 2.143240 required for this test'; 11 eval { require CPAN::Meta::Converter; } 12 or plan skip_all => 'CPAN::Meta::Converter required for this test'; 13 eval { require Parse::CPAN::Meta; } 14 or plan skip_all => 'Parse::CPAN::Meta required for this test'; 15} 16use Data::Dumper; 17use File::Temp; 18use Cwd; 19use MakeMaker::Test::Utils; 20 21plan tests => 35; 22require ExtUtils::MM_Any; 23 24sub mymeta_ok { 25 my($have, $want, $name) = @_; 26 local $Test::Builder::Level = $Test::Builder::Level + 1; 27 my $have_gen = delete $have->{generated_by}; 28 my $want_gen = delete $want->{generated_by}; 29 my $have_url = delete $have->{'meta-spec'}->{url}; 30 my $want_url = delete $want->{'meta-spec'}->{url}; 31 is_deeply $have, $want, $name; 32 like $have_gen, qr{CPAN::Meta}, "CPAN::Meta mentioned in the generated_by"; 33 like $have_url, qr{CPAN::Meta::Spec}, "CPAN::Meta::Spec mentioned in meta-spec URL"; 34 return; 35} 36 37my $new_mm = sub { 38 return bless { ARGS => {@_}, @_ }, 'ExtUtils::MM_Any'; 39}; 40my @METASPEC14 = ( 41 'meta-spec' => { 42 url => 'http://module-build.sourceforge.net/META-spec-v1.4.html', 43 version => 1.4 44 }, 45); 46my @METASPEC20 = ( 47 'meta-spec' => { 48 url => 'https://metacpan.org/pod/CPAN::Meta::Spec', 49 version => 2 50 }, 51); 52my @REQ20 = ( 53 configure => { requires => { 'ExtUtils::MakeMaker' => 0, }, }, 54 build => { requires => { 'ExtUtils::MakeMaker' => 0, }, }, 55); 56my @GENERIC_IN = ( 57 DISTNAME => 'Foo-Bar', 58 VERSION => 1.23, 59 PM => { "Foo::Bar" => 'lib/Foo/Bar.pm', }, 60); 61my @GENERIC_OUT = ( 62 # mandatory 63 abstract => 'unknown', 64 author => [qw(unknown)], 65 dynamic_config => 1, 66 generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION", 67 license => ['unknown'], 68 @METASPEC20, 69 name => 'Foo-Bar', 70 release_status => 'stable', 71 version => 1.23, 72 # optional 73 no_index => { directory => [qw(t inc)], }, 74); 75 76{ 77 my $mm = $new_mm->(@GENERIC_IN); 78 is_deeply $mm->metafile_data, { 79 @GENERIC_OUT, 80 prereqs => { @REQ20, }, 81 }; 82 is_deeply $mm->metafile_data({}, { no_index => { directory => [qw(foo)] } }), { 83 @GENERIC_OUT, 84 prereqs => { @REQ20, }, 85 no_index => { directory => [qw(t inc foo)], }, 86 }, 'rt.cpan.org 39348'; 87} 88 89{ 90 my $mm = $new_mm->( 91 DISTNAME => 'Foo-Bar', 92 VERSION => 1.23, 93 AUTHOR => ['Some Guy'], 94 PREREQ_PM => { Foo => 2.34, Bar => 4.56, }, 95 ); 96 is_deeply $mm->metafile_data( 97 { 98 configure_requires => { Stuff => 2.34 }, 99 wobble => 42 100 }, 101 { 102 no_index => { package => "Thing" }, 103 wibble => 23 104 }, 105 ), 106 { 107 @GENERIC_OUT, # some overridden, which is fine 108 author => ['Some Guy'], 109 prereqs => { 110 @REQ20, 111 configure => { requires => { Stuff => 2.34, }, }, 112 runtime => { requires => { Foo => 2.34, Bar => 4.56, }, }, 113 }, 114 no_index => { 115 directory => [qw(t inc)], 116 package => ['Thing'], 117 }, 118 x_wibble => 23, 119 x_wobble => 42, 120 }, '_add vs _merge'; 121} 122 123# Test MIN_PERL_VERSION meta-spec 1.4 124{ 125 my $mm = $new_mm->( 126 @GENERIC_IN, 127 MIN_PERL_VERSION => 5.006, 128 ); 129 is_deeply $mm->metafile_data( {}, { @METASPEC14 }, ), { 130 @GENERIC_OUT, 131 prereqs => { 132 @REQ20, 133 runtime => { requires => { perl => 5.006, }, }, 134 }, 135 }, 'MIN_PERL_VERSION meta-spec 1.4'; 136} 137 138# Test MIN_PERL_VERSION meta-spec 2.0 139{ 140 my $mm = $new_mm->( 141 @GENERIC_IN, 142 MIN_PERL_VERSION => 5.006, 143 ); 144 is_deeply $mm->metafile_data, { 145 prereqs => { 146 @REQ20, 147 runtime => { requires => { 'perl' => '5.006', }, }, 148 }, 149 @GENERIC_OUT, 150 }, 'MIN_PERL_VERSION meta-spec 2.0'; 151} 152 153# Test MIN_PERL_VERSION meta-spec 1.4 154{ 155 my $mm = $new_mm->( 156 @GENERIC_IN, 157 MIN_PERL_VERSION => 5.006, 158 PREREQ_PM => { 'Foo::Bar' => 1.23, }, 159 ); 160 is_deeply $mm->metafile_data, { 161 @GENERIC_OUT, 162 prereqs => { 163 @REQ20, 164 runtime => { 165 requires => { 166 'Foo::Bar' => 1.23, 167 'perl' => '5.006', 168 }, 169 }, 170 }, 171 }, 'MIN_PERL_VERSION and PREREQ_PM meta-spec 1.4'; 172} 173 174# Test CONFIGURE_REQUIRES meta-spec 1.4 175{ 176 my $mm = $new_mm->( 177 @GENERIC_IN, 178 CONFIGURE_REQUIRES => { "Fake::Module1" => 1.01, }, 179 ); 180 is_deeply $mm->metafile_data( {}, { @METASPEC14 }, ), { 181 prereqs => { 182 @REQ20, 183 configure => { requires => { 'Fake::Module1' => 1.01, }, }, 184 }, 185 @GENERIC_OUT, 186 },'CONFIGURE_REQUIRES meta-spec 1.4'; 187} 188 189# Test CONFIGURE_REQUIRES meta-spec 2.0 190{ 191 my $mm = $new_mm->( 192 @GENERIC_IN, 193 CONFIGURE_REQUIRES => { "Fake::Module1" => 1.01, }, 194 ); 195 is_deeply $mm->metafile_data, { 196 prereqs => { 197 @REQ20, 198 configure => { requires => { 'Fake::Module1' => 1.01, }, }, 199 }, 200 @GENERIC_OUT, 201 },'CONFIGURE_REQUIRES meta-spec 2.0'; 202} 203 204# Test BUILD_REQUIRES meta-spec 1.4 205{ 206 my $mm = $new_mm->( 207 @GENERIC_IN, 208 BUILD_REQUIRES => { "Fake::Module1" => 1.01, }, 209 META_MERGE => { "meta-spec" => { version => 1.4 }}, 210 ); 211 is_deeply $mm->metafile_data( {}, { @METASPEC14 }, ), { 212 prereqs => { 213 @REQ20, 214 build => { requires => { 'Fake::Module1' => 1.01, }, }, 215 }, 216 @GENERIC_OUT, 217 },'BUILD_REQUIRES meta-spec 1.4'; 218} 219 220# Test BUILD_REQUIRES meta-spec 2.0 221{ 222 my $mm = $new_mm->( 223 @GENERIC_IN, 224 BUILD_REQUIRES => { "Fake::Module1" => 1.01, }, 225 ); 226 is_deeply $mm->metafile_data, { 227 prereqs => { 228 @REQ20, 229 build => { requires => { 'Fake::Module1' => 1.01, }, }, 230 }, 231 @GENERIC_OUT, 232 },'BUILD_REQUIRES meta-spec 2.0'; 233} 234 235# Test TEST_REQUIRES meta-spec 1.4 236{ 237 my $mm = $new_mm->( 238 @GENERIC_IN, 239 TEST_REQUIRES => { "Fake::Module1" => 1.01, }, 240 META_MERGE => { "meta-spec" => { version => 1.4 }}, 241 ); 242 is_deeply $mm->metafile_data( {}, { @METASPEC14 }, ), { 243 prereqs => { 244 @REQ20, 245 test => { requires => { "Fake::Module1" => 1.01, }, }, 246 }, 247 @GENERIC_OUT, 248 },'TEST_REQUIRES meta-spec 1.4'; 249} 250 251# Test TEST_REQUIRES meta-spec 2.0 252{ 253 my $mm = $new_mm->( 254 @GENERIC_IN, 255 TEST_REQUIRES => { "Fake::Module1" => 1.01, }, 256 ); 257 is_deeply $mm->metafile_data, { 258 prereqs => { 259 @REQ20, 260 test => { requires => { "Fake::Module1" => 1.01, }, }, 261 }, 262 @GENERIC_OUT, 263 },'TEST_REQUIRES meta-spec 2.0'; 264} 265 266{ 267 my $mm = $new_mm->( 268 @GENERIC_IN, 269 ); 270 is_deeply $mm->metafile_data( 271 { 272 resources => { 273 homepage => "https://metacpan.org/release/ExtUtils-MakeMaker", 274 repository => "http://github.com/Perl-Toolchain-Gang/ExtUtils-MakeMaker", 275 }, 276 }, 277 { @METASPEC14 }, 278 ), { 279 prereqs => { @REQ20 }, 280 resources => { 281 homepage => "https://metacpan.org/release/ExtUtils-MakeMaker", 282 repository => { 283 url => "http://github.com/Perl-Toolchain-Gang/ExtUtils-MakeMaker", 284 }, 285 }, 286 @GENERIC_OUT, 287 }, 'META_ADD takes meta version 1.4 from META_MERGE'; 288} 289 290{ 291 my $mm = $new_mm->( 292 @GENERIC_IN, 293 ); 294 is_deeply $mm->metafile_data( 295 { @METASPEC14 }, 296 { 297 resources => { 298 homepage => "https://metacpan.org/release/ExtUtils-MakeMaker", 299 repository => "http://github.com/Perl-Toolchain-Gang/ExtUtils-MakeMaker", 300 }, 301 }, 302 ), { 303 prereqs => { @REQ20 }, 304 resources => { 305 homepage => "https://metacpan.org/release/ExtUtils-MakeMaker", 306 repository => { 307 url => "http://github.com/Perl-Toolchain-Gang/ExtUtils-MakeMaker", 308 }, 309 }, 310 @GENERIC_OUT, 311 }, 'META_MERGE takes meta version 1.4 from META_ADD'; 312} 313 314{ 315 my $mm = $new_mm->( 316 @GENERIC_IN, 317 ); 318 is_deeply $mm->metafile_data( 319 { 320 'configure_requires' => { 321 'Fake::Module1' => 1, 322 }, 323 'prereqs' => { 324 @REQ20, 325 'test' => { 326 'requires' => { 327 'Fake::Module2' => 2, 328 }, 329 }, 330 }, 331 }, 332 { @METASPEC20 }, 333 ), { 334 prereqs => { 335 @REQ20, 336 test => { requires => { "Fake::Module2" => 2, }, }, 337 }, 338 @GENERIC_OUT, 339 }, 'META_ADD takes meta version 2 from META_MERGE'; 340} 341 342{ 343 my $mm = $new_mm->( 344 @GENERIC_IN, 345 ); 346 is_deeply $mm->metafile_data( 347 { @METASPEC20 }, 348 { 349 'configure_requires' => { 350 'Fake::Module1' => 1, 351 }, 352 'prereqs' => { 353 @REQ20, 354 'test' => { 355 'requires' => { 356 'Fake::Module2' => 2, 357 }, 358 }, 359 }, 360 }, 361 ), { 362 prereqs => { 363 @REQ20, 364 test => { requires => { "Fake::Module2" => 2, }, }, 365 }, 366 @GENERIC_OUT, 367 }, 'META_MERGE takes meta version 2 from META_ADD'; 368} 369 370# Test _REQUIRES key priority over META_ADD 371{ 372 my $mm = $new_mm->( 373 @GENERIC_IN, 374 BUILD_REQUIRES => { "Fake::Module1" => 1.01, }, 375 META_ADD => (my $meta_add = { build_requires => {}, configure_requires => {} }), 376 ); 377 is_deeply $mm->metafile_data($meta_add), { 378 prereqs => { 379 configure => { requires => { }, }, 380 build => { requires => { }, }, 381 }, 382 @GENERIC_OUT, 383 },'META.yml data (META_ADD wins)'; 384 # Yes, this is all hard coded. 385 386 my $want_mymeta = { 387 name => 'ExtUtils-MakeMaker', 388 version => '6.57_07', 389 abstract => 'Create a module Makefile', 390 author => ['Michael G Schwern <schwern@pobox.com>'], 391 license => ['perl_5'], 392 dynamic_config => 0, 393 prereqs => { 394 runtime => { 395 requires => { 396 "DirHandle" => 0, 397 "File::Basename" => 0, 398 "File::Spec" => "0.8", 399 "Pod::Man" => 0, 400 "perl" => "5.006", 401 }, 402 }, 403 @REQ20, 404 build => { requires => { 'Fake::Module1' => 1.01, }, }, 405 }, 406 release_status => 'testing', 407 resources => { 408 license => [ 'http://dev.perl.org/licenses/' ], 409 homepage => 'http://makemaker.org', 410 bugtracker => { web => 'http://rt.cpan.org/NoAuth/Bugs.html?Dist=ExtUtils-MakeMaker' }, 411 repository => { url => 'http://github.com/Perl-Toolchain-Gang/ExtUtils-MakeMaker' }, 412 x_MailingList => 'makemaker@perl.org', 413 }, 414 no_index => { 415 directory => [qw(t inc)], 416 package => ["DynaLoader", "in"], 417 }, 418 generated_by => "ExtUtils::MakeMaker version 6.5707, CPAN::Meta::Converter version 2.110580", 419 @METASPEC20, 420 }; 421 mymeta_ok $mm->mymeta("t/META_for_testing.json"), 422 $want_mymeta, 423 'MYMETA JSON data (BUILD_REQUIRES wins)'; 424 mymeta_ok $mm->mymeta("t/META_for_testing.yml"), 425 $want_mymeta, 426 'MYMETA YAML data (BUILD_REQUIRES wins)'; 427} 428 429{ 430 my $mm = $new_mm->( 431 @GENERIC_IN, 432 CONFIGURE_REQUIRES => { "Fake::Module0" => 0.99 }, 433 BUILD_REQUIRES => { "Fake::Module1" => 1.01 }, 434 TEST_REQUIRES => { "Fake::Module2" => 1.23 }, 435 ); 436 my $meta = $mm->mymeta('t/META_for_testing.json'); 437 is($meta->{configure_requires}, undef, "no configure_requires in v2 META"); 438 is($meta->{build_requires}, undef, "no build_requires in v2 META"); 439 is_deeply( 440 $meta->{prereqs}{configure}{requires}, 441 { "Fake::Module0" => 0.99 }, 442 "configure requires are one thing in META v2...", 443 ); 444 is_deeply( 445 $meta->{prereqs}{build}{requires}, 446 { "Fake::Module1" => 1.01 }, 447 "build requires are one thing in META v2...", 448 ); 449 is_deeply( 450 $meta->{prereqs}{test}{requires}, 451 { "Fake::Module2" => 1.23 }, 452 "...and test requires are another", 453 ); 454} 455 456note "CPAN::Meta bug using the module version instead of the meta spec version"; 457{ 458 my $mm = $new_mm->( 459 NAME => 'GD::Barcode::Code93', 460 AUTHOR => 'Chris DiMartino', 461 ABSTRACT => 'Code 93 implementation of GD::Barcode family', 462 PREREQ_PM => { 463 'GD::Barcode' => 0, 464 'GD' => 0 465 }, 466 VERSION => '1.4', 467 ); 468 my $meta = $mm->mymeta("t/META_for_testing_tricky_version.yml"); 469 is $meta->{'meta-spec'}{version}, 2, "internally, our MYMETA struct is v2"; 470 in_dir { 471 $mm->write_mymeta($meta); 472 ok -e "MYMETA.yml"; 473 ok -e "MYMETA.json"; 474 my $meta_yml = Parse::CPAN::Meta->load_file("MYMETA.yml"); 475 is $meta_yml->{'meta-spec'}{version}, 1.4, "MYMETA.yml correctly downgraded to 1.4"; 476 my $meta_json = Parse::CPAN::Meta->load_file("MYMETA.json"); 477 cmp_ok $meta_json->{'meta-spec'}{version}, ">=", 2, "MYMETA.json at 2 or better"; 478 }; 479} 480 481note "A bad license string"; 482{ 483 my $mm = $new_mm->( 484 @GENERIC_IN, 485 LICENSE => 'death and retribution', 486 ); 487 in_dir { 488 my $meta = $mm->mymeta; 489 { 490 local $SIG{__WARN__} = sub {}; # suppress "Invalid" warning 491 $mm->write_mymeta($meta); 492 } 493 my $meta_yml = Parse::CPAN::Meta->load_file("MYMETA.yml"); 494 is $meta_yml->{license}, "unknown", "in yaml"; 495 my $meta_json = Parse::CPAN::Meta->load_file("MYMETA.json"); 496 is_deeply $meta_json->{license}, ["unknown"], "in json"; 497 }; 498} 499