1
2
3
4
5 package properties
6
7 import (
8 "reflect"
9 "testing"
10 "time"
11 )
12
13 func TestDecodeValues(t *testing.T) {
14 type S struct {
15 S string
16 BT bool
17 BF bool
18 I int
19 I8 int8
20 I16 int16
21 I32 int32
22 I64 int64
23 U uint
24 U8 uint8
25 U16 uint16
26 U32 uint32
27 U64 uint64
28 F32 float32
29 F64 float64
30 D time.Duration
31 TM time.Time
32 }
33 in := `
34 S=abc
35 BT=true
36 BF=false
37 I=-1
38 I8=-8
39 I16=-16
40 I32=-32
41 I64=-64
42 U=1
43 U8=8
44 U16=16
45 U32=32
46 U64=64
47 F32=3.2
48 F64=6.4
49 D=5s
50 TM=2015-01-02T12:34:56Z
51 `
52 out := &S{
53 S: "abc",
54 BT: true,
55 BF: false,
56 I: -1,
57 I8: -8,
58 I16: -16,
59 I32: -32,
60 I64: -64,
61 U: 1,
62 U8: 8,
63 U16: 16,
64 U32: 32,
65 U64: 64,
66 F32: 3.2,
67 F64: 6.4,
68 D: 5 * time.Second,
69 TM: tm(t, time.RFC3339, "2015-01-02T12:34:56Z"),
70 }
71 testDecode(t, in, &S{}, out)
72 }
73
74 func TestDecodeValueDefaults(t *testing.T) {
75 type S struct {
76 S string `properties:",default=abc"`
77 BT bool `properties:",default=true"`
78 BF bool `properties:",default=false"`
79 I int `properties:",default=-1"`
80 I8 int8 `properties:",default=-8"`
81 I16 int16 `properties:",default=-16"`
82 I32 int32 `properties:",default=-32"`
83 I64 int64 `properties:",default=-64"`
84 U uint `properties:",default=1"`
85 U8 uint8 `properties:",default=8"`
86 U16 uint16 `properties:",default=16"`
87 U32 uint32 `properties:",default=32"`
88 U64 uint64 `properties:",default=64"`
89 F32 float32 `properties:",default=3.2"`
90 F64 float64 `properties:",default=6.4"`
91 D time.Duration `properties:",default=5s"`
92 TM time.Time `properties:",default=2015-01-02T12:34:56Z"`
93 }
94 out := &S{
95 S: "abc",
96 BT: true,
97 BF: false,
98 I: -1,
99 I8: -8,
100 I16: -16,
101 I32: -32,
102 I64: -64,
103 U: 1,
104 U8: 8,
105 U16: 16,
106 U32: 32,
107 U64: 64,
108 F32: 3.2,
109 F64: 6.4,
110 D: 5 * time.Second,
111 TM: tm(t, time.RFC3339, "2015-01-02T12:34:56Z"),
112 }
113 testDecode(t, "", &S{}, out)
114 }
115
116 func TestDecodeArrays(t *testing.T) {
117 type S struct {
118 S []string
119 B []bool
120 I []int
121 I8 []int8
122 I16 []int16
123 I32 []int32
124 I64 []int64
125 U []uint
126 U8 []uint8
127 U16 []uint16
128 U32 []uint32
129 U64 []uint64
130 F32 []float32
131 F64 []float64
132 D []time.Duration
133 TM []time.Time
134 }
135 in := `
136 S=a;b
137 B=true;false
138 I=-1;-2
139 I8=-8;-9
140 I16=-16;-17
141 I32=-32;-33
142 I64=-64;-65
143 U=1;2
144 U8=8;9
145 U16=16;17
146 U32=32;33
147 U64=64;65
148 F32=3.2;3.3
149 F64=6.4;6.5
150 D=4s;5s
151 TM=2015-01-01T00:00:00Z;2016-01-01T00:00:00Z
152 `
153 out := &S{
154 S: []string{"a", "b"},
155 B: []bool{true, false},
156 I: []int{-1, -2},
157 I8: []int8{-8, -9},
158 I16: []int16{-16, -17},
159 I32: []int32{-32, -33},
160 I64: []int64{-64, -65},
161 U: []uint{1, 2},
162 U8: []uint8{8, 9},
163 U16: []uint16{16, 17},
164 U32: []uint32{32, 33},
165 U64: []uint64{64, 65},
166 F32: []float32{3.2, 3.3},
167 F64: []float64{6.4, 6.5},
168 D: []time.Duration{4 * time.Second, 5 * time.Second},
169 TM: []time.Time{tm(t, time.RFC3339, "2015-01-01T00:00:00Z"), tm(t, time.RFC3339, "2016-01-01T00:00:00Z")},
170 }
171 testDecode(t, in, &S{}, out)
172 }
173
174 func TestDecodeArrayDefaults(t *testing.T) {
175 type S struct {
176 S []string `properties:",default=a;b"`
177 B []bool `properties:",default=true;false"`
178 I []int `properties:",default=-1;-2"`
179 I8 []int8 `properties:",default=-8;-9"`
180 I16 []int16 `properties:",default=-16;-17"`
181 I32 []int32 `properties:",default=-32;-33"`
182 I64 []int64 `properties:",default=-64;-65"`
183 U []uint `properties:",default=1;2"`
184 U8 []uint8 `properties:",default=8;9"`
185 U16 []uint16 `properties:",default=16;17"`
186 U32 []uint32 `properties:",default=32;33"`
187 U64 []uint64 `properties:",default=64;65"`
188 F32 []float32 `properties:",default=3.2;3.3"`
189 F64 []float64 `properties:",default=6.4;6.5"`
190 D []time.Duration `properties:",default=4s;5s"`
191 TM []time.Time `properties:",default=2015-01-01T00:00:00Z;2016-01-01T00:00:00Z"`
192 }
193 out := &S{
194 S: []string{"a", "b"},
195 B: []bool{true, false},
196 I: []int{-1, -2},
197 I8: []int8{-8, -9},
198 I16: []int16{-16, -17},
199 I32: []int32{-32, -33},
200 I64: []int64{-64, -65},
201 U: []uint{1, 2},
202 U8: []uint8{8, 9},
203 U16: []uint16{16, 17},
204 U32: []uint32{32, 33},
205 U64: []uint64{64, 65},
206 F32: []float32{3.2, 3.3},
207 F64: []float64{6.4, 6.5},
208 D: []time.Duration{4 * time.Second, 5 * time.Second},
209 TM: []time.Time{tm(t, time.RFC3339, "2015-01-01T00:00:00Z"), tm(t, time.RFC3339, "2016-01-01T00:00:00Z")},
210 }
211 testDecode(t, "", &S{}, out)
212 }
213
214 func TestDecodeSkipUndef(t *testing.T) {
215 type S struct {
216 X string `properties:"-"`
217 Undef string `properties:",default=some value"`
218 }
219 in := `X=ignore`
220 out := &S{"", "some value"}
221 testDecode(t, in, &S{}, out)
222 }
223
224 func TestDecodeStruct(t *testing.T) {
225 type A struct {
226 S string
227 T string `properties:"t"`
228 U string `properties:"u,default=uuu"`
229 }
230 type S struct {
231 A A
232 B A `properties:"b"`
233 }
234 in := `
235 A.S=sss
236 A.t=ttt
237 b.S=SSS
238 b.t=TTT
239 `
240 out := &S{
241 A{S: "sss", T: "ttt", U: "uuu"},
242 A{S: "SSS", T: "TTT", U: "uuu"},
243 }
244 testDecode(t, in, &S{}, out)
245 }
246
247 func TestDecodeMap(t *testing.T) {
248 type S struct {
249 A string `properties:"a"`
250 }
251 type X struct {
252 A map[string]string
253 B map[string][]string
254 C map[string]map[string]string
255 D map[string]S
256 E map[string]int
257 F map[string]int `properties:"-"`
258 }
259 in := `
260 A.foo=bar
261 A.bar=bang
262 B.foo=a;b;c
263 B.bar=1;2;3
264 C.foo.one=1
265 C.foo.two=2
266 C.bar.three=3
267 C.bar.four=4
268 D.foo.a=bar
269 `
270 out := &X{
271 A: map[string]string{"foo": "bar", "bar": "bang"},
272 B: map[string][]string{"foo": {"a", "b", "c"}, "bar": {"1", "2", "3"}},
273 C: map[string]map[string]string{"foo": {"one": "1", "two": "2"}, "bar": {"three": "3", "four": "4"}},
274 D: map[string]S{"foo": {"bar"}},
275 E: map[string]int{},
276 }
277 testDecode(t, in, &X{}, out)
278 }
279
280 func testDecode(t *testing.T, in string, v, out interface{}) {
281 p, err := parse(in)
282 if err != nil {
283 t.Fatalf("got %v want nil", err)
284 }
285 if err := p.Decode(v); err != nil {
286 t.Fatalf("got %v want nil", err)
287 }
288 if got, want := v, out; !reflect.DeepEqual(got, want) {
289 t.Fatalf("\ngot %+v\nwant %+v", got, want)
290 }
291 }
292
293 func tm(t *testing.T, layout, s string) time.Time {
294 tm, err := time.Parse(layout, s)
295 if err != nil {
296 t.Fatalf("got %v want nil", err)
297 }
298 return tm
299 }
300
View as plain text