1#!perl -w
2
3use strict;
4use warnings;
5use lib 't/lib';
6
7use Test::More;
8
9use TAP::Parser::YAMLish::Reader;
10
11my @SCHEDULE;
12
13BEGIN {
14    @SCHEDULE = (
15        {   name => 'Hello World',
16            in   => [
17                '--- Hello, World',
18                '...',
19            ],
20            out => "Hello, World",
21        },
22        {   name => 'Hello World 2',
23            in   => [
24                '--- \'Hello, \'\'World\'',
25                '...',
26            ],
27            out => "Hello, 'World",
28        },
29        {   name => 'Hello World 3',
30            in   => [
31                '--- "Hello, World"',
32                '...',
33            ],
34            out => "Hello, World",
35        },
36        {   name => 'Hello World 4',
37            in   => [
38                '--- "Hello, World"',
39                '...',
40            ],
41            out => "Hello, World",
42        },
43        {   name => 'Hello World 4',
44            in   => [
45                '--- >',
46                '   Hello,',
47                '      World',
48                '...',
49            ],
50            out => "Hello, World\n",
51        },
52        {   name => 'Hello World Block',
53            in   => [
54                '--- |',
55                '   Hello,',
56                '      World',
57                '...',
58            ],
59            out => "Hello,\n   World\n",
60        },
61        {   name => 'Hello World 5',
62            in   => [
63                '--- >',
64                '   Hello,',
65                '  World',
66                '...',
67            ],
68            error => qr{Missing\s+'[.][.][.]'},
69        },
70        {   name => 'Simple array',
71            in   => [
72                '---',
73                '- 1',
74                '- 2',
75                '- 3',
76                '...',
77            ],
78            out => [ '1', '2', '3' ],
79        },
80        {   name => 'Mixed array',
81            in   => [
82                '---',
83                '- 1',
84                '- \'two\'',
85                '- "three\n"',
86                '...',
87            ],
88            out => [ '1', 'two', "three\n" ],
89        },
90        {   name => 'Hash in array',
91            in   => [
92                '---',
93                '- 1',
94                '- two: 2',
95                '- 3',
96                '...',
97            ],
98            out => [ '1', { two => '2' }, '3' ],
99        },
100        {   name => 'Hash in array 2',
101            in   => [
102                '---',
103                '- 1',
104                '- two: 2',
105                '  three: 3',
106                '- 4',
107                '...',
108            ],
109            out => [ '1', { two => '2', three => '3' }, '4' ],
110        },
111        {   name => 'Nested array',
112            in   => [
113                '---',
114                '- one',
115                '-',
116                '  - two',
117                '  -',
118                '    - three',
119                '  - four',
120                '- five',
121                '...',
122            ],
123            out => [ 'one', [ 'two', ['three'], 'four' ], 'five' ],
124        },
125        {   name => 'Nested hash',
126            in   => [
127                '---',
128                'one:',
129                '  five: 5',
130                '  two:',
131                '    four: 4',
132                '    three: 3',
133                'six: 6',
134                '...',
135            ],
136            out => {
137                one => { two => { three => '3', four => '4' }, five => '5' },
138                six => '6'
139            },
140        },
141        {   name => 'Space after colon',
142            in   => [ '---', 'spog: ', ' - 1', ' - 2', '...' ],
143            out => { spog => [ 1, 2 ] },
144        },
145        {   name => 'Original YAML::Tiny test',
146            in   => [
147                '---',
148                'invoice: 34843',
149                'date   : 2001-01-23',
150                'bill-to:',
151                '    given  : Chris',
152                '    family : Dumars',
153                '    address:',
154                '        lines: |',
155                '            458 Walkman Dr.',
156                '            Suite #292',
157                '        city    : Royal Oak',
158                '        state   : MI',
159                '        postal  : 48046',
160                'product:',
161                '    - sku         : BL394D',
162                '      quantity    : 4',
163                '      description : Basketball',
164                '      price       : 450.00',
165                '    - sku         : BL4438H',
166                '      quantity    : 1',
167                '      description : Super Hoop',
168                '      price       : 2392.00',
169                'tax  : 251.42',
170                'total: 4443.52',
171                'comments: >',
172                '    Late afternoon is best.',
173                '    Backup contact is Nancy',
174                '    Billsmer @ 338-4338',
175                '...',
176            ],
177            out => {
178                'bill-to' => {
179                    'given'   => 'Chris',
180                    'address' => {
181                        'city'   => 'Royal Oak',
182                        'postal' => '48046',
183                        'lines'  => "458 Walkman Dr.\nSuite #292\n",
184                        'state'  => 'MI'
185                    },
186                    'family' => 'Dumars'
187                },
188                'invoice' => '34843',
189                'date'    => '2001-01-23',
190                'tax'     => '251.42',
191                'product' => [
192                    {   'sku'         => 'BL394D',
193                        'quantity'    => '4',
194                        'price'       => '450.00',
195                        'description' => 'Basketball'
196                    },
197                    {   'sku'         => 'BL4438H',
198                        'quantity'    => '1',
199                        'price'       => '2392.00',
200                        'description' => 'Super Hoop'
201                    }
202                ],
203                'comments' =>
204                  "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338\n",
205                'total' => '4443.52'
206            }
207        },
208
209        # Tests harvested from YAML::Tiny
210        {   in    => ['...'],
211            name  => 'Regression: empty',
212            error => qr{document\s+header\s+not\s+found}
213        },
214        {   in => [
215                '# comment',
216                '...'
217            ],
218            name  => 'Regression: only_comment',
219            error => qr{document\s+header\s+not\s+found}
220        },
221        {   out => undef,
222            in  => [
223                '---',
224                '...'
225            ],
226            name  => 'Regression: only_header',
227            error => qr{Premature\s+end}i,
228        },
229        {   out => undef,
230            in  => [
231                '---',
232                '---',
233                '...'
234            ],
235            name  => 'Regression: two_header',
236            error => qr{Unexpected\s+start}i,
237        },
238        {   out => undef,
239            in  => [
240                '--- ~',
241                '...'
242            ],
243            name => 'Regression: one_undef'
244        },
245        {   out => undef,
246            in  => [
247                '---  ~',
248                '...'
249            ],
250            name => 'Regression: one_undef2'
251        },
252        {   in => [
253                '--- ~',
254                '---',
255                '...'
256            ],
257            name  => 'Regression: two_undef',
258            error => qr{Missing\s+'[.][.][.]'},
259        },
260        {   out => 'foo',
261            in  => [
262                '--- foo',
263                '...'
264            ],
265            name => 'Regression: one_scalar',
266        },
267        {   out => 'foo',
268            in  => [
269                '---  foo',
270                '...'
271            ],
272            name => 'Regression: one_scalar2',
273        },
274        {   in => [
275                '--- foo',
276                '--- bar',
277                '...'
278            ],
279            name  => 'Regression: two_scalar',
280            error => qr{Missing\s+'[.][.][.]'},
281        },
282        {   out => ['foo'],
283            in  => [
284                '---',
285                '- foo',
286                '...'
287            ],
288            name => 'Regression: one_list1'
289        },
290        {   out => [
291                'foo',
292                'bar'
293            ],
294            in => [
295                '---',
296                '- foo',
297                '- bar',
298                '...'
299            ],
300            name => 'Regression: one_list2'
301        },
302        {   out => [
303                undef,
304                'bar'
305            ],
306            in => [
307                '---',
308                '- ~',
309                '- bar',
310                '...'
311            ],
312            name => 'Regression: one_listundef'
313        },
314        {   out => { 'foo' => 'bar' },
315            in  => [
316                '---',
317                'foo: bar',
318                '...'
319            ],
320            name => 'Regression: one_hash1'
321        },
322        {   out => {
323                'foo'  => 'bar',
324                'this' => undef
325            },
326            in => [
327                '---',
328                'foo: bar',
329                'this: ~',
330                '...'
331            ],
332            name => 'Regression: one_hash2'
333        },
334        {   out => {
335                'foo' => [
336                    'bar',
337                    undef,
338                    'baz'
339                ]
340            },
341            in => [
342                '---',
343                'foo:',
344                '  - bar',
345                '  - ~',
346                '  - baz',
347                '...'
348            ],
349            name => 'Regression: array_in_hash'
350        },
351        {   out => {
352                'bar' => { 'foo' => 'bar' },
353                'foo' => undef
354            },
355            in => [
356                '---',
357                'foo: ~',
358                'bar:',
359                '  foo: bar',
360                '...'
361            ],
362            name => 'Regression: hash_in_hash'
363        },
364        {   out => [
365                {   'foo'  => undef,
366                    'this' => 'that'
367                },
368                'foo', undef,
369                {   'foo'  => 'bar',
370                    'this' => 'that'
371                }
372            ],
373            in => [
374                '---',
375                '-',
376                '  foo: ~',
377                '  this: that',
378                '- foo',
379                '- ~',
380                '-',
381                '  foo: bar',
382                '  this: that',
383                '...'
384            ],
385            name => 'Regression: hash_in_array'
386        },
387        {   out => ['foo'],
388            in  => [
389                '---',
390                '- \'foo\'',
391                '...'
392            ],
393            name => 'Regression: single_quote1'
394        },
395        {   out => ['  '],
396            in  => [
397                '---',
398                '- \'  \'',
399                '...'
400            ],
401            name => 'Regression: single_spaces'
402        },
403        {   out => [''],
404            in  => [
405                '---',
406                '- \'\'',
407                '...'
408            ],
409            name => 'Regression: single_null'
410        },
411        {   out => '  ',
412            in  => [
413                '--- "  "',
414                '...'
415            ],
416            name => 'Regression: only_spaces'
417        },
418        {   out => [
419                undef,
420                {   'foo'  => 'bar',
421                    'this' => 'that'
422                },
423                'baz'
424            ],
425            in => [
426                '---',
427                '- ~',
428                '- foo: bar',
429                '  this: that',
430                '- baz',
431                '...'
432            ],
433            name => 'Regression: inline_nested_hash'
434        },
435        {   name => "Unprintables",
436            in   => [
437                "---",
438                "- \"\\z\\x01\\x02\\x03\\x04\\x05\\x06\\a\\x08\\t\\n\\v\\f\\r\\x0e\\x0f\"",
439                "- \"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\e\\x1c\\x1d\\x1e\\x1f\"",
440                "- \" !\\\"#\$%&'()*+,-./\"",
441                "- 0123456789:;<=>?",
442                "- '\@ABCDEFGHIJKLMNO'",
443                "- 'PQRSTUVWXYZ[\\]^_'",
444                "- '`abcdefghijklmno'",
445                "- 'pqrstuvwxyz{|}~\177'",
446                "- \200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
447                "- \220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
448                "- \240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
449                "- \260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
450                "- \300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
451                "- \320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
452                "- \340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
453                "- \360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
454                "..."
455            ],
456            out => [
457                "\0\1\2\3\4\5\6\a\b\t\n\13\f\r\16\17",
458                "\20\21\22\23\24\25\26\27\30\31\32\e\34\35\36\37",
459                " !\"#\$%&'()*+,-./",
460                "0123456789:;<=>?",
461                "\@ABCDEFGHIJKLMNO",
462                "PQRSTUVWXYZ[\\]^_",
463                "`abcdefghijklmno",
464                "pqrstuvwxyz{|}~\177",
465                "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217",
466                "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237",
467                "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257",
468                "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277",
469                "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317",
470                "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337",
471                "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357",
472                "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
473            ],
474        },
475        {   name => 'Quoted hash keys',
476            in   => [
477                '---',
478                '  "quoted": Magic!',
479                '  "\n\t": newline, tab',
480                '...',
481            ],
482            out => {
483                quoted => 'Magic!',
484                "\n\t" => 'newline, tab',
485            },
486        },
487        {   name => 'Empty',
488            in   => [],
489            out  => undef,
490        },
491    );
492
493    plan tests => @SCHEDULE * 5;
494}
495
496sub iter {
497    my $ar = shift;
498    return sub {
499        return shift @$ar;
500    };
501}
502
503for my $test (@SCHEDULE) {
504    my $name = $test->{name};
505    ok my $yaml = TAP::Parser::YAMLish::Reader->new, "$name: Created";
506    isa_ok $yaml, 'TAP::Parser::YAMLish::Reader';
507
508    my $source = join( "\n", @{ $test->{in} } ) . "\n";
509
510    my $iter = iter( $test->{in} );
511    my $got = eval { $yaml->read($iter) };
512
513    my $raw = $yaml->get_raw;
514
515    if ( my $err = $test->{error} ) {
516        unless ( like $@, $err, "$name: Error message" ) {
517            diag "Error: $@\n";
518        }
519        ok !$got, "$name: No result";
520        pass;
521    }
522    else {
523        my $want = $test->{out};
524        unless ( ok !$@, "$name: No error" ) {
525            diag "Error: $@\n";
526        }
527        is_deeply $got, $want,   "$name: Result matches";
528        is $raw,        $source, "$name: Captured source matches";
529    }
530}
531