traefik/pkg/config/parser/element_fill_test.go
Ludovic Fernandez 8d7eccad5d New static configuration loading system.
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
2019-06-17 11:48:05 +02:00

1432 lines
33 KiB
Go

package parser
import (
"reflect"
"testing"
"time"
"github.com/containous/traefik/pkg/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFill(t *testing.T) {
type expected struct {
element interface{}
error bool
}
testCases := []struct {
desc string
node *Node
element interface{}
expected expected
}{
{
desc: "empty node",
node: &Node{},
element: &struct{ Foo string }{},
expected: expected{error: true},
},
{
desc: "empty element",
node: &Node{Name: "traefik", Kind: reflect.Struct},
element: &struct{}{},
expected: expected{element: &struct{}{}},
},
{
desc: "type struct as root",
node: &Node{Name: "traefik", Kind: reflect.Struct},
element: struct{}{},
expected: expected{error: true},
},
{
desc: "nil node",
node: nil,
element: &struct{ Foo string }{},
expected: expected{element: &struct{ Foo string }{}},
},
{
desc: "nil element",
node: &Node{Name: "traefik", Kind: reflect.Struct},
element: nil,
expected: expected{element: nil},
},
{
desc: "string",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "bar", Kind: reflect.String},
},
},
element: &struct{ Foo string }{},
expected: expected{element: &struct{ Foo string }{Foo: "bar"}},
},
{
desc: "field not found",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Fii", Value: "bar", Kind: reflect.String},
},
},
element: &struct{ Foo string }{},
expected: expected{error: true},
},
{
desc: "2 children",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Fii", FieldName: "Fii", Value: "bir", Kind: reflect.String},
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Int},
},
},
element: &struct {
Fii string
Foo int
}{},
expected: expected{element: &struct {
Fii string
Foo int
}{Fii: "bir", Foo: 4}},
},
{
desc: "case insensitive",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "foo", FieldName: "Foo", Value: "bir", Kind: reflect.String},
},
},
element: &struct {
Foo string
foo int
}{},
expected: expected{element: &struct {
Foo string
foo int
}{Foo: "bir"}},
},
{
desc: "func",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Kind: reflect.Func},
},
},
element: &struct{ Foo func() }{},
expected: expected{element: &struct{ Foo func() }{}},
},
{
desc: "int",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Int},
},
},
element: &struct{ Foo int }{},
expected: expected{element: &struct{ Foo int }{Foo: 4}},
},
{
desc: "invalid int",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Int},
},
},
element: &struct{ Foo int }{},
expected: expected{error: true},
},
{
desc: "int8",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Int8},
},
},
element: &struct{ Foo int8 }{},
expected: expected{element: &struct{ Foo int8 }{Foo: 4}},
},
{
desc: "invalid int8",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Int8},
},
},
element: &struct{ Foo int8 }{},
expected: expected{error: true},
},
{
desc: "int16",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Int16},
},
},
element: &struct{ Foo int16 }{},
expected: expected{element: &struct{ Foo int16 }{Foo: 4}},
},
{
desc: "invalid int16",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Int16},
},
},
element: &struct{ Foo int16 }{},
expected: expected{error: true},
},
{
desc: "int32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Int32},
},
},
element: &struct{ Foo int32 }{},
expected: expected{element: &struct{ Foo int32 }{Foo: 4}},
},
{
desc: "invalid int32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Int32},
},
},
element: &struct{ Foo int32 }{},
expected: expected{error: true},
},
{
desc: "int64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Int64},
},
},
element: &struct{ Foo int64 }{},
expected: expected{element: &struct{ Foo int64 }{Foo: 4}},
},
{
desc: "invalid int64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Int64},
},
},
element: &struct{ Foo int64 }{},
expected: expected{error: true},
},
{
desc: "uint",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Uint},
},
},
element: &struct{ Foo uint }{},
expected: expected{element: &struct{ Foo uint }{Foo: 4}},
},
{
desc: "invalid uint",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Uint},
},
},
element: &struct{ Foo uint }{},
expected: expected{error: true},
},
{
desc: "uint8",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Uint8},
},
},
element: &struct{ Foo uint8 }{},
expected: expected{element: &struct{ Foo uint8 }{Foo: 4}},
},
{
desc: "invalid uint8",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Uint8},
},
},
element: &struct{ Foo uint8 }{},
expected: expected{error: true},
},
{
desc: "uint16",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Uint16},
},
},
element: &struct{ Foo uint16 }{},
expected: expected{element: &struct{ Foo uint16 }{Foo: 4}},
},
{
desc: "invalid uint16",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Uint16},
},
},
element: &struct{ Foo uint16 }{},
expected: expected{error: true},
},
{
desc: "uint32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Uint32},
},
},
element: &struct{ Foo uint32 }{},
expected: expected{element: &struct{ Foo uint32 }{Foo: 4}},
},
{
desc: "invalid uint32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Uint32},
},
},
element: &struct{ Foo uint32 }{},
expected: expected{error: true},
},
{
desc: "uint64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Uint64},
},
},
element: &struct{ Foo uint64 }{},
expected: expected{element: &struct{ Foo uint64 }{Foo: 4}},
},
{
desc: "invalid uint64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four", Kind: reflect.Uint64},
},
},
element: &struct{ Foo uint64 }{},
expected: expected{error: true},
},
{
desc: "time.Duration with unit",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4s", Kind: reflect.Int64},
},
},
element: &struct{ Foo time.Duration }{},
expected: expected{element: &struct{ Foo time.Duration }{Foo: 4 * time.Second}},
},
{
desc: "time.Duration without unit",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Int64},
},
},
element: &struct{ Foo time.Duration }{},
expected: expected{element: &struct{ Foo time.Duration }{Foo: 4 * time.Nanosecond}},
},
{
desc: "types.Duration with unit",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4s", Kind: reflect.Int64},
},
},
element: &struct{ Foo types.Duration }{},
expected: expected{element: &struct{ Foo types.Duration }{Foo: types.Duration(4 * time.Second)}},
},
{
desc: "types.Duration without unit",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Int64},
},
},
element: &struct{ Foo types.Duration }{},
expected: expected{element: &struct{ Foo types.Duration }{Foo: types.Duration(4 * time.Second)}},
},
{
desc: "bool",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "true", Kind: reflect.Bool},
},
},
element: &struct{ Foo bool }{},
expected: expected{element: &struct{ Foo bool }{Foo: true}},
},
{
desc: "invalid bool",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "bool", Kind: reflect.Bool},
},
},
element: &struct{ Foo bool }{},
expected: expected{error: true},
},
{
desc: "float32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "2.1", Kind: reflect.Float32},
},
},
element: &struct{ Foo float32 }{},
expected: expected{element: &struct{ Foo float32 }{Foo: 2.1}},
},
{
desc: "invalid float32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "two dot one", Kind: reflect.Float32},
},
},
element: &struct{ Foo float32 }{},
expected: expected{error: true},
},
{
desc: "float64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "2.1", Kind: reflect.Float64},
},
},
element: &struct{ Foo float64 }{},
expected: expected{element: &struct{ Foo float64 }{Foo: 2.1}},
},
{
desc: "invalid float64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "two dot one", Kind: reflect.Float64},
},
},
element: &struct{ Foo float64 }{},
expected: expected{error: true},
},
{
desc: "struct",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Fii", FieldName: "Fii", Value: "huu", Kind: reflect.String},
{Name: "Fuu", FieldName: "Fuu", Value: "6", Kind: reflect.Int},
}},
}},
element: &struct {
Foo struct {
Fii string
Fuu int
}
}{},
expected: expected{element: &struct {
Foo struct {
Fii string
Fuu int
}
}{
Foo: struct {
Fii string
Fuu int
}{
Fii: "huu",
Fuu: 6,
}},
},
},
{
desc: "pointer",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Fii", FieldName: "Fii", Value: "huu", Kind: reflect.String},
{Name: "Fuu", FieldName: "Fuu", Value: "6", Kind: reflect.Int},
}},
}},
element: &struct {
Foo *struct {
Fii string
Fuu int
}
}{},
expected: expected{element: &struct {
Foo *struct {
Fii string
Fuu int
}
}{
Foo: &struct {
Fii string
Fuu int
}{
Fii: "huu",
Fuu: 6,
}},
},
},
{
desc: "pointer disabled false without children",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Kind: reflect.Ptr,
},
}},
element: &struct {
Foo *struct {
Fii string
Fuu int
} `label:"allowEmpty"`
}{},
expected: expected{element: &struct {
Foo *struct {
Fii string
Fuu int
} `label:"allowEmpty"`
}{
Foo: &struct {
Fii string
Fuu int
}{}},
},
},
{
desc: "pointer disabled true without children",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Kind: reflect.Ptr,
Disabled: true,
},
}},
element: &struct {
Foo *struct {
Fii string
Fuu int
} `label:"allowEmpty"`
}{},
expected: expected{element: &struct {
Foo *struct {
Fii string
Fuu int
} `label:"allowEmpty"`
}{},
},
},
{
desc: "pointer disabled true with children",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Disabled: true,
Kind: reflect.Ptr,
Children: []*Node{
{Name: "Fii", FieldName: "Fii", Value: "huu", Kind: reflect.String},
{Name: "Fuu", FieldName: "Fuu", Value: "6", Kind: reflect.Int},
}},
}},
element: &struct {
Foo *struct {
Fii string
Fuu int
} `label:"allowEmpty"`
}{},
expected: expected{element: &struct {
Foo *struct {
Fii string
Fuu int
} `label:"allowEmpty"`
}{},
},
},
{
desc: "map string",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Kind: reflect.Map,
Children: []*Node{
{Name: "name1", Value: "hii", Kind: reflect.String},
{Name: "name2", Value: "huu", Kind: reflect.String},
}},
}},
element: &struct {
Foo map[string]string
}{},
expected: expected{element: &struct {
Foo map[string]string
}{
Foo: map[string]string{
"name1": "hii",
"name2": "huu",
}},
},
},
{
desc: "map struct",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Kind: reflect.Map,
Children: []*Node{
{
Name: "name1",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Fii", FieldName: "Fii", Kind: reflect.String, Value: "hii"},
},
},
{
Name: "name2",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Fii", FieldName: "Fii", Kind: reflect.String, Value: "huu"},
},
},
}},
}},
element: &struct {
Foo map[string]struct{ Fii string }
}{},
expected: expected{element: &struct {
Foo map[string]struct{ Fii string }
}{
Foo: map[string]struct{ Fii string }{
"name1": {Fii: "hii"},
"name2": {Fii: "huu"},
}},
},
},
{
desc: "slice string",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "huu,hii,hoo", Kind: reflect.Slice},
},
},
element: &struct{ Foo []string }{},
expected: expected{element: &struct{ Foo []string }{Foo: []string{"huu", "hii", "hoo"}}},
},
{
desc: "slice named type",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "huu,hii,hoo", Kind: reflect.Slice},
},
},
element: &struct{ Foo []NamedType }{},
expected: expected{element: &struct{ Foo []NamedType }{Foo: []NamedType{"huu", "hii", "hoo"}}},
},
{
desc: "slice named type int",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "1,2,3", Kind: reflect.Slice},
},
},
element: &struct{ Foo []NamedTypeInt }{},
expected: expected{element: &struct{ Foo []NamedTypeInt }{Foo: []NamedTypeInt{1, 2, 3}}},
},
{
desc: "empty slice",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "", Kind: reflect.Slice},
},
},
element: &struct{ Foo []string }{},
expected: expected{element: &struct{ Foo []string }{Foo: nil}},
},
{
desc: "slice int",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int }{},
expected: expected{element: &struct{ Foo []int }{Foo: []int{4, 3, 6}}},
},
{
desc: "slice invalid int",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int }{},
expected: expected{error: true},
},
{
desc: "slice int8",
node: &Node{
Name: "traefik",
Kind: reflect.Slice,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int8 }{},
expected: expected{element: &struct{ Foo []int8 }{Foo: []int8{4, 3, 6}}},
},
{
desc: "slice invalid int8",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int8 }{},
expected: expected{error: true},
},
{
desc: "slice int16",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int16 }{},
expected: expected{element: &struct{ Foo []int16 }{Foo: []int16{4, 3, 6}}},
},
{
desc: "slice invalid int16",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int16 }{},
expected: expected{error: true},
},
{
desc: "slice int32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int32 }{},
expected: expected{element: &struct{ Foo []int32 }{Foo: []int32{4, 3, 6}}},
},
{
desc: "slice invalid int32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int32 }{},
expected: expected{error: true},
},
{
desc: "slice int64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int64 }{},
expected: expected{element: &struct{ Foo []int64 }{Foo: []int64{4, 3, 6}}},
},
{
desc: "slice invalid int64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []int64 }{},
expected: expected{error: true},
},
{
desc: "slice uint",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint }{},
expected: expected{element: &struct{ Foo []uint }{Foo: []uint{4, 3, 6}}},
},
{
desc: "slice invalid uint",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint }{},
expected: expected{error: true},
},
{
desc: "slice uint8",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint8 }{},
expected: expected{element: &struct{ Foo []uint8 }{Foo: []uint8{4, 3, 6}}},
},
{
desc: "slice invalid uint8",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint8 }{},
expected: expected{error: true},
},
{
desc: "slice uint16",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint16 }{},
expected: expected{element: &struct{ Foo []uint16 }{Foo: []uint16{4, 3, 6}}},
},
{
desc: "slice invalid uint16",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint16 }{},
expected: expected{error: true},
},
{
desc: "slice uint32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint32 }{},
expected: expected{element: &struct{ Foo []uint32 }{Foo: []uint32{4, 3, 6}}},
},
{
desc: "slice invalid uint32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint32 }{},
expected: expected{error: true},
},
{
desc: "slice uint64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint64 }{},
expected: expected{element: &struct{ Foo []uint64 }{Foo: []uint64{4, 3, 6}}},
},
{
desc: "slice invalid uint64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []uint64 }{},
expected: expected{error: true},
},
{
desc: "slice float32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []float32 }{},
expected: expected{element: &struct{ Foo []float32 }{Foo: []float32{4, 3, 6}}},
},
{
desc: "slice invalid float32",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []float32 }{},
expected: expected{error: true},
},
{
desc: "slice float64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4,3,6", Kind: reflect.Slice},
},
},
element: &struct{ Foo []float64 }{},
expected: expected{element: &struct{ Foo []float64 }{Foo: []float64{4, 3, 6}}},
},
{
desc: "slice invalid float64",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "four,three,six", Kind: reflect.Slice},
},
},
element: &struct{ Foo []float64 }{},
expected: expected{error: true},
},
{
desc: "slice bool",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "true, false, true", Kind: reflect.Slice},
},
},
element: &struct{ Foo []bool }{},
expected: expected{element: &struct{ Foo []bool }{Foo: []bool{true, false, true}}},
},
{
desc: "slice invalid bool",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "bool, false, true", Kind: reflect.Slice},
},
},
element: &struct{ Foo []bool }{},
expected: expected{error: true},
},
{
desc: "slice slice-as-struct",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Fii",
FieldName: "Foo",
Kind: reflect.Slice,
Tag: `label-slice-as-struct:"Fii"`,
Children: []*Node{
{Name: "bar", FieldName: "Bar", Kind: reflect.String, Value: "haa"},
{Name: "bir", FieldName: "Bir", Kind: reflect.String, Value: "hii"},
},
},
},
},
element: &struct {
Foo []struct {
Bar string
Bir string
} `label-slice-as-struct:"Fii"`
}{},
expected: expected{element: &struct {
Foo []struct {
Bar string
Bir string
} `label-slice-as-struct:"Fii"`
}{
Foo: []struct {
Bar string
Bir string
}{
{
Bar: "haa",
Bir: "hii",
},
},
}},
},
{
desc: "slice slice-as-struct pointer",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Fii",
FieldName: "Foo",
Kind: reflect.Slice,
Tag: `label-slice-as-struct:"Fii"`,
Children: []*Node{
{Name: "bar", FieldName: "Bar", Kind: reflect.String, Value: "haa"},
{Name: "bir", FieldName: "Bir", Kind: reflect.String, Value: "hii"},
},
},
},
},
element: &struct {
Foo []*struct {
Bar string
Bir string
} `label-slice-as-struct:"Fii"`
}{},
expected: expected{element: &struct {
Foo []*struct {
Bar string
Bir string
} `label-slice-as-struct:"Fii"`
}{
Foo: []*struct {
Bar string
Bir string
}{
{
Bar: "haa",
Bir: "hii",
},
},
}},
},
{
desc: "slice slice-as-struct without children",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Fii",
FieldName: "Foo",
Tag: `label-slice-as-struct:"Fii"`,
Kind: reflect.Slice,
},
},
},
element: &struct {
Foo []struct {
Bar string
Bir string
} `label-slice-as-struct:"Fii"`
}{},
expected: expected{error: true},
},
{
desc: "pointer SetDefaults method",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Fuu", FieldName: "Fuu", Value: "huu", Kind: reflect.String},
}},
}},
element: &struct {
Foo *InitializedFoo
}{},
expected: expected{element: &struct {
Foo *InitializedFoo
}{
Foo: &InitializedFoo{
Fii: "default",
Fuu: "huu",
},
}},
},
{
desc: "pointer wrong SetDefaults method",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Fuu", FieldName: "Fuu", Value: "huu", Kind: reflect.String},
}},
}},
element: &struct {
Foo *wrongInitialledFoo
}{},
expected: expected{element: &struct {
Foo *wrongInitialledFoo
}{
Foo: &wrongInitialledFoo{
Fuu: "huu",
},
}},
},
{
desc: "int pointer",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "4", Kind: reflect.Ptr},
},
},
element: &struct{ Foo *int }{},
expected: expected{element: &struct{ Foo *int }{Foo: func(v int) *int { return &v }(4)}},
},
{
desc: "bool pointer",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "true", Kind: reflect.Ptr},
},
},
element: &struct{ Foo *bool }{},
expected: expected{element: &struct{ Foo *bool }{Foo: func(v bool) *bool { return &v }(true)}},
},
{
desc: "string pointer",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Value: "bar", Kind: reflect.Ptr},
},
},
element: &struct{ Foo *string }{},
expected: expected{element: &struct{ Foo *string }{Foo: func(v string) *string { return &v }("bar")}},
},
{
desc: "embedded",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{
Name: "Foo",
FieldName: "Foo",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Fuu", FieldName: "Fuu", Value: "huu", Kind: reflect.String},
}},
}},
element: &struct {
Foo struct {
FiiFoo
}
}{},
expected: expected{element: &struct {
Foo struct {
FiiFoo
}
}{
Foo: struct {
FiiFoo
}{
FiiFoo: FiiFoo{
Fii: "",
Fuu: "huu",
},
},
}},
},
{
desc: "slice struct",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Kind: reflect.Slice, Children: []*Node{
{Name: "[0]", Kind: reflect.Struct, Children: []*Node{
{Name: "Field1", FieldName: "Field1", Value: "A", Kind: reflect.String},
{Name: "Field2", FieldName: "Field2", Value: "A", Kind: reflect.String},
}},
{Name: "[1]", Kind: reflect.Struct, Children: []*Node{
{Name: "Field1", FieldName: "Field1", Value: "B", Kind: reflect.String},
{Name: "Field2", FieldName: "Field2", Value: "B", Kind: reflect.String},
}},
{Name: "[2]", Kind: reflect.Struct, Children: []*Node{
{Name: "Field1", FieldName: "Field1", Value: "C", Kind: reflect.String},
{Name: "Field2", FieldName: "Field2", Value: "C", Kind: reflect.String},
}},
}},
},
},
element: &struct {
Foo []struct {
Field1 string
Field2 string
}
}{},
expected: expected{element: &struct {
Foo []struct {
Field1 string
Field2 string
}
}{
Foo: []struct {
Field1 string
Field2 string
}{
{Field1: "A", Field2: "A"},
{Field1: "B", Field2: "B"},
{Field1: "C", Field2: "C"},
},
}},
},
{
desc: "slice pointer struct",
node: &Node{
Name: "traefik",
Kind: reflect.Struct,
Children: []*Node{
{Name: "Foo", FieldName: "Foo", Kind: reflect.Slice, Children: []*Node{
{Name: "[0]", Kind: reflect.Ptr, Children: []*Node{
{Name: "Field1", FieldName: "Field1", Value: "A", Kind: reflect.String},
{Name: "Field2", FieldName: "Field2", Value: "A", Kind: reflect.String},
}},
{Name: "[1]", Kind: reflect.Ptr, Children: []*Node{
{Name: "Field1", FieldName: "Field1", Value: "B", Kind: reflect.String},
{Name: "Field2", FieldName: "Field2", Value: "B", Kind: reflect.String},
}},
{Name: "[2]", Kind: reflect.Ptr, Children: []*Node{
{Name: "Field1", FieldName: "Field1", Value: "C", Kind: reflect.String},
{Name: "Field2", FieldName: "Field2", Value: "C", Kind: reflect.String},
}},
}},
},
},
element: &struct {
Foo []*struct {
Field1 string
Field2 string
}
}{},
expected: expected{element: &struct {
Foo []*struct {
Field1 string
Field2 string
}
}{
Foo: []*struct {
Field1 string
Field2 string
}{
{Field1: "A", Field2: "A"},
{Field1: "B", Field2: "B"},
{Field1: "C", Field2: "C"},
},
}},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
err := Fill(test.element, test.node)
if test.expected.error {
require.Error(t, err)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected.element, test.element)
}
})
}
}
type NamedType string
type NamedTypeInt int
type InitializedFoo struct {
Fii string
Fuu string
}
func (t *InitializedFoo) SetDefaults() {
t.Fii = "default"
}
type wrongInitialledFoo struct {
Fii string
Fuu string
}
func (t *wrongInitialledFoo) SetDefaults() error {
t.Fii = "default"
return nil
}
type Bouya string
type FiiFoo struct {
Fii string
Fuu Bouya
}