use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Parser;
+use Symfony\Component\Yaml\Tag\TaggedValue;
class ParserTest extends TestCase
{
protected function tearDown()
{
$this->parser = null;
+
+ chmod(__DIR__.'/Fixtures/not_readable.yml', 0644);
}
/**
* @dataProvider getDataFormSpecifications
*/
- public function testSpecifications($file, $expected, $yaml, $comment, $deprecated)
+ public function testSpecifications($expected, $yaml, $comment, $deprecated)
{
$deprecations = array();
restore_error_handler();
$this->assertCount(1, $deprecations);
- $this->assertContains('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', $deprecations[0]);
+ $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]);
}
}
public function getDataFormSpecifications()
{
- $parser = new Parser();
- $path = __DIR__.'/Fixtures';
-
- $tests = array();
- $files = $parser->parse(file_get_contents($path.'/index.yml'));
- foreach ($files as $file) {
- $yamls = file_get_contents($path.'/'.$file.'.yml');
+ return $this->loadTestsFromFixtureFiles('index.yml');
+ }
- // split YAMLs documents
- foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {
- if (!$yaml) {
- continue;
- }
+ /**
+ * @group legacy
+ * @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
+ * @dataProvider getNonStringMappingKeysData
+ */
+ public function testNonStringMappingKeys($expected, $yaml, $comment)
+ {
+ $this->assertSame($expected, var_export($this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS), true), $comment);
+ }
- $test = $parser->parse($yaml);
- if (isset($test['todo']) && $test['todo']) {
- // TODO
- } else {
- eval('$expected = '.trim($test['php']).';');
+ public function getNonStringMappingKeysData()
+ {
+ return $this->loadTestsFromFixtureFiles('nonStringKeys.yml');
+ }
- $tests[] = array($file, var_export($expected, true), $test['yaml'], $test['test'], isset($test['deprecated']) ? $test['deprecated'] : false);
- }
- }
- }
+ /**
+ * @group legacy
+ * @dataProvider getLegacyNonStringMappingKeysData
+ */
+ public function testLegacyNonStringMappingKeys($expected, $yaml, $comment)
+ {
+ $this->assertSame($expected, var_export($this->parser->parse($yaml), true), $comment);
+ }
- return $tests;
+ public function getLegacyNonStringMappingKeysData()
+ {
+ return $this->loadTestsFromFixtureFiles('legacyNonStringKeys.yml');
}
public function testTabsInYaml()
public function testObjectSupportEnabled()
{
$input = <<<'EOF'
-foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
+foo: !php/object O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
bar: 1
EOF;
$this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
/**
* @group legacy
+ * @dataProvider deprecatedObjectValueProvider
*/
- public function testObjectSupportEnabledWithDeprecatedTag()
+ public function testObjectSupportEnabledWithDeprecatedTag($yaml)
{
- $input = <<<'EOF'
+ $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($yaml, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
+ }
+
+ public function deprecatedObjectValueProvider()
+ {
+ return array(
+ array(
+ <<<YAML
foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
bar: 1
-EOF;
- $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
+YAML
+ ),
+ array(
+ <<<YAML
+foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
+bar: 1
+YAML
+ ),
+ );
}
/**
*/
public function testObjectForMap($yaml, $expected)
{
- $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));
+ $flags = Yaml::PARSE_OBJECT_FOR_MAP;
+
+ $this->assertEquals($expected, $this->parser->parse($yaml, $flags));
}
/**
$yaml = <<<'YAML'
map:
- 0: one
- 1: two
+ '0': one
+ '1': two
YAML;
$expected = new \stdClass();
$expected->map = new \stdClass();
$this->parser->parse($yaml, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE);
}
+ public function testCanParseContentWithTrailingSpaces()
+ {
+ $yaml = "items: \n foo: bar";
+
+ $expected = array(
+ 'items' => array('foo' => 'bar'),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
/**
* @group legacy
* @dataProvider invalidDumpedObjectProvider
$this->assertSame($expected, $this->parser->parse($yaml));
}
+ public function testNonStringFollowedByCommentEmbeddedInMapping()
+ {
+ $yaml = <<<'EOT'
+a:
+ b:
+ {}
+# comment
+ d:
+ 1.1
+# another comment
+EOT;
+ $expected = array(
+ 'a' => array(
+ 'b' => array(),
+ 'd' => 1.1,
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
+ public function getParseExceptionNotAffectedMultiLineStringLastResortParsing()
+ {
+ $tests = array();
+
+ $yaml = <<<'EOT'
+a
+ b:
+EOT;
+ $tests['parse error on first line'] = array($yaml);
+
+ $yaml = <<<'EOT'
+a
+
+b
+ c:
+EOT;
+ $tests['parse error due to inconsistent indentation'] = array($yaml);
+
+ $yaml = <<<'EOT'
+ & * ! | > ' " % @ ` #, { asd a;sdasd }-@^qw3
+EOT;
+ $tests['symfony/symfony/issues/22967#issuecomment-322067742'] = array($yaml);
+
+ return $tests;
+ }
+
+ /**
+ * @dataProvider getParseExceptionNotAffectedMultiLineStringLastResortParsing
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ */
+ public function testParseExceptionNotAffectedByMultiLineStringLastResortParsing($yaml)
+ {
+ $this->parser->parse($yaml);
+ }
+
+ public function testMultiLineStringLastResortParsing()
+ {
+ $yaml = <<<'EOT'
+test:
+ You can have things that don't look like strings here
+ true
+ yes you can
+EOT;
+ $expected = array(
+ 'test' => 'You can have things that don\'t look like strings here true yes you can',
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+
+ $yaml = <<<'EOT'
+a:
+ b
+ c
+EOT;
+ $expected = array(
+ 'a' => 'b c',
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
*/
/**
* @group legacy
* @dataProvider getParseExceptionOnDuplicateData
- * @expectedDeprecation Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s.
+ * @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.
* throws \Symfony\Component\Yaml\Exception\ParseException in 4.0
*/
public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber)
$this->assertEquals(array('foo' => 1, 'bar' => 2), $this->parser->parse($yaml));
}
+ /**
+ * @group legacy
+ * @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.
+ */
public function testFloatKeys()
{
$yaml = <<<'EOF'
$this->assertEquals($expected, $this->parser->parse($yaml));
}
+ /**
+ * @group legacy
+ * @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.
+ */
+ public function testBooleanKeys()
+ {
+ $yaml = <<<'EOF'
+true: foo
+false: bar
+EOF;
+
+ $expected = array(
+ 1 => 'foo',
+ 0 => 'bar',
+ );
+
+ $this->assertEquals($expected, $this->parser->parse($yaml));
+ }
+
+ public function testExplicitStringCasting()
+ {
+ $yaml = <<<'EOF'
+'1.2': "bar"
+!!str 1.3: "baz"
+
+'true': foo
+!!str false: bar
+
+!!str null: 'null'
+'~': 'null'
+EOF;
+
+ $expected = array(
+ '1.2' => 'bar',
+ '1.3' => 'baz',
+ 'true' => 'foo',
+ 'false' => 'bar',
+ 'null' => 'null',
+ '~' => 'null',
+ );
+
+ $this->assertEquals($expected, $this->parser->parse($yaml));
+ }
+
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
* @expectedExceptionMessage A colon cannot be used in an unquoted mapping value
$this->assertSame(array('foo' => 'bar baz foobar foo', 'bar' => 'baz'), $this->parser->parse($yaml));
}
+ public function testMultiLineQuotedStringWithTrailingBackslash()
+ {
+ $yaml = <<<YAML
+foobar:
+ "foo\
+ bar"
+YAML;
+
+ $this->assertSame(array('foobar' => 'foobar'), $this->parser->parse($yaml));
+ }
+
+ public function testCommentCharactersInMultiLineQuotedStrings()
+ {
+ $yaml = <<<YAML
+foo:
+ foobar: 'foo
+ #bar'
+ bar: baz
+YAML;
+ $expected = array(
+ 'foo' => array(
+ 'foobar' => 'foo #bar',
+ 'bar' => 'baz',
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
+ public function testBlankLinesInQuotedMultiLineString()
+ {
+ $yaml = <<<YAML
+foobar: 'foo
+
+ bar'
+YAML;
+ $expected = array(
+ 'foobar' => "foo\nbar",
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
public function testParseMultiLineUnquotedString()
{
$yaml = <<<EOT
$this->assertSame(array('foo' => 'bar baz foobar foo', 'bar' => 'baz'), $this->parser->parse($yaml));
}
+ public function testParseMultiLineString()
+ {
+ $this->assertEquals("foo bar\nbaz", $this->parser->parse("foo\nbar\n\nbaz"));
+ }
+
+ /**
+ * @dataProvider multiLineDataProvider
+ */
+ public function testParseMultiLineMappingValue($yaml, $expected, $parseError)
+ {
+ $this->assertEquals($expected, $this->parser->parse($yaml));
+ }
+
+ public function multiLineDataProvider()
+ {
+ $tests = array();
+
+ $yaml = <<<'EOF'
+foo:
+- bar:
+ one
+
+ two
+ three
+EOF;
+ $expected = array(
+ 'foo' => array(
+ array(
+ 'bar' => "one\ntwo three",
+ ),
+ ),
+ );
+
+ $tests[] = array($yaml, $expected, false);
+
+ $yaml = <<<'EOF'
+bar
+"foo"
+EOF;
+ $expected = 'bar "foo"';
+
+ $tests[] = array($yaml, $expected, false);
+
+ $yaml = <<<'EOF'
+bar
+"foo
+EOF;
+ $expected = 'bar "foo';
+
+ $tests[] = array($yaml, $expected, false);
+
+ $yaml = <<<'EOF'
+bar
+
+'foo'
+EOF;
+ $expected = "bar\n'foo'";
+
+ $tests[] = array($yaml, $expected, false);
+
+ $yaml = <<<'EOF'
+bar
+
+foo'
+EOF;
+ $expected = "bar\nfoo'";
+
+ $tests[] = array($yaml, $expected, false);
+
+ return $tests;
+ }
+
+ public function testTaggedInlineMapping()
+ {
+ $this->assertEquals(new TaggedValue('foo', array('foo' => 'bar')), $this->parser->parse('!foo {foo: bar}', Yaml::PARSE_CUSTOM_TAGS));
+ }
+
+ /**
+ * @dataProvider taggedValuesProvider
+ */
+ public function testCustomTagSupport($expected, $yaml)
+ {
+ $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_CUSTOM_TAGS));
+ }
+
+ public function taggedValuesProvider()
+ {
+ return array(
+ 'sequences' => array(
+ array(new TaggedValue('foo', array('yaml')), new TaggedValue('quz', array('bar'))),
+ <<<YAML
+- !foo
+ - yaml
+- !quz [bar]
+YAML
+ ),
+ 'mappings' => array(
+ new TaggedValue('foo', array('foo' => new TaggedValue('quz', array('bar')), 'quz' => new TaggedValue('foo', array('quz' => 'bar')))),
+ <<<YAML
+!foo
+foo: !quz [bar]
+quz: !foo
+ quz: bar
+YAML
+ ),
+ 'inline' => array(
+ array(new TaggedValue('foo', array('foo', 'bar')), new TaggedValue('quz', array('foo' => 'bar', 'quz' => new TaggedValue('bar', array('one' => 'bar'))))),
+ <<<YAML
+- !foo [foo, bar]
+- !quz {foo: bar, quz: !bar {one: bar}}
+YAML
+ ),
+ );
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessage Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator [foo]").
+ */
+ public function testCustomTagsDisabled()
+ {
+ $this->parser->parse('!iterator [foo]');
+ }
+
+ /**
+ * @group legacy
+ * @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.
+ */
+ public function testUnsupportedTagWithScalar()
+ {
+ $this->assertEquals('!iterator foo', $this->parser->parse('!iterator foo'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessage The built-in tag "!!foo" is not implemented at line 1 (near "!!foo").
+ */
+ public function testExceptionWhenUsingUnsuportedBuiltInTags()
+ {
+ $this->parser->parse('!!foo');
+ }
+
+ /**
+ * @group legacy
+ * @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.
+ */
+ public function testComplexMappingThrowsParseException()
+ {
+ $yaml = <<<YAML
+? "1"
+:
+ name: végétalien
+YAML;
+
+ $this->parser->parse($yaml);
+ }
+
+ /**
+ * @group legacy
+ * @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.
+ */
+ public function testComplexMappingNestedInMappingThrowsParseException()
+ {
+ $yaml = <<<YAML
+diet:
+ ? "1"
+ :
+ name: végétalien
+YAML;
+
+ $this->parser->parse($yaml);
+ }
+
+ /**
+ * @group legacy
+ * @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.
+ */
+ public function testComplexMappingNestedInSequenceThrowsParseException()
+ {
+ $yaml = <<<YAML
+- ? "1"
+ :
+ name: végétalien
+YAML;
+
+ $this->parser->parse($yaml);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessage Unable to parse at line 1 (near "[parameters]").
+ */
+ public function testParsingIniThrowsException()
+ {
+ $ini = <<<INI
+[parameters]
+ foo = bar
+ bar = %foo%
+INI;
+
+ $this->parser->parse($ini);
+ }
+
+ private function loadTestsFromFixtureFiles($testsFile)
+ {
+ $parser = new Parser();
+
+ $tests = array();
+ $files = $parser->parseFile(__DIR__.'/Fixtures/'.$testsFile);
+ foreach ($files as $file) {
+ $yamls = file_get_contents(__DIR__.'/Fixtures/'.$file.'.yml');
+
+ // split YAMLs documents
+ foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {
+ if (!$yaml) {
+ continue;
+ }
+
+ $test = $parser->parse($yaml);
+ if (isset($test['todo']) && $test['todo']) {
+ // TODO
+ } else {
+ eval('$expected = '.trim($test['php']).';');
+
+ $tests[] = array(var_export($expected, true), $test['yaml'], $test['test'], isset($test['deprecated']) ? $test['deprecated'] : false);
+ }
+ }
+ }
+
+ return $tests;
+ }
+
public function testCanParseVeryLongValue()
{
$longStringWithSpaces = str_repeat('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ', 20000);
YAML;
$this->parser->parse($yaml);
}
+
+ public function testPhpConstantTagMappingKey()
+ {
+ $yaml = <<<YAML
+transitions:
+ !php/const 'Symfony\Component\Yaml\Tests\B::FOO':
+ from:
+ - !php/const 'Symfony\Component\Yaml\Tests\B::BAR'
+ to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ'
+YAML;
+ $expected = array(
+ 'transitions' => array(
+ 'foo' => array(
+ 'from' => array(
+ 'bar',
+ ),
+ 'to' => 'baz',
+ ),
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
+ }
+
+ /**
+ * @group legacy
+ * @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.
+ * @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.
+ * @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.
+ */
+ public function testDeprecatedPhpConstantTagMappingKey()
+ {
+ $yaml = <<<YAML
+transitions:
+ !php/const:Symfony\Component\Yaml\Tests\B::FOO:
+ from:
+ - !php/const:Symfony\Component\Yaml\Tests\B::BAR
+ to: !php/const:Symfony\Component\Yaml\Tests\B::BAZ
+YAML;
+ $expected = array(
+ 'transitions' => array(
+ 'foo' => array(
+ 'from' => array(
+ 'bar',
+ ),
+ 'to' => 'baz',
+ ),
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
+ }
+
+ /**
+ * @group legacy
+ * @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.
+ */
+ public function testPhpConstantTagMappingKeyWithKeysCastToStrings()
+ {
+ $yaml = <<<YAML
+transitions:
+ !php/const 'Symfony\Component\Yaml\Tests\B::FOO':
+ from:
+ - !php/const 'Symfony\Component\Yaml\Tests\B::BAR'
+ to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ'
+YAML;
+ $expected = array(
+ 'transitions' => array(
+ 'foo' => array(
+ 'from' => array(
+ 'bar',
+ ),
+ 'to' => 'baz',
+ ),
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT | Yaml::PARSE_KEYS_AS_STRINGS));
+ }
+
+ public function testMergeKeysWhenMappingsAreParsedAsObjects()
+ {
+ $yaml = <<<YAML
+foo: &FOO
+ bar: 1
+bar: &BAR
+ baz: 2
+ <<: *FOO
+baz:
+ baz_foo: 3
+ <<:
+ baz_bar: 4
+foobar:
+ bar: ~
+ <<: [*FOO, *BAR]
+YAML;
+ $expected = (object) array(
+ 'foo' => (object) array(
+ 'bar' => 1,
+ ),
+ 'bar' => (object) array(
+ 'baz' => 2,
+ 'bar' => 1,
+ ),
+ 'baz' => (object) array(
+ 'baz_foo' => 3,
+ 'baz_bar' => 4,
+ ),
+ 'foobar' => (object) array(
+ 'bar' => null,
+ 'baz' => 2,
+ ),
+ );
+
+ $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));
+ }
+
+ public function testFilenamesAreParsedAsStringsWithoutFlag()
+ {
+ $file = __DIR__.'/Fixtures/index.yml';
+
+ $this->assertSame($file, $this->parser->parse($file));
+ }
+
+ public function testParseFile()
+ {
+ $this->assertInternalType('array', $this->parser->parseFile(__DIR__.'/Fixtures/index.yml'));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessageRegExp #^File ".+/Fixtures/nonexistent.yml" does not exist\.$#
+ */
+ public function testParsingNonExistentFilesThrowsException()
+ {
+ $this->parser->parseFile(__DIR__.'/Fixtures/nonexistent.yml');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessageRegExp #^File ".+/Fixtures/not_readable.yml" cannot be read\.$#
+ */
+ public function testParsingNotReadableFilesThrowsException()
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('chmod is not supported on Windows');
+ }
+
+ $file = __DIR__.'/Fixtures/not_readable.yml';
+ chmod($file, 0200);
+
+ $this->parser->parseFile($file);
+ }
+
+ public function testParseReferencesOnMergeKeys()
+ {
+ $yaml = <<<YAML
+mergekeyrefdef:
+ a: foo
+ <<: &quux
+ b: bar
+ c: baz
+mergekeyderef:
+ d: quux
+ <<: *quux
+YAML;
+ $expected = array(
+ 'mergekeyrefdef' => array(
+ 'a' => 'foo',
+ 'b' => 'bar',
+ 'c' => 'baz',
+ ),
+ 'mergekeyderef' => array(
+ 'd' => 'quux',
+ 'b' => 'bar',
+ 'c' => 'baz',
+ ),
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
+ public function testParseReferencesOnMergeKeysWithMappingsParsedAsObjects()
+ {
+ $yaml = <<<YAML
+mergekeyrefdef:
+ a: foo
+ <<: &quux
+ b: bar
+ c: baz
+mergekeyderef:
+ d: quux
+ <<: *quux
+YAML;
+ $expected = (object) array(
+ 'mergekeyrefdef' => (object) array(
+ 'a' => 'foo',
+ 'b' => 'bar',
+ 'c' => 'baz',
+ ),
+ 'mergekeyderef' => (object) array(
+ 'd' => 'quux',
+ 'b' => 'bar',
+ 'c' => 'baz',
+ ),
+ );
+
+ $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Yaml\Exception\ParseException
+ * @expectedExceptionMessage Reference "foo" does not exist
+ */
+ public function testEvalRefException()
+ {
+ $yaml = <<<EOE
+foo: { &foo { a: Steve, <<: *foo} }
+EOE;
+ $this->parser->parse($yaml);
+ }
+
+ /**
+ * @dataProvider indentedMappingData
+ */
+ public function testParseIndentedMappings($yaml, $expected)
+ {
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
+ public function indentedMappingData()
+ {
+ $tests = array();
+
+ $yaml = <<<YAML
+foo:
+ - bar: "foobar"
+ # A comment
+ baz: "foobaz"
+YAML;
+ $expected = array(
+ 'foo' => array(
+ array(
+ 'bar' => 'foobar',
+ 'baz' => 'foobaz',
+ ),
+ ),
+ );
+ $tests['comment line is first line in indented block'] = array($yaml, $expected);
+
+ $yaml = <<<YAML
+foo:
+ - bar:
+ # comment
+ baz: [1, 2, 3]
+YAML;
+ $expected = array(
+ 'foo' => array(
+ array(
+ 'bar' => array(
+ 'baz' => array(1, 2, 3),
+ ),
+ ),
+ ),
+ );
+ $tests['mapping value on new line starting with a comment line'] = array($yaml, $expected);
+
+ $yaml = <<<YAML
+foo:
+ -
+ bar: foobar
+YAML;
+ $expected = array(
+ 'foo' => array(
+ array(
+ 'bar' => 'foobar',
+ ),
+ ),
+ );
+ $tests['mapping in sequence starting on a new line'] = array($yaml, $expected);
+
+ $yaml = <<<YAML
+foo:
+
+ bar: baz
+YAML;
+ $expected = array(
+ 'foo' => array(
+ 'bar' => 'baz',
+ ),
+ );
+ $tests['blank line at the beginning of an indented mapping value'] = array($yaml, $expected);
+
+ return $tests;
+ }
}
class B
{
public $b = 'foo';
+
+ const FOO = 'foo';
+ const BAR = 'bar';
+ const BAZ = 'baz';
}