1// Copyright © 2014 Steve Francia <spf@spf13.com>.
2//
3// Use of this source code is governed by an MIT-style
4// license that can be found in the LICENSE file.
5
6package cast
7
8import (
9	"fmt"
10	"html/template"
11	"testing"
12	"time"
13
14	"github.com/stretchr/testify/assert"
15)
16
17func TestToUintE(t *testing.T) {
18	tests := []struct {
19		input  interface{}
20		expect uint
21		iserr  bool
22	}{
23		{int(8), 8, false},
24		{int8(8), 8, false},
25		{int16(8), 8, false},
26		{int32(8), 8, false},
27		{int64(8), 8, false},
28		{uint(8), 8, false},
29		{uint8(8), 8, false},
30		{uint16(8), 8, false},
31		{uint32(8), 8, false},
32		{uint64(8), 8, false},
33		{float32(8.31), 8, false},
34		{float64(8.31), 8, false},
35		{true, 1, false},
36		{false, 0, false},
37		{"8", 8, false},
38		{nil, 0, false},
39		// errors
40		{int(-8), 0, true},
41		{int8(-8), 0, true},
42		{int16(-8), 0, true},
43		{int32(-8), 0, true},
44		{int64(-8), 0, true},
45		{float32(-8.31), 0, true},
46		{float64(-8.31), 0, true},
47		{"-8", 0, true},
48		{"test", 0, true},
49		{testing.T{}, 0, true},
50	}
51
52	for i, test := range tests {
53		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
54
55		v, err := ToUintE(test.input)
56		if test.iserr {
57			assert.Error(t, err, errmsg)
58			continue
59		}
60
61		assert.NoError(t, err, errmsg)
62		assert.Equal(t, test.expect, v, errmsg)
63
64		// Non-E test:
65		v = ToUint(test.input)
66		assert.Equal(t, test.expect, v, errmsg)
67	}
68}
69
70func TestToUint64E(t *testing.T) {
71	tests := []struct {
72		input  interface{}
73		expect uint64
74		iserr  bool
75	}{
76		{int(8), 8, false},
77		{int8(8), 8, false},
78		{int16(8), 8, false},
79		{int32(8), 8, false},
80		{int64(8), 8, false},
81		{uint(8), 8, false},
82		{uint8(8), 8, false},
83		{uint16(8), 8, false},
84		{uint32(8), 8, false},
85		{uint64(8), 8, false},
86		{float32(8.31), 8, false},
87		{float64(8.31), 8, false},
88		{true, 1, false},
89		{false, 0, false},
90		{"8", 8, false},
91		{nil, 0, false},
92		// errors
93		{int(-8), 0, true},
94		{int8(-8), 0, true},
95		{int16(-8), 0, true},
96		{int32(-8), 0, true},
97		{int64(-8), 0, true},
98		{float32(-8.31), 0, true},
99		{float64(-8.31), 0, true},
100		{"-8", 0, true},
101		{"test", 0, true},
102		{testing.T{}, 0, true},
103	}
104
105	for i, test := range tests {
106		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
107
108		v, err := ToUint64E(test.input)
109		if test.iserr {
110			assert.Error(t, err, errmsg)
111			continue
112		}
113
114		assert.NoError(t, err, errmsg)
115		assert.Equal(t, test.expect, v, errmsg)
116
117		// Non-E test:
118		v = ToUint64(test.input)
119		assert.Equal(t, test.expect, v, errmsg)
120	}
121}
122
123func TestToUint32E(t *testing.T) {
124	tests := []struct {
125		input  interface{}
126		expect uint32
127		iserr  bool
128	}{
129		{int(8), 8, false},
130		{int8(8), 8, false},
131		{int16(8), 8, false},
132		{int32(8), 8, false},
133		{int64(8), 8, false},
134		{uint(8), 8, false},
135		{uint8(8), 8, false},
136		{uint16(8), 8, false},
137		{uint32(8), 8, false},
138		{uint64(8), 8, false},
139		{float32(8.31), 8, false},
140		{float64(8.31), 8, false},
141		{true, 1, false},
142		{false, 0, false},
143		{"8", 8, false},
144		{nil, 0, false},
145		{int(-8), 0, true},
146		{int8(-8), 0, true},
147		{int16(-8), 0, true},
148		{int32(-8), 0, true},
149		{int64(-8), 0, true},
150		{float32(-8.31), 0, true},
151		{float64(-8.31), 0, true},
152		{"-8", 0, true},
153		// errors
154		{"test", 0, true},
155		{testing.T{}, 0, true},
156	}
157
158	for i, test := range tests {
159		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
160
161		v, err := ToUint32E(test.input)
162		if test.iserr {
163			assert.Error(t, err, errmsg)
164			continue
165		}
166
167		assert.NoError(t, err, errmsg)
168		assert.Equal(t, test.expect, v, errmsg)
169
170		// Non-E test:
171		v = ToUint32(test.input)
172		assert.Equal(t, test.expect, v, errmsg)
173	}
174}
175
176func TestToUint16E(t *testing.T) {
177	tests := []struct {
178		input  interface{}
179		expect uint16
180		iserr  bool
181	}{
182		{int(8), 8, false},
183		{int8(8), 8, false},
184		{int16(8), 8, false},
185		{int32(8), 8, false},
186		{int64(8), 8, false},
187		{uint(8), 8, false},
188		{uint8(8), 8, false},
189		{uint16(8), 8, false},
190		{uint32(8), 8, false},
191		{uint64(8), 8, false},
192		{float32(8.31), 8, false},
193		{float64(8.31), 8, false},
194		{true, 1, false},
195		{false, 0, false},
196		{"8", 8, false},
197		{nil, 0, false},
198		// errors
199		{int(-8), 0, true},
200		{int8(-8), 0, true},
201		{int16(-8), 0, true},
202		{int32(-8), 0, true},
203		{int64(-8), 0, true},
204		{float32(-8.31), 0, true},
205		{float64(-8.31), 0, true},
206		{"-8", 0, true},
207		{"test", 0, true},
208		{testing.T{}, 0, true},
209	}
210
211	for i, test := range tests {
212		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
213
214		v, err := ToUint16E(test.input)
215		if test.iserr {
216			assert.Error(t, err, errmsg)
217			continue
218		}
219
220		assert.NoError(t, err, errmsg)
221		assert.Equal(t, test.expect, v, errmsg)
222
223		// Non-E test
224		v = ToUint16(test.input)
225		assert.Equal(t, test.expect, v, errmsg)
226	}
227}
228
229func TestToUint8E(t *testing.T) {
230	tests := []struct {
231		input  interface{}
232		expect uint8
233		iserr  bool
234	}{
235		{int(8), 8, false},
236		{int8(8), 8, false},
237		{int16(8), 8, false},
238		{int32(8), 8, false},
239		{int64(8), 8, false},
240		{uint(8), 8, false},
241		{uint8(8), 8, false},
242		{uint16(8), 8, false},
243		{uint32(8), 8, false},
244		{uint64(8), 8, false},
245		{float32(8.31), 8, false},
246		{float64(8.31), 8, false},
247		{true, 1, false},
248		{false, 0, false},
249		{"8", 8, false},
250		{nil, 0, false},
251		// errors
252		{int(-8), 0, true},
253		{int8(-8), 0, true},
254		{int16(-8), 0, true},
255		{int32(-8), 0, true},
256		{int64(-8), 0, true},
257		{float32(-8.31), 0, true},
258		{float64(-8.31), 0, true},
259		{"-8", 0, true},
260		{"test", 0, true},
261		{testing.T{}, 0, true},
262	}
263
264	for i, test := range tests {
265		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
266
267		v, err := ToUint8E(test.input)
268		if test.iserr {
269			assert.Error(t, err, errmsg)
270			continue
271		}
272
273		assert.NoError(t, err, errmsg)
274		assert.Equal(t, test.expect, v, errmsg)
275
276		// Non-E test
277		v = ToUint8(test.input)
278		assert.Equal(t, test.expect, v, errmsg)
279	}
280}
281
282func TestToIntE(t *testing.T) {
283	tests := []struct {
284		input  interface{}
285		expect int
286		iserr  bool
287	}{
288		{int(8), 8, false},
289		{int8(8), 8, false},
290		{int16(8), 8, false},
291		{int32(8), 8, false},
292		{int64(8), 8, false},
293		{uint(8), 8, false},
294		{uint8(8), 8, false},
295		{uint16(8), 8, false},
296		{uint32(8), 8, false},
297		{uint64(8), 8, false},
298		{float32(8.31), 8, false},
299		{float64(8.31), 8, false},
300		{true, 1, false},
301		{false, 0, false},
302		{"8", 8, false},
303		{nil, 0, false},
304		// errors
305		{"test", 0, true},
306		{testing.T{}, 0, true},
307	}
308
309	for i, test := range tests {
310		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
311
312		v, err := ToIntE(test.input)
313		if test.iserr {
314			assert.Error(t, err, errmsg)
315			continue
316		}
317
318		assert.NoError(t, err, errmsg)
319		assert.Equal(t, test.expect, v, errmsg)
320
321		// Non-E test
322		v = ToInt(test.input)
323		assert.Equal(t, test.expect, v, errmsg)
324	}
325}
326
327func TestToInt64E(t *testing.T) {
328	tests := []struct {
329		input  interface{}
330		expect int64
331		iserr  bool
332	}{
333		{int(8), 8, false},
334		{int8(8), 8, false},
335		{int16(8), 8, false},
336		{int32(8), 8, false},
337		{int64(8), 8, false},
338		{uint(8), 8, false},
339		{uint8(8), 8, false},
340		{uint16(8), 8, false},
341		{uint32(8), 8, false},
342		{uint64(8), 8, false},
343		{float32(8.31), 8, false},
344		{float64(8.31), 8, false},
345		{true, 1, false},
346		{false, 0, false},
347		{"8", 8, false},
348		{nil, 0, false},
349		// errors
350		{"test", 0, true},
351		{testing.T{}, 0, true},
352	}
353
354	for i, test := range tests {
355		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
356
357		v, err := ToInt64E(test.input)
358		if test.iserr {
359			assert.Error(t, err, errmsg)
360			continue
361		}
362
363		assert.NoError(t, err, errmsg)
364		assert.Equal(t, test.expect, v, errmsg)
365
366		// Non-E test
367		v = ToInt64(test.input)
368		assert.Equal(t, test.expect, v, errmsg)
369	}
370}
371
372func TestToInt32E(t *testing.T) {
373	tests := []struct {
374		input  interface{}
375		expect int32
376		iserr  bool
377	}{
378		{int(8), 8, false},
379		{int8(8), 8, false},
380		{int16(8), 8, false},
381		{int32(8), 8, false},
382		{int64(8), 8, false},
383		{uint(8), 8, false},
384		{uint8(8), 8, false},
385		{uint16(8), 8, false},
386		{uint32(8), 8, false},
387		{uint64(8), 8, false},
388		{float32(8.31), 8, false},
389		{float64(8.31), 8, false},
390		{true, 1, false},
391		{false, 0, false},
392		{"8", 8, false},
393		{nil, 0, false},
394		// errors
395		{"test", 0, true},
396		{testing.T{}, 0, true},
397	}
398
399	for i, test := range tests {
400		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
401
402		v, err := ToInt32E(test.input)
403		if test.iserr {
404			assert.Error(t, err, errmsg)
405			continue
406		}
407
408		assert.NoError(t, err, errmsg)
409		assert.Equal(t, test.expect, v, errmsg)
410
411		// Non-E test
412		v = ToInt32(test.input)
413		assert.Equal(t, test.expect, v, errmsg)
414	}
415}
416
417func TestToInt16E(t *testing.T) {
418	tests := []struct {
419		input  interface{}
420		expect int16
421		iserr  bool
422	}{
423		{int(8), 8, false},
424		{int8(8), 8, false},
425		{int16(8), 8, false},
426		{int32(8), 8, false},
427		{int64(8), 8, false},
428		{uint(8), 8, false},
429		{uint8(8), 8, false},
430		{uint16(8), 8, false},
431		{uint32(8), 8, false},
432		{uint64(8), 8, false},
433		{float32(8.31), 8, false},
434		{float64(8.31), 8, false},
435		{true, 1, false},
436		{false, 0, false},
437		{"8", 8, false},
438		{nil, 0, false},
439		// errors
440		{"test", 0, true},
441		{testing.T{}, 0, true},
442	}
443
444	for i, test := range tests {
445		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
446
447		v, err := ToInt16E(test.input)
448		if test.iserr {
449			assert.Error(t, err, errmsg)
450			continue
451		}
452
453		assert.NoError(t, err, errmsg)
454		assert.Equal(t, test.expect, v, errmsg)
455
456		// Non-E test
457		v = ToInt16(test.input)
458		assert.Equal(t, test.expect, v, errmsg)
459	}
460}
461
462func TestToInt8E(t *testing.T) {
463	tests := []struct {
464		input  interface{}
465		expect int8
466		iserr  bool
467	}{
468		{int(8), 8, false},
469		{int8(8), 8, false},
470		{int16(8), 8, false},
471		{int32(8), 8, false},
472		{int64(8), 8, false},
473		{uint(8), 8, false},
474		{uint8(8), 8, false},
475		{uint16(8), 8, false},
476		{uint32(8), 8, false},
477		{uint64(8), 8, false},
478		{float32(8.31), 8, false},
479		{float64(8.31), 8, false},
480		{true, 1, false},
481		{false, 0, false},
482		{"8", 8, false},
483		{nil, 0, false},
484		// errors
485		{"test", 0, true},
486		{testing.T{}, 0, true},
487	}
488
489	for i, test := range tests {
490		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
491
492		v, err := ToInt8E(test.input)
493		if test.iserr {
494			assert.Error(t, err, errmsg)
495			continue
496		}
497
498		assert.NoError(t, err, errmsg)
499		assert.Equal(t, test.expect, v, errmsg)
500
501		// Non-E test
502		v = ToInt8(test.input)
503		assert.Equal(t, test.expect, v, errmsg)
504	}
505}
506
507func TestToFloat64E(t *testing.T) {
508	tests := []struct {
509		input  interface{}
510		expect float64
511		iserr  bool
512	}{
513		{int(8), 8, false},
514		{int8(8), 8, false},
515		{int16(8), 8, false},
516		{int32(8), 8, false},
517		{int64(8), 8, false},
518		{uint(8), 8, false},
519		{uint8(8), 8, false},
520		{uint16(8), 8, false},
521		{uint32(8), 8, false},
522		{uint64(8), 8, false},
523		{float32(8), 8, false},
524		{float64(8.31), 8.31, false},
525		{"8", 8, false},
526		{true, 1, false},
527		{false, 0, false},
528		// errors
529		{"test", 0, true},
530		{testing.T{}, 0, true},
531	}
532
533	for i, test := range tests {
534		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
535
536		v, err := ToFloat64E(test.input)
537		if test.iserr {
538			assert.Error(t, err, errmsg)
539			continue
540		}
541
542		assert.NoError(t, err, errmsg)
543		assert.Equal(t, test.expect, v, errmsg)
544
545		// Non-E test
546		v = ToFloat64(test.input)
547		assert.Equal(t, test.expect, v, errmsg)
548	}
549}
550
551func TestToFloat32E(t *testing.T) {
552	tests := []struct {
553		input  interface{}
554		expect float32
555		iserr  bool
556	}{
557		{int(8), 8, false},
558		{int8(8), 8, false},
559		{int16(8), 8, false},
560		{int32(8), 8, false},
561		{int64(8), 8, false},
562		{uint(8), 8, false},
563		{uint8(8), 8, false},
564		{uint16(8), 8, false},
565		{uint32(8), 8, false},
566		{uint64(8), 8, false},
567		{float32(8.31), 8.31, false},
568		{float64(8.31), 8.31, false},
569		{"8", 8, false},
570		{true, 1, false},
571		{false, 0, false},
572		// errors
573		{"test", 0, true},
574		{testing.T{}, 0, true},
575	}
576
577	for i, test := range tests {
578		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
579
580		v, err := ToFloat32E(test.input)
581		if test.iserr {
582			assert.Error(t, err, errmsg)
583			continue
584		}
585
586		assert.NoError(t, err, errmsg)
587		assert.Equal(t, test.expect, v, errmsg)
588
589		// Non-E test
590		v = ToFloat32(test.input)
591		assert.Equal(t, test.expect, v, errmsg)
592	}
593}
594
595func TestToStringE(t *testing.T) {
596	type Key struct {
597		k string
598	}
599	key := &Key{"foo"}
600
601	tests := []struct {
602		input  interface{}
603		expect string
604		iserr  bool
605	}{
606		{int(8), "8", false},
607		{int8(8), "8", false},
608		{int16(8), "8", false},
609		{int32(8), "8", false},
610		{int64(8), "8", false},
611		{uint(8), "8", false},
612		{uint8(8), "8", false},
613		{uint16(8), "8", false},
614		{uint32(8), "8", false},
615		{uint64(8), "8", false},
616		{float32(8.31), "8.31", false},
617		{float64(8.31), "8.31", false},
618		{true, "true", false},
619		{false, "false", false},
620		{nil, "", false},
621		{[]byte("one time"), "one time", false},
622		{"one more time", "one more time", false},
623		{template.HTML("one time"), "one time", false},
624		{template.URL("http://somehost.foo"), "http://somehost.foo", false},
625		{template.JS("(1+2)"), "(1+2)", false},
626		{template.CSS("a"), "a", false},
627		{template.HTMLAttr("a"), "a", false},
628		// errors
629		{testing.T{}, "", true},
630		{key, "", true},
631	}
632
633	for i, test := range tests {
634		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
635
636		v, err := ToStringE(test.input)
637		if test.iserr {
638			assert.Error(t, err, errmsg)
639			continue
640		}
641
642		assert.NoError(t, err, errmsg)
643		assert.Equal(t, test.expect, v, errmsg)
644
645		// Non-E test
646		v = ToString(test.input)
647		assert.Equal(t, test.expect, v, errmsg)
648	}
649}
650
651type foo struct {
652	val string
653}
654
655func (x foo) String() string {
656	return x.val
657}
658
659func TestStringerToString(t *testing.T) {
660	var x foo
661	x.val = "bar"
662	assert.Equal(t, "bar", ToString(x))
663}
664
665type fu struct {
666	val string
667}
668
669func (x fu) Error() string {
670	return x.val
671}
672
673func TestErrorToString(t *testing.T) {
674	var x fu
675	x.val = "bar"
676	assert.Equal(t, "bar", ToString(x))
677}
678
679func TestStringMapStringSliceE(t *testing.T) {
680	// ToStringMapString inputs/outputs
681	var stringMapString = map[string]string{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
682	var stringMapInterface = map[string]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
683	var interfaceMapString = map[interface{}]string{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
684	var interfaceMapInterface = map[interface{}]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
685
686	// ToStringMapStringSlice inputs/outputs
687	var stringMapStringSlice = map[string][]string{"key 1": {"value 1", "value 2", "value 3"}, "key 2": {"value 1", "value 2", "value 3"}, "key 3": {"value 1", "value 2", "value 3"}}
688	var stringMapInterfaceSlice = map[string][]interface{}{"key 1": {"value 1", "value 2", "value 3"}, "key 2": {"value 1", "value 2", "value 3"}, "key 3": {"value 1", "value 2", "value 3"}}
689	var stringMapInterfaceInterfaceSlice = map[string]interface{}{"key 1": []interface{}{"value 1", "value 2", "value 3"}, "key 2": []interface{}{"value 1", "value 2", "value 3"}, "key 3": []interface{}{"value 1", "value 2", "value 3"}}
690	var stringMapStringSingleSliceFieldsResult = map[string][]string{"key 1": {"value", "1"}, "key 2": {"value", "2"}, "key 3": {"value", "3"}}
691	var interfaceMapStringSlice = map[interface{}][]string{"key 1": {"value 1", "value 2", "value 3"}, "key 2": {"value 1", "value 2", "value 3"}, "key 3": {"value 1", "value 2", "value 3"}}
692	var interfaceMapInterfaceSlice = map[interface{}][]interface{}{"key 1": {"value 1", "value 2", "value 3"}, "key 2": {"value 1", "value 2", "value 3"}, "key 3": {"value 1", "value 2", "value 3"}}
693
694	var stringMapStringSliceMultiple = map[string][]string{"key 1": {"value 1", "value 2", "value 3"}, "key 2": {"value 1", "value 2", "value 3"}, "key 3": {"value 1", "value 2", "value 3"}}
695	var stringMapStringSliceSingle = map[string][]string{"key 1": {"value 1"}, "key 2": {"value 2"}, "key 3": {"value 3"}}
696
697	var stringMapInterface1 = map[string]interface{}{"key 1": []string{"value 1"}, "key 2": []string{"value 2"}}
698	var stringMapInterfaceResult1 = map[string][]string{"key 1": {"value 1"}, "key 2": {"value 2"}}
699
700	var jsonStringMapString = `{"key 1": "value 1", "key 2": "value 2"}`
701	var jsonStringMapStringArray = `{"key 1": ["value 1"], "key 2": ["value 2", "value 3"]}`
702	var jsonStringMapStringArrayResult = map[string][]string{"key 1": {"value 1"}, "key 2": {"value 2", "value 3"}}
703
704	type Key struct {
705		k string
706	}
707
708	tests := []struct {
709		input  interface{}
710		expect map[string][]string
711		iserr  bool
712	}{
713		{stringMapStringSlice, stringMapStringSlice, false},
714		{stringMapInterfaceSlice, stringMapStringSlice, false},
715		{stringMapInterfaceInterfaceSlice, stringMapStringSlice, false},
716		{stringMapStringSliceMultiple, stringMapStringSlice, false},
717		{stringMapStringSliceMultiple, stringMapStringSlice, false},
718		{stringMapString, stringMapStringSliceSingle, false},
719		{stringMapInterface, stringMapStringSliceSingle, false},
720		{stringMapInterface1, stringMapInterfaceResult1, false},
721		{interfaceMapStringSlice, stringMapStringSlice, false},
722		{interfaceMapInterfaceSlice, stringMapStringSlice, false},
723		{interfaceMapString, stringMapStringSingleSliceFieldsResult, false},
724		{interfaceMapInterface, stringMapStringSingleSliceFieldsResult, false},
725		{jsonStringMapStringArray, jsonStringMapStringArrayResult, false},
726
727		// errors
728		{nil, nil, true},
729		{testing.T{}, nil, true},
730		{map[interface{}]interface{}{"foo": testing.T{}}, nil, true},
731		{map[interface{}]interface{}{Key{"foo"}: "bar"}, nil, true}, // ToStringE(Key{"foo"}) should fail
732		{jsonStringMapString, nil, true},
733		{"", nil, true},
734	}
735
736	for i, test := range tests {
737		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
738
739		v, err := ToStringMapStringSliceE(test.input)
740		if test.iserr {
741			assert.Error(t, err, errmsg)
742			continue
743		}
744
745		assert.NoError(t, err, errmsg)
746		assert.Equal(t, test.expect, v, errmsg)
747
748		// Non-E test
749		v = ToStringMapStringSlice(test.input)
750		assert.Equal(t, test.expect, v, errmsg)
751	}
752}
753
754func TestToStringMapE(t *testing.T) {
755	tests := []struct {
756		input  interface{}
757		expect map[string]interface{}
758		iserr  bool
759	}{
760		{map[interface{}]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
761		{map[string]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
762		{`{"tag": "tags", "group": "groups"}`, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
763		{`{"tag": "tags", "group": true}`, map[string]interface{}{"tag": "tags", "group": true}, false},
764
765		// errors
766		{nil, nil, true},
767		{testing.T{}, nil, true},
768		{"", nil, true},
769	}
770
771	for i, test := range tests {
772		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
773
774		v, err := ToStringMapE(test.input)
775		if test.iserr {
776			assert.Error(t, err, errmsg)
777			continue
778		}
779
780		assert.NoError(t, err, errmsg)
781		assert.Equal(t, test.expect, v, errmsg)
782
783		// Non-E test
784		v = ToStringMap(test.input)
785		assert.Equal(t, test.expect, v, errmsg)
786	}
787}
788
789func TestToStringMapBoolE(t *testing.T) {
790	tests := []struct {
791		input  interface{}
792		expect map[string]bool
793		iserr  bool
794	}{
795		{map[interface{}]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
796		{map[string]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
797		{map[string]bool{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
798		{`{"v1": true, "v2": false}`, map[string]bool{"v1": true, "v2": false}, false},
799
800		// errors
801		{nil, nil, true},
802		{testing.T{}, nil, true},
803		{"", nil, true},
804	}
805
806	for i, test := range tests {
807		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
808
809		v, err := ToStringMapBoolE(test.input)
810		if test.iserr {
811			assert.Error(t, err, errmsg)
812			continue
813		}
814
815		assert.NoError(t, err, errmsg)
816		assert.Equal(t, test.expect, v, errmsg)
817
818		// Non-E test
819		v = ToStringMapBool(test.input)
820		assert.Equal(t, test.expect, v, errmsg)
821	}
822}
823
824func TestToStringMapIntE(t *testing.T) {
825	tests := []struct {
826		input  interface{}
827		expect map[string]int
828		iserr  bool
829	}{
830		{map[interface{}]interface{}{"v1": 1, "v2": 222}, map[string]int{"v1": 1, "v2": 222}, false},
831		{map[string]interface{}{"v1": 342, "v2": 5141}, map[string]int{"v1": 342, "v2": 5141}, false},
832		{map[string]int{"v1": 33, "v2": 88}, map[string]int{"v1": 33, "v2": 88}, false},
833		{map[string]int32{"v1": int32(33), "v2": int32(88)}, map[string]int{"v1": 33, "v2": 88}, false},
834		{map[string]uint16{"v1": uint16(33), "v2": uint16(88)}, map[string]int{"v1": 33, "v2": 88}, false},
835		{map[string]float64{"v1": float64(8.22), "v2": float64(43.32)}, map[string]int{"v1": 8, "v2": 43}, false},
836		{`{"v1": 67, "v2": 56}`, map[string]int{"v1": 67, "v2": 56}, false},
837
838		// errors
839		{nil, nil, true},
840		{testing.T{}, nil, true},
841		{"", nil, true},
842	}
843
844	for i, test := range tests {
845		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
846
847		v, err := ToStringMapIntE(test.input)
848		if test.iserr {
849			assert.Error(t, err, errmsg)
850			continue
851		}
852
853		assert.NoError(t, err, errmsg)
854		assert.Equal(t, test.expect, v, errmsg)
855
856		// Non-E test
857		v = ToStringMapInt(test.input)
858		assert.Equal(t, test.expect, v, errmsg)
859	}
860}
861
862func TestToStringMapInt64E(t *testing.T) {
863	tests := []struct {
864		input  interface{}
865		expect map[string]int64
866		iserr  bool
867	}{
868		{map[interface{}]interface{}{"v1": int32(8), "v2": int32(888)}, map[string]int64{"v1": int64(8), "v2": int64(888)}, false},
869		{map[string]interface{}{"v1": int64(45), "v2": int64(67)}, map[string]int64{"v1": 45, "v2": 67}, false},
870		{map[string]int64{"v1": 33, "v2": 88}, map[string]int64{"v1": 33, "v2": 88}, false},
871		{map[string]int{"v1": 33, "v2": 88}, map[string]int64{"v1": 33, "v2": 88}, false},
872		{map[string]int32{"v1": int32(33), "v2": int32(88)}, map[string]int64{"v1": 33, "v2": 88}, false},
873		{map[string]uint16{"v1": uint16(33), "v2": uint16(88)}, map[string]int64{"v1": 33, "v2": 88}, false},
874		{map[string]float64{"v1": float64(8.22), "v2": float64(43.32)}, map[string]int64{"v1": 8, "v2": 43}, false},
875		{`{"v1": 67, "v2": 56}`, map[string]int64{"v1": 67, "v2": 56}, false},
876
877		// errors
878		{nil, nil, true},
879		{testing.T{}, nil, true},
880		{"", nil, true},
881	}
882
883	for i, test := range tests {
884		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
885
886		v, err := ToStringMapInt64E(test.input)
887		if test.iserr {
888			assert.Error(t, err, errmsg)
889			continue
890		}
891
892		assert.NoError(t, err, errmsg)
893		assert.Equal(t, test.expect, v, errmsg)
894
895		// Non-E test
896		v = ToStringMapInt64(test.input)
897		assert.Equal(t, test.expect, v, errmsg)
898	}
899}
900
901func TestToStringMapStringE(t *testing.T) {
902	var stringMapString = map[string]string{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
903	var stringMapInterface = map[string]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
904	var interfaceMapString = map[interface{}]string{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
905	var interfaceMapInterface = map[interface{}]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
906	var jsonString = `{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}`
907	var invalidJsonString = `{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"`
908	var emptyString = ""
909
910	tests := []struct {
911		input  interface{}
912		expect map[string]string
913		iserr  bool
914	}{
915		{stringMapString, stringMapString, false},
916		{stringMapInterface, stringMapString, false},
917		{interfaceMapString, stringMapString, false},
918		{interfaceMapInterface, stringMapString, false},
919		{jsonString, stringMapString, false},
920
921		// errors
922		{nil, nil, true},
923		{testing.T{}, nil, true},
924		{invalidJsonString, nil, true},
925		{emptyString, nil, true},
926	}
927
928	for i, test := range tests {
929		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
930
931		v, err := ToStringMapStringE(test.input)
932		if test.iserr {
933			assert.Error(t, err, errmsg)
934			continue
935		}
936
937		assert.NoError(t, err, errmsg)
938		assert.Equal(t, test.expect, v, errmsg)
939
940		// Non-E test
941		v = ToStringMapString(test.input)
942		assert.Equal(t, test.expect, v, errmsg)
943	}
944}
945
946func TestToBoolSliceE(t *testing.T) {
947	tests := []struct {
948		input  interface{}
949		expect []bool
950		iserr  bool
951	}{
952		{[]bool{true, false, true}, []bool{true, false, true}, false},
953		{[]interface{}{true, false, true}, []bool{true, false, true}, false},
954		{[]int{1, 0, 1}, []bool{true, false, true}, false},
955		{[]string{"true", "false", "true"}, []bool{true, false, true}, false},
956		// errors
957		{nil, nil, true},
958		{testing.T{}, nil, true},
959		{[]string{"foo", "bar"}, nil, true},
960	}
961
962	for i, test := range tests {
963		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
964
965		v, err := ToBoolSliceE(test.input)
966		if test.iserr {
967			assert.Error(t, err, errmsg)
968			continue
969		}
970
971		assert.NoError(t, err, errmsg)
972		assert.Equal(t, test.expect, v, errmsg)
973
974		// Non-E test
975		v = ToBoolSlice(test.input)
976		assert.Equal(t, test.expect, v, errmsg)
977	}
978}
979
980func TestToIntSliceE(t *testing.T) {
981	tests := []struct {
982		input  interface{}
983		expect []int
984		iserr  bool
985	}{
986		{[]int{1, 3}, []int{1, 3}, false},
987		{[]interface{}{1.2, 3.2}, []int{1, 3}, false},
988		{[]string{"2", "3"}, []int{2, 3}, false},
989		{[2]string{"2", "3"}, []int{2, 3}, false},
990		// errors
991		{nil, nil, true},
992		{testing.T{}, nil, true},
993		{[]string{"foo", "bar"}, nil, true},
994	}
995
996	for i, test := range tests {
997		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
998
999		v, err := ToIntSliceE(test.input)
1000		if test.iserr {
1001			assert.Error(t, err, errmsg)
1002			continue
1003		}
1004
1005		assert.NoError(t, err, errmsg)
1006		assert.Equal(t, test.expect, v, errmsg)
1007
1008		// Non-E test
1009		v = ToIntSlice(test.input)
1010		assert.Equal(t, test.expect, v, errmsg)
1011	}
1012}
1013
1014func TestToSliceE(t *testing.T) {
1015	tests := []struct {
1016		input  interface{}
1017		expect []interface{}
1018		iserr  bool
1019	}{
1020		{[]interface{}{1, 3}, []interface{}{1, 3}, false},
1021		{[]map[string]interface{}{{"k1": 1}, {"k2": 2}}, []interface{}{map[string]interface{}{"k1": 1}, map[string]interface{}{"k2": 2}}, false},
1022		// errors
1023		{nil, nil, true},
1024		{testing.T{}, nil, true},
1025	}
1026
1027	for i, test := range tests {
1028		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
1029
1030		v, err := ToSliceE(test.input)
1031		if test.iserr {
1032			assert.Error(t, err, errmsg)
1033			continue
1034		}
1035
1036		assert.NoError(t, err, errmsg)
1037		assert.Equal(t, test.expect, v, errmsg)
1038
1039		// Non-E test
1040		v = ToSlice(test.input)
1041		assert.Equal(t, test.expect, v, errmsg)
1042	}
1043}
1044
1045func TestToStringSliceE(t *testing.T) {
1046	tests := []struct {
1047		input  interface{}
1048		expect []string
1049		iserr  bool
1050	}{
1051		{[]string{"a", "b"}, []string{"a", "b"}, false},
1052		{[]interface{}{1, 3}, []string{"1", "3"}, false},
1053		{interface{}(1), []string{"1"}, false},
1054		// errors
1055		{nil, nil, true},
1056		{testing.T{}, nil, true},
1057	}
1058
1059	for i, test := range tests {
1060		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
1061
1062		v, err := ToStringSliceE(test.input)
1063		if test.iserr {
1064			assert.Error(t, err, errmsg)
1065			continue
1066		}
1067
1068		assert.NoError(t, err, errmsg)
1069		assert.Equal(t, test.expect, v, errmsg)
1070
1071		// Non-E test
1072		v = ToStringSlice(test.input)
1073		assert.Equal(t, test.expect, v, errmsg)
1074	}
1075}
1076
1077func TestToDurationSliceE(t *testing.T) {
1078	tests := []struct {
1079		input  interface{}
1080		expect []time.Duration
1081		iserr  bool
1082	}{
1083		{[]string{"1s", "1m"}, []time.Duration{time.Second, time.Minute}, false},
1084		{[]int{1, 2}, []time.Duration{1, 2}, false},
1085		{[]interface{}{1, 3}, []time.Duration{1, 3}, false},
1086		{[]time.Duration{1, 3}, []time.Duration{1, 3}, false},
1087
1088		// errors
1089		{nil, nil, true},
1090		{testing.T{}, nil, true},
1091		{[]string{"invalid"}, nil, true},
1092	}
1093
1094	for i, test := range tests {
1095		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
1096
1097		v, err := ToDurationSliceE(test.input)
1098		if test.iserr {
1099			assert.Error(t, err, errmsg)
1100			continue
1101		}
1102
1103		assert.NoError(t, err, errmsg)
1104		assert.Equal(t, test.expect, v, errmsg)
1105
1106		// Non-E test
1107		v = ToDurationSlice(test.input)
1108		assert.Equal(t, test.expect, v, errmsg)
1109	}
1110}
1111
1112func TestToBoolE(t *testing.T) {
1113	tests := []struct {
1114		input  interface{}
1115		expect bool
1116		iserr  bool
1117	}{
1118		{0, false, false},
1119		{nil, false, false},
1120		{"false", false, false},
1121		{"FALSE", false, false},
1122		{"False", false, false},
1123		{"f", false, false},
1124		{"F", false, false},
1125		{false, false, false},
1126
1127		{"true", true, false},
1128		{"TRUE", true, false},
1129		{"True", true, false},
1130		{"t", true, false},
1131		{"T", true, false},
1132		{1, true, false},
1133		{true, true, false},
1134		{-1, true, false},
1135
1136		// errors
1137		{"test", false, true},
1138		{testing.T{}, false, true},
1139	}
1140
1141	for i, test := range tests {
1142		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
1143
1144		v, err := ToBoolE(test.input)
1145		if test.iserr {
1146			assert.Error(t, err, errmsg)
1147			continue
1148		}
1149
1150		assert.NoError(t, err, errmsg)
1151		assert.Equal(t, test.expect, v, errmsg)
1152
1153		// Non-E test
1154		v = ToBool(test.input)
1155		assert.Equal(t, test.expect, v, errmsg)
1156	}
1157}
1158
1159func BenchmarkTooBool(b *testing.B) {
1160	for i := 0; i < b.N; i++ {
1161		if !ToBool(true) {
1162			b.Fatal("ToBool returned false")
1163		}
1164	}
1165}
1166
1167func TestIndirectPointers(t *testing.T) {
1168	x := 13
1169	y := &x
1170	z := &y
1171
1172	assert.Equal(t, ToInt(y), 13)
1173	assert.Equal(t, ToInt(z), 13)
1174}
1175
1176func TestToTimeEE(t *testing.T) {
1177	tests := []struct {
1178		input  interface{}
1179		expect time.Time
1180		iserr  bool
1181	}{
1182		{"2009-11-10 23:00:00 +0000 UTC", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},   // Time.String()
1183		{"Tue Nov 10 23:00:00 2009", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},        // ANSIC
1184		{"Tue Nov 10 23:00:00 UTC 2009", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},    // UnixDate
1185		{"Tue Nov 10 23:00:00 +0000 2009", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},  // RubyDate
1186		{"10 Nov 09 23:00 UTC", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},             // RFC822
1187		{"10 Nov 09 23:00 +0000", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},           // RFC822Z
1188		{"Tuesday, 10-Nov-09 23:00:00 UTC", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false}, // RFC850
1189		{"Tue, 10 Nov 2009 23:00:00 UTC", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},   // RFC1123
1190		{"Tue, 10 Nov 2009 23:00:00 +0000", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false}, // RFC1123Z
1191		{"2009-11-10T23:00:00Z", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},            // RFC3339
1192		{"2018-10-21T23:21:29+0200", time.Date(2018, 10, 21, 21, 21, 29, 0, time.UTC), false},      // RFC3339 without timezone hh:mm colon
1193		{"2009-11-10T23:00:00Z", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},            // RFC3339Nano
1194		{"11:00PM", time.Date(0, 1, 1, 23, 0, 0, 0, time.UTC), false},                              // Kitchen
1195		{"Nov 10 23:00:00", time.Date(0, 11, 10, 23, 0, 0, 0, time.UTC), false},                    // Stamp
1196		{"Nov 10 23:00:00.000", time.Date(0, 11, 10, 23, 0, 0, 0, time.UTC), false},                // StampMilli
1197		{"Nov 10 23:00:00.000000", time.Date(0, 11, 10, 23, 0, 0, 0, time.UTC), false},             // StampMicro
1198		{"Nov 10 23:00:00.000000000", time.Date(0, 11, 10, 23, 0, 0, 0, time.UTC), false},          // StampNano
1199		{"2016-03-06 15:28:01-00:00", time.Date(2016, 3, 6, 15, 28, 1, 0, time.UTC), false},        // RFC3339 without T
1200		{"2016-03-06 15:28:01-0000", time.Date(2016, 3, 6, 15, 28, 1, 0, time.UTC), false},         // RFC3339 without T or timezone hh:mm colon
1201		{"2016-03-06 15:28:01", time.Date(2016, 3, 6, 15, 28, 1, 0, time.UTC), false},
1202		{"2016-03-06 15:28:01 -0000", time.Date(2016, 3, 6, 15, 28, 1, 0, time.UTC), false},
1203		{"2016-03-06 15:28:01 -00:00", time.Date(2016, 3, 6, 15, 28, 1, 0, time.UTC), false},
1204		{"2006-01-02", time.Date(2006, 1, 2, 0, 0, 0, 0, time.UTC), false},
1205		{"02 Jan 2006", time.Date(2006, 1, 2, 0, 0, 0, 0, time.UTC), false},
1206		{1472574600, time.Date(2016, 8, 30, 16, 30, 0, 0, time.UTC), false},
1207		{int(1482597504), time.Date(2016, 12, 24, 16, 38, 24, 0, time.UTC), false},
1208		{int64(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1209		{int32(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1210		{uint(1482597504), time.Date(2016, 12, 24, 16, 38, 24, 0, time.UTC), false},
1211		{uint64(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1212		{uint32(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1213		{time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1214		// errors
1215		{"2006", time.Time{}, true},
1216		{testing.T{}, time.Time{}, true},
1217	}
1218
1219	for i, test := range tests {
1220		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
1221
1222		v, err := ToTimeE(test.input)
1223		if test.iserr {
1224			assert.Error(t, err, errmsg)
1225			continue
1226		}
1227
1228		assert.NoError(t, err, errmsg)
1229		assert.Equal(t, test.expect, v.UTC(), errmsg)
1230
1231		// Non-E test
1232		v = ToTime(test.input)
1233		assert.Equal(t, test.expect, v.UTC(), errmsg)
1234	}
1235}
1236
1237func TestToDurationE(t *testing.T) {
1238	var td time.Duration = 5
1239
1240	tests := []struct {
1241		input  interface{}
1242		expect time.Duration
1243		iserr  bool
1244	}{
1245		{time.Duration(5), td, false},
1246		{int(5), td, false},
1247		{int64(5), td, false},
1248		{int32(5), td, false},
1249		{int16(5), td, false},
1250		{int8(5), td, false},
1251		{uint(5), td, false},
1252		{uint64(5), td, false},
1253		{uint32(5), td, false},
1254		{uint16(5), td, false},
1255		{uint8(5), td, false},
1256		{float64(5), td, false},
1257		{float32(5), td, false},
1258		{string("5"), td, false},
1259		{string("5ns"), td, false},
1260		{string("5us"), time.Microsecond * td, false},
1261		{string("5µs"), time.Microsecond * td, false},
1262		{string("5ms"), time.Millisecond * td, false},
1263		{string("5s"), time.Second * td, false},
1264		{string("5m"), time.Minute * td, false},
1265		{string("5h"), time.Hour * td, false},
1266		// errors
1267		{"test", 0, true},
1268		{testing.T{}, 0, true},
1269	}
1270
1271	for i, test := range tests {
1272		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
1273
1274		v, err := ToDurationE(test.input)
1275		if test.iserr {
1276			assert.Error(t, err, errmsg)
1277			continue
1278		}
1279
1280		assert.NoError(t, err, errmsg)
1281		assert.Equal(t, test.expect, v, errmsg)
1282
1283		// Non-E test
1284		v = ToDuration(test.input)
1285		assert.Equal(t, test.expect, v, errmsg)
1286	}
1287}
1288