5849898283
Unit tests functional and coverage back to 100% Add more routes to dictionary, add more credentials, add default port 5554, rename cameradar logs ENV variable, improve unit test readability, remove tmp file
1335 lines
30 KiB
Go
1335 lines
30 KiB
Go
package yaml_test
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"math"
|
|
"reflect"
|
|
"strings"
|
|
"time"
|
|
|
|
. "gopkg.in/check.v1"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
var unmarshalIntTest = 123
|
|
|
|
var unmarshalTests = []struct {
|
|
data string
|
|
value interface{}
|
|
}{
|
|
{
|
|
"",
|
|
(*struct{})(nil),
|
|
},
|
|
{
|
|
"{}", &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},
|
|
}, {
|
|
"bin: -0b1000000000000000000000000000000000000000000000000000000000000000",
|
|
map[string]interface{}{"bin": -9223372036854775808},
|
|
}, {
|
|
"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[interface{}]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, 2]",
|
|
&struct{ A [2]int }{[2]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{},
|
|
},
|
|
|
|
// int
|
|
{
|
|
"int_max: 2147483647",
|
|
map[string]int{"int_max": math.MaxInt32},
|
|
},
|
|
{
|
|
"int_min: -2147483648",
|
|
map[string]int{"int_min": math.MinInt32},
|
|
},
|
|
{
|
|
"int_overflow: 9223372036854775808", // math.MaxInt64 + 1
|
|
map[string]int{},
|
|
},
|
|
|
|
// int64
|
|
{
|
|
"int64_max: 9223372036854775807",
|
|
map[string]int64{"int64_max": math.MaxInt64},
|
|
},
|
|
{
|
|
"int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
|
|
map[string]int64{"int64_max_base2": math.MaxInt64},
|
|
},
|
|
{
|
|
"int64_min: -9223372036854775808",
|
|
map[string]int64{"int64_min": math.MinInt64},
|
|
},
|
|
{
|
|
"int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
|
|
map[string]int64{"int64_neg_base2": -math.MaxInt64},
|
|
},
|
|
{
|
|
"int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
|
|
map[string]int64{},
|
|
},
|
|
|
|
// uint
|
|
{
|
|
"uint_min: 0",
|
|
map[string]uint{"uint_min": 0},
|
|
},
|
|
{
|
|
"uint_max: 4294967295",
|
|
map[string]uint{"uint_max": math.MaxUint32},
|
|
},
|
|
{
|
|
"uint_underflow: -1",
|
|
map[string]uint{},
|
|
},
|
|
|
|
// uint64
|
|
{
|
|
"uint64_min: 0",
|
|
map[string]uint{"uint64_min": 0},
|
|
},
|
|
{
|
|
"uint64_max: 18446744073709551615",
|
|
map[string]uint64{"uint64_max": math.MaxUint64},
|
|
},
|
|
{
|
|
"uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
|
|
map[string]uint64{"uint64_max_base2": math.MaxUint64},
|
|
},
|
|
{
|
|
"uint64_maxint64: 9223372036854775807",
|
|
map[string]uint64{"uint64_maxint64": math.MaxInt64},
|
|
},
|
|
{
|
|
"uint64_underflow: -1",
|
|
map[string]uint64{},
|
|
},
|
|
|
|
// float32
|
|
{
|
|
"float32_max: 3.40282346638528859811704183484516925440e+38",
|
|
map[string]float32{"float32_max": math.MaxFloat32},
|
|
},
|
|
{
|
|
"float32_nonzero: 1.401298464324817070923729583289916131280e-45",
|
|
map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32},
|
|
},
|
|
{
|
|
"float32_maxuint64: 18446744073709551615",
|
|
map[string]float32{"float32_maxuint64": float32(math.MaxUint64)},
|
|
},
|
|
{
|
|
"float32_maxuint64+1: 18446744073709551616",
|
|
map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)},
|
|
},
|
|
|
|
// float64
|
|
{
|
|
"float64_max: 1.797693134862315708145274237317043567981e+308",
|
|
map[string]float64{"float64_max": math.MaxFloat64},
|
|
},
|
|
{
|
|
"float64_nonzero: 4.940656458412465441765687928682213723651e-324",
|
|
map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64},
|
|
},
|
|
{
|
|
"float64_maxuint64: 18446744073709551615",
|
|
map[string]float64{"float64_maxuint64": float64(math.MaxUint64)},
|
|
},
|
|
{
|
|
"float64_maxuint64+1: 18446744073709551616",
|
|
map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)},
|
|
},
|
|
|
|
// 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: !!float 0",
|
|
map[string]interface{}{"v": float64(0)},
|
|
}, {
|
|
"v: !!float -1",
|
|
map[string]interface{}{"v": float64(-1)},
|
|
}, {
|
|
"v: !!null ''",
|
|
map[string]interface{}{"v": nil},
|
|
}, {
|
|
"%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
|
|
map[string]interface{}{"v": 1},
|
|
},
|
|
|
|
// Non-specific tag (Issue #75)
|
|
{
|
|
"v: ! test",
|
|
map[string]interface{}{"v": "test"},
|
|
},
|
|
|
|
// 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": nil},
|
|
}, {
|
|
"foo: null",
|
|
map[string]string{"foo": ""},
|
|
}, {
|
|
"foo: null",
|
|
map[string]interface{}{"foo": nil},
|
|
},
|
|
|
|
// Support for ~
|
|
{
|
|
"foo: ~",
|
|
map[string]*string{"foo": nil},
|
|
}, {
|
|
"foo: ~",
|
|
map[string]string{"foo": ""},
|
|
}, {
|
|
"foo: ~",
|
|
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}}},
|
|
},
|
|
|
|
// Map inlining
|
|
{
|
|
"a: 1\nb: 2\nc: 3\n",
|
|
&struct {
|
|
A int
|
|
C map[string]int `yaml:",inline"`
|
|
}{1, map[string]int{"b": 2, "c": 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"},
|
|
},
|
|
|
|
// issue #295 (allow scalars with colons in flow mappings and sequences)
|
|
{
|
|
"a: {b: https://github.com/go-yaml/yaml}",
|
|
map[string]interface{}{"a": map[interface{}]interface{}{
|
|
"b": "https://github.com/go-yaml/yaml",
|
|
}},
|
|
},
|
|
{
|
|
"a: [https://github.com/go-yaml/yaml]",
|
|
map[string]interface{}{"a": []interface{}{"https://github.com/go-yaml/yaml"}},
|
|
},
|
|
|
|
// 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)},
|
|
},
|
|
|
|
// Ordered maps.
|
|
{
|
|
"{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
|
|
&yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
|
|
},
|
|
|
|
// Issue #39.
|
|
{
|
|
"a:\n b:\n c: d\n",
|
|
map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}},
|
|
},
|
|
|
|
// Custom map type.
|
|
{
|
|
"a: {b: c}",
|
|
M{"a": M{"b": "c"}},
|
|
},
|
|
|
|
// Support encoding.TextUnmarshaler.
|
|
{
|
|
"a: 1.2.3.4\n",
|
|
map[string]textUnmarshaler{"a": textUnmarshaler{S: "1.2.3.4"}},
|
|
},
|
|
{
|
|
"a: 2015-02-24T18:19:39Z\n",
|
|
map[string]textUnmarshaler{"a": textUnmarshaler{"2015-02-24T18:19:39Z"}},
|
|
},
|
|
|
|
// Timestamps
|
|
{
|
|
// Date only.
|
|
"a: 2015-01-01\n",
|
|
map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
|
|
},
|
|
{
|
|
// RFC3339
|
|
"a: 2015-02-24T18:19:39.12Z\n",
|
|
map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, .12e9, time.UTC)},
|
|
},
|
|
{
|
|
// RFC3339 with short dates.
|
|
"a: 2015-2-3T3:4:5Z",
|
|
map[string]time.Time{"a": time.Date(2015, 2, 3, 3, 4, 5, 0, time.UTC)},
|
|
},
|
|
{
|
|
// ISO8601 lower case t
|
|
"a: 2015-02-24t18:19:39Z\n",
|
|
map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
|
|
},
|
|
{
|
|
// space separate, no time zone
|
|
"a: 2015-02-24 18:19:39\n",
|
|
map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
|
|
},
|
|
// Some cases not currently handled. Uncomment these when
|
|
// the code is fixed.
|
|
// {
|
|
// // space separated with time zone
|
|
// "a: 2001-12-14 21:59:43.10 -5",
|
|
// map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)},
|
|
// },
|
|
// {
|
|
// // arbitrary whitespace between fields
|
|
// "a: 2001-12-14 \t\t \t21:59:43.10 \t Z",
|
|
// map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)},
|
|
// },
|
|
{
|
|
// explicit string tag
|
|
"a: !!str 2015-01-01",
|
|
map[string]interface{}{"a": "2015-01-01"},
|
|
},
|
|
{
|
|
// explicit timestamp tag on quoted string
|
|
"a: !!timestamp \"2015-01-01\"",
|
|
map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
|
|
},
|
|
{
|
|
// explicit timestamp tag on unquoted string
|
|
"a: !!timestamp 2015-01-01",
|
|
map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
|
|
},
|
|
{
|
|
// quoted string that's a valid timestamp
|
|
"a: \"2015-01-01\"",
|
|
map[string]interface{}{"a": "2015-01-01"},
|
|
},
|
|
{
|
|
// explicit timestamp tag into interface.
|
|
"a: !!timestamp \"2015-01-01\"",
|
|
map[string]interface{}{"a": "2015-01-01"},
|
|
},
|
|
{
|
|
// implicit timestamp tag into interface.
|
|
"a: 2015-01-01",
|
|
map[string]interface{}{"a": "2015-01-01"},
|
|
},
|
|
|
|
// Encode empty lists as zero-length slices.
|
|
{
|
|
"a: []",
|
|
&struct{ A []int }{[]int{}},
|
|
},
|
|
|
|
// UTF-16-LE
|
|
{
|
|
"\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00",
|
|
M{"ñoño": "very yes"},
|
|
},
|
|
// UTF-16-LE with surrogate.
|
|
{
|
|
"\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00",
|
|
M{"ñoño": "very yes 🟔"},
|
|
},
|
|
|
|
// UTF-16-BE
|
|
{
|
|
"\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n",
|
|
M{"ñoño": "very yes"},
|
|
},
|
|
// UTF-16-BE with surrogate.
|
|
{
|
|
"\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n",
|
|
M{"ñoño": "very yes 🟔"},
|
|
},
|
|
|
|
// YAML Float regex shouldn't match this
|
|
{
|
|
"a: 123456e1\n",
|
|
M{"a": "123456e1"},
|
|
}, {
|
|
"a: 123456E1\n",
|
|
M{"a": "123456E1"},
|
|
},
|
|
// yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes
|
|
{
|
|
"First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n",
|
|
map[interface{}]interface{}{
|
|
"Reuse anchor": "Bar",
|
|
"First occurrence": "Foo",
|
|
"Second occurrence": "Foo",
|
|
"Override anchor": "Bar",
|
|
},
|
|
},
|
|
// Single document with garbage following it.
|
|
{
|
|
"---\nhello\n...\n}not yaml",
|
|
"hello",
|
|
},
|
|
{
|
|
"a: 5\n",
|
|
&struct{ A jsonNumberT }{"5"},
|
|
},
|
|
{
|
|
"a: 5.5\n",
|
|
&struct{ A jsonNumberT }{"5.5"},
|
|
},
|
|
}
|
|
|
|
type M map[interface{}]interface{}
|
|
|
|
type inlineB struct {
|
|
B int
|
|
inlineC `yaml:",inline"`
|
|
}
|
|
|
|
type inlineC struct {
|
|
C int
|
|
}
|
|
|
|
func (s *S) TestUnmarshal(c *C) {
|
|
for i, item := range unmarshalTests {
|
|
c.Logf("test %d: %q", i, item.data)
|
|
t := reflect.ValueOf(item.value).Type()
|
|
value := reflect.New(t)
|
|
err := yaml.Unmarshal([]byte(item.data), value.Interface())
|
|
if _, ok := err.(*yaml.TypeError); !ok {
|
|
c.Assert(err, IsNil)
|
|
}
|
|
c.Assert(value.Elem().Interface(), DeepEquals, item.value, Commentf("error: %v", err))
|
|
}
|
|
}
|
|
|
|
// TODO(v3): This test should also work when unmarshaling onto an interface{}.
|
|
func (s *S) TestUnmarshalFullTimestamp(c *C) {
|
|
// Full timestamp in same format as encoded. This is confirmed to be
|
|
// properly decoded by Python as a timestamp as well.
|
|
var str = "2015-02-24T18:19:39.123456789-03:00"
|
|
var t time.Time
|
|
err := yaml.Unmarshal([]byte(str), &t)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.Location()))
|
|
c.Assert(t.In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC))
|
|
}
|
|
|
|
func (s *S) TestDecoderSingleDocument(c *C) {
|
|
// Test that Decoder.Decode works as expected on
|
|
// all the unmarshal tests.
|
|
for i, item := range unmarshalTests {
|
|
c.Logf("test %d: %q", i, item.data)
|
|
if item.data == "" {
|
|
// Behaviour differs when there's no YAML.
|
|
continue
|
|
}
|
|
t := reflect.ValueOf(item.value).Type()
|
|
value := reflect.New(t)
|
|
err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(value.Interface())
|
|
if _, ok := err.(*yaml.TypeError); !ok {
|
|
c.Assert(err, IsNil)
|
|
}
|
|
c.Assert(value.Elem().Interface(), DeepEquals, item.value)
|
|
}
|
|
}
|
|
|
|
var decoderTests = []struct {
|
|
data string
|
|
values []interface{}
|
|
}{{
|
|
"",
|
|
nil,
|
|
}, {
|
|
"a: b",
|
|
[]interface{}{
|
|
map[interface{}]interface{}{"a": "b"},
|
|
},
|
|
}, {
|
|
"---\na: b\n...\n",
|
|
[]interface{}{
|
|
map[interface{}]interface{}{"a": "b"},
|
|
},
|
|
}, {
|
|
"---\n'hello'\n...\n---\ngoodbye\n...\n",
|
|
[]interface{}{
|
|
"hello",
|
|
"goodbye",
|
|
},
|
|
}}
|
|
|
|
func (s *S) TestDecoder(c *C) {
|
|
for i, item := range decoderTests {
|
|
c.Logf("test %d: %q", i, item.data)
|
|
var values []interface{}
|
|
dec := yaml.NewDecoder(strings.NewReader(item.data))
|
|
for {
|
|
var value interface{}
|
|
err := dec.Decode(&value)
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
c.Assert(err, IsNil)
|
|
values = append(values, value)
|
|
}
|
|
c.Assert(values, DeepEquals, item.values)
|
|
}
|
|
}
|
|
|
|
type errReader struct{}
|
|
|
|
func (errReader) Read([]byte) (int, error) {
|
|
return 0, errors.New("some read error")
|
|
}
|
|
|
|
func (s *S) TestDecoderReadError(c *C) {
|
|
err := yaml.NewDecoder(errReader{}).Decode(&struct{}{})
|
|
c.Assert(err, ErrorMatches, `yaml: input error: some read error`)
|
|
}
|
|
|
|
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: cannot decode !!str `error` as a !!float"},
|
|
{"v: [A,", "yaml: line 1: did not find expected node content"},
|
|
{"v:\n- [A,", "yaml: line 2: did not find expected node content"},
|
|
{"a:\n- b: *,", "yaml: line 2: did not find expected alphabetic or numeric character"},
|
|
{"a: *b\n", "yaml: unknown anchor 'b' referenced"},
|
|
{"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"},
|
|
{"value: -", "yaml: block sequence entries are not allowed in this context"},
|
|
{"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"},
|
|
{"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`},
|
|
{"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
|
|
{"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`},
|
|
{"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"},
|
|
}
|
|
|
|
func (s *S) TestUnmarshalErrors(c *C) {
|
|
for i, item := range unmarshalErrorTests {
|
|
c.Logf("test %d: %q", i, item.data)
|
|
var value interface{}
|
|
err := yaml.Unmarshal([]byte(item.data), &value)
|
|
c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
|
|
}
|
|
}
|
|
|
|
func (s *S) TestDecoderErrors(c *C) {
|
|
for _, item := range unmarshalErrorTests {
|
|
var value interface{}
|
|
err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(&value)
|
|
c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
|
|
}
|
|
}
|
|
|
|
var unmarshalerTests = []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!"},
|
|
{`_: ""`, "!!str", ""},
|
|
}
|
|
|
|
var unmarshalerResult = map[int]error{}
|
|
|
|
type unmarshalerType struct {
|
|
value interface{}
|
|
}
|
|
|
|
func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error {
|
|
if err := unmarshal(&o.value); err != nil {
|
|
return err
|
|
}
|
|
if i, ok := o.value.(int); ok {
|
|
if result, ok := unmarshalerResult[i]; ok {
|
|
return result
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type unmarshalerPointer struct {
|
|
Field *unmarshalerType "_"
|
|
}
|
|
|
|
type unmarshalerValue struct {
|
|
Field unmarshalerType "_"
|
|
}
|
|
|
|
func (s *S) TestUnmarshalerPointerField(c *C) {
|
|
for _, item := range unmarshalerTests {
|
|
obj := &unmarshalerPointer{}
|
|
err := yaml.Unmarshal([]byte(item.data), obj)
|
|
c.Assert(err, IsNil)
|
|
if item.value == nil {
|
|
c.Assert(obj.Field, IsNil)
|
|
} else {
|
|
c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
|
|
c.Assert(obj.Field.value, DeepEquals, item.value)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *S) TestUnmarshalerValueField(c *C) {
|
|
for _, item := range unmarshalerTests {
|
|
obj := &unmarshalerValue{}
|
|
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.value, DeepEquals, item.value)
|
|
}
|
|
}
|
|
|
|
func (s *S) TestUnmarshalerWholeDocument(c *C) {
|
|
obj := &unmarshalerType{}
|
|
err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj)
|
|
c.Assert(err, IsNil)
|
|
value, ok := obj.value.(map[interface{}]interface{})
|
|
c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value))
|
|
c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value)
|
|
}
|
|
|
|
func (s *S) TestUnmarshalerTypeError(c *C) {
|
|
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
|
|
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
|
|
defer func() {
|
|
delete(unmarshalerResult, 2)
|
|
delete(unmarshalerResult, 4)
|
|
}()
|
|
|
|
type T struct {
|
|
Before int
|
|
After int
|
|
M map[string]*unmarshalerType
|
|
}
|
|
var v T
|
|
data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
|
|
err := yaml.Unmarshal([]byte(data), &v)
|
|
c.Assert(err, ErrorMatches, ""+
|
|
"yaml: unmarshal errors:\n"+
|
|
" line 1: cannot unmarshal !!str `A` into int\n"+
|
|
" foo\n"+
|
|
" bar\n"+
|
|
" line 1: cannot unmarshal !!str `B` into int")
|
|
c.Assert(v.M["abc"], NotNil)
|
|
c.Assert(v.M["def"], IsNil)
|
|
c.Assert(v.M["ghi"], NotNil)
|
|
c.Assert(v.M["jkl"], IsNil)
|
|
|
|
c.Assert(v.M["abc"].value, Equals, 1)
|
|
c.Assert(v.M["ghi"].value, Equals, 3)
|
|
}
|
|
|
|
type proxyTypeError struct{}
|
|
|
|
func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
var s string
|
|
var a int32
|
|
var b int64
|
|
if err := unmarshal(&s); err != nil {
|
|
panic(err)
|
|
}
|
|
if s == "a" {
|
|
if err := unmarshal(&b); err == nil {
|
|
panic("should have failed")
|
|
}
|
|
return unmarshal(&a)
|
|
}
|
|
if err := unmarshal(&a); err == nil {
|
|
panic("should have failed")
|
|
}
|
|
return unmarshal(&b)
|
|
}
|
|
|
|
func (s *S) TestUnmarshalerTypeErrorProxying(c *C) {
|
|
type T struct {
|
|
Before int
|
|
After int
|
|
M map[string]*proxyTypeError
|
|
}
|
|
var v T
|
|
data := `{before: A, m: {abc: a, def: b}, after: B}`
|
|
err := yaml.Unmarshal([]byte(data), &v)
|
|
c.Assert(err, ErrorMatches, ""+
|
|
"yaml: unmarshal errors:\n"+
|
|
" line 1: cannot unmarshal !!str `A` into int\n"+
|
|
" line 1: cannot unmarshal !!str `a` into int32\n"+
|
|
" line 1: cannot unmarshal !!str `b` into int64\n"+
|
|
" line 1: cannot unmarshal !!str `B` into int")
|
|
}
|
|
|
|
type failingUnmarshaler struct{}
|
|
|
|
var failingErr = errors.New("failingErr")
|
|
|
|
func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
return failingErr
|
|
}
|
|
|
|
func (s *S) TestUnmarshalerError(c *C) {
|
|
err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{})
|
|
c.Assert(err, Equals, failingErr)
|
|
}
|
|
|
|
type sliceUnmarshaler []int
|
|
|
|
func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
var slice []int
|
|
err := unmarshal(&slice)
|
|
if err == nil {
|
|
*su = slice
|
|
return nil
|
|
}
|
|
|
|
var intVal int
|
|
err = unmarshal(&intVal)
|
|
if err == nil {
|
|
*su = []int{intVal}
|
|
return nil
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func (s *S) TestUnmarshalerRetry(c *C) {
|
|
var su sliceUnmarshaler
|
|
err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3}))
|
|
|
|
err = yaml.Unmarshal([]byte("1"), &su)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1}))
|
|
}
|
|
|
|
// From http://yaml.org/type/merge.html
|
|
var mergeTests = `
|
|
anchors:
|
|
list:
|
|
- &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[interface{}]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)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *S) TestUnmarshalSliceOnPreset(c *C) {
|
|
// Issue #48.
|
|
v := struct{ A []int }{[]int{1}}
|
|
yaml.Unmarshal([]byte("a: [2]"), &v)
|
|
c.Assert(v.A, DeepEquals, []int{2})
|
|
}
|
|
|
|
var unmarshalStrictTests = []struct {
|
|
data string
|
|
value interface{}
|
|
error string
|
|
}{{
|
|
data: "a: 1\nc: 2\n",
|
|
value: struct{ A, B int }{A: 1},
|
|
error: `yaml: unmarshal errors:\n line 2: field c not found in type struct { A int; B int }`,
|
|
}, {
|
|
data: "a: 1\nb: 2\na: 3\n",
|
|
value: struct{ A, B int }{A: 3, B: 2},
|
|
error: `yaml: unmarshal errors:\n line 3: field a already set in type struct { A int; B int }`,
|
|
}, {
|
|
data: "c: 3\na: 1\nb: 2\nc: 4\n",
|
|
value: struct {
|
|
A int
|
|
inlineB `yaml:",inline"`
|
|
}{
|
|
A: 1,
|
|
inlineB: inlineB{
|
|
B: 2,
|
|
inlineC: inlineC{
|
|
C: 4,
|
|
},
|
|
},
|
|
},
|
|
error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`,
|
|
}, {
|
|
data: "c: 0\na: 1\nb: 2\nc: 1\n",
|
|
value: struct {
|
|
A int
|
|
inlineB `yaml:",inline"`
|
|
}{
|
|
A: 1,
|
|
inlineB: inlineB{
|
|
B: 2,
|
|
inlineC: inlineC{
|
|
C: 1,
|
|
},
|
|
},
|
|
},
|
|
error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`,
|
|
}, {
|
|
data: "c: 1\na: 1\nb: 2\nc: 3\n",
|
|
value: struct {
|
|
A int
|
|
M map[string]interface{} `yaml:",inline"`
|
|
}{
|
|
A: 1,
|
|
M: map[string]interface{}{
|
|
"b": 2,
|
|
"c": 3,
|
|
},
|
|
},
|
|
error: `yaml: unmarshal errors:\n line 4: key "c" already set in map`,
|
|
}, {
|
|
data: "a: 1\n9: 2\nnull: 3\n9: 4",
|
|
value: map[interface{}]interface{}{
|
|
"a": 1,
|
|
nil: 3,
|
|
9: 4,
|
|
},
|
|
error: `yaml: unmarshal errors:\n line 4: key 9 already set in map`,
|
|
}}
|
|
|
|
func (s *S) TestUnmarshalStrict(c *C) {
|
|
for i, item := range unmarshalStrictTests {
|
|
c.Logf("test %d: %q", i, item.data)
|
|
// First test that normal Unmarshal unmarshals to the expected value.
|
|
t := reflect.ValueOf(item.value).Type()
|
|
value := reflect.New(t)
|
|
err := yaml.Unmarshal([]byte(item.data), value.Interface())
|
|
c.Assert(err, Equals, nil)
|
|
c.Assert(value.Elem().Interface(), DeepEquals, item.value)
|
|
|
|
// Then test that UnmarshalStrict fails on the same thing.
|
|
t = reflect.ValueOf(item.value).Type()
|
|
value = reflect.New(t)
|
|
err = yaml.UnmarshalStrict([]byte(item.data), value.Interface())
|
|
c.Assert(err, ErrorMatches, item.error)
|
|
}
|
|
}
|
|
|
|
type textUnmarshaler struct {
|
|
S string
|
|
}
|
|
|
|
func (t *textUnmarshaler) UnmarshalText(s []byte) error {
|
|
t.S = string(s)
|
|
return nil
|
|
}
|
|
|
|
func (s *S) TestFuzzCrashers(c *C) {
|
|
cases := []string{
|
|
// runtime error: index out of range
|
|
"\"\\0\\\r\n",
|
|
|
|
// should not happen
|
|
" 0: [\n] 0",
|
|
"? ? \"\n\" 0",
|
|
" - {\n000}0",
|
|
"0:\n 0: [0\n] 0",
|
|
" - \"\n000\"0",
|
|
" - \"\n000\"\"",
|
|
"0:\n - {\n000}0",
|
|
"0:\n - \"\n000\"0",
|
|
"0:\n - \"\n000\"\"",
|
|
|
|
// runtime error: index out of range
|
|
" \ufeff\n",
|
|
"? \ufeff\n",
|
|
"? \ufeff:\n",
|
|
"0: \ufeff\n",
|
|
"? \ufeff: \ufeff\n",
|
|
}
|
|
for _, data := range cases {
|
|
var v interface{}
|
|
_ = yaml.Unmarshal([]byte(data), &v)
|
|
}
|
|
}
|
|
|
|
//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)
|
|
// }
|
|
//}
|