2019-06-17 09:48:05 +00:00
|
|
|
package file
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
2019-08-03 01:58:23 +00:00
|
|
|
"github.com/containous/traefik/v2/pkg/config/parser"
|
2019-06-17 09:48:05 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func Test_decodeRawToNode(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
data map[string]interface{}
|
|
|
|
expected *parser.Node
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "empty",
|
|
|
|
data: map[string]interface{}{},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "string",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "bar"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "string named type",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": bar("bar"),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "bar"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "bool",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": true,
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "true"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": 1,
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int8",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": int8(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int16",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": int16(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int32",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": int32(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int64",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": int64(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "uint",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": uint(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "uint8",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": uint8(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "uint16",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": uint16(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "uint32",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": uint32(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "uint64",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": uint64(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "float32",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": float32(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "float64",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": float64(1),
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "string slice",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []string{"A", "B"},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "A,B"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int slice",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []int{1, 2},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1,2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int8 slice",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []int8{1, 2},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1,2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int16 slice",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []int16{1, 2},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1,2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int32 slice",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []int32{1, 2},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1,2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int64 slice",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []int64{1, 2},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1,2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "bool slice",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []bool{true, false},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "true,false"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "interface (string) slice",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []interface{}{"A", "B"},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "A,B"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "interface (int) slice",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []interface{}{1, 2},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Value: "1,2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "2 strings",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": "bar",
|
|
|
|
"fii": "bir",
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "fii", Value: "bir"},
|
|
|
|
{Name: "foo", Value: "bar"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "string, level 2",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"fii": map[interface{}]interface{}{
|
|
|
|
"fuu": "bur",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "fii", Children: []*parser.Node{{Name: "fuu", Value: "bur"}}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int, level 2",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"fii": map[interface{}]interface{}{
|
|
|
|
"fuu": 1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "fii", Children: []*parser.Node{{Name: "fuu", Value: "1"}}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "uint, level 2",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"fii": map[interface{}]interface{}{
|
|
|
|
"fuu": uint(1),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "fii", Children: []*parser.Node{{Name: "fuu", Value: "1"}}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "bool, level 2",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"fii": map[interface{}]interface{}{
|
|
|
|
"fuu": true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "fii", Children: []*parser.Node{{Name: "fuu", Value: "true"}}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "string, level 3",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": map[interface{}]interface{}{
|
|
|
|
"fii": map[interface{}]interface{}{
|
|
|
|
"fuu": "bur",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Children: []*parser.Node{
|
|
|
|
{Name: "fii", Children: []*parser.Node{{Name: "fuu", Value: "bur"}}},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "int, level 3",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"fii": map[interface{}]interface{}{
|
|
|
|
"fuu": 1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "fii", Children: []*parser.Node{{Name: "fuu", Value: "1"}}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "uint, level 3",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"fii": map[interface{}]interface{}{
|
|
|
|
"fuu": uint(1),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "fii", Children: []*parser.Node{{Name: "fuu", Value: "1"}}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "bool, level 3",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"fii": map[interface{}]interface{}{
|
|
|
|
"fuu": true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "fii", Children: []*parser.Node{{Name: "fuu", Value: "true"}}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "struct",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": map[interface{}]interface{}{
|
|
|
|
"field1": "C",
|
|
|
|
"field2": "C",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Children: []*parser.Node{
|
|
|
|
{Name: "field1", Value: "C"},
|
|
|
|
{Name: "field2", Value: "C"},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "slice struct 1",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []map[string]interface{}{
|
|
|
|
{"field1": "A", "field2": "A"},
|
|
|
|
{"field1": "B", "field2": "B"},
|
|
|
|
{"field2": "C", "field1": "C"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Children: []*parser.Node{
|
|
|
|
{Name: "[0]", Children: []*parser.Node{
|
|
|
|
{Name: "field1", Value: "A"},
|
|
|
|
{Name: "field2", Value: "A"},
|
|
|
|
}},
|
|
|
|
{Name: "[1]", Children: []*parser.Node{
|
|
|
|
{Name: "field1", Value: "B"},
|
|
|
|
{Name: "field2", Value: "B"},
|
|
|
|
}},
|
|
|
|
{Name: "[2]", Children: []*parser.Node{
|
|
|
|
{Name: "field1", Value: "C"},
|
|
|
|
{Name: "field2", Value: "C"},
|
|
|
|
}},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "slice struct 2",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": []interface{}{
|
|
|
|
map[interface{}]interface{}{
|
|
|
|
"field2": "A",
|
|
|
|
"field1": "A",
|
|
|
|
},
|
|
|
|
map[interface{}]interface{}{
|
|
|
|
"field1": "B",
|
|
|
|
"field2": "B",
|
|
|
|
},
|
|
|
|
map[interface{}]interface{}{
|
|
|
|
"field1": "C",
|
|
|
|
"field2": "C",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "foo", Children: []*parser.Node{
|
|
|
|
{Name: "[0]", Children: []*parser.Node{
|
|
|
|
{Name: "field1", Value: "A"},
|
|
|
|
{Name: "field2", Value: "A"},
|
|
|
|
}},
|
|
|
|
{Name: "[1]", Children: []*parser.Node{
|
|
|
|
{Name: "field1", Value: "B"},
|
|
|
|
{Name: "field2", Value: "B"},
|
|
|
|
}},
|
|
|
|
{Name: "[2]", Children: []*parser.Node{
|
|
|
|
{Name: "field1", Value: "C"},
|
|
|
|
{Name: "field2", Value: "C"},
|
|
|
|
}},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-07-17 09:04:04 +00:00
|
|
|
{
|
|
|
|
desc: "nil value",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"fii": map[interface{}]interface{}{
|
|
|
|
"fuu": nil,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: &parser.Node{
|
|
|
|
Name: "traefik",
|
|
|
|
Children: []*parser.Node{
|
|
|
|
{Name: "fii"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2019-06-17 09:48:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
test := test
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
2019-06-21 08:08:04 +00:00
|
|
|
node, err := decodeRawToNode(test.data, parser.DefaultRootName)
|
2019-06-17 09:48:05 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
assert.Equal(t, test.expected, node)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2019-09-30 15:52:04 +00:00
|
|
|
|
|
|
|
func Test_decodeRawToNode_errors(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
data map[string]interface{}
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "invalid type",
|
|
|
|
data: map[string]interface{}{
|
|
|
|
"foo": struct{}{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
test := test
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
_, err := decodeRawToNode(test.data, parser.DefaultRootName)
|
|
|
|
require.Error(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|