Skip to content

Commit

Permalink
Fixed validation for string subtypes (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
boynton committed Jul 8, 2017
1 parent 83c5c40 commit 7d2a393
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 26 deletions.
88 changes: 62 additions & 26 deletions rdl/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,39 +199,75 @@ func (checker *validator) validate(t *Type, data interface{}, context string) Va
return checker.typeMismatchVariant(context, data, t)
}

func (checker *validator) validateString(t *Type, data string, context string) Validation {
func (checker *validator) flattenStringConstraints(t *Type, name TypeName, pattern string, values []string, min, max *int32) (TypeName, string, []string, *int32, *int32) {
var super TypeRef
switch t.Variant {
case TypeVariantStringTypeDef:
typedef := t.StringTypeDef
if typedef.Values != nil {
match := false
for _, v := range typedef.Values {
if v == data {
match = true
break
}
}
if !match {
return checker.bad(context, "Value mismatch in String type", data, typedef.Name)
}
if name == "" {
name = typedef.Name
}
if typedef.Pattern != "" {
pattern := "^" + typedef.Pattern + "$"
matcher, err := regexp.Compile(pattern)
if err != nil {
return checker.bad(context, "Bad pattern in String type definition /"+pattern+"/", data, typedef.Name)
}
if !matcher.MatchString(data) {
return checker.bad(context, "Pattern mismatch in String type /"+pattern+"/", data, typedef.Name)
}
if pattern == "" && typedef.Pattern != "" {
pattern = typedef.Pattern
}
if values == nil && typedef.Values != nil {
values = typedef.Values
}
if min == nil && typedef.MinSize != nil {
min = typedef.MinSize
}
if max == nil && typedef.MaxSize != nil {
max = typedef.MaxSize
}
super = typedef.Type
case TypeVariantAliasTypeDef:
//nothing to check
super = t.AliasTypeDef.Type
if name == "" {
name = t.AliasTypeDef.Name
}
case TypeVariantBaseType:
//nothing to check
default:
tName, _, _ := TypeInfo(t)
return checker.bad(context, "Bad variant", data, tName)
if name == "" {
name = "String"
}
return name, pattern, values, min, max
}
st := checker.registry.FindType(super)
return checker.flattenStringConstraints(st, name, pattern, values, min, max)
}

func (checker *validator) validateString(t *Type, data string, context string) Validation {
name, pattern, values, min, max := checker.flattenStringConstraints(t, "", "", nil, nil, nil)
if min != nil {
if len(data) < int(*min) {
return checker.bad(context, "String too small", data, name)
}
}
if max != nil {
if len(data) > int(*max) {
return checker.bad(context, "String too large", data, name)
}
}
if values != nil {
match := false
for _, v := range values {
if v == data {
match = true
break
}
}
if !match {
return checker.bad(context, "Value mismatch in String type", data, name)
}
}
if pattern != "" {
pat := "^" + pattern + "$"
matcher, err := regexp.Compile(pat)
if err != nil {
return checker.bad(context, "Bad pattern in String type definition /"+pat+"/", data, name)
}
if !matcher.MatchString(data) {
return checker.bad(context, "Pattern mismatch in String type /"+pat+"/", data, name)
}
}
return checker.good(t, data)
}
Expand Down
19 changes: 19 additions & 0 deletions rdl/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,22 @@ func TestValidatorCustomTypes(test *testing.T) {
}

}

func TestValidateStringSubtype(test *testing.T) {
schema, err := parseRDLString(`
type Foo String (pattern="[a-z]*")
type Bar Foo (maxSize=4);
`)
if err != nil {
test.Errorf("cannot parse valid RDL: %v", err)
return
}
validation := Validate(schema, "Bar", "1")
if validation.Error == "" {
test.Errorf("validation error did not occur, string has non-alpha characters: %v\nschema is: %v", validation, schema)
}
validation = Validate(schema, "Bar", "abcdef")
if validation.Error == "" {
test.Errorf("Validation error did not occur, string is too long: %v\nschema is: %v", validation, schema)
}
}

0 comments on commit 7d2a393

Please sign in to comment.