Skip to content

Commit

Permalink
Add mapstructure support and expand test cases for "Duration" type (#57)
Browse files Browse the repository at this point in the history
* Add mapstructure support and expand test cases
  • Loading branch information
Mrod1598 authored Mar 15, 2021
1 parent a7b781e commit 61f2a8b
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 9 deletions.
9 changes: 8 additions & 1 deletion operator/helper/duration.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package helper
import (
"encoding/json"
"fmt"
"strconv"
"time"
)

Expand Down Expand Up @@ -79,7 +80,13 @@ func durationFromInterface(val interface{}) (time.Duration, error) {
case int:
return time.Duration(value) * time.Second, nil
case string:
var err error

if _, err := strconv.Atoi(value); err == nil {
value += "s" // int value with no unit
}
if _, err := strconv.ParseFloat(value, 64); err == nil {
value += "s" // float value with no unit
}
d, err := time.ParseDuration(value)
return d, err
default:
Expand Down
149 changes: 141 additions & 8 deletions operator/helper/duration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,178 @@ import (
"testing"
"time"

"github.com/mitchellh/mapstructure"
"github.com/stretchr/testify/require"
yaml "gopkg.in/yaml.v2"
)

type durationTestCase struct {
name string
input string
expected Duration
expectError bool
}

func TestParseDuration(t *testing.T) {
cases := []struct {
name string
input string
expected Duration
}{
cases := []durationTestCase{
{
"simple nanosecond",
`"10ns"`,
Duration{10 * time.Nanosecond},
false,
},
{
"simple microsecond",
`"10us"`,
Duration{10 * time.Microsecond},
false,
},
{
"simple alternate microsecond",
`"10µs"`,
Duration{10 * time.Microsecond},
false,
},
{
"simple millisecond",
`"10ms"`,
Duration{10 * time.Millisecond},
false,
},
{
"simple second",
`"1s"`,
Duration{time.Second},
false,
},
{
"simple minute",
`"10m"`,
Duration{10 * time.Minute},
false,
},
{
"simple hour",
`"10h"`,
Duration{10 * time.Hour},
false,
},
{
"float hour",
`"1.5h"`,
Duration{1.5 * 3600000000000},
false,
},
{
"number defaults to seconds",
`10`,
Duration{10 * time.Second},
false,
},
{
"float",
`1.5`,
Duration{1.5 * 1000000000.0},
false,
},
{
"int string",
`"10"`,
Duration{10 * time.Second},
false,
},
{
"multi unit",
`"10h10m10s"`,
Duration{(10 * time.Second) + (10 * time.Minute) + (10 * time.Hour)},
false,
},
{
"character",
`i`,
Duration{time.Second},
true,
},
{
"space before unit",
`"10 s"`,
Duration{(10 * time.Second)},
true,
},
{
"capital unit",
`"10S"`,
Duration{(10 * time.Second)},
true,
},
}

for _, tc := range cases {
t.Run("json/"+tc.name, func(t *testing.T) {
var dur Duration

err := json.Unmarshal([]byte(tc.input), &dur)
if tc.expectError {
require.Error(t, err)
return
}

require.NoError(t, err)
require.Equal(t, tc.expected, dur)
})
}

additionalCases := []durationTestCase{
{
"simple minute unquoted",
`10m`,
Duration{10 * time.Minute},
false,
},
{
"simple second unquoted",
`10s`,
Duration{10 * time.Second},
false,
},
{
"simple multi unquoted",
`10h10m10s`,
Duration{(10 * time.Second) + (10 * time.Minute) + (10 * time.Hour)},
false,
},
}

cases = append(cases, additionalCases...)

for _, tc := range cases {
t.Run("yaml "+tc.name, func(t *testing.T) {
t.Run("yaml/"+tc.name, func(t *testing.T) {
var dur Duration
err := yaml.UnmarshalStrict([]byte(tc.input), &dur)
if tc.expectError {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, tc.expected, dur)
})

t.Run("json "+tc.name, func(t *testing.T) {
t.Run("mapstructure/"+tc.name, func(t *testing.T) {
var dur Duration
err := json.Unmarshal([]byte(tc.input), &dur)
var raw string
_ = yaml.Unmarshal([]byte(tc.input), &raw)

dc := &mapstructure.DecoderConfig{Result: &dur, DecodeHook: JSONUnmarshalerHook()}
ms, err := mapstructure.NewDecoder(dc)
require.NoError(t, err)

err = ms.Decode(raw)
if tc.expectError {
require.Error(t, err)
return
}
require.NoError(t, err)

require.Equal(t, tc.expected, dur)
})
}
Expand Down

0 comments on commit 61f2a8b

Please sign in to comment.