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