704 lines
15 KiB
Go
704 lines
15 KiB
Go
|
package yaml_test
|
||
|
|
||
|
import (
|
||
|
. "gopkg.in/check.v1"
|
||
|
"gopkg.in/yaml.v1"
|
||
|
"math"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
var unmarshalIntTest = 123
|
||
|
|
||
|
var unmarshalTests = []struct {
|
||
|
data string
|
||
|
value interface{}
|
||
|
}{
|
||
|
{
|
||
|
"",
|
||
|
&struct{}{},
|
||
|
}, {
|
||
|
"{}", &struct{}{},
|
||
|
}, {
|
||
|
"v: hi",
|
||
|
map[string]string{"v": "hi"},
|
||
|
}, {
|
||
|
"v: hi", map[string]interface{}{"v": "hi"},
|
||
|
}, {
|
||
|
"v: true",
|
||
|
map[string]string{"v": "true"},
|
||
|
}, {
|
||
|
"v: true",
|
||
|
map[string]interface{}{"v": true},
|
||
|
}, {
|
||
|
"v: 10",
|
||
|
map[string]interface{}{"v": 10},
|
||
|
}, {
|
||
|
"v: 0b10",
|
||
|
map[string]interface{}{"v": 2},
|
||
|
}, {
|
||
|
"v: 0xA",
|
||
|
map[string]interface{}{"v": 10},
|
||
|
}, {
|
||
|
"v: 4294967296",
|
||
|
map[string]int64{"v": 4294967296},
|
||
|
}, {
|
||
|
"v: 0.1",
|
||
|
map[string]interface{}{"v": 0.1},
|
||
|
}, {
|
||
|
"v: .1",
|
||
|
map[string]interface{}{"v": 0.1},
|
||
|
}, {
|
||
|
"v: .Inf",
|
||
|
map[string]interface{}{"v": math.Inf(+1)},
|
||
|
}, {
|
||
|
"v: -.Inf",
|
||
|
map[string]interface{}{"v": math.Inf(-1)},
|
||
|
}, {
|
||
|
"v: -10",
|
||
|
map[string]interface{}{"v": -10},
|
||
|
}, {
|
||
|
"v: -.1",
|
||
|
map[string]interface{}{"v": -0.1},
|
||
|
},
|
||
|
|
||
|
// Simple values.
|
||
|
{
|
||
|
"123",
|
||
|
&unmarshalIntTest,
|
||
|
},
|
||
|
|
||
|
// Floats from spec
|
||
|
{
|
||
|
"canonical: 6.8523e+5",
|
||
|
map[string]interface{}{"canonical": 6.8523e+5},
|
||
|
}, {
|
||
|
"expo: 685.230_15e+03",
|
||
|
map[string]interface{}{"expo": 685.23015e+03},
|
||
|
}, {
|
||
|
"fixed: 685_230.15",
|
||
|
map[string]interface{}{"fixed": 685230.15},
|
||
|
}, {
|
||
|
"neginf: -.inf",
|
||
|
map[string]interface{}{"neginf": math.Inf(-1)},
|
||
|
}, {
|
||
|
"fixed: 685_230.15",
|
||
|
map[string]float64{"fixed": 685230.15},
|
||
|
},
|
||
|
//{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported
|
||
|
//{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails.
|
||
|
|
||
|
// Bools from spec
|
||
|
{
|
||
|
"canonical: y",
|
||
|
map[string]interface{}{"canonical": true},
|
||
|
}, {
|
||
|
"answer: NO",
|
||
|
map[string]interface{}{"answer": false},
|
||
|
}, {
|
||
|
"logical: True",
|
||
|
map[string]interface{}{"logical": true},
|
||
|
}, {
|
||
|
"option: on",
|
||
|
map[string]interface{}{"option": true},
|
||
|
}, {
|
||
|
"option: on",
|
||
|
map[string]bool{"option": true},
|
||
|
},
|
||
|
// Ints from spec
|
||
|
{
|
||
|
"canonical: 685230",
|
||
|
map[string]interface{}{"canonical": 685230},
|
||
|
}, {
|
||
|
"decimal: +685_230",
|
||
|
map[string]interface{}{"decimal": 685230},
|
||
|
}, {
|
||
|
"octal: 02472256",
|
||
|
map[string]interface{}{"octal": 685230},
|
||
|
}, {
|
||
|
"hexa: 0x_0A_74_AE",
|
||
|
map[string]interface{}{"hexa": 685230},
|
||
|
}, {
|
||
|
"bin: 0b1010_0111_0100_1010_1110",
|
||
|
map[string]interface{}{"bin": 685230},
|
||
|
}, {
|
||
|
"bin: -0b101010",
|
||
|
map[string]interface{}{"bin": -42},
|
||
|
}, {
|
||
|
"decimal: +685_230",
|
||
|
map[string]int{"decimal": 685230},
|
||
|
},
|
||
|
|
||
|
//{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported
|
||
|
|
||
|
// Nulls from spec
|
||
|
{
|
||
|
"empty:",
|
||
|
map[string]interface{}{"empty": nil},
|
||
|
}, {
|
||
|
"canonical: ~",
|
||
|
map[string]interface{}{"canonical": nil},
|
||
|
}, {
|
||
|
"english: null",
|
||
|
map[string]interface{}{"english": nil},
|
||
|
}, {
|
||
|
"~: null key",
|
||
|
map[interface{}]string{nil: "null key"},
|
||
|
}, {
|
||
|
"empty:",
|
||
|
map[string]*bool{"empty": nil},
|
||
|
},
|
||
|
|
||
|
// Flow sequence
|
||
|
{
|
||
|
"seq: [A,B]",
|
||
|
map[string]interface{}{"seq": []interface{}{"A", "B"}},
|
||
|
}, {
|
||
|
"seq: [A,B,C,]",
|
||
|
map[string][]string{"seq": []string{"A", "B", "C"}},
|
||
|
}, {
|
||
|
"seq: [A,1,C]",
|
||
|
map[string][]string{"seq": []string{"A", "1", "C"}},
|
||
|
}, {
|
||
|
"seq: [A,1,C]",
|
||
|
map[string][]int{"seq": []int{1}},
|
||
|
}, {
|
||
|
"seq: [A,1,C]",
|
||
|
map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
|
||
|
},
|
||
|
// Block sequence
|
||
|
{
|
||
|
"seq:\n - A\n - B",
|
||
|
map[string]interface{}{"seq": []interface{}{"A", "B"}},
|
||
|
}, {
|
||
|
"seq:\n - A\n - B\n - C",
|
||
|
map[string][]string{"seq": []string{"A", "B", "C"}},
|
||
|
}, {
|
||
|
"seq:\n - A\n - 1\n - C",
|
||
|
map[string][]string{"seq": []string{"A", "1", "C"}},
|
||
|
}, {
|
||
|
"seq:\n - A\n - 1\n - C",
|
||
|
map[string][]int{"seq": []int{1}},
|
||
|
}, {
|
||
|
"seq:\n - A\n - 1\n - C",
|
||
|
map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
|
||
|
},
|
||
|
|
||
|
// Literal block scalar
|
||
|
{
|
||
|
"scalar: | # Comment\n\n literal\n\n \ttext\n\n",
|
||
|
map[string]string{"scalar": "\nliteral\n\n\ttext\n"},
|
||
|
},
|
||
|
|
||
|
// Folded block scalar
|
||
|
{
|
||
|
"scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n",
|
||
|
map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"},
|
||
|
},
|
||
|
|
||
|
// Map inside interface with no type hints.
|
||
|
{
|
||
|
"a: {b: c}",
|
||
|
map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
|
||
|
},
|
||
|
|
||
|
// Structs and type conversions.
|
||
|
{
|
||
|
"hello: world",
|
||
|
&struct{ Hello string }{"world"},
|
||
|
}, {
|
||
|
"a: {b: c}",
|
||
|
&struct{ A struct{ B string } }{struct{ B string }{"c"}},
|
||
|
}, {
|
||
|
"a: {b: c}",
|
||
|
&struct{ A *struct{ B string } }{&struct{ B string }{"c"}},
|
||
|
}, {
|
||
|
"a: {b: c}",
|
||
|
&struct{ A map[string]string }{map[string]string{"b": "c"}},
|
||
|
}, {
|
||
|
"a: {b: c}",
|
||
|
&struct{ A *map[string]string }{&map[string]string{"b": "c"}},
|
||
|
}, {
|
||
|
"a:",
|
||
|
&struct{ A map[string]string }{},
|
||
|
}, {
|
||
|
"a: 1",
|
||
|
&struct{ A int }{1},
|
||
|
}, {
|
||
|
"a: 1",
|
||
|
&struct{ A float64 }{1},
|
||
|
}, {
|
||
|
"a: 1.0",
|
||
|
&struct{ A int }{1},
|
||
|
}, {
|
||
|
"a: 1.0",
|
||
|
&struct{ A uint }{1},
|
||
|
}, {
|
||
|
"a: [1, 2]",
|
||
|
&struct{ A []int }{[]int{1, 2}},
|
||
|
}, {
|
||
|
"a: 1",
|
||
|
&struct{ B int }{0},
|
||
|
}, {
|
||
|
"a: 1",
|
||
|
&struct {
|
||
|
B int "a"
|
||
|
}{1},
|
||
|
}, {
|
||
|
"a: y",
|
||
|
&struct{ A bool }{true},
|
||
|
},
|
||
|
|
||
|
// Some cross type conversions
|
||
|
{
|
||
|
"v: 42",
|
||
|
map[string]uint{"v": 42},
|
||
|
}, {
|
||
|
"v: -42",
|
||
|
map[string]uint{},
|
||
|
}, {
|
||
|
"v: 4294967296",
|
||
|
map[string]uint64{"v": 4294967296},
|
||
|
}, {
|
||
|
"v: -4294967296",
|
||
|
map[string]uint64{},
|
||
|
},
|
||
|
|
||
|
// Overflow cases.
|
||
|
{
|
||
|
"v: 4294967297",
|
||
|
map[string]int32{},
|
||
|
}, {
|
||
|
"v: 128",
|
||
|
map[string]int8{},
|
||
|
},
|
||
|
|
||
|
// Quoted values.
|
||
|
{
|
||
|
"'1': '\"2\"'",
|
||
|
map[interface{}]interface{}{"1": "\"2\""},
|
||
|
}, {
|
||
|
"v:\n- A\n- 'B\n\n C'\n",
|
||
|
map[string][]string{"v": []string{"A", "B\nC"}},
|
||
|
},
|
||
|
|
||
|
// Explicit tags.
|
||
|
{
|
||
|
"v: !!float '1.1'",
|
||
|
map[string]interface{}{"v": 1.1},
|
||
|
}, {
|
||
|
"v: !!null ''",
|
||
|
map[string]interface{}{"v": nil},
|
||
|
}, {
|
||
|
"%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
|
||
|
map[string]interface{}{"v": 1},
|
||
|
},
|
||
|
|
||
|
// Anchors and aliases.
|
||
|
{
|
||
|
"a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
|
||
|
&struct{ A, B, C, D int }{1, 2, 1, 2},
|
||
|
}, {
|
||
|
"a: &a {c: 1}\nb: *a",
|
||
|
&struct {
|
||
|
A, B struct {
|
||
|
C int
|
||
|
}
|
||
|
}{struct{ C int }{1}, struct{ C int }{1}},
|
||
|
}, {
|
||
|
"a: &a [1, 2]\nb: *a",
|
||
|
&struct{ B []int }{[]int{1, 2}},
|
||
|
},
|
||
|
|
||
|
// Bug #1133337
|
||
|
{
|
||
|
"foo: ''",
|
||
|
map[string]*string{"foo": new(string)},
|
||
|
}, {
|
||
|
"foo: null",
|
||
|
map[string]string{"foo": ""},
|
||
|
}, {
|
||
|
"foo: null",
|
||
|
map[string]interface{}{"foo": nil},
|
||
|
},
|
||
|
|
||
|
// Ignored field
|
||
|
{
|
||
|
"a: 1\nb: 2\n",
|
||
|
&struct {
|
||
|
A int
|
||
|
B int "-"
|
||
|
}{1, 0},
|
||
|
},
|
||
|
|
||
|
// Bug #1191981
|
||
|
{
|
||
|
"" +
|
||
|
"%YAML 1.1\n" +
|
||
|
"--- !!str\n" +
|
||
|
`"Generic line break (no glyph)\n\` + "\n" +
|
||
|
` Generic line break (glyphed)\n\` + "\n" +
|
||
|
` Line separator\u2028\` + "\n" +
|
||
|
` Paragraph separator\u2029"` + "\n",
|
||
|
"" +
|
||
|
"Generic line break (no glyph)\n" +
|
||
|
"Generic line break (glyphed)\n" +
|
||
|
"Line separator\u2028Paragraph separator\u2029",
|
||
|
},
|
||
|
|
||
|
// Struct inlining
|
||
|
{
|
||
|
"a: 1\nb: 2\nc: 3\n",
|
||
|
&struct {
|
||
|
A int
|
||
|
C inlineB `yaml:",inline"`
|
||
|
}{1, inlineB{2, inlineC{3}}},
|
||
|
},
|
||
|
|
||
|
// bug 1243827
|
||
|
{
|
||
|
"a: -b_c",
|
||
|
map[string]interface{}{"a": "-b_c"},
|
||
|
},
|
||
|
{
|
||
|
"a: +b_c",
|
||
|
map[string]interface{}{"a": "+b_c"},
|
||
|
},
|
||
|
{
|
||
|
"a: 50cent_of_dollar",
|
||
|
map[string]interface{}{"a": "50cent_of_dollar"},
|
||
|
},
|
||
|
|
||
|
// Duration
|
||
|
{
|
||
|
"a: 3s",
|
||
|
map[string]time.Duration{"a": 3 * time.Second},
|
||
|
},
|
||
|
|
||
|
// Issue #24.
|
||
|
{
|
||
|
"a: <foo>",
|
||
|
map[string]string{"a": "<foo>"},
|
||
|
},
|
||
|
|
||
|
// Base 60 floats are obsolete and unsupported.
|
||
|
{
|
||
|
"a: 1:1\n",
|
||
|
map[string]string{"a": "1:1"},
|
||
|
},
|
||
|
|
||
|
// Binary data.
|
||
|
{
|
||
|
"a: !!binary gIGC\n",
|
||
|
map[string]string{"a": "\x80\x81\x82"},
|
||
|
}, {
|
||
|
"a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
|
||
|
map[string]string{"a": strings.Repeat("\x90", 54)},
|
||
|
}, {
|
||
|
"a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n",
|
||
|
map[string]string{"a": strings.Repeat("\x00", 52)},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
type inlineB struct {
|
||
|
B int
|
||
|
inlineC `yaml:",inline"`
|
||
|
}
|
||
|
|
||
|
type inlineC struct {
|
||
|
C int
|
||
|
}
|
||
|
|
||
|
func (s *S) TestUnmarshal(c *C) {
|
||
|
for i, item := range unmarshalTests {
|
||
|
t := reflect.ValueOf(item.value).Type()
|
||
|
var value interface{}
|
||
|
switch t.Kind() {
|
||
|
case reflect.Map:
|
||
|
value = reflect.MakeMap(t).Interface()
|
||
|
case reflect.String:
|
||
|
t := reflect.ValueOf(item.value).Type()
|
||
|
v := reflect.New(t)
|
||
|
value = v.Interface()
|
||
|
default:
|
||
|
pt := reflect.ValueOf(item.value).Type()
|
||
|
pv := reflect.New(pt.Elem())
|
||
|
value = pv.Interface()
|
||
|
}
|
||
|
err := yaml.Unmarshal([]byte(item.data), value)
|
||
|
c.Assert(err, IsNil, Commentf("Item #%d", i))
|
||
|
if t.Kind() == reflect.String {
|
||
|
c.Assert(*value.(*string), Equals, item.value, Commentf("Item #%d", i))
|
||
|
} else {
|
||
|
c.Assert(value, DeepEquals, item.value, Commentf("Item #%d", i))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *S) TestUnmarshalNaN(c *C) {
|
||
|
value := map[string]interface{}{}
|
||
|
err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
|
||
|
c.Assert(err, IsNil)
|
||
|
c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
|
||
|
}
|
||
|
|
||
|
var unmarshalErrorTests = []struct {
|
||
|
data, error string
|
||
|
}{
|
||
|
{"v: !!float 'error'", "YAML error: cannot decode !!str `error` as a !!float"},
|
||
|
{"v: [A,", "YAML error: line 1: did not find expected node content"},
|
||
|
{"v:\n- [A,", "YAML error: line 2: did not find expected node content"},
|
||
|
{"a: *b\n", "YAML error: Unknown anchor 'b' referenced"},
|
||
|
{"a: &a\n b: *a\n", "YAML error: Anchor 'a' value contains itself"},
|
||
|
{"value: -", "YAML error: block sequence entries are not allowed in this context"},
|
||
|
{"a: !!binary ==", "YAML error: !!binary value contains invalid base64 data"},
|
||
|
{"{[.]}", `YAML error: invalid map key: \[\]interface \{\}\{"\."\}`},
|
||
|
{"{{.}}", `YAML error: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
|
||
|
}
|
||
|
|
||
|
func (s *S) TestUnmarshalErrors(c *C) {
|
||
|
for _, item := range unmarshalErrorTests {
|
||
|
var value interface{}
|
||
|
err := yaml.Unmarshal([]byte(item.data), &value)
|
||
|
c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var setterTests = []struct {
|
||
|
data, tag string
|
||
|
value interface{}
|
||
|
}{
|
||
|
{"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}},
|
||
|
{"_: [1,A]", "!!seq", []interface{}{1, "A"}},
|
||
|
{"_: 10", "!!int", 10},
|
||
|
{"_: null", "!!null", nil},
|
||
|
{`_: BAR!`, "!!str", "BAR!"},
|
||
|
{`_: "BAR!"`, "!!str", "BAR!"},
|
||
|
{"_: !!foo 'BAR!'", "!!foo", "BAR!"},
|
||
|
}
|
||
|
|
||
|
var setterResult = map[int]bool{}
|
||
|
|
||
|
type typeWithSetter struct {
|
||
|
tag string
|
||
|
value interface{}
|
||
|
}
|
||
|
|
||
|
func (o *typeWithSetter) SetYAML(tag string, value interface{}) (ok bool) {
|
||
|
o.tag = tag
|
||
|
o.value = value
|
||
|
if i, ok := value.(int); ok {
|
||
|
if result, ok := setterResult[i]; ok {
|
||
|
return result
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
type setterPointerType struct {
|
||
|
Field *typeWithSetter "_"
|
||
|
}
|
||
|
|
||
|
type setterValueType struct {
|
||
|
Field typeWithSetter "_"
|
||
|
}
|
||
|
|
||
|
func (s *S) TestUnmarshalWithPointerSetter(c *C) {
|
||
|
for _, item := range setterTests {
|
||
|
obj := &setterPointerType{}
|
||
|
err := yaml.Unmarshal([]byte(item.data), obj)
|
||
|
c.Assert(err, IsNil)
|
||
|
c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
|
||
|
c.Assert(obj.Field.tag, Equals, item.tag)
|
||
|
c.Assert(obj.Field.value, DeepEquals, item.value)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *S) TestUnmarshalWithValueSetter(c *C) {
|
||
|
for _, item := range setterTests {
|
||
|
obj := &setterValueType{}
|
||
|
err := yaml.Unmarshal([]byte(item.data), obj)
|
||
|
c.Assert(err, IsNil)
|
||
|
c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
|
||
|
c.Assert(obj.Field.tag, Equals, item.tag)
|
||
|
c.Assert(obj.Field.value, DeepEquals, item.value)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) {
|
||
|
obj := &typeWithSetter{}
|
||
|
err := yaml.Unmarshal([]byte(setterTests[0].data), obj)
|
||
|
c.Assert(err, IsNil)
|
||
|
c.Assert(obj.tag, Equals, setterTests[0].tag)
|
||
|
value, ok := obj.value.(map[interface{}]interface{})
|
||
|
c.Assert(ok, Equals, true)
|
||
|
c.Assert(value["_"], DeepEquals, setterTests[0].value)
|
||
|
}
|
||
|
|
||
|
func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) {
|
||
|
setterResult[2] = false
|
||
|
setterResult[4] = false
|
||
|
defer func() {
|
||
|
delete(setterResult, 2)
|
||
|
delete(setterResult, 4)
|
||
|
}()
|
||
|
|
||
|
m := map[string]*typeWithSetter{}
|
||
|
data := `{abc: 1, def: 2, ghi: 3, jkl: 4}`
|
||
|
err := yaml.Unmarshal([]byte(data), m)
|
||
|
c.Assert(err, IsNil)
|
||
|
c.Assert(m["abc"], NotNil)
|
||
|
c.Assert(m["def"], IsNil)
|
||
|
c.Assert(m["ghi"], NotNil)
|
||
|
c.Assert(m["jkl"], IsNil)
|
||
|
|
||
|
c.Assert(m["abc"].value, Equals, 1)
|
||
|
c.Assert(m["ghi"].value, Equals, 3)
|
||
|
}
|
||
|
|
||
|
// From http://yaml.org/type/merge.html
|
||
|
var mergeTests = `
|
||
|
anchors:
|
||
|
- &CENTER { "x": 1, "y": 2 }
|
||
|
- &LEFT { "x": 0, "y": 2 }
|
||
|
- &BIG { "r": 10 }
|
||
|
- &SMALL { "r": 1 }
|
||
|
|
||
|
# All the following maps are equal:
|
||
|
|
||
|
plain:
|
||
|
# Explicit keys
|
||
|
"x": 1
|
||
|
"y": 2
|
||
|
"r": 10
|
||
|
label: center/big
|
||
|
|
||
|
mergeOne:
|
||
|
# Merge one map
|
||
|
<< : *CENTER
|
||
|
"r": 10
|
||
|
label: center/big
|
||
|
|
||
|
mergeMultiple:
|
||
|
# Merge multiple maps
|
||
|
<< : [ *CENTER, *BIG ]
|
||
|
label: center/big
|
||
|
|
||
|
override:
|
||
|
# Override
|
||
|
<< : [ *BIG, *LEFT, *SMALL ]
|
||
|
"x": 1
|
||
|
label: center/big
|
||
|
|
||
|
shortTag:
|
||
|
# Explicit short merge tag
|
||
|
!!merge "<<" : [ *CENTER, *BIG ]
|
||
|
label: center/big
|
||
|
|
||
|
longTag:
|
||
|
# Explicit merge long tag
|
||
|
!<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
|
||
|
label: center/big
|
||
|
|
||
|
inlineMap:
|
||
|
# Inlined map
|
||
|
<< : {"x": 1, "y": 2, "r": 10}
|
||
|
label: center/big
|
||
|
|
||
|
inlineSequenceMap:
|
||
|
# Inlined map in sequence
|
||
|
<< : [ *CENTER, {"r": 10} ]
|
||
|
label: center/big
|
||
|
`
|
||
|
|
||
|
func (s *S) TestMerge(c *C) {
|
||
|
var want = map[interface{}]interface{}{
|
||
|
"x": 1,
|
||
|
"y": 2,
|
||
|
"r": 10,
|
||
|
"label": "center/big",
|
||
|
}
|
||
|
|
||
|
var m map[string]interface{}
|
||
|
err := yaml.Unmarshal([]byte(mergeTests), &m)
|
||
|
c.Assert(err, IsNil)
|
||
|
for name, test := range m {
|
||
|
if name == "anchors" {
|
||
|
continue
|
||
|
}
|
||
|
c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *S) TestMergeStruct(c *C) {
|
||
|
type Data struct {
|
||
|
X, Y, R int
|
||
|
Label string
|
||
|
}
|
||
|
want := Data{1, 2, 10, "center/big"}
|
||
|
|
||
|
var m map[string]Data
|
||
|
err := yaml.Unmarshal([]byte(mergeTests), &m)
|
||
|
c.Assert(err, IsNil)
|
||
|
for name, test := range m {
|
||
|
if name == "anchors" {
|
||
|
continue
|
||
|
}
|
||
|
c.Assert(test, Equals, want, Commentf("test %q failed", name))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var unmarshalNullTests = []func() interface{}{
|
||
|
func() interface{} { var v interface{}; v = "v"; return &v },
|
||
|
func() interface{} { var s = "s"; return &s },
|
||
|
func() interface{} { var s = "s"; sptr := &s; return &sptr },
|
||
|
func() interface{} { var i = 1; return &i },
|
||
|
func() interface{} { var i = 1; iptr := &i; return &iptr },
|
||
|
func() interface{} { m := map[string]int{"s": 1}; return &m },
|
||
|
func() interface{} { m := map[string]int{"s": 1}; return m },
|
||
|
}
|
||
|
|
||
|
func (s *S) TestUnmarshalNull(c *C) {
|
||
|
for _, test := range unmarshalNullTests {
|
||
|
item := test()
|
||
|
zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface()
|
||
|
err := yaml.Unmarshal([]byte("null"), item)
|
||
|
c.Assert(err, IsNil)
|
||
|
if reflect.TypeOf(item).Kind() == reflect.Map {
|
||
|
c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface())
|
||
|
} else {
|
||
|
c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//var data []byte
|
||
|
//func init() {
|
||
|
// var err error
|
||
|
// data, err = ioutil.ReadFile("/tmp/file.yaml")
|
||
|
// if err != nil {
|
||
|
// panic(err)
|
||
|
// }
|
||
|
//}
|
||
|
//
|
||
|
//func (s *S) BenchmarkUnmarshal(c *C) {
|
||
|
// var err error
|
||
|
// for i := 0; i < c.N; i++ {
|
||
|
// var v map[string]interface{}
|
||
|
// err = yaml.Unmarshal(data, &v)
|
||
|
// }
|
||
|
// if err != nil {
|
||
|
// panic(err)
|
||
|
// }
|
||
|
//}
|
||
|
//
|
||
|
//func (s *S) BenchmarkMarshal(c *C) {
|
||
|
// var v map[string]interface{}
|
||
|
// yaml.Unmarshal(data, &v)
|
||
|
// c.ResetTimer()
|
||
|
// for i := 0; i < c.N; i++ {
|
||
|
// yaml.Marshal(&v)
|
||
|
// }
|
||
|
//}
|