fix(validators): handle pointer fields in RequiredIf (#334) - #335
Merged
Merged
Conversation
RequiredIf silently skipped its check whenever either side of the rule
was a pointer:
- When the destination field is a pointer (e.g. *bool), reflect.ValueOf
returns a value of Kind Pointer. convTypeByBaseKind has no
string-to-Pointer conversion, so dstVal == wantVal was never
evaluated and the function fell through to default-True / skip.
- When the source field is a pointer to a zero value (e.g.
*string("")), val != nil && !IsEmpty(val) was true, so the
rule's 'must be present and not empty' contract was not enforced.
Unwrap pointers on both sides: treat a nil pointer as the field being
absent (rule does not trigger, dependent field remains optional), and
treat a pointer to a zero value as the zero value itself for the
not-empty check. Adds five subtests covering each pointer scenario;
two of them fail on the old code and pass on the new code.
Closes gookit#334
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #334.
Validation.RequiredIfsilently skipped its check whenever either side of the rule was a pointer:*bool/*stringfield,reflect.ValueOf(dstVal).Kind()isreflect.Pointer.convTypeByBaseKindhas no string-to-Pointer conversion, sodstVal == wantValwas never evaluated and the function fell through to thedefault as True, skip checkbranch.val != nil && !IsEmpty(val)istruefor*string("")(the pointer is non-nil), so themust be present and not emptycontract was not enforced.Unwrap pointers on both sides:
requiredIfValIsPresenthelper applies the same nil-and-zero-via-pointer logic to the source field, so*string("")is treated the same as"".The reproducer from the issue:
Before this PR, both
{IsOld: &true, Experience: &""}and{IsOld: &true}reportedIsSuccess() == true. With this PR they correctly reportfalse, while{IsOld: &false}and{IsOld: nil}still pass and{IsOld: &true, Experience: &"10y"}still passes.Tests
TestIssues_334inissues_test.goadds five subtests covering each pointer scenario in the issue. Two of them (pointer to empty string is not present,nil pointer is not present) fail on the old code withResult should be Falseand pass on the new code; the three previously-passing positive cases continue to pass.go test ./... -count=1 -racepasses locally for the main package and all three locale sub-packages.go vet ./...andgofmt -l validators.go issues_test.goare clean.