410 lines
6.8 KiB
Go
410 lines
6.8 KiB
Go
package unmarshaler
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/pelletier/go-toml/v2/internal/ast"
|
|
)
|
|
|
|
func TestUnmarshal(t *testing.T) {
|
|
type test struct {
|
|
target interface{}
|
|
expected interface{}
|
|
}
|
|
examples := []struct {
|
|
desc string
|
|
input string
|
|
gen func() test
|
|
}{
|
|
{
|
|
desc: "kv string",
|
|
input: `A = "foo"`,
|
|
gen: func() test {
|
|
type doc struct {
|
|
A string
|
|
}
|
|
return test{
|
|
&doc{},
|
|
&doc{A: "foo"},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
desc: "string array",
|
|
input: `A = ["foo", "bar"]`,
|
|
gen: func() test {
|
|
type doc struct {
|
|
A []string
|
|
}
|
|
return test{
|
|
&doc{},
|
|
&doc{A: []string{"foo", "bar"}},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
desc: "inline table",
|
|
input: `Name = {First = "hello", Last = "world"}`,
|
|
gen: func() test {
|
|
type name struct {
|
|
First string
|
|
Last string
|
|
}
|
|
type doc struct {
|
|
Name name
|
|
}
|
|
return test{
|
|
&doc{},
|
|
&doc{Name: name{
|
|
First: "hello",
|
|
Last: "world",
|
|
}},
|
|
}
|
|
},
|
|
},
|
|
{
|
|
desc: "inline table inside array",
|
|
input: `Names = [{First = "hello", Last = "world"}, {First = "ab", Last = "cd"}]`,
|
|
gen: func() test {
|
|
type name struct {
|
|
First string
|
|
Last string
|
|
}
|
|
type doc struct {
|
|
Names []name
|
|
}
|
|
return test{
|
|
&doc{},
|
|
&doc{
|
|
Names: []name{
|
|
{
|
|
First: "hello",
|
|
Last: "world",
|
|
},
|
|
{
|
|
First: "ab",
|
|
Last: "cd",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, e := range examples {
|
|
t.Run(e.desc, func(t *testing.T) {
|
|
test := e.gen()
|
|
err := Unmarshal([]byte(e.input), test.target)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, test.expected, test.target)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFromAst_KV(t *testing.T) {
|
|
root := ast.Root{
|
|
ast.Node{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.Key,
|
|
Data: []byte(`Foo`),
|
|
},
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`hello`),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
type Doc struct {
|
|
Foo string
|
|
}
|
|
|
|
x := Doc{}
|
|
err := fromAst(root, &x)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Doc{Foo: "hello"}, x)
|
|
}
|
|
|
|
func TestFromAst_Table(t *testing.T) {
|
|
t.Run("one level table on struct", func(t *testing.T) {
|
|
root := ast.Root{
|
|
ast.Node{
|
|
Kind: ast.Table,
|
|
Children: []ast.Node{
|
|
{Kind: ast.Key, Data: []byte(`Level1`)},
|
|
},
|
|
},
|
|
ast.Node{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.Key,
|
|
Data: []byte(`A`),
|
|
},
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`hello`),
|
|
},
|
|
},
|
|
},
|
|
ast.Node{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.Key,
|
|
Data: []byte(`B`),
|
|
},
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`world`),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
type Level1 struct {
|
|
A string
|
|
B string
|
|
}
|
|
|
|
type Doc struct {
|
|
Level1 Level1
|
|
}
|
|
|
|
x := Doc{}
|
|
err := fromAst(root, &x)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Doc{
|
|
Level1: Level1{
|
|
A: "hello",
|
|
B: "world",
|
|
},
|
|
}, x)
|
|
})
|
|
t.Run("one level table on struct", func(t *testing.T) {
|
|
root := ast.Root{
|
|
ast.Node{
|
|
Kind: ast.Table,
|
|
Children: []ast.Node{
|
|
{Kind: ast.Key, Data: []byte(`A`)},
|
|
{Kind: ast.Key, Data: []byte(`B`)},
|
|
},
|
|
},
|
|
ast.Node{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.Key,
|
|
Data: []byte(`C`),
|
|
},
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`value`),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
type B struct {
|
|
C string
|
|
}
|
|
|
|
type A struct {
|
|
B B
|
|
}
|
|
|
|
type Doc struct {
|
|
A A
|
|
}
|
|
|
|
x := Doc{}
|
|
err := fromAst(root, &x)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Doc{
|
|
A: A{B: B{C: "value"}},
|
|
}, x)
|
|
})
|
|
}
|
|
|
|
func TestFromAst_InlineTable(t *testing.T) {
|
|
t.Run("one level of strings", func(t *testing.T) {
|
|
// name = { first = "Tom", last = "Preston-Werner" }
|
|
|
|
root := ast.Root{
|
|
ast.Node{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.Key,
|
|
Data: []byte(`Name`)},
|
|
{
|
|
Kind: ast.InlineTable,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{Kind: ast.Key, Data: []byte(`First`)},
|
|
{Kind: ast.String, Data: []byte(`Tom`)},
|
|
},
|
|
},
|
|
{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{Kind: ast.Key, Data: []byte(`Last`)},
|
|
{Kind: ast.String, Data: []byte(`Preston-Werner`)},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
type Name struct {
|
|
First string
|
|
Last string
|
|
}
|
|
|
|
type Doc struct {
|
|
Name Name
|
|
}
|
|
|
|
x := Doc{}
|
|
err := fromAst(root, &x)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Doc{
|
|
Name: Name{
|
|
First: "Tom",
|
|
Last: "Preston-Werner",
|
|
},
|
|
}, x)
|
|
|
|
})
|
|
}
|
|
|
|
func TestFromAst_Slice(t *testing.T) {
|
|
t.Run("slice of string", func(t *testing.T) {
|
|
root := ast.Root{
|
|
ast.Node{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.Key,
|
|
Data: []byte(`Foo`),
|
|
},
|
|
{
|
|
Kind: ast.Array,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`hello`),
|
|
},
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`world`),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
type Doc struct {
|
|
Foo []string
|
|
}
|
|
|
|
x := Doc{}
|
|
err := fromAst(root, &x)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Doc{Foo: []string{"hello", "world"}}, x)
|
|
})
|
|
|
|
t.Run("slice of interfaces for strings", func(t *testing.T) {
|
|
root := ast.Root{
|
|
ast.Node{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.Key,
|
|
Data: []byte(`Foo`),
|
|
},
|
|
{
|
|
Kind: ast.Array,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`hello`),
|
|
},
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`world`),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
type Doc struct {
|
|
Foo []interface{}
|
|
}
|
|
|
|
x := Doc{}
|
|
err := fromAst(root, &x)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Doc{Foo: []interface{}{"hello", "world"}}, x)
|
|
})
|
|
|
|
t.Run("slice of interfaces with slices", func(t *testing.T) {
|
|
root := ast.Root{
|
|
ast.Node{
|
|
Kind: ast.KeyValue,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.Key,
|
|
Data: []byte(`Foo`),
|
|
},
|
|
{
|
|
Kind: ast.Array,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`hello`),
|
|
},
|
|
{
|
|
Kind: ast.Array,
|
|
Children: []ast.Node{
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`inner1`),
|
|
},
|
|
{
|
|
Kind: ast.String,
|
|
Data: []byte(`inner2`),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
type Doc struct {
|
|
Foo []interface{}
|
|
}
|
|
|
|
x := Doc{}
|
|
err := fromAst(root, &x)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Doc{Foo: []interface{}{"hello", []interface{}{"inner1", "inner2"}}}, x)
|
|
})
|
|
}
|