From a964f5384a87251e7db989326ae721f559f5394b Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Sun, 30 Aug 2015 20:29:04 -0400 Subject: [PATCH] Completed 100% test coverage for alis registration --- baked_in.go | 4 +++- util.go | 27 ++++++++++++++++++--------- validator.go | 10 ++++++++-- validator_test.go | 10 ++++++++++ 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/baked_in.go b/baked_in.go index 802804c..c749266 100644 --- a/baked_in.go +++ b/baked_in.go @@ -14,7 +14,9 @@ import ( // defines a common or complex set of validation(s) to simplify // adding validation to structs. i.e. set key "_ageok" and the tags // are "gt=0,lte=130" or key "_preferredname" and tags "omitempty,gt=0,lte=60" -var BakedInAliasValidators = map[string]string{} +var BakedInAliasValidators = map[string]string{ + "iscolor": "hexcolor|rgb|rgba|hsl|hsla", +} // BakedInValidators is the default map of ValidationFunc // you can add, remove or even replace items to suite your needs, diff --git a/util.go b/util.go index eb5d11f..59e4505 100644 --- a/util.go +++ b/util.go @@ -13,8 +13,8 @@ const ( leftBracket = "[" rightBracket = "]" restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}" - restrictedAliasErr = "Alias \"%s\" either contains restricted characters or is the same as a restricted tag needed for normal operation\n" - restrictedTagErr = "Tag \"%s\" either contains restricted characters or is the same as a restricted tag needed for normal operation\n" + restrictedAliasErr = "Alias \"%s\" either contains restricted characters or is the same as a restricted tag needed for normal operation" + restrictedTagErr = "Tag \"%s\" either contains restricted characters or is the same as a restricted tag needed for normal operation" ) var ( @@ -234,15 +234,16 @@ func panicIf(err error) { func (v *Validate) parseTags(tag, fieldName string) []*tagCache { - return v.parseTagsRecursive(tag, fieldName, blank, false) + tags, _ := v.parseTagsRecursive(tag, fieldName, blank, false) + return tags } -func (v *Validate) parseTagsRecursive(tag, fieldName, alias string, isAlias bool) []*tagCache { +func (v *Validate) parseTagsRecursive(tag, fieldName, alias string, isAlias bool) ([]*tagCache, bool) { tags := []*tagCache{} if len(tag) == 0 { - return tags + return tags, true } for _, t := range strings.Split(tag, tagSeparator) { @@ -250,14 +251,22 @@ func (v *Validate) parseTagsRecursive(tag, fieldName, alias string, isAlias bool if v.config.hasAliasValidators { // check map for alias and process new tags, otherwise process as usual if tagsVal, ok := v.config.aliasValidators[t]; ok { - tags = append(tags, v.parseTagsRecursive(tagsVal, fieldName, t, true)...) + + aliasTags, leave := v.parseTagsRecursive(tagsVal, fieldName, t, true) + tags = append(tags, aliasTags...) + + if leave { + return tags, leave + } + continue } } if t == diveTag { - tags = append(tags, &tagCache{tagVals: [][]string{{t}}}) - break + tVals := &tagCache{diveTag: tag, tagVals: [][]string{{t}}} + tags = append(tags, tVals) + return tags, true } // if a pipe character is needed within the param you must use the utf8Pipe representation "0x7C" @@ -291,5 +300,5 @@ func (v *Validate) parseTagsRecursive(tag, fieldName, alias string, isAlias bool } } - return tags + return tags, false } diff --git a/validator.go b/validator.go index 8dcfa60..1fbba26 100644 --- a/validator.go +++ b/validator.go @@ -55,6 +55,7 @@ type tagCache struct { isOrVal bool isAlias bool tag string + diveTag string // actualTag string } @@ -191,8 +192,12 @@ func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{ // to structs. func (v *Validate) RegisterAliasValidation(alias, tags string) { - if v.config.aliasValidators == nil { + if len(v.config.aliasValidators) == 0 { + // must copy validators for separate validations to be used in each v.config.aliasValidators = map[string]string{} + for k, val := range BakedInAliasValidators { + v.config.aliasValidators[k] = val + } } _, ok := restrictedTags[alias] @@ -471,7 +476,8 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect. if cTag.tagVals[0][0] == diveTag { dive = true - diveSubTag = strings.TrimLeft(strings.SplitN(tag, diveTag, 2)[1], ",") + // fmt.Println(cTag.diveTag) + diveSubTag = strings.TrimLeft(strings.SplitN(cTag.diveTag, diveTag, 2)[1], ",") break } diff --git a/validator_test.go b/validator_test.go index 03bf489..45a3e58 100644 --- a/validator_test.go +++ b/validator_test.go @@ -243,6 +243,14 @@ func TestAliasTags(t *testing.T) { NotEqual(t, errs, nil) AssertError(t, errs, "Test.Color", "Color", "iscolor") Equal(t, errs["Test.Color"].ActualTag, "hexcolor|rgb|rgba|hsl|hsla") + + validate.RegisterAliasValidation("req", "required,dive,iscolor") + arr := []string{"val1", "#fff", "#000"} + errs = validate.Field(arr, "req") + NotEqual(t, errs, nil) + AssertError(t, errs, "[0]", "[0]", "iscolor") + + PanicMatches(t, func() { validate.RegisterAliasValidation("exists", "gt=5,lt=10") }, "Alias \"exists\" either contains restricted characters or is the same as a restricted tag needed for normal operation") } func TestStructPartial(t *testing.T) { @@ -3881,6 +3889,8 @@ func TestAddFunctions(t *testing.T) { errs = validate.RegisterValidation("new", fn) Equal(t, errs, nil) + + PanicMatches(t, func() { validate.RegisterValidation("dive", fn) }, "Tag \"dive\" either contains restricted characters or is the same as a restricted tag needed for normal operation") } func TestChangeTag(t *testing.T) {