Decode: assigned empty struct to empty defined sections (#879)
Co-authored-by: Thomas Pelletier <thomas@pelletier.codes>
This commit is contained in:
@@ -79,6 +79,7 @@ cover() {
|
|||||||
go test -covermode=atomic -coverpkg=./... -coverprofile=coverage.out.tmp ./...
|
go test -covermode=atomic -coverpkg=./... -coverprofile=coverage.out.tmp ./...
|
||||||
cat coverage.out.tmp | grep -v fuzz | grep -v testsuite | grep -v tomltestgen | grep -v gotoml-test-decoder > coverage.out
|
cat coverage.out.tmp | grep -v fuzz | grep -v testsuite | grep -v tomltestgen | grep -v gotoml-test-decoder > coverage.out
|
||||||
go tool cover -func=coverage.out
|
go tool cover -func=coverage.out
|
||||||
|
echo "Coverage profile for ${branch}: ${dir}/coverage.out" >&2
|
||||||
popd
|
popd
|
||||||
|
|
||||||
if [ "${branch}" != "HEAD" ]; then
|
if [ "${branch}" != "HEAD" ]; then
|
||||||
|
|||||||
+2
-2
@@ -1170,10 +1170,10 @@ func initAndDereferencePointer(v reflect.Value) reflect.Value {
|
|||||||
|
|
||||||
// Same as reflect.Value.FieldByIndex, but creates pointers if needed.
|
// Same as reflect.Value.FieldByIndex, but creates pointers if needed.
|
||||||
func fieldByIndex(v reflect.Value, path []int) reflect.Value {
|
func fieldByIndex(v reflect.Value, path []int) reflect.Value {
|
||||||
for i, x := range path {
|
for _, x := range path {
|
||||||
v = v.Field(x)
|
v = v.Field(x)
|
||||||
|
|
||||||
if i < len(path)-1 && v.Kind() == reflect.Ptr {
|
if v.Kind() == reflect.Ptr {
|
||||||
if v.IsNil() {
|
if v.IsNil() {
|
||||||
v.Set(reflect.New(v.Type().Elem()))
|
v.Set(reflect.New(v.Type().Elem()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1277,6 +1277,64 @@ B = "data"`,
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "array table into maps with pointer on last key",
|
||||||
|
input: `[[foo]]
|
||||||
|
bar = "hello"`,
|
||||||
|
gen: func() test {
|
||||||
|
type doc struct {
|
||||||
|
Foo **[]interface{}
|
||||||
|
}
|
||||||
|
x := &[]interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"bar": "hello",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return test{
|
||||||
|
target: &doc{},
|
||||||
|
expected: &doc{
|
||||||
|
Foo: &x,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "array table into maps with pointer on intermediate key",
|
||||||
|
input: `[[foo.foo2]]
|
||||||
|
bar = "hello"`,
|
||||||
|
gen: func() test {
|
||||||
|
type doc struct {
|
||||||
|
Foo **map[string]interface{}
|
||||||
|
}
|
||||||
|
x := &map[string]interface{}{
|
||||||
|
"foo2": []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"bar": "hello",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return test{
|
||||||
|
target: &doc{},
|
||||||
|
expected: &doc{
|
||||||
|
Foo: &x,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "array table into maps with pointer on last key with invalid leaf type",
|
||||||
|
input: `[[foo]]
|
||||||
|
bar = "hello"`,
|
||||||
|
gen: func() test {
|
||||||
|
type doc struct {
|
||||||
|
Foo **[]map[string]int
|
||||||
|
}
|
||||||
|
return test{
|
||||||
|
target: &doc{},
|
||||||
|
err: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "unexported struct fields are ignored",
|
desc: "unexported struct fields are ignored",
|
||||||
input: `foo = "bar"`,
|
input: `foo = "bar"`,
|
||||||
@@ -3511,3 +3569,47 @@ func TestUnmarshalEmbedNonString(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Nil(t, d.Foo)
|
require.Nil(t, d.Foo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnmarshal_Nil(t *testing.T) {
|
||||||
|
type Foo struct {
|
||||||
|
Foo *Foo `toml:"foo,omitempty"`
|
||||||
|
Bar *Foo `toml:"bar,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
examples := []struct {
|
||||||
|
desc string
|
||||||
|
input string
|
||||||
|
expected string
|
||||||
|
err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "empty",
|
||||||
|
input: ``,
|
||||||
|
expected: ``,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "simplest",
|
||||||
|
input: `
|
||||||
|
[foo]
|
||||||
|
[foo.foo]
|
||||||
|
`,
|
||||||
|
expected: "[foo]\n[foo.foo]\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ex := range examples {
|
||||||
|
e := ex
|
||||||
|
t.Run(e.desc, func(t *testing.T) {
|
||||||
|
foo := Foo{}
|
||||||
|
err := toml.Unmarshal([]byte(e.input), &foo)
|
||||||
|
if e.err {
|
||||||
|
require.Error(t, err)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
j, err := toml.Marshal(foo)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, e.expected, string(j))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user