10 use vars qw{@ISA @EXPORT};
12 @ISA = qw{ Exporter };
14 tests yaml_ok yaml_error slurp load_ok
19 # Do we have the authorative YAML to test against
23 # This doesn't currently work, but is documented to.
24 # So if it ever turns up, use it.
25 $YAML::UseVersion = 1;
27 my $HAVE_YAMLPM = !! (
30 $YAML::VERSION >= 0.66
32 sub have_yamlpm { $HAVE_YAMLPM }
34 # Do we have YAML::Perl to test against?
38 my $HAVE_YAMLPERL = !! (
41 $YAML::Perl::VERSION >= 0.02
43 sub have_yamlperl { $HAVE_YAMLPERL }
45 # Do we have YAML::Syck to test against?
52 $YAML::Syck::VERSION >= 1.05
54 sub have_syck { $HAVE_SYCK }
56 # Do we have YAML::XS to test against?
63 $YAML::XS::VERSION >= 0.29
65 sub have_xs{ $HAVE_XS }
67 # 22 tests per call to yaml_ok
68 # 4 tests per call to load_ok
70 return ( tests => count(@_) );
73 sub test_data_directory {
74 return File::Spec->catdir( 't', 'data' );
78 my $yaml_ok = shift || 0;
79 my $load_ok = shift || 0;
80 my $single = shift || 0;
81 my $count = $yaml_ok * 38 + $load_ok * 4 + $single;
88 my $name = shift || 'unnamed';
90 bless $object, 'CPAN::Meta::YAML';
92 # If YAML itself is available, test with it
94 unless ( $HAVE_YAMLPM ) {
95 Test::More::skip( "Skipping YAML.pm, not available for testing", 7 );
97 if ( $options{noyamlpm} ) {
98 Test::More::skip( "Skipping YAML.pm for known-broken feature", 7 );
101 # Test writing with YAML.pm
102 my $yamlpm_out = eval { YAML::Dump( @$object ) };
103 Test::More::is( $@, '', "$name: YAML.pm saves without error" );
105 Test::More::skip( "Shortcutting after failure", 4 ) if $@;
107 !!(defined $yamlpm_out and ! ref $yamlpm_out),
108 "$name: YAML.pm serializes correctly",
110 my @yamlpm_round = eval { YAML::Load( $yamlpm_out ) };
111 Test::More::is( $@, '', "$name: YAML.pm round-trips without error" );
112 Test::More::skip( "Shortcutting after failure", 2 ) if $@;
113 my $round = bless [ @yamlpm_round ], 'CPAN::Meta::YAML';
114 Test::More::is_deeply( $round, $object, "$name: YAML.pm round-trips correctly" );
117 # Test reading with YAML.pm
118 my $yamlpm_copy = $string;
119 my @yamlpm_in = eval { YAML::Load( $yamlpm_copy ) };
120 Test::More::is( $@, '', "$name: YAML.pm loads without error" );
121 Test::More::is( $yamlpm_copy, $string, "$name: YAML.pm does not modify the input string" );
123 Test::More::skip( "Shortcutting after failure", 1 ) if $@;
124 Test::More::is_deeply( \@yamlpm_in, $object, "$name: YAML.pm parses correctly" );
128 # If YAML::Syck itself is available, test with it
130 unless ( $HAVE_SYCK ) {
131 Test::More::skip( "Skipping YAML::Syck, not available for testing", 7 );
133 if ( $options{nosyck} ) {
134 Test::More::skip( "Skipping YAML::Syck for known-broken feature", 7 );
136 unless ( @$object == 1 ) {
137 Test::More::skip( "Skipping YAML::Syck for unsupported feature", 7 );
140 # Test writing with YAML::Syck
141 my $syck_out = eval { YAML::Syck::Dump( @$object ) };
142 Test::More::is( $@, '', "$name: YAML::Syck saves without error" );
144 Test::More::skip( "Shortcutting after failure", 4 ) if $@;
146 !!(defined $syck_out and ! ref $syck_out),
147 "$name: YAML::Syck serializes correctly",
149 my @syck_round = eval { YAML::Syck::Load( $syck_out ) };
150 Test::More::is( $@, '', "$name: YAML::Syck round-trips without error" );
151 Test::More::skip( "Shortcutting after failure", 2 ) if $@;
152 my $round = bless [ @syck_round ], 'CPAN::Meta::YAML';
153 Test::More::is_deeply( $round, $object, "$name: YAML::Syck round-trips correctly" );
156 # Test reading with YAML::Syck
157 my $syck_copy = $string;
158 my @syck_in = eval { YAML::Syck::Load( $syck_copy ) };
159 Test::More::is( $@, '', "$name: YAML::Syck loads without error" );
160 Test::More::is( $syck_copy, $string, "$name: YAML::Syck does not modify the input string" );
162 Test::More::skip( "Shortcutting after failure", 1 ) if $@;
163 Test::More::is_deeply( \@syck_in, $object, "$name: YAML::Syck parses correctly" );
167 # If YAML::XS itself is available, test with it
169 unless ( $HAVE_XS ) {
170 Test::More::skip( "Skipping YAML::XS, not available for testing", 7 );
172 if ( $options{noxs} ) {
173 Test::More::skip( "Skipping YAML::XS for known-broken feature", 7 );
176 # Test writing with YAML::XS
177 my $xs_out = eval { YAML::XS::Dump( @$object ) };
178 Test::More::is( $@, '', "$name: YAML::XS saves without error" );
180 Test::More::skip( "Shortcutting after failure", 4 ) if $@;
182 !!(defined $xs_out and ! ref $xs_out),
183 "$name: YAML::XS serializes correctly",
185 my @xs_round = eval { YAML::XS::Load( $xs_out ) };
186 Test::More::is( $@, '', "$name: YAML::XS round-trips without error" );
187 Test::More::skip( "Shortcutting after failure", 2 ) if $@;
188 my $round = bless [ @xs_round ], 'CPAN::Meta::YAML';
189 Test::More::is_deeply( $round, $object, "$name: YAML::XS round-trips correctly" );
192 # Test reading with YAML::XS
193 my $xs_copy = $string;
194 my @xs_in = eval { YAML::XS::Load( $xs_copy ) };
195 Test::More::is( $@, '', "$name: YAML::XS loads without error" );
196 Test::More::is( $xs_copy, $string, "$name: YAML::XS does not modify the input string" );
198 Test::More::skip( "Shortcutting after failure", 1 ) if $@;
199 Test::More::is_deeply( \@xs_in, $object, "$name: YAML::XS parses correctly" );
203 # If YAML::Perl is available, test with it
205 unless ( $HAVE_YAMLPERL ) {
206 Test::More::skip( "Skipping YAML::Perl, not available for testing", 7 );
208 if ( $options{noyamlperl} ) {
209 Test::More::skip( "Skipping YAML::Perl for known-broken feature", 7 );
212 # Test writing with YAML.pm
213 my $yamlperl_out = eval { YAML::Perl::Dump( @$object ) };
214 Test::More::is( $@, '', "$name: YAML::Perl saves without error" );
216 Test::More::skip( "Shortcutting after failure", 4 ) if $@;
218 !!(defined $yamlperl_out and ! ref $yamlperl_out),
219 "$name: YAML::Perl serializes correctly",
221 my @yamlperl_round = eval { YAML::Perl::Load( $yamlperl_out ) };
222 Test::More::is( $@, '', "$name: YAML::Perl round-trips without error" );
223 Test::More::skip( "Shortcutting after failure", 2 ) if $@;
224 my $round = bless [ @yamlperl_round ], 'CPAN::Meta::YAML';
225 Test::More::is_deeply( $round, $object, "$name: YAML::Perl round-trips correctly" );
228 # Test reading with YAML::Perl
229 my $yamlperl_copy = $string;
230 my @yamlperl_in = eval { YAML::Perl::Load( $yamlperl_copy ) };
231 Test::More::is( $@, '', "$name: YAML::Perl loads without error" );
232 Test::More::is( $yamlperl_copy, $string, "$name: YAML::Perl does not modify the input string" );
234 Test::More::skip( "Shortcutting after failure", 1 ) if $@;
235 Test::More::is_deeply( \@yamlperl_in, $object, "$name: YAML::Perl parses correctly" );
239 # Does the string parse to the structure
240 my $yaml_copy = $string;
241 my $yaml = eval { CPAN::Meta::YAML->read_string( $yaml_copy ); };
242 Test::More::is( $@, '', "$name: CPAN::Meta::YAML parses without error" );
243 Test::More::is( $yaml_copy, $string, "$name: CPAN::Meta::YAML does not modify the input string" );
245 Test::More::skip( "Shortcutting after failure", 2 ) if $@;
246 Test::More::isa_ok( $yaml, 'CPAN::Meta::YAML' );
247 Test::More::is_deeply( $yaml, $object, "$name: CPAN::Meta::YAML parses correctly" );
250 # Does the structure serialize to the string.
251 # We can't test this by direct comparison, because any
252 # whitespace or comments would be lost.
253 # So instead we parse back in.
254 my $output = eval { $object->write_string };
255 Test::More::is( $@, '', "$name: CPAN::Meta::YAML serializes without error" );
257 Test::More::skip( "Shortcutting after failure", 5 ) if $@;
259 !!(defined $output and ! ref $output),
260 "$name: CPAN::Meta::YAML serializes correctly",
262 my $roundtrip = eval { CPAN::Meta::YAML->read_string( $output ) };
263 Test::More::is( $@, '', "$name: CPAN::Meta::YAML round-trips without error" );
264 Test::More::skip( "Shortcutting after failure", 2 ) if $@;
265 Test::More::isa_ok( $roundtrip, 'CPAN::Meta::YAML' );
266 Test::More::is_deeply( $roundtrip, $object, "$name: CPAN::Meta::YAML round-trips correctly" );
268 # Testing the serialization
269 Test::More::skip( "Shortcutting perfect serialization tests", 1 ) unless $options{serializes};
270 Test::More::is( $output, $string, 'Serializes ok' );
273 # Return true as a convenience
280 my $yaml = CPAN::Meta::YAML->read_string( $string );
281 Test::More::is( $yaml, undef, '->read_string returns undef' );
282 Test::More::ok( CPAN::Meta::YAML->errstr =~ /$like/, "Got expected error" );
283 # NOTE: like() gives better diagnostics (but requires 5.005)
284 # Test::More::like( $@, qr/$_[0]/, "CPAN::Meta::YAML throws expected error" );
290 open( FILE, " $file" ) or die "open($file) failed: $!";
291 binmode( FILE, $_[0] ) if @_ > 0 && $] > 5.006;
292 # binmode(FILE); # disable perl's BOM interpretation
294 close( FILE ) or die "close($file) failed: $!";
302 Test::More::ok( -f $file, "Found $name" );
303 Test::More::ok( -r $file, "Can read $name" );
304 my $content = slurp( $file );
305 Test::More::ok( (defined $content and ! ref $content), "Loaded $name" );
306 Test::More::ok( ($size < length $content), "Content of $name larger than $size bytes" );