Skip to content

Commit

Permalink
Handle JSON Number in ParseCommaStringSlice (#29)
Browse files Browse the repository at this point in the history
* Return err if ParseCommaStringSlice fails to parse input string

* Add test cases for ParseCommaStringSlice

* properly handle json.Number in ParseCommaStringSlice by stringifying

* add exhaustive type support testing for ParseCommaStringSlice

* remove accidental added newline

* adding a couple more cases to Test_ParseCommaStringSlice
  • Loading branch information
ccapurso authored Mar 16, 2022
1 parent f913ac8 commit b459752
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 2 deletions.
5 changes: 5 additions & 0 deletions parseutil/parseutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ func ParseString(in interface{}) (string, error) {
}

func ParseCommaStringSlice(in interface{}) ([]string, error) {
jsonIn, ok := in.(json.Number)
if ok {
in = jsonIn.String()
}

rawString, ok := in.(string)
if ok && rawString == "" {
return []string{}, nil
Expand Down
182 changes: 180 additions & 2 deletions parseutil/parseutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package parseutil

import (
"encoding/json"
"math/cmplx"
"testing"
"time"
)
Expand Down Expand Up @@ -461,12 +462,12 @@ func Test_ParseIntSlice(t *testing.T) {
{
"1,2",
true,
[]int64{1,2},
[]int64{1, 2},
},
{
"1,2,3",
true,
[]int64{1,2,3},
[]int64{1, 2, 3},
},
}

Expand All @@ -487,3 +488,180 @@ func Test_ParseIntSlice(t *testing.T) {
}
}
}

func equalStringSlice(a, b []string) bool {
if len(a) != len(b) {
return false
}

for i := range a {
if a[i] != b[i] {
return false
}
}

return true
}

func Test_ParseCommaStringSlice(t *testing.T) {
cases := []struct {
name string
inp interface{}
expected []string
valid bool
}{
{
"nil",
nil,
[]string{},
true,
},
{
"empty string",
"",
[]string{},
true,
},
{
"string without commas",
"foo",
[]string{"foo"},
true,
},
{
"comma-separated string",
"foo,bar,baz",
[]string{"foo", "bar", "baz"},
true,
},
{
"comma-separated string with trim",
" foo , bar ,baz ",
[]string{"foo", "bar", "baz"},
true,
},
{
"json number",
json.Number("123"),
[]string{"123"},
true,
},
{
"int",
1,
[]string{"1"},
true,
},
{
"float",
5.5,
[]string{"5.5"},
true,
},
{
"rune",
'a',
[]string{"97"},
true,
},
{
"bool",
true,
[]string{"1"},
true,
},
{
"byte",
byte(10),
[]string{"10"},
true,
},
{
"complex",
cmplx.Sqrt(-1),
nil,
false,
},
{
"time",
time.Now(),
nil,
false,
},
{
"string slice",
[]string{"foo", "bar", "baz"},
[]string{"foo", "bar", "baz"},
true,
},
{
"json number slice",
[]json.Number{json.Number("1"), json.Number("2")},
[]string{"1", "2"},
true,
},
{
"int slice",
[]int{1, 2, 3},
[]string{"1", "2", "3"},
true,
},
{
"float slice",
[]float64{1.1, 1.2, 1.3},
[]string{"1.1", "1.2", "1.3"},
true,
},
{
"rune slice",
[]rune{'a', 'b', 'c'},
[]string{"97", "98", "99"},
true,
},
{
"bool slice",
[]bool{true, false, true},
[]string{"1", "0", "1"},
true,
},
{
"complex slice",
[]complex128{cmplx.Sqrt(-1)},
nil,
false,
},
{
"map",
map[string]interface{}{"foo": "bar"},
nil,
false,
},
{
"struct",
struct{ name string }{"foo"},
nil,
false,
},
}

for _, tc := range cases {
tc := tc

t.Run(tc.name, func(t *testing.T) {
t.Parallel()

outp, err := ParseCommaStringSlice(tc.inp)
if tc.valid && err != nil {
t.Errorf("failed to parse: %v. err: %v", tc.inp, err)
}

if !tc.valid && err == nil {
t.Errorf("no error for: %v", tc.inp)
}

if !equalStringSlice(outp, tc.expected) {
t.Errorf("input %v parsed as %v, expected %v", tc.inp, outp, tc.expected)
}
})
}
}

0 comments on commit b459752

Please sign in to comment.