diff --git a/helper/validation/validation.go b/helper/validation/validation.go index 8c8ac54fc..efded8928 100644 --- a/helper/validation/validation.go +++ b/helper/validation/validation.go @@ -320,3 +320,22 @@ func ValidateRFC3339TimeString(v interface{}, k string) (ws []string, errors []e } return } + +// FloatBetween returns a SchemaValidateFunc which tests if the provided value +// is of type float64 and is between min and max (inclusive). +func FloatBetween(min, max float64) schema.SchemaValidateFunc { + return func(i interface{}, k string) (s []string, es []error) { + v, ok := i.(float64) + if !ok { + es = append(es, fmt.Errorf("expected type of %s to be float64", k)) + return + } + + if v < min || v > max { + es = append(es, fmt.Errorf("expected %s to be in the range (%f - %f), got %f", k, min, max, v)) + return + } + + return + } +} diff --git a/helper/validation/validation_test.go b/helper/validation/validation_test.go index 26205d905..d46507b41 100644 --- a/helper/validation/validation_test.go +++ b/helper/validation/validation_test.go @@ -455,3 +455,46 @@ func runTestCases(t *testing.T, cases []testCase) { } } } + +func TestFloatBetween(t *testing.T) { + cases := map[string]struct { + Value interface{} + ValidateFunc schema.SchemaValidateFunc + ExpectValidationErrors bool + }{ + "accept valid value": { + Value: 1.5, + ValidateFunc: FloatBetween(1.0, 2.0), + ExpectValidationErrors: false, + }, + "accept valid value inclusive upper bound": { + Value: 1.0, + ValidateFunc: FloatBetween(0.0, 1.0), + ExpectValidationErrors: false, + }, + "accept valid value inclusive lower bound": { + Value: 0.0, + ValidateFunc: FloatBetween(0.0, 1.0), + ExpectValidationErrors: false, + }, + "reject out of range value": { + Value: -1.0, + ValidateFunc: FloatBetween(0.0, 1.0), + ExpectValidationErrors: true, + }, + "reject incorrectly typed value": { + Value: 1, + ValidateFunc: FloatBetween(0.0, 1.0), + ExpectValidationErrors: true, + }, + } + + for tn, tc := range cases { + _, errors := tc.ValidateFunc(tc.Value, tn) + if len(errors) > 0 && !tc.ExpectValidationErrors { + t.Errorf("%s: unexpected errors %s", tn, errors) + } else if len(errors) == 0 && tc.ExpectValidationErrors { + t.Errorf("%s: expected errors but got none", tn) + } + } +}