7ca692dd1003565761cd8974eecf7032927ecfa2
[yaffs-website] / vendor / symfony / yaml / Tests / InlineTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Yaml\Tests;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Yaml\Inline;
16
17 class InlineTest extends TestCase
18 {
19     /**
20      * @dataProvider getTestsForParse
21      */
22     public function testParse($yaml, $value)
23     {
24         $this->assertSame($value, Inline::parse($yaml), sprintf('::parse() converts an inline YAML to a PHP structure (%s)', $yaml));
25     }
26
27     /**
28      * @dataProvider getTestsForParseWithMapObjects
29      */
30     public function testParseWithMapObjects($yaml, $value)
31     {
32         $actual = Inline::parse($yaml, false, false, true);
33
34         $this->assertSame(serialize($value), serialize($actual));
35     }
36
37     /**
38      * @dataProvider getTestsForDump
39      */
40     public function testDump($yaml, $value)
41     {
42         $this->assertEquals($yaml, Inline::dump($value), sprintf('::dump() converts a PHP structure to an inline YAML (%s)', $yaml));
43
44         $this->assertSame($value, Inline::parse(Inline::dump($value)), 'check consistency');
45     }
46
47     public function testDumpNumericValueWithLocale()
48     {
49         $locale = setlocale(LC_NUMERIC, 0);
50         if (false === $locale) {
51             $this->markTestSkipped('Your platform does not support locales.');
52         }
53
54         try {
55             $requiredLocales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252');
56             if (false === setlocale(LC_NUMERIC, $requiredLocales)) {
57                 $this->markTestSkipped('Could not set any of required locales: '.implode(', ', $requiredLocales));
58             }
59
60             $this->assertEquals('1.2', Inline::dump(1.2));
61             $this->assertContains('fr', strtolower(setlocale(LC_NUMERIC, 0)));
62             setlocale(LC_NUMERIC, $locale);
63         } catch (\Exception $e) {
64             setlocale(LC_NUMERIC, $locale);
65             throw $e;
66         }
67     }
68
69     public function testHashStringsResemblingExponentialNumericsShouldNotBeChangedToINF()
70     {
71         $value = '686e444';
72
73         $this->assertSame($value, Inline::parse(Inline::dump($value)));
74     }
75
76     /**
77      * @group legacy
78      * throws \Symfony\Component\Yaml\Exception\ParseException in 3.0
79      */
80     public function testParseScalarWithNonEscapedBlackslashShouldThrowException()
81     {
82         $this->assertSame('Foo\Var', Inline::parse('"Foo\Var"'));
83     }
84
85     /**
86      * @expectedException \Symfony\Component\Yaml\Exception\ParseException
87      */
88     public function testParseScalarWithNonEscapedBlackslashAtTheEndShouldThrowException()
89     {
90         Inline::parse('"Foo\\"');
91     }
92
93     /**
94      * @expectedException \Symfony\Component\Yaml\Exception\ParseException
95      */
96     public function testParseScalarWithIncorrectlyQuotedStringShouldThrowException()
97     {
98         $value = "'don't do somthin' like that'";
99         Inline::parse($value);
100     }
101
102     /**
103      * @expectedException \Symfony\Component\Yaml\Exception\ParseException
104      */
105     public function testParseScalarWithIncorrectlyDoubleQuotedStringShouldThrowException()
106     {
107         $value = '"don"t do somthin" like that"';
108         Inline::parse($value);
109     }
110
111     /**
112      * @expectedException \Symfony\Component\Yaml\Exception\ParseException
113      */
114     public function testParseInvalidMappingKeyShouldThrowException()
115     {
116         $value = '{ "foo " bar": "bar" }';
117         Inline::parse($value);
118     }
119
120     /**
121      * @expectedException \Symfony\Component\Yaml\Exception\ParseException
122      */
123     public function testParseInvalidMappingShouldThrowException()
124     {
125         Inline::parse('[foo] bar');
126     }
127
128     /**
129      * @expectedException \Symfony\Component\Yaml\Exception\ParseException
130      */
131     public function testParseInvalidSequenceShouldThrowException()
132     {
133         Inline::parse('{ foo: bar } bar');
134     }
135
136     public function testParseScalarWithCorrectlyQuotedStringShouldReturnString()
137     {
138         $value = "'don''t do somthin'' like that'";
139         $expect = "don't do somthin' like that";
140
141         $this->assertSame($expect, Inline::parseScalar($value));
142     }
143
144     /**
145      * @dataProvider getDataForParseReferences
146      */
147     public function testParseReferences($yaml, $expected)
148     {
149         $this->assertSame($expected, Inline::parse($yaml, false, false, false, array('var' => 'var-value')));
150     }
151
152     public function getDataForParseReferences()
153     {
154         return array(
155             'scalar' => array('*var', 'var-value'),
156             'list' => array('[ *var ]', array('var-value')),
157             'list-in-list' => array('[[ *var ]]', array(array('var-value'))),
158             'map-in-list' => array('[ { key: *var } ]', array(array('key' => 'var-value'))),
159             'embedded-mapping-in-list' => array('[ key: *var ]', array(array('key' => 'var-value'))),
160             'map' => array('{ key: *var }', array('key' => 'var-value')),
161             'list-in-map' => array('{ key: [*var] }', array('key' => array('var-value'))),
162             'map-in-map' => array('{ foo: { bar: *var } }', array('foo' => array('bar' => 'var-value'))),
163         );
164     }
165
166     public function testParseMapReferenceInSequence()
167     {
168         $foo = array(
169             'a' => 'Steve',
170             'b' => 'Clark',
171             'c' => 'Brian',
172         );
173         $this->assertSame(array($foo), Inline::parse('[*foo]', false, false, false, array('foo' => $foo)));
174     }
175
176     /**
177      * @expectedException \Symfony\Component\Yaml\Exception\ParseException
178      * @expectedExceptionMessage A reference must contain at least one character.
179      */
180     public function testParseUnquotedAsterisk()
181     {
182         Inline::parse('{ foo: * }');
183     }
184
185     /**
186      * @expectedException \Symfony\Component\Yaml\Exception\ParseException
187      * @expectedExceptionMessage A reference must contain at least one character.
188      */
189     public function testParseUnquotedAsteriskFollowedByAComment()
190     {
191         Inline::parse('{ foo: * #foo }');
192     }
193
194     /**
195      * @group legacy
196      * @expectedDeprecation Not quoting the scalar "@foo " starting with "@" is deprecated since Symfony 2.8 and will throw a ParseException in 3.0.
197      * throws \Symfony\Component\Yaml\Exception\ParseException in 3.0
198      */
199     public function testParseUnquotedScalarStartingWithReservedAtIndicator()
200     {
201         Inline::parse('{ foo: @foo }');
202     }
203
204     /**
205      * @group legacy
206      * @expectedDeprecation Not quoting the scalar "`foo " starting with "`" is deprecated since Symfony 2.8 and will throw a ParseException in 3.0.
207      * throws \Symfony\Component\Yaml\Exception\ParseException in 3.0
208      */
209     public function testParseUnquotedScalarStartingWithReservedBacktickIndicator()
210     {
211         Inline::parse('{ foo: `foo }');
212     }
213
214     /**
215      * @group legacy
216      * @expectedDeprecation Not quoting the scalar "|foo " starting with "|" is deprecated since Symfony 2.8 and will throw a ParseException in 3.0.
217      * throws \Symfony\Component\Yaml\Exception\ParseException in 3.0
218      */
219     public function testParseUnquotedScalarStartingWithLiteralStyleIndicator()
220     {
221         Inline::parse('{ foo: |foo }');
222     }
223
224     /**
225      * @group legacy
226      * @expectedDeprecation Not quoting the scalar ">foo " starting with ">" is deprecated since Symfony 2.8 and will throw a ParseException in 3.0.
227      * throws \Symfony\Component\Yaml\Exception\ParseException in 3.0
228      */
229     public function testParseUnquotedScalarStartingWithFoldedStyleIndicator()
230     {
231         Inline::parse('{ foo: >foo }');
232     }
233
234     public function getScalarIndicators()
235     {
236         return array(array('|'), array('>'));
237     }
238
239     /**
240      * @dataProvider getDataForIsHash
241      */
242     public function testIsHash($array, $expected)
243     {
244         $this->assertSame($expected, Inline::isHash($array));
245     }
246
247     public function getDataForIsHash()
248     {
249         return array(
250             array(array(), false),
251             array(array(1, 2, 3), false),
252             array(array(2 => 1, 1 => 2, 0 => 3), true),
253             array(array('foo' => 1, 'bar' => 2), true),
254         );
255     }
256
257     public function getTestsForParse()
258     {
259         return array(
260             array('', ''),
261             array('null', null),
262             array('false', false),
263             array('true', true),
264             array('12', 12),
265             array('-12', -12),
266             array('"quoted string"', 'quoted string'),
267             array("'quoted string'", 'quoted string'),
268             array('12.30e+02', 12.30e+02),
269             array('0x4D2', 0x4D2),
270             array('02333', 02333),
271             array('.Inf', -log(0)),
272             array('-.Inf', log(0)),
273             array("'686e444'", '686e444'),
274             array('686e444', 646e444),
275             array('123456789123456789123456789123456789', '123456789123456789123456789123456789'),
276             array('"foo\r\nbar"', "foo\r\nbar"),
277             array("'foo#bar'", 'foo#bar'),
278             array("'foo # bar'", 'foo # bar'),
279             array("'#cfcfcf'", '#cfcfcf'),
280             array('::form_base.html.twig', '::form_base.html.twig'),
281
282             // Pre-YAML-1.2 booleans
283             array("'y'", 'y'),
284             array("'n'", 'n'),
285             array("'yes'", 'yes'),
286             array("'no'", 'no'),
287             array("'on'", 'on'),
288             array("'off'", 'off'),
289
290             array('2007-10-30', gmmktime(0, 0, 0, 10, 30, 2007)),
291             array('2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)),
292             array('2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)),
293             array('1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)),
294             array('1730-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 1730)),
295
296             array('"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''),
297             array("'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''),
298
299             // sequences
300             // urls are no key value mapping. see #3609. Valid yaml "key: value" mappings require a space after the colon
301             array('[foo, http://urls.are/no/mappings, false, null, 12]', array('foo', 'http://urls.are/no/mappings', false, null, 12)),
302             array('[  foo  ,   bar , false  ,  null     ,  12  ]', array('foo', 'bar', false, null, 12)),
303             array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')),
304
305             // mappings
306             array('{foo:bar,bar:foo,false:false,null:null,integer:12}', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
307             array('{ foo  : bar, bar : foo,  false  :   false,  null  :   null,  integer :  12  }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
308             array('{foo: \'bar\', bar: \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')),
309             array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')),
310             array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', array('foo\'' => 'bar', 'bar"' => 'foo: bar')),
311             array('{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}', array('foo: ' => 'bar', 'bar: ' => 'foo: bar')),
312
313             // nested sequences and mappings
314             array('[foo, [bar, foo]]', array('foo', array('bar', 'foo'))),
315             array('[foo, {bar: foo}]', array('foo', array('bar' => 'foo'))),
316             array('{ foo: {bar: foo} }', array('foo' => array('bar' => 'foo'))),
317             array('{ foo: [bar, foo] }', array('foo' => array('bar', 'foo'))),
318
319             array('[  foo, [  bar, foo  ]  ]', array('foo', array('bar', 'foo'))),
320
321             array('[{ foo: {bar: foo} }]', array(array('foo' => array('bar' => 'foo')))),
322
323             array('[foo, [bar, [foo, [bar, foo]], foo]]', array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo'))),
324
325             array('[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]', array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo')))),
326
327             array('[foo, bar: { foo: bar }]', array('foo', '1' => array('bar' => array('foo' => 'bar')))),
328             array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')),
329         );
330     }
331
332     public function getTestsForParseWithMapObjects()
333     {
334         return array(
335             array('', ''),
336             array('null', null),
337             array('false', false),
338             array('true', true),
339             array('12', 12),
340             array('-12', -12),
341             array('"quoted string"', 'quoted string'),
342             array("'quoted string'", 'quoted string'),
343             array('12.30e+02', 12.30e+02),
344             array('0x4D2', 0x4D2),
345             array('02333', 02333),
346             array('.Inf', -log(0)),
347             array('-.Inf', log(0)),
348             array("'686e444'", '686e444'),
349             array('686e444', 646e444),
350             array('123456789123456789123456789123456789', '123456789123456789123456789123456789'),
351             array('"foo\r\nbar"', "foo\r\nbar"),
352             array("'foo#bar'", 'foo#bar'),
353             array("'foo # bar'", 'foo # bar'),
354             array("'#cfcfcf'", '#cfcfcf'),
355             array('::form_base.html.twig', '::form_base.html.twig'),
356
357             array('2007-10-30', gmmktime(0, 0, 0, 10, 30, 2007)),
358             array('2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)),
359             array('2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)),
360             array('1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)),
361             array('1730-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 1730)),
362
363             array('"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''),
364             array("'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''),
365
366             // sequences
367             // urls are no key value mapping. see #3609. Valid yaml "key: value" mappings require a space after the colon
368             array('[foo, http://urls.are/no/mappings, false, null, 12]', array('foo', 'http://urls.are/no/mappings', false, null, 12)),
369             array('[  foo  ,   bar , false  ,  null     ,  12  ]', array('foo', 'bar', false, null, 12)),
370             array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')),
371
372             // mappings
373             array('{foo:bar,bar:foo,false:false,null:null,integer:12}', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
374             array('{ foo  : bar, bar : foo,  false  :   false,  null  :   null,  integer :  12  }', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
375             array('{foo: \'bar\', bar: \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')),
376             array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')),
377             array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', (object) array('foo\'' => 'bar', 'bar"' => 'foo: bar')),
378             array('{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}', (object) array('foo: ' => 'bar', 'bar: ' => 'foo: bar')),
379
380             // nested sequences and mappings
381             array('[foo, [bar, foo]]', array('foo', array('bar', 'foo'))),
382             array('[foo, {bar: foo}]', array('foo', (object) array('bar' => 'foo'))),
383             array('{ foo: {bar: foo} }', (object) array('foo' => (object) array('bar' => 'foo'))),
384             array('{ foo: [bar, foo] }', (object) array('foo' => array('bar', 'foo'))),
385
386             array('[  foo, [  bar, foo  ]  ]', array('foo', array('bar', 'foo'))),
387
388             array('[{ foo: {bar: foo} }]', array((object) array('foo' => (object) array('bar' => 'foo')))),
389
390             array('[foo, [bar, [foo, [bar, foo]], foo]]', array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo'))),
391
392             array('[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]', array('foo', (object) array('bar' => 'foo', 'foo' => array('foo', (object) array('bar' => 'foo'))), array('foo', (object) array('bar' => 'foo')))),
393
394             array('[foo, bar: { foo: bar }]', array('foo', '1' => (object) array('bar' => (object) array('foo' => 'bar')))),
395             array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', (object) array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')),
396
397             array('{}', new \stdClass()),
398             array('{ foo  : bar, bar : {}  }', (object) array('foo' => 'bar', 'bar' => new \stdClass())),
399             array('{ foo  : [], bar : {}  }', (object) array('foo' => array(), 'bar' => new \stdClass())),
400             array('{foo: \'bar\', bar: {} }', (object) array('foo' => 'bar', 'bar' => new \stdClass())),
401             array('{\'foo\': \'bar\', "bar": {}}', (object) array('foo' => 'bar', 'bar' => new \stdClass())),
402             array('{\'foo\': \'bar\', "bar": \'{}\'}', (object) array('foo' => 'bar', 'bar' => '{}')),
403
404             array('[foo, [{}, {}]]', array('foo', array(new \stdClass(), new \stdClass()))),
405             array('[foo, [[], {}]]', array('foo', array(array(), new \stdClass()))),
406             array('[foo, [[{}, {}], {}]]', array('foo', array(array(new \stdClass(), new \stdClass()), new \stdClass()))),
407             array('[foo, {bar: {}}]', array('foo', '1' => (object) array('bar' => new \stdClass()))),
408         );
409     }
410
411     public function getTestsForDump()
412     {
413         return array(
414             array('null', null),
415             array('false', false),
416             array('true', true),
417             array('12', 12),
418             array("'quoted string'", 'quoted string'),
419             array('!!float 1230', 12.30e+02),
420             array('1234', 0x4D2),
421             array('1243', 02333),
422             array('.Inf', -log(0)),
423             array('-.Inf', log(0)),
424             array("'686e444'", '686e444'),
425             array('"foo\r\nbar"', "foo\r\nbar"),
426             array("'foo#bar'", 'foo#bar'),
427             array("'foo # bar'", 'foo # bar'),
428             array("'#cfcfcf'", '#cfcfcf'),
429
430             array("'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''),
431
432             array("'-dash'", '-dash'),
433             array("'-'", '-'),
434
435             // Pre-YAML-1.2 booleans
436             array("'y'", 'y'),
437             array("'n'", 'n'),
438             array("'yes'", 'yes'),
439             array("'no'", 'no'),
440             array("'on'", 'on'),
441             array("'off'", 'off'),
442
443             // sequences
444             array('[foo, bar, false, null, 12]', array('foo', 'bar', false, null, 12)),
445             array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')),
446
447             // mappings
448             array('{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)),
449             array('{ foo: bar, bar: \'foo: bar\' }', array('foo' => 'bar', 'bar' => 'foo: bar')),
450
451             // nested sequences and mappings
452             array('[foo, [bar, foo]]', array('foo', array('bar', 'foo'))),
453
454             array('[foo, [bar, [foo, [bar, foo]], foo]]', array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo'))),
455
456             array('{ foo: { bar: foo } }', array('foo' => array('bar' => 'foo'))),
457
458             array('[foo, { bar: foo }]', array('foo', array('bar' => 'foo'))),
459
460             array('[foo, { bar: foo, foo: [foo, { bar: foo }] }, [foo, { bar: foo }]]', array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo')))),
461
462             array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')),
463
464             array('{ foo: { bar: { 1: 2, baz: 3 } } }', array('foo' => array('bar' => array(1 => 2, 'baz' => 3)))),
465         );
466     }
467
468     /**
469      * @expectedException \Symfony\Component\Yaml\Exception\ParseException
470      * @expectedExceptionMessage Malformed inline YAML string: {this, is not, supported}.
471      */
472     public function testNotSupportedMissingValue()
473     {
474         Inline::parse('{this, is not, supported}');
475     }
476
477     public function testVeryLongQuotedStrings()
478     {
479         $longStringWithQuotes = str_repeat("x\r\n\\\"x\"x", 1000);
480
481         $yamlString = Inline::dump(array('longStringWithQuotes' => $longStringWithQuotes));
482         $arrayFromYaml = Inline::parse($yamlString);
483
484         $this->assertEquals($longStringWithQuotes, $arrayFromYaml['longStringWithQuotes']);
485     }
486
487     public function testBooleanMappingKeysAreConvertedToStrings()
488     {
489         $this->assertSame(array('false' => 'foo'), Inline::parse('{false: foo}'));
490         $this->assertSame(array('true' => 'foo'), Inline::parse('{true: foo}'));
491     }
492
493     public function testTheEmptyStringIsAValidMappingKey()
494     {
495         $this->assertSame(array('' => 'foo'), Inline::parse('{ "": foo }'));
496     }
497 }