ODPM 266: Go-libmemif + 2 examples.
[govpp.git] / vendor / gopkg.in / yaml.v2 / decode_test.go
1 package yaml_test
2
3 import (
4         "errors"
5         . "gopkg.in/check.v1"
6         "gopkg.in/yaml.v2"
7         "math"
8         "net"
9         "reflect"
10         "strings"
11         "time"
12 )
13
14 var unmarshalIntTest = 123
15
16 var unmarshalTests = []struct {
17         data  string
18         value interface{}
19 }{
20         {
21                 "",
22                 &struct{}{},
23         }, {
24                 "{}", &struct{}{},
25         }, {
26                 "v: hi",
27                 map[string]string{"v": "hi"},
28         }, {
29                 "v: hi", map[string]interface{}{"v": "hi"},
30         }, {
31                 "v: true",
32                 map[string]string{"v": "true"},
33         }, {
34                 "v: true",
35                 map[string]interface{}{"v": true},
36         }, {
37                 "v: 10",
38                 map[string]interface{}{"v": 10},
39         }, {
40                 "v: 0b10",
41                 map[string]interface{}{"v": 2},
42         }, {
43                 "v: 0xA",
44                 map[string]interface{}{"v": 10},
45         }, {
46                 "v: 4294967296",
47                 map[string]int64{"v": 4294967296},
48         }, {
49                 "v: 0.1",
50                 map[string]interface{}{"v": 0.1},
51         }, {
52                 "v: .1",
53                 map[string]interface{}{"v": 0.1},
54         }, {
55                 "v: .Inf",
56                 map[string]interface{}{"v": math.Inf(+1)},
57         }, {
58                 "v: -.Inf",
59                 map[string]interface{}{"v": math.Inf(-1)},
60         }, {
61                 "v: -10",
62                 map[string]interface{}{"v": -10},
63         }, {
64                 "v: -.1",
65                 map[string]interface{}{"v": -0.1},
66         },
67
68         // Simple values.
69         {
70                 "123",
71                 &unmarshalIntTest,
72         },
73
74         // Floats from spec
75         {
76                 "canonical: 6.8523e+5",
77                 map[string]interface{}{"canonical": 6.8523e+5},
78         }, {
79                 "expo: 685.230_15e+03",
80                 map[string]interface{}{"expo": 685.23015e+03},
81         }, {
82                 "fixed: 685_230.15",
83                 map[string]interface{}{"fixed": 685230.15},
84         }, {
85                 "neginf: -.inf",
86                 map[string]interface{}{"neginf": math.Inf(-1)},
87         }, {
88                 "fixed: 685_230.15",
89                 map[string]float64{"fixed": 685230.15},
90         },
91         //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported
92         //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails.
93
94         // Bools from spec
95         {
96                 "canonical: y",
97                 map[string]interface{}{"canonical": true},
98         }, {
99                 "answer: NO",
100                 map[string]interface{}{"answer": false},
101         }, {
102                 "logical: True",
103                 map[string]interface{}{"logical": true},
104         }, {
105                 "option: on",
106                 map[string]interface{}{"option": true},
107         }, {
108                 "option: on",
109                 map[string]bool{"option": true},
110         },
111         // Ints from spec
112         {
113                 "canonical: 685230",
114                 map[string]interface{}{"canonical": 685230},
115         }, {
116                 "decimal: +685_230",
117                 map[string]interface{}{"decimal": 685230},
118         }, {
119                 "octal: 02472256",
120                 map[string]interface{}{"octal": 685230},
121         }, {
122                 "hexa: 0x_0A_74_AE",
123                 map[string]interface{}{"hexa": 685230},
124         }, {
125                 "bin: 0b1010_0111_0100_1010_1110",
126                 map[string]interface{}{"bin": 685230},
127         }, {
128                 "bin: -0b101010",
129                 map[string]interface{}{"bin": -42},
130         }, {
131                 "decimal: +685_230",
132                 map[string]int{"decimal": 685230},
133         },
134
135         //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported
136
137         // Nulls from spec
138         {
139                 "empty:",
140                 map[string]interface{}{"empty": nil},
141         }, {
142                 "canonical: ~",
143                 map[string]interface{}{"canonical": nil},
144         }, {
145                 "english: null",
146                 map[string]interface{}{"english": nil},
147         }, {
148                 "~: null key",
149                 map[interface{}]string{nil: "null key"},
150         }, {
151                 "empty:",
152                 map[string]*bool{"empty": nil},
153         },
154
155         // Flow sequence
156         {
157                 "seq: [A,B]",
158                 map[string]interface{}{"seq": []interface{}{"A", "B"}},
159         }, {
160                 "seq: [A,B,C,]",
161                 map[string][]string{"seq": []string{"A", "B", "C"}},
162         }, {
163                 "seq: [A,1,C]",
164                 map[string][]string{"seq": []string{"A", "1", "C"}},
165         }, {
166                 "seq: [A,1,C]",
167                 map[string][]int{"seq": []int{1}},
168         }, {
169                 "seq: [A,1,C]",
170                 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
171         },
172         // Block sequence
173         {
174                 "seq:\n - A\n - B",
175                 map[string]interface{}{"seq": []interface{}{"A", "B"}},
176         }, {
177                 "seq:\n - A\n - B\n - C",
178                 map[string][]string{"seq": []string{"A", "B", "C"}},
179         }, {
180                 "seq:\n - A\n - 1\n - C",
181                 map[string][]string{"seq": []string{"A", "1", "C"}},
182         }, {
183                 "seq:\n - A\n - 1\n - C",
184                 map[string][]int{"seq": []int{1}},
185         }, {
186                 "seq:\n - A\n - 1\n - C",
187                 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
188         },
189
190         // Literal block scalar
191         {
192                 "scalar: | # Comment\n\n literal\n\n \ttext\n\n",
193                 map[string]string{"scalar": "\nliteral\n\n\ttext\n"},
194         },
195
196         // Folded block scalar
197         {
198                 "scalar: > # Comment\n\n folded\n line\n \n next\n line\n  * one\n  * two\n\n last\n line\n\n",
199                 map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"},
200         },
201
202         // Map inside interface with no type hints.
203         {
204                 "a: {b: c}",
205                 map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
206         },
207
208         // Structs and type conversions.
209         {
210                 "hello: world",
211                 &struct{ Hello string }{"world"},
212         }, {
213                 "a: {b: c}",
214                 &struct{ A struct{ B string } }{struct{ B string }{"c"}},
215         }, {
216                 "a: {b: c}",
217                 &struct{ A *struct{ B string } }{&struct{ B string }{"c"}},
218         }, {
219                 "a: {b: c}",
220                 &struct{ A map[string]string }{map[string]string{"b": "c"}},
221         }, {
222                 "a: {b: c}",
223                 &struct{ A *map[string]string }{&map[string]string{"b": "c"}},
224         }, {
225                 "a:",
226                 &struct{ A map[string]string }{},
227         }, {
228                 "a: 1",
229                 &struct{ A int }{1},
230         }, {
231                 "a: 1",
232                 &struct{ A float64 }{1},
233         }, {
234                 "a: 1.0",
235                 &struct{ A int }{1},
236         }, {
237                 "a: 1.0",
238                 &struct{ A uint }{1},
239         }, {
240                 "a: [1, 2]",
241                 &struct{ A []int }{[]int{1, 2}},
242         }, {
243                 "a: 1",
244                 &struct{ B int }{0},
245         }, {
246                 "a: 1",
247                 &struct {
248                         B int "a"
249                 }{1},
250         }, {
251                 "a: y",
252                 &struct{ A bool }{true},
253         },
254
255         // Some cross type conversions
256         {
257                 "v: 42",
258                 map[string]uint{"v": 42},
259         }, {
260                 "v: -42",
261                 map[string]uint{},
262         }, {
263                 "v: 4294967296",
264                 map[string]uint64{"v": 4294967296},
265         }, {
266                 "v: -4294967296",
267                 map[string]uint64{},
268         },
269
270         // int
271         {
272                 "int_max: 2147483647",
273                 map[string]int{"int_max": math.MaxInt32},
274         },
275         {
276                 "int_min: -2147483648",
277                 map[string]int{"int_min": math.MinInt32},
278         },
279         {
280                 "int_overflow: 9223372036854775808", // math.MaxInt64 + 1
281                 map[string]int{},
282         },
283
284         // int64
285         {
286                 "int64_max: 9223372036854775807",
287                 map[string]int64{"int64_max": math.MaxInt64},
288         },
289         {
290                 "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
291                 map[string]int64{"int64_max_base2": math.MaxInt64},
292         },
293         {
294                 "int64_min: -9223372036854775808",
295                 map[string]int64{"int64_min": math.MinInt64},
296         },
297         {
298                 "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
299                 map[string]int64{"int64_neg_base2": -math.MaxInt64},
300         },
301         {
302                 "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
303                 map[string]int64{},
304         },
305
306         // uint
307         {
308                 "uint_min: 0",
309                 map[string]uint{"uint_min": 0},
310         },
311         {
312                 "uint_max: 4294967295",
313                 map[string]uint{"uint_max": math.MaxUint32},
314         },
315         {
316                 "uint_underflow: -1",
317                 map[string]uint{},
318         },
319
320         // uint64
321         {
322                 "uint64_min: 0",
323                 map[string]uint{"uint64_min": 0},
324         },
325         {
326                 "uint64_max: 18446744073709551615",
327                 map[string]uint64{"uint64_max": math.MaxUint64},
328         },
329         {
330                 "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
331                 map[string]uint64{"uint64_max_base2": math.MaxUint64},
332         },
333         {
334                 "uint64_maxint64: 9223372036854775807",
335                 map[string]uint64{"uint64_maxint64": math.MaxInt64},
336         },
337         {
338                 "uint64_underflow: -1",
339                 map[string]uint64{},
340         },
341
342         // float32
343         {
344                 "float32_max: 3.40282346638528859811704183484516925440e+38",
345                 map[string]float32{"float32_max": math.MaxFloat32},
346         },
347         {
348                 "float32_nonzero: 1.401298464324817070923729583289916131280e-45",
349                 map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32},
350         },
351         {
352                 "float32_maxuint64: 18446744073709551615",
353                 map[string]float32{"float32_maxuint64": float32(math.MaxUint64)},
354         },
355         {
356                 "float32_maxuint64+1: 18446744073709551616",
357                 map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)},
358         },
359
360         // float64
361         {
362                 "float64_max: 1.797693134862315708145274237317043567981e+308",
363                 map[string]float64{"float64_max": math.MaxFloat64},
364         },
365         {
366                 "float64_nonzero: 4.940656458412465441765687928682213723651e-324",
367                 map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64},
368         },
369         {
370                 "float64_maxuint64: 18446744073709551615",
371                 map[string]float64{"float64_maxuint64": float64(math.MaxUint64)},
372         },
373         {
374                 "float64_maxuint64+1: 18446744073709551616",
375                 map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)},
376         },
377
378         // Overflow cases.
379         {
380                 "v: 4294967297",
381                 map[string]int32{},
382         }, {
383                 "v: 128",
384                 map[string]int8{},
385         },
386
387         // Quoted values.
388         {
389                 "'1': '\"2\"'",
390                 map[interface{}]interface{}{"1": "\"2\""},
391         }, {
392                 "v:\n- A\n- 'B\n\n  C'\n",
393                 map[string][]string{"v": []string{"A", "B\nC"}},
394         },
395
396         // Explicit tags.
397         {
398                 "v: !!float '1.1'",
399                 map[string]interface{}{"v": 1.1},
400         }, {
401                 "v: !!null ''",
402                 map[string]interface{}{"v": nil},
403         }, {
404                 "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
405                 map[string]interface{}{"v": 1},
406         },
407
408         // Anchors and aliases.
409         {
410                 "a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
411                 &struct{ A, B, C, D int }{1, 2, 1, 2},
412         }, {
413                 "a: &a {c: 1}\nb: *a",
414                 &struct {
415                         A, B struct {
416                                 C int
417                         }
418                 }{struct{ C int }{1}, struct{ C int }{1}},
419         }, {
420                 "a: &a [1, 2]\nb: *a",
421                 &struct{ B []int }{[]int{1, 2}},
422         }, {
423                 "b: *a\na: &a {c: 1}",
424                 &struct {
425                         A, B struct {
426                                 C int
427                         }
428                 }{struct{ C int }{1}, struct{ C int }{1}},
429         },
430
431         // Bug #1133337
432         {
433                 "foo: ''",
434                 map[string]*string{"foo": new(string)},
435         }, {
436                 "foo: null",
437                 map[string]string{"foo": ""},
438         }, {
439                 "foo: null",
440                 map[string]interface{}{"foo": nil},
441         },
442
443         // Ignored field
444         {
445                 "a: 1\nb: 2\n",
446                 &struct {
447                         A int
448                         B int "-"
449                 }{1, 0},
450         },
451
452         // Bug #1191981
453         {
454                 "" +
455                         "%YAML 1.1\n" +
456                         "--- !!str\n" +
457                         `"Generic line break (no glyph)\n\` + "\n" +
458                         ` Generic line break (glyphed)\n\` + "\n" +
459                         ` Line separator\u2028\` + "\n" +
460                         ` Paragraph separator\u2029"` + "\n",
461                 "" +
462                         "Generic line break (no glyph)\n" +
463                         "Generic line break (glyphed)\n" +
464                         "Line separator\u2028Paragraph separator\u2029",
465         },
466
467         // Struct inlining
468         {
469                 "a: 1\nb: 2\nc: 3\n",
470                 &struct {
471                         A int
472                         C inlineB `yaml:",inline"`
473                 }{1, inlineB{2, inlineC{3}}},
474         },
475
476         // Map inlining
477         {
478                 "a: 1\nb: 2\nc: 3\n",
479                 &struct {
480                         A int
481                         C map[string]int `yaml:",inline"`
482                 }{1, map[string]int{"b": 2, "c": 3}},
483         },
484
485         // bug 1243827
486         {
487                 "a: -b_c",
488                 map[string]interface{}{"a": "-b_c"},
489         },
490         {
491                 "a: +b_c",
492                 map[string]interface{}{"a": "+b_c"},
493         },
494         {
495                 "a: 50cent_of_dollar",
496                 map[string]interface{}{"a": "50cent_of_dollar"},
497         },
498
499         // Duration
500         {
501                 "a: 3s",
502                 map[string]time.Duration{"a": 3 * time.Second},
503         },
504
505         // Issue #24.
506         {
507                 "a: <foo>",
508                 map[string]string{"a": "<foo>"},
509         },
510
511         // Base 60 floats are obsolete and unsupported.
512         {
513                 "a: 1:1\n",
514                 map[string]string{"a": "1:1"},
515         },
516
517         // Binary data.
518         {
519                 "a: !!binary gIGC\n",
520                 map[string]string{"a": "\x80\x81\x82"},
521         }, {
522                 "a: !!binary |\n  " + strings.Repeat("kJCQ", 17) + "kJ\n  CQ\n",
523                 map[string]string{"a": strings.Repeat("\x90", 54)},
524         }, {
525                 "a: !!binary |\n  " + strings.Repeat("A", 70) + "\n  ==\n",
526                 map[string]string{"a": strings.Repeat("\x00", 52)},
527         },
528
529         // Ordered maps.
530         {
531                 "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
532                 &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
533         },
534
535         // Issue #39.
536         {
537                 "a:\n b:\n  c: d\n",
538                 map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}},
539         },
540
541         // Custom map type.
542         {
543                 "a: {b: c}",
544                 M{"a": M{"b": "c"}},
545         },
546
547         // Support encoding.TextUnmarshaler.
548         {
549                 "a: 1.2.3.4\n",
550                 map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)},
551         },
552         {
553                 "a: 2015-02-24T18:19:39Z\n",
554                 map[string]time.Time{"a": time.Unix(1424801979, 0).In(time.UTC)},
555         },
556
557         // Encode empty lists as zero-length slices.
558         {
559                 "a: []",
560                 &struct{ A []int }{[]int{}},
561         },
562
563         // UTF-16-LE
564         {
565                 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00",
566                 M{"ñoño": "very yes"},
567         },
568         // UTF-16-LE with surrogate.
569         {
570                 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00",
571                 M{"ñoño": "very yes ðŸŸ”"},
572         },
573
574         // UTF-16-BE
575         {
576                 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n",
577                 M{"ñoño": "very yes"},
578         },
579         // UTF-16-BE with surrogate.
580         {
581                 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n",
582                 M{"ñoño": "very yes ðŸŸ”"},
583         },
584
585         // YAML Float regex shouldn't match this
586         {
587                 "a: 123456e1\n",
588                 M{"a": "123456e1"},
589         }, {
590                 "a: 123456E1\n",
591                 M{"a": "123456E1"},
592         },
593 }
594
595 type M map[interface{}]interface{}
596
597 type inlineB struct {
598         B       int
599         inlineC `yaml:",inline"`
600 }
601
602 type inlineC struct {
603         C int
604 }
605
606 func (s *S) TestUnmarshal(c *C) {
607         for _, item := range unmarshalTests {
608                 t := reflect.ValueOf(item.value).Type()
609                 var value interface{}
610                 switch t.Kind() {
611                 case reflect.Map:
612                         value = reflect.MakeMap(t).Interface()
613                 case reflect.String:
614                         value = reflect.New(t).Interface()
615                 case reflect.Ptr:
616                         value = reflect.New(t.Elem()).Interface()
617                 default:
618                         c.Fatalf("missing case for %s", t)
619                 }
620                 err := yaml.Unmarshal([]byte(item.data), value)
621                 if _, ok := err.(*yaml.TypeError); !ok {
622                         c.Assert(err, IsNil)
623                 }
624                 if t.Kind() == reflect.String {
625                         c.Assert(*value.(*string), Equals, item.value)
626                 } else {
627                         c.Assert(value, DeepEquals, item.value)
628                 }
629         }
630 }
631
632 func (s *S) TestUnmarshalNaN(c *C) {
633         value := map[string]interface{}{}
634         err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
635         c.Assert(err, IsNil)
636         c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
637 }
638
639 var unmarshalErrorTests = []struct {
640         data, error string
641 }{
642         {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"},
643         {"v: [A,", "yaml: line 1: did not find expected node content"},
644         {"v:\n- [A,", "yaml: line 2: did not find expected node content"},
645         {"a: *b\n", "yaml: unknown anchor 'b' referenced"},
646         {"a: &a\n  b: *a\n", "yaml: anchor 'a' value contains itself"},
647         {"value: -", "yaml: block sequence entries are not allowed in this context"},
648         {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"},
649         {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`},
650         {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
651 }
652
653 func (s *S) TestUnmarshalErrors(c *C) {
654         for _, item := range unmarshalErrorTests {
655                 var value interface{}
656                 err := yaml.Unmarshal([]byte(item.data), &value)
657                 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
658         }
659 }
660
661 var unmarshalerTests = []struct {
662         data, tag string
663         value     interface{}
664 }{
665         {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}},
666         {"_: [1,A]", "!!seq", []interface{}{1, "A"}},
667         {"_: 10", "!!int", 10},
668         {"_: null", "!!null", nil},
669         {`_: BAR!`, "!!str", "BAR!"},
670         {`_: "BAR!"`, "!!str", "BAR!"},
671         {"_: !!foo 'BAR!'", "!!foo", "BAR!"},
672         {`_: ""`, "!!str", ""},
673 }
674
675 var unmarshalerResult = map[int]error{}
676
677 type unmarshalerType struct {
678         value interface{}
679 }
680
681 func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error {
682         if err := unmarshal(&o.value); err != nil {
683                 return err
684         }
685         if i, ok := o.value.(int); ok {
686                 if result, ok := unmarshalerResult[i]; ok {
687                         return result
688                 }
689         }
690         return nil
691 }
692
693 type unmarshalerPointer struct {
694         Field *unmarshalerType "_"
695 }
696
697 type unmarshalerValue struct {
698         Field unmarshalerType "_"
699 }
700
701 func (s *S) TestUnmarshalerPointerField(c *C) {
702         for _, item := range unmarshalerTests {
703                 obj := &unmarshalerPointer{}
704                 err := yaml.Unmarshal([]byte(item.data), obj)
705                 c.Assert(err, IsNil)
706                 if item.value == nil {
707                         c.Assert(obj.Field, IsNil)
708                 } else {
709                         c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
710                         c.Assert(obj.Field.value, DeepEquals, item.value)
711                 }
712         }
713 }
714
715 func (s *S) TestUnmarshalerValueField(c *C) {
716         for _, item := range unmarshalerTests {
717                 obj := &unmarshalerValue{}
718                 err := yaml.Unmarshal([]byte(item.data), obj)
719                 c.Assert(err, IsNil)
720                 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
721                 c.Assert(obj.Field.value, DeepEquals, item.value)
722         }
723 }
724
725 func (s *S) TestUnmarshalerWholeDocument(c *C) {
726         obj := &unmarshalerType{}
727         err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj)
728         c.Assert(err, IsNil)
729         value, ok := obj.value.(map[interface{}]interface{})
730         c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value))
731         c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value)
732 }
733
734 func (s *S) TestUnmarshalerTypeError(c *C) {
735         unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
736         unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
737         defer func() {
738                 delete(unmarshalerResult, 2)
739                 delete(unmarshalerResult, 4)
740         }()
741
742         type T struct {
743                 Before int
744                 After  int
745                 M      map[string]*unmarshalerType
746         }
747         var v T
748         data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
749         err := yaml.Unmarshal([]byte(data), &v)
750         c.Assert(err, ErrorMatches, ""+
751                 "yaml: unmarshal errors:\n"+
752                 "  line 1: cannot unmarshal !!str `A` into int\n"+
753                 "  foo\n"+
754                 "  bar\n"+
755                 "  line 1: cannot unmarshal !!str `B` into int")
756         c.Assert(v.M["abc"], NotNil)
757         c.Assert(v.M["def"], IsNil)
758         c.Assert(v.M["ghi"], NotNil)
759         c.Assert(v.M["jkl"], IsNil)
760
761         c.Assert(v.M["abc"].value, Equals, 1)
762         c.Assert(v.M["ghi"].value, Equals, 3)
763 }
764
765 type proxyTypeError struct{}
766
767 func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error {
768         var s string
769         var a int32
770         var b int64
771         if err := unmarshal(&s); err != nil {
772                 panic(err)
773         }
774         if s == "a" {
775                 if err := unmarshal(&b); err == nil {
776                         panic("should have failed")
777                 }
778                 return unmarshal(&a)
779         }
780         if err := unmarshal(&a); err == nil {
781                 panic("should have failed")
782         }
783         return unmarshal(&b)
784 }
785
786 func (s *S) TestUnmarshalerTypeErrorProxying(c *C) {
787         type T struct {
788                 Before int
789                 After  int
790                 M      map[string]*proxyTypeError
791         }
792         var v T
793         data := `{before: A, m: {abc: a, def: b}, after: B}`
794         err := yaml.Unmarshal([]byte(data), &v)
795         c.Assert(err, ErrorMatches, ""+
796                 "yaml: unmarshal errors:\n"+
797                 "  line 1: cannot unmarshal !!str `A` into int\n"+
798                 "  line 1: cannot unmarshal !!str `a` into int32\n"+
799                 "  line 1: cannot unmarshal !!str `b` into int64\n"+
800                 "  line 1: cannot unmarshal !!str `B` into int")
801 }
802
803 type failingUnmarshaler struct{}
804
805 var failingErr = errors.New("failingErr")
806
807 func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
808         return failingErr
809 }
810
811 func (s *S) TestUnmarshalerError(c *C) {
812         err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{})
813         c.Assert(err, Equals, failingErr)
814 }
815
816 type sliceUnmarshaler []int
817
818 func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
819         var slice []int
820         err := unmarshal(&slice)
821         if err == nil {
822                 *su = slice
823                 return nil
824         }
825
826         var intVal int
827         err = unmarshal(&intVal)
828         if err == nil {
829                 *su = []int{intVal}
830                 return nil
831         }
832
833         return err
834 }
835
836 func (s *S) TestUnmarshalerRetry(c *C) {
837         var su sliceUnmarshaler
838         err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
839         c.Assert(err, IsNil)
840         c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3}))
841
842         err = yaml.Unmarshal([]byte("1"), &su)
843         c.Assert(err, IsNil)
844         c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1}))
845 }
846
847 // From http://yaml.org/type/merge.html
848 var mergeTests = `
849 anchors:
850   list:
851     - &CENTER { "x": 1, "y": 2 }
852     - &LEFT   { "x": 0, "y": 2 }
853     - &BIG    { "r": 10 }
854     - &SMALL  { "r": 1 }
855
856 # All the following maps are equal:
857
858 plain:
859   # Explicit keys
860   "x": 1
861   "y": 2
862   "r": 10
863   label: center/big
864
865 mergeOne:
866   # Merge one map
867   << : *CENTER
868   "r": 10
869   label: center/big
870
871 mergeMultiple:
872   # Merge multiple maps
873   << : [ *CENTER, *BIG ]
874   label: center/big
875
876 override:
877   # Override
878   << : [ *BIG, *LEFT, *SMALL ]
879   "x": 1
880   label: center/big
881
882 shortTag:
883   # Explicit short merge tag
884   !!merge "<<" : [ *CENTER, *BIG ]
885   label: center/big
886
887 longTag:
888   # Explicit merge long tag
889   !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
890   label: center/big
891
892 inlineMap:
893   # Inlined map 
894   << : {"x": 1, "y": 2, "r": 10}
895   label: center/big
896
897 inlineSequenceMap:
898   # Inlined map in sequence
899   << : [ *CENTER, {"r": 10} ]
900   label: center/big
901 `
902
903 func (s *S) TestMerge(c *C) {
904         var want = map[interface{}]interface{}{
905                 "x":     1,
906                 "y":     2,
907                 "r":     10,
908                 "label": "center/big",
909         }
910
911         var m map[interface{}]interface{}
912         err := yaml.Unmarshal([]byte(mergeTests), &m)
913         c.Assert(err, IsNil)
914         for name, test := range m {
915                 if name == "anchors" {
916                         continue
917                 }
918                 c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
919         }
920 }
921
922 func (s *S) TestMergeStruct(c *C) {
923         type Data struct {
924                 X, Y, R int
925                 Label   string
926         }
927         want := Data{1, 2, 10, "center/big"}
928
929         var m map[string]Data
930         err := yaml.Unmarshal([]byte(mergeTests), &m)
931         c.Assert(err, IsNil)
932         for name, test := range m {
933                 if name == "anchors" {
934                         continue
935                 }
936                 c.Assert(test, Equals, want, Commentf("test %q failed", name))
937         }
938 }
939
940 var unmarshalNullTests = []func() interface{}{
941         func() interface{} { var v interface{}; v = "v"; return &v },
942         func() interface{} { var s = "s"; return &s },
943         func() interface{} { var s = "s"; sptr := &s; return &sptr },
944         func() interface{} { var i = 1; return &i },
945         func() interface{} { var i = 1; iptr := &i; return &iptr },
946         func() interface{} { m := map[string]int{"s": 1}; return &m },
947         func() interface{} { m := map[string]int{"s": 1}; return m },
948 }
949
950 func (s *S) TestUnmarshalNull(c *C) {
951         for _, test := range unmarshalNullTests {
952                 item := test()
953                 zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface()
954                 err := yaml.Unmarshal([]byte("null"), item)
955                 c.Assert(err, IsNil)
956                 if reflect.TypeOf(item).Kind() == reflect.Map {
957                         c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface())
958                 } else {
959                         c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero)
960                 }
961         }
962 }
963
964 func (s *S) TestUnmarshalSliceOnPreset(c *C) {
965         // Issue #48.
966         v := struct{ A []int }{[]int{1}}
967         yaml.Unmarshal([]byte("a: [2]"), &v)
968         c.Assert(v.A, DeepEquals, []int{2})
969 }
970
971 //var data []byte
972 //func init() {
973 //      var err error
974 //      data, err = ioutil.ReadFile("/tmp/file.yaml")
975 //      if err != nil {
976 //              panic(err)
977 //      }
978 //}
979 //
980 //func (s *S) BenchmarkUnmarshal(c *C) {
981 //      var err error
982 //      for i := 0; i < c.N; i++ {
983 //              var v map[string]interface{}
984 //              err = yaml.Unmarshal(data, &v)
985 //      }
986 //      if err != nil {
987 //              panic(err)
988 //      }
989 //}
990 //
991 //func (s *S) BenchmarkMarshal(c *C) {
992 //      var v map[string]interface{}
993 //      yaml.Unmarshal(data, &v)
994 //      c.ResetTimer()
995 //      for i := 0; i < c.N; i++ {
996 //              yaml.Marshal(&v)
997 //      }
998 //}