Skip to content

Commit

Permalink
Enable customValidation on root (#438)
Browse files Browse the repository at this point in the history
* Enable customValidation on root

* handle review comments

* remove CustomValidFuncType

Co-authored-by: samanta <soumik.samanta@nokia.com>
  • Loading branch information
soumiksamanta and samanta authored Sep 1, 2020
1 parent b9d3c8f commit dc7c9e6
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
23 changes: 22 additions & 1 deletion ytypes/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ type LeafrefOptions struct {
// interface.
func (*LeafrefOptions) IsValidationOption() {}

// CustomValidationOptions controls the custom validate function to be
// invoked on the root
type CustomValidationOptions struct {
// FakeRootCustomValidate specifies the user implemented method
FakeRootCustomValidate func(ygot.GoStruct) error
}

// IsValidationOption ensures that CustomValidationOptions implements the ValidationOption
// interface.
func (*CustomValidationOptions) IsValidationOption() {}

// Validate recursively validates the value of the given data tree struct
// against the given schema.
func Validate(schema *yang.Entry, value interface{}, opts ...ygot.ValidationOption) util.Errors {
Expand All @@ -60,10 +71,13 @@ func Validate(schema *yang.Entry, value interface{}, opts ...ygot.ValidationOpti
// and overwrite with the last within the options slice, rather than
// explicitly returning an error.
var leafrefOpt *LeafrefOptions
var customValidOpt *CustomValidationOptions
for _, o := range opts {
switch v := o.(type) {
case *LeafrefOptions:
leafrefOpt = v
case *CustomValidationOptions:
customValidOpt = v
}
}

Expand All @@ -72,6 +86,14 @@ func Validate(schema *yang.Entry, value interface{}, opts ...ygot.ValidationOpti
// Leafref validation traverses entire tree from the root. Do this only
// once from the fakeroot.
errs = ValidateLeafRefData(schema, value, leafrefOpt)
// If CustomValidation is enabled, call the CustomValidateFunc
// and append the error, if any
gsv, ok := value.(ygot.GoStruct)
if ok && customValidOpt != nil {
if err := customValidOpt.FakeRootCustomValidate(gsv); err != nil {
errs = util.AppendErr(errs, err)
}
}
}

util.DbgPrint("Validate with value %v, type %T, schema name %s", util.ValueStr(value), value, schema.Name)
Expand All @@ -92,6 +114,5 @@ func Validate(schema *yang.Entry, value interface{}, opts ...ygot.ValidationOpti
case schema.IsChoice():
return util.AppendErrs(errs, util.NewErrs(fmt.Errorf("cannot pass choice schema %s to Validate", schema.Name)))
}

return util.AppendErrs(errs, util.NewErrs(fmt.Errorf("unknown schema type for type %T, value %v", value, value)))
}
42 changes: 42 additions & 0 deletions ytypes/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package ytypes

import (
"fmt"
"testing"

"github.com/openconfig/goyang/pkg/yang"
Expand Down Expand Up @@ -46,6 +47,16 @@ type FakeRootStruct struct {

func (*FakeRootStruct) IsYANGGoStruct() {}

func customValidation(val ygot.GoStruct) error {
fakeRoot, ok := val.(*FakeRootStruct)
if !ok {
return fmt.Errorf("not valid fakeroot")
}
if fakeRoot.LeafThree == nil || *fakeRoot.LeafThree != "kingfisher" {
return fmt.Errorf("leafThree should be kingfisher")
}
return nil
}
func TestValidate(t *testing.T) {
leafSchema := &yang.Entry{Name: "leaf-schema", Kind: yang.LeafEntry, Type: &yang.YangType{Kind: yang.Ystring}}

Expand Down Expand Up @@ -189,6 +200,37 @@ func TestValidate(t *testing.T) {
},
opts: []ygot.ValidationOption{&LeafrefOptions{IgnoreMissingData: true}},
},
{
desc: "fakeroot with custom validation",
schema: fakerootSchema,
val: &FakeRootStruct{
LeafOne: ygot.String("one"),
LeafTwo: ygot.String("one"),
},
opts: []ygot.ValidationOption{&CustomValidationOptions{FakeRootCustomValidate: customValidation}},
wantErr: "leafThree should be kingfisher",
wantErrLen: 1,
},
{
desc: "fakeroot with custom validation and ignore bad leafref",
schema: fakerootSchema,
val: &FakeRootStruct{
LeafTwo: ygot.String("two"),
},
opts: []ygot.ValidationOption{&LeafrefOptions{IgnoreMissingData: true}, &CustomValidationOptions{FakeRootCustomValidate: customValidation}},
wantErr: "leafThree should be kingfisher",
wantErrLen: 1,
},
{
desc: "fakeroot with custom validation and bad leafref",
schema: fakerootSchema,
val: &FakeRootStruct{
LeafTwo: ygot.String("two"),
},
opts: []ygot.ValidationOption{&CustomValidationOptions{FakeRootCustomValidate: customValidation}},
wantErr: "pointed-to value with path ../leaf-one from field LeafTwo value two (string ptr) schema /device/leaf-two is empty set, leafThree should be kingfisher",
wantErrLen: 2,
},
{
desc: "two errors",
schema: fakerootSchema,
Expand Down

0 comments on commit dc7c9e6

Please sign in to comment.