package validate import ( "reflect" "testing" ) func TestAddRule(t *testing.T) { type s struct { A string `validate:"custom"` } AddRule(`custom`, nil, Kinds{ reflect.String: func(rv reflect.Value, _ interface{}) bool { return rv.String() == `custom` }, }) pass := s{`custom`} fail := s{`somethingelse`} check(t, pass, 0) check(t, fail, 1) } func TestRuleRequired(t *testing.T) { type s struct { A *string `validate:"required"` B []int `validate:"required"` C []int `validate:"required"` D string `validate:"required"` E int `validate:"required"` F uint `validate:"required"` G float64 `validate:"required"` H interface{} `validate:"required"` I map[int]int `validate:"required"` } str := `` pass := s{&str, make([]int, 1), make([]int, 1), ` `, -1, 1, 0.01, ``, map[int]int{0: 1}} fail := s{nil, nil, make([]int, 0), ``, 0, 0, 0.000, nil, nil} check(t, pass, 0) check(t, fail, 9) } func TestRulePrefixSuffix(t *testing.T) { type s struct { A string `validate:"prefix=#"` B string `validate:"suffix=@"` } pass := s{`#a`, `a@`} fail := s{`a#`, `@a`} check(t, pass, 0) check(t, fail, 2) } func TestRuleContains(t *testing.T) { type s struct { A string `validate:"contains=%"` } pass1 := s{`a%`} pass2 := s{`%a`} pass3 := s{`%`} pass4 := s{`a%a`} fail := s{`aa`} check(t, pass1, 0) check(t, pass2, 0) check(t, pass3, 0) check(t, pass4, 0) check(t, fail, 1) } func TestRuleRegexp(t *testing.T) { type s struct { A string `validate:"regexp=^[0-9]$"` } pass1 := s{`0`} pass2 := s{`7`} fail1 := s{`A`} fail2 := s{`11`} check(t, pass1, 0) check(t, pass2, 0) check(t, fail1, 1) check(t, fail2, 1) } func TestRuleEqGtLt(t *testing.T) { type s struct { A int `validate:"eq=3"` B float64 `validate:"gt=1e5"` C uint `validate:"lt=1"` } pass := s{3, 100001, 0} fail1 := s{2, 1e5, 1} fail2 := s{4, 9999, 2} check(t, pass, 0) check(t, fail1, 3) check(t, fail2, 3) } func TestRuleGteLte(t *testing.T) { type s struct { U uint `validate:"gte=0,lte=10"` I int `validate:"gte=-10,lte=0"` F float64 `validate:"gte=0,lte=10"` } pass1 := s{0, -10, 0} pass2 := s{10, 0, 10} // Uint fail1 := s{11, -10, 0} // Int fail2 := s{0, -11, 0} fail3 := s{0, 1, 0} // Float fail4 := s{0, -10, -0.0001} fail5 := s{0, -10, 10.0001} check(t, pass1, 0) check(t, pass2, 0) check(t, fail1, 1) check(t, fail2, 1) check(t, fail3, 1) check(t, fail4, 1) check(t, fail5, 1) } func TestRuleLenMinMax(t *testing.T) { type s struct { A string `validate:"len=3"` B []int `validate:"min=2"` C map[int]string `validate:"max=1"` } pass := s{`abc`, []int{1, 2}, nil} fail1 := s{`ab`, []int{1}, map[int]string{1: `a`, 2: `b`}} fail2 := s{`abcd`, nil, nil} check(t, pass, 0) check(t, fail1, 3) check(t, fail2, 2) } func check(t *testing.T, c interface{}, errCount int) { t.Helper() errs := Validate(c) if len(errs) != errCount { t.Errorf(`Case %T(%v) should get %d errors, but got %v`, c, c, errCount, errs) } }