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	type Key struct {
701		k string
702	}
703
704	tests := []struct {
705		input  interface{}
706		expect map[string][]string
707		iserr  bool
708	}{
709		{stringMapStringSlice, stringMapStringSlice, false},
710		{stringMapInterfaceSlice, stringMapStringSlice, false},
711		{stringMapInterfaceInterfaceSlice, stringMapStringSlice, false},
712		{stringMapStringSliceMultiple, stringMapStringSlice, false},
713		{stringMapStringSliceMultiple, stringMapStringSlice, false},
714		{stringMapString, stringMapStringSliceSingle, false},
715		{stringMapInterface, stringMapStringSliceSingle, false},
716		{stringMapInterface1, stringMapInterfaceResult1, false},
717		{interfaceMapStringSlice, stringMapStringSlice, false},
718		{interfaceMapInterfaceSlice, stringMapStringSlice, false},
719		{interfaceMapString, stringMapStringSingleSliceFieldsResult, false},
720		{interfaceMapInterface, stringMapStringSingleSliceFieldsResult, false},
721		// errors
722		{nil, nil, true},
723		{testing.T{}, nil, true},
724		{map[interface{}]interface{}{"foo": testing.T{}}, nil, true},
725		{map[interface{}]interface{}{Key{"foo"}: "bar"}, nil, true}, // ToStringE(Key{"foo"}) should fail
726	}
727
728	for i, test := range tests {
729		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
730
731		v, err := ToStringMapStringSliceE(test.input)
732		if test.iserr {
733			assert.Error(t, err, errmsg)
734			continue
735		}
736
737		assert.NoError(t, err, errmsg)
738		assert.Equal(t, test.expect, v, errmsg)
739
740		// Non-E test
741		v = ToStringMapStringSlice(test.input)
742		assert.Equal(t, test.expect, v, errmsg)
743	}
744}
745
746func TestToStringMapE(t *testing.T) {
747	tests := []struct {
748		input  interface{}
749		expect map[string]interface{}
750		iserr  bool
751	}{
752		{map[interface{}]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
753		{map[string]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
754		// errors
755		{nil, nil, true},
756		{testing.T{}, nil, true},
757	}
758
759	for i, test := range tests {
760		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
761
762		v, err := ToStringMapE(test.input)
763		if test.iserr {
764			assert.Error(t, err, errmsg)
765			continue
766		}
767
768		assert.NoError(t, err, errmsg)
769		assert.Equal(t, test.expect, v, errmsg)
770
771		// Non-E test
772		v = ToStringMap(test.input)
773		assert.Equal(t, test.expect, v, errmsg)
774	}
775}
776
777func TestToStringMapBoolE(t *testing.T) {
778	tests := []struct {
779		input  interface{}
780		expect map[string]bool
781		iserr  bool
782	}{
783		{map[interface{}]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
784		{map[string]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
785		{map[string]bool{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
786		// errors
787		{nil, nil, true},
788		{testing.T{}, nil, true},
789	}
790
791	for i, test := range tests {
792		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
793
794		v, err := ToStringMapBoolE(test.input)
795		if test.iserr {
796			assert.Error(t, err, errmsg)
797			continue
798		}
799
800		assert.NoError(t, err, errmsg)
801		assert.Equal(t, test.expect, v, errmsg)
802
803		// Non-E test
804		v = ToStringMapBool(test.input)
805		assert.Equal(t, test.expect, v, errmsg)
806	}
807}
808
809func TestToStringMapStringE(t *testing.T) {
810	var stringMapString = map[string]string{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
811	var stringMapInterface = map[string]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
812	var interfaceMapString = map[interface{}]string{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
813	var interfaceMapInterface = map[interface{}]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
814
815	tests := []struct {
816		input  interface{}
817		expect map[string]string
818		iserr  bool
819	}{
820		{stringMapString, stringMapString, false},
821		{stringMapInterface, stringMapString, false},
822		{interfaceMapString, stringMapString, false},
823		{interfaceMapInterface, stringMapString, false},
824		// errors
825		{nil, nil, true},
826		{testing.T{}, nil, true},
827	}
828
829	for i, test := range tests {
830		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
831
832		v, err := ToStringMapStringE(test.input)
833		if test.iserr {
834			assert.Error(t, err, errmsg)
835			continue
836		}
837
838		assert.NoError(t, err, errmsg)
839		assert.Equal(t, test.expect, v, errmsg)
840
841		// Non-E test
842		v = ToStringMapString(test.input)
843		assert.Equal(t, test.expect, v, errmsg)
844	}
845}
846
847func TestToBoolSliceE(t *testing.T) {
848	tests := []struct {
849		input  interface{}
850		expect []bool
851		iserr  bool
852	}{
853		{[]bool{true, false, true}, []bool{true, false, true}, false},
854		{[]interface{}{true, false, true}, []bool{true, false, true}, false},
855		{[]int{1, 0, 1}, []bool{true, false, true}, false},
856		{[]string{"true", "false", "true"}, []bool{true, false, true}, false},
857		// errors
858		{nil, nil, true},
859		{testing.T{}, nil, true},
860		{[]string{"foo", "bar"}, nil, true},
861	}
862
863	for i, test := range tests {
864		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
865
866		v, err := ToBoolSliceE(test.input)
867		if test.iserr {
868			assert.Error(t, err, errmsg)
869			continue
870		}
871
872		assert.NoError(t, err, errmsg)
873		assert.Equal(t, test.expect, v, errmsg)
874
875		// Non-E test
876		v = ToBoolSlice(test.input)
877		assert.Equal(t, test.expect, v, errmsg)
878	}
879}
880
881func TestToIntSliceE(t *testing.T) {
882	tests := []struct {
883		input  interface{}
884		expect []int
885		iserr  bool
886	}{
887		{[]int{1, 3}, []int{1, 3}, false},
888		{[]interface{}{1.2, 3.2}, []int{1, 3}, false},
889		{[]string{"2", "3"}, []int{2, 3}, false},
890		{[2]string{"2", "3"}, []int{2, 3}, false},
891		// errors
892		{nil, nil, true},
893		{testing.T{}, nil, true},
894		{[]string{"foo", "bar"}, nil, true},
895	}
896
897	for i, test := range tests {
898		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
899
900		v, err := ToIntSliceE(test.input)
901		if test.iserr {
902			assert.Error(t, err, errmsg)
903			continue
904		}
905
906		assert.NoError(t, err, errmsg)
907		assert.Equal(t, test.expect, v, errmsg)
908
909		// Non-E test
910		v = ToIntSlice(test.input)
911		assert.Equal(t, test.expect, v, errmsg)
912	}
913}
914
915func TestToSliceE(t *testing.T) {
916	tests := []struct {
917		input  interface{}
918		expect []interface{}
919		iserr  bool
920	}{
921		{[]interface{}{1, 3}, []interface{}{1, 3}, false},
922		{[]map[string]interface{}{{"k1": 1}, {"k2": 2}}, []interface{}{map[string]interface{}{"k1": 1}, map[string]interface{}{"k2": 2}}, false},
923		// errors
924		{nil, nil, true},
925		{testing.T{}, nil, true},
926	}
927
928	for i, test := range tests {
929		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
930
931		v, err := ToSliceE(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 = ToSlice(test.input)
942		assert.Equal(t, test.expect, v, errmsg)
943	}
944}
945
946func TestToStringSliceE(t *testing.T) {
947	tests := []struct {
948		input  interface{}
949		expect []string
950		iserr  bool
951	}{
952		{[]string{"a", "b"}, []string{"a", "b"}, false},
953		{[]interface{}{1, 3}, []string{"1", "3"}, false},
954		{interface{}(1), []string{"1"}, false},
955		// errors
956		{nil, nil, true},
957		{testing.T{}, nil, true},
958	}
959
960	for i, test := range tests {
961		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
962
963		v, err := ToStringSliceE(test.input)
964		if test.iserr {
965			assert.Error(t, err, errmsg)
966			continue
967		}
968
969		assert.NoError(t, err, errmsg)
970		assert.Equal(t, test.expect, v, errmsg)
971
972		// Non-E test
973		v = ToStringSlice(test.input)
974		assert.Equal(t, test.expect, v, errmsg)
975	}
976}
977
978func TestToDurationSliceE(t *testing.T) {
979	tests := []struct {
980		input  interface{}
981		expect []time.Duration
982		iserr  bool
983	}{
984		{[]string{"1s", "1m"}, []time.Duration{time.Second, time.Minute}, false},
985		{[]int{1, 2}, []time.Duration{1, 2}, false},
986		{[]interface{}{1, 3}, []time.Duration{1, 3}, false},
987		// errors
988		{nil, nil, true},
989		{testing.T{}, nil, true},
990	}
991
992	for i, test := range tests {
993		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
994
995		v, err := ToDurationSliceE(test.input)
996		if test.iserr {
997			assert.Error(t, err, errmsg)
998			continue
999		}
1000
1001		assert.NoError(t, err, errmsg)
1002		assert.Equal(t, test.expect, v, errmsg)
1003
1004		// Non-E test
1005		v = ToDurationSlice(test.input)
1006		assert.Equal(t, test.expect, v, errmsg)
1007	}
1008}
1009
1010func TestToBoolE(t *testing.T) {
1011	tests := []struct {
1012		input  interface{}
1013		expect bool
1014		iserr  bool
1015	}{
1016		{0, false, false},
1017		{nil, false, false},
1018		{"false", false, false},
1019		{"FALSE", false, false},
1020		{"False", false, false},
1021		{"f", false, false},
1022		{"F", false, false},
1023		{false, false, false},
1024
1025		{"true", true, false},
1026		{"TRUE", true, false},
1027		{"True", true, false},
1028		{"t", true, false},
1029		{"T", true, false},
1030		{1, true, false},
1031		{true, true, false},
1032		{-1, true, false},
1033
1034		// errors
1035		{"test", false, true},
1036		{testing.T{}, false, true},
1037	}
1038
1039	for i, test := range tests {
1040		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
1041
1042		v, err := ToBoolE(test.input)
1043		if test.iserr {
1044			assert.Error(t, err, errmsg)
1045			continue
1046		}
1047
1048		assert.NoError(t, err, errmsg)
1049		assert.Equal(t, test.expect, v, errmsg)
1050
1051		// Non-E test
1052		v = ToBool(test.input)
1053		assert.Equal(t, test.expect, v, errmsg)
1054	}
1055}
1056
1057func BenchmarkTooBool(b *testing.B) {
1058	for i := 0; i < b.N; i++ {
1059		if !ToBool(true) {
1060			b.Fatal("ToBool returned false")
1061		}
1062	}
1063}
1064
1065func TestIndirectPointers(t *testing.T) {
1066	x := 13
1067	y := &x
1068	z := &y
1069
1070	assert.Equal(t, ToInt(y), 13)
1071	assert.Equal(t, ToInt(z), 13)
1072}
1073
1074func TestToTimeEE(t *testing.T) {
1075	tests := []struct {
1076		input  interface{}
1077		expect time.Time
1078		iserr  bool
1079	}{
1080		{"2009-11-10 23:00:00 +0000 UTC", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},   // Time.String()
1081		{"Tue Nov 10 23:00:00 2009", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},        // ANSIC
1082		{"Tue Nov 10 23:00:00 UTC 2009", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},    // UnixDate
1083		{"Tue Nov 10 23:00:00 +0000 2009", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},  // RubyDate
1084		{"10 Nov 09 23:00 UTC", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},             // RFC822
1085		{"10 Nov 09 23:00 +0000", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},           // RFC822Z
1086		{"Tuesday, 10-Nov-09 23:00:00 UTC", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false}, // RFC850
1087		{"Tue, 10 Nov 2009 23:00:00 UTC", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},   // RFC1123
1088		{"Tue, 10 Nov 2009 23:00:00 +0000", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false}, // RFC1123Z
1089		{"2009-11-10T23:00:00Z", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},            // RFC3339
1090		{"2009-11-10T23:00:00Z", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC), false},            // RFC3339Nano
1091		{"11:00PM", time.Date(0, 1, 1, 23, 0, 0, 0, time.UTC), false},                              // Kitchen
1092		{"Nov 10 23:00:00", time.Date(0, 11, 10, 23, 0, 0, 0, time.UTC), false},                    // Stamp
1093		{"Nov 10 23:00:00.000", time.Date(0, 11, 10, 23, 0, 0, 0, time.UTC), false},                // StampMilli
1094		{"Nov 10 23:00:00.000000", time.Date(0, 11, 10, 23, 0, 0, 0, time.UTC), false},             // StampMicro
1095		{"Nov 10 23:00:00.000000000", time.Date(0, 11, 10, 23, 0, 0, 0, time.UTC), false},          // StampNano
1096		{"2016-03-06 15:28:01-00:00", time.Date(2016, 3, 6, 15, 28, 1, 0, time.UTC), false},        // RFC3339 without T
1097		{"2016-03-06 15:28:01", time.Date(2016, 3, 6, 15, 28, 1, 0, time.UTC), false},
1098		{"2016-03-06 15:28:01 -0000", time.Date(2016, 3, 6, 15, 28, 1, 0, time.UTC), false},
1099		{"2016-03-06 15:28:01 -00:00", time.Date(2016, 3, 6, 15, 28, 1, 0, time.UTC), false},
1100		{"2006-01-02", time.Date(2006, 1, 2, 0, 0, 0, 0, time.UTC), false},
1101		{"02 Jan 2006", time.Date(2006, 1, 2, 0, 0, 0, 0, time.UTC), false},
1102		{1472574600, time.Date(2016, 8, 30, 16, 30, 0, 0, time.UTC), false},
1103		{int(1482597504), time.Date(2016, 12, 24, 16, 38, 24, 0, time.UTC), false},
1104		{int64(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1105		{int32(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1106		{uint(1482597504), time.Date(2016, 12, 24, 16, 38, 24, 0, time.UTC), false},
1107		{uint64(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1108		{uint32(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1109		{time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false},
1110		// errors
1111		{"2006", time.Time{}, true},
1112		{testing.T{}, time.Time{}, true},
1113	}
1114
1115	for i, test := range tests {
1116		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
1117
1118		v, err := ToTimeE(test.input)
1119		if test.iserr {
1120			assert.Error(t, err, errmsg)
1121			continue
1122		}
1123
1124		assert.NoError(t, err, errmsg)
1125		assert.Equal(t, test.expect, v.UTC(), errmsg)
1126
1127		// Non-E test
1128		v = ToTime(test.input)
1129		assert.Equal(t, test.expect, v.UTC(), errmsg)
1130	}
1131}
1132
1133func TestToDurationE(t *testing.T) {
1134	var td time.Duration = 5
1135
1136	tests := []struct {
1137		input  interface{}
1138		expect time.Duration
1139		iserr  bool
1140	}{
1141		{time.Duration(5), td, false},
1142		{int(5), td, false},
1143		{int64(5), td, false},
1144		{int32(5), td, false},
1145		{int16(5), td, false},
1146		{int8(5), td, false},
1147		{uint(5), td, false},
1148		{uint64(5), td, false},
1149		{uint32(5), td, false},
1150		{uint16(5), td, false},
1151		{uint8(5), td, false},
1152		{float64(5), td, false},
1153		{float32(5), td, false},
1154		{string("5"), td, false},
1155		{string("5ns"), td, false},
1156		{string("5us"), time.Microsecond * td, false},
1157		{string("5µs"), time.Microsecond * td, false},
1158		{string("5ms"), time.Millisecond * td, false},
1159		{string("5s"), time.Second * td, false},
1160		{string("5m"), time.Minute * td, false},
1161		{string("5h"), time.Hour * td, false},
1162		// errors
1163		{"test", 0, true},
1164		{testing.T{}, 0, true},
1165	}
1166
1167	for i, test := range tests {
1168		errmsg := fmt.Sprintf("i = %d", i) // assert helper message
1169
1170		v, err := ToDurationE(test.input)
1171		if test.iserr {
1172			assert.Error(t, err, errmsg)
1173			continue
1174		}
1175
1176		assert.NoError(t, err, errmsg)
1177		assert.Equal(t, test.expect, v, errmsg)
1178
1179		// Non-E test
1180		v = ToDuration(test.input)
1181		assert.Equal(t, test.expect, v, errmsg)
1182	}
1183}
1184