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