1 package yaml_test
2
3 import (
4 "errors"
5 "io"
6 "math"
7 "reflect"
8 "strings"
9 "time"
10
11 . "gopkg.in/check.v1"
12 "gopkg.in/yaml.v2"
13 )
14
15 var unmarshalIntTest = 123
16
17 var unmarshalTests = []struct {
18 data string
19 value interface{}
20 }{
21 {
22 "",
23 (*struct{})(nil),
24 },
25 {
26 "{}", &struct{}{},
27 }, {
28 "v: hi",
29 map[string]string{"v": "hi"},
30 }, {
31 "v: hi", map[string]interface{}{"v": "hi"},
32 }, {
33 "v: true",
34 map[string]string{"v": "true"},
35 }, {
36 "v: true",
37 map[string]interface{}{"v": true},
38 }, {
39 "v: 10",
40 map[string]interface{}{"v": 10},
41 }, {
42 "v: 0b10",
43 map[string]interface{}{"v": 2},
44 }, {
45 "v: 0xA",
46 map[string]interface{}{"v": 10},
47 }, {
48 "v: 4294967296",
49 map[string]int64{"v": 4294967296},
50 }, {
51 "v: 0.1",
52 map[string]interface{}{"v": 0.1},
53 }, {
54 "v: .1",
55 map[string]interface{}{"v": 0.1},
56 }, {
57 "v: .Inf",
58 map[string]interface{}{"v": math.Inf(+1)},
59 }, {
60 "v: -.Inf",
61 map[string]interface{}{"v": math.Inf(-1)},
62 }, {
63 "v: -10",
64 map[string]interface{}{"v": -10},
65 }, {
66 "v: -.1",
67 map[string]interface{}{"v": -0.1},
68 },
69
70
71 {
72 "123",
73 &unmarshalIntTest,
74 },
75
76
77 {
78 "canonical: 6.8523e+5",
79 map[string]interface{}{"canonical": 6.8523e+5},
80 }, {
81 "expo: 685.230_15e+03",
82 map[string]interface{}{"expo": 685.23015e+03},
83 }, {
84 "fixed: 685_230.15",
85 map[string]interface{}{"fixed": 685230.15},
86 }, {
87 "neginf: -.inf",
88 map[string]interface{}{"neginf": math.Inf(-1)},
89 }, {
90 "fixed: 685_230.15",
91 map[string]float64{"fixed": 685230.15},
92 },
93
94
95
96
97 {
98 "canonical: y",
99 map[string]interface{}{"canonical": true},
100 }, {
101 "answer: NO",
102 map[string]interface{}{"answer": false},
103 }, {
104 "logical: True",
105 map[string]interface{}{"logical": true},
106 }, {
107 "option: on",
108 map[string]interface{}{"option": true},
109 }, {
110 "option: on",
111 map[string]bool{"option": true},
112 },
113
114 {
115 "canonical: 685230",
116 map[string]interface{}{"canonical": 685230},
117 }, {
118 "decimal: +685_230",
119 map[string]interface{}{"decimal": 685230},
120 }, {
121 "octal: 02472256",
122 map[string]interface{}{"octal": 685230},
123 }, {
124 "hexa: 0x_0A_74_AE",
125 map[string]interface{}{"hexa": 685230},
126 }, {
127 "bin: 0b1010_0111_0100_1010_1110",
128 map[string]interface{}{"bin": 685230},
129 }, {
130 "bin: -0b101010",
131 map[string]interface{}{"bin": -42},
132 }, {
133 "bin: -0b1000000000000000000000000000000000000000000000000000000000000000",
134 map[string]interface{}{"bin": -9223372036854775808},
135 }, {
136 "decimal: +685_230",
137 map[string]int{"decimal": 685230},
138 },
139
140
141
142
143 {
144 "empty:",
145 map[string]interface{}{"empty": nil},
146 }, {
147 "canonical: ~",
148 map[string]interface{}{"canonical": nil},
149 }, {
150 "english: null",
151 map[string]interface{}{"english": nil},
152 }, {
153 "~: null key",
154 map[interface{}]string{nil: "null key"},
155 }, {
156 "empty:",
157 map[string]*bool{"empty": nil},
158 },
159
160
161 {
162 "seq: [A,B]",
163 map[string]interface{}{"seq": []interface{}{"A", "B"}},
164 }, {
165 "seq: [A,B,C,]",
166 map[string][]string{"seq": []string{"A", "B", "C"}},
167 }, {
168 "seq: [A,1,C]",
169 map[string][]string{"seq": []string{"A", "1", "C"}},
170 }, {
171 "seq: [A,1,C]",
172 map[string][]int{"seq": []int{1}},
173 }, {
174 "seq: [A,1,C]",
175 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
176 },
177
178 {
179 "seq:\n - A\n - B",
180 map[string]interface{}{"seq": []interface{}{"A", "B"}},
181 }, {
182 "seq:\n - A\n - B\n - C",
183 map[string][]string{"seq": []string{"A", "B", "C"}},
184 }, {
185 "seq:\n - A\n - 1\n - C",
186 map[string][]string{"seq": []string{"A", "1", "C"}},
187 }, {
188 "seq:\n - A\n - 1\n - C",
189 map[string][]int{"seq": []int{1}},
190 }, {
191 "seq:\n - A\n - 1\n - C",
192 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
193 },
194
195
196 {
197 "scalar: | # Comment\n\n literal\n\n \ttext\n\n",
198 map[string]string{"scalar": "\nliteral\n\n\ttext\n"},
199 },
200
201
202 {
203 "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n",
204 map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"},
205 },
206
207
208 {
209 "a: {b: c}",
210 map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
211 },
212
213
214 {
215 "hello: world",
216 &struct{ Hello string }{"world"},
217 }, {
218 "a: {b: c}",
219 &struct{ A struct{ B string } }{struct{ B string }{"c"}},
220 }, {
221 "a: {b: c}",
222 &struct{ A *struct{ B string } }{&struct{ B string }{"c"}},
223 }, {
224 "a: {b: c}",
225 &struct{ A map[string]string }{map[string]string{"b": "c"}},
226 }, {
227 "a: {b: c}",
228 &struct{ A *map[string]string }{&map[string]string{"b": "c"}},
229 }, {
230 "a:",
231 &struct{ A map[string]string }{},
232 }, {
233 "a: 1",
234 &struct{ A int }{1},
235 }, {
236 "a: 1",
237 &struct{ A float64 }{1},
238 }, {
239 "a: 1.0",
240 &struct{ A int }{1},
241 }, {
242 "a: 1.0",
243 &struct{ A uint }{1},
244 }, {
245 "a: [1, 2]",
246 &struct{ A []int }{[]int{1, 2}},
247 }, {
248 "a: [1, 2]",
249 &struct{ A [2]int }{[2]int{1, 2}},
250 }, {
251 "a: 1",
252 &struct{ B int }{0},
253 }, {
254 "a: 1",
255 &struct {
256 B int "a"
257 }{1},
258 }, {
259 "a: y",
260 &struct{ A bool }{true},
261 },
262
263
264 {
265 "v: 42",
266 map[string]uint{"v": 42},
267 }, {
268 "v: -42",
269 map[string]uint{},
270 }, {
271 "v: 4294967296",
272 map[string]uint64{"v": 4294967296},
273 }, {
274 "v: -4294967296",
275 map[string]uint64{},
276 },
277
278
279 {
280 "int_max: 2147483647",
281 map[string]int{"int_max": math.MaxInt32},
282 },
283 {
284 "int_min: -2147483648",
285 map[string]int{"int_min": math.MinInt32},
286 },
287 {
288 "int_overflow: 9223372036854775808",
289 map[string]int{},
290 },
291
292
293 {
294 "int64_max: 9223372036854775807",
295 map[string]int64{"int64_max": math.MaxInt64},
296 },
297 {
298 "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
299 map[string]int64{"int64_max_base2": math.MaxInt64},
300 },
301 {
302 "int64_min: -9223372036854775808",
303 map[string]int64{"int64_min": math.MinInt64},
304 },
305 {
306 "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
307 map[string]int64{"int64_neg_base2": -math.MaxInt64},
308 },
309 {
310 "int64_overflow: 9223372036854775808",
311 map[string]int64{},
312 },
313
314
315 {
316 "uint_min: 0",
317 map[string]uint{"uint_min": 0},
318 },
319 {
320 "uint_max: 4294967295",
321 map[string]uint{"uint_max": math.MaxUint32},
322 },
323 {
324 "uint_underflow: -1",
325 map[string]uint{},
326 },
327
328
329 {
330 "uint64_min: 0",
331 map[string]uint{"uint64_min": 0},
332 },
333 {
334 "uint64_max: 18446744073709551615",
335 map[string]uint64{"uint64_max": math.MaxUint64},
336 },
337 {
338 "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
339 map[string]uint64{"uint64_max_base2": math.MaxUint64},
340 },
341 {
342 "uint64_maxint64: 9223372036854775807",
343 map[string]uint64{"uint64_maxint64": math.MaxInt64},
344 },
345 {
346 "uint64_underflow: -1",
347 map[string]uint64{},
348 },
349
350
351 {
352 "float32_max: 3.40282346638528859811704183484516925440e+38",
353 map[string]float32{"float32_max": math.MaxFloat32},
354 },
355 {
356 "float32_nonzero: 1.401298464324817070923729583289916131280e-45",
357 map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32},
358 },
359 {
360 "float32_maxuint64: 18446744073709551615",
361 map[string]float32{"float32_maxuint64": float32(math.MaxUint64)},
362 },
363 {
364 "float32_maxuint64+1: 18446744073709551616",
365 map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)},
366 },
367
368
369 {
370 "float64_max: 1.797693134862315708145274237317043567981e+308",
371 map[string]float64{"float64_max": math.MaxFloat64},
372 },
373 {
374 "float64_nonzero: 4.940656458412465441765687928682213723651e-324",
375 map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64},
376 },
377 {
378 "float64_maxuint64: 18446744073709551615",
379 map[string]float64{"float64_maxuint64": float64(math.MaxUint64)},
380 },
381 {
382 "float64_maxuint64+1: 18446744073709551616",
383 map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)},
384 },
385
386
387 {
388 "v: 4294967297",
389 map[string]int32{},
390 }, {
391 "v: 128",
392 map[string]int8{},
393 },
394
395
396 {
397 "'1': '\"2\"'",
398 map[interface{}]interface{}{"1": "\"2\""},
399 }, {
400 "v:\n- A\n- 'B\n\n C'\n",
401 map[string][]string{"v": []string{"A", "B\nC"}},
402 },
403
404
405 {
406 "v: !!float '1.1'",
407 map[string]interface{}{"v": 1.1},
408 }, {
409 "v: !!float 0",
410 map[string]interface{}{"v": float64(0)},
411 }, {
412 "v: !!float -1",
413 map[string]interface{}{"v": float64(-1)},
414 }, {
415 "v: !!null ''",
416 map[string]interface{}{"v": nil},
417 }, {
418 "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
419 map[string]interface{}{"v": 1},
420 },
421
422
423 {
424 "v: ! test",
425 map[string]interface{}{"v": "test"},
426 },
427
428
429 {
430 "a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
431 &struct{ A, B, C, D int }{1, 2, 1, 2},
432 }, {
433 "a: &a {c: 1}\nb: *a",
434 &struct {
435 A, B struct {
436 C int
437 }
438 }{struct{ C int }{1}, struct{ C int }{1}},
439 }, {
440 "a: &a [1, 2]\nb: *a",
441 &struct{ B []int }{[]int{1, 2}},
442 },
443
444
445 {
446 "foo: ''",
447 map[string]*string{"foo": new(string)},
448 }, {
449 "foo: null",
450 map[string]*string{"foo": nil},
451 }, {
452 "foo: null",
453 map[string]string{"foo": ""},
454 }, {
455 "foo: null",
456 map[string]interface{}{"foo": nil},
457 },
458
459
460 {
461 "foo: ~",
462 map[string]*string{"foo": nil},
463 }, {
464 "foo: ~",
465 map[string]string{"foo": ""},
466 }, {
467 "foo: ~",
468 map[string]interface{}{"foo": nil},
469 },
470
471
472 {
473 "a: 1\nb: 2\n",
474 &struct {
475 A int
476 B int "-"
477 }{1, 0},
478 },
479
480
481 {
482 "" +
483 "%YAML 1.1\n" +
484 "--- !!str\n" +
485 `"Generic line break (no glyph)\n\` + "\n" +
486 ` Generic line break (glyphed)\n\` + "\n" +
487 ` Line separator\u2028\` + "\n" +
488 ` Paragraph separator\u2029"` + "\n",
489 "" +
490 "Generic line break (no glyph)\n" +
491 "Generic line break (glyphed)\n" +
492 "Line separator\u2028Paragraph separator\u2029",
493 },
494
495
496 {
497 "a: 1\nb: 2\nc: 3\n",
498 &struct {
499 A int
500 C inlineB `yaml:",inline"`
501 }{1, inlineB{2, inlineC{3}}},
502 },
503
504
505 {
506 "a: 1\nb: 2\nc: 3\n",
507 &struct {
508 A int
509 C map[string]int `yaml:",inline"`
510 }{1, map[string]int{"b": 2, "c": 3}},
511 },
512
513
514 {
515 "a: -b_c",
516 map[string]interface{}{"a": "-b_c"},
517 },
518 {
519 "a: +b_c",
520 map[string]interface{}{"a": "+b_c"},
521 },
522 {
523 "a: 50cent_of_dollar",
524 map[string]interface{}{"a": "50cent_of_dollar"},
525 },
526
527
528 {
529 "a: {b: https://github.com/go-yaml/yaml}",
530 map[string]interface{}{"a": map[interface{}]interface{}{
531 "b": "https://github.com/go-yaml/yaml",
532 }},
533 },
534 {
535 "a: [https://github.com/go-yaml/yaml]",
536 map[string]interface{}{"a": []interface{}{"https://github.com/go-yaml/yaml"}},
537 },
538
539
540 {
541 "a: 3s",
542 map[string]time.Duration{"a": 3 * time.Second},
543 },
544
545
546 {
547 "a: <foo>",
548 map[string]string{"a": "<foo>"},
549 },
550
551
552 {
553 "a: 1:1\n",
554 map[string]string{"a": "1:1"},
555 },
556
557
558 {
559 "a: !!binary gIGC\n",
560 map[string]string{"a": "\x80\x81\x82"},
561 }, {
562 "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
563 map[string]string{"a": strings.Repeat("\x90", 54)},
564 }, {
565 "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n",
566 map[string]string{"a": strings.Repeat("\x00", 52)},
567 },
568
569
570 {
571 "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
572 &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
573 },
574
575
576 {
577 "a:\n b:\n c: d\n",
578 map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}},
579 },
580
581
582 {
583 "a: {b: c}",
584 M{"a": M{"b": "c"}},
585 },
586
587
588 {
589 "a: 1.2.3.4\n",
590 map[string]textUnmarshaler{"a": textUnmarshaler{S: "1.2.3.4"}},
591 },
592 {
593 "a: 2015-02-24T18:19:39Z\n",
594 map[string]textUnmarshaler{"a": textUnmarshaler{"2015-02-24T18:19:39Z"}},
595 },
596
597
598 {
599
600 "a: 2015-01-01\n",
601 map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
602 },
603 {
604
605 "a: 2015-02-24T18:19:39.12Z\n",
606 map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, .12e9, time.UTC)},
607 },
608 {
609
610 "a: 2015-2-3T3:4:5Z",
611 map[string]time.Time{"a": time.Date(2015, 2, 3, 3, 4, 5, 0, time.UTC)},
612 },
613 {
614
615 "a: 2015-02-24t18:19:39Z\n",
616 map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
617 },
618 {
619
620 "a: 2015-02-24 18:19:39\n",
621 map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
622 },
623
624
625
626
627
628
629
630
631
632
633
634
635 {
636
637 "a: !!str 2015-01-01",
638 map[string]interface{}{"a": "2015-01-01"},
639 },
640 {
641
642 "a: !!timestamp \"2015-01-01\"",
643 map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
644 },
645 {
646
647 "a: !!timestamp 2015-01-01",
648 map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
649 },
650 {
651
652 "a: \"2015-01-01\"",
653 map[string]interface{}{"a": "2015-01-01"},
654 },
655 {
656
657 "a: !!timestamp \"2015-01-01\"",
658 map[string]interface{}{"a": "2015-01-01"},
659 },
660 {
661
662 "a: 2015-01-01",
663 map[string]interface{}{"a": "2015-01-01"},
664 },
665
666
667 {
668 "a: []",
669 &struct{ A []int }{[]int{}},
670 },
671
672
673 {
674 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00",
675 M{"ñoño": "very yes"},
676 },
677
678 {
679 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00",
680 M{"ñoño": "very yes 🟔"},
681 },
682
683
684 {
685 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n",
686 M{"ñoño": "very yes"},
687 },
688
689 {
690 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n",
691 M{"ñoño": "very yes 🟔"},
692 },
693
694
695 {
696 "a: 123456e1\n",
697 M{"a": 123456e1},
698 }, {
699 "a: 123456E1\n",
700 M{"a": 123456E1},
701 },
702
703 {
704 "First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n",
705 map[interface{}]interface{}{
706 "Reuse anchor": "Bar",
707 "First occurrence": "Foo",
708 "Second occurrence": "Foo",
709 "Override anchor": "Bar",
710 },
711 },
712
713 {
714 "---\nhello\n...\n}not yaml",
715 "hello",
716 },
717 {
718 "a: 5\n",
719 &struct{ A jsonNumberT }{"5"},
720 },
721 {
722 "a: 5.5\n",
723 &struct{ A jsonNumberT }{"5.5"},
724 },
725 {
726 `
727 a:
728 b
729 b:
730 ? a
731 : a`,
732 &M{"a": "b",
733 "b": M{
734 "a": "a",
735 }},
736 },
737 }
738
739 type M map[interface{}]interface{}
740
741 type inlineB struct {
742 B int
743 inlineC `yaml:",inline"`
744 }
745
746 type inlineC struct {
747 C int
748 }
749
750 func (s *S) TestUnmarshal(c *C) {
751 for i, item := range unmarshalTests {
752 c.Logf("test %d: %q", i, item.data)
753 t := reflect.ValueOf(item.value).Type()
754 value := reflect.New(t)
755 err := yaml.Unmarshal([]byte(item.data), value.Interface())
756 if _, ok := err.(*yaml.TypeError); !ok {
757 c.Assert(err, IsNil)
758 }
759 c.Assert(value.Elem().Interface(), DeepEquals, item.value, Commentf("error: %v", err))
760 }
761 }
762
763
764 func (s *S) TestUnmarshalFullTimestamp(c *C) {
765
766
767 var str = "2015-02-24T18:19:39.123456789-03:00"
768 var t time.Time
769 err := yaml.Unmarshal([]byte(str), &t)
770 c.Assert(err, IsNil)
771 c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.Location()))
772 c.Assert(t.In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC))
773 }
774
775 func (s *S) TestDecoderSingleDocument(c *C) {
776
777
778 for i, item := range unmarshalTests {
779 c.Logf("test %d: %q", i, item.data)
780 if item.data == "" {
781
782 continue
783 }
784 t := reflect.ValueOf(item.value).Type()
785 value := reflect.New(t)
786 err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(value.Interface())
787 if _, ok := err.(*yaml.TypeError); !ok {
788 c.Assert(err, IsNil)
789 }
790 c.Assert(value.Elem().Interface(), DeepEquals, item.value)
791 }
792 }
793
794 var decoderTests = []struct {
795 data string
796 values []interface{}
797 }{{
798 "",
799 nil,
800 }, {
801 "a: b",
802 []interface{}{
803 map[interface{}]interface{}{"a": "b"},
804 },
805 }, {
806 "---\na: b\n...\n",
807 []interface{}{
808 map[interface{}]interface{}{"a": "b"},
809 },
810 }, {
811 "---\n'hello'\n...\n---\ngoodbye\n...\n",
812 []interface{}{
813 "hello",
814 "goodbye",
815 },
816 }}
817
818 func (s *S) TestDecoder(c *C) {
819 for i, item := range decoderTests {
820 c.Logf("test %d: %q", i, item.data)
821 var values []interface{}
822 dec := yaml.NewDecoder(strings.NewReader(item.data))
823 for {
824 var value interface{}
825 err := dec.Decode(&value)
826 if err == io.EOF {
827 break
828 }
829 c.Assert(err, IsNil)
830 values = append(values, value)
831 }
832 c.Assert(values, DeepEquals, item.values)
833 }
834 }
835
836 type errReader struct{}
837
838 func (errReader) Read([]byte) (int, error) {
839 return 0, errors.New("some read error")
840 }
841
842 func (s *S) TestDecoderReadError(c *C) {
843 err := yaml.NewDecoder(errReader{}).Decode(&struct{}{})
844 c.Assert(err, ErrorMatches, `yaml: input error: some read error`)
845 }
846
847 func (s *S) TestUnmarshalNaN(c *C) {
848 value := map[string]interface{}{}
849 err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
850 c.Assert(err, IsNil)
851 c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
852 }
853
854 var unmarshalErrorTests = []struct {
855 data, error string
856 }{
857 {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"},
858 {"v: [A,", "yaml: line 1: did not find expected node content"},
859 {"v:\n- [A,", "yaml: line 2: did not find expected node content"},
860 {"a:\n- b: *,", "yaml: line 2: did not find expected alphabetic or numeric character"},
861 {"a: *b\n", "yaml: unknown anchor 'b' referenced"},
862 {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"},
863 {"a: &x null\n<<:\n- *x\nb: &x {}\n", `yaml: map merge requires map or sequence of maps as the value`},
864 {"value: -", "yaml: block sequence entries are not allowed in this context"},
865 {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"},
866 {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`},
867 {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
868 {"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`},
869 {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"},
870 {"a:\n 1:\nb\n 2:", ".*could not find expected ':'"},
871 {
872 "a: &a [00,00,00,00,00,00,00,00,00]\n" +
873 "b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" +
874 "c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" +
875 "d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" +
876 "e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" +
877 "f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" +
878 "g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" +
879 "h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" +
880 "i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n",
881 "yaml: document contains excessive aliasing",
882 },
883 }
884
885 func (s *S) TestUnmarshalErrors(c *C) {
886 for i, item := range unmarshalErrorTests {
887 c.Logf("test %d: %q", i, item.data)
888 var value interface{}
889 err := yaml.Unmarshal([]byte(item.data), &value)
890 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
891
892 if strings.Contains(item.data, ":") {
893
894 var value map[string]interface{}
895 err := yaml.Unmarshal([]byte(item.data), &value)
896 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
897 }
898 }
899 }
900
901 func (s *S) TestDecoderErrors(c *C) {
902 for _, item := range unmarshalErrorTests {
903 var value interface{}
904 err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(&value)
905 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
906 }
907 }
908
909 var unmarshalerTests = []struct {
910 data, tag string
911 value interface{}
912 }{
913 {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}},
914 {"_: [1,A]", "!!seq", []interface{}{1, "A"}},
915 {"_: 10", "!!int", 10},
916 {"_: null", "!!null", nil},
917 {`_: BAR!`, "!!str", "BAR!"},
918 {`_: "BAR!"`, "!!str", "BAR!"},
919 {"_: !!foo 'BAR!'", "!!foo", "BAR!"},
920 {`_: ""`, "!!str", ""},
921 }
922
923 var unmarshalerResult = map[int]error{}
924
925 type unmarshalerType struct {
926 value interface{}
927 }
928
929 func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error {
930 if err := unmarshal(&o.value); err != nil {
931 return err
932 }
933 if i, ok := o.value.(int); ok {
934 if result, ok := unmarshalerResult[i]; ok {
935 return result
936 }
937 }
938 return nil
939 }
940
941 type unmarshalerPointer struct {
942 Field *unmarshalerType "_"
943 }
944
945 type unmarshalerValue struct {
946 Field unmarshalerType "_"
947 }
948
949 func (s *S) TestUnmarshalerPointerField(c *C) {
950 for _, item := range unmarshalerTests {
951 obj := &unmarshalerPointer{}
952 err := yaml.Unmarshal([]byte(item.data), obj)
953 c.Assert(err, IsNil)
954 if item.value == nil {
955 c.Assert(obj.Field, IsNil)
956 } else {
957 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
958 c.Assert(obj.Field.value, DeepEquals, item.value)
959 }
960 }
961 }
962
963 func (s *S) TestUnmarshalerValueField(c *C) {
964 for _, item := range unmarshalerTests {
965 obj := &unmarshalerValue{}
966 err := yaml.Unmarshal([]byte(item.data), obj)
967 c.Assert(err, IsNil)
968 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
969 c.Assert(obj.Field.value, DeepEquals, item.value)
970 }
971 }
972
973 func (s *S) TestUnmarshalerWholeDocument(c *C) {
974 obj := &unmarshalerType{}
975 err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj)
976 c.Assert(err, IsNil)
977 value, ok := obj.value.(map[interface{}]interface{})
978 c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value))
979 c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value)
980 }
981
982 func (s *S) TestUnmarshalerTypeError(c *C) {
983 unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
984 unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
985 defer func() {
986 delete(unmarshalerResult, 2)
987 delete(unmarshalerResult, 4)
988 }()
989
990 type T struct {
991 Before int
992 After int
993 M map[string]*unmarshalerType
994 }
995 var v T
996 data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
997 err := yaml.Unmarshal([]byte(data), &v)
998 c.Assert(err, ErrorMatches, ""+
999 "yaml: unmarshal errors:\n"+
1000 " line 1: cannot unmarshal !!str `A` into int\n"+
1001 " foo\n"+
1002 " bar\n"+
1003 " line 1: cannot unmarshal !!str `B` into int")
1004 c.Assert(v.M["abc"], NotNil)
1005 c.Assert(v.M["def"], IsNil)
1006 c.Assert(v.M["ghi"], NotNil)
1007 c.Assert(v.M["jkl"], IsNil)
1008
1009 c.Assert(v.M["abc"].value, Equals, 1)
1010 c.Assert(v.M["ghi"].value, Equals, 3)
1011 }
1012
1013 type proxyTypeError struct{}
1014
1015 func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error {
1016 var s string
1017 var a int32
1018 var b int64
1019 if err := unmarshal(&s); err != nil {
1020 panic(err)
1021 }
1022 if s == "a" {
1023 if err := unmarshal(&b); err == nil {
1024 panic("should have failed")
1025 }
1026 return unmarshal(&a)
1027 }
1028 if err := unmarshal(&a); err == nil {
1029 panic("should have failed")
1030 }
1031 return unmarshal(&b)
1032 }
1033
1034 func (s *S) TestUnmarshalerTypeErrorProxying(c *C) {
1035 type T struct {
1036 Before int
1037 After int
1038 M map[string]*proxyTypeError
1039 }
1040 var v T
1041 data := `{before: A, m: {abc: a, def: b}, after: B}`
1042 err := yaml.Unmarshal([]byte(data), &v)
1043 c.Assert(err, ErrorMatches, ""+
1044 "yaml: unmarshal errors:\n"+
1045 " line 1: cannot unmarshal !!str `A` into int\n"+
1046 " line 1: cannot unmarshal !!str `a` into int32\n"+
1047 " line 1: cannot unmarshal !!str `b` into int64\n"+
1048 " line 1: cannot unmarshal !!str `B` into int")
1049 }
1050
1051 type failingUnmarshaler struct{}
1052
1053 var failingErr = errors.New("failingErr")
1054
1055 func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
1056 return failingErr
1057 }
1058
1059 func (s *S) TestUnmarshalerError(c *C) {
1060 err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{})
1061 c.Assert(err, Equals, failingErr)
1062 }
1063
1064 type sliceUnmarshaler []int
1065
1066 func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
1067 var slice []int
1068 err := unmarshal(&slice)
1069 if err == nil {
1070 *su = slice
1071 return nil
1072 }
1073
1074 var intVal int
1075 err = unmarshal(&intVal)
1076 if err == nil {
1077 *su = []int{intVal}
1078 return nil
1079 }
1080
1081 return err
1082 }
1083
1084 func (s *S) TestUnmarshalerRetry(c *C) {
1085 var su sliceUnmarshaler
1086 err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
1087 c.Assert(err, IsNil)
1088 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3}))
1089
1090 err = yaml.Unmarshal([]byte("1"), &su)
1091 c.Assert(err, IsNil)
1092 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1}))
1093 }
1094
1095
1096 var mergeTests = `
1097 anchors:
1098 list:
1099 - &CENTER { "x": 1, "y": 2 }
1100 - &LEFT { "x": 0, "y": 2 }
1101 - &BIG { "r": 10 }
1102 - &SMALL { "r": 1 }
1103
1104 # All the following maps are equal:
1105
1106 plain:
1107 # Explicit keys
1108 "x": 1
1109 "y": 2
1110 "r": 10
1111 label: center/big
1112
1113 mergeOne:
1114 # Merge one map
1115 << : *CENTER
1116 "r": 10
1117 label: center/big
1118
1119 mergeMultiple:
1120 # Merge multiple maps
1121 << : [ *CENTER, *BIG ]
1122 label: center/big
1123
1124 override:
1125 # Override
1126 << : [ *BIG, *LEFT, *SMALL ]
1127 "x": 1
1128 label: center/big
1129
1130 shortTag:
1131 # Explicit short merge tag
1132 !!merge "<<" : [ *CENTER, *BIG ]
1133 label: center/big
1134
1135 longTag:
1136 # Explicit merge long tag
1137 !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
1138 label: center/big
1139
1140 inlineMap:
1141 # Inlined map
1142 << : {"x": 1, "y": 2, "r": 10}
1143 label: center/big
1144
1145 inlineSequenceMap:
1146 # Inlined map in sequence
1147 << : [ *CENTER, {"r": 10} ]
1148 label: center/big
1149 `
1150
1151 func (s *S) TestMerge(c *C) {
1152 var want = map[interface{}]interface{}{
1153 "x": 1,
1154 "y": 2,
1155 "r": 10,
1156 "label": "center/big",
1157 }
1158
1159 var m map[interface{}]interface{}
1160 err := yaml.Unmarshal([]byte(mergeTests), &m)
1161 c.Assert(err, IsNil)
1162 for name, test := range m {
1163 if name == "anchors" {
1164 continue
1165 }
1166 c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
1167 }
1168 }
1169
1170 func (s *S) TestMergeStruct(c *C) {
1171 type Data struct {
1172 X, Y, R int
1173 Label string
1174 }
1175 want := Data{1, 2, 10, "center/big"}
1176
1177 var m map[string]Data
1178 err := yaml.Unmarshal([]byte(mergeTests), &m)
1179 c.Assert(err, IsNil)
1180 for name, test := range m {
1181 if name == "anchors" {
1182 continue
1183 }
1184 c.Assert(test, Equals, want, Commentf("test %q failed", name))
1185 }
1186 }
1187
1188 var unmarshalNullTests = []func() interface{}{
1189 func() interface{} { var v interface{}; v = "v"; return &v },
1190 func() interface{} { var s = "s"; return &s },
1191 func() interface{} { var s = "s"; sptr := &s; return &sptr },
1192 func() interface{} { var i = 1; return &i },
1193 func() interface{} { var i = 1; iptr := &i; return &iptr },
1194 func() interface{} { m := map[string]int{"s": 1}; return &m },
1195 func() interface{} { m := map[string]int{"s": 1}; return m },
1196 }
1197
1198 func (s *S) TestUnmarshalNull(c *C) {
1199 for _, test := range unmarshalNullTests {
1200 item := test()
1201 zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface()
1202 err := yaml.Unmarshal([]byte("null"), item)
1203 c.Assert(err, IsNil)
1204 if reflect.TypeOf(item).Kind() == reflect.Map {
1205 c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface())
1206 } else {
1207 c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero)
1208 }
1209 }
1210 }
1211
1212 func (s *S) TestUnmarshalSliceOnPreset(c *C) {
1213
1214 v := struct{ A []int }{[]int{1}}
1215 yaml.Unmarshal([]byte("a: [2]"), &v)
1216 c.Assert(v.A, DeepEquals, []int{2})
1217 }
1218
1219 var unmarshalStrictTests = []struct {
1220 data string
1221 value interface{}
1222 error string
1223 }{{
1224 data: "a: 1\nc: 2\n",
1225 value: struct{ A, B int }{A: 1},
1226 error: `yaml: unmarshal errors:\n line 2: field c not found in type struct { A int; B int }`,
1227 }, {
1228 data: "a: 1\nb: 2\na: 3\n",
1229 value: struct{ A, B int }{A: 3, B: 2},
1230 error: `yaml: unmarshal errors:\n line 3: field a already set in type struct { A int; B int }`,
1231 }, {
1232 data: "c: 3\na: 1\nb: 2\nc: 4\n",
1233 value: struct {
1234 A int
1235 inlineB `yaml:",inline"`
1236 }{
1237 A: 1,
1238 inlineB: inlineB{
1239 B: 2,
1240 inlineC: inlineC{
1241 C: 4,
1242 },
1243 },
1244 },
1245 error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`,
1246 }, {
1247 data: "c: 0\na: 1\nb: 2\nc: 1\n",
1248 value: struct {
1249 A int
1250 inlineB `yaml:",inline"`
1251 }{
1252 A: 1,
1253 inlineB: inlineB{
1254 B: 2,
1255 inlineC: inlineC{
1256 C: 1,
1257 },
1258 },
1259 },
1260 error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`,
1261 }, {
1262 data: "c: 1\na: 1\nb: 2\nc: 3\n",
1263 value: struct {
1264 A int
1265 M map[string]interface{} `yaml:",inline"`
1266 }{
1267 A: 1,
1268 M: map[string]interface{}{
1269 "b": 2,
1270 "c": 3,
1271 },
1272 },
1273 error: `yaml: unmarshal errors:\n line 4: key "c" already set in map`,
1274 }, {
1275 data: "a: 1\n9: 2\nnull: 3\n9: 4",
1276 value: map[interface{}]interface{}{
1277 "a": 1,
1278 nil: 3,
1279 9: 4,
1280 },
1281 error: `yaml: unmarshal errors:\n line 4: key 9 already set in map`,
1282 }}
1283
1284 func (s *S) TestUnmarshalStrict(c *C) {
1285 for i, item := range unmarshalStrictTests {
1286 c.Logf("test %d: %q", i, item.data)
1287
1288 t := reflect.ValueOf(item.value).Type()
1289 value := reflect.New(t)
1290 err := yaml.Unmarshal([]byte(item.data), value.Interface())
1291 c.Assert(err, Equals, nil)
1292 c.Assert(value.Elem().Interface(), DeepEquals, item.value)
1293
1294
1295 t = reflect.ValueOf(item.value).Type()
1296 value = reflect.New(t)
1297 err = yaml.UnmarshalStrict([]byte(item.data), value.Interface())
1298 c.Assert(err, ErrorMatches, item.error)
1299 }
1300 }
1301
1302 type textUnmarshaler struct {
1303 S string
1304 }
1305
1306 func (t *textUnmarshaler) UnmarshalText(s []byte) error {
1307 t.S = string(s)
1308 return nil
1309 }
1310
1311 func (s *S) TestFuzzCrashers(c *C) {
1312 cases := []string{
1313
1314 "\"\\0\\\r\n",
1315
1316
1317 " 0: [\n] 0",
1318 "? ? \"\n\" 0",
1319 " - {\n000}0",
1320 "0:\n 0: [0\n] 0",
1321 " - \"\n000\"0",
1322 " - \"\n000\"\"",
1323 "0:\n - {\n000}0",
1324 "0:\n - \"\n000\"0",
1325 "0:\n - \"\n000\"\"",
1326
1327
1328 " \ufeff\n",
1329 "? \ufeff\n",
1330 "? \ufeff:\n",
1331 "0: \ufeff\n",
1332 "? \ufeff: \ufeff\n",
1333 }
1334 for _, data := range cases {
1335 var v interface{}
1336 _ = yaml.Unmarshal([]byte(data), &v)
1337 }
1338 }
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
View as plain text