1use strict; 2use warnings; 3 4use Test::More; 5use CPAN::Meta; 6use CPAN::Meta::Merge; 7 8delete $ENV{PERL_YAML_BACKEND}; 9delete $ENV{PERL_JSON_BACKEND}; 10delete $ENV{CPAN_META_JSON_BACKEND}; 11delete $ENV{CPAN_META_JSON_DECODER}; 12 13my %base = ( 14 abstract => 'This is a test', 15 author => ['A.U. Thor'], 16 generated_by => 'Myself', 17 license => [ 'perl_5' ], 18 resources => { 19 license => [ 'http://dev.perl.org/licenses/' ], 20 bugtracker => { web => 'https://rt.cpan.org/Dist/Display.html?Foo-Bar' }, 21 }, 22 prereqs => { 23 runtime => { 24 requires => { 25 Foo => '0', 26 }, 27 }, 28 }, 29 dynamic_config => 0, 30 provides => { 31 Baz => { 32 file => 'lib/Baz.pm', 33 }, 34 }, 35 'meta-spec' => { 36 url => "http://search.cpan.org/perldoc?CPAN::Meta::Spec", 37 version => 2, 38 }, 39); 40 41my %first = ( 42 author => [ 'I.M. Poster' ], 43 generated_by => 'Some other guy', 44 license => [ 'bsd' ], 45 resources => { 46 license => [ 'http://opensource.org/licenses/bsd-license.php' ], 47 }, 48 prereqs => { 49 runtime => { 50 requires => { 51 Foo => '< 1', 52 }, 53 recommends => { 54 Bar => '3.14', 55 }, 56 }, 57 test => { 58 requires => { 59 'Test::Bar' => 0, 60 }, 61 }, 62 }, 63 dynamic_config => 1, 64 provides => { 65 Quz => { 66 file => 'lib/Quz.pm', 67 }, 68 }, 69); 70my %first_expected = ( 71 abstract => 'This is a test', 72 author => [ 'A.U. Thor', 'I.M. Poster' ], 73 generated_by => 'Myself, Some other guy', 74 license => [ 'perl_5', 'bsd' ], 75 resources => { 76 license => [ 'http://dev.perl.org/licenses/', 'http://opensource.org/licenses/bsd-license.php' ], 77 bugtracker => { web => 'https://rt.cpan.org/Dist/Display.html?Foo-Bar' }, 78 }, 79 prereqs => { 80 runtime => { 81 requires => { 82 Foo => '>= 0, < 1', 83 }, 84 recommends => { 85 Bar => '3.14', 86 }, 87 }, 88 test => { 89 requires => { 90 'Test::Bar' => 0, 91 }, 92 }, 93 }, 94 provides => { 95 Baz => { 96 file => 'lib/Baz.pm', 97 }, 98 Quz => { 99 file => 'lib/Quz.pm', 100 }, 101 }, 102 dynamic_config => 1, 103 'meta-spec' => { 104 url => "http://search.cpan.org/perldoc?CPAN::Meta::Spec", 105 version => 2, 106 }, 107); 108my %provides_merge_expected = ( 109 abstract => 'This is a test', 110 author => ['A.U. Thor'], 111 generated_by => 'Myself', 112 license => [ 'perl_5' ], 113 resources => { 114 license => [ 'http://dev.perl.org/licenses/' ], 115 bugtracker => { web => 'https://rt.cpan.org/Dist/Display.html?Foo-Bar' }, 116 }, 117 prereqs => { 118 runtime => { 119 requires => { 120 Foo => '0', 121 }, 122 }, 123 }, 124 dynamic_config => 0, 125 provides => { 126 Baz => { 127 file => 'lib/Baz.pm', 128 version => '0.001', # same as %base, but for this extra key 129 }, 130 }, 131 'meta-spec' => { 132 url => "http://search.cpan.org/perldoc?CPAN::Meta::Spec", 133 version => 2, 134 }, 135); 136 137my $merger = CPAN::Meta::Merge->new(default_version => '2'); 138 139my $first_result = $merger->merge(\%base, \%first); 140 141is_deeply($first_result, \%first_expected, 'First result is as expected'); 142 143is_deeply($merger->merge(\%base, { abstract => 'This is a test' }), \%base, 'Can merge in identical abstract'); 144is( 145 eval { $merger->merge(\%base, { abstract => 'And now for something else' }) }, 146 undef, 147 'Trying to merge different abstract gives an exception', 148); 149like $@, qr/^Can't merge attribute abstract/, 'Exception looks right'; 150 151is( 152 eval { $merger->merge(\%base, { resources => { bugtracker => { web => 'http://foo.com' } } } ) }, 153 undef, 154 'Trying to merge a different bugtracker URL gives an exception', 155); 156like $@, qr/^Duplication of element resources\.bugtracker\.web /, 'Exception looks right'; 157 158is( 159 eval { $merger->merge(\%base, { provides => { Baz => { file => 'Baz.pm' } } }) }, 160 undef, 161 'Trying to merge different provides.$module.file gives an exception', 162); 163like $@, qr/^Duplication of element provides\.Baz\.file /, 'Exception looks right'; 164 165my $provides_result = $merger->merge(\%base, { provides => { Baz => { file => 'lib/Baz.pm', version => '0.001' } } }); 166is_deeply( 167 $provides_result, 168 \%provides_merge_expected, 169 'Trying to merge a new key for provides.$module is permitted; identical values are preserved', 170); 171 172my $extra_merger = CPAN::Meta::Merge->new( 173 default_version => '2', 174 extra_mappings => { 175 'x_toolkit' => 'set_addition', 176 'x_meta_meta' => { 177 name => 'identical', 178 tags => 'set_addition', 179 } 180 } 181); 182 183my $extra_results = $extra_merger->merge(\%base, { 184 x_toolkit => [ 'marble' ], 185 x_meta_meta => { 186 name => 'Test', 187 tags => [ 'Testing' ], 188 } 189 }, 190 { x_toolkit => [ 'trike'], 191 x_meta_meta => { 192 name => 'Test', 193 tags => [ 'TDD' ], 194 } 195 } 196); 197 198my $expected_nested_extra = { 199 name => 'Test', 200 tags => [ 'Testing', 'TDD' ], 201}; 202is_deeply($extra_results->{x_toolkit}, [ 'marble', 'trike' ], 'Extra mapping fields are merged'); 203is_deeply($extra_results->{x_meta_meta}, $expected_nested_extra, 'Nested extra mapping fields are merged' ); 204 205my $adds_to = sub { 206 my ($left, $right, $path) = @_; 207 if ($right !~ /^\Q$left\E/) { 208 die sprintf "Can't merge attribute %s: '%s' does not start with '%s'", join('.', @{$path}), $right, $left; 209 } 210 return $right; 211}; 212 213$extra_merger = CPAN::Meta::Merge->new(default_version => '2', extra_mappings => { 'abstract' => \&$adds_to } ); 214my $extra_results2 = $extra_merger->merge({ abstract => 'This is a test.'}, { abstract => 'This is a test. Includes more detail..' } ); 215is($extra_results2->{abstract}, 'This is a test. Includes more detail..', 'Extra mapping fields overwrite existing mappings'); 216my $extra_failure = eval { $extra_merger->merge({ abstract => 'This is a test.'}, { abstract => 'This is a better test.' } ) }; 217is($extra_failure, undef, 'Extra mapping produces a failure'); 218like $@, qr/does not start with/, 'Exception looks right'; 219 220 221 222# issue 67 223@base{qw/name version release_status/} = qw/Foo-Bar 0.01 testing/; 224my $base_obj = CPAN::Meta->create(\%base); 225ok my $first_result_obj = $merger->merge($base_obj, \%first), 'merging CPAN::Meta objects succeeds'; 226 227done_testing(); 228# vim: ts=4 sts=4 sw=4 tw=78 noet : 229