From 1560346402187dccdbfe741e19fdb911a30f0997 Mon Sep 17 00:00:00 2001 From: Joshua Powers Date: Fri, 11 Mar 2022 08:15:04 -0700 Subject: [PATCH] fix: update parsing logic of config.Duration (#10803) --- config/types.go | 36 +++++++++++++++--------------------- config/types_test.go | 5 +++++ 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/config/types.go b/config/types.go index 7c1c50b9e..677df68dd 100644 --- a/config/types.go +++ b/config/types.go @@ -1,8 +1,8 @@ package config import ( - "bytes" "strconv" + "strings" "time" "github.com/alecthomas/units" @@ -16,40 +16,34 @@ type Size int64 // UnmarshalTOML parses the duration from the TOML config file func (d *Duration) UnmarshalTOML(b []byte) error { - var err error - b = bytes.Trim(b, `'`) - - // see if we can directly convert it - dur, err := time.ParseDuration(string(b)) - if err == nil { - *d = Duration(dur) - return nil - } - - // Parse string duration, ie, "1s" - if uq, err := strconv.Unquote(string(b)); err == nil && len(uq) > 0 { - dur, err := time.ParseDuration(uq) - if err == nil { - *d = Duration(dur) - return nil - } - } + // convert to string + durStr := string(b) + // Value is a TOML number (e.g. 3, 10, 3.5) // First try parsing as integer seconds - sI, err := strconv.ParseInt(string(b), 10, 64) + sI, err := strconv.ParseInt(durStr, 10, 64) if err == nil { dur := time.Second * time.Duration(sI) *d = Duration(dur) return nil } // Second try parsing as float seconds - sF, err := strconv.ParseFloat(string(b), 64) + sF, err := strconv.ParseFloat(durStr, 64) if err == nil { dur := time.Second * time.Duration(sF) *d = Duration(dur) return nil } + // Finally, try value is a TOML string (e.g. "3s", 3s) or literal (e.g. '3s') + durStr = strings.ReplaceAll(durStr, "'", "") + durStr = strings.ReplaceAll(durStr, "\"", "") + dur, err := time.ParseDuration(durStr) + if err != nil { + return err + } + + *d = Duration(dur) return nil } diff --git a/config/types_test.go b/config/types_test.go index afff599e3..33b1cc62d 100644 --- a/config/types_test.go +++ b/config/types_test.go @@ -51,6 +51,11 @@ func TestDuration(t *testing.T) { d = config.Duration(0) require.NoError(t, d.UnmarshalTOML([]byte(`1.5`))) require.Equal(t, time.Second, time.Duration(d)) + + require.Error(t, d.UnmarshalTOML([]byte(`"1"`))) // string missing unit + require.Error(t, d.UnmarshalTOML([]byte(`'2'`))) // string missing unit + require.Error(t, d.UnmarshalTOML([]byte(`'ns'`))) // string missing time + require.Error(t, d.UnmarshalTOML([]byte(`'us'`))) // string missing time } func TestSize(t *testing.T) {