OSDN Git Service

new repo
[bytom/vapor.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         // Non-specific tag (Issue #75)
409         {
410                 "v: ! test",
411                 map[string]interface{}{"v": "test"},
412         },
413
414         // Anchors and aliases.
415         {
416                 "a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
417                 &struct{ A, B, C, D int }{1, 2, 1, 2},
418         }, {
419                 "a: &a {c: 1}\nb: *a",
420                 &struct {
421                         A, B struct {
422                                 C int
423                         }
424                 }{struct{ C int }{1}, struct{ C int }{1}},
425         }, {
426                 "a: &a [1, 2]\nb: *a",
427                 &struct{ B []int }{[]int{1, 2}},
428         }, {
429                 "b: *a\na: &a {c: 1}",
430                 &struct {
431                         A, B struct {
432                                 C int
433                         }
434                 }{struct{ C int }{1}, struct{ C int }{1}},
435         },
436
437         // Bug #1133337
438         {
439                 "foo: ''",
440                 map[string]*string{"foo": new(string)},
441         }, {
442                 "foo: null",
443                 map[string]string{"foo": ""},
444         }, {
445                 "foo: null",
446                 map[string]interface{}{"foo": nil},
447         },
448
449         // Ignored field
450         {
451                 "a: 1\nb: 2\n",
452                 &struct {
453                         A int
454                         B int "-"
455                 }{1, 0},
456         },
457
458         // Bug #1191981
459         {
460                 "" +
461                         "%YAML 1.1\n" +
462                         "--- !!str\n" +
463                         `"Generic line break (no glyph)\n\` + "\n" +
464                         ` Generic line break (glyphed)\n\` + "\n" +
465                         ` Line separator\u2028\` + "\n" +
466                         ` Paragraph separator\u2029"` + "\n",
467                 "" +
468                         "Generic line break (no glyph)\n" +
469                         "Generic line break (glyphed)\n" +
470                         "Line separator\u2028Paragraph separator\u2029",
471         },
472
473         // Struct inlining
474         {
475                 "a: 1\nb: 2\nc: 3\n",
476                 &struct {
477                         A int
478                         C inlineB `yaml:",inline"`
479                 }{1, inlineB{2, inlineC{3}}},
480         },
481
482         // Map inlining
483         {
484                 "a: 1\nb: 2\nc: 3\n",
485                 &struct {
486                         A int
487                         C map[string]int `yaml:",inline"`
488                 }{1, map[string]int{"b": 2, "c": 3}},
489         },
490
491         // bug 1243827
492         {
493                 "a: -b_c",
494                 map[string]interface{}{"a": "-b_c"},
495         },
496         {
497                 "a: +b_c",
498                 map[string]interface{}{"a": "+b_c"},
499         },
500         {
501                 "a: 50cent_of_dollar",
502                 map[string]interface{}{"a": "50cent_of_dollar"},
503         },
504
505         // Duration
506         {
507                 "a: 3s",
508                 map[string]time.Duration{"a": 3 * time.Second},
509         },
510
511         // Issue #24.
512         {
513                 "a: <foo>",
514                 map[string]string{"a": "<foo>"},
515         },
516
517         // Base 60 floats are obsolete and unsupported.
518         {
519                 "a: 1:1\n",
520                 map[string]string{"a": "1:1"},
521         },
522
523         // Binary data.
524         {
525                 "a: !!binary gIGC\n",
526                 map[string]string{"a": "\x80\x81\x82"},
527         }, {
528                 "a: !!binary |\n  " + strings.Repeat("kJCQ", 17) + "kJ\n  CQ\n",
529                 map[string]string{"a": strings.Repeat("\x90", 54)},
530         }, {
531                 "a: !!binary |\n  " + strings.Repeat("A", 70) + "\n  ==\n",
532                 map[string]string{"a": strings.Repeat("\x00", 52)},
533         },
534
535         // Ordered maps.
536         {
537                 "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
538                 &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
539         },
540
541         // Issue #39.
542         {
543                 "a:\n b:\n  c: d\n",
544                 map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}},
545         },
546
547         // Custom map type.
548         {
549                 "a: {b: c}",
550                 M{"a": M{"b": "c"}},
551         },
552
553         // Support encoding.TextUnmarshaler.
554         {
555                 "a: 1.2.3.4\n",
556                 map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)},
557         },
558         {
559                 "a: 2015-02-24T18:19:39Z\n",
560                 map[string]time.Time{"a": time.Unix(1424801979, 0).In(time.UTC)},
561         },
562
563         // Encode empty lists as zero-length slices.
564         {
565                 "a: []",
566                 &struct{ A []int }{[]int{}},
567         },
568
569         // UTF-16-LE
570         {
571                 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00",
572                 M{"ñoño": "very yes"},
573         },
574         // UTF-16-LE with surrogate.
575         {
576                 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00",
577                 M{"ñoño": "very yes ðŸŸ”"},
578         },
579
580         // UTF-16-BE
581         {
582                 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n",
583                 M{"ñoño": "very yes"},
584         },
585         // UTF-16-BE with surrogate.
586         {
587                 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n",
588                 M{"ñoño": "very yes ðŸŸ”"},
589         },
590
591         // YAML Float regex shouldn't match this
592         {
593                 "a: 123456e1\n",
594                 M{"a": "123456e1"},
595         }, {
596                 "a: 123456E1\n",
597                 M{"a": "123456E1"},
598         },
599 }
600
601 type M map[interface{}]interface{}
602
603 type inlineB struct {
604         B       int
605         inlineC `yaml:",inline"`
606 }
607
608 type inlineC struct {
609         C int
610 }
611
612 func (s *S) TestUnmarshal(c *C) {
613         for i, item := range unmarshalTests {
614                 c.Logf("test %d: %q", i, item.data)
615                 t := reflect.ValueOf(item.value).Type()
616                 var value interface{}
617                 switch t.Kind() {
618                 case reflect.Map:
619                         value = reflect.MakeMap(t).Interface()
620                 case reflect.String:
621                         value = reflect.New(t).Interface()
622                 case reflect.Ptr:
623                         value = reflect.New(t.Elem()).Interface()
624                 default:
625                         c.Fatalf("missing case for %s", t)
626                 }
627                 err := yaml.Unmarshal([]byte(item.data), value)
628                 if _, ok := err.(*yaml.TypeError); !ok {
629                         c.Assert(err, IsNil)
630                 }
631                 if t.Kind() == reflect.String {
632                         c.Assert(*value.(*string), Equals, item.value)
633                 } else {
634                         c.Assert(value, DeepEquals, item.value)
635                 }
636         }
637 }
638
639 func (s *S) TestUnmarshalNaN(c *C) {
640         value := map[string]interface{}{}
641         err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
642         c.Assert(err, IsNil)
643         c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
644 }
645
646 var unmarshalErrorTests = []struct {
647         data, error string
648 }{
649         {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"},
650         {"v: [A,", "yaml: line 1: did not find expected node content"},
651         {"v:\n- [A,", "yaml: line 2: did not find expected node content"},
652         {"a: *b\n", "yaml: unknown anchor 'b' referenced"},
653         {"a: &a\n  b: *a\n", "yaml: anchor 'a' value contains itself"},
654         {"value: -", "yaml: block sequence entries are not allowed in this context"},
655         {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"},
656         {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`},
657         {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
658         {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"},
659 }
660
661 func (s *S) TestUnmarshalErrors(c *C) {
662         for _, item := range unmarshalErrorTests {
663                 var value interface{}
664                 err := yaml.Unmarshal([]byte(item.data), &value)
665                 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
666         }
667 }
668
669 var unmarshalerTests = []struct {
670         data, tag string
671         value     interface{}
672 }{
673         {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}},
674         {"_: [1,A]", "!!seq", []interface{}{1, "A"}},
675         {"_: 10", "!!int", 10},
676         {"_: null", "!!null", nil},
677         {`_: BAR!`, "!!str", "BAR!"},
678         {`_: "BAR!"`, "!!str", "BAR!"},
679         {"_: !!foo 'BAR!'", "!!foo", "BAR!"},
680         {`_: ""`, "!!str", ""},
681 }
682
683 var unmarshalerResult = map[int]error{}
684
685 type unmarshalerType struct {
686         value interface{}
687 }
688
689 func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error {
690         if err := unmarshal(&o.value); err != nil {
691                 return err
692         }
693         if i, ok := o.value.(int); ok {
694                 if result, ok := unmarshalerResult[i]; ok {
695                         return result
696                 }
697         }
698         return nil
699 }
700
701 type unmarshalerPointer struct {
702         Field *unmarshalerType "_"
703 }
704
705 type unmarshalerValue struct {
706         Field unmarshalerType "_"
707 }
708
709 func (s *S) TestUnmarshalerPointerField(c *C) {
710         for _, item := range unmarshalerTests {
711                 obj := &unmarshalerPointer{}
712                 err := yaml.Unmarshal([]byte(item.data), obj)
713                 c.Assert(err, IsNil)
714                 if item.value == nil {
715                         c.Assert(obj.Field, IsNil)
716                 } else {
717                         c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
718                         c.Assert(obj.Field.value, DeepEquals, item.value)
719                 }
720         }
721 }
722
723 func (s *S) TestUnmarshalerValueField(c *C) {
724         for _, item := range unmarshalerTests {
725                 obj := &unmarshalerValue{}
726                 err := yaml.Unmarshal([]byte(item.data), obj)
727                 c.Assert(err, IsNil)
728                 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
729                 c.Assert(obj.Field.value, DeepEquals, item.value)
730         }
731 }
732
733 func (s *S) TestUnmarshalerWholeDocument(c *C) {
734         obj := &unmarshalerType{}
735         err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj)
736         c.Assert(err, IsNil)
737         value, ok := obj.value.(map[interface{}]interface{})
738         c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value))
739         c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value)
740 }
741
742 func (s *S) TestUnmarshalerTypeError(c *C) {
743         unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
744         unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
745         defer func() {
746                 delete(unmarshalerResult, 2)
747                 delete(unmarshalerResult, 4)
748         }()
749
750         type T struct {
751                 Before int
752                 After  int
753                 M      map[string]*unmarshalerType
754         }
755         var v T
756         data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
757         err := yaml.Unmarshal([]byte(data), &v)
758         c.Assert(err, ErrorMatches, ""+
759                 "yaml: unmarshal errors:\n"+
760                 "  line 1: cannot unmarshal !!str `A` into int\n"+
761                 "  foo\n"+
762                 "  bar\n"+
763                 "  line 1: cannot unmarshal !!str `B` into int")
764         c.Assert(v.M["abc"], NotNil)
765         c.Assert(v.M["def"], IsNil)
766         c.Assert(v.M["ghi"], NotNil)
767         c.Assert(v.M["jkl"], IsNil)
768
769         c.Assert(v.M["abc"].value, Equals, 1)
770         c.Assert(v.M["ghi"].value, Equals, 3)
771 }
772
773 type proxyTypeError struct{}
774
775 func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error {
776         var s string
777         var a int32
778         var b int64
779         if err := unmarshal(&s); err != nil {
780                 panic(err)
781         }
782         if s == "a" {
783                 if err := unmarshal(&b); err == nil {
784                         panic("should have failed")
785                 }
786                 return unmarshal(&a)
787         }
788         if err := unmarshal(&a); err == nil {
789                 panic("should have failed")
790         }
791         return unmarshal(&b)
792 }
793
794 func (s *S) TestUnmarshalerTypeErrorProxying(c *C) {
795         type T struct {
796                 Before int
797                 After  int
798                 M      map[string]*proxyTypeError
799         }
800         var v T
801         data := `{before: A, m: {abc: a, def: b}, after: B}`
802         err := yaml.Unmarshal([]byte(data), &v)
803         c.Assert(err, ErrorMatches, ""+
804                 "yaml: unmarshal errors:\n"+
805                 "  line 1: cannot unmarshal !!str `A` into int\n"+
806                 "  line 1: cannot unmarshal !!str `a` into int32\n"+
807                 "  line 1: cannot unmarshal !!str `b` into int64\n"+
808                 "  line 1: cannot unmarshal !!str `B` into int")
809 }
810
811 type failingUnmarshaler struct{}
812
813 var failingErr = errors.New("failingErr")
814
815 func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
816         return failingErr
817 }
818
819 func (s *S) TestUnmarshalerError(c *C) {
820         err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{})
821         c.Assert(err, Equals, failingErr)
822 }
823
824 type sliceUnmarshaler []int
825
826 func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
827         var slice []int
828         err := unmarshal(&slice)
829         if err == nil {
830                 *su = slice
831                 return nil
832         }
833
834         var intVal int
835         err = unmarshal(&intVal)
836         if err == nil {
837                 *su = []int{intVal}
838                 return nil
839         }
840
841         return err
842 }
843
844 func (s *S) TestUnmarshalerRetry(c *C) {
845         var su sliceUnmarshaler
846         err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
847         c.Assert(err, IsNil)
848         c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3}))
849
850         err = yaml.Unmarshal([]byte("1"), &su)
851         c.Assert(err, IsNil)
852         c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1}))
853 }
854
855 // From http://yaml.org/type/merge.html
856 var mergeTests = `
857 anchors:
858   list:
859     - &CENTER { "x": 1, "y": 2 }
860     - &LEFT   { "x": 0, "y": 2 }
861     - &BIG    { "r": 10 }
862     - &SMALL  { "r": 1 }
863
864 # All the following maps are equal:
865
866 plain:
867   # Explicit keys
868   "x": 1
869   "y": 2
870   "r": 10
871   label: center/big
872
873 mergeOne:
874   # Merge one map
875   << : *CENTER
876   "r": 10
877   label: center/big
878
879 mergeMultiple:
880   # Merge multiple maps
881   << : [ *CENTER, *BIG ]
882   label: center/big
883
884 override:
885   # Override
886   << : [ *BIG, *LEFT, *SMALL ]
887   "x": 1
888   label: center/big
889
890 shortTag:
891   # Explicit short merge tag
892   !!merge "<<" : [ *CENTER, *BIG ]
893   label: center/big
894
895 longTag:
896   # Explicit merge long tag
897   !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
898   label: center/big
899
900 inlineMap:
901   # Inlined map 
902   << : {"x": 1, "y": 2, "r": 10}
903   label: center/big
904
905 inlineSequenceMap:
906   # Inlined map in sequence
907   << : [ *CENTER, {"r": 10} ]
908   label: center/big
909 `
910
911 func (s *S) TestMerge(c *C) {
912         var want = map[interface{}]interface{}{
913                 "x":     1,
914                 "y":     2,
915                 "r":     10,
916                 "label": "center/big",
917         }
918
919         var m map[interface{}]interface{}
920         err := yaml.Unmarshal([]byte(mergeTests), &m)
921         c.Assert(err, IsNil)
922         for name, test := range m {
923                 if name == "anchors" {
924                         continue
925                 }
926                 c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
927         }
928 }
929
930 func (s *S) TestMergeStruct(c *C) {
931         type Data struct {
932                 X, Y, R int
933                 Label   string
934         }
935         want := Data{1, 2, 10, "center/big"}
936
937         var m map[string]Data
938         err := yaml.Unmarshal([]byte(mergeTests), &m)
939         c.Assert(err, IsNil)
940         for name, test := range m {
941                 if name == "anchors" {
942                         continue
943                 }
944                 c.Assert(test, Equals, want, Commentf("test %q failed", name))
945         }
946 }
947
948 var unmarshalNullTests = []func() interface{}{
949         func() interface{} { var v interface{}; v = "v"; return &v },
950         func() interface{} { var s = "s"; return &s },
951         func() interface{} { var s = "s"; sptr := &s; return &sptr },
952         func() interface{} { var i = 1; return &i },
953         func() interface{} { var i = 1; iptr := &i; return &iptr },
954         func() interface{} { m := map[string]int{"s": 1}; return &m },
955         func() interface{} { m := map[string]int{"s": 1}; return m },
956 }
957
958 func (s *S) TestUnmarshalNull(c *C) {
959         for _, test := range unmarshalNullTests {
960                 item := test()
961                 zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface()
962                 err := yaml.Unmarshal([]byte("null"), item)
963                 c.Assert(err, IsNil)
964                 if reflect.TypeOf(item).Kind() == reflect.Map {
965                         c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface())
966                 } else {
967                         c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero)
968                 }
969         }
970 }
971
972 func (s *S) TestUnmarshalSliceOnPreset(c *C) {
973         // Issue #48.
974         v := struct{ A []int }{[]int{1}}
975         yaml.Unmarshal([]byte("a: [2]"), &v)
976         c.Assert(v.A, DeepEquals, []int{2})
977 }
978
979 func (s *S) TestUnmarshalStrict(c *C) {
980         v := struct{ A, B int }{}
981
982         err := yaml.UnmarshalStrict([]byte("a: 1\nb: 2"), &v)
983         c.Check(err, IsNil)
984         err = yaml.Unmarshal([]byte("a: 1\nb: 2\nc: 3"), &v)
985         c.Check(err, IsNil)
986         err = yaml.UnmarshalStrict([]byte("a: 1\nb: 2\nc: 3"), &v)
987         c.Check(err, ErrorMatches, "yaml: unmarshal errors:\n  line 1: field c not found in struct struct { A int; B int }")
988 }
989
990 //var data []byte
991 //func init() {
992 //      var err error
993 //      data, err = ioutil.ReadFile("/tmp/file.yaml")
994 //      if err != nil {
995 //              panic(err)
996 //      }
997 //}
998 //
999 //func (s *S) BenchmarkUnmarshal(c *C) {
1000 //      var err error
1001 //      for i := 0; i < c.N; i++ {
1002 //              var v map[string]interface{}
1003 //              err = yaml.Unmarshal(data, &v)
1004 //      }
1005 //      if err != nil {
1006 //              panic(err)
1007 //      }
1008 //}
1009 //
1010 //func (s *S) BenchmarkMarshal(c *C) {
1011 //      var v map[string]interface{}
1012 //      yaml.Unmarshal(data, &v)
1013 //      c.ResetTimer()
1014 //      for i := 0; i < c.N; i++ {
1015 //              yaml.Marshal(&v)
1016 //      }
1017 //}