ParserTest::testTagMappingAsScalarKey()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <[email protected]>
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\Parser;
16
use Symfony\Component\Yaml\Tag\TaggedValue;
17
use Symfony\Component\Yaml\Yaml;
18
19
class ParserTest extends TestCase
20
{
21
    /** @var Parser */
22
    protected $parser;
23
24
    protected function setUp()
25
    {
26
        $this->parser = new Parser();
27
    }
28
29
    protected function tearDown()
30
    {
31
        $this->parser = null;
32
33
        chmod(__DIR__.'/Fixtures/not_readable.yml', 0644);
34
    }
35
36
    /**
37
     * @dataProvider getDataFormSpecifications
38
     */
39
    public function testSpecifications($expected, $yaml, $comment, $deprecated)
40
    {
41
        $deprecations = [];
42
43
        if ($deprecated) {
44
            set_error_handler(function ($type, $msg) use (&$deprecations) {
45
                if (\E_USER_DEPRECATED !== $type) {
46
                    restore_error_handler();
47
48
                    return \call_user_func_array('PHPUnit\Util\ErrorHandler::handleError', \func_get_args());
49
                }
50
51
                $deprecations[] = $msg;
52
53
                return null;
54
            });
55
        }
56
57
        $this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment);
58
59
        if ($deprecated) {
60
            restore_error_handler();
61
62
            $this->assertCount(1, $deprecations);
63
            $this->assertStringContainsString(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]);
64
        }
65
    }
66
67
    public function getDataFormSpecifications()
68
    {
69
        return $this->loadTestsFromFixtureFiles('index.yml');
70
    }
71
72
    /**
73
     * @group legacy
74
     * @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
75
     * @dataProvider getNonStringMappingKeysData
76
     */
77
    public function testNonStringMappingKeys($expected, $yaml, $comment)
78
    {
79
        $this->assertSame($expected, var_export($this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS), true), $comment);
0 ignored issues
show
Deprecated Code introduced by
The constant Symfony\Component\Yaml\Yaml::PARSE_KEYS_AS_STRINGS has been deprecated: since version 3.4, to be removed in 4.0. Quote your evaluable keys instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

79
        $this->assertSame($expected, var_export($this->parser->parse($yaml, /** @scrutinizer ignore-deprecated */ Yaml::PARSE_KEYS_AS_STRINGS), true), $comment);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
80
    }
81
82
    public function getNonStringMappingKeysData()
83
    {
84
        return $this->loadTestsFromFixtureFiles('nonStringKeys.yml');
85
    }
86
87
    /**
88
     * @group legacy
89
     * @dataProvider getLegacyNonStringMappingKeysData
90
     */
91
    public function testLegacyNonStringMappingKeys($expected, $yaml, $comment)
92
    {
93
        $this->assertSame($expected, var_export($this->parser->parse($yaml), true), $comment);
94
    }
95
96
    public function getLegacyNonStringMappingKeysData()
97
    {
98
        return $this->loadTestsFromFixtureFiles('legacyNonStringKeys.yml');
99
    }
100
101
    public function testTabsInYaml()
102
    {
103
        // test tabs in YAML
104
        $yamls = [
105
            "foo:\n	bar",
106
            "foo:\n 	bar",
107
            "foo:\n	 bar",
108
            "foo:\n 	 bar",
109
        ];
110
111
        foreach ($yamls as $yaml) {
112
            try {
113
                $this->parser->parse($yaml);
114
115
                $this->fail('YAML files must not contain tabs');
116
            } catch (\Exception $e) {
117
                $this->assertInstanceOf('\Exception', $e, 'YAML files must not contain tabs');
118
                $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');
119
            }
120
        }
121
    }
122
123
    public function testEndOfTheDocumentMarker()
124
    {
125
        $yaml = <<<'EOF'
126
--- %YAML:1.0
127
foo
128
...
129
EOF;
130
131
        $this->assertEquals('foo', $this->parser->parse($yaml));
132
    }
133
134
    public function getBlockChompingTests()
135
    {
136
        $tests = [];
137
138
        $yaml = <<<'EOF'
139
foo: |-
140
    one
141
    two
142
bar: |-
143
    one
144
    two
145
146
EOF;
147
        $expected = [
148
            'foo' => "one\ntwo",
149
            'bar' => "one\ntwo",
150
        ];
151
        $tests['Literal block chomping strip with single trailing newline'] = [$expected, $yaml];
152
153
        $yaml = <<<'EOF'
154
foo: |-
155
    one
156
    two
157
158
bar: |-
159
    one
160
    two
161
162
163
EOF;
164
        $expected = [
165
            'foo' => "one\ntwo",
166
            'bar' => "one\ntwo",
167
        ];
168
        $tests['Literal block chomping strip with multiple trailing newlines'] = [$expected, $yaml];
169
170
        $yaml = <<<'EOF'
171
{}
172
173
174
EOF;
175
        $expected = [];
176
        $tests['Literal block chomping strip with multiple trailing newlines after a 1-liner'] = [$expected, $yaml];
177
178
        $yaml = <<<'EOF'
179
foo: |-
180
    one
181
    two
182
bar: |-
183
    one
184
    two
185
EOF;
186
        $expected = [
187
            'foo' => "one\ntwo",
188
            'bar' => "one\ntwo",
189
        ];
190
        $tests['Literal block chomping strip without trailing newline'] = [$expected, $yaml];
191
192
        $yaml = <<<'EOF'
193
foo: |
194
    one
195
    two
196
bar: |
197
    one
198
    two
199
200
EOF;
201
        $expected = [
202
            'foo' => "one\ntwo\n",
203
            'bar' => "one\ntwo\n",
204
        ];
205
        $tests['Literal block chomping clip with single trailing newline'] = [$expected, $yaml];
206
207
        $yaml = <<<'EOF'
208
foo: |
209
    one
210
    two
211
212
bar: |
213
    one
214
    two
215
216
217
EOF;
218
        $expected = [
219
            'foo' => "one\ntwo\n",
220
            'bar' => "one\ntwo\n",
221
        ];
222
        $tests['Literal block chomping clip with multiple trailing newlines'] = [$expected, $yaml];
223
224
        $yaml = <<<'EOF'
225
foo:
226
- bar: |
227
    one
228
229
    two
230
EOF;
231
        $expected = [
232
            'foo' => [
233
                [
234
                    'bar' => "one\n\ntwo",
235
                ],
236
            ],
237
        ];
238
        $tests['Literal block chomping clip with embedded blank line inside unindented collection'] = [$expected, $yaml];
239
240
        $yaml = <<<'EOF'
241
foo: |
242
    one
243
    two
244
bar: |
245
    one
246
    two
247
EOF;
248
        $expected = [
249
            'foo' => "one\ntwo\n",
250
            'bar' => "one\ntwo",
251
        ];
252
        $tests['Literal block chomping clip without trailing newline'] = [$expected, $yaml];
253
254
        $yaml = <<<'EOF'
255
foo: |+
256
    one
257
    two
258
bar: |+
259
    one
260
    two
261
262
EOF;
263
        $expected = [
264
            'foo' => "one\ntwo\n",
265
            'bar' => "one\ntwo\n",
266
        ];
267
        $tests['Literal block chomping keep with single trailing newline'] = [$expected, $yaml];
268
269
        $yaml = <<<'EOF'
270
foo: |+
271
    one
272
    two
273
274
bar: |+
275
    one
276
    two
277
278
279
EOF;
280
        $expected = [
281
            'foo' => "one\ntwo\n\n",
282
            'bar' => "one\ntwo\n\n",
283
        ];
284
        $tests['Literal block chomping keep with multiple trailing newlines'] = [$expected, $yaml];
285
286
        $yaml = <<<'EOF'
287
foo: |+
288
    one
289
    two
290
bar: |+
291
    one
292
    two
293
EOF;
294
        $expected = [
295
            'foo' => "one\ntwo\n",
296
            'bar' => "one\ntwo",
297
        ];
298
        $tests['Literal block chomping keep without trailing newline'] = [$expected, $yaml];
299
300
        $yaml = <<<'EOF'
301
foo: >-
302
    one
303
    two
304
bar: >-
305
    one
306
    two
307
308
EOF;
309
        $expected = [
310
            'foo' => 'one two',
311
            'bar' => 'one two',
312
        ];
313
        $tests['Folded block chomping strip with single trailing newline'] = [$expected, $yaml];
314
315
        $yaml = <<<'EOF'
316
foo: >-
317
    one
318
    two
319
320
bar: >-
321
    one
322
    two
323
324
325
EOF;
326
        $expected = [
327
            'foo' => 'one two',
328
            'bar' => 'one two',
329
        ];
330
        $tests['Folded block chomping strip with multiple trailing newlines'] = [$expected, $yaml];
331
332
        $yaml = <<<'EOF'
333
foo: >-
334
    one
335
    two
336
bar: >-
337
    one
338
    two
339
EOF;
340
        $expected = [
341
            'foo' => 'one two',
342
            'bar' => 'one two',
343
        ];
344
        $tests['Folded block chomping strip without trailing newline'] = [$expected, $yaml];
345
346
        $yaml = <<<'EOF'
347
foo: >
348
    one
349
    two
350
bar: >
351
    one
352
    two
353
354
EOF;
355
        $expected = [
356
            'foo' => "one two\n",
357
            'bar' => "one two\n",
358
        ];
359
        $tests['Folded block chomping clip with single trailing newline'] = [$expected, $yaml];
360
361
        $yaml = <<<'EOF'
362
foo: >
363
    one
364
    two
365
366
bar: >
367
    one
368
    two
369
370
371
EOF;
372
        $expected = [
373
            'foo' => "one two\n",
374
            'bar' => "one two\n",
375
        ];
376
        $tests['Folded block chomping clip with multiple trailing newlines'] = [$expected, $yaml];
377
378
        $yaml = <<<'EOF'
379
foo: >
380
    one
381
    two
382
bar: >
383
    one
384
    two
385
EOF;
386
        $expected = [
387
            'foo' => "one two\n",
388
            'bar' => 'one two',
389
        ];
390
        $tests['Folded block chomping clip without trailing newline'] = [$expected, $yaml];
391
392
        $yaml = <<<'EOF'
393
foo: >+
394
    one
395
    two
396
bar: >+
397
    one
398
    two
399
400
EOF;
401
        $expected = [
402
            'foo' => "one two\n",
403
            'bar' => "one two\n",
404
        ];
405
        $tests['Folded block chomping keep with single trailing newline'] = [$expected, $yaml];
406
407
        $yaml = <<<'EOF'
408
foo: >+
409
    one
410
    two
411
412
bar: >+
413
    one
414
    two
415
416
417
EOF;
418
        $expected = [
419
            'foo' => "one two\n\n",
420
            'bar' => "one two\n\n",
421
        ];
422
        $tests['Folded block chomping keep with multiple trailing newlines'] = [$expected, $yaml];
423
424
        $yaml = <<<'EOF'
425
foo: >+
426
    one
427
    two
428
bar: >+
429
    one
430
    two
431
EOF;
432
        $expected = [
433
            'foo' => "one two\n",
434
            'bar' => 'one two',
435
        ];
436
        $tests['Folded block chomping keep without trailing newline'] = [$expected, $yaml];
437
438
        return $tests;
439
    }
440
441
    /**
442
     * @dataProvider getBlockChompingTests
443
     */
444
    public function testBlockChomping($expected, $yaml)
445
    {
446
        $this->assertSame($expected, $this->parser->parse($yaml));
447
    }
448
449
    /**
450
     * Regression test for issue #7989.
451
     *
452
     * @see https://github.com/symfony/symfony/issues/7989
453
     */
454
    public function testBlockLiteralWithLeadingNewlines()
455
    {
456
        $yaml = <<<'EOF'
457
foo: |-
458
459
460
    bar
461
462
EOF;
463
        $expected = [
464
            'foo' => "\n\nbar",
465
        ];
466
467
        $this->assertSame($expected, $this->parser->parse($yaml));
468
    }
469
470
    public function testObjectSupportEnabled()
471
    {
472
        $input = <<<'EOF'
473
foo: !php/object O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
474
bar: 1
475
EOF;
476
        $this->assertEquals(['foo' => new B(), 'bar' => 1], $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
477
    }
478
479
    /**
480
     * @group legacy
481
     */
482
    public function testObjectSupportEnabledPassingTrue()
483
    {
484
        $input = <<<'EOF'
485
foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
486
bar: 1
487
EOF;
488
        $this->assertEquals(['foo' => new B(), 'bar' => 1], $this->parser->parse($input, false, true), '->parse() is able to parse objects');
489
    }
490
491
    /**
492
     * @group legacy
493
     * @dataProvider deprecatedObjectValueProvider
494
     */
495
    public function testObjectSupportEnabledWithDeprecatedTag($yaml)
496
    {
497
        $this->assertEquals(['foo' => new B(), 'bar' => 1], $this->parser->parse($yaml, Yaml::PARSE_OBJECT), '->parse() is able to parse objects');
498
    }
499
500
    public function deprecatedObjectValueProvider()
501
    {
502
        return [
503
            [
504
                <<<YAML
505
foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
506
bar: 1
507
YAML
508
            ],
509
            [
510
                <<<YAML
511
foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
512
bar: 1
513
YAML
514
            ],
515
        ];
516
    }
517
518
    /**
519
     * @dataProvider invalidDumpedObjectProvider
520
     */
521
    public function testObjectSupportDisabledButNoExceptions($input)
522
    {
523
        $this->assertEquals(['foo' => null, 'bar' => 1], $this->parser->parse($input), '->parse() does not parse objects');
524
    }
525
526
    /**
527
     * @dataProvider getObjectForMapTests
528
     */
529
    public function testObjectForMap($yaml, $expected)
530
    {
531
        $flags = Yaml::PARSE_OBJECT_FOR_MAP;
532
533
        $this->assertEquals($expected, $this->parser->parse($yaml, $flags));
534
    }
535
536
    /**
537
     * @group legacy
538
     * @dataProvider getObjectForMapTests
539
     */
540
    public function testObjectForMapEnabledWithMappingUsingBooleanToggles($yaml, $expected)
541
    {
542
        $this->assertEquals($expected, $this->parser->parse($yaml, false, false, true));
543
    }
544
545
    public function getObjectForMapTests()
546
    {
547
        $tests = [];
548
549
        $yaml = <<<'EOF'
550
foo:
551
    fiz: [cat]
552
EOF;
553
        $expected = new \stdClass();
554
        $expected->foo = new \stdClass();
555
        $expected->foo->fiz = ['cat'];
556
        $tests['mapping'] = [$yaml, $expected];
557
558
        $yaml = '{ "foo": "bar", "fiz": "cat" }';
559
        $expected = new \stdClass();
560
        $expected->foo = 'bar';
561
        $expected->fiz = 'cat';
562
        $tests['inline-mapping'] = [$yaml, $expected];
563
564
        $yaml = "foo: bar\nbaz: foobar";
565
        $expected = new \stdClass();
566
        $expected->foo = 'bar';
567
        $expected->baz = 'foobar';
568
        $tests['object-for-map-is-applied-after-parsing'] = [$yaml, $expected];
569
570
        $yaml = <<<'EOT'
571
array:
572
  - key: one
573
  - key: two
574
EOT;
575
        $expected = new \stdClass();
576
        $expected->array = [];
577
        $expected->array[0] = new \stdClass();
578
        $expected->array[0]->key = 'one';
579
        $expected->array[1] = new \stdClass();
580
        $expected->array[1]->key = 'two';
581
        $tests['nest-map-and-sequence'] = [$yaml, $expected];
582
583
        $yaml = <<<'YAML'
584
map:
585
  1: one
586
  2: two
587
YAML;
588
        $expected = new \stdClass();
589
        $expected->map = new \stdClass();
590
        $expected->map->{1} = 'one';
591
        $expected->map->{2} = 'two';
592
        $tests['numeric-keys'] = [$yaml, $expected];
593
594
        $yaml = <<<'YAML'
595
map:
596
  '0': one
597
  '1': two
598
YAML;
599
        $expected = new \stdClass();
600
        $expected->map = new \stdClass();
601
        $expected->map->{0} = 'one';
602
        $expected->map->{1} = 'two';
603
        $tests['zero-indexed-numeric-keys'] = [$yaml, $expected];
604
605
        return $tests;
606
    }
607
608
    /**
609
     * @dataProvider invalidDumpedObjectProvider
610
     */
611
    public function testObjectsSupportDisabledWithExceptions($yaml)
612
    {
613
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
614
        $this->parser->parse($yaml, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE);
615
    }
616
617
    public function testCanParseContentWithTrailingSpaces()
618
    {
619
        $yaml = "items:  \n  foo: bar";
620
621
        $expected = [
622
            'items' => ['foo' => 'bar'],
623
        ];
624
625
        $this->assertSame($expected, $this->parser->parse($yaml));
626
    }
627
628
    /**
629
     * @group legacy
630
     * @dataProvider invalidDumpedObjectProvider
631
     */
632
    public function testObjectsSupportDisabledWithExceptionsUsingBooleanToggles($yaml)
633
    {
634
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
635
        $this->parser->parse($yaml, true);
636
    }
637
638
    public function invalidDumpedObjectProvider()
639
    {
640
        $yamlTag = <<<'EOF'
641
foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}
642
bar: 1
643
EOF;
644
        $localTag = <<<'EOF'
645
foo: !php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}
646
bar: 1
647
EOF;
648
649
        return [
650
            'yaml-tag' => [$yamlTag],
651
            'local-tag' => [$localTag],
652
        ];
653
    }
654
655
    /**
656
     * @requires extension iconv
657
     */
658
    public function testNonUtf8Exception()
659
    {
660
        $yamls = [
661
            iconv('UTF-8', 'ISO-8859-1', "foo: 'äöüß'"),
662
            iconv('UTF-8', 'ISO-8859-15', "euro: '€'"),
663
            iconv('UTF-8', 'CP1252', "cp1252: '©ÉÇáñ'"),
664
        ];
665
666
        foreach ($yamls as $yaml) {
667
            try {
668
                $this->parser->parse($yaml);
669
670
                $this->fail('charsets other than UTF-8 are rejected.');
671
            } catch (\Exception $e) {
672
                $this->assertInstanceOf('Symfony\Component\Yaml\Exception\ParseException', $e, 'charsets other than UTF-8 are rejected.');
673
            }
674
        }
675
    }
676
677
    public function testUnindentedCollectionException()
678
    {
679
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
680
        $yaml = <<<'EOF'
681
682
collection:
683
-item1
684
-item2
685
-item3
686
687
EOF;
688
689
        $this->parser->parse($yaml);
690
    }
691
692
    public function testShortcutKeyUnindentedCollectionException()
693
    {
694
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
695
        $yaml = <<<'EOF'
696
697
collection:
698
-  key: foo
699
  foo: bar
700
701
EOF;
702
703
        $this->parser->parse($yaml);
704
    }
705
706
    public function testMultipleDocumentsNotSupportedException()
707
    {
708
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
709
        $this->expectExceptionMessageMatches('/^Multiple documents are not supported.+/');
0 ignored issues
show
Bug introduced by
The method expectExceptionMessageMatches() does not exist on Symfony\Component\Yaml\Tests\ParserTest. Did you maybe mean expectExceptionMessage()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

709
        $this->/** @scrutinizer ignore-call */ 
710
               expectExceptionMessageMatches('/^Multiple documents are not supported.+/');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
710
        Yaml::parse(<<<'EOL'
711
# Ranking of 1998 home runs
712
---
713
- Mark McGwire
714
- Sammy Sosa
715
- Ken Griffey
716
717
# Team ranking
718
---
719
- Chicago Cubs
720
- St Louis Cardinals
721
EOL
722
        );
723
    }
724
725
    public function testSequenceInAMapping()
726
    {
727
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
728
        Yaml::parse(<<<'EOF'
729
yaml:
730
  hash: me
731
  - array stuff
732
EOF
733
        );
734
    }
735
736
    public function testSequenceInMappingStartedBySingleDashLine()
737
    {
738
        $yaml = <<<'EOT'
739
a:
740
-
741
  b:
742
  -
743
    bar: baz
744
- foo
745
d: e
746
EOT;
747
        $expected = [
748
            'a' => [
749
                [
750
                    'b' => [
751
                        [
752
                            'bar' => 'baz',
753
                        ],
754
                    ],
755
                ],
756
                'foo',
757
            ],
758
            'd' => 'e',
759
        ];
760
761
        $this->assertSame($expected, $this->parser->parse($yaml));
762
    }
763
764
    public function testSequenceFollowedByCommentEmbeddedInMapping()
765
    {
766
        $yaml = <<<'EOT'
767
a:
768
    b:
769
        - c
770
# comment
771
    d: e
772
EOT;
773
        $expected = [
774
            'a' => [
775
                'b' => ['c'],
776
                'd' => 'e',
777
            ],
778
        ];
779
780
        $this->assertSame($expected, $this->parser->parse($yaml));
781
    }
782
783
    public function testNonStringFollowedByCommentEmbeddedInMapping()
784
    {
785
        $yaml = <<<'EOT'
786
a:
787
    b:
788
        {}
789
# comment
790
    d:
791
        1.1
792
# another comment
793
EOT;
794
        $expected = [
795
            'a' => [
796
                'b' => [],
797
                'd' => 1.1,
798
            ],
799
        ];
800
801
        $this->assertSame($expected, $this->parser->parse($yaml));
802
    }
803
804
    public function getParseExceptionNotAffectedMultiLineStringLastResortParsing()
805
    {
806
        $tests = [];
807
808
        $yaml = <<<'EOT'
809
a
810
    b:
811
EOT;
812
        $tests['parse error on first line'] = [$yaml];
813
814
        $yaml = <<<'EOT'
815
a
816
817
b
818
    c:
819
EOT;
820
        $tests['parse error due to inconsistent indentation'] = [$yaml];
821
822
        $yaml = <<<'EOT'
823
 &  *  !  |  >  '  "  %  @  ` #, { asd a;sdasd }-@^qw3
824
EOT;
825
        $tests['symfony/symfony/issues/22967#issuecomment-322067742'] = [$yaml];
826
827
        return $tests;
828
    }
829
830
    /**
831
     * @dataProvider getParseExceptionNotAffectedMultiLineStringLastResortParsing
832
     */
833
    public function testParseExceptionNotAffectedByMultiLineStringLastResortParsing($yaml)
834
    {
835
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
836
        $this->parser->parse($yaml);
837
    }
838
839
    public function testMultiLineStringLastResortParsing()
840
    {
841
        $yaml = <<<'EOT'
842
test:
843
  You can have things that don't look like strings here
844
  true
845
  yes you can
846
EOT;
847
        $expected = [
848
            'test' => 'You can have things that don\'t look like strings here true yes you can',
849
        ];
850
851
        $this->assertSame($expected, $this->parser->parse($yaml));
852
853
        $yaml = <<<'EOT'
854
a:
855
    b
856
       c
857
EOT;
858
        $expected = [
859
            'a' => 'b c',
860
        ];
861
862
        $this->assertSame($expected, $this->parser->parse($yaml));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->parser->parse($yaml) targeting Symfony\Component\Yaml\Parser::parse() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
863
    }
864
865
    public function testMappingInASequence()
866
    {
867
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
868
        Yaml::parse(<<<'EOF'
869
yaml:
870
  - array stuff
871
  hash: me
872
EOF
873
        );
874
    }
875
876
    public function testScalarInSequence()
877
    {
878
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
879
        $this->expectExceptionMessage('missing colon');
880
        Yaml::parse(<<<'EOF'
881
foo:
882
    - bar
883
"missing colon"
884
    foo: bar
885
EOF
886
        );
887
    }
888
889
    /**
890
     * > It is an error for two equal keys to appear in the same mapping node.
891
     * > In such a case the YAML processor may continue, ignoring the second
892
     * > `key: value` pair and issuing an appropriate warning. This strategy
893
     * > preserves a consistent information model for one-pass and random access
894
     * > applications.
895
     *
896
     * @see http://yaml.org/spec/1.2/spec.html#id2759572
897
     * @see http://yaml.org/spec/1.1/#id932806
898
     * @group legacy
899
     */
900
    public function testMappingDuplicateKeyBlock()
901
    {
902
        $input = <<<'EOD'
903
parent:
904
    child: first
905
    child: duplicate
906
parent:
907
    child: duplicate
908
    child: duplicate
909
EOD;
910
        $expected = [
911
            'parent' => [
912
                'child' => 'first',
913
            ],
914
        ];
915
        $this->assertSame($expected, Yaml::parse($input));
916
    }
917
918
    /**
919
     * @group legacy
920
     */
921
    public function testMappingDuplicateKeyFlow()
922
    {
923
        $input = <<<'EOD'
924
parent: { child: first, child: duplicate }
925
parent: { child: duplicate, child: duplicate }
926
EOD;
927
        $expected = [
928
            'parent' => [
929
                'child' => 'first',
930
            ],
931
        ];
932
        $this->assertSame($expected, Yaml::parse($input));
933
    }
934
935
    /**
936
     * @group legacy
937
     * @dataProvider getParseExceptionOnDuplicateData
938
     * @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.
939
     * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0
940
     */
941
    public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber)
0 ignored issues
show
Unused Code introduced by
The parameter $lineNumber is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

941
    public function testParseExceptionOnDuplicate($input, $duplicateKey, /** @scrutinizer ignore-unused */ $lineNumber)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $duplicateKey is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

941
    public function testParseExceptionOnDuplicate($input, /** @scrutinizer ignore-unused */ $duplicateKey, $lineNumber)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
942
    {
943
        Yaml::parse($input);
944
    }
945
946
    public function getParseExceptionOnDuplicateData()
947
    {
948
        $tests = [];
949
950
        $yaml = <<<EOD
951
parent: { child: first, child: duplicate }
952
EOD;
953
        $tests[] = [$yaml, 'child', 1];
954
955
        $yaml = <<<EOD
956
parent:
957
  child: first,
958
  child: duplicate
959
EOD;
960
        $tests[] = [$yaml, 'child', 3];
961
962
        $yaml = <<<EOD
963
parent: { child: foo }
964
parent: { child: bar }
965
EOD;
966
        $tests[] = [$yaml, 'parent', 2];
967
968
        $yaml = <<<EOD
969
parent: { child_mapping: { value: bar},  child_mapping: { value: bar} }
970
EOD;
971
        $tests[] = [$yaml, 'child_mapping', 1];
972
973
        $yaml = <<<EOD
974
parent:
975
  child_mapping:
976
    value: bar
977
  child_mapping:
978
    value: bar
979
EOD;
980
        $tests[] = [$yaml, 'child_mapping', 4];
981
982
        $yaml = <<<EOD
983
parent: { child_sequence: ['key1', 'key2', 'key3'],  child_sequence: ['key1', 'key2', 'key3'] }
984
EOD;
985
        $tests[] = [$yaml, 'child_sequence', 1];
986
987
        $yaml = <<<EOD
988
parent:
989
  child_sequence:
990
    - key1
991
    - key2
992
    - key3
993
  child_sequence:
994
    - key1
995
    - key2
996
    - key3
997
EOD;
998
        $tests[] = [$yaml, 'child_sequence', 6];
999
1000
        return $tests;
1001
    }
1002
1003
    public function testEmptyValue()
1004
    {
1005
        $input = <<<'EOF'
1006
hash:
1007
EOF;
1008
1009
        $this->assertEquals(['hash' => null], Yaml::parse($input));
1010
    }
1011
1012
    public function testCommentAtTheRootIndent()
1013
    {
1014
        $this->assertEquals([
1015
            'services' => [
1016
                'app.foo_service' => [
1017
                    'class' => 'Foo',
1018
                ],
1019
                'app/bar_service' => [
1020
                    'class' => 'Bar',
1021
                ],
1022
            ],
1023
        ], Yaml::parse(<<<'EOF'
1024
# comment 1
1025
services:
1026
# comment 2
1027
    # comment 3
1028
    app.foo_service:
1029
        class: Foo
1030
# comment 4
1031
    # comment 5
1032
    app/bar_service:
1033
        class: Bar
1034
EOF
1035
        ));
1036
    }
1037
1038
    public function testStringBlockWithComments()
1039
    {
1040
        $this->assertEquals(['content' => <<<'EOT'
1041
# comment 1
1042
header
1043
1044
    # comment 2
1045
    <body>
1046
        <h1>title</h1>
1047
    </body>
1048
1049
footer # comment3
1050
EOT
1051
        ], Yaml::parse(<<<'EOF'
1052
content: |
1053
    # comment 1
1054
    header
1055
1056
        # comment 2
1057
        <body>
1058
            <h1>title</h1>
1059
        </body>
1060
1061
    footer # comment3
1062
EOF
1063
        ));
1064
    }
1065
1066
    public function testFoldedStringBlockWithComments()
1067
    {
1068
        $this->assertEquals([['content' => <<<'EOT'
1069
# comment 1
1070
header
1071
1072
    # comment 2
1073
    <body>
1074
        <h1>title</h1>
1075
    </body>
1076
1077
footer # comment3
1078
EOT
1079
        ]], Yaml::parse(<<<'EOF'
1080
-
1081
    content: |
1082
        # comment 1
1083
        header
1084
1085
            # comment 2
1086
            <body>
1087
                <h1>title</h1>
1088
            </body>
1089
1090
        footer # comment3
1091
EOF
1092
        ));
1093
    }
1094
1095
    public function testNestedFoldedStringBlockWithComments()
1096
    {
1097
        $this->assertEquals([[
1098
            'title' => 'some title',
1099
            'content' => <<<'EOT'
1100
# comment 1
1101
header
1102
1103
    # comment 2
1104
    <body>
1105
        <h1>title</h1>
1106
    </body>
1107
1108
footer # comment3
1109
EOT
1110
        ]], Yaml::parse(<<<'EOF'
1111
-
1112
    title: some title
1113
    content: |
1114
        # comment 1
1115
        header
1116
1117
            # comment 2
1118
            <body>
1119
                <h1>title</h1>
1120
            </body>
1121
1122
        footer # comment3
1123
EOF
1124
        ));
1125
    }
1126
1127
    public function testReferenceResolvingInInlineStrings()
1128
    {
1129
        $this->assertEquals([
1130
            'var' => 'var-value',
1131
            'scalar' => 'var-value',
1132
            'list' => ['var-value'],
1133
            'list_in_list' => [['var-value']],
1134
            'map_in_list' => [['key' => 'var-value']],
1135
            'embedded_mapping' => [['key' => 'var-value']],
1136
            'map' => ['key' => 'var-value'],
1137
            'list_in_map' => ['key' => ['var-value']],
1138
            'map_in_map' => ['foo' => ['bar' => 'var-value']],
1139
        ], Yaml::parse(<<<'EOF'
1140
var:  &var var-value
1141
scalar: *var
1142
list: [ *var ]
1143
list_in_list: [[ *var ]]
1144
map_in_list: [ { key: *var } ]
1145
embedded_mapping: [ key: *var ]
1146
map: { key: *var }
1147
list_in_map: { key: [*var] }
1148
map_in_map: { foo: { bar: *var } }
1149
EOF
1150
        ));
1151
    }
1152
1153
    public function testYamlDirective()
1154
    {
1155
        $yaml = <<<'EOF'
1156
%YAML 1.2
1157
---
1158
foo: 1
1159
bar: 2
1160
EOF;
1161
        $this->assertEquals(['foo' => 1, 'bar' => 2], $this->parser->parse($yaml));
1162
    }
1163
1164
    /**
1165
     * @group legacy
1166
     * @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.
1167
     */
1168
    public function testFloatKeys()
1169
    {
1170
        $yaml = <<<'EOF'
1171
foo:
1172
    1.2: "bar"
1173
    1.3: "baz"
1174
EOF;
1175
1176
        $expected = [
1177
            'foo' => [
1178
                '1.2' => 'bar',
1179
                '1.3' => 'baz',
1180
            ],
1181
        ];
1182
1183
        $this->assertEquals($expected, $this->parser->parse($yaml));
1184
    }
1185
1186
    /**
1187
     * @group legacy
1188
     * @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.
1189
     */
1190
    public function testBooleanKeys()
1191
    {
1192
        $yaml = <<<'EOF'
1193
true: foo
1194
false: bar
1195
EOF;
1196
1197
        $expected = [
1198
            1 => 'foo',
1199
            0 => 'bar',
1200
        ];
1201
1202
        $this->assertEquals($expected, $this->parser->parse($yaml));
1203
    }
1204
1205
    public function testExplicitStringCasting()
1206
    {
1207
        $yaml = <<<'EOF'
1208
'1.2': "bar"
1209
!!str 1.3: "baz"
1210
1211
'true': foo
1212
!!str false: bar
1213
1214
!!str null: 'null'
1215
'~': 'null'
1216
EOF;
1217
1218
        $expected = [
1219
            '1.2' => 'bar',
1220
            '1.3' => 'baz',
1221
            'true' => 'foo',
1222
            'false' => 'bar',
1223
            'null' => 'null',
1224
            '~' => 'null',
1225
        ];
1226
1227
        $this->assertEquals($expected, $this->parser->parse($yaml));
1228
    }
1229
1230
    public function testColonInMappingValueException()
1231
    {
1232
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
1233
        $this->expectExceptionMessage('A colon cannot be used in an unquoted mapping value');
1234
        $yaml = <<<'EOF'
1235
foo: bar: baz
1236
EOF;
1237
1238
        $this->parser->parse($yaml);
1239
    }
1240
1241
    public function testColonInMappingValueExceptionNotTriggeredByColonInComment()
1242
    {
1243
        $yaml = <<<'EOT'
1244
foo:
1245
    bar: foobar # Note: a comment after a colon
1246
EOT;
1247
1248
        $this->assertSame(['foo' => ['bar' => 'foobar']], $this->parser->parse($yaml));
1249
    }
1250
1251
    /**
1252
     * @dataProvider getCommentLikeStringInScalarBlockData
1253
     */
1254
    public function testCommentLikeStringsAreNotStrippedInBlockScalars($yaml, $expectedParserResult)
1255
    {
1256
        $this->assertSame($expectedParserResult, $this->parser->parse($yaml));
1257
    }
1258
1259
    public function getCommentLikeStringInScalarBlockData()
1260
    {
1261
        $tests = [];
1262
1263
        $yaml = <<<'EOT'
1264
pages:
1265
    -
1266
        title: some title
1267
        content: |
1268
            # comment 1
1269
            header
1270
1271
                # comment 2
1272
                <body>
1273
                    <h1>title</h1>
1274
                </body>
1275
1276
            footer # comment3
1277
EOT;
1278
        $expected = [
1279
            'pages' => [
1280
                [
1281
                    'title' => 'some title',
1282
                    'content' => <<<'EOT'
1283
# comment 1
1284
header
1285
1286
    # comment 2
1287
    <body>
1288
        <h1>title</h1>
1289
    </body>
1290
1291
footer # comment3
1292
EOT
1293
                    ,
1294
                ],
1295
            ],
1296
        ];
1297
        $tests[] = [$yaml, $expected];
1298
1299
        $yaml = <<<'EOT'
1300
test: |
1301
    foo
1302
    # bar
1303
    baz
1304
collection:
1305
    - one: |
1306
        foo
1307
        # bar
1308
        baz
1309
    - two: |
1310
        foo
1311
        # bar
1312
        baz
1313
EOT;
1314
        $expected = [
1315
            'test' => <<<'EOT'
1316
foo
1317
# bar
1318
baz
1319
1320
EOT
1321
            ,
1322
            'collection' => [
1323
                [
1324
                    'one' => <<<'EOT'
1325
foo
1326
# bar
1327
baz
1328
1329
EOT
1330
                    ,
1331
                ],
1332
                [
1333
                    'two' => <<<'EOT'
1334
foo
1335
# bar
1336
baz
1337
EOT
1338
                    ,
1339
                ],
1340
            ],
1341
        ];
1342
        $tests[] = [$yaml, $expected];
1343
1344
        $yaml = <<<'EOT'
1345
foo:
1346
  bar:
1347
    scalar-block: >
1348
      line1
1349
      line2>
1350
  baz:
1351
# comment
1352
    foobar: ~
1353
EOT;
1354
        $expected = [
1355
            'foo' => [
1356
                'bar' => [
1357
                    'scalar-block' => "line1 line2>\n",
1358
                ],
1359
                'baz' => [
1360
                    'foobar' => null,
1361
                ],
1362
            ],
1363
        ];
1364
        $tests[] = [$yaml, $expected];
1365
1366
        $yaml = <<<'EOT'
1367
a:
1368
    b: hello
1369
#    c: |
1370
#        first row
1371
#        second row
1372
    d: hello
1373
EOT;
1374
        $expected = [
1375
            'a' => [
1376
                'b' => 'hello',
1377
                'd' => 'hello',
1378
            ],
1379
        ];
1380
        $tests[] = [$yaml, $expected];
1381
1382
        return $tests;
1383
    }
1384
1385
    public function testBlankLinesAreParsedAsNewLinesInFoldedBlocks()
1386
    {
1387
        $yaml = <<<'EOT'
1388
test: >
1389
    <h2>A heading</h2>
1390
1391
    <ul>
1392
    <li>a list</li>
1393
    <li>may be a good example</li>
1394
    </ul>
1395
EOT;
1396
1397
        $this->assertSame(
1398
            [
1399
                'test' => <<<'EOT'
1400
<h2>A heading</h2>
1401
<ul> <li>a list</li> <li>may be a good example</li> </ul>
1402
EOT
1403
                ,
1404
            ],
1405
            $this->parser->parse($yaml)
1406
        );
1407
    }
1408
1409
    public function testAdditionallyIndentedLinesAreParsedAsNewLinesInFoldedBlocks()
1410
    {
1411
        $yaml = <<<'EOT'
1412
test: >
1413
    <h2>A heading</h2>
1414
1415
    <ul>
1416
      <li>a list</li>
1417
      <li>may be a good example</li>
1418
    </ul>
1419
EOT;
1420
1421
        $this->assertSame(
1422
            [
1423
                'test' => <<<'EOT'
1424
<h2>A heading</h2>
1425
<ul>
1426
  <li>a list</li>
1427
  <li>may be a good example</li>
1428
</ul>
1429
EOT
1430
                ,
1431
            ],
1432
            $this->parser->parse($yaml)
1433
        );
1434
    }
1435
1436
    /**
1437
     * @dataProvider getBinaryData
1438
     */
1439
    public function testParseBinaryData($data)
1440
    {
1441
        $this->assertSame(['data' => 'Hello world'], $this->parser->parse($data));
1442
    }
1443
1444
    public function getBinaryData()
1445
    {
1446
        return [
1447
            'enclosed with double quotes' => ['data: !!binary "SGVsbG8gd29ybGQ="'],
1448
            'enclosed with single quotes' => ["data: !!binary 'SGVsbG8gd29ybGQ='"],
1449
            'containing spaces' => ['data: !!binary  "SGVs bG8gd 29ybGQ="'],
1450
            'in block scalar' => [
1451
                <<<'EOT'
1452
data: !!binary |
1453
    SGVsbG8gd29ybGQ=
1454
EOT
1455
    ],
1456
            'containing spaces in block scalar' => [
1457
                <<<'EOT'
1458
data: !!binary |
1459
    SGVs bG8gd 29ybGQ=
1460
EOT
1461
    ],
1462
        ];
1463
    }
1464
1465
    /**
1466
     * @dataProvider getInvalidBinaryData
1467
     */
1468
    public function testParseInvalidBinaryData($data, $expectedMessage)
1469
    {
1470
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
1471
        $this->expectExceptionMessageMatches($expectedMessage);
1472
1473
        $this->parser->parse($data);
1474
    }
1475
1476
    public function getInvalidBinaryData()
1477
    {
1478
        return [
1479
            'length not a multiple of four' => ['data: !!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'],
1480
            'invalid characters' => ['!!binary "SGVsbG8#d29ybGQ="', '/The base64 encoded data \(.*\) contains invalid characters/'],
1481
            'too many equals characters' => ['data: !!binary "SGVsbG8gd29yb==="', '/The base64 encoded data \(.*\) contains invalid characters/'],
1482
            'misplaced equals character' => ['data: !!binary "SGVsbG8gd29ybG=Q"', '/The base64 encoded data \(.*\) contains invalid characters/'],
1483
            'length not a multiple of four in block scalar' => [
1484
                <<<'EOT'
1485
data: !!binary |
1486
    SGVsbG8d29ybGQ=
1487
EOT
1488
                ,
1489
                '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/',
1490
            ],
1491
            'invalid characters in block scalar' => [
1492
                <<<'EOT'
1493
data: !!binary |
1494
    SGVsbG8#d29ybGQ=
1495
EOT
1496
                ,
1497
                '/The base64 encoded data \(.*\) contains invalid characters/',
1498
            ],
1499
            'too many equals characters in block scalar' => [
1500
                <<<'EOT'
1501
data: !!binary |
1502
    SGVsbG8gd29yb===
1503
EOT
1504
                ,
1505
                '/The base64 encoded data \(.*\) contains invalid characters/',
1506
            ],
1507
            'misplaced equals character in block scalar' => [
1508
                <<<'EOT'
1509
data: !!binary |
1510
    SGVsbG8gd29ybG=Q
1511
EOT
1512
                ,
1513
                '/The base64 encoded data \(.*\) contains invalid characters/',
1514
            ],
1515
        ];
1516
    }
1517
1518
    public function testParseDateAsMappingValue()
1519
    {
1520
        $yaml = <<<'EOT'
1521
date: 2002-12-14
1522
EOT;
1523
        $expectedDate = new \DateTime();
1524
        $expectedDate->setTimeZone(new \DateTimeZone('UTC'));
1525
        $expectedDate->setDate(2002, 12, 14);
1526
        $expectedDate->setTime(0, 0, 0);
1527
1528
        $this->assertEquals(['date' => $expectedDate], $this->parser->parse($yaml, Yaml::PARSE_DATETIME));
1529
    }
1530
1531
    /**
1532
     * @param $lineNumber
1533
     * @param $yaml
1534
     * @dataProvider parserThrowsExceptionWithCorrectLineNumberProvider
1535
     */
1536
    public function testParserThrowsExceptionWithCorrectLineNumber($lineNumber, $yaml)
1537
    {
1538
        $this->expectException('\Symfony\Component\Yaml\Exception\ParseException');
1539
        $this->expectExceptionMessage(sprintf('Unexpected characters near "," at line %d (near "bar: "123",").', $lineNumber));
1540
1541
        $this->parser->parse($yaml);
1542
    }
1543
1544
    public function parserThrowsExceptionWithCorrectLineNumberProvider()
1545
    {
1546
        return [
1547
            [
1548
                4,
1549
                <<<'YAML'
1550
foo:
1551
    -
1552
        # bar
1553
        bar: "123",
1554
YAML
1555
            ],
1556
            [
1557
                5,
1558
                <<<'YAML'
1559
foo:
1560
    -
1561
        # bar
1562
        # bar
1563
        bar: "123",
1564
YAML
1565
            ],
1566
            [
1567
                8,
1568
                <<<'YAML'
1569
foo:
1570
    -
1571
        # foobar
1572
        baz: 123
1573
bar:
1574
    -
1575
        # bar
1576
        bar: "123",
1577
YAML
1578
            ],
1579
            [
1580
                10,
1581
                <<<'YAML'
1582
foo:
1583
    -
1584
        # foobar
1585
        # foobar
1586
        baz: 123
1587
bar:
1588
    -
1589
        # bar
1590
        # bar
1591
        bar: "123",
1592
YAML
1593
            ],
1594
        ];
1595
    }
1596
1597
    public function testParseMultiLineQuotedString()
1598
    {
1599
        $yaml = <<<EOT
1600
foo: "bar
1601
  baz
1602
   foobar
1603
foo"
1604
bar: baz
1605
EOT;
1606
1607
        $this->assertSame(['foo' => 'bar baz foobar foo', 'bar' => 'baz'], $this->parser->parse($yaml));
1608
    }
1609
1610
    public function testMultiLineQuotedStringWithTrailingBackslash()
1611
    {
1612
        $yaml = <<<YAML
1613
foobar:
1614
    "foo\
1615
    bar"
1616
YAML;
1617
1618
        $this->assertSame(['foobar' => 'foobar'], $this->parser->parse($yaml));
1619
    }
1620
1621
    public function testCommentCharactersInMultiLineQuotedStrings()
1622
    {
1623
        $yaml = <<<YAML
1624
foo:
1625
    foobar: 'foo
1626
      #bar'
1627
    bar: baz
1628
YAML;
1629
        $expected = [
1630
            'foo' => [
1631
                'foobar' => 'foo #bar',
1632
                'bar' => 'baz',
1633
            ],
1634
        ];
1635
1636
        $this->assertSame($expected, $this->parser->parse($yaml));
1637
    }
1638
1639
    public function testBlankLinesInQuotedMultiLineString()
1640
    {
1641
        $yaml = <<<YAML
1642
foobar: 'foo
1643
1644
    bar'
1645
YAML;
1646
        $expected = [
1647
            'foobar' => "foo\nbar",
1648
        ];
1649
1650
        $this->assertSame($expected, $this->parser->parse($yaml));
1651
    }
1652
1653
    public function testEscapedQuoteInQuotedMultiLineString()
1654
    {
1655
        $yaml = <<<YAML
1656
foobar: "foo
1657
    \\"bar\\"
1658
    baz"
1659
YAML;
1660
        $expected = [
1661
            'foobar' => 'foo "bar" baz',
1662
        ];
1663
1664
        $this->assertSame($expected, $this->parser->parse($yaml));
1665
    }
1666
1667
    public function testBackslashInQuotedMultiLineString()
1668
    {
1669
        $yaml = <<<YAML
1670
foobar: "foo
1671
    bar\\\\"
1672
YAML;
1673
        $expected = [
1674
            'foobar' => 'foo bar\\',
1675
        ];
1676
1677
        $this->assertSame($expected, $this->parser->parse($yaml));
1678
    }
1679
1680
    public function testParseMultiLineUnquotedString()
1681
    {
1682
        $yaml = <<<EOT
1683
foo: bar
1684
  baz
1685
   foobar
1686
  foo
1687
bar: baz
1688
EOT;
1689
1690
        $this->assertSame(['foo' => 'bar baz foobar foo', 'bar' => 'baz'], $this->parser->parse($yaml));
1691
    }
1692
1693
    public function testParseMultiLineString()
1694
    {
1695
        $this->assertEquals("foo bar\nbaz", $this->parser->parse("foo\nbar\n\nbaz"));
1696
    }
1697
1698
    /**
1699
     * @dataProvider multiLineDataProvider
1700
     */
1701
    public function testParseMultiLineMappingValue($yaml, $expected, $parseError)
0 ignored issues
show
Unused Code introduced by
The parameter $parseError is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1701
    public function testParseMultiLineMappingValue($yaml, $expected, /** @scrutinizer ignore-unused */ $parseError)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1702
    {
1703
        $this->assertEquals($expected, $this->parser->parse($yaml));
1704
    }
1705
1706
    public function multiLineDataProvider()
1707
    {
1708
        $tests = [];
1709
1710
        $yaml = <<<'EOF'
1711
foo:
1712
- bar:
1713
    one
1714
1715
    two
1716
    three
1717
EOF;
1718
        $expected = [
1719
            'foo' => [
1720
                [
1721
                    'bar' => "one\ntwo three",
1722
                ],
1723
            ],
1724
        ];
1725
1726
        $tests[] = [$yaml, $expected, false];
1727
1728
        $yaml = <<<'EOF'
1729
bar
1730
"foo"
1731
EOF;
1732
        $expected = 'bar "foo"';
1733
1734
        $tests[] = [$yaml, $expected, false];
1735
1736
        $yaml = <<<'EOF'
1737
bar
1738
"foo
1739
EOF;
1740
        $expected = 'bar "foo';
1741
1742
        $tests[] = [$yaml, $expected, false];
1743
1744
        $yaml = <<<'EOF'
1745
bar
1746
1747
'foo'
1748
EOF;
1749
        $expected = "bar\n'foo'";
1750
1751
        $tests[] = [$yaml, $expected, false];
1752
1753
        $yaml = <<<'EOF'
1754
bar
1755
1756
foo'
1757
EOF;
1758
        $expected = "bar\nfoo'";
1759
1760
        $tests[] = [$yaml, $expected, false];
1761
1762
        return $tests;
1763
    }
1764
1765
    public function testTaggedInlineMapping()
1766
    {
1767
        $this->assertEquals(new TaggedValue('foo', ['foo' => 'bar']), $this->parser->parse('!foo {foo: bar}', Yaml::PARSE_CUSTOM_TAGS));
1768
    }
1769
1770
    /**
1771
     * @dataProvider taggedValuesProvider
1772
     */
1773
    public function testCustomTagSupport($expected, $yaml)
1774
    {
1775
        $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_CUSTOM_TAGS));
1776
    }
1777
1778
    public function taggedValuesProvider()
1779
    {
1780
        return [
1781
            'sequences' => [
1782
                [new TaggedValue('foo', ['yaml']), new TaggedValue('quz', ['bar'])],
1783
                <<<YAML
1784
- !foo
1785
    - yaml
1786
- !quz [bar]
1787
YAML
1788
            ],
1789
            'mappings' => [
1790
                new TaggedValue('foo', ['foo' => new TaggedValue('quz', ['bar']), 'quz' => new TaggedValue('foo', ['quz' => 'bar'])]),
1791
                <<<YAML
1792
!foo
1793
foo: !quz [bar]
1794
quz: !foo
1795
   quz: bar
1796
YAML
1797
            ],
1798
            'inline' => [
1799
                [new TaggedValue('foo', ['foo', 'bar']), new TaggedValue('quz', ['foo' => 'bar', 'quz' => new TaggedValue('bar', ['one' => 'bar'])])],
1800
                <<<YAML
1801
- !foo [foo, bar]
1802
- !quz {foo: bar, quz: !bar {one: bar}}
1803
YAML
1804
            ],
1805
        ];
1806
    }
1807
1808
    public function testCustomTagsDisabled()
1809
    {
1810
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
1811
        $this->expectExceptionMessage('Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator [foo]").');
1812
        $this->parser->parse('!iterator [foo]');
1813
    }
1814
1815
    /**
1816
     * @group legacy
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.
1818
     */
1819
    public function testUnsupportedTagWithScalar()
1820
    {
1821
        $this->assertEquals('!iterator foo', $this->parser->parse('!iterator foo'));
1822
    }
1823
1824
    public function testExceptionWhenUsingUnsupportedBuiltInTags()
1825
    {
1826
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
1827
        $this->expectExceptionMessage('The built-in tag "!!foo" is not implemented at line 1 (near "!!foo").');
1828
        $this->parser->parse('!!foo');
1829
    }
1830
1831
    /**
1832
     * @group legacy
1833
     * @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.
1834
     */
1835
    public function testComplexMappingThrowsParseException()
1836
    {
1837
        $yaml = <<<YAML
1838
? "1"
1839
:
1840
  name: végétalien
1841
YAML;
1842
1843
        $this->parser->parse($yaml);
1844
    }
1845
1846
    /**
1847
     * @group legacy
1848
     * @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.
1849
     */
1850
    public function testComplexMappingNestedInMappingThrowsParseException()
1851
    {
1852
        $yaml = <<<YAML
1853
diet:
1854
  ? "1"
1855
  :
1856
    name: végétalien
1857
YAML;
1858
1859
        $this->parser->parse($yaml);
1860
    }
1861
1862
    /**
1863
     * @group legacy
1864
     * @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.
1865
     */
1866
    public function testComplexMappingNestedInSequenceThrowsParseException()
1867
    {
1868
        $yaml = <<<YAML
1869
- ? "1"
1870
  :
1871
    name: végétalien
1872
YAML;
1873
1874
        $this->parser->parse($yaml);
1875
    }
1876
1877
    public function testParsingIniThrowsException()
1878
    {
1879
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
1880
        $this->expectExceptionMessage('Unable to parse at line 1 (near "[parameters]").');
1881
        $ini = <<<INI
1882
[parameters]
1883
  foo = bar
1884
  bar = %foo%
1885
INI;
1886
1887
        $this->parser->parse($ini);
1888
    }
1889
1890
    private function loadTestsFromFixtureFiles($testsFile)
1891
    {
1892
        $parser = new Parser();
1893
1894
        $tests = [];
1895
        $files = $parser->parseFile(__DIR__.'/Fixtures/'.$testsFile);
1896
        foreach ($files as $file) {
1897
            $yamls = file_get_contents(__DIR__.'/Fixtures/'.$file.'.yml');
1898
1899
            // split YAMLs documents
1900
            foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {
1901
                if (!$yaml) {
1902
                    continue;
1903
                }
1904
1905
                $test = $parser->parse($yaml);
1906
                if (isset($test['todo']) && $test['todo']) {
1907
                    // TODO
1908
                } else {
1909
                    eval('$expected = '.trim($test['php']).';');
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
1910
1911
                    $tests[] = [var_export($expected, true), $test['yaml'], $test['test'], isset($test['deprecated']) ? $test['deprecated'] : false];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $expected seems to be never defined.
Loading history...
1912
                }
1913
            }
1914
        }
1915
1916
        return $tests;
1917
    }
1918
1919
    public function testCanParseVeryLongValue()
1920
    {
1921
        $longStringWithSpaces = str_repeat('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ', 20000);
1922
        $trickyVal = ['x' => $longStringWithSpaces];
1923
1924
        $yamlString = Yaml::dump($trickyVal);
1925
        $arrayFromYaml = $this->parser->parse($yamlString);
1926
1927
        $this->assertEquals($trickyVal, $arrayFromYaml);
1928
    }
1929
1930
    public function testParserCleansUpReferencesBetweenRuns()
1931
    {
1932
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
1933
        $this->expectExceptionMessage('Reference "foo" does not exist at line 2');
1934
        $yaml = <<<YAML
1935
foo: &foo
1936
    baz: foobar
1937
bar:
1938
    <<: *foo
1939
YAML;
1940
        $this->parser->parse($yaml);
1941
1942
        $yaml = <<<YAML
1943
bar:
1944
    <<: *foo
1945
YAML;
1946
        $this->parser->parse($yaml);
1947
    }
1948
1949
    public function testPhpConstantTagMappingKey()
1950
    {
1951
        $yaml = <<<YAML
1952
transitions:
1953
    !php/const 'Symfony\Component\Yaml\Tests\B::FOO':
1954
        from:
1955
            - !php/const 'Symfony\Component\Yaml\Tests\B::BAR'
1956
        to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ'
1957
YAML;
1958
        $expected = [
1959
            'transitions' => [
1960
                'foo' => [
1961
                    'from' => [
1962
                        'bar',
1963
                    ],
1964
                    'to' => 'baz',
1965
                ],
1966
            ],
1967
        ];
1968
1969
        $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
1970
    }
1971
1972
    /**
1973
     * @group legacy
1974
     * @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.
1975
     * @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.
1976
     * @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.
1977
     */
1978
    public function testDeprecatedPhpConstantTagMappingKey()
1979
    {
1980
        $yaml = <<<YAML
1981
transitions:
1982
    !php/const:Symfony\Component\Yaml\Tests\B::FOO:
1983
        from:
1984
            - !php/const:Symfony\Component\Yaml\Tests\B::BAR
1985
        to: !php/const:Symfony\Component\Yaml\Tests\B::BAZ
1986
YAML;
1987
        $expected = [
1988
            'transitions' => [
1989
                'foo' => [
1990
                    'from' => [
1991
                        'bar',
1992
                    ],
1993
                    'to' => 'baz',
1994
                ],
1995
            ],
1996
        ];
1997
1998
        $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
1999
    }
2000
2001
    /**
2002
     * @group legacy
2003
     * @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.
2004
     */
2005
    public function testPhpConstantTagMappingKeyWithKeysCastToStrings()
2006
    {
2007
        $yaml = <<<YAML
2008
transitions:
2009
    !php/const 'Symfony\Component\Yaml\Tests\B::FOO':
2010
        from:
2011
            - !php/const 'Symfony\Component\Yaml\Tests\B::BAR'
2012
        to: !php/const 'Symfony\Component\Yaml\Tests\B::BAZ'
2013
YAML;
2014
        $expected = [
2015
            'transitions' => [
2016
                'foo' => [
2017
                    'from' => [
2018
                        'bar',
2019
                    ],
2020
                    'to' => 'baz',
2021
                ],
2022
            ],
2023
        ];
2024
2025
        $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT | Yaml::PARSE_KEYS_AS_STRINGS));
0 ignored issues
show
Deprecated Code introduced by
The constant Symfony\Component\Yaml\Yaml::PARSE_KEYS_AS_STRINGS has been deprecated: since version 3.4, to be removed in 4.0. Quote your evaluable keys instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

2025
        $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT | /** @scrutinizer ignore-deprecated */ Yaml::PARSE_KEYS_AS_STRINGS));

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
2026
    }
2027
2028
    public function testPhpConstantTagMappingAsScalarKey()
2029
    {
2030
        $yaml = <<<YAML
2031
map1:
2032
  - foo: 'value_0'
2033
    !php/const 'Symfony\Component\Yaml\Tests\B::BAR': 'value_1'
2034
map2:
2035
  - !php/const 'Symfony\Component\Yaml\Tests\B::FOO': 'value_0'
2036
    bar: 'value_1'
2037
YAML;
2038
        $this->assertSame([
2039
            'map1' => [['foo' => 'value_0', 'bar' => 'value_1']],
2040
            'map2' => [['foo' => 'value_0', 'bar' => 'value_1']],
2041
        ], $this->parser->parse($yaml, Yaml::PARSE_CONSTANT));
2042
    }
2043
2044
    public function testTagMappingAsScalarKey()
2045
    {
2046
        $yaml = <<<YAML
2047
map1:
2048
  - !!str 0: 'value_0'
2049
    !!str 1: 'value_1'
2050
YAML;
2051
        $this->assertSame([
2052
            'map1' => [['0' => 'value_0', '1' => 'value_1']],
2053
        ], $this->parser->parse($yaml));
2054
    }
2055
2056
    public function testMergeKeysWhenMappingsAreParsedAsObjects()
2057
    {
2058
        $yaml = <<<YAML
2059
foo: &FOO
2060
    bar: 1
2061
bar: &BAR
2062
    baz: 2
2063
    <<: *FOO
2064
baz:
2065
    baz_foo: 3
2066
    <<:
2067
        baz_bar: 4
2068
foobar:
2069
    bar: ~
2070
    <<: [*FOO, *BAR]
2071
YAML;
2072
        $expected = (object) [
2073
            'foo' => (object) [
2074
                'bar' => 1,
2075
            ],
2076
            'bar' => (object) [
2077
                'baz' => 2,
2078
                'bar' => 1,
2079
            ],
2080
            'baz' => (object) [
2081
                'baz_foo' => 3,
2082
                'baz_bar' => 4,
2083
            ],
2084
            'foobar' => (object) [
2085
                'bar' => null,
2086
                'baz' => 2,
2087
            ],
2088
        ];
2089
2090
        $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));
2091
    }
2092
2093
    public function testFilenamesAreParsedAsStringsWithoutFlag()
2094
    {
2095
        $file = __DIR__.'/Fixtures/index.yml';
2096
2097
        $this->assertSame($file, $this->parser->parse($file));
2098
    }
2099
2100
    public function testParseFile()
2101
    {
2102
        $this->assertIsArray($this->parser->parseFile(__DIR__.'/Fixtures/index.yml'));
2103
    }
2104
2105
    public function testParsingNonExistentFilesThrowsException()
2106
    {
2107
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
2108
        $this->expectExceptionMessageMatches('#^File ".+/Fixtures/nonexistent.yml" does not exist\.$#');
2109
        $this->parser->parseFile(__DIR__.'/Fixtures/nonexistent.yml');
2110
    }
2111
2112
    public function testParsingNotReadableFilesThrowsException()
2113
    {
2114
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
2115
        $this->expectExceptionMessageMatches('#^File ".+/Fixtures/not_readable.yml" cannot be read\.$#');
2116
        if ('\\' === \DIRECTORY_SEPARATOR) {
2117
            $this->markTestSkipped('chmod is not supported on Windows');
2118
        }
2119
2120
        if (!getenv('USER') || 'root' === getenv('USER')) {
2121
            $this->markTestSkipped('This test will fail if run under superuser');
2122
        }
2123
2124
        $file = __DIR__.'/Fixtures/not_readable.yml';
2125
        chmod($file, 0200);
2126
2127
        $this->parser->parseFile($file);
2128
    }
2129
2130
    public function testParseReferencesOnMergeKeys()
2131
    {
2132
        $yaml = <<<YAML
2133
mergekeyrefdef:
2134
    a: foo
2135
    <<: &quux
2136
        b: bar
2137
        c: baz
2138
mergekeyderef:
2139
    d: quux
2140
    <<: *quux
2141
YAML;
2142
        $expected = [
2143
            'mergekeyrefdef' => [
2144
                'a' => 'foo',
2145
                'b' => 'bar',
2146
                'c' => 'baz',
2147
            ],
2148
            'mergekeyderef' => [
2149
                'd' => 'quux',
2150
                'b' => 'bar',
2151
                'c' => 'baz',
2152
            ],
2153
        ];
2154
2155
        $this->assertSame($expected, $this->parser->parse($yaml));
2156
    }
2157
2158
    public function testParseReferencesOnMergeKeysWithMappingsParsedAsObjects()
2159
    {
2160
        $yaml = <<<YAML
2161
mergekeyrefdef:
2162
    a: foo
2163
    <<: &quux
2164
        b: bar
2165
        c: baz
2166
mergekeyderef:
2167
    d: quux
2168
    <<: *quux
2169
YAML;
2170
        $expected = (object) [
2171
            'mergekeyrefdef' => (object) [
2172
                'a' => 'foo',
2173
                'b' => 'bar',
2174
                'c' => 'baz',
2175
            ],
2176
            'mergekeyderef' => (object) [
2177
                'd' => 'quux',
2178
                'b' => 'bar',
2179
                'c' => 'baz',
2180
            ],
2181
        ];
2182
2183
        $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP));
2184
    }
2185
2186
    public function testEvalRefException()
2187
    {
2188
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
2189
        $this->expectExceptionMessage('Reference "foo" does not exist');
2190
        $yaml = <<<EOE
2191
foo: { &foo { a: Steve, <<: *foo} }
2192
EOE;
2193
        $this->parser->parse($yaml);
2194
    }
2195
2196
    /**
2197
     * @dataProvider circularReferenceProvider
2198
     */
2199
    public function testDetectCircularReferences($yaml)
2200
    {
2201
        $this->expectException('Symfony\Component\Yaml\Exception\ParseException');
2202
        $this->expectExceptionMessage('Circular reference [foo, bar, foo] detected');
2203
        $this->parser->parse($yaml, Yaml::PARSE_CUSTOM_TAGS);
2204
    }
2205
2206
    public function circularReferenceProvider()
2207
    {
2208
        $tests = [];
2209
2210
        $yaml = <<<YAML
2211
foo:
2212
    - &foo
2213
      - &bar
2214
        bar: foobar
2215
        baz: *foo
2216
YAML;
2217
        $tests['sequence'] = [$yaml];
2218
2219
        $yaml = <<<YAML
2220
foo: &foo
2221
    bar: &bar
2222
        foobar: baz
2223
        baz: *foo
2224
YAML;
2225
        $tests['mapping'] = [$yaml];
2226
2227
        $yaml = <<<YAML
2228
foo: &foo
2229
    bar: &bar
2230
        foobar: baz
2231
        <<: *foo
2232
YAML;
2233
        $tests['mapping with merge key'] = [$yaml];
2234
2235
        return $tests;
2236
    }
2237
2238
    /**
2239
     * @dataProvider indentedMappingData
2240
     */
2241
    public function testParseIndentedMappings($yaml, $expected)
2242
    {
2243
        $this->assertSame($expected, $this->parser->parse($yaml));
2244
    }
2245
2246
    public function indentedMappingData()
2247
    {
2248
        $tests = [];
2249
2250
        $yaml = <<<YAML
2251
foo:
2252
  - bar: "foobar"
2253
    # A comment
2254
    baz: "foobaz"
2255
YAML;
2256
        $expected = [
2257
            'foo' => [
2258
                [
2259
                    'bar' => 'foobar',
2260
                    'baz' => 'foobaz',
2261
                ],
2262
            ],
2263
        ];
2264
        $tests['comment line is first line in indented block'] = [$yaml, $expected];
2265
2266
        $yaml = <<<YAML
2267
foo:
2268
    - bar:
2269
        # comment
2270
        baz: [1, 2, 3]
2271
YAML;
2272
        $expected = [
2273
            'foo' => [
2274
                [
2275
                    'bar' => [
2276
                        'baz' => [1, 2, 3],
2277
                    ],
2278
                ],
2279
            ],
2280
        ];
2281
        $tests['mapping value on new line starting with a comment line'] = [$yaml, $expected];
2282
2283
        $yaml = <<<YAML
2284
foo:
2285
  -
2286
    bar: foobar
2287
YAML;
2288
        $expected = [
2289
            'foo' => [
2290
                [
2291
                    'bar' => 'foobar',
2292
                ],
2293
            ],
2294
        ];
2295
        $tests['mapping in sequence starting on a new line'] = [$yaml, $expected];
2296
2297
        $yaml = <<<YAML
2298
foo:
2299
2300
    bar: baz
2301
YAML;
2302
        $expected = [
2303
            'foo' => [
2304
                'bar' => 'baz',
2305
            ],
2306
        ];
2307
        $tests['blank line at the beginning of an indented mapping value'] = [$yaml, $expected];
2308
2309
        return $tests;
2310
    }
2311
2312
    public function testMultiLineComment()
2313
    {
2314
        $yaml = <<<YAML
2315
parameters:
2316
    abc
2317
2318
# Comment
2319
YAML;
2320
2321
        $this->assertSame(['parameters' => 'abc'], $this->parser->parse($yaml));
2322
    }
2323
2324
    public function testParseValueWithModifiers()
2325
    {
2326
        $yaml = <<<YAML
2327
parameters:
2328
    abc: |+5 # plus five spaces indent
2329
         one
2330
         two
2331
         three
2332
         four
2333
         five
2334
YAML;
2335
        $this->assertSame(
2336
            [
2337
                'parameters' => [
2338
                    'abc' => implode("\n", ['one', 'two', 'three', 'four', 'five']),
2339
                ],
2340
            ],
2341
            $this->parser->parse($yaml)
2342
        );
2343
    }
2344
2345
    public function testParseValueWithNegativeModifiers()
2346
    {
2347
        $yaml = <<<YAML
2348
parameters:
2349
    abc: |-3 # minus
2350
       one
2351
       two
2352
       three
2353
       four
2354
       five
2355
YAML;
2356
        $this->assertSame(
2357
            [
2358
                'parameters' => [
2359
                    'abc' => implode("\n", ['one', 'two', 'three', 'four', 'five']),
2360
                ],
2361
            ],
2362
            $this->parser->parse($yaml)
2363
        );
2364
    }
2365
2366
    /**
2367
     * This is a regression test for a bug where a YAML block with a nested multiline string using | was parsed without
2368
     * a trailing \n when a shorter YAML document was parsed before.
2369
     *
2370
     * When a shorter document was parsed before, the nested string did not have a \n at the end of the string, because
2371
     * the Parser thought it was the end of the file, even though it is not.
2372
     */
2373
    public function testParsingMultipleDocuments()
2374
    {
2375
        $shortDocument = 'foo: bar';
2376
        $longDocument = <<<YAML
2377
a:
2378
    b: |
2379
        row
2380
        row2
2381
c: d
2382
YAML;
2383
2384
        // The first parsing set and fixed the totalNumberOfLines in the Parser before, so parsing the short document here
2385
        // to reproduce the issue. If the issue would not have been fixed, the next assertion will fail
2386
        $this->parser->parse($shortDocument);
2387
2388
        // After the total number of lines has been reset the result will be the same as if a new parser was used
2389
        // (before, there was no \n after row2)
2390
        $this->assertSame(['a' => ['b' => "row\nrow2\n"], 'c' => 'd'], $this->parser->parse($longDocument));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->parser->parse($longDocument) targeting Symfony\Component\Yaml\Parser::parse() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
2391
    }
2392
}
2393
2394
class B
2395
{
2396
    public $b = 'foo';
2397
2398
    const FOO = 'foo';
2399
    const BAR = 'bar';
2400
    const BAZ = 'baz';
2401
}
2402