| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606 | <?php/* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */namespace Symfony\Component\Yaml\Tests;use PHPUnit\Framework\TestCase;use Symfony\Component\Yaml\Dumper;use Symfony\Component\Yaml\Parser;use Symfony\Component\Yaml\Tag\TaggedValue;use Symfony\Component\Yaml\Yaml;class DumperTest extends TestCase{    protected $parser;    protected $dumper;    protected $path;    protected $array = [        '' => 'bar',        'foo' => '#bar',        'foo\'bar' => [],        'bar' => [1, 'foo'],        'foobar' => [            'foo' => 'bar',            'bar' => [1, 'foo'],            'foobar' => [                'foo' => 'bar',                'bar' => [1, 'foo'],            ],        ],    ];    protected function setUp()    {        $this->parser = new Parser();        $this->dumper = new Dumper();        $this->path = __DIR__.'/Fixtures';    }    protected function tearDown()    {        $this->parser = null;        $this->dumper = null;        $this->path = null;        $this->array = null;    }    public function testIndentationInConstructor()    {        $dumper = new Dumper(7);        $expected = <<<'EOF''': barfoo: '#bar''foo''bar': {  }bar:       - 1       - foofoobar:       foo: bar       bar:              - 1              - foo       foobar:              foo: bar              bar:                     - 1                     - fooEOF;        $this->assertEquals($expected, $dumper->dump($this->array, 4, 0));    }    /**     * @group legacy     */    public function testSetIndentation()    {        $this->dumper->setIndentation(7);        $expected = <<<'EOF''': barfoo: '#bar''foo''bar': {  }bar:       - 1       - foofoobar:       foo: bar       bar:              - 1              - foo       foobar:              foo: bar              bar:                     - 1                     - fooEOF;        $this->assertEquals($expected, $this->dumper->dump($this->array, 4, 0));    }    public function testSpecifications()    {        $files = $this->parser->parse(file_get_contents($this->path.'/index.yml'));        foreach ($files as $file) {            $yamls = file_get_contents($this->path.'/'.$file.'.yml');            // split YAMLs documents            foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {                if (!$yaml) {                    continue;                }                $test = $this->parser->parse($yaml);                if (isset($test['dump_skip']) && $test['dump_skip']) {                    continue;                } elseif (isset($test['todo']) && $test['todo']) {                    // TODO                } else {                    eval('$expected = '.trim($test['php']).';');                    $this->assertSame($expected, $this->parser->parse($this->dumper->dump($expected, 10)), $test['test']);                }            }        }    }    public function testInlineLevel()    {        $expected = <<<'EOF'{ '': bar, foo: '#bar', 'foo''bar': {  }, bar: [1, foo], foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } } }EOF;        $this->assertEquals($expected, $this->dumper->dump($this->array, -10), '->dump() takes an inline level argument');        $this->assertEquals($expected, $this->dumper->dump($this->array, 0), '->dump() takes an inline level argument');        $expected = <<<'EOF''': barfoo: '#bar''foo''bar': {  }bar: [1, foo]foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } }EOF;        $this->assertEquals($expected, $this->dumper->dump($this->array, 1), '->dump() takes an inline level argument');        $expected = <<<'EOF''': barfoo: '#bar''foo''bar': {  }bar:    - 1    - foofoobar:    foo: bar    bar: [1, foo]    foobar: { foo: bar, bar: [1, foo] }EOF;        $this->assertEquals($expected, $this->dumper->dump($this->array, 2), '->dump() takes an inline level argument');        $expected = <<<'EOF''': barfoo: '#bar''foo''bar': {  }bar:    - 1    - foofoobar:    foo: bar    bar:        - 1        - foo    foobar:        foo: bar        bar: [1, foo]EOF;        $this->assertEquals($expected, $this->dumper->dump($this->array, 3), '->dump() takes an inline level argument');        $expected = <<<'EOF''': barfoo: '#bar''foo''bar': {  }bar:    - 1    - foofoobar:    foo: bar    bar:        - 1        - foo    foobar:        foo: bar        bar:            - 1            - fooEOF;        $this->assertEquals($expected, $this->dumper->dump($this->array, 4), '->dump() takes an inline level argument');        $this->assertEquals($expected, $this->dumper->dump($this->array, 10), '->dump() takes an inline level argument');    }    public function testObjectSupportEnabled()    {        $dump = $this->dumper->dump(['foo' => new A(), 'bar' => 1], 0, 0, Yaml::DUMP_OBJECT);        $this->assertEquals('{ foo: !php/object \'O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}\', bar: 1 }', $dump, '->dump() is able to dump objects');    }    /**     * @group legacy     */    public function testObjectSupportEnabledPassingTrue()    {        $dump = $this->dumper->dump(['foo' => new A(), 'bar' => 1], 0, 0, false, true);        $this->assertEquals('{ foo: !php/object \'O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}\', bar: 1 }', $dump, '->dump() is able to dump objects');    }    public function testObjectSupportDisabledButNoExceptions()    {        $dump = $this->dumper->dump(['foo' => new A(), 'bar' => 1]);        $this->assertEquals('{ foo: null, bar: 1 }', $dump, '->dump() does not dump objects when disabled');    }    public function testObjectSupportDisabledWithExceptions()    {        $this->expectException('Symfony\Component\Yaml\Exception\DumpException');        $this->dumper->dump(['foo' => new A(), 'bar' => 1], 0, 0, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE);    }    /**     * @group legacy     */    public function testObjectSupportDisabledWithExceptionsPassingTrue()    {        $this->expectException('Symfony\Component\Yaml\Exception\DumpException');        $this->dumper->dump(['foo' => new A(), 'bar' => 1], 0, 0, true);    }    public function testEmptyArray()    {        $dump = $this->dumper->dump([]);        $this->assertEquals('{  }', $dump);        $dump = $this->dumper->dump([], 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE);        $this->assertEquals('[]', $dump);        $dump = $this->dumper->dump([], 9, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE);        $this->assertEquals('[]', $dump);        $dump = $this->dumper->dump(new \ArrayObject(), 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_OBJECT_AS_MAP);        $this->assertEquals('{  }', $dump);        $dump = $this->dumper->dump(new \stdClass(), 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_OBJECT_AS_MAP);        $this->assertEquals('{  }', $dump);    }    /**     * @dataProvider getEscapeSequences     */    public function testEscapedEscapeSequencesInQuotedScalar($input, $expected)    {        $this->assertEquals($expected, $this->dumper->dump($input));    }    public function getEscapeSequences()    {        return [            'empty string' => ['', "''"],            'null' => ["\x0", '"\\0"'],            'bell' => ["\x7", '"\\a"'],            'backspace' => ["\x8", '"\\b"'],            'horizontal-tab' => ["\t", '"\\t"'],            'line-feed' => ["\n", '"\\n"'],            'vertical-tab' => ["\v", '"\\v"'],            'form-feed' => ["\xC", '"\\f"'],            'carriage-return' => ["\r", '"\\r"'],            'escape' => ["\x1B", '"\\e"'],            'space' => [' ', "' '"],            'double-quote' => ['"', "'\"'"],            'slash' => ['/', '/'],            'backslash' => ['\\', '\\'],            'next-line' => ["\xC2\x85", '"\\N"'],            'non-breaking-space' => ["\xc2\xa0", '"\\_"'],            'line-separator' => ["\xE2\x80\xA8", '"\\L"'],            'paragraph-separator' => ["\xE2\x80\xA9", '"\\P"'],            'colon' => [':', "':'"],        ];    }    public function testBinaryDataIsDumpedBase64Encoded()    {        $binaryData = file_get_contents(__DIR__.'/Fixtures/arrow.gif');        $expected = '{ data: !!binary '.base64_encode($binaryData).' }';        $this->assertSame($expected, $this->dumper->dump(['data' => $binaryData]));    }    public function testNonUtf8DataIsDumpedBase64Encoded()    {        // "für" (ISO-8859-1 encoded)        $this->assertSame('!!binary ZsM/cg==', $this->dumper->dump("f\xc3\x3fr"));    }    /**     * @dataProvider objectAsMapProvider     */    public function testDumpObjectAsMap($object, $expected)    {        $yaml = $this->dumper->dump($object, 0, 0, Yaml::DUMP_OBJECT_AS_MAP);        $this->assertEquals($expected, Yaml::parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));    }    public function objectAsMapProvider()    {        $tests = [];        $bar = new \stdClass();        $bar->class = 'classBar';        $bar->args = ['bar'];        $zar = new \stdClass();        $foo = new \stdClass();        $foo->bar = $bar;        $foo->zar = $zar;        $object = new \stdClass();        $object->foo = $foo;        $tests['stdClass'] = [$object, $object];        $arrayObject = new \ArrayObject();        $arrayObject['foo'] = 'bar';        $arrayObject['baz'] = 'foobar';        $parsedArrayObject = new \stdClass();        $parsedArrayObject->foo = 'bar';        $parsedArrayObject->baz = 'foobar';        $tests['ArrayObject'] = [$arrayObject, $parsedArrayObject];        $a = new A();        $tests['arbitrary-object'] = [$a, null];        return $tests;    }    public function testDumpingArrayObjectInstancesRespectsInlineLevel()    {        $deep = new \ArrayObject(['deep1' => 'd', 'deep2' => 'e']);        $inner = new \ArrayObject(['inner1' => 'b', 'inner2' => 'c', 'inner3' => $deep]);        $outer = new \ArrayObject(['outer1' => 'a', 'outer2' => $inner]);        $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP);        $expected = <<<YAMLouter1: aouter2:    inner1: b    inner2: c    inner3: { deep1: d, deep2: e }YAML;        $this->assertSame($expected, $yaml);    }    public function testDumpingArrayObjectInstancesWithNumericKeysInlined()    {        $deep = new \ArrayObject(['d', 'e']);        $inner = new \ArrayObject(['b', 'c', $deep]);        $outer = new \ArrayObject(['a', $inner]);        $yaml = $this->dumper->dump($outer, 0, 0, Yaml::DUMP_OBJECT_AS_MAP);        $expected = <<<YAML{ 0: a, 1: { 0: b, 1: c, 2: { 0: d, 1: e } } }YAML;        $this->assertSame($expected, $yaml);    }    public function testDumpingArrayObjectInstancesWithNumericKeysRespectsInlineLevel()    {        $deep = new \ArrayObject(['d', 'e']);        $inner = new \ArrayObject(['b', 'c', $deep]);        $outer = new \ArrayObject(['a', $inner]);        $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP);        $expected = <<<YAML0: a1:    0: b    1: c    2: { 0: d, 1: e }YAML;        $this->assertEquals($expected, $yaml);    }    public function testDumpEmptyArrayObjectInstanceAsMap()    {        $this->assertSame('{  }', $this->dumper->dump(new \ArrayObject(), 2, 0, Yaml::DUMP_OBJECT_AS_MAP));    }    public function testDumpEmptyStdClassInstanceAsMap()    {        $this->assertSame('{  }', $this->dumper->dump(new \stdClass(), 2, 0, Yaml::DUMP_OBJECT_AS_MAP));    }    public function testDumpingStdClassInstancesRespectsInlineLevel()    {        $deep = new \stdClass();        $deep->deep1 = 'd';        $deep->deep2 = 'e';        $inner = new \stdClass();        $inner->inner1 = 'b';        $inner->inner2 = 'c';        $inner->inner3 = $deep;        $outer = new \stdClass();        $outer->outer1 = 'a';        $outer->outer2 = $inner;        $yaml = $this->dumper->dump($outer, 2, 0, Yaml::DUMP_OBJECT_AS_MAP);        $expected = <<<YAMLouter1: aouter2:    inner1: b    inner2: c    inner3: { deep1: d, deep2: e }YAML;        $this->assertSame($expected, $yaml);    }    public function testDumpingTaggedValueSequenceRespectsInlineLevel()    {        $data = [            new TaggedValue('user', [                'username' => 'jane',            ]),            new TaggedValue('user', [                'username' => 'john',            ]),        ];        $yaml = $this->dumper->dump($data, 2);        $expected = <<<YAML- !user  username: jane- !user  username: johnYAML;        $this->assertSame($expected, $yaml);    }    public function testDumpingTaggedValueSequenceWithInlinedTagValues()    {        $data = [            new TaggedValue('user', [                'username' => 'jane',            ]),            new TaggedValue('user', [                'username' => 'john',            ]),        ];        $yaml = $this->dumper->dump($data, 1);        $expected = <<<YAML- !user { username: jane }- !user { username: john }YAML;        $this->assertSame($expected, $yaml);    }    public function testDumpingTaggedValueMapRespectsInlineLevel()    {        $data = [            'user1' => new TaggedValue('user', [                'username' => 'jane',            ]),            'user2' => new TaggedValue('user', [                'username' => 'john',            ]),        ];        $yaml = $this->dumper->dump($data, 2);        $expected = <<<YAMLuser1: !user    username: janeuser2: !user    username: johnYAML;        $this->assertSame($expected, $yaml);    }    public function testDumpingTaggedValueMapWithInlinedTagValues()    {        $data = [            'user1' => new TaggedValue('user', [                'username' => 'jane',            ]),            'user2' => new TaggedValue('user', [                'username' => 'john',            ]),        ];        $yaml = $this->dumper->dump($data, 1);        $expected = <<<YAMLuser1: !user { username: jane }user2: !user { username: john }YAML;        $this->assertSame($expected, $yaml);    }    public function testDumpingNotInlinedScalarTaggedValue()    {        $data = [            'user1' => new TaggedValue('user', 'jane'),            'user2' => new TaggedValue('user', 'john'),        ];        $expected = <<<YAMLuser1: !user janeuser2: !user johnYAML;        $this->assertSame($expected, $this->dumper->dump($data, 2));    }    public function testDumpingNotInlinedNullTaggedValue()    {        $data = [            'foo' => new TaggedValue('bar', null),        ];        $expected = <<<YAMLfoo: !bar nullYAML;        $this->assertSame($expected, $this->dumper->dump($data, 2));    }    public function testDumpMultiLineStringAsScalarBlock()    {        $data = [            'data' => [                'single_line' => 'foo bar baz',                'multi_line' => "foo\nline with trailing spaces:\n  \nbar\ninteger like line:\n123456789\nempty line:\n\nbaz",                'multi_line_with_carriage_return' => "foo\nbar\r\nbaz",                'nested_inlined_multi_line_string' => [                    'inlined_multi_line' => "foo\nbar\r\nempty line:\n\nbaz",                ],            ],        ];        $this->assertSame(file_get_contents(__DIR__.'/Fixtures/multiple_lines_as_literal_block.yml'), $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK));    }    public function testDumpMultiLineStringAsScalarBlockWhenFirstLineHasLeadingSpace()    {        $data = [            'data' => [                'multi_line' => "    the first line has leading spaces\nThe second line does not.",            ],        ];        $this->assertSame(file_get_contents(__DIR__.'/Fixtures/multiple_lines_as_literal_block_leading_space_in_first_line.yml'), $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK));    }    public function testCarriageReturnIsMaintainedWhenDumpingAsMultiLineLiteralBlock()    {        $this->assertSame("- \"a\\r\\nb\\nc\"\n", $this->dumper->dump(["a\r\nb\nc"], 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK));    }    public function testZeroIndentationThrowsException()    {        $this->expectException('InvalidArgumentException');        $this->expectExceptionMessage('The indentation must be greater than zero');        new Dumper(0);    }    public function testNegativeIndentationThrowsException()    {        $this->expectException('InvalidArgumentException');        $this->expectExceptionMessage('The indentation must be greater than zero');        new Dumper(-4);    }}class A{    public $a = 'foo';}
 |