Skip to content

Commit 74dd82a

Browse files
test: cover startsnotwith/endsnotwith, RegisterStructValidationMapRules, and float32 comparator branches (#1609)
`Summary` These paths were shipped but never exercised by tests: - startsnotwith/endsnotwith tags (present since [Add validators that check if string does not start/end with supplied parameter #f3b347c](f3b347c)) had 0% coverage despite being documented in README. - RegisterStructValidationMapRules, a public API for overriding struct tags via a rules map, had no test at all - registration, per-field tag override, fallback to the struct's own tag, deep-copy isolation from the caller's map, pointer-type registration, and non-struct types being silently ignored were all unverified. - isGt/isGte/isLt/isLte/hasLengthOf only tested their float64 branch. The identical float32 case switch was dead to coverage. `Result` - package coverage 95.6% -> 96.8%, all eight targeted functions now at 100%. No production code changed.
1 parent 379edc8 commit 74dd82a

1 file changed

Lines changed: 162 additions & 0 deletions

File tree

‎validator_test.go‎

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,60 @@ func TestStructLevelValidations(t *testing.T) {
694694
Equal(t, errs, nil)
695695
}
696696

697+
func TestRegisterStructValidationMapRules(t *testing.T) {
698+
type MapRulesTestStruct struct {
699+
Name string `validate:"required"`
700+
Age int
701+
}
702+
703+
rules := map[string]string{
704+
"Name": "omitempty",
705+
"Age": "required,gt=0",
706+
}
707+
708+
validate := New()
709+
validate.RegisterStructValidationMapRules(rules, MapRulesTestStruct{})
710+
711+
// Name's own "required" tag is superseded by the "omitempty" rule, so an
712+
// empty Name is now allowed, while Age's rule is enforced.
713+
errs := validate.Struct(MapRulesTestStruct{Name: "", Age: 5})
714+
Equal(t, errs, nil)
715+
716+
errs = validate.Struct(MapRulesTestStruct{Name: "", Age: 0})
717+
NotEqual(t, errs, nil)
718+
AssertError(t, errs, "MapRulesTestStruct.Age", "MapRulesTestStruct.Age", "Age", "Age", "required")
719+
720+
errs = validate.Struct(MapRulesTestStruct{Name: "gopher", Age: 5})
721+
Equal(t, errs, nil)
722+
723+
// mutating the map passed to RegisterStructValidationMapRules after
724+
// registration must not affect already-registered rules (deep copy).
725+
rules["Name"] = "required"
726+
errs = validate.Struct(MapRulesTestStruct{Name: "", Age: 5})
727+
Equal(t, errs, nil)
728+
729+
// a struct with no registered rules falls back to its own tags.
730+
type NoRulesTestStruct struct {
731+
Name string `validate:"required"`
732+
}
733+
errs = validate.Struct(NoRulesTestStruct{Name: ""})
734+
NotEqual(t, errs, nil)
735+
AssertError(t, errs, "NoRulesTestStruct.Name", "NoRulesTestStruct.Name", "Name", "Name", "required")
736+
737+
// registering against a pointer type applies the same as the value type.
738+
v2 := New()
739+
v2.RegisterStructValidationMapRules(rules, &MapRulesTestStruct{})
740+
errs = v2.Struct(&MapRulesTestStruct{Name: "", Age: 5})
741+
NotEqual(t, errs, nil)
742+
AssertError(t, errs, "MapRulesTestStruct.Name", "MapRulesTestStruct.Name", "Name", "Name", "required")
743+
744+
// non-struct types are silently ignored rather than panicking.
745+
v3 := New()
746+
v3.RegisterStructValidationMapRules(map[string]string{"Foo": "required"}, 5)
747+
errs = v3.Struct(MapRulesTestStruct{Name: "gopher", Age: 5})
748+
Equal(t, errs, nil)
749+
}
750+
697751
func TestAliasTags(t *testing.T) {
698752
validate := New()
699753
validate.RegisterAlias("iscoloralias", "hexcolor|rgb|rgba|hsl|hsla|cmyk")
@@ -8031,6 +8085,10 @@ func TestLength(t *testing.T) {
80318085
validate := New()
80328086
i := true
80338087
PanicMatches(t, func() { _ = validate.Var(i, "len") }, "Bad field type bool")
8088+
8089+
var f32 float32 = 5
8090+
Equal(t, validate.Var(f32, "len=5"), nil)
8091+
NotEqual(t, validate.Var(f32, "len=6"), nil)
80348092
}
80358093

80368094
func TestIsGt(t *testing.T) {
@@ -8051,6 +8109,11 @@ func TestIsGt(t *testing.T) {
80518109
NotEqual(t, errs, nil)
80528110
AssertError(t, errs, "", "", "", "", "gt")
80538111

8112+
var f32 float32 = 1.23
8113+
errs = validate.Var(f32, "gt=5")
8114+
NotEqual(t, errs, nil)
8115+
AssertError(t, errs, "", "", "", "", "gt")
8116+
80548117
i := true
80558118
PanicMatches(t, func() { _ = validate.Var(i, "gt") }, "Bad field type bool")
80568119

@@ -8136,6 +8199,26 @@ func TestIsGte(t *testing.T) {
81368199
var errs error
81378200
validate := New()
81388201

8202+
myMap := map[string]string{}
8203+
errs = validate.Var(myMap, "gte=1")
8204+
NotEqual(t, errs, nil)
8205+
AssertError(t, errs, "", "", "", "", "gte")
8206+
8207+
f := 1.23
8208+
errs = validate.Var(f, "gte=5")
8209+
NotEqual(t, errs, nil)
8210+
AssertError(t, errs, "", "", "", "", "gte")
8211+
8212+
var ui uint = 5
8213+
errs = validate.Var(ui, "gte=10")
8214+
NotEqual(t, errs, nil)
8215+
AssertError(t, errs, "", "", "", "", "gte")
8216+
8217+
var f32 float32 = 1.23
8218+
errs = validate.Var(f32, "gte=5")
8219+
NotEqual(t, errs, nil)
8220+
AssertError(t, errs, "", "", "", "", "gte")
8221+
81398222
i := true
81408223
PanicMatches(t, func() { _ = validate.Var(i, "gte") }, "Bad field type bool")
81418224

@@ -8452,6 +8535,11 @@ func TestIsLt(t *testing.T) {
84528535
NotEqual(t, errs, nil)
84538536
AssertError(t, errs, "", "", "", "", "lt")
84548537

8538+
var f32 float32 = 1.23
8539+
errs = validate.Var(f32, "lt=0")
8540+
NotEqual(t, errs, nil)
8541+
AssertError(t, errs, "", "", "", "", "lt")
8542+
84558543
i := true
84568544
PanicMatches(t, func() { _ = validate.Var(i, "lt") }, "Bad field type bool")
84578545

@@ -8538,6 +8626,26 @@ func TestIsLte(t *testing.T) {
85388626
var errs error
85398627
validate := New()
85408628

8629+
myMap := map[string]string{"key": "value"}
8630+
errs = validate.Var(myMap, "lte=0")
8631+
NotEqual(t, errs, nil)
8632+
AssertError(t, errs, "", "", "", "", "lte")
8633+
8634+
f := 1.23
8635+
errs = validate.Var(f, "lte=0")
8636+
NotEqual(t, errs, nil)
8637+
AssertError(t, errs, "", "", "", "", "lte")
8638+
8639+
var ui uint = 5
8640+
errs = validate.Var(ui, "lte=0")
8641+
NotEqual(t, errs, nil)
8642+
AssertError(t, errs, "", "", "", "", "lte")
8643+
8644+
var f32 float32 = 1.23
8645+
errs = validate.Var(f32, "lte=0")
8646+
NotEqual(t, errs, nil)
8647+
AssertError(t, errs, "", "", "", "", "lte")
8648+
85418649
i := true
85428650
PanicMatches(t, func() { _ = validate.Var(i, "lte") }, "Bad field type bool")
85438651

@@ -12079,6 +12187,60 @@ func TestEndsWithValidation(t *testing.T) {
1207912187
}
1208012188
}
1208112189

12190+
func TestStartsNotWithValidation(t *testing.T) {
12191+
tests := []struct {
12192+
Value string `validate:"startsnotwith=(/^ヮ^)/*:・゚✧"`
12193+
Tag string
12194+
ExpectedNil bool
12195+
}{
12196+
{Value: "abcd", Tag: "startsnotwith=(/^ヮ^)/*:・゚✧", ExpectedNil: true},
12197+
{Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "startsnotwith=(/^ヮ^)/*:・゚✧", ExpectedNil: false},
12198+
}
12199+
12200+
validate := New()
12201+
12202+
for i, s := range tests {
12203+
errs := validate.Var(s.Value, s.Tag)
12204+
12205+
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
12206+
t.Fatalf("Index: %d failed Error: %s", i, errs)
12207+
}
12208+
12209+
errs = validate.Struct(s)
12210+
12211+
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
12212+
t.Fatalf("Index: %d failed Error: %s", i, errs)
12213+
}
12214+
}
12215+
}
12216+
12217+
func TestEndsNotWithValidation(t *testing.T) {
12218+
tests := []struct {
12219+
Value string `validate:"endsnotwith=(/^ヮ^)/*:・゚✧"`
12220+
Tag string
12221+
ExpectedNil bool
12222+
}{
12223+
{Value: "(/^ヮ^)/*:・゚✧ glitter", Tag: "endsnotwith=(/^ヮ^)/*:・゚✧", ExpectedNil: true},
12224+
{Value: "glitter (/^ヮ^)/*:・゚✧", Tag: "endsnotwith=(/^ヮ^)/*:・゚✧", ExpectedNil: false},
12225+
}
12226+
12227+
validate := New()
12228+
12229+
for i, s := range tests {
12230+
errs := validate.Var(s.Value, s.Tag)
12231+
12232+
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
12233+
t.Fatalf("Index: %d failed Error: %s", i, errs)
12234+
}
12235+
12236+
errs = validate.Struct(s)
12237+
12238+
if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
12239+
t.Fatalf("Index: %d failed Error: %s", i, errs)
12240+
}
12241+
}
12242+
}
12243+
1208212244
func TestRequiredIf(t *testing.T) {
1208312245
type Inner struct {
1208412246
Field *string

0 commit comments

Comments
 (0)