4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Yaml\Tests;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Yaml\Exception\ParseException;
16 use Symfony\Component\Yaml\Yaml;
17 use Symfony\Component\Yaml\Parser;
18 use Symfony\Component\Yaml\Tag\TaggedValue;
20 class ParserTest extends TestCase
25 protected function setUp()
27 $this->parser = new Parser();
30 protected function tearDown()
34 chmod(__DIR__.'/Fixtures/not_readable.yml', 0644);
38 * @dataProvider getDataFormSpecifications
40 public function testSpecifications($expected, $yaml, $comment, $deprecated)
42 $deprecations = array();
45 set_error_handler(function ($type, $msg) use (&$deprecations) {
46 if (E_USER_DEPRECATED !== $type) {
47 restore_error_handler();
49 if (class_exists('PHPUnit_Util_ErrorHandler')) {
50 return call_user_func_array('PHPUnit_Util_ErrorHandler::handleError', func_get_args());
53 return call_user_func_array('PHPUnit\Util\ErrorHandler::handleError', func_get_args());
56 $deprecations[] = $msg;
60 $this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment);
63 restore_error_handler();
65 $this->assertCount(1, $deprecations);
66 $this->assertContains(true !== $deprecated ? $deprecated : 'Using the comma as a group separator for floats is deprecated since Symfony 3.2 and will be removed in 4.0 on line 1.', $deprecations[0]);
70 public function getDataFormSpecifications()
72 return $this->loadTestsFromFixtureFiles('index.yml');
77 * @expectedDeprecationMessage Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since Symfony 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable
78 * @dataProvider getNonStringMappingKeysData
80 public function testNonStringMappingKeys($expected, $yaml, $comment)
82 $this->assertSame($expected, var_export($this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS), true), $comment);
85 public function getNonStringMappingKeysData()
87 return $this->loadTestsFromFixtureFiles('nonStringKeys.yml');
92 * @dataProvider getLegacyNonStringMappingKeysData
94 public function testLegacyNonStringMappingKeys($expected, $yaml, $comment)
96 $this->assertSame($expected, var_export($this->parser->parse($yaml), true), $comment);
99 public function getLegacyNonStringMappingKeysData()
101 return $this->loadTestsFromFixtureFiles('legacyNonStringKeys.yml');
104 public function testTabsInYaml()
114 foreach ($yamls as $yaml) {
116 $content = $this->parser->parse($yaml);
118 $this->fail('YAML files must not contain tabs');
119 } catch (\Exception $e) {
120 $this->assertInstanceOf('\Exception', $e, 'YAML files must not contain tabs');
121 $this->assertEquals('A YAML file cannot contain tabs as indentation at line 2 (near "'.strpbrk($yaml, "\t").'").', $e->getMessage(), 'YAML files must not contain tabs');
126 public function testEndOfTheDocumentMarker()
134 $this->assertEquals('foo', $this->parser->parse($yaml));
137 public function getBlockChompingTests()
154 $tests['Literal block chomping strip with single trailing newline'] = array($expected, $yaml);
171 $tests['Literal block chomping strip with multiple trailing newlines'] = array($expected, $yaml);
179 $tests['Literal block chomping strip with multiple trailing newlines after a 1-liner'] = array($expected, $yaml);
193 $tests['Literal block chomping strip without trailing newline'] = array($expected, $yaml);
205 'foo' => "one\ntwo\n",
206 'bar' => "one\ntwo\n",
208 $tests['Literal block chomping clip with single trailing newline'] = array($expected, $yaml);
222 'foo' => "one\ntwo\n",
223 'bar' => "one\ntwo\n",
225 $tests['Literal block chomping clip with multiple trailing newlines'] = array($expected, $yaml);
237 'bar' => "one\n\ntwo",
241 $tests['Literal block chomping clip with embedded blank line inside unindented collection'] = array($expected, $yaml);
252 'foo' => "one\ntwo\n",
255 $tests['Literal block chomping clip without trailing newline'] = array($expected, $yaml);
267 'foo' => "one\ntwo\n",
268 'bar' => "one\ntwo\n",
270 $tests['Literal block chomping keep with single trailing newline'] = array($expected, $yaml);
284 'foo' => "one\ntwo\n\n",
285 'bar' => "one\ntwo\n\n",
287 $tests['Literal block chomping keep with multiple trailing newlines'] = array($expected, $yaml);
298 'foo' => "one\ntwo\n",
301 $tests['Literal block chomping keep without trailing newline'] = array($expected, $yaml);
316 $tests['Folded block chomping strip with single trailing newline'] = array($expected, $yaml);
333 $tests['Folded block chomping strip with multiple trailing newlines'] = array($expected, $yaml);
347 $tests['Folded block chomping strip without trailing newline'] = array($expected, $yaml);
359 'foo' => "one two\n",
360 'bar' => "one two\n",
362 $tests['Folded block chomping clip with single trailing newline'] = array($expected, $yaml);
376 'foo' => "one two\n",
377 'bar' => "one two\n",
379 $tests['Folded block chomping clip with multiple trailing newlines'] = array($expected, $yaml);
390 'foo' => "one two\n",
393 $tests['Folded block chomping clip without trailing newline'] = array($expected, $yaml);
405 'foo' => "one two\n",
406 'bar' => "one two\n",
408 $tests['Folded block chomping keep with single trailing newline'] = array($expected, $yaml);
422 'foo' => "one two\n\n",
423 'bar' => "one two\n\n",
425 $tests['Folded block chomping keep with multiple trailing newlines'] = array($expected, $yaml);
436 'foo' => "one two\n",
439 $tests['Folded block chomping keep without trailing newline'] = array($expected, $yaml);
445 * @dataProvider getBlockChompingTests
447 public function testBlockChomping($expected, $yaml)
449 $this->assertSame($expected, $this->parser->parse($yaml));
453 * Regression test for issue #7989.
455 * @see https://github.com/symfony/symfony/issues/7989
457 public function testBlockLiteralWithLeadingNewlines()
470 $this->assertSame($expected, $this->parser->parse($yaml));
473 public function testObjectSupportEnabled()
476 foo: !php/object O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
479 $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
485 public function testObjectSupportEnabledPassingTrue()
488 foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
491 $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects');
496 * @dataProvider deprecatedObjectValueProvider
498 public function testObjectSupportEnabledWithDeprecatedTag($yaml)
500 $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($yaml, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
503 public function deprecatedObjectValueProvider()
508 foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
514 foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
522 * @dataProvider invalidDumpedObjectProvider
524 public function testObjectSupportDisabledButNoExceptions($input)
526 $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects');
530 * @dataProvider getObjectForMapTests
532 public function testObjectForMap($yaml, $expected)
534 $flags = Yaml::PARSE_OBJECT_FOR_MAP;
536 $this->assertEquals($expected, $this->parser->parse($yaml, $flags));
541 * @dataProvider getObjectForMapTests
543 public function testObjectForMapEnabledWithMappingUsingBooleanToggles($yaml, $expected)
545 $this->assertEquals($expected, $this->parser->parse($yaml, false, false, true));
548 public function getObjectForMapTests()
556 $expected = new \stdClass();
557 $expected->foo = new \stdClass();
558 $expected->foo->fiz = array('cat');
559 $tests['mapping'] = array($yaml, $expected);
561 $yaml = '{ "foo": "bar", "fiz": "cat" }';
562 $expected = new \stdClass();
563 $expected->foo = 'bar';
564 $expected->fiz = 'cat';
565 $tests['inline-mapping'] = array($yaml, $expected);
567 $yaml = "foo: bar\nbaz: foobar";
568 $expected = new \stdClass();
569 $expected->foo = 'bar';
570 $expected->baz = 'foobar';
571 $tests['object-for-map-is-applied-after-parsing'] = array($yaml, $expected);
578 $expected = new \stdClass();
579 $expected->array = array();
580 $expected->array[0] = new \stdClass();
581 $expected->array[0]->key = 'one';
582 $expected->array[1] = new \stdClass();
583 $expected->array[1]->key = 'two';
584 $tests['nest-map-and-sequence'] = array($yaml, $expected);
591 $expected = new \stdClass();
592 $expected->map = new \stdClass();
593 $expected->map->{1} = 'one';
594 $expected->map->{2} = 'two';
595 $tests['numeric-keys'] = array($yaml, $expected);
602 $expected = new \stdClass();
603 $expected->map = new \stdClass();
604 $expected->map->{0} = 'one';
605 $expected->map->{1} = 'two';
606 $tests['zero-indexed-numeric-keys'] = array($yaml, $expected);
612 * @dataProvider invalidDumpedObjectProvider
613 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
615 public function testObjectsSupportDisabledWithExceptions($yaml)
617 $this->parser->parse($yaml, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE);
620 public function testCanParseContentWithTrailingSpaces()
622 $yaml = "items: \n foo: bar";
625 'items' => array('foo' => 'bar'),
628 $this->assertSame($expected, $this->parser->parse($yaml));
633 * @dataProvider invalidDumpedObjectProvider
634 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
636 public function testObjectsSupportDisabledWithExceptionsUsingBooleanToggles($yaml)
638 $this->parser->parse($yaml, true);
641 public function invalidDumpedObjectProvider()
644 foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}
648 foo: !php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}
653 'yaml-tag' => array($yamlTag),
654 'local-tag' => array($localTag),
659 * @requires extension iconv
661 public function testNonUtf8Exception()
664 iconv('UTF-8', 'ISO-8859-1', "foo: 'äöüß'"),
665 iconv('UTF-8', 'ISO-8859-15', "euro: '€'"),
666 iconv('UTF-8', 'CP1252', "cp1252: '©ÉÇáñ'"),
669 foreach ($yamls as $yaml) {
671 $this->parser->parse($yaml);
673 $this->fail('charsets other than UTF-8 are rejected.');
674 } catch (\Exception $e) {
675 $this->assertInstanceOf('Symfony\Component\Yaml\Exception\ParseException', $e, 'charsets other than UTF-8 are rejected.');
681 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
683 public function testUnindentedCollectionException()
694 $this->parser->parse($yaml);
698 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
700 public function testShortcutKeyUnindentedCollectionException()
710 $this->parser->parse($yaml);
714 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
715 * @expectedExceptionMessageRegExp /^Multiple documents are not supported.+/
717 public function testMultipleDocumentsNotSupportedException()
720 # Ranking of 1998 home runs
735 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
737 public function testSequenceInAMapping()
747 public function testSequenceInMappingStartedBySingleDashLine()
772 $this->assertSame($expected, $this->parser->parse($yaml));
775 public function testSequenceFollowedByCommentEmbeddedInMapping()
791 $this->assertSame($expected, $this->parser->parse($yaml));
794 public function testNonStringFollowedByCommentEmbeddedInMapping()
812 $this->assertSame($expected, $this->parser->parse($yaml));
815 public function getParseExceptionNotAffectedMultiLineStringLastResortParsing()
823 $tests['parse error on first line'] = array($yaml);
831 $tests['parse error due to inconsistent indentation'] = array($yaml);
834 & * ! | > ' " % @ ` #, { asd a;sdasd }-@^qw3
836 $tests['symfony/symfony/issues/22967#issuecomment-322067742'] = array($yaml);
842 * @dataProvider getParseExceptionNotAffectedMultiLineStringLastResortParsing
843 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
845 public function testParseExceptionNotAffectedByMultiLineStringLastResortParsing($yaml)
847 $this->parser->parse($yaml);
850 public function testMultiLineStringLastResortParsing()
854 You can have things that don't look like strings here
859 'test' => 'You can have things that don\'t look like strings here true yes you can',
862 $this->assertSame($expected, $this->parser->parse($yaml));
873 $this->assertSame($expected, $this->parser->parse($yaml));
877 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
879 public function testMappingInASequence()
890 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
891 * @expectedExceptionMessage missing colon
893 public function testScalarInSequence()
905 * > It is an error for two equal keys to appear in the same mapping node.
906 * > In such a case the YAML processor may continue, ignoring the second
907 * > `key: value` pair and issuing an appropriate warning. This strategy
908 * > preserves a consistent information model for one-pass and random access
911 * @see http://yaml.org/spec/1.2/spec.html#id2759572
912 * @see http://yaml.org/spec/1.1/#id932806
915 public function testMappingDuplicateKeyBlock()
930 $this->assertSame($expected, Yaml::parse($input));
936 public function testMappingDuplicateKeyFlow()
939 parent: { child: first, child: duplicate }
940 parent: { child: duplicate, child: duplicate }
947 $this->assertSame($expected, Yaml::parse($input));
952 * @dataProvider getParseExceptionOnDuplicateData
953 * @expectedDeprecation Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.
954 * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0
956 public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber)
961 public function getParseExceptionOnDuplicateData()
966 parent: { child: first, child: duplicate }
968 $tests[] = array($yaml, 'child', 1);
975 $tests[] = array($yaml, 'child', 3);
978 parent: { child: foo }
979 parent: { child: bar }
981 $tests[] = array($yaml, 'parent', 2);
984 parent: { child_mapping: { value: bar}, child_mapping: { value: bar} }
986 $tests[] = array($yaml, 'child_mapping', 1);
995 $tests[] = array($yaml, 'child_mapping', 4);
998 parent: { child_sequence: ['key1', 'key2', 'key3'], child_sequence: ['key1', 'key2', 'key3'] }
1000 $tests[] = array($yaml, 'child_sequence', 1);
1013 $tests[] = array($yaml, 'child_sequence', 6);
1018 public function testEmptyValue()
1024 $this->assertEquals(array('hash' => null), Yaml::parse($input));
1027 public function testCommentAtTheRootIndent()
1029 $this->assertEquals(array(
1030 'services' => array(
1031 'app.foo_service' => array(
1034 'app/bar_service' => array(
1038 ), Yaml::parse(<<<'EOF'
1053 public function testStringBlockWithComments()
1055 $this->assertEquals(array('content' => <<<'EOT'
1066 ), Yaml::parse(<<<'EOF'
1081 public function testFoldedStringBlockWithComments()
1083 $this->assertEquals(array(array('content' => <<<'EOT'
1094 )), Yaml::parse(<<<'EOF'
1110 public function testNestedFoldedStringBlockWithComments()
1112 $this->assertEquals(array(array(
1113 'title' => 'some title',
1114 'content' => <<<'EOT'
1125 )), Yaml::parse(<<<'EOF'
1142 public function testReferenceResolvingInInlineStrings()
1144 $this->assertEquals(array(
1145 'var' => 'var-value',
1146 'scalar' => 'var-value',
1147 'list' => array('var-value'),
1148 'list_in_list' => array(array('var-value')),
1149 'map_in_list' => array(array('key' => 'var-value')),
1150 'embedded_mapping' => array(array('key' => 'var-value')),
1151 'map' => array('key' => 'var-value'),
1152 'list_in_map' => array('key' => array('var-value')),
1153 'map_in_map' => array('foo' => array('bar' => 'var-value')),
1154 ), Yaml::parse(<<<'EOF'
1158 list_in_list: [[ *var ]]
1159 map_in_list: [ { key: *var } ]
1160 embedded_mapping: [ key: *var ]
1162 list_in_map: { key: [*var] }
1163 map_in_map: { foo: { bar: *var } }
1168 public function testYamlDirective()
1176 $this->assertEquals(array('foo' => 1, 'bar' => 2), $this->parser->parse($yaml));
1181 * @expectedDeprecation Implicit casting of numeric key to string is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 2.
1183 public function testFloatKeys()
1198 $this->assertEquals($expected, $this->parser->parse($yaml));
1203 * @expectedDeprecation Implicit casting of non-string key to string is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 1.
1205 public function testBooleanKeys()
1217 $this->assertEquals($expected, $this->parser->parse($yaml));
1220 public function testExplicitStringCasting()
1242 $this->assertEquals($expected, $this->parser->parse($yaml));
1246 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
1247 * @expectedExceptionMessage A colon cannot be used in an unquoted mapping value
1249 public function testColonInMappingValueException()
1255 $this->parser->parse($yaml);
1258 public function testColonInMappingValueExceptionNotTriggeredByColonInComment()
1262 bar: foobar # Note: a comment after a colon
1265 $this->assertSame(array('foo' => array('bar' => 'foobar')), $this->parser->parse($yaml));
1269 * @dataProvider getCommentLikeStringInScalarBlockData
1271 public function testCommentLikeStringsAreNotStrippedInBlockScalars($yaml, $expectedParserResult)
1273 $this->assertSame($expectedParserResult, $this->parser->parse($yaml));
1276 public function getCommentLikeStringInScalarBlockData()
1298 'title' => 'some title',
1299 'content' => <<<'EOT'
1314 $tests[] = array($yaml, $expected);
1339 'collection' => array(
1359 $tests[] = array($yaml, $expected);
1374 'scalar-block' => "line1 line2>\n",
1381 $tests[] = array($yaml, $expected);
1397 $tests[] = array($yaml, $expected);
1402 public function testBlankLinesAreParsedAsNewLinesInFoldedBlocks()
1410 <li>may be a good example</li>
1418 <ul> <li>a list</li> <li>may be a good example</li> </ul>
1422 $this->parser->parse($yaml)
1426 public function testAdditionallyIndentedLinesAreParsedAsNewLinesInFoldedBlocks()
1434 <li>may be a good example</li>
1444 <li>may be a good example</li>
1449 $this->parser->parse($yaml)
1454 * @dataProvider getBinaryData
1456 public function testParseBinaryData($data)
1458 $this->assertSame(array('data' => 'Hello world'), $this->parser->parse($data));
1461 public function getBinaryData()
1464 'enclosed with double quotes' => array('data: !!binary "SGVsbG8gd29ybGQ="'),
1465 'enclosed with single quotes' => array("data: !!binary 'SGVsbG8gd29ybGQ='"),
1466 'containing spaces' => array('data: !!binary "SGVs bG8gd 29ybGQ="'),
1467 'in block scalar' => array(
1473 'containing spaces in block scalar' => array(
1483 * @dataProvider getInvalidBinaryData
1484 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
1486 public function testParseInvalidBinaryData($data, $expectedMessage)
1488 if (method_exists($this, 'expectException')) {
1489 $this->expectExceptionMessageRegExp($expectedMessage);
1491 $this->setExpectedExceptionRegExp(ParseException::class, $expectedMessage);
1494 $this->parser->parse($data);
1497 public function getInvalidBinaryData()
1500 'length not a multiple of four' => array('data: !!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'),
1501 'invalid characters' => array('!!binary "SGVsbG8#d29ybGQ="', '/The base64 encoded data \(.*\) contains invalid characters/'),
1502 'too many equals characters' => array('data: !!binary "SGVsbG8gd29yb==="', '/The base64 encoded data \(.*\) contains invalid characters/'),
1503 'misplaced equals character' => array('data: !!binary "SGVsbG8gd29ybG=Q"', '/The base64 encoded data \(.*\) contains invalid characters/'),
1504 'length not a multiple of four in block scalar' => array(
1510 '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/',
1512 'invalid characters in block scalar' => array(
1518 '/The base64 encoded data \(.*\) contains invalid characters/',
1520 'too many equals characters in block scalar' => array(
1526 '/The base64 encoded data \(.*\) contains invalid characters/',
1528 'misplaced equals character in block scalar' => array(
1534 '/The base64 encoded data \(.*\) contains invalid characters/',
1539 public function testParseDateAsMappingValue()
1544 $expectedDate = new \DateTime();
1545 $expectedDate->setTimeZone(new \DateTimeZone('UTC'));
1546 $expectedDate->setDate(2002, 12, 14);
1547 $expectedDate->setTime(0, 0, 0);
1549 $this->assertEquals(array('date' => $expectedDate), $this->parser->parse($yaml, Yaml::PARSE_DATETIME));
1553 * @param $lineNumber
1555 * @dataProvider parserThrowsExceptionWithCorrectLineNumberProvider
1557 public function testParserThrowsExceptionWithCorrectLineNumber($lineNumber, $yaml)
1559 if (method_exists($this, 'expectException')) {
1560 $this->expectException('\Symfony\Component\Yaml\Exception\ParseException');
1561 $this->expectExceptionMessage(sprintf('Unexpected characters near "," at line %d (near "bar: "123",").', $lineNumber));
1563 $this->setExpectedException('\Symfony\Component\Yaml\Exception\ParseException', sprintf('Unexpected characters near "," at line %d (near "bar: "123",").', $lineNumber));
1566 $this->parser->parse($yaml);
1569 public function parserThrowsExceptionWithCorrectLineNumberProvider()
1622 public function testParseMultiLineQuotedString()
1632 $this->assertSame(array('foo' => 'bar baz foobar foo', 'bar' => 'baz'), $this->parser->parse($yaml));
1635 public function testMultiLineQuotedStringWithTrailingBackslash()
1643 $this->assertSame(array('foobar' => 'foobar'), $this->parser->parse($yaml));
1646 public function testCommentCharactersInMultiLineQuotedStrings()
1656 'foobar' => 'foo #bar',
1661 $this->assertSame($expected, $this->parser->parse($yaml));
1664 public function testBlankLinesInQuotedMultiLineString()
1672 'foobar' => "foo\nbar",
1675 $this->assertSame($expected, $this->parser->parse($yaml));
1678 public function testParseMultiLineUnquotedString()
1688 $this->assertSame(array('foo' => 'bar baz foobar foo', 'bar' => 'baz'), $this->parser->parse($yaml));
1691 public function testParseMultiLineString()
1693 $this->assertEquals("foo bar\nbaz", $this->parser->parse("foo\nbar\n\nbaz"));
1697 * @dataProvider multiLineDataProvider
1699 public function testParseMultiLineMappingValue($yaml, $expected, $parseError)
1701 $this->assertEquals($expected, $this->parser->parse($yaml));
1704 public function multiLineDataProvider()
1719 'bar' => "one\ntwo three",
1724 $tests[] = array($yaml, $expected, false);
1730 $expected = 'bar "foo"';
1732 $tests[] = array($yaml, $expected, false);
1738 $expected = 'bar "foo';
1740 $tests[] = array($yaml, $expected, false);
1747 $expected = "bar\n'foo'";
1749 $tests[] = array($yaml, $expected, false);
1756 $expected = "bar\nfoo'";
1758 $tests[] = array($yaml, $expected, false);
1763 public function testTaggedInlineMapping()
1765 $this->assertEquals(new TaggedValue('foo', array('foo' => 'bar')), $this->parser->parse('!foo {foo: bar}', Yaml::PARSE_CUSTOM_TAGS));
1769 * @dataProvider taggedValuesProvider
1771 public function testCustomTagSupport($expected, $yaml)
1773 $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_CUSTOM_TAGS));
1776 public function taggedValuesProvider()
1779 'sequences' => array(
1780 array(new TaggedValue('foo', array('yaml')), new TaggedValue('quz', array('bar'))),
1787 'mappings' => array(
1788 new TaggedValue('foo', array('foo' => new TaggedValue('quz', array('bar')), 'quz' => new TaggedValue('foo', array('quz' => 'bar')))),
1797 array(new TaggedValue('foo', array('foo', 'bar')), new TaggedValue('quz', array('foo' => 'bar', 'quz' => new TaggedValue('bar', array('one' => 'bar'))))),
1800 - !quz {foo: bar, quz: !bar {one: bar}}
1807 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
1808 * @expectedExceptionMessage Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator [foo]").
1810 public function testCustomTagsDisabled()
1812 $this->parser->parse('!iterator [foo]');
1817 * @expectedDeprecation Using the unquoted scalar value "!iterator foo" is deprecated since Symfony 3.3 and will be considered as a tagged value in 4.0. You must quote it on line 1.
1819 public function testUnsupportedTagWithScalar()
1821 $this->assertEquals('!iterator foo', $this->parser->parse('!iterator foo'));
1825 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
1826 * @expectedExceptionMessage The built-in tag "!!foo" is not implemented at line 1 (near "!!foo").
1828 public function testExceptionWhenUsingUnsuportedBuiltInTags()
1830 $this->parser->parse('!!foo');
1835 * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 1.
1837 public function testComplexMappingThrowsParseException()
1845 $this->parser->parse($yaml);
1850 * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 2.
1852 public function testComplexMappingNestedInMappingThrowsParseException()
1861 $this->parser->parse($yaml);
1866 * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since Symfony 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 1.
1868 public function testComplexMappingNestedInSequenceThrowsParseException()
1876 $this->parser->parse($yaml);
1880 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
1881 * @expectedExceptionMessage Unable to parse at line 1 (near "[parameters]").
1883 public function testParsingIniThrowsException()
1891 $this->parser->parse($ini);
1894 private function loadTestsFromFixtureFiles($testsFile)
1896 $parser = new Parser();
1899 $files = $parser->parseFile(__DIR__.'/Fixtures/'.$testsFile);
1900 foreach ($files as $file) {
1901 $yamls = file_get_contents(__DIR__.'/Fixtures/'.$file.'.yml');
1903 // split YAMLs documents
1904 foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {
1909 $test = $parser->parse($yaml);
1910 if (isset($test['todo']) && $test['todo']) {
1913 eval('$expected = '.trim($test['php']).';');
1915 $tests[] = array(var_export($expected, true), $test['yaml'], $test['test'], isset($test['deprecated']) ? $test['deprecated'] : false);
1923 public function testCanParseVeryLongValue()
1925 $longStringWithSpaces = str_repeat('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ', 20000);
1926 $trickyVal = array('x' => $longStringWithSpaces);
1928 $yamlString = Yaml::dump($trickyVal);
1929 $arrayFromYaml = $this->parser->parse($yamlString);
1931 $this->assertEquals($trickyVal, $arrayFromYaml);
1935 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
1936 * @expectedExceptionMessage Reference "foo" does not exist at line 2
1938 public function testParserCleansUpReferencesBetweenRuns()
1946 $this->parser->parse($yaml);
1952 $this->parser->parse($yaml);
1955 public function testPhpConstantTagMappingKey()
1959 !php/const 'Symfony\Component\Yaml\Tests\B::FOO':
1961 - !php/const 'Symfony\Component\Yaml\Tests\B::BAR'
1962 to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ'
1965 'transitions' => array(
1975 $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
1980 * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 2.
1981 * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 4.
1982 * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since Symfony 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 5.
1984 public function testDeprecatedPhpConstantTagMappingKey()
1988 !php/const:Symfony\Component\Yaml\Tests\B::FOO:
1990 - !php/const:Symfony\Component\Yaml\Tests\B::BAR
1991 to: !php/const:Symfony\Component\Yaml\Tests\B::BAZ
1994 'transitions' => array(
2004 $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
2009 * @expectedDeprecation Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since Symfony 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.
2011 public function testPhpConstantTagMappingKeyWithKeysCastToStrings()
2015 !php/const 'Symfony\Component\Yaml\Tests\B::FOO':
2017 - !php/const 'Symfony\Component\Yaml\Tests\B::BAR'
2018 to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ'
2021 'transitions' => array(
2031 $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT | Yaml::PARSE_KEYS_AS_STRINGS));
2034 public function testMergeKeysWhenMappingsAreParsedAsObjects()
2050 $expected = (object) array(
2051 'foo' => (object) array(
2054 'bar' => (object) array(
2058 'baz' => (object) array(
2062 'foobar' => (object) array(
2068 $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));
2071 public function testFilenamesAreParsedAsStringsWithoutFlag()
2073 $file = __DIR__.'/Fixtures/index.yml';
2075 $this->assertSame($file, $this->parser->parse($file));
2078 public function testParseFile()
2080 $this->assertInternalType('array', $this->parser->parseFile(__DIR__.'/Fixtures/index.yml'));
2084 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
2085 * @expectedExceptionMessageRegExp #^File ".+/Fixtures/nonexistent.yml" does not exist\.$#
2087 public function testParsingNonExistentFilesThrowsException()
2089 $this->parser->parseFile(__DIR__.'/Fixtures/nonexistent.yml');
2093 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
2094 * @expectedExceptionMessageRegExp #^File ".+/Fixtures/not_readable.yml" cannot be read\.$#
2096 public function testParsingNotReadableFilesThrowsException()
2098 if ('\\' === DIRECTORY_SEPARATOR) {
2099 $this->markTestSkipped('chmod is not supported on Windows');
2102 $file = __DIR__.'/Fixtures/not_readable.yml';
2105 $this->parser->parseFile($file);
2108 public function testParseReferencesOnMergeKeys()
2121 'mergekeyrefdef' => array(
2126 'mergekeyderef' => array(
2133 $this->assertSame($expected, $this->parser->parse($yaml));
2136 public function testParseReferencesOnMergeKeysWithMappingsParsedAsObjects()
2148 $expected = (object) array(
2149 'mergekeyrefdef' => (object) array(
2154 'mergekeyderef' => (object) array(
2161 $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));
2165 * @expectedException \Symfony\Component\Yaml\Exception\ParseException
2166 * @expectedExceptionMessage Reference "foo" does not exist
2168 public function testEvalRefException()
2171 foo: { &foo { a: Steve, <<: *foo} }
2173 $this->parser->parse($yaml);
2177 * @dataProvider indentedMappingData
2179 public function testParseIndentedMappings($yaml, $expected)
2181 $this->assertSame($expected, $this->parser->parse($yaml));
2184 public function indentedMappingData()
2202 $tests['comment line is first line in indented block'] = array($yaml, $expected);
2214 'baz' => array(1, 2, 3),
2219 $tests['mapping value on new line starting with a comment line'] = array($yaml, $expected);
2233 $tests['mapping in sequence starting on a new line'] = array($yaml, $expected);
2245 $tests['blank line at the beginning of an indented mapping value'] = array($yaml, $expected);