Skip to content

Commit

Permalink
Update validating utilities
Browse files Browse the repository at this point in the history
Change-Id: I0f80c1a4676e76186b668ac465e7552ec4786d50
  • Loading branch information
jxskiss committed Nov 11, 2023
1 parent d27853c commit e2fd04d
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 116 deletions.
108 changes: 48 additions & 60 deletions utils/vdutil/common_rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package validat

import (
"context"
"errors"
"fmt"
"strconv"

Expand All @@ -10,52 +11,39 @@ import (
)

func GreaterThanZero[T constraints.Integer](name string, value T) RuleFunc {
return func(ctx context.Context, result *Result) error {
return func(ctx context.Context, result *Result) (any, error) {
var err error
if value <= 0 {
return fmt.Errorf("%s value %v <= 0", name, value)
err = &ValidatingError{Name: name, Err: fmt.Errorf("value %v <= 0", value)}
}
return nil
return value, err
}
}

func Int64GreaterThanZero[T Int64OrString](name string, value T) RuleFunc {
return func(ctx context.Context, result *Result) error {
func Int64GreaterThanZero[T Int64OrString](name string, value T, save bool) RuleFunc {
var zero int64
return func(ctx context.Context, result *Result) (any, error) {
intVal, err := parseInt64(value)
if err != nil {
return err
return zero, &ValidatingError{Name: name, Err: fmt.Errorf("value %v is not integer: %w", value, err)}
}
if intVal <= 0 {
return fmt.Errorf("%s value %v <= 0", name, value)
return zero, &ValidatingError{Name: name, Err: fmt.Errorf("value %v <= 0", value)}
}
if name != "" {
result.Extra.Set(name, intVal)
if save && name != "" {
result.Data.Set(name, intVal)
}
return nil
return intVal, nil
}
}

func LessThanOrEqual[T constraints.Integer](name string, limit, value T) RuleFunc {
return func(ctx context.Context, result *Result) error {
return func(ctx context.Context, result *Result) (any, error) {
var err error
if value > limit {
return fmt.Errorf("%s value %d > %d", name, value, limit)
}
return nil
}
}

func StringIntegerGreaterThanZero(name string, value string) RuleFunc {
return func(ctx context.Context, result *Result) error {
intVal, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return fmt.Errorf("%s value is not integer: %v", name, value)
}
if intVal <= 0 {
return fmt.Errorf("%s value %v <= 0", name, value)
}
if name != "" {
result.Extra.Set(name, intVal)
err = &ValidatingError{Name: name, Err: fmt.Errorf("value %d > %d", value, limit)}
}
return nil
return value, err
}
}

Expand All @@ -69,82 +57,82 @@ const (
)

func InRange[T constraints.Integer](name string, min, max T, value T) RuleFunc {
return func(ctx context.Context, result *Result) error {
if value >= min && value <= max {
return nil
return func(ctx context.Context, result *Result) (any, error) {
var err error
if value < min || value > max {
err = &ValidatingError{Name: name, Err: fmt.Errorf("value %d is not in range [%d, %d]", value, min, max)}
}
return fmt.Errorf("%s value %v is not in range [%v, %v]", name, value, min, max)
return value, err
}
}

func InRangeMode[T constraints.Integer](name string, mode RangeMode, min, max T, value T) RuleFunc {
return func(ctx context.Context, result *Result) error {
return func(ctx context.Context, result *Result) (any, error) {
var err error
switch mode {
case GtAndLte:
if value > min && value <= max {
return nil
if !(value > min && value <= max) {
err = &ValidatingError{Name: name, Err: fmt.Errorf("value %v is not in range (%d, %d]", value, min, max)}
}
return fmt.Errorf("%s value %v is not in range (%v, %v]", name, value, min, max)
case GtAndLt:
if value > min && value < max {
return nil
if !(value > min && value < max) {
err = &ValidatingError{Name: name, Err: fmt.Errorf("value %d is not in range (%d, %d)", value, min, max)}
}
return fmt.Errorf("%s value %v is not in range (%v, %v)", name, value, min, max)
case GteAndLte:
if value >= min && value <= max {
return nil
if !(value >= min && value <= max) {
err = &ValidatingError{Name: name, Err: fmt.Errorf("value %d is not in range [%d, %d]", value, min, max)}
}
return fmt.Errorf("%s value %v is not in range [%v, %v]", name, value, min, max)
case GteAndLt:
if value >= min && value < max {
return nil
if !(value >= min && value < max) {
err = &ValidatingError{Name: name, Err: fmt.Errorf("value %d is not in range [%d, %d)", value, min, max)}
}
return fmt.Errorf("%s value %v is not in range [%v, %v)", name, value, min, max)
default:
return fmt.Errorf("%s unknown range mode %v", name, mode)
err = fmt.Errorf("%s: unknown range mode %v", name, mode)
}
return value, err
}
}

func ParseStringsToInt64s(name string, values []string) RuleFunc {
return func(ctx context.Context, result *Result) error {
func ParseStrsToInt64Slice(name string, values []string) RuleFunc {
return func(ctx context.Context, result *Result) (any, error) {
out := make([]int64, 0, len(values))
for _, v := range values {
intVal, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return fmt.Errorf("%s value %s is not integer", name, v)
return nil, &ValidatingError{Name: name, Err: fmt.Errorf("value %v is not integer", v)}
}
out = append(out, intVal)
}
if name != "" {
result.Extra.Set(name, out)
result.Data.Set(name, out)
}
return nil
return out, nil
}
}

func ParseStringsToInt64Map(name string, values []string) RuleFunc {
return func(ctx context.Context, result *Result) error {
func ParseStrsToInt64Map(name string, values []string) RuleFunc {
return func(ctx context.Context, result *Result) (any, error) {
out := make(map[int64]bool, len(values))
for _, v := range values {
intVal, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return fmt.Errorf("%s value %s is not integer", name, v)
return nil, &ValidatingError{Name: name, Err: fmt.Errorf("value %v is not integer", v)}
}
out[intVal] = true
}
if name != "" {
result.Extra.Set(name, out)
result.Data.Set(name, out)
}
return nil
return out, nil
}
}

func NotNil(name string, value any) RuleFunc {
return func(ctx context.Context, result *Result) error {
return func(ctx context.Context, result *Result) (any, error) {
var err error
if reflectx.IsNil(value) {
return fmt.Errorf("%s value is nil", name)
err = &ValidatingError{Name: name, Err: errors.New("value is nil")}
}
return nil
return value, err
}
}
88 changes: 41 additions & 47 deletions utils/vdutil/common_rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,78 +2,67 @@ package validat

import (
"context"
"errors"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestGreaterThanZero(t *testing.T) {
got1, err := Validate(context.Background(),
var vdErr *ValidatingError

_, err := Validate(context.Background(),
GreaterThanZero("testVar", 100))
require.Nil(t, err)
assert.False(t, got1.IsInternalError)

got2, err := Validate(context.Background(),
_, err = Validate(context.Background(),
GreaterThanZero("testVar", -100))
require.NotNil(t, err)
assert.False(t, got2.IsInternalError)
assert.Contains(t, err.Error(), "testVar value -100 <= 0")
assert.True(t, errors.As(err, &vdErr))
assert.Contains(t, err.Error(), "testVar: value -100 <= 0")
}

func TestInt64GreaterThanZero(t *testing.T) {
var vdErr *ValidatingError

got1, err := Validate(context.Background(),
Int64GreaterThanZero("testVar", int64(100)))
Int64GreaterThanZero("testVar", int64(100), true))
require.Nil(t, err)
assert.Equal(t, int64(100), got1.Extra.GetInt("testVar"))
assert.Equal(t, int64(100), got1.Data.GetInt("testVar"))

got2, err := Validate(context.Background(),
Int64GreaterThanZero("testVar", "100"))
Int64GreaterThanZero("testVar", "100", true))
require.Nil(t, err)
assert.Equal(t, int64(100), got2.Extra.GetInt("testVar"))
assert.Equal(t, int64(100), got2.Data.GetInt("testVar"))

got3, err := Validate(context.Background(),
Int64GreaterThanZero("testVar", "0"))
Int64GreaterThanZero("testVar", "0", true))
require.NotNil(t, err)
require.NotNil(t, got3)
assert.Contains(t, err.Error(), "testVar value 0 <= 0")
assert.True(t, errors.As(err, &vdErr))
assert.Contains(t, err.Error(), "testVar: value 0 <= 0")

got4, err := Validate(context.Background(),
Int64GreaterThanZero("testVar", "xyz"))
Int64GreaterThanZero("testVar", "xyz", true))
require.NotNil(t, err)
require.NotNil(t, got4)
assert.Contains(t, err.Error(), "value xyz is not integer")
assert.True(t, errors.As(err, &vdErr))
assert.Contains(t, err.Error(), "testVar: value xyz is not integer")
}

func TestLessThanOrEqual(t *testing.T) {
got1, err := Validate(context.Background(),
var vdErr *ValidatingError

_, err := Validate(context.Background(),
LessThanOrEqual("testVar", 20, 20))
require.Nil(t, err)
_ = got1

got2, err := Validate(context.Background(),
_, err = Validate(context.Background(),
LessThanOrEqual("testVar", 20, 25))
require.NotNil(t, err)
assert.False(t, got2.IsInternalError)
assert.Contains(t, err.Error(), "testVar value 25 > 20")
}

func TestStringIntegerGreaterThanZero(t *testing.T) {
got1, err := Validate(context.Background(),
StringIntegerGreaterThanZero("userID", "123458"))
require.Nil(t, err)
assert.Equal(t, int64(123458), got1.Extra.GetInt("userID"))

got2, err := Validate(context.Background(),
StringIntegerGreaterThanZero("userID", "dsiaozdfk"))
require.NotNil(t, err)
assert.False(t, got2.IsInternalError)

got3, err := Validate(context.Background(),
StringIntegerGreaterThanZero("userID", "-10234"))
require.NotNil(t, err)
assert.Contains(t, err.Error(), "userID value -10234 <= 0")
_ = got3
assert.True(t, errors.As(err, &vdErr))
assert.Contains(t, err.Error(), "testVar: value 25 > 20")
}

func TestInRange(t *testing.T) {
Expand All @@ -85,7 +74,7 @@ func TestInRange(t *testing.T) {
got2, err := Validate(context.Background(),
InRange("count", 1, 20, 100))
require.NotNil(t, err)
assert.Contains(t, err.Error(), "count value 100 is not in range [1, 20]")
assert.Contains(t, err.Error(), "count: value 100 is not in range [1, 20]")
_ = got2
}

Expand All @@ -100,46 +89,48 @@ func TestInRangeMode(t *testing.T) {
ErrMsg string
}{
{"testVar", GtAndLte, 1, 20, 15, true, ""},
{"testVar", GtAndLte, 1, 20, 1, false, "testVar value 1 is not in range (1, 20]"},
{"testVar", GtAndLte, 1, 20, 1, false, "testVar: value 1 is not in range (1, 20]"},
{"testVar", GtAndLte, 1, 20, 20, true, ""},

{"testVar", GtAndLt, 1, 20, 15, true, ""},
{"testVar", GtAndLt, 1, 20, 1, false, "testVar value 1 is not in range (1, 20)"},
{"testVar", GtAndLt, 1, 20, 20, false, "testVar value 20 is not in range (1, 20)"},
{"testVar", GtAndLt, 1, 20, 1, false, "testVar: value 1 is not in range (1, 20)"},
{"testVar", GtAndLt, 1, 20, 20, false, "testVar: value 20 is not in range (1, 20)"},

{"testVar", GteAndLte, 1, 20, 15, true, ""},
{"testVar", GteAndLte, 1, 20, 1, true, ""},
{"testVar", GteAndLte, 1, 20, 20, true, ""},

{"testVar", GteAndLt, 1, 20, 15, true, ""},
{"testVar", GteAndLt, 1, 20, 1, true, ""},
{"testVar", GteAndLt, 1, 20, 20, false, "testVar value 20 is not in range [1, 20)"},
{"testVar", GteAndLt, 1, 20, 20, false, "testVar: value 20 is not in range [1, 20)"},
}

var vdErr *ValidatingError
for _, c := range testData {
_, err := Validate(context.Background(),
InRangeMode(c.Name, c.Mode, c.Min, c.Max, c.Value))
if c.ErrIsNil {
assert.Nil(t, err)
} else {
assert.NotNil(t, err)
assert.True(t, errors.As(err, &vdErr))
assert.Contains(t, err.Error(), c.ErrMsg)
}
}
}

func TestParseStringSliceToIntSlice(t *testing.T) {
func TestParseStringSliceToInt64Slice(t *testing.T) {
got1, err := Validate(context.Background(),
ParseStringsToInt64s("entityIDs", []string{"1", "2", "3"}))
ParseStrsToInt64Slice("entityIDs", []string{"1", "2", "3"}))
assert.Nil(t, err)
assert.Equal(t, []int64{1, 2, 3}, got1.Extra.GetInt64s("entityIDs"))
assert.Equal(t, []int64{1, 2, 3}, got1.Data.GetInt64s("entityIDs"))
}

func TestParseStringSliceToIntMap(t *testing.T) {
func TestParseStringSliceToInt64Map(t *testing.T) {
got1, err := Validate(context.Background(),
ParseStringsToInt64Map("entityIDs", []string{"1", "2", "3"}))
ParseStrsToInt64Map("entityIDs", []string{"1", "2", "3"}))
assert.Nil(t, err)
assert.Equal(t, map[int64]bool{1: true, 2: true, 3: true}, got1.Extra.MustGet("entityIDs").(map[int64]bool))
assert.Equal(t, map[int64]bool{1: true, 2: true, 3: true}, got1.Data.MustGet("entityIDs").(map[int64]bool))
}

func TestNotNil(t *testing.T) {
Expand All @@ -156,6 +147,7 @@ func TestNotNil(t *testing.T) {
assert.Nil(t, err)
}

var vdErr *ValidatingError
nilValues := []any{
nil,
(*int)(nil),
Expand All @@ -168,5 +160,7 @@ func TestNotNil(t *testing.T) {
for _, x := range nilValues {
_, err := Validate(context.Background(), NotNil("testVar", x))
assert.NotNil(t, err)
assert.True(t, errors.As(err, &vdErr))
assert.Contains(t, err.Error(), "value is nil")
}
}
Loading

0 comments on commit e2fd04d

Please sign in to comment.