Completed
Pull Request — master (#462)
by Richard
15:24
created

ParserTest   F

Complexity

Total Complexity 53

Size/Duplication

Total Lines 1217
Duplicated Lines 4.68 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 57
loc 1217
rs 1.6949
c 0
b 0
f 0
wmc 53
lcom 1
cbo 3

32 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 4 1
A tearDown() 0 4 1
A testSpecifications() 0 4 1
B getDataFormSpecifications() 0 29 6
A testTabsInYaml() 0 21 3
A testEndOfTheDocumentMarker() 0 10 1
B getBlockChompingTests() 0 306 1
A testBlockChomping() 0 4 1
A testBlockLiteralWithLeadingNewlines() 0 15 1
A testObjectSupportEnabled() 0 14 1
A testObjectSupportDisabledButNoExceptions() 0 4 1
A testObjectsSupportDisabledWithExceptions() 0 4 1
A testNonUtf8Exception() 0 18 3
A testUnindentedCollectionException() 0 13 1
A testShortcutKeyUnindentedCollectionException() 0 12 1
A testMultipleDocumentsNotSupportedException() 0 16 1
A testSequenceInAMapping() 0 9 1
B testSequenceInMappingStartedBySingleDashLine() 0 27 1
A testMappingInASequence() 0 9 1
A testMappingDuplicateKeyBlock() 17 17 1
A testMappingDuplicateKeyFlow() 13 13 1
A testEmptyValue() 0 8 1
B testStringBlockWithComments() 0 27 1
B testFoldedStringBlockWithComments() 0 28 1
B testNestedFoldedStringBlockWithComments() 0 31 1
B testReferenceResolvingInInlineStrings() 0 25 1
A testYamlDirective() 10 10 1
A testCommentLikeStringsAreNotStrippedInBlockScalars() 0 4 1
B getCommentLikeStringInScalarBlockData() 0 125 1
A testBlankLinesAreParsedAsNewLinesInFoldedBlocks() 0 23 1
B testAdditionallyIndentedLinesAreParsedAsNewLinesInFoldedBlocks() 0 26 1
A testCanParseVeryLongValue() 0 10 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ParserTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ParserTest, and based on these observations, apply Extract Interface, too.

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\Yaml;
16
use Symfony\Component\Yaml\Parser;
17
18
class ParserTest extends TestCase
19
{
20
    /** @var Parser */
21
    protected $parser;
22
23
    protected function setUp()
24
    {
25
        $this->parser = new Parser();
26
    }
27
28
    protected function tearDown()
29
    {
30
        $this->parser = null;
31
    }
32
33
    /**
34
     * @dataProvider getDataFormSpecifications
35
     */
36
    public function testSpecifications($file, $expected, $yaml, $comment)
37
    {
38
        $this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment);
39
    }
40
41
    public function getDataFormSpecifications()
42
    {
43
        $parser = new Parser();
44
        $path = __DIR__.'/Fixtures';
45
46
        $tests = array();
47
        $files = $parser->parse(file_get_contents($path.'/index.yml'));
48
        foreach ($files as $file) {
0 ignored issues
show
Bug introduced by
The expression $files of type string|array|object<stdClass> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
49
            $yamls = file_get_contents($path.'/'.$file.'.yml');
50
51
            // split YAMLs documents
52
            foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {
53
                if (!$yaml) {
54
                    continue;
55
                }
56
57
                $test = $parser->parse($yaml);
58
                if (isset($test['todo']) && $test['todo']) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
59
                    // TODO
60
                } else {
61
                    eval('$expected = '.trim($test['php']).';');
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
62
63
                    $tests[] = array($file, var_export($expected, true), $test['yaml'], $test['test']);
0 ignored issues
show
Bug introduced by
The variable $expected does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
64
                }
65
            }
66
        }
67
68
        return $tests;
69
    }
70
71
    public function testTabsInYaml()
72
    {
73
        // test tabs in YAML
74
        $yamls = array(
75
            "foo:\n	bar",
76
            "foo:\n 	bar",
77
            "foo:\n	 bar",
78
            "foo:\n 	 bar",
79
        );
80
81
        foreach ($yamls as $yaml) {
82
            try {
83
                $content = $this->parser->parse($yaml);
0 ignored issues
show
Unused Code introduced by
$content is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
84
85
                $this->fail('YAML files must not contain tabs');
86
            } catch (\Exception $e) {
87
                $this->assertInstanceOf('\Exception', $e, 'YAML files must not contain tabs');
88
                $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');
89
            }
90
        }
91
    }
92
93
    public function testEndOfTheDocumentMarker()
94
    {
95
        $yaml = <<<'EOF'
96
--- %YAML:1.0
97
foo
98
...
99
EOF;
100
101
        $this->assertEquals('foo', $this->parser->parse($yaml));
102
    }
103
104
    public function getBlockChompingTests()
105
    {
106
        $tests = array();
107
108
        $yaml = <<<'EOF'
109
foo: |-
110
    one
111
    two
112
bar: |-
113
    one
114
    two
115
116
EOF;
117
        $expected = array(
118
            'foo' => "one\ntwo",
119
            'bar' => "one\ntwo",
120
        );
121
        $tests['Literal block chomping strip with single trailing newline'] = array($expected, $yaml);
122
123
        $yaml = <<<'EOF'
124
foo: |-
125
    one
126
    two
127
128
bar: |-
129
    one
130
    two
131
132
133
EOF;
134
        $expected = array(
135
            'foo' => "one\ntwo",
136
            'bar' => "one\ntwo",
137
        );
138
        $tests['Literal block chomping strip with multiple trailing newlines'] = array($expected, $yaml);
139
140
        $yaml = <<<'EOF'
141
{}
142
143
144
EOF;
145
        $expected = array();
146
        $tests['Literal block chomping strip with multiple trailing newlines after a 1-liner'] = array($expected, $yaml);
147
148
        $yaml = <<<'EOF'
149
foo: |-
150
    one
151
    two
152
bar: |-
153
    one
154
    two
155
EOF;
156
        $expected = array(
157
            'foo' => "one\ntwo",
158
            'bar' => "one\ntwo",
159
        );
160
        $tests['Literal block chomping strip without trailing newline'] = array($expected, $yaml);
161
162
        $yaml = <<<'EOF'
163
foo: |
164
    one
165
    two
166
bar: |
167
    one
168
    two
169
170
EOF;
171
        $expected = array(
172
            'foo' => "one\ntwo\n",
173
            'bar' => "one\ntwo\n",
174
        );
175
        $tests['Literal block chomping clip with single trailing newline'] = array($expected, $yaml);
176
177
        $yaml = <<<'EOF'
178
foo: |
179
    one
180
    two
181
182
bar: |
183
    one
184
    two
185
186
187
EOF;
188
        $expected = array(
189
            'foo' => "one\ntwo\n",
190
            'bar' => "one\ntwo\n",
191
        );
192
        $tests['Literal block chomping clip with multiple trailing newlines'] = array($expected, $yaml);
193
194
        $yaml = <<<'EOF'
195
foo:
196
- bar: |
197
    one
198
199
    two
200
EOF;
201
        $expected = array(
202
            'foo' => array(
203
                array(
204
                    'bar' => "one\n\ntwo",
205
                ),
206
            ),
207
        );
208
        $tests['Literal block chomping clip with embedded blank line inside unindented collection'] = array($expected, $yaml);
209
210
        $yaml = <<<'EOF'
211
foo: |
212
    one
213
    two
214
bar: |
215
    one
216
    two
217
EOF;
218
        $expected = array(
219
            'foo' => "one\ntwo\n",
220
            'bar' => "one\ntwo",
221
        );
222
        $tests['Literal block chomping clip without trailing newline'] = array($expected, $yaml);
223
224
        $yaml = <<<'EOF'
225
foo: |+
226
    one
227
    two
228
bar: |+
229
    one
230
    two
231
232
EOF;
233
        $expected = array(
234
            'foo' => "one\ntwo\n",
235
            'bar' => "one\ntwo\n",
236
        );
237
        $tests['Literal block chomping keep with single trailing newline'] = array($expected, $yaml);
238
239
        $yaml = <<<'EOF'
240
foo: |+
241
    one
242
    two
243
244
bar: |+
245
    one
246
    two
247
248
249
EOF;
250
        $expected = array(
251
            'foo' => "one\ntwo\n\n",
252
            'bar' => "one\ntwo\n\n",
253
        );
254
        $tests['Literal block chomping keep with multiple trailing newlines'] = array($expected, $yaml);
255
256
        $yaml = <<<'EOF'
257
foo: |+
258
    one
259
    two
260
bar: |+
261
    one
262
    two
263
EOF;
264
        $expected = array(
265
            'foo' => "one\ntwo\n",
266
            'bar' => "one\ntwo",
267
        );
268
        $tests['Literal block chomping keep without trailing newline'] = array($expected, $yaml);
269
270
        $yaml = <<<'EOF'
271
foo: >-
272
    one
273
    two
274
bar: >-
275
    one
276
    two
277
278
EOF;
279
        $expected = array(
280
            'foo' => 'one two',
281
            'bar' => 'one two',
282
        );
283
        $tests['Folded block chomping strip with single trailing newline'] = array($expected, $yaml);
284
285
        $yaml = <<<'EOF'
286
foo: >-
287
    one
288
    two
289
290
bar: >-
291
    one
292
    two
293
294
295
EOF;
296
        $expected = array(
297
            'foo' => 'one two',
298
            'bar' => 'one two',
299
        );
300
        $tests['Folded block chomping strip with multiple trailing newlines'] = array($expected, $yaml);
301
302
        $yaml = <<<'EOF'
303
foo: >-
304
    one
305
    two
306
bar: >-
307
    one
308
    two
309
EOF;
310
        $expected = array(
311
            'foo' => 'one two',
312
            'bar' => 'one two',
313
        );
314
        $tests['Folded block chomping strip without trailing newline'] = array($expected, $yaml);
315
316
        $yaml = <<<'EOF'
317
foo: >
318
    one
319
    two
320
bar: >
321
    one
322
    two
323
324
EOF;
325
        $expected = array(
326
            'foo' => "one two\n",
327
            'bar' => "one two\n",
328
        );
329
        $tests['Folded block chomping clip with single trailing newline'] = array($expected, $yaml);
330
331
        $yaml = <<<'EOF'
332
foo: >
333
    one
334
    two
335
336
bar: >
337
    one
338
    two
339
340
341
EOF;
342
        $expected = array(
343
            'foo' => "one two\n",
344
            'bar' => "one two\n",
345
        );
346
        $tests['Folded block chomping clip with multiple trailing newlines'] = array($expected, $yaml);
347
348
        $yaml = <<<'EOF'
349
foo: >
350
    one
351
    two
352
bar: >
353
    one
354
    two
355
EOF;
356
        $expected = array(
357
            'foo' => "one two\n",
358
            'bar' => 'one two',
359
        );
360
        $tests['Folded block chomping clip without trailing newline'] = array($expected, $yaml);
361
362
        $yaml = <<<'EOF'
363
foo: >+
364
    one
365
    two
366
bar: >+
367
    one
368
    two
369
370
EOF;
371
        $expected = array(
372
            'foo' => "one two\n",
373
            'bar' => "one two\n",
374
        );
375
        $tests['Folded block chomping keep with single trailing newline'] = array($expected, $yaml);
376
377
        $yaml = <<<'EOF'
378
foo: >+
379
    one
380
    two
381
382
bar: >+
383
    one
384
    two
385
386
387
EOF;
388
        $expected = array(
389
            'foo' => "one two\n\n",
390
            'bar' => "one two\n\n",
391
        );
392
        $tests['Folded block chomping keep with multiple trailing newlines'] = array($expected, $yaml);
393
394
        $yaml = <<<'EOF'
395
foo: >+
396
    one
397
    two
398
bar: >+
399
    one
400
    two
401
EOF;
402
        $expected = array(
403
            'foo' => "one two\n",
404
            'bar' => 'one two',
405
        );
406
        $tests['Folded block chomping keep without trailing newline'] = array($expected, $yaml);
407
408
        return $tests;
409
    }
410
411
    /**
412
     * @dataProvider getBlockChompingTests
413
     */
414
    public function testBlockChomping($expected, $yaml)
415
    {
416
        $this->assertSame($expected, $this->parser->parse($yaml));
417
    }
418
419
    /**
420
     * Regression test for issue #7989.
421
     *
422
     * @see https://github.com/symfony/symfony/issues/7989
423
     */
424
    public function testBlockLiteralWithLeadingNewlines()
425
    {
426
        $yaml = <<<'EOF'
427
foo: |-
428
429
430
    bar
431
432
EOF;
433
        $expected = array(
434
            'foo' => "\n\nbar",
435
        );
436
437
        $this->assertSame($expected, $this->parser->parse($yaml));
438
    }
439
440
    public function testObjectSupportEnabled()
441
    {
442
        $input = <<<'EOF'
443
foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
444
bar: 1
445
EOF;
446
        $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects');
447
448
        $input = <<<'EOF'
449
foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
450
bar: 1
451
EOF;
452
        $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects');
453
    }
454
455
    /**
456
     * @dataProvider invalidDumpedObjectProvider
457
     */
458
    public function testObjectSupportDisabledButNoExceptions($input)
459
    {
460
        $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects');
461
    }
462
463
    /**
464
     * @dataProvider getObjectForMapTests
465
     */
466
    public function testObjectForMap($yaml, $expected)
467
    {
468
        $this->assertEquals($expected, $this->parser->parse($yaml, false, false, true));
469
    }
470
471
    public function getObjectForMapTests()
472
    {
473
        $tests = array();
474
475
        $yaml = <<<'EOF'
476
foo:
477
    fiz: [cat]
478
EOF;
479
        $expected = new \stdClass();
480
        $expected->foo = new \stdClass();
481
        $expected->foo->fiz = array('cat');
482
        $tests['mapping'] = array($yaml, $expected);
483
484
        $yaml = '{ "foo": "bar", "fiz": "cat" }';
485
        $expected = new \stdClass();
486
        $expected->foo = 'bar';
487
        $expected->fiz = 'cat';
488
        $tests['inline-mapping'] = array($yaml, $expected);
489
490
        $yaml = "foo: bar\nbaz: foobar";
491
        $expected = new \stdClass();
492
        $expected->foo = 'bar';
493
        $expected->baz = 'foobar';
494
        $tests['object-for-map-is-applied-after-parsing'] = array($yaml, $expected);
495
496
        $yaml = <<<'EOT'
497
array:
498
  - key: one
499
  - key: two
500
EOT;
501
        $expected = new \stdClass();
502
        $expected->array = array();
503
        $expected->array[0] = new \stdClass();
504
        $expected->array[0]->key = 'one';
505
        $expected->array[1] = new \stdClass();
506
        $expected->array[1]->key = 'two';
507
        $tests['nest-map-and-sequence'] = array($yaml, $expected);
508
509
        $yaml = <<<'YAML'
510
map:
511
  1: one
512
  2: two
513
YAML;
514
        $expected = new \stdClass();
515
        $expected->map = new \stdClass();
516
        $expected->map->{1} = 'one';
517
        $expected->map->{2} = 'two';
518
        $tests['numeric-keys'] = array($yaml, $expected);
519
520
        $yaml = <<<'YAML'
521
map:
522
  0: one
523
  1: two
524
YAML;
525
        $expected = new \stdClass();
526
        $expected->map = new \stdClass();
527
        $expected->map->{0} = 'one';
528
        $expected->map->{1} = 'two';
529
        $tests['zero-indexed-numeric-keys'] = array($yaml, $expected);
530
531
        return $tests;
532
    }
533
534
    /**
535
     * @dataProvider invalidDumpedObjectProvider
536
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
537
     */
538
    public function testObjectsSupportDisabledWithExceptions($yaml)
539
    {
540
        $this->parser->parse($yaml, true, false);
541
    }
542
543
    public function invalidDumpedObjectProvider()
544
    {
545
        $yamlTag = <<<'EOF'
546
foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}
547
bar: 1
548
EOF;
549
        $localTag = <<<'EOF'
550
foo: !php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}
551
bar: 1
552
EOF;
553
554
        return array(
555
            'yaml-tag' => array($yamlTag),
556
            'local-tag' => array($localTag),
557
        );
558
    }
559
560
    /**
561
     * @requires extension iconv
562
     */
563
    public function testNonUtf8Exception()
564
    {
565
        $yamls = array(
566
            iconv('UTF-8', 'ISO-8859-1', "foo: 'äöüß'"),
567
            iconv('UTF-8', 'ISO-8859-15', "euro: '€'"),
568
            iconv('UTF-8', 'CP1252', "cp1252: '©ÉÇáñ'"),
569
        );
570
571
        foreach ($yamls as $yaml) {
572
            try {
573
                $this->parser->parse($yaml);
574
575
                $this->fail('charsets other than UTF-8 are rejected.');
576
            } catch (\Exception $e) {
577
                $this->assertInstanceOf('Symfony\Component\Yaml\Exception\ParseException', $e, 'charsets other than UTF-8 are rejected.');
578
            }
579
        }
580
    }
581
582
    /**
583
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
584
     */
585
    public function testUnindentedCollectionException()
586
    {
587
        $yaml = <<<'EOF'
588
589
collection:
590
-item1
591
-item2
592
-item3
593
594
EOF;
595
596
        $this->parser->parse($yaml);
597
    }
598
599
    /**
600
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
601
     */
602
    public function testShortcutKeyUnindentedCollectionException()
603
    {
604
        $yaml = <<<'EOF'
605
606
collection:
607
-  key: foo
608
  foo: bar
609
610
EOF;
611
612
        $this->parser->parse($yaml);
613
    }
614
615
    /**
616
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
617
     * @expectedExceptionMessageRegExp /^Multiple documents are not supported.+/
618
     */
619
    public function testMultipleDocumentsNotSupportedException()
620
    {
621
        Yaml::parse(<<<'EOL'
622
# Ranking of 1998 home runs
623
---
624
- Mark McGwire
625
- Sammy Sosa
626
- Ken Griffey
627
628
# Team ranking
629
---
630
- Chicago Cubs
631
- St Louis Cardinals
632
EOL
633
        );
634
    }
635
636
    /**
637
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
638
     */
639
    public function testSequenceInAMapping()
640
    {
641
        Yaml::parse(<<<'EOF'
642
yaml:
643
  hash: me
644
  - array stuff
645
EOF
646
        );
647
    }
648
649
    public function testSequenceInMappingStartedBySingleDashLine()
650
    {
651
        $yaml = <<<'EOT'
652
a:
653
-
654
  b:
655
  -
656
    bar: baz
657
- foo
658
d: e
659
EOT;
660
        $expected = array(
661
            'a' => array(
662
                array(
663
                    'b' => array(
664
                        array(
665
                            'bar' => 'baz',
666
                        ),
667
                    ),
668
                ),
669
                'foo',
670
            ),
671
            'd' => 'e',
672
        );
673
674
        $this->assertSame($expected, $this->parser->parse($yaml));
675
    }
676
677
    public function testSequenceFollowedByCommentEmbeddedInMapping()
678
    {
679
        $yaml = <<<'EOT'
680
a:
681
    b:
682
        - c
683
# comment
684
    d: e
685
EOT;
686
        $expected = array(
687
            'a' => array(
688
                'b' => array('c'),
689
                'd' => 'e',
690
            ),
691
        );
692
693
        $this->assertSame($expected, $this->parser->parse($yaml));
694
    }
695
696
    /**
697
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
698
     */
699
    public function testMappingInASequence()
700
    {
701
        Yaml::parse(<<<'EOF'
702
yaml:
703
  - array stuff
704
  hash: me
705
EOF
706
        );
707
    }
708
709
    /**
710
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
711
     * @expectedExceptionMessage missing colon
712
     */
713
    public function testScalarInSequence()
714
    {
715
        Yaml::parse(<<<'EOF'
716
foo:
717
    - bar
718
"missing colon"
719
    foo: bar
720
EOF
721
        );
722
    }
723
724
    /**
725
     * > It is an error for two equal keys to appear in the same mapping node.
726
     * > In such a case the YAML processor may continue, ignoring the second
727
     * > `key: value` pair and issuing an appropriate warning. This strategy
728
     * > preserves a consistent information model for one-pass and random access
729
     * > applications.
730
     *
731
     * @see http://yaml.org/spec/1.2/spec.html#id2759572
732
     * @see http://yaml.org/spec/1.1/#id932806
733
     */
734 View Code Duplication
    public function testMappingDuplicateKeyBlock()
735
    {
736
        $input = <<<'EOD'
737
parent:
738
    child: first
739
    child: duplicate
740
parent:
741
    child: duplicate
742
    child: duplicate
743
EOD;
744
        $expected = array(
745
            'parent' => array(
746
                'child' => 'first',
747
            ),
748
        );
749
        $this->assertSame($expected, Yaml::parse($input));
750
    }
751
752 View Code Duplication
    public function testMappingDuplicateKeyFlow()
753
    {
754
        $input = <<<'EOD'
755
parent: { child: first, child: duplicate }
756
parent: { child: duplicate, child: duplicate }
757
EOD;
758
        $expected = array(
759
            'parent' => array(
760
                'child' => 'first',
761
            ),
762
        );
763
        $this->assertSame($expected, Yaml::parse($input));
764
    }
765
766
    public function testEmptyValue()
767
    {
768
        $input = <<<'EOF'
769
hash:
770
EOF;
771
772
        $this->assertEquals(array('hash' => null), Yaml::parse($input));
773
    }
774
775
    public function testCommentAtTheRootIndent()
776
    {
777
        $this->assertEquals(array(
778
            'services' => array(
779
                'app.foo_service' => array(
780
                    'class' => 'Foo',
781
                ),
782
                'app/bar_service' => array(
783
                    'class' => 'Bar',
784
                ),
785
            ),
786
        ), Yaml::parse(<<<'EOF'
787
# comment 1
788
services:
789
# comment 2
790
    # comment 3
791
    app.foo_service:
792
        class: Foo
793
# comment 4
794
    # comment 5
795
    app/bar_service:
796
        class: Bar
797
EOF
798
        ));
799
    }
800
801
    public function testStringBlockWithComments()
802
    {
803
        $this->assertEquals(array('content' => <<<'EOT'
804
# comment 1
805
header
806
807
    # comment 2
808
    <body>
809
        <h1>title</h1>
810
    </body>
811
812
footer # comment3
813
EOT
814
        ), Yaml::parse(<<<'EOF'
815
content: |
816
    # comment 1
817
    header
818
819
        # comment 2
820
        <body>
821
            <h1>title</h1>
822
        </body>
823
824
    footer # comment3
825
EOF
826
        ));
827
    }
828
829
    public function testFoldedStringBlockWithComments()
830
    {
831
        $this->assertEquals(array(array('content' => <<<'EOT'
832
# comment 1
833
header
834
835
    # comment 2
836
    <body>
837
        <h1>title</h1>
838
    </body>
839
840
footer # comment3
841
EOT
842
        )), Yaml::parse(<<<'EOF'
843
-
844
    content: |
845
        # comment 1
846
        header
847
848
            # comment 2
849
            <body>
850
                <h1>title</h1>
851
            </body>
852
853
        footer # comment3
854
EOF
855
        ));
856
    }
857
858
    public function testNestedFoldedStringBlockWithComments()
859
    {
860
        $this->assertEquals(array(array(
861
            'title' => 'some title',
862
            'content' => <<<'EOT'
863
# comment 1
864
header
865
866
    # comment 2
867
    <body>
868
        <h1>title</h1>
869
    </body>
870
871
footer # comment3
872
EOT
873
        )), Yaml::parse(<<<'EOF'
874
-
875
    title: some title
876
    content: |
877
        # comment 1
878
        header
879
880
            # comment 2
881
            <body>
882
                <h1>title</h1>
883
            </body>
884
885
        footer # comment3
886
EOF
887
        ));
888
    }
889
890
    public function testReferenceResolvingInInlineStrings()
891
    {
892
        $this->assertEquals(array(
893
            'var' => 'var-value',
894
            'scalar' => 'var-value',
895
            'list' => array('var-value'),
896
            'list_in_list' => array(array('var-value')),
897
            'map_in_list' => array(array('key' => 'var-value')),
898
            'embedded_mapping' => array(array('key' => 'var-value')),
899
            'map' => array('key' => 'var-value'),
900
            'list_in_map' => array('key' => array('var-value')),
901
            'map_in_map' => array('foo' => array('bar' => 'var-value')),
902
        ), Yaml::parse(<<<'EOF'
903
var:  &var var-value
904
scalar: *var
905
list: [ *var ]
906
list_in_list: [[ *var ]]
907
map_in_list: [ { key: *var } ]
908
embedded_mapping: [ key: *var ]
909
map: { key: *var }
910
list_in_map: { key: [*var] }
911
map_in_map: { foo: { bar: *var } }
912
EOF
913
        ));
914
    }
915
916 View Code Duplication
    public function testYamlDirective()
917
    {
918
        $yaml = <<<'EOF'
919
%YAML 1.2
920
---
921
foo: 1
922
bar: 2
923
EOF;
924
        $this->assertEquals(array('foo' => 1, 'bar' => 2), $this->parser->parse($yaml));
925
    }
926
927 View Code Duplication
    public function testFloatKeys()
928
    {
929
        $yaml = <<<'EOF'
930
foo:
931
    1.2: "bar"
932
    1.3: "baz"
933
EOF;
934
935
        $expected = array(
936
            'foo' => array(
937
                '1.2' => 'bar',
938
                '1.3' => 'baz',
939
            ),
940
        );
941
942
        $this->assertEquals($expected, $this->parser->parse($yaml));
943
    }
944
945
    /**
946
     * @group legacy
947
     * @expectedDeprecation Using a colon in the unquoted mapping value "bar: baz" in line 1 is deprecated since Symfony 2.8 and will throw a ParseException in 3.0.
948
     * throw ParseException in Symfony 3.0
949
     */
950
    public function testColonInMappingValueException()
951
    {
952
        $yaml = <<<'EOF'
953
foo: bar: baz
954
EOF;
955
956
        $this->parser->parse($yaml);
957
    }
958
959
    public function testColonInMappingValueExceptionNotTriggeredByColonInComment()
960
    {
961
        $yaml = <<<'EOT'
962
foo:
963
    bar: foobar # Note: a comment after a colon
964
EOT;
965
966
        $this->assertSame(array('foo' => array('bar' => 'foobar')), $this->parser->parse($yaml));
967
    }
968
969
    /**
970
     * @dataProvider getCommentLikeStringInScalarBlockData
971
     */
972
    public function testCommentLikeStringsAreNotStrippedInBlockScalars($yaml, $expectedParserResult)
973
    {
974
        $this->assertSame($expectedParserResult, $this->parser->parse($yaml));
975
    }
976
977
    public function getCommentLikeStringInScalarBlockData()
978
    {
979
        $tests = array();
980
981
        $yaml = <<<'EOT'
982
pages:
983
    -
984
        title: some title
985
        content: |
986
            # comment 1
987
            header
988
989
                # comment 2
990
                <body>
991
                    <h1>title</h1>
992
                </body>
993
994
            footer # comment3
995
EOT;
996
        $expected = array(
997
            'pages' => array(
998
                array(
999
                    'title' => 'some title',
1000
                    'content' => <<<'EOT'
1001
# comment 1
1002
header
1003
1004
    # comment 2
1005
    <body>
1006
        <h1>title</h1>
1007
    </body>
1008
1009
footer # comment3
1010
EOT
1011
                    ,
1012
                ),
1013
            ),
1014
        );
1015
        $tests[] = array($yaml, $expected);
1016
1017
        $yaml = <<<'EOT'
1018
test: |
1019
    foo
1020
    # bar
1021
    baz
1022
collection:
1023
    - one: |
1024
        foo
1025
        # bar
1026
        baz
1027
    - two: |
1028
        foo
1029
        # bar
1030
        baz
1031
EOT;
1032
        $expected = array(
1033
            'test' => <<<'EOT'
1034
foo
1035
# bar
1036
baz
1037
1038
EOT
1039
            ,
1040
            'collection' => array(
1041
                array(
1042
                    'one' => <<<'EOT'
1043
foo
1044
# bar
1045
baz
1046
1047
EOT
1048
                    ,
1049
                ),
1050
                array(
1051
                    'two' => <<<'EOT'
1052
foo
1053
# bar
1054
baz
1055
EOT
1056
                    ,
1057
                ),
1058
            ),
1059
        );
1060
        $tests[] = array($yaml, $expected);
1061
1062
        $yaml = <<<'EOT'
1063
foo:
1064
  bar:
1065
    scalar-block: >
1066
      line1
1067
      line2>
1068
  baz:
1069
# comment
1070
    foobar: ~
1071
EOT;
1072
        $expected = array(
1073
            'foo' => array(
1074
                'bar' => array(
1075
                    'scalar-block' => "line1 line2>\n",
1076
                ),
1077
                'baz' => array(
1078
                    'foobar' => null,
1079
                ),
1080
            ),
1081
        );
1082
        $tests[] = array($yaml, $expected);
1083
1084
        $yaml = <<<'EOT'
1085
a:
1086
    b: hello
1087
#    c: |
1088
#        first row
1089
#        second row
1090
    d: hello
1091
EOT;
1092
        $expected = array(
1093
            'a' => array(
1094
                'b' => 'hello',
1095
                'd' => 'hello',
1096
            ),
1097
        );
1098
        $tests[] = array($yaml, $expected);
1099
1100
        return $tests;
1101
    }
1102
1103
    public function testBlankLinesAreParsedAsNewLinesInFoldedBlocks()
1104
    {
1105
        $yaml = <<<'EOT'
1106
test: >
1107
    <h2>A heading</h2>
1108
1109
    <ul>
1110
    <li>a list</li>
1111
    <li>may be a good example</li>
1112
    </ul>
1113
EOT;
1114
1115
        $this->assertSame(
1116
            array(
1117
                'test' => <<<'EOT'
1118
<h2>A heading</h2>
1119
<ul> <li>a list</li> <li>may be a good example</li> </ul>
1120
EOT
1121
                ,
1122
            ),
1123
            $this->parser->parse($yaml)
1124
        );
1125
    }
1126
1127
    public function testAdditionallyIndentedLinesAreParsedAsNewLinesInFoldedBlocks()
1128
    {
1129
        $yaml = <<<'EOT'
1130
test: >
1131
    <h2>A heading</h2>
1132
1133
    <ul>
1134
      <li>a list</li>
1135
      <li>may be a good example</li>
1136
    </ul>
1137
EOT;
1138
1139
        $this->assertSame(
1140
            array(
1141
                'test' => <<<'EOT'
1142
<h2>A heading</h2>
1143
<ul>
1144
  <li>a list</li>
1145
  <li>may be a good example</li>
1146
</ul>
1147
EOT
1148
                ,
1149
            ),
1150
            $this->parser->parse($yaml)
1151
        );
1152
    }
1153
1154
    /**
1155
     * @param $lineNumber
1156
     * @param $yaml
1157
     * @dataProvider parserThrowsExceptionWithCorrectLineNumberProvider
1158
     */
1159
    public function testParserThrowsExceptionWithCorrectLineNumber($lineNumber, $yaml)
1160
    {
1161
        if (method_exists($this, 'expectException')) {
1162
            $this->expectException('\Symfony\Component\Yaml\Exception\ParseException');
1163
            $this->expectExceptionMessage(sprintf('Unexpected characters near "," at line %d (near "bar: "123",").', $lineNumber));
1164
        } else {
1165
            $this->setExpectedException('\Symfony\Component\Yaml\Exception\ParseException', sprintf('Unexpected characters near "," at line %d (near "bar: "123",").', $lineNumber));
1166
        }
1167
1168
        $this->parser->parse($yaml);
1169
    }
1170
1171
    public function parserThrowsExceptionWithCorrectLineNumberProvider()
1172
    {
1173
        return array(
1174
            array(
1175
                4,
1176
                <<<'YAML'
1177
foo:
1178
    -
1179
        # bar
1180
        bar: "123",
1181
YAML
1182
            ),
1183
            array(
1184
                5,
1185
                <<<'YAML'
1186
foo:
1187
    -
1188
        # bar
1189
        # bar
1190
        bar: "123",
1191
YAML
1192
            ),
1193
            array(
1194
                8,
1195
                <<<'YAML'
1196
foo:
1197
    -
1198
        # foobar
1199
        baz: 123
1200
bar:
1201
    -
1202
        # bar
1203
        bar: "123",
1204
YAML
1205
            ),
1206
            array(
1207
                10,
1208
                <<<'YAML'
1209
foo:
1210
    -
1211
        # foobar
1212
        # foobar
1213
        baz: 123
1214
bar:
1215
    -
1216
        # bar
1217
        # bar
1218
        bar: "123",
1219
YAML
1220
            ),
1221
        );
1222
    }
1223
1224
    public function testCanParseVeryLongValue()
1225
    {
1226
        $longStringWithSpaces = str_repeat('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ', 20000);
1227
        $trickyVal = array('x' => $longStringWithSpaces);
1228
1229
        $yamlString = Yaml::dump($trickyVal);
1230
        $arrayFromYaml = $this->parser->parse($yamlString);
1231
1232
        $this->assertEquals($trickyVal, $arrayFromYaml);
1233
    }
1234
}
1235
1236
class B
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
1237
{
1238
    public $b = 'foo';
1239
}
1240