296 lines
6.3 KiB
Go
296 lines
6.3 KiB
Go
package properties
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestDecodeValues(t *testing.T) {
|
|
type S struct {
|
|
S string
|
|
BT bool
|
|
BF bool
|
|
I int
|
|
I8 int8
|
|
I16 int16
|
|
I32 int32
|
|
I64 int64
|
|
U uint
|
|
U8 uint8
|
|
U16 uint16
|
|
U32 uint32
|
|
U64 uint64
|
|
F32 float32
|
|
F64 float64
|
|
D time.Duration
|
|
TM time.Time
|
|
}
|
|
in := `
|
|
S=abc
|
|
BT=true
|
|
BF=false
|
|
I=-1
|
|
I8=-8
|
|
I16=-16
|
|
I32=-32
|
|
I64=-64
|
|
U=1
|
|
U8=8
|
|
U16=16
|
|
U32=32
|
|
U64=64
|
|
F32=3.2
|
|
F64=6.4
|
|
D=5s
|
|
TM=2015-01-02T12:34:56Z
|
|
`
|
|
out := &S{
|
|
S: "abc",
|
|
BT: true,
|
|
BF: false,
|
|
I: -1,
|
|
I8: -8,
|
|
I16: -16,
|
|
I32: -32,
|
|
I64: -64,
|
|
U: 1,
|
|
U8: 8,
|
|
U16: 16,
|
|
U32: 32,
|
|
U64: 64,
|
|
F32: 3.2,
|
|
F64: 6.4,
|
|
D: 5 * time.Second,
|
|
TM: tm(t, time.RFC3339, "2015-01-02T12:34:56Z"),
|
|
}
|
|
testDecode(t, in, &S{}, out)
|
|
}
|
|
|
|
func TestDecodeValueDefaults(t *testing.T) {
|
|
type S struct {
|
|
S string `properties:",default=abc"`
|
|
BT bool `properties:",default=true"`
|
|
BF bool `properties:",default=false"`
|
|
I int `properties:",default=-1"`
|
|
I8 int8 `properties:",default=-8"`
|
|
I16 int16 `properties:",default=-16"`
|
|
I32 int32 `properties:",default=-32"`
|
|
I64 int64 `properties:",default=-64"`
|
|
U uint `properties:",default=1"`
|
|
U8 uint8 `properties:",default=8"`
|
|
U16 uint16 `properties:",default=16"`
|
|
U32 uint32 `properties:",default=32"`
|
|
U64 uint64 `properties:",default=64"`
|
|
F32 float32 `properties:",default=3.2"`
|
|
F64 float64 `properties:",default=6.4"`
|
|
D time.Duration `properties:",default=5s"`
|
|
TM time.Time `properties:",default=2015-01-02T12:34:56Z"`
|
|
}
|
|
out := &S{
|
|
S: "abc",
|
|
BT: true,
|
|
BF: false,
|
|
I: -1,
|
|
I8: -8,
|
|
I16: -16,
|
|
I32: -32,
|
|
I64: -64,
|
|
U: 1,
|
|
U8: 8,
|
|
U16: 16,
|
|
U32: 32,
|
|
U64: 64,
|
|
F32: 3.2,
|
|
F64: 6.4,
|
|
D: 5 * time.Second,
|
|
TM: tm(t, time.RFC3339, "2015-01-02T12:34:56Z"),
|
|
}
|
|
testDecode(t, "", &S{}, out)
|
|
}
|
|
|
|
func TestDecodeArrays(t *testing.T) {
|
|
type S struct {
|
|
S []string
|
|
B []bool
|
|
I []int
|
|
I8 []int8
|
|
I16 []int16
|
|
I32 []int32
|
|
I64 []int64
|
|
U []uint
|
|
U8 []uint8
|
|
U16 []uint16
|
|
U32 []uint32
|
|
U64 []uint64
|
|
F32 []float32
|
|
F64 []float64
|
|
D []time.Duration
|
|
TM []time.Time
|
|
}
|
|
in := `
|
|
S=a;b
|
|
B=true;false
|
|
I=-1;-2
|
|
I8=-8;-9
|
|
I16=-16;-17
|
|
I32=-32;-33
|
|
I64=-64;-65
|
|
U=1;2
|
|
U8=8;9
|
|
U16=16;17
|
|
U32=32;33
|
|
U64=64;65
|
|
F32=3.2;3.3
|
|
F64=6.4;6.5
|
|
D=4s;5s
|
|
TM=2015-01-01T00:00:00Z;2016-01-01T00:00:00Z
|
|
`
|
|
out := &S{
|
|
S: []string{"a", "b"},
|
|
B: []bool{true, false},
|
|
I: []int{-1, -2},
|
|
I8: []int8{-8, -9},
|
|
I16: []int16{-16, -17},
|
|
I32: []int32{-32, -33},
|
|
I64: []int64{-64, -65},
|
|
U: []uint{1, 2},
|
|
U8: []uint8{8, 9},
|
|
U16: []uint16{16, 17},
|
|
U32: []uint32{32, 33},
|
|
U64: []uint64{64, 65},
|
|
F32: []float32{3.2, 3.3},
|
|
F64: []float64{6.4, 6.5},
|
|
D: []time.Duration{4 * time.Second, 5 * time.Second},
|
|
TM: []time.Time{tm(t, time.RFC3339, "2015-01-01T00:00:00Z"), tm(t, time.RFC3339, "2016-01-01T00:00:00Z")},
|
|
}
|
|
testDecode(t, in, &S{}, out)
|
|
}
|
|
|
|
func TestDecodeArrayDefaults(t *testing.T) {
|
|
type S struct {
|
|
S []string `properties:",default=a;b"`
|
|
B []bool `properties:",default=true;false"`
|
|
I []int `properties:",default=-1;-2"`
|
|
I8 []int8 `properties:",default=-8;-9"`
|
|
I16 []int16 `properties:",default=-16;-17"`
|
|
I32 []int32 `properties:",default=-32;-33"`
|
|
I64 []int64 `properties:",default=-64;-65"`
|
|
U []uint `properties:",default=1;2"`
|
|
U8 []uint8 `properties:",default=8;9"`
|
|
U16 []uint16 `properties:",default=16;17"`
|
|
U32 []uint32 `properties:",default=32;33"`
|
|
U64 []uint64 `properties:",default=64;65"`
|
|
F32 []float32 `properties:",default=3.2;3.3"`
|
|
F64 []float64 `properties:",default=6.4;6.5"`
|
|
D []time.Duration `properties:",default=4s;5s"`
|
|
TM []time.Time `properties:",default=2015-01-01T00:00:00Z;2016-01-01T00:00:00Z"`
|
|
}
|
|
out := &S{
|
|
S: []string{"a", "b"},
|
|
B: []bool{true, false},
|
|
I: []int{-1, -2},
|
|
I8: []int8{-8, -9},
|
|
I16: []int16{-16, -17},
|
|
I32: []int32{-32, -33},
|
|
I64: []int64{-64, -65},
|
|
U: []uint{1, 2},
|
|
U8: []uint8{8, 9},
|
|
U16: []uint16{16, 17},
|
|
U32: []uint32{32, 33},
|
|
U64: []uint64{64, 65},
|
|
F32: []float32{3.2, 3.3},
|
|
F64: []float64{6.4, 6.5},
|
|
D: []time.Duration{4 * time.Second, 5 * time.Second},
|
|
TM: []time.Time{tm(t, time.RFC3339, "2015-01-01T00:00:00Z"), tm(t, time.RFC3339, "2016-01-01T00:00:00Z")},
|
|
}
|
|
testDecode(t, "", &S{}, out)
|
|
}
|
|
|
|
func TestDecodeSkipUndef(t *testing.T) {
|
|
type S struct {
|
|
X string `properties:"-"`
|
|
Undef string `properties:",default=some value"`
|
|
}
|
|
in := `X=ignore`
|
|
out := &S{"", "some value"}
|
|
testDecode(t, in, &S{}, out)
|
|
}
|
|
|
|
func TestDecodeStruct(t *testing.T) {
|
|
type A struct {
|
|
S string
|
|
T string `properties:"t"`
|
|
U string `properties:"u,default=uuu"`
|
|
}
|
|
type S struct {
|
|
A A
|
|
B A `properties:"b"`
|
|
}
|
|
in := `
|
|
A.S=sss
|
|
A.t=ttt
|
|
b.S=SSS
|
|
b.t=TTT
|
|
`
|
|
out := &S{
|
|
A{S: "sss", T: "ttt", U: "uuu"},
|
|
A{S: "SSS", T: "TTT", U: "uuu"},
|
|
}
|
|
testDecode(t, in, &S{}, out)
|
|
}
|
|
|
|
func TestDecodeMap(t *testing.T) {
|
|
type S struct {
|
|
A string `properties:"a"`
|
|
}
|
|
type X struct {
|
|
A map[string]string
|
|
B map[string][]string
|
|
C map[string]map[string]string
|
|
D map[string]S
|
|
E map[string]int
|
|
F map[string]int `properties:"-"`
|
|
}
|
|
in := `
|
|
A.foo=bar
|
|
A.bar=bang
|
|
B.foo=a;b;c
|
|
B.bar=1;2;3
|
|
C.foo.one=1
|
|
C.foo.two=2
|
|
C.bar.three=3
|
|
C.bar.four=4
|
|
D.foo.a=bar
|
|
`
|
|
out := &X{
|
|
A: map[string]string{"foo": "bar", "bar": "bang"},
|
|
B: map[string][]string{"foo": []string{"a", "b", "c"}, "bar": []string{"1", "2", "3"}},
|
|
C: map[string]map[string]string{"foo": map[string]string{"one": "1", "two": "2"}, "bar": map[string]string{"three": "3", "four": "4"}},
|
|
D: map[string]S{"foo": S{"bar"}},
|
|
E: map[string]int{},
|
|
}
|
|
testDecode(t, in, &X{}, out)
|
|
}
|
|
|
|
func testDecode(t *testing.T, in string, v, out interface{}) {
|
|
p, err := parse(in)
|
|
if err != nil {
|
|
t.Fatalf("got %v want nil", err)
|
|
}
|
|
if err := p.Decode(v); err != nil {
|
|
t.Fatalf("got %v want nil", err)
|
|
}
|
|
if got, want := v, out; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("\ngot %+v\nwant %+v", got, want)
|
|
}
|
|
}
|
|
|
|
func tm(t *testing.T, layout, s string) time.Time {
|
|
tm, err := time.Parse(layout, s)
|
|
if err != nil {
|
|
t.Fatalf("got %v want nil", err)
|
|
}
|
|
return tm
|
|
}
|