#!/usr/bin/perl # Testing of common META.yml examples use strict; BEGIN { $| = 1; $^W = 1; } use File::Spec::Functions ':ALL'; use t::lib::Test; use Test::More tests(37, 0, 13); use CPAN::Meta::YAML qw{ Load Dump LoadFile DumpFile freeze thaw }; ##################################################################### # Check Exports ok( defined(&Load), 'Found exported Load function' ); ok( defined(&Dump), 'Found exported Dump function' ); ok( defined(&LoadFile), 'Found exported LoadFile function' ); ok( defined(&DumpFile), 'Found exported DumpFile function' ); ok( defined(&freeze), 'Found exported freeze function' ); ok( defined(&thaw), 'Found exported thaw functiona' ); ##################################################################### # In META.yml files, some hash keys contain module names # Hash key legally containing a colon yaml_ok( "---\nFoo::Bar: 1\n", [ { 'Foo::Bar' => 1 } ], 'module_hash_key', ); # Hash indented yaml_ok( "---\n" . " foo: bar\n", [ { foo => "bar" } ], 'hash_indented', ); ##################################################################### # Support for literal multi-line scalars # Declarative multi-line scalar yaml_ok( "---\n" . " foo: >\n" . " bar\n" . " baz\n", [ { foo => "bar baz\n" } ], 'simple_multiline', ); # Piped multi-line scalar yaml_ok( <<'END_YAML', --- - | foo bar - 1 END_YAML [ [ "foo\nbar\n", 1 ] ], 'indented', ); # ... with a pointless hyphen yaml_ok( <<'END_YAML', --- - |- foo bar - 1 END_YAML [ [ "foo\nbar", 1 ] ], 'indented', ); ##################################################################### # Support for YAML version directives # Simple inline case (comment variant) yaml_ok( <<'END_YAML', --- #YAML:1.0 foo: bar END_YAML [ { foo => 'bar' } ], 'simple_doctype_comment', nosyck => 1, ); # Simple inline case (percent variant) yaml_ok( <<'END_YAML', --- %YAML:1.0 foo: bar END_YAML [ { foo => 'bar' } ], 'simple_doctype_percent', noyamlpm => 1, noxs => 1, noyamlperl => 1, ); # Simple header (comment variant) yaml_ok( <<'END_YAML', %YAML:1.0 --- foo: bar END_YAML [ { foo => 'bar' } ], 'predocument_1_0', noyamlpm => 1, nosyck => 1, noxs => 1, noyamlperl => 1, ); # Simple inline case (comment variant) yaml_ok( <<'END_YAML', %YAML 1.1 --- foo: bar END_YAML [ { foo => 'bar' } ], 'predocument_1_1', noyamlpm => 1, nosyck => 1, noyamlperl => 1, ); # Multiple inline documents (comment variant) yaml_ok( <<'END_YAML', --- #YAML:1.0 foo: bar --- #YAML:1.0 - 1 --- #YAML:1.0 foo: bar END_YAML [ { foo => 'bar' }, [ 1 ], { foo => 'bar' } ], 'multi_doctype_comment', ); # Simple pre-document case (comment variant) yaml_ok( <<'END_YAML', %YAML 1.1 --- foo: bar END_YAML [ { foo => 'bar' } ], 'predocument_percent', noyamlpm => 1, nosyck => 1, noyamlperl => 1, ); # Simple pre-document case (comment variant) yaml_ok( <<'END_YAML', #YAML 1.1 --- foo: bar END_YAML [ { foo => 'bar' } ], 'predocument_comment', ); ##################################################################### # Hitchhiker Scalar yaml_ok( <<'END_YAML', --- 42 END_YAML [ 42 ], 'hitchhiker scalar', serializes => 1, ); ##################################################################### # Null HASH/ARRAY yaml_ok( <<'END_YAML', --- - foo - {} - bar END_YAML [ [ 'foo', {}, 'bar' ] ], 'null hash in array', ); yaml_ok( <<'END_YAML', --- - foo - [] - bar END_YAML [ [ 'foo', [], 'bar' ] ], 'null array in array', ); yaml_ok( <<'END_YAML', --- foo: {} bar: 1 END_YAML [ { foo => {}, bar => 1 } ], 'null hash in hash', ); yaml_ok( <<'END_YAML', --- foo: [] bar: 1 END_YAML [ { foo => [], bar => 1 } ], 'null array in hash', ); ##################################################################### # Trailing Whitespace yaml_ok( <<'END_YAML', --- abstract: Generate fractal curves foo: ~ arr: - foo - ~ - 'bar' END_YAML [ { abstract => 'Generate fractal curves', foo => undef, arr => [ 'foo', undef, 'bar' ], } ], 'trailing whitespace', noyamlperl => 1, ); ##################################################################### # Quote vs Hash yaml_ok( <<'END_YAML', --- author: - 'mst: Matt S. Trout ' END_YAML [ { author => [ 'mst: Matt S. Trout ' ] } ], 'hash-like quote', ); ##################################################################### # Quote and Escaping Idiosyncracies yaml_ok( <<'END_YAML', --- name1: 'O''Reilly' name2: 'O''Reilly O''Tool' name3: 'Double '''' Quote' END_YAML [ { name1 => "O'Reilly", name2 => "O'Reilly O'Tool", name3 => "Double '' Quote", } ], 'single quote subtleties', ); yaml_ok( <<'END_YAML', --- slash1: '\\' slash2: '\\foo' slash3: '\\foo\\\\' END_YAML [ { slash1 => "\\\\", slash2 => "\\\\foo", slash3 => "\\\\foo\\\\\\\\", } ], 'single quote subtleties', ); ##################################################################### # Empty Values and Premature EOF yaml_ok( <<'END_YAML', --- foo: 0 requires: build_requires: END_YAML [ { foo => 0, requires => undef, build_requires => undef } ], 'empty hash keys', noyamlpm => 1, noyamlperl => 1, ); yaml_ok( <<'END_YAML', --- - foo - - END_YAML [ [ 'foo', undef, undef ] ], 'empty array keys', noyamlpm => 1, noyamlperl => 1, ); ##################################################################### # Comment on the Document Line yaml_ok( <<'END_YAML', --- # Comment foo: bar END_YAML [ { foo => 'bar' } ], 'comment header', noyamlpm => 1, noyamlperl => 1, ); ##################################################################### # Newlines and tabs yaml_ok( <<'END_YAML', foo: "foo\\\n\tbar" END_YAML [ { foo => "foo\\\n\tbar" } ], 'special characters', ); ##################################################################### # Circular Reference Protection SCOPE: { my $foo = { a => 'b' }; my $bar = [ $foo, 2 ]; $foo->{c} = $bar; my $circ = CPAN::Meta::YAML->new( [ $foo, $bar ] ); isa_ok( $circ, 'CPAN::Meta::YAML' ); # When we try to serialize, it should NOT infinite loop my $string = undef; $string = eval { $circ->write_string; }; is( $string, undef, '->write_string does not return a value' ); ok( $@, 'Error string is defined' ); ok( $@ =~ /does not support circular references/, 'Got the expected error message', ); } ##################################################################### # Confirm we can read the synopsis yaml_ok( <<'END_YAML', --- rootproperty: blah section: one: two three: four Foo: Bar empty: ~ END_YAML [ { rootproperty => 'blah', section => { one => 'two', three => 'four', Foo => 'Bar', empty => undef, }, } ], 'synopsis', noyamlperl => 1, ); ##################################################################### # Unprintable Characters yaml_ok( "--- \"foo\\n\\x00\"\n", [ "foo\n\0" ], 'unprintable', ); ##################################################################### # Empty Quote Line yaml_ok( <<'END_YAML', --- - foo # - bar END_YAML [ [ "foo", "bar" ] ], ); ##################################################################### # Indentation after empty hash value yaml_ok( <<'END_YAML', --- Test: optmods: Bad: 0 Foo: 1 Long: 0 version: 5 Test_IncludeA: optmods: Test_IncludeB: optmods: _meta: name: 'test profile' note: 'note this test profile' END_YAML [ { Test => { optmods => { Bad => 0, Foo => 1, Long => 0, }, version => 5, }, Test_IncludeA => { optmods => undef, }, Test_IncludeB => { optmods => undef, }, _meta => { name => 'test profile', note => 'note this test profile', }, } ], 'Indentation after empty hash value', noyamlperl => 1, ); ##################################################################### # Spaces in the Key yaml_ok( <<'END_YAML', --- the key: the value END_YAML [ { 'the key' => 'the value' } ], ); ##################################################################### # Ticker #32402 # Tests a particular pathological case yaml_ok( <<'END_YAML', --- - value - '><' END_YAML [ [ 'value', '><' ] ], 'Pathological >< case', ); ##################################################################### # Special Characters #yaml_ok( # <<'END_YAML', #--- #- "Ingy d\xC3\xB6t Net" #END_YAML # [ [ "Ingy d\xC3\xB6t Net" ] ], #); ###################################################################### # Non-Indenting Sub-List yaml_ok( <<'END_YAML', --- foo: - list bar: value END_YAML [ { foo => [ 'list' ], bar => 'value' } ], 'Non-indenting sub-list', noyamlpm => 1, noyamlperl => 1, ); ##################################################################### # Check Multiple-Escaping # RT #42119: write of two single quotes yaml_ok( "--- \"A'B'C\"\n", [ "A'B'C" ], 'Multiple escaping of quote ok', ); # Escapes without whitespace yaml_ok( "--- A\\B\\C\n", [ "A\\B\\C" ], 'Multiple escaping of escape ok', ); # Escapes with whitespace yaml_ok( "--- 'A\\B \\C'\n", [ "A\\B \\C" ], 'Multiple escaping of escape with whitespace ok', ); ###################################################################### # Check illegal characters that are in legal places yaml_ok( "--- 'Wow!'\n", [ "Wow!" ], 'Bang in a quote', ); yaml_ok( "--- 'This&that'\n", [ "This&that" ], 'Ampersand in a quote', ); ###################################################################### # Check for unescaped boolean keywords is_deeply( CPAN::Meta::YAML->new( 'True' )->write_string, "--- 'True'\n", 'Idiomatic trivial boolean string is escaped', ); is_deeply( CPAN::Meta::YAML->new( [ qw{ null Null NULL y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF } ] )->write_string, <<'END_YAML' ); --- - 'null' - 'Null' - 'NULL' - 'y' - 'Y' - 'yes' - 'Yes' - 'YES' - 'n' - 'N' - 'no' - 'No' - 'NO' - 'true' - 'True' - 'TRUE' - 'false' - 'False' - 'FALSE' - 'on' - 'On' - 'ON' - 'off' - 'Off' - 'OFF' END_YAML ###################################################################### # Always quote for scalars ending with : is_deeply( CPAN::Meta::YAML->new( [ 'A:' ] )->write_string, "---\n- 'A:'\n", 'Simple scalar ending in a colon is correctly quoted', );