diff options
| author | Dave Henderson <dhenderson@gmail.com> | 2018-08-24 21:12:11 -0400 |
|---|---|---|
| committer | Dave Henderson <dhenderson@gmail.com> | 2018-09-24 23:22:40 -0400 |
| commit | cc0dc067c7362adfb1de802c86c3bab1601b5fe0 (patch) | |
| tree | a59826f272902b2ba138c95e3a1eba6cfad7dda6 /conv | |
| parent | 2eeb9a78c06835db36b2df169e26334cb9d65c86 (diff) | |
Return error instead of using log.Fatal
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
Diffstat (limited to 'conv')
| -rw-r--r-- | conv/conv.go | 20 | ||||
| -rw-r--r-- | conv/conv_test.go | 181 |
2 files changed, 122 insertions, 79 deletions
diff --git a/conv/conv.go b/conv/conv.go index 442ba216..0920dffc 100644 --- a/conv/conv.go +++ b/conv/conv.go @@ -2,10 +2,11 @@ package conv import ( "fmt" - "log" "reflect" "strconv" "strings" + + "github.com/pkg/errors" ) // Bool converts a string to a boolean value, using strconv.ParseBool under the covers. @@ -71,35 +72,36 @@ func Slice(args ...interface{}) []interface{} { // // This is functionally identical to strings.Join, except that each element is // coerced to a string first -func Join(in interface{}, sep string) string { +func Join(in interface{}, sep string) (out string, err error) { s, ok := in.([]string) if ok { - return strings.Join(s, sep) + return strings.Join(s, sep), nil } var a []interface{} a, ok = in.([]interface{}) if !ok { - var err error a, err = interfaceSlice(in) - ok = err == nil + if err != nil { + return "", errors.Wrap(err, "Input to Join must be an array") + } + ok = true } if ok { b := make([]string, len(a)) for i := range a { b[i] = ToString(a[i]) } - return strings.Join(b, sep) + return strings.Join(b, sep), nil } - log.Fatal("Input to Join must be an array") - return "" + return "", errors.New("Input to Join must be an array") } func interfaceSlice(slice interface{}) ([]interface{}, error) { s := reflect.ValueOf(slice) if s.Kind() != reflect.Slice { - return nil, fmt.Errorf("interfaceSlice given a non-slice type %T", s) + return nil, errors.Errorf("interfaceSlice given a non-slice type %T", s) } ret := make([]interface{}, s.Len()) for i := 0; i < s.Len(); i++ { diff --git a/conv/conv_test.go b/conv/conv_test.go index 43bc6d80..72db4f4e 100644 --- a/conv/conv_test.go +++ b/conv/conv_test.go @@ -9,19 +9,27 @@ import ( ) func TestBool(t *testing.T) { - assert.False(t, Bool("")) - assert.False(t, Bool("asdf")) - assert.False(t, Bool("1234")) - assert.False(t, Bool("False")) - assert.False(t, Bool("0")) - assert.False(t, Bool("false")) - assert.False(t, Bool("F")) - assert.False(t, Bool("f")) - assert.True(t, Bool("true")) - assert.True(t, Bool("True")) - assert.True(t, Bool("t")) - assert.True(t, Bool("T")) - assert.True(t, Bool("1")) + testdata := []struct { + in string + out bool + }{ + {"", false}, + {"asdf", false}, + {"1234", false}, + {"False", false}, + {"0", false}, + {"false", false}, + {"F", false}, + {"f", false}, + {"true", true}, + {"True", true}, + {"t", true}, + {"T", true}, + {"1", true}, + } + for _, d := range testdata { + assert.Equal(t, d.out, Bool(d.in)) + } } func TestSlice(t *testing.T) { @@ -32,19 +40,29 @@ func TestSlice(t *testing.T) { } func TestJoin(t *testing.T) { - - assert.Equal(t, "foo,bar", Join([]interface{}{"foo", "bar"}, ",")) - assert.Equal(t, "foo,\nbar", Join([]interface{}{"foo", "bar"}, ",\n")) - // Join handles all kinds of scalar types too... - assert.Equal(t, "42-18446744073709551615", Join([]interface{}{42, uint64(18446744073709551615)}, "-")) - assert.Equal(t, "42,100", Join([]int{42, 100}, ",")) - assert.Equal(t, "42,100", Join([]int64{42, 100}, ",")) - assert.Equal(t, "42,100", Join([]uint64{42, 100}, ",")) - assert.Equal(t, "true,false", Join([]bool{true, false}, ",")) - assert.Equal(t, "1,2", Join([]float64{1, 2}, ",")) - assert.Equal(t, "1,,true,3.14,foo,nil", Join([]interface{}{1, "", true, 3.14, "foo", nil}, ",")) - // and best-effort with weird types - assert.Equal(t, "[foo],bar", Join([]interface{}{[]string{"foo"}, "bar"}, ",")) + testdata := []struct { + in interface{} + sep string + out string + }{ + {[]interface{}{"foo", "bar"}, ",", "foo,bar"}, + {[]interface{}{"foo", "bar"}, ",\n", "foo,\nbar"}, + // Join handles all kinds of scalar types too... + {[]interface{}{42, uint64(18446744073709551615)}, "-", "42-18446744073709551615"}, + {[]int{42, 100}, ",", "42,100"}, + {[]int64{42, 100}, ",", "42,100"}, + {[]uint64{42, 100}, ",", "42,100"}, + {[]bool{true, false}, ",", "true,false"}, + {[]float64{1, 2}, ",", "1,2"}, + {[]interface{}{1, "", true, 3.14, "foo", nil}, ",", "1,,true,3.14,foo,nil"}, + // and best-effort with weird types + {[]interface{}{[]string{"foo"}, "bar"}, ",", "[foo],bar"}, + } + for _, d := range testdata { + out, err := Join(d.in, d.sep) + assert.NoError(t, err) + assert.Equal(t, d.out, out) + } } func TestHas(t *testing.T) { @@ -56,13 +74,23 @@ func TestHas(t *testing.T) { }, } - assert.True(t, Has(in, "foo")) - assert.False(t, Has(in, "bar")) - assert.True(t, Has(in["baz"], "qux")) - assert.True(t, Has([]string{"foo", "bar", "baz"}, "bar")) - assert.True(t, Has([]interface{}{"foo", "bar", "baz"}, "bar")) - assert.False(t, Has([]interface{}{"foo", "bar", "baz"}, 42)) - assert.True(t, Has([]int{1, 2, 42}, 42)) + testdata := []struct { + in interface{} + key interface{} + out bool + }{ + {in, "foo", true}, + {in, "bar", false}, + {in["baz"], "qux", true}, + {[]string{"foo", "bar", "baz"}, "bar", true}, + {[]interface{}{"foo", "bar", "baz"}, "bar", true}, + {[]interface{}{"foo", "bar", "baz"}, 42, false}, + {[]int{1, 2, 42}, 42, true}, + } + + for _, d := range testdata { + assert.Equal(t, d.out, Has(d.in, d.key)) + } } func TestMustParseInt(t *testing.T) { @@ -196,7 +224,7 @@ func TestToString(t *testing.T) { var n *string - data := []struct { + testdata := []struct { in interface{} out string }{ @@ -219,48 +247,61 @@ func TestToString(t *testing.T) { {n, "<nil>"}, } - for _, d := range data { + for _, d := range testdata { t.Run(fmt.Sprintf("%T/%#v == %s", d.in, d.in, d.out), func(t *testing.T) { - assert.Equal(t, d.out, ToString(d.in)) + out := ToString(d.in) + assert.Equal(t, d.out, out) }) } } func TestToBool(t *testing.T) { - assert.True(t, ToBool(true)) - assert.True(t, ToBool(1)) - assert.True(t, ToBool(int8(1))) - assert.True(t, ToBool(uint8(1))) - assert.True(t, ToBool(int32(1))) - assert.True(t, ToBool(uint32(1))) - assert.True(t, ToBool(int64(1))) - assert.True(t, ToBool(uint64(1))) - assert.True(t, ToBool(float32(1))) - assert.True(t, ToBool(float64(1))) - assert.True(t, ToBool("1")) - assert.True(t, ToBool("0x1")) - assert.True(t, ToBool("1.0")) - assert.True(t, ToBool("01")) - assert.True(t, ToBool("true")) - assert.True(t, ToBool("True")) - assert.True(t, ToBool("T")) - assert.True(t, ToBool("t")) - assert.True(t, ToBool("TrUe")) - assert.True(t, ToBool("yes")) - assert.True(t, ToBool("YES")) - - assert.False(t, ToBool(nil)) - assert.False(t, ToBool(false)) - assert.False(t, ToBool(42)) - assert.False(t, ToBool(uint64(math.MaxUint64))) - assert.False(t, ToBool(uint8(math.MaxUint8))) - assert.False(t, ToBool("")) - assert.False(t, ToBool("false")) - assert.False(t, ToBool("foo")) - assert.False(t, ToBool("0xFFFF")) - assert.False(t, ToBool("010")) - assert.False(t, ToBool("4,096")) - assert.False(t, ToBool("-4,096.00")) + trueData := []interface{}{ + true, + 1, + int8(1), + uint8(1), + int32(1), + uint32(1), + int64(1), + uint64(1), + float32(1), + float64(1), + "1", + "0x1", + "1.0", + "01", + "true", + "True", + "T", + "t", + "TrUe", + "yes", + "YES", + } + for _, d := range trueData { + out := ToBool(d) + assert.True(t, out) + } + + falseData := []interface{}{ + nil, + false, + 42, + uint64(math.MaxUint64), + uint8(math.MaxUint8), + "", + "false", + "foo", + "0xFFFF", + "010", + "4,096", + "-4,096.00", + } + for _, d := range falseData { + out := ToBool(d) + assert.False(t, out) + } } func TestDict(t *testing.T) { |
