1: | <?php
|
2: |
|
3: | |
4: | |
5: | |
6: | |
7: | |
8: | |
9: | |
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: | |
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: | |
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: | |
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: | |
78: | |
79: |
|
80: | public function testParseScalarWithNonEscapedBlackslashShouldThrowException()
|
81: | {
|
82: | $this->assertSame('Foo\Var', Inline::parse('"Foo\Var"'));
|
83: | }
|
84: |
|
85: | |
86: | |
87: |
|
88: | public function testParseScalarWithNonEscapedBlackslashAtTheEndShouldThrowException()
|
89: | {
|
90: | Inline::parse('"Foo\\"');
|
91: | }
|
92: |
|
93: | |
94: | |
95: |
|
96: | public function testParseScalarWithIncorrectlyQuotedStringShouldThrowException()
|
97: | {
|
98: | $value = "'don't do somthin' like that'";
|
99: | Inline::parse($value);
|
100: | }
|
101: |
|
102: | |
103: | |
104: |
|
105: | public function testParseScalarWithIncorrectlyDoubleQuotedStringShouldThrowException()
|
106: | {
|
107: | $value = '"don"t do somthin" like that"';
|
108: | Inline::parse($value);
|
109: | }
|
110: |
|
111: | |
112: | |
113: |
|
114: | public function testParseInvalidMappingKeyShouldThrowException()
|
115: | {
|
116: | $value = '{ "foo " bar": "bar" }';
|
117: | Inline::parse($value);
|
118: | }
|
119: |
|
120: | |
121: | |
122: |
|
123: | public function testParseInvalidMappingShouldThrowException()
|
124: | {
|
125: | Inline::parse('[foo] bar');
|
126: | }
|
127: |
|
128: | |
129: | |
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: | |
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: | |
178: | |
179: |
|
180: | public function testParseUnquotedAsterisk()
|
181: | {
|
182: | Inline::parse('{ foo: * }');
|
183: | }
|
184: |
|
185: | |
186: | |
187: | |
188: |
|
189: | public function testParseUnquotedAsteriskFollowedByAComment()
|
190: | {
|
191: | Inline::parse('{ foo: * #foo }');
|
192: | }
|
193: |
|
194: | |
195: | |
196: | |
197: | |
198: |
|
199: | public function testParseUnquotedScalarStartingWithReservedAtIndicator()
|
200: | {
|
201: | Inline::parse('{ foo: @foo }');
|
202: | }
|
203: |
|
204: | |
205: | |
206: | |
207: | |
208: |
|
209: | public function testParseUnquotedScalarStartingWithReservedBacktickIndicator()
|
210: | {
|
211: | Inline::parse('{ foo: `foo }');
|
212: | }
|
213: |
|
214: | |
215: | |
216: | |
217: | |
218: |
|
219: | public function testParseUnquotedScalarStartingWithLiteralStyleIndicator()
|
220: | {
|
221: | Inline::parse('{ foo: |foo }');
|
222: | }
|
223: |
|
224: | |
225: | |
226: | |
227: | |
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: | |
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: |
|
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: |
|
300: |
|
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: |
|
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: |
|
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: |
|
367: |
|
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: |
|
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: |
|
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: |
|
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: |
|
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: |
|
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: |
|
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: | |
470: | |
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: |
|
498: | |
499: | |
500: | |
501: |
|
502: | public function testUnfinishedInlineMap()
|
503: | {
|
504: | Inline::parse("{abc: 'def'");
|
505: | }
|
506: | }
|
507: | |