1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package yaml_test
17
18 import (
19 "bytes"
20 "errors"
21 "fmt"
22 "io"
23 "math"
24 "reflect"
25 "strings"
26 "time"
27
28 . "gopkg.in/check.v1"
29 "gopkg.in/yaml.v3"
30 )
31
32 var unmarshalIntTest = 123
33
34 var unmarshalTests = []struct {
35 data string
36 value interface{}
37 }{
38 {
39 "",
40 (*struct{})(nil),
41 },
42 {
43 "{}", &struct{}{},
44 }, {
45 "v: hi",
46 map[string]string{"v": "hi"},
47 }, {
48 "v: hi", map[string]interface{}{"v": "hi"},
49 }, {
50 "v: true",
51 map[string]string{"v": "true"},
52 }, {
53 "v: true",
54 map[string]interface{}{"v": true},
55 }, {
56 "v: 10",
57 map[string]interface{}{"v": 10},
58 }, {
59 "v: 0b10",
60 map[string]interface{}{"v": 2},
61 }, {
62 "v: 0xA",
63 map[string]interface{}{"v": 10},
64 }, {
65 "v: 4294967296",
66 map[string]int64{"v": 4294967296},
67 }, {
68 "v: 0.1",
69 map[string]interface{}{"v": 0.1},
70 }, {
71 "v: .1",
72 map[string]interface{}{"v": 0.1},
73 }, {
74 "v: .Inf",
75 map[string]interface{}{"v": math.Inf(+1)},
76 }, {
77 "v: -.Inf",
78 map[string]interface{}{"v": math.Inf(-1)},
79 }, {
80 "v: -10",
81 map[string]interface{}{"v": -10},
82 }, {
83 "v: -.1",
84 map[string]interface{}{"v": -0.1},
85 },
86
87
88 {
89 "123",
90 &unmarshalIntTest,
91 },
92
93
94 {
95 "canonical: 6.8523e+5",
96 map[string]interface{}{"canonical": 6.8523e+5},
97 }, {
98 "expo: 685.230_15e+03",
99 map[string]interface{}{"expo": 685.23015e+03},
100 }, {
101 "fixed: 685_230.15",
102 map[string]interface{}{"fixed": 685230.15},
103 }, {
104 "neginf: -.inf",
105 map[string]interface{}{"neginf": math.Inf(-1)},
106 }, {
107 "fixed: 685_230.15",
108 map[string]float64{"fixed": 685230.15},
109 },
110
111
112
113
114 {
115 "canonical: true",
116 map[string]interface{}{"canonical": true},
117 }, {
118 "canonical: false",
119 map[string]interface{}{"canonical": false},
120 }, {
121 "bool: True",
122 map[string]interface{}{"bool": true},
123 }, {
124 "bool: False",
125 map[string]interface{}{"bool": false},
126 }, {
127 "bool: TRUE",
128 map[string]interface{}{"bool": true},
129 }, {
130 "bool: FALSE",
131 map[string]interface{}{"bool": false},
132 },
133
134 {
135 "option: on",
136 map[string]bool{"option": true},
137 }, {
138 "option: y",
139 map[string]bool{"option": true},
140 }, {
141 "option: Off",
142 map[string]bool{"option": false},
143 }, {
144 "option: No",
145 map[string]bool{"option": false},
146 }, {
147 "option: other",
148 map[string]bool{},
149 },
150
151 {
152 "canonical: 685230",
153 map[string]interface{}{"canonical": 685230},
154 }, {
155 "decimal: +685_230",
156 map[string]interface{}{"decimal": 685230},
157 }, {
158 "octal: 02472256",
159 map[string]interface{}{"octal": 685230},
160 }, {
161 "octal: -02472256",
162 map[string]interface{}{"octal": -685230},
163 }, {
164 "octal: 0o2472256",
165 map[string]interface{}{"octal": 685230},
166 }, {
167 "octal: -0o2472256",
168 map[string]interface{}{"octal": -685230},
169 }, {
170 "hexa: 0x_0A_74_AE",
171 map[string]interface{}{"hexa": 685230},
172 }, {
173 "bin: 0b1010_0111_0100_1010_1110",
174 map[string]interface{}{"bin": 685230},
175 }, {
176 "bin: -0b101010",
177 map[string]interface{}{"bin": -42},
178 }, {
179 "bin: -0b1000000000000000000000000000000000000000000000000000000000000000",
180 map[string]interface{}{"bin": -9223372036854775808},
181 }, {
182 "decimal: +685_230",
183 map[string]int{"decimal": 685230},
184 },
185
186
187
188
189 {
190 "empty:",
191 map[string]interface{}{"empty": nil},
192 }, {
193 "canonical: ~",
194 map[string]interface{}{"canonical": nil},
195 }, {
196 "english: null",
197 map[string]interface{}{"english": nil},
198 }, {
199 "~: null key",
200 map[interface{}]string{nil: "null key"},
201 }, {
202 "empty:",
203 map[string]*bool{"empty": nil},
204 },
205
206
207 {
208 "seq: [A,B]",
209 map[string]interface{}{"seq": []interface{}{"A", "B"}},
210 }, {
211 "seq: [A,B,C,]",
212 map[string][]string{"seq": []string{"A", "B", "C"}},
213 }, {
214 "seq: [A,1,C]",
215 map[string][]string{"seq": []string{"A", "1", "C"}},
216 }, {
217 "seq: [A,1,C]",
218 map[string][]int{"seq": []int{1}},
219 }, {
220 "seq: [A,1,C]",
221 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
222 },
223
224 {
225 "seq:\n - A\n - B",
226 map[string]interface{}{"seq": []interface{}{"A", "B"}},
227 }, {
228 "seq:\n - A\n - B\n - C",
229 map[string][]string{"seq": []string{"A", "B", "C"}},
230 }, {
231 "seq:\n - A\n - 1\n - C",
232 map[string][]string{"seq": []string{"A", "1", "C"}},
233 }, {
234 "seq:\n - A\n - 1\n - C",
235 map[string][]int{"seq": []int{1}},
236 }, {
237 "seq:\n - A\n - 1\n - C",
238 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
239 },
240
241
242 {
243 "scalar: | # Comment\n\n literal\n\n \ttext\n\n",
244 map[string]string{"scalar": "\nliteral\n\n\ttext\n"},
245 },
246
247
248 {
249 "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n",
250 map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"},
251 },
252
253
254 {
255 "a: {b: c}",
256 map[interface{}]interface{}{"a": map[string]interface{}{"b": "c"}},
257 },
258
259 {
260 "a: {b: c, 1: d}",
261 map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c", 1: "d"}},
262 },
263
264
265 {
266 "hello: world",
267 &struct{ Hello string }{"world"},
268 }, {
269 "a: {b: c}",
270 &struct{ A struct{ B string } }{struct{ B string }{"c"}},
271 }, {
272 "a: {b: c}",
273 &struct{ A *struct{ B string } }{&struct{ B string }{"c"}},
274 }, {
275 "a: 'null'",
276 &struct{ A *unmarshalerType }{&unmarshalerType{"null"}},
277 }, {
278 "a: {b: c}",
279 &struct{ A map[string]string }{map[string]string{"b": "c"}},
280 }, {
281 "a: {b: c}",
282 &struct{ A *map[string]string }{&map[string]string{"b": "c"}},
283 }, {
284 "a:",
285 &struct{ A map[string]string }{},
286 }, {
287 "a: 1",
288 &struct{ A int }{1},
289 }, {
290 "a: 1",
291 &struct{ A float64 }{1},
292 }, {
293 "a: 1.0",
294 &struct{ A int }{1},
295 }, {
296 "a: 1.0",
297 &struct{ A uint }{1},
298 }, {
299 "a: [1, 2]",
300 &struct{ A []int }{[]int{1, 2}},
301 }, {
302 "a: [1, 2]",
303 &struct{ A [2]int }{[2]int{1, 2}},
304 }, {
305 "a: 1",
306 &struct{ B int }{0},
307 }, {
308 "a: 1",
309 &struct {
310 B int "a"
311 }{1},
312 }, {
313
314 "a: YES",
315 &struct{ A bool }{true},
316 },
317
318
319 {
320 "v: 42",
321 map[string]uint{"v": 42},
322 }, {
323 "v: -42",
324 map[string]uint{},
325 }, {
326 "v: 4294967296",
327 map[string]uint64{"v": 4294967296},
328 }, {
329 "v: -4294967296",
330 map[string]uint64{},
331 },
332
333
334 {
335 "int_max: 2147483647",
336 map[string]int{"int_max": math.MaxInt32},
337 },
338 {
339 "int_min: -2147483648",
340 map[string]int{"int_min": math.MinInt32},
341 },
342 {
343 "int_overflow: 9223372036854775808",
344 map[string]int{},
345 },
346
347
348 {
349 "int64_max: 9223372036854775807",
350 map[string]int64{"int64_max": math.MaxInt64},
351 },
352 {
353 "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
354 map[string]int64{"int64_max_base2": math.MaxInt64},
355 },
356 {
357 "int64_min: -9223372036854775808",
358 map[string]int64{"int64_min": math.MinInt64},
359 },
360 {
361 "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
362 map[string]int64{"int64_neg_base2": -math.MaxInt64},
363 },
364 {
365 "int64_overflow: 9223372036854775808",
366 map[string]int64{},
367 },
368
369
370 {
371 "uint_min: 0",
372 map[string]uint{"uint_min": 0},
373 },
374 {
375 "uint_max: 4294967295",
376 map[string]uint{"uint_max": math.MaxUint32},
377 },
378 {
379 "uint_underflow: -1",
380 map[string]uint{},
381 },
382
383
384 {
385 "uint64_min: 0",
386 map[string]uint{"uint64_min": 0},
387 },
388 {
389 "uint64_max: 18446744073709551615",
390 map[string]uint64{"uint64_max": math.MaxUint64},
391 },
392 {
393 "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
394 map[string]uint64{"uint64_max_base2": math.MaxUint64},
395 },
396 {
397 "uint64_maxint64: 9223372036854775807",
398 map[string]uint64{"uint64_maxint64": math.MaxInt64},
399 },
400 {
401 "uint64_underflow: -1",
402 map[string]uint64{},
403 },
404
405
406 {
407 "float32_max: 3.40282346638528859811704183484516925440e+38",
408 map[string]float32{"float32_max": math.MaxFloat32},
409 },
410 {
411 "float32_nonzero: 1.401298464324817070923729583289916131280e-45",
412 map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32},
413 },
414 {
415 "float32_maxuint64: 18446744073709551615",
416 map[string]float32{"float32_maxuint64": float32(math.MaxUint64)},
417 },
418 {
419 "float32_maxuint64+1: 18446744073709551616",
420 map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)},
421 },
422
423
424 {
425 "float64_max: 1.797693134862315708145274237317043567981e+308",
426 map[string]float64{"float64_max": math.MaxFloat64},
427 },
428 {
429 "float64_nonzero: 4.940656458412465441765687928682213723651e-324",
430 map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64},
431 },
432 {
433 "float64_maxuint64: 18446744073709551615",
434 map[string]float64{"float64_maxuint64": float64(math.MaxUint64)},
435 },
436 {
437 "float64_maxuint64+1: 18446744073709551616",
438 map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)},
439 },
440
441
442 {
443 "v: 4294967297",
444 map[string]int32{},
445 }, {
446 "v: 128",
447 map[string]int8{},
448 },
449
450
451 {
452 "'1': '\"2\"'",
453 map[interface{}]interface{}{"1": "\"2\""},
454 }, {
455 "v:\n- A\n- 'B\n\n C'\n",
456 map[string][]string{"v": []string{"A", "B\nC"}},
457 },
458
459
460 {
461 "v: !!float '1.1'",
462 map[string]interface{}{"v": 1.1},
463 }, {
464 "v: !!float 0",
465 map[string]interface{}{"v": float64(0)},
466 }, {
467 "v: !!float -1",
468 map[string]interface{}{"v": float64(-1)},
469 }, {
470 "v: !!null ''",
471 map[string]interface{}{"v": nil},
472 }, {
473 "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
474 map[string]interface{}{"v": 1},
475 },
476
477
478 {
479 "v: ! test",
480 map[string]interface{}{"v": "test"},
481 },
482
483
484 {
485 "a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
486 &struct{ A, B, C, D int }{1, 2, 1, 2},
487 }, {
488 "a: &a {c: 1}\nb: *a",
489 &struct {
490 A, B struct {
491 C int
492 }
493 }{struct{ C int }{1}, struct{ C int }{1}},
494 }, {
495 "a: &a [1, 2]\nb: *a",
496 &struct{ B []int }{[]int{1, 2}},
497 },
498
499
500 {
501 "foo: ''",
502 map[string]*string{"foo": new(string)},
503 }, {
504 "foo: null",
505 map[string]*string{"foo": nil},
506 }, {
507 "foo: null",
508 map[string]string{"foo": ""},
509 }, {
510 "foo: null",
511 map[string]interface{}{"foo": nil},
512 },
513
514
515 {
516 "foo: ~",
517 map[string]*string{"foo": nil},
518 }, {
519 "foo: ~",
520 map[string]string{"foo": ""},
521 }, {
522 "foo: ~",
523 map[string]interface{}{"foo": nil},
524 },
525
526
527 {
528 "a: 1\nb: 2\n",
529 &struct {
530 A int
531 B int "-"
532 }{1, 0},
533 },
534
535
536 {
537 "" +
538 "%YAML 1.1\n" +
539 "--- !!str\n" +
540 `"Generic line break (no glyph)\n\` + "\n" +
541 ` Generic line break (glyphed)\n\` + "\n" +
542 ` Line separator\u2028\` + "\n" +
543 ` Paragraph separator\u2029"` + "\n",
544 "" +
545 "Generic line break (no glyph)\n" +
546 "Generic line break (glyphed)\n" +
547 "Line separator\u2028Paragraph separator\u2029",
548 },
549
550
551 {
552 "a: 1\nb: 2\nc: 3\n",
553 &struct {
554 A int
555 C inlineB `yaml:",inline"`
556 }{1, inlineB{2, inlineC{3}}},
557 },
558
559
560 {
561 "a: 1\nb: 2\nc: 3\n",
562 &struct {
563 A int
564 C *inlineB `yaml:",inline"`
565 }{1, &inlineB{2, inlineC{3}}},
566 }, {
567 "a: 1\n",
568 &struct {
569 A int
570 C *inlineB `yaml:",inline"`
571 }{1, nil},
572 }, {
573 "a: 1\nc: 3\nd: 4\n",
574 &struct {
575 A int
576 C *inlineD `yaml:",inline"`
577 }{1, &inlineD{&inlineC{3}, 4}},
578 },
579
580
581 {
582 "a: 1\nb: 2\nc: 3\n",
583 &struct {
584 A int
585 C map[string]int `yaml:",inline"`
586 }{1, map[string]int{"b": 2, "c": 3}},
587 },
588
589
590 {
591 "a: -b_c",
592 map[string]interface{}{"a": "-b_c"},
593 },
594 {
595 "a: +b_c",
596 map[string]interface{}{"a": "+b_c"},
597 },
598 {
599 "a: 50cent_of_dollar",
600 map[string]interface{}{"a": "50cent_of_dollar"},
601 },
602
603
604 {
605 "a: {b: https://github.com/go-yaml/yaml}",
606 map[string]interface{}{"a": map[string]interface{}{
607 "b": "https://github.com/go-yaml/yaml",
608 }},
609 },
610 {
611 "a: [https://github.com/go-yaml/yaml]",
612 map[string]interface{}{"a": []interface{}{"https://github.com/go-yaml/yaml"}},
613 },
614
615
616 {
617 "a: 3s",
618 map[string]time.Duration{"a": 3 * time.Second},
619 },
620
621
622 {
623 "a: <foo>",
624 map[string]string{"a": "<foo>"},
625 },
626
627
628 {
629 "a: 1:1\n",
630 map[string]string{"a": "1:1"},
631 },
632
633
634 {
635 "a: !!binary gIGC\n",
636 map[string]string{"a": "\x80\x81\x82"},
637 }, {
638 "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
639 map[string]string{"a": strings.Repeat("\x90", 54)},
640 }, {
641 "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n",
642 map[string]string{"a": strings.Repeat("\x00", 52)},
643 },
644
645
646 {
647 "a:\n b:\n c: d\n",
648 map[string]struct{ B interface{} }{"a": {map[string]interface{}{"c": "d"}}},
649 },
650
651
652 {
653 "a: {b: c}",
654 M{"a": M{"b": "c"}},
655 },
656
657
658 {
659 "a: 1.2.3.4\n",
660 map[string]textUnmarshaler{"a": textUnmarshaler{S: "1.2.3.4"}},
661 },
662 {
663 "a: 2015-02-24T18:19:39Z\n",
664 map[string]textUnmarshaler{"a": textUnmarshaler{"2015-02-24T18:19:39Z"}},
665 },
666
667
668 {
669
670 "a: 2015-01-01\n",
671 map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
672 },
673 {
674
675 "a: 2015-02-24T18:19:39.12Z\n",
676 map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, .12e9, time.UTC)},
677 },
678 {
679
680 "a: 2015-2-3T3:4:5Z",
681 map[string]time.Time{"a": time.Date(2015, 2, 3, 3, 4, 5, 0, time.UTC)},
682 },
683 {
684
685 "a: 2015-02-24t18:19:39Z\n",
686 map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
687 },
688 {
689
690 "a: 2015-02-24 18:19:39\n",
691 map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
692 },
693
694
695
696
697
698
699
700
701
702
703
704
705 {
706
707 "a: !!str 2015-01-01",
708 map[string]interface{}{"a": "2015-01-01"},
709 },
710 {
711
712 "a: !!timestamp \"2015-01-01\"",
713 map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
714 },
715 {
716
717 "a: !!timestamp 2015-01-01",
718 map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
719 },
720 {
721
722 "a: \"2015-01-01\"",
723 map[string]interface{}{"a": "2015-01-01"},
724 },
725 {
726
727 "a: !!timestamp \"2015-01-01\"",
728 map[string]interface{}{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
729 },
730 {
731
732 "a: 2015-01-01",
733 map[string]interface{}{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
734 },
735
736
737 {
738 "a: []",
739 &struct{ A []int }{[]int{}},
740 },
741
742
743 {
744 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00",
745 M{"ñoño": "very yes"},
746 },
747
748 {
749 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00",
750 M{"ñoño": "very yes 🟔"},
751 },
752
753
754 {
755 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n",
756 M{"ñoño": "very yes"},
757 },
758
759 {
760 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n",
761 M{"ñoño": "very yes 🟔"},
762 },
763
764
765 {
766 "a: 123456e1\n",
767 M{"a": 123456e1},
768 }, {
769 "a: 123456E1\n",
770 M{"a": 123456e1},
771 },
772
773 {
774 "First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n",
775 map[string]interface{}{
776 "First occurrence": "Foo",
777 "Second occurrence": "Foo",
778 "Override anchor": "Bar",
779 "Reuse anchor": "Bar",
780 },
781 },
782
783 {
784 "---\nhello\n...\n}not yaml",
785 "hello",
786 },
787
788
789 {
790 "true\n#" + strings.Repeat(" ", 512*3),
791 "true",
792 }, {
793 "true #" + strings.Repeat(" ", 512*3),
794 "true",
795 },
796
797
798 {
799 "a: b\r\nc:\r\n- d\r\n- e\r\n",
800 map[string]interface{}{
801 "a": "b",
802 "c": []interface{}{"d", "e"},
803 },
804 },
805 }
806
807 type M map[string]interface{}
808
809 type inlineB struct {
810 B int
811 inlineC `yaml:",inline"`
812 }
813
814 type inlineC struct {
815 C int
816 }
817
818 type inlineD struct {
819 C *inlineC `yaml:",inline"`
820 D int
821 }
822
823 func (s *S) TestUnmarshal(c *C) {
824 for i, item := range unmarshalTests {
825 c.Logf("test %d: %q", i, item.data)
826 t := reflect.ValueOf(item.value).Type()
827 value := reflect.New(t)
828 err := yaml.Unmarshal([]byte(item.data), value.Interface())
829 if _, ok := err.(*yaml.TypeError); !ok {
830 c.Assert(err, IsNil)
831 }
832 c.Assert(value.Elem().Interface(), DeepEquals, item.value, Commentf("error: %v", err))
833 }
834 }
835
836 func (s *S) TestUnmarshalFullTimestamp(c *C) {
837
838
839 var str = "2015-02-24T18:19:39.123456789-03:00"
840 var t interface{}
841 err := yaml.Unmarshal([]byte(str), &t)
842 c.Assert(err, IsNil)
843 c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.(time.Time).Location()))
844 c.Assert(t.(time.Time).In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC))
845 }
846
847 func (s *S) TestDecoderSingleDocument(c *C) {
848
849
850 for i, item := range unmarshalTests {
851 c.Logf("test %d: %q", i, item.data)
852 if item.data == "" {
853
854 continue
855 }
856 t := reflect.ValueOf(item.value).Type()
857 value := reflect.New(t)
858 err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(value.Interface())
859 if _, ok := err.(*yaml.TypeError); !ok {
860 c.Assert(err, IsNil)
861 }
862 c.Assert(value.Elem().Interface(), DeepEquals, item.value)
863 }
864 }
865
866 var decoderTests = []struct {
867 data string
868 values []interface{}
869 }{{
870 "",
871 nil,
872 }, {
873 "a: b",
874 []interface{}{
875 map[string]interface{}{"a": "b"},
876 },
877 }, {
878 "---\na: b\n...\n",
879 []interface{}{
880 map[string]interface{}{"a": "b"},
881 },
882 }, {
883 "---\n'hello'\n...\n---\ngoodbye\n...\n",
884 []interface{}{
885 "hello",
886 "goodbye",
887 },
888 }}
889
890 func (s *S) TestDecoder(c *C) {
891 for i, item := range decoderTests {
892 c.Logf("test %d: %q", i, item.data)
893 var values []interface{}
894 dec := yaml.NewDecoder(strings.NewReader(item.data))
895 for {
896 var value interface{}
897 err := dec.Decode(&value)
898 if err == io.EOF {
899 break
900 }
901 c.Assert(err, IsNil)
902 values = append(values, value)
903 }
904 c.Assert(values, DeepEquals, item.values)
905 }
906 }
907
908 type errReader struct{}
909
910 func (errReader) Read([]byte) (int, error) {
911 return 0, errors.New("some read error")
912 }
913
914 func (s *S) TestDecoderReadError(c *C) {
915 err := yaml.NewDecoder(errReader{}).Decode(&struct{}{})
916 c.Assert(err, ErrorMatches, `yaml: input error: some read error`)
917 }
918
919 func (s *S) TestUnmarshalNaN(c *C) {
920 value := map[string]interface{}{}
921 err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
922 c.Assert(err, IsNil)
923 c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
924 }
925
926 func (s *S) TestUnmarshalDurationInt(c *C) {
927
928 var d time.Duration
929 err := yaml.Unmarshal([]byte("123"), &d)
930 c.Assert(err, ErrorMatches, "(?s).* line 1: cannot unmarshal !!int `123` into time.Duration")
931 }
932
933 var unmarshalErrorTests = []struct {
934 data, error string
935 }{
936 {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"},
937 {"v: [A,", "yaml: line 1: did not find expected node content"},
938 {"v:\n- [A,", "yaml: line 2: did not find expected node content"},
939 {"a:\n- b: *,", "yaml: line 2: did not find expected alphabetic or numeric character"},
940 {"a: *b\n", "yaml: unknown anchor 'b' referenced"},
941 {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"},
942 {"value: -", "yaml: block sequence entries are not allowed in this context"},
943 {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"},
944 {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`},
945 {"{{.}}", `yaml: invalid map key: map\[string]interface \{\}\{".":interface \{\}\(nil\)\}`},
946 {"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`},
947 {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"},
948 {"a:\n 1:\nb\n 2:", ".*could not find expected ':'"},
949 {"a: 1\nb: 2\nc 2\nd: 3\n", "^yaml: line 3: could not find expected ':'$"},
950 {"#\n-\n{", "yaml: line 3: could not find expected ':'"},
951 {"0: [:!00 \xef", "yaml: incomplete UTF-8 octet sequence"},
952 {
953 "a: &a [00,00,00,00,00,00,00,00,00]\n" +
954 "b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" +
955 "c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" +
956 "d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" +
957 "e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" +
958 "f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" +
959 "g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" +
960 "h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" +
961 "i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n",
962 "yaml: document contains excessive aliasing",
963 },
964 }
965
966 func (s *S) TestUnmarshalErrors(c *C) {
967 for i, item := range unmarshalErrorTests {
968 c.Logf("test %d: %q", i, item.data)
969 var value interface{}
970 err := yaml.Unmarshal([]byte(item.data), &value)
971 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
972 }
973 }
974
975 func (s *S) TestDecoderErrors(c *C) {
976 for _, item := range unmarshalErrorTests {
977 var value interface{}
978 err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(&value)
979 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
980 }
981 }
982
983 var unmarshalerTests = []struct {
984 data, tag string
985 value interface{}
986 }{
987 {"_: {hi: there}", "!!map", map[string]interface{}{"hi": "there"}},
988 {"_: [1,A]", "!!seq", []interface{}{1, "A"}},
989 {"_: 10", "!!int", 10},
990 {"_: null", "!!null", nil},
991 {`_: BAR!`, "!!str", "BAR!"},
992 {`_: "BAR!"`, "!!str", "BAR!"},
993 {"_: !!foo 'BAR!'", "!!foo", "BAR!"},
994 {`_: ""`, "!!str", ""},
995 }
996
997 var unmarshalerResult = map[int]error{}
998
999 type unmarshalerType struct {
1000 value interface{}
1001 }
1002
1003 func (o *unmarshalerType) UnmarshalYAML(value *yaml.Node) error {
1004 if err := value.Decode(&o.value); err != nil {
1005 return err
1006 }
1007 if i, ok := o.value.(int); ok {
1008 if result, ok := unmarshalerResult[i]; ok {
1009 return result
1010 }
1011 }
1012 return nil
1013 }
1014
1015 type unmarshalerPointer struct {
1016 Field *unmarshalerType "_"
1017 }
1018
1019 type unmarshalerValue struct {
1020 Field unmarshalerType "_"
1021 }
1022
1023 type unmarshalerInlined struct {
1024 Field *unmarshalerType "_"
1025 Inlined unmarshalerType `yaml:",inline"`
1026 }
1027
1028 type unmarshalerInlinedTwice struct {
1029 InlinedTwice unmarshalerInlined `yaml:",inline"`
1030 }
1031
1032 type obsoleteUnmarshalerType struct {
1033 value interface{}
1034 }
1035
1036 func (o *obsoleteUnmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error {
1037 if err := unmarshal(&o.value); err != nil {
1038 return err
1039 }
1040 if i, ok := o.value.(int); ok {
1041 if result, ok := unmarshalerResult[i]; ok {
1042 return result
1043 }
1044 }
1045 return nil
1046 }
1047
1048 type obsoleteUnmarshalerPointer struct {
1049 Field *obsoleteUnmarshalerType "_"
1050 }
1051
1052 type obsoleteUnmarshalerValue struct {
1053 Field obsoleteUnmarshalerType "_"
1054 }
1055
1056 func (s *S) TestUnmarshalerPointerField(c *C) {
1057 for _, item := range unmarshalerTests {
1058 obj := &unmarshalerPointer{}
1059 err := yaml.Unmarshal([]byte(item.data), obj)
1060 c.Assert(err, IsNil)
1061 if item.value == nil {
1062 c.Assert(obj.Field, IsNil)
1063 } else {
1064 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
1065 c.Assert(obj.Field.value, DeepEquals, item.value)
1066 }
1067 }
1068 for _, item := range unmarshalerTests {
1069 obj := &obsoleteUnmarshalerPointer{}
1070 err := yaml.Unmarshal([]byte(item.data), obj)
1071 c.Assert(err, IsNil)
1072 if item.value == nil {
1073 c.Assert(obj.Field, IsNil)
1074 } else {
1075 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
1076 c.Assert(obj.Field.value, DeepEquals, item.value)
1077 }
1078 }
1079 }
1080
1081 func (s *S) TestUnmarshalerValueField(c *C) {
1082 for _, item := range unmarshalerTests {
1083 obj := &obsoleteUnmarshalerValue{}
1084 err := yaml.Unmarshal([]byte(item.data), obj)
1085 c.Assert(err, IsNil)
1086 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
1087 c.Assert(obj.Field.value, DeepEquals, item.value)
1088 }
1089 }
1090
1091 func (s *S) TestUnmarshalerInlinedField(c *C) {
1092 obj := &unmarshalerInlined{}
1093 err := yaml.Unmarshal([]byte("_: a\ninlined: b\n"), obj)
1094 c.Assert(err, IsNil)
1095 c.Assert(obj.Field, DeepEquals, &unmarshalerType{"a"})
1096 c.Assert(obj.Inlined, DeepEquals, unmarshalerType{map[string]interface{}{"_": "a", "inlined": "b"}})
1097
1098 twc := &unmarshalerInlinedTwice{}
1099 err = yaml.Unmarshal([]byte("_: a\ninlined: b\n"), twc)
1100 c.Assert(err, IsNil)
1101 c.Assert(twc.InlinedTwice.Field, DeepEquals, &unmarshalerType{"a"})
1102 c.Assert(twc.InlinedTwice.Inlined, DeepEquals, unmarshalerType{map[string]interface{}{"_": "a", "inlined": "b"}})
1103 }
1104
1105 func (s *S) TestUnmarshalerWholeDocument(c *C) {
1106 obj := &obsoleteUnmarshalerType{}
1107 err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj)
1108 c.Assert(err, IsNil)
1109 value, ok := obj.value.(map[string]interface{})
1110 c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value))
1111 c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value)
1112 }
1113
1114 func (s *S) TestUnmarshalerTypeError(c *C) {
1115 unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
1116 unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
1117 defer func() {
1118 delete(unmarshalerResult, 2)
1119 delete(unmarshalerResult, 4)
1120 }()
1121
1122 type T struct {
1123 Before int
1124 After int
1125 M map[string]*unmarshalerType
1126 }
1127 var v T
1128 data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
1129 err := yaml.Unmarshal([]byte(data), &v)
1130 c.Assert(err, ErrorMatches, ""+
1131 "yaml: unmarshal errors:\n"+
1132 " line 1: cannot unmarshal !!str `A` into int\n"+
1133 " foo\n"+
1134 " bar\n"+
1135 " line 1: cannot unmarshal !!str `B` into int")
1136 c.Assert(v.M["abc"], NotNil)
1137 c.Assert(v.M["def"], IsNil)
1138 c.Assert(v.M["ghi"], NotNil)
1139 c.Assert(v.M["jkl"], IsNil)
1140
1141 c.Assert(v.M["abc"].value, Equals, 1)
1142 c.Assert(v.M["ghi"].value, Equals, 3)
1143 }
1144
1145 func (s *S) TestObsoleteUnmarshalerTypeError(c *C) {
1146 unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
1147 unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
1148 defer func() {
1149 delete(unmarshalerResult, 2)
1150 delete(unmarshalerResult, 4)
1151 }()
1152
1153 type T struct {
1154 Before int
1155 After int
1156 M map[string]*obsoleteUnmarshalerType
1157 }
1158 var v T
1159 data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
1160 err := yaml.Unmarshal([]byte(data), &v)
1161 c.Assert(err, ErrorMatches, ""+
1162 "yaml: unmarshal errors:\n"+
1163 " line 1: cannot unmarshal !!str `A` into int\n"+
1164 " foo\n"+
1165 " bar\n"+
1166 " line 1: cannot unmarshal !!str `B` into int")
1167 c.Assert(v.M["abc"], NotNil)
1168 c.Assert(v.M["def"], IsNil)
1169 c.Assert(v.M["ghi"], NotNil)
1170 c.Assert(v.M["jkl"], IsNil)
1171
1172 c.Assert(v.M["abc"].value, Equals, 1)
1173 c.Assert(v.M["ghi"].value, Equals, 3)
1174 }
1175
1176 type proxyTypeError struct{}
1177
1178 func (v *proxyTypeError) UnmarshalYAML(node *yaml.Node) error {
1179 var s string
1180 var a int32
1181 var b int64
1182 if err := node.Decode(&s); err != nil {
1183 panic(err)
1184 }
1185 if s == "a" {
1186 if err := node.Decode(&b); err == nil {
1187 panic("should have failed")
1188 }
1189 return node.Decode(&a)
1190 }
1191 if err := node.Decode(&a); err == nil {
1192 panic("should have failed")
1193 }
1194 return node.Decode(&b)
1195 }
1196
1197 func (s *S) TestUnmarshalerTypeErrorProxying(c *C) {
1198 type T struct {
1199 Before int
1200 After int
1201 M map[string]*proxyTypeError
1202 }
1203 var v T
1204 data := `{before: A, m: {abc: a, def: b}, after: B}`
1205 err := yaml.Unmarshal([]byte(data), &v)
1206 c.Assert(err, ErrorMatches, ""+
1207 "yaml: unmarshal errors:\n"+
1208 " line 1: cannot unmarshal !!str `A` into int\n"+
1209 " line 1: cannot unmarshal !!str `a` into int32\n"+
1210 " line 1: cannot unmarshal !!str `b` into int64\n"+
1211 " line 1: cannot unmarshal !!str `B` into int")
1212 }
1213
1214 type obsoleteProxyTypeError struct{}
1215
1216 func (v *obsoleteProxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error {
1217 var s string
1218 var a int32
1219 var b int64
1220 if err := unmarshal(&s); err != nil {
1221 panic(err)
1222 }
1223 if s == "a" {
1224 if err := unmarshal(&b); err == nil {
1225 panic("should have failed")
1226 }
1227 return unmarshal(&a)
1228 }
1229 if err := unmarshal(&a); err == nil {
1230 panic("should have failed")
1231 }
1232 return unmarshal(&b)
1233 }
1234
1235 func (s *S) TestObsoleteUnmarshalerTypeErrorProxying(c *C) {
1236 type T struct {
1237 Before int
1238 After int
1239 M map[string]*obsoleteProxyTypeError
1240 }
1241 var v T
1242 data := `{before: A, m: {abc: a, def: b}, after: B}`
1243 err := yaml.Unmarshal([]byte(data), &v)
1244 c.Assert(err, ErrorMatches, ""+
1245 "yaml: unmarshal errors:\n"+
1246 " line 1: cannot unmarshal !!str `A` into int\n"+
1247 " line 1: cannot unmarshal !!str `a` into int32\n"+
1248 " line 1: cannot unmarshal !!str `b` into int64\n"+
1249 " line 1: cannot unmarshal !!str `B` into int")
1250 }
1251
1252 var failingErr = errors.New("failingErr")
1253
1254 type failingUnmarshaler struct{}
1255
1256 func (ft *failingUnmarshaler) UnmarshalYAML(node *yaml.Node) error {
1257 return failingErr
1258 }
1259
1260 func (s *S) TestUnmarshalerError(c *C) {
1261 err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{})
1262 c.Assert(err, Equals, failingErr)
1263 }
1264
1265 type obsoleteFailingUnmarshaler struct{}
1266
1267 func (ft *obsoleteFailingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
1268 return failingErr
1269 }
1270
1271 func (s *S) TestObsoleteUnmarshalerError(c *C) {
1272 err := yaml.Unmarshal([]byte("a: b"), &obsoleteFailingUnmarshaler{})
1273 c.Assert(err, Equals, failingErr)
1274 }
1275
1276 type sliceUnmarshaler []int
1277
1278 func (su *sliceUnmarshaler) UnmarshalYAML(node *yaml.Node) error {
1279 var slice []int
1280 err := node.Decode(&slice)
1281 if err == nil {
1282 *su = slice
1283 return nil
1284 }
1285
1286 var intVal int
1287 err = node.Decode(&intVal)
1288 if err == nil {
1289 *su = []int{intVal}
1290 return nil
1291 }
1292
1293 return err
1294 }
1295
1296 func (s *S) TestUnmarshalerRetry(c *C) {
1297 var su sliceUnmarshaler
1298 err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
1299 c.Assert(err, IsNil)
1300 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3}))
1301
1302 err = yaml.Unmarshal([]byte("1"), &su)
1303 c.Assert(err, IsNil)
1304 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1}))
1305 }
1306
1307 type obsoleteSliceUnmarshaler []int
1308
1309 func (su *obsoleteSliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
1310 var slice []int
1311 err := unmarshal(&slice)
1312 if err == nil {
1313 *su = slice
1314 return nil
1315 }
1316
1317 var intVal int
1318 err = unmarshal(&intVal)
1319 if err == nil {
1320 *su = []int{intVal}
1321 return nil
1322 }
1323
1324 return err
1325 }
1326
1327 func (s *S) TestObsoleteUnmarshalerRetry(c *C) {
1328 var su obsoleteSliceUnmarshaler
1329 err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
1330 c.Assert(err, IsNil)
1331 c.Assert(su, DeepEquals, obsoleteSliceUnmarshaler([]int{1, 2, 3}))
1332
1333 err = yaml.Unmarshal([]byte("1"), &su)
1334 c.Assert(err, IsNil)
1335 c.Assert(su, DeepEquals, obsoleteSliceUnmarshaler([]int{1}))
1336 }
1337
1338
1339 var mergeTests = `
1340 anchors:
1341 list:
1342 - &CENTER { "x": 1, "y": 2 }
1343 - &LEFT { "x": 0, "y": 2 }
1344 - &BIG { "r": 10 }
1345 - &SMALL { "r": 1 }
1346
1347 # All the following maps are equal:
1348
1349 plain:
1350 # Explicit keys
1351 "x": 1
1352 "y": 2
1353 "r": 10
1354 label: center/big
1355
1356 mergeOne:
1357 # Merge one map
1358 << : *CENTER
1359 "r": 10
1360 label: center/big
1361
1362 mergeMultiple:
1363 # Merge multiple maps
1364 << : [ *CENTER, *BIG ]
1365 label: center/big
1366
1367 override:
1368 # Override
1369 << : [ *BIG, *LEFT, *SMALL ]
1370 "x": 1
1371 label: center/big
1372
1373 shortTag:
1374 # Explicit short merge tag
1375 !!merge "<<" : [ *CENTER, *BIG ]
1376 label: center/big
1377
1378 longTag:
1379 # Explicit merge long tag
1380 !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
1381 label: center/big
1382
1383 inlineMap:
1384 # Inlined map
1385 << : {"x": 1, "y": 2, "r": 10}
1386 label: center/big
1387
1388 inlineSequenceMap:
1389 # Inlined map in sequence
1390 << : [ *CENTER, {"r": 10} ]
1391 label: center/big
1392 `
1393
1394 func (s *S) TestMerge(c *C) {
1395 var want = map[string]interface{}{
1396 "x": 1,
1397 "y": 2,
1398 "r": 10,
1399 "label": "center/big",
1400 }
1401
1402 wantStringMap := make(map[string]interface{})
1403 for k, v := range want {
1404 wantStringMap[fmt.Sprintf("%v", k)] = v
1405 }
1406
1407 var m map[interface{}]interface{}
1408 err := yaml.Unmarshal([]byte(mergeTests), &m)
1409 c.Assert(err, IsNil)
1410 for name, test := range m {
1411 if name == "anchors" {
1412 continue
1413 }
1414 if name == "plain" {
1415 c.Assert(test, DeepEquals, wantStringMap, Commentf("test %q failed", name))
1416 continue
1417 }
1418 c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
1419 }
1420 }
1421
1422 func (s *S) TestMergeStruct(c *C) {
1423 type Data struct {
1424 X, Y, R int
1425 Label string
1426 }
1427 want := Data{1, 2, 10, "center/big"}
1428
1429 var m map[string]Data
1430 err := yaml.Unmarshal([]byte(mergeTests), &m)
1431 c.Assert(err, IsNil)
1432 for name, test := range m {
1433 if name == "anchors" {
1434 continue
1435 }
1436 c.Assert(test, Equals, want, Commentf("test %q failed", name))
1437 }
1438 }
1439
1440 var mergeTestsNested = `
1441 mergeouter1: &mergeouter1
1442 d: 40
1443 e: 50
1444
1445 mergeouter2: &mergeouter2
1446 e: 5
1447 f: 6
1448 g: 70
1449
1450 mergeinner1: &mergeinner1
1451 <<: *mergeouter1
1452 inner:
1453 a: 1
1454 b: 2
1455
1456 mergeinner2: &mergeinner2
1457 <<: *mergeouter2
1458 inner:
1459 a: -1
1460 b: -2
1461
1462 outer:
1463 <<: [*mergeinner1, *mergeinner2]
1464 f: 60
1465 inner:
1466 a: 10
1467 `
1468
1469 func (s *S) TestMergeNestedStruct(c *C) {
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497 type Inner struct {
1498 A, B, C int
1499 }
1500 type Outer struct {
1501 D, E int
1502 Inner Inner
1503 Inline map[string]int `yaml:",inline"`
1504 }
1505 type Data struct {
1506 Outer Outer
1507 }
1508
1509 test := Data{Outer{0, 0, Inner{C: 30}, nil}}
1510 want := Data{Outer{40, 50, Inner{A: 10, C: 30}, map[string]int{"f": 60, "g": 70}}}
1511
1512 err := yaml.Unmarshal([]byte(mergeTestsNested), &test)
1513 c.Assert(err, IsNil)
1514 c.Assert(test, DeepEquals, want)
1515
1516
1517
1518 var testm map[string]interface{}
1519 var wantm = map[string]interface {} {
1520 "f": 60,
1521 "inner": map[string]interface{}{
1522 "a": 10,
1523 },
1524 "d": 40,
1525 "e": 50,
1526 "g": 70,
1527 }
1528 err = yaml.Unmarshal([]byte(mergeTestsNested), &testm)
1529 c.Assert(err, IsNil)
1530 c.Assert(testm["outer"], DeepEquals, wantm)
1531 }
1532
1533 var unmarshalNullTests = []struct {
1534 input string
1535 pristine, expected func() interface{}
1536 }{{
1537 "null",
1538 func() interface{} { var v interface{}; v = "v"; return &v },
1539 func() interface{} { var v interface{}; v = nil; return &v },
1540 }, {
1541 "null",
1542 func() interface{} { var s = "s"; return &s },
1543 func() interface{} { var s = "s"; return &s },
1544 }, {
1545 "null",
1546 func() interface{} { var s = "s"; sptr := &s; return &sptr },
1547 func() interface{} { var sptr *string; return &sptr },
1548 }, {
1549 "null",
1550 func() interface{} { var i = 1; return &i },
1551 func() interface{} { var i = 1; return &i },
1552 }, {
1553 "null",
1554 func() interface{} { var i = 1; iptr := &i; return &iptr },
1555 func() interface{} { var iptr *int; return &iptr },
1556 }, {
1557 "null",
1558 func() interface{} { var m = map[string]int{"s": 1}; return &m },
1559 func() interface{} { var m map[string]int; return &m },
1560 }, {
1561 "null",
1562 func() interface{} { var m = map[string]int{"s": 1}; return m },
1563 func() interface{} { var m = map[string]int{"s": 1}; return m },
1564 }, {
1565 "s2: null\ns3: null",
1566 func() interface{} { var m = map[string]int{"s1": 1, "s2": 2}; return m },
1567 func() interface{} { var m = map[string]int{"s1": 1, "s2": 2, "s3": 0}; return m },
1568 }, {
1569 "s2: null\ns3: null",
1570 func() interface{} { var m = map[string]interface{}{"s1": 1, "s2": 2}; return m },
1571 func() interface{} { var m = map[string]interface{}{"s1": 1, "s2": nil, "s3": nil}; return m },
1572 }}
1573
1574 func (s *S) TestUnmarshalNull(c *C) {
1575 for _, test := range unmarshalNullTests {
1576 pristine := test.pristine()
1577 expected := test.expected()
1578 err := yaml.Unmarshal([]byte(test.input), pristine)
1579 c.Assert(err, IsNil)
1580 c.Assert(pristine, DeepEquals, expected)
1581 }
1582 }
1583
1584 func (s *S) TestUnmarshalPreservesData(c *C) {
1585 var v struct {
1586 A, B int
1587 C int `yaml:"-"`
1588 }
1589 v.A = 42
1590 v.C = 88
1591 err := yaml.Unmarshal([]byte("---"), &v)
1592 c.Assert(err, IsNil)
1593 c.Assert(v.A, Equals, 42)
1594 c.Assert(v.B, Equals, 0)
1595 c.Assert(v.C, Equals, 88)
1596
1597 err = yaml.Unmarshal([]byte("b: 21\nc: 99"), &v)
1598 c.Assert(err, IsNil)
1599 c.Assert(v.A, Equals, 42)
1600 c.Assert(v.B, Equals, 21)
1601 c.Assert(v.C, Equals, 88)
1602 }
1603
1604 func (s *S) TestUnmarshalSliceOnPreset(c *C) {
1605
1606 v := struct{ A []int }{[]int{1}}
1607 yaml.Unmarshal([]byte("a: [2]"), &v)
1608 c.Assert(v.A, DeepEquals, []int{2})
1609 }
1610
1611 var unmarshalStrictTests = []struct {
1612 known bool
1613 unique bool
1614 data string
1615 value interface{}
1616 error string
1617 }{{
1618 known: true,
1619 data: "a: 1\nc: 2\n",
1620 value: struct{ A, B int }{A: 1},
1621 error: `yaml: unmarshal errors:\n line 2: field c not found in type struct { A int; B int }`,
1622 }, {
1623 unique: true,
1624 data: "a: 1\nb: 2\na: 3\n",
1625 value: struct{ A, B int }{A: 3, B: 2},
1626 error: `yaml: unmarshal errors:\n line 3: mapping key "a" already defined at line 1`,
1627 }, {
1628 unique: true,
1629 data: "c: 3\na: 1\nb: 2\nc: 4\n",
1630 value: struct {
1631 A int
1632 inlineB `yaml:",inline"`
1633 }{
1634 A: 1,
1635 inlineB: inlineB{
1636 B: 2,
1637 inlineC: inlineC{
1638 C: 4,
1639 },
1640 },
1641 },
1642 error: `yaml: unmarshal errors:\n line 4: mapping key "c" already defined at line 1`,
1643 }, {
1644 unique: true,
1645 data: "c: 0\na: 1\nb: 2\nc: 1\n",
1646 value: struct {
1647 A int
1648 inlineB `yaml:",inline"`
1649 }{
1650 A: 1,
1651 inlineB: inlineB{
1652 B: 2,
1653 inlineC: inlineC{
1654 C: 1,
1655 },
1656 },
1657 },
1658 error: `yaml: unmarshal errors:\n line 4: mapping key "c" already defined at line 1`,
1659 }, {
1660 unique: true,
1661 data: "c: 1\na: 1\nb: 2\nc: 3\n",
1662 value: struct {
1663 A int
1664 M map[string]interface{} `yaml:",inline"`
1665 }{
1666 A: 1,
1667 M: map[string]interface{}{
1668 "b": 2,
1669 "c": 3,
1670 },
1671 },
1672 error: `yaml: unmarshal errors:\n line 4: mapping key "c" already defined at line 1`,
1673 }, {
1674 unique: true,
1675 data: "a: 1\n9: 2\nnull: 3\n9: 4",
1676 value: map[interface{}]interface{}{
1677 "a": 1,
1678 nil: 3,
1679 9: 4,
1680 },
1681 error: `yaml: unmarshal errors:\n line 4: mapping key "9" already defined at line 2`,
1682 }}
1683
1684 func (s *S) TestUnmarshalKnownFields(c *C) {
1685 for i, item := range unmarshalStrictTests {
1686 c.Logf("test %d: %q", i, item.data)
1687
1688 if !item.unique {
1689 t := reflect.ValueOf(item.value).Type()
1690 value := reflect.New(t)
1691 err := yaml.Unmarshal([]byte(item.data), value.Interface())
1692 c.Assert(err, Equals, nil)
1693 c.Assert(value.Elem().Interface(), DeepEquals, item.value)
1694 }
1695
1696
1697 t := reflect.ValueOf(item.value).Type()
1698 value := reflect.New(t)
1699 dec := yaml.NewDecoder(bytes.NewBuffer([]byte(item.data)))
1700 dec.KnownFields(item.known)
1701 err := dec.Decode(value.Interface())
1702 c.Assert(err, ErrorMatches, item.error)
1703 }
1704 }
1705
1706 type textUnmarshaler struct {
1707 S string
1708 }
1709
1710 func (t *textUnmarshaler) UnmarshalText(s []byte) error {
1711 t.S = string(s)
1712 return nil
1713 }
1714
1715 func (s *S) TestFuzzCrashers(c *C) {
1716 cases := []string{
1717
1718 "\"\\0\\\r\n",
1719
1720
1721 " 0: [\n] 0",
1722 "? ? \"\n\" 0",
1723 " - {\n000}0",
1724 "0:\n 0: [0\n] 0",
1725 " - \"\n000\"0",
1726 " - \"\n000\"\"",
1727 "0:\n - {\n000}0",
1728 "0:\n - \"\n000\"0",
1729 "0:\n - \"\n000\"\"",
1730
1731
1732 " \ufeff\n",
1733 "? \ufeff\n",
1734 "? \ufeff:\n",
1735 "0: \ufeff\n",
1736 "? \ufeff: \ufeff\n",
1737 }
1738 for _, data := range cases {
1739 var v interface{}
1740 _ = yaml.Unmarshal([]byte(data), &v)
1741 }
1742 }
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
View as plain text