separate options
This commit is contained in:
16
input/validator/enum.go
Normal file
16
input/validator/enum.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package validator
|
||||
|
||||
import "gitoa.ru/go-4devs/console/input/value"
|
||||
|
||||
func Enum(enum ...string) func(value.Value) error {
|
||||
return func(in value.Value) error {
|
||||
v := in.String()
|
||||
for _, e := range enum {
|
||||
if e == v {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return NewError(ErrInvalid, v, enum)
|
||||
}
|
||||
}
|
||||
24
input/validator/enum_test.go
Normal file
24
input/validator/enum_test.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package validator_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/validator"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func TestEnum(t *testing.T) {
|
||||
validValue := value.New("valid")
|
||||
invalidValue := value.New("invalid")
|
||||
|
||||
enum := validator.Enum("valid", "other", "three")
|
||||
|
||||
if err := enum(validValue); err != nil {
|
||||
t.Errorf("expected valid value got err:%s", err)
|
||||
}
|
||||
|
||||
if err := enum(invalidValue); !errors.Is(err, validator.ErrInvalid) {
|
||||
t.Errorf("expected err:%s, got: %s", validator.ErrInvalid, err)
|
||||
}
|
||||
}
|
||||
37
input/validator/error.go
Normal file
37
input/validator/error.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalid = errors.New("invalid value")
|
||||
ErrNotBlank = errors.New("not blank")
|
||||
)
|
||||
|
||||
func NewError(err error, value, expect interface{}) Error {
|
||||
return Error{
|
||||
err: err,
|
||||
value: value,
|
||||
expect: expect,
|
||||
}
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
err error
|
||||
value interface{}
|
||||
expect interface{}
|
||||
}
|
||||
|
||||
func (e Error) Error() string {
|
||||
return fmt.Sprintf("%s: expext: %s, given: %s", e.err, e.expect, e.value)
|
||||
}
|
||||
|
||||
func (e Error) Is(err error) bool {
|
||||
return errors.Is(e.err, err)
|
||||
}
|
||||
|
||||
func (e Error) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
110
input/validator/not_blank.go
Normal file
110
input/validator/not_blank.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
//nolint: gocyclo
|
||||
func NotBlank(f flag.Flag) func(value.Value) error {
|
||||
return func(in value.Value) error {
|
||||
switch {
|
||||
case f.IsAny() && in.Any() != nil:
|
||||
return nil
|
||||
case f.IsArray():
|
||||
return arrayNotBlank(f, in)
|
||||
case f.IsInt() && in.Int() != 0:
|
||||
return nil
|
||||
case f.IsInt64() && in.Int64() != 0:
|
||||
return nil
|
||||
case f.IsUint() && in.Uint() != 0:
|
||||
return nil
|
||||
case f.IsUint64() && in.Uint64() != 0:
|
||||
return nil
|
||||
case f.IsFloat64() && in.Float64() != 0:
|
||||
return nil
|
||||
case f.IsDuration() && in.Duration() != 0:
|
||||
return nil
|
||||
case f.IsTime() && !in.Time().IsZero():
|
||||
return nil
|
||||
case f.IsString() && len(in.String()) > 0:
|
||||
return nil
|
||||
}
|
||||
|
||||
return ErrNotBlank
|
||||
}
|
||||
}
|
||||
|
||||
//nolint: gocyclo,gocognit
|
||||
func arrayNotBlank(f flag.Flag, in value.Value) error {
|
||||
switch {
|
||||
case f.IsInt() && len(in.Ints()) > 0:
|
||||
for _, i := range in.Ints() {
|
||||
if i == 0 {
|
||||
return ErrNotBlank
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
case f.IsInt64() && len(in.Int64s()) > 0:
|
||||
for _, i := range in.Int64s() {
|
||||
if i == 0 {
|
||||
return ErrNotBlank
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
case f.IsUint() && len(in.Uints()) > 0:
|
||||
for _, u := range in.Uints() {
|
||||
if u == 0 {
|
||||
return ErrNotBlank
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
case f.IsUint64() && len(in.Uint64s()) > 0:
|
||||
for _, u := range in.Uint64s() {
|
||||
if u == 0 {
|
||||
return ErrNotBlank
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
case f.IsFloat64() && len(in.Float64s()) > 0:
|
||||
for _, f := range in.Float64s() {
|
||||
if f == 0 {
|
||||
return ErrNotBlank
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
case f.IsBool() && len(in.Bools()) > 0:
|
||||
return nil
|
||||
case f.IsDuration() && len(in.Durations()) > 0:
|
||||
for _, d := range in.Durations() {
|
||||
if d == 0 {
|
||||
return ErrNotBlank
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
case f.IsTime() && len(in.Times()) > 0:
|
||||
for _, t := range in.Times() {
|
||||
if t.IsZero() {
|
||||
return ErrNotBlank
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
case f.IsString() && len(in.Strings()) > 0:
|
||||
for _, st := range in.Strings() {
|
||||
if len(st) == 0 {
|
||||
return ErrNotBlank
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return ErrNotBlank
|
||||
}
|
||||
109
input/validator/not_blank_test.go
Normal file
109
input/validator/not_blank_test.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package validator_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/validator"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func TestNotBlank(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
flag flag.Flag
|
||||
value value.Value
|
||||
empty value.Value
|
||||
}{
|
||||
"any": {flag: flag.Any, value: value.New(float32(1))},
|
||||
"array int": {
|
||||
flag: flag.Int | flag.Array,
|
||||
value: value.New([]int{1}),
|
||||
empty: value.New([]int{10, 20, 0}),
|
||||
},
|
||||
"array int64": {
|
||||
flag: flag.Int64 | flag.Array,
|
||||
value: value.New([]int64{1}),
|
||||
empty: value.New([]int64{0}),
|
||||
},
|
||||
"array uint": {
|
||||
flag: flag.Uint | flag.Array,
|
||||
value: value.New([]uint{1}),
|
||||
empty: value.New([]uint{1, 0}),
|
||||
},
|
||||
"array uint64": {
|
||||
flag: flag.Uint64 | flag.Array,
|
||||
value: value.New([]uint64{1}),
|
||||
empty: value.New([]uint64{0}),
|
||||
},
|
||||
"array float64": {
|
||||
flag: flag.Float64 | flag.Array,
|
||||
value: value.New([]float64{0.2}),
|
||||
empty: value.New([]float64{0}),
|
||||
},
|
||||
"array bool": {
|
||||
flag: flag.Bool | flag.Array,
|
||||
value: value.New([]bool{true, false}),
|
||||
empty: value.New([]bool{}),
|
||||
},
|
||||
"array duration": {
|
||||
flag: flag.Duration | flag.Array,
|
||||
value: value.New([]time.Duration{time.Second}),
|
||||
empty: value.New([]time.Duration{time.Second, 0}),
|
||||
},
|
||||
"array time": {
|
||||
flag: flag.Time | flag.Array,
|
||||
value: value.New([]time.Time{time.Now()}),
|
||||
empty: value.New([]time.Time{{}, time.Now()}),
|
||||
},
|
||||
"array string": {
|
||||
flag: flag.Array,
|
||||
value: value.New([]string{"value"}),
|
||||
empty: value.New([]string{""}),
|
||||
},
|
||||
"int": {
|
||||
flag: flag.Int,
|
||||
value: value.New(int(1)),
|
||||
},
|
||||
"int64": {
|
||||
flag: flag.Int64,
|
||||
value: value.New(int64(2)),
|
||||
},
|
||||
"uint": {
|
||||
flag: flag.Uint,
|
||||
value: value.New(uint(1)),
|
||||
empty: value.New([]uint{1}),
|
||||
},
|
||||
"uint64": {
|
||||
flag: flag.Uint64,
|
||||
value: value.New(uint64(10)),
|
||||
},
|
||||
"float64": {
|
||||
flag: flag.Float64,
|
||||
value: value.New(float64(.00001)),
|
||||
},
|
||||
"duration": {
|
||||
flag: flag.Duration,
|
||||
value: value.New(time.Minute),
|
||||
empty: value.New("same string"),
|
||||
},
|
||||
"time": {flag: flag.Time, value: value.New(time.Now())},
|
||||
"string": {value: value.New("string"), empty: value.New("")},
|
||||
}
|
||||
|
||||
for name, ca := range cases {
|
||||
valid := validator.NotBlank(ca.flag)
|
||||
if err := valid(ca.value); err != nil {
|
||||
t.Errorf("case: %s, expected error <nil>, got: %s", name, err)
|
||||
}
|
||||
|
||||
if ca.empty == nil {
|
||||
ca.empty = &value.Empty{}
|
||||
}
|
||||
|
||||
if err := valid(ca.empty); err == nil || !errors.Is(err, validator.ErrNotBlank) {
|
||||
t.Errorf("case: %s, expect: %s, got:%s", name, validator.ErrNotBlank, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
15
input/validator/valid.go
Normal file
15
input/validator/valid.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package validator
|
||||
|
||||
import "gitoa.ru/go-4devs/console/input/value"
|
||||
|
||||
func Valid(v ...func(value.Value) error) func(value.Value) error {
|
||||
return func(in value.Value) error {
|
||||
for _, valid := range v {
|
||||
if err := valid(in); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
28
input/validator/valid_test.go
Normal file
28
input/validator/valid_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package validator_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/flag"
|
||||
"gitoa.ru/go-4devs/console/input/validator"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func TestValid(t *testing.T) {
|
||||
validValue := value.New("one")
|
||||
invalidValue := value.New([]string{"one"})
|
||||
|
||||
valid := validator.Valid(
|
||||
validator.NotBlank(flag.String),
|
||||
validator.Enum("one", "two"),
|
||||
)
|
||||
|
||||
if err := valid(validValue); err != nil {
|
||||
t.Errorf("expected valid value, got: %s", err)
|
||||
}
|
||||
|
||||
if err := valid(invalidValue); !errors.Is(err, validator.ErrNotBlank) {
|
||||
t.Errorf("expected not blank, got:%s", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user