diff --git a/src/common/config/metadata/type.go b/src/common/config/metadata/type.go index 745f30868..1feb55b2e 100644 --- a/src/common/config/metadata/type.go +++ b/src/common/config/metadata/type.go @@ -18,6 +18,7 @@ package metadata import ( "encoding/json" "fmt" + "math" "strconv" "strings" @@ -139,12 +140,12 @@ type Int64Type struct { } func (t *Int64Type) validate(str string) error { - _, err := strconv.ParseInt(str, 10, 64) + _, err := parseInt64(str) return err } func (t *Int64Type) get(str string) (interface{}, error) { - return strconv.ParseInt(str, 10, 64) + return parseInt64(str) } // BoolType ... @@ -194,7 +195,7 @@ type QuotaType struct { } func (t *QuotaType) validate(str string) error { - val, err := strconv.ParseInt(str, 10, 64) + val, err := parseInt64(str) if err != nil { return err } @@ -205,3 +206,18 @@ func (t *QuotaType) validate(str string) error { return nil } + +// parseInt64 returns int64 from string which support scientific notation +func parseInt64(str string) (int64, error) { + val, err := strconv.ParseInt(str, 10, 64) + if err == nil { + return val, nil + } + + fval, err := strconv.ParseFloat(str, 64) + if err == nil && fval == math.Trunc(fval) { + return int64(fval), nil + } + + return 0, fmt.Errorf("invalid int64 string: %s", str) +} diff --git a/src/common/config/metadata/type_test.go b/src/common/config/metadata/type_test.go index 31a0730de..ed3ddc526 100644 --- a/src/common/config/metadata/type_test.go +++ b/src/common/config/metadata/type_test.go @@ -15,8 +15,9 @@ package metadata import ( - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) func TestIntType_validate(t *testing.T) { @@ -96,3 +97,33 @@ func TestMapType_get(t *testing.T) { result, _ := test.get(`{"sample":"abc", "another":"welcome"}`) assert.Equal(t, map[string]interface{}{"sample": "abc", "another": "welcome"}, result) } + +func Test_parseInt64(t *testing.T) { + type args struct { + str string + } + tests := []struct { + name string + args args + want int64 + wantErr bool + }{ + {"1", args{"1"}, int64(1), false}, + {"1.0", args{"1.0"}, int64(1), false}, + {"1.1", args{"1.1"}, int64(0), true}, + {"1E2", args{"1E2"}, int64(100), false}, + {"1.073741824e+11", args{"1.073741824e+11"}, int64(107374182400), false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseInt64(tt.args.str) + if (err != nil) != tt.wantErr { + t.Errorf("parseInt64() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("parseInt64() = %v, want %v", got, tt.want) + } + }) + } +}