From 1d36b4ad76e5cfb41a8b67c8c37ab725575afde4 Mon Sep 17 00:00:00 2001 From: Wen Bo Li <50884368+wenovus@users.noreply.github.com> Date: Fri, 30 Sep 2022 13:41:09 -0700 Subject: [PATCH] Add .Validate() to ytypes.Schema and ygot.ValidateGoStruct() (#732) * Add .Validate() to ytypes.Schema * Add ygot.ValidateGoStruct --- ygot/struct_validation_map.go | 9 ++------- ygot/types.go | 10 ++++++++++ ytypes/types.go | 9 +++++++++ ytypes/types_test.go | 4 ++++ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/ygot/struct_validation_map.go b/ygot/struct_validation_map.go index bab72ccf0..1485f8412 100644 --- a/ygot/struct_validation_map.go +++ b/ygot/struct_validation_map.go @@ -411,18 +411,13 @@ func EmitJSON(gs GoStruct, opts *EmitJSONConfig) (string, error) { skipValidation = opts.SkipValidation } - s, ok := gs.(validatedGoStruct) - if !ok { - return "", fmt.Errorf("input GoStruct does not have ΛValidate() method") - } - if !skipValidation { - if err := s.ΛValidate(vopts...); err != nil { + if err := ValidateGoStruct(gs, vopts...); err != nil { return "", fmt.Errorf("validation err: %v", err) } } - v, err := makeJSON(s, opts) + v, err := makeJSON(gs, opts) if err != nil { return "", err } diff --git a/ygot/types.go b/ygot/types.go index 2b437f212..03bc75392 100644 --- a/ygot/types.go +++ b/ygot/types.go @@ -15,6 +15,7 @@ package ygot import ( + "fmt" "reflect" ) @@ -56,6 +57,15 @@ type ValidatedGoStruct interface { ΛBelongingModule() string } +// ValidateGoStruct validates a GoStruct. +func ValidateGoStruct(goStruct GoStruct, vopts ...ValidationOption) error { + vroot, ok := goStruct.(validatedGoStruct) + if !ok { + return fmt.Errorf("GoStruct cannot be validated: (%T, %v)", goStruct, goStruct) + } + return vroot.ΛValidate(vopts...) +} + // validatedGoStruct is an interface used for validating GoStructs. // This interface is implemented by all Go structs (YANG container or lists), // regardless of generation flag. diff --git a/ytypes/types.go b/ytypes/types.go index faaed45a0..94d5199ea 100644 --- a/ytypes/types.go +++ b/ytypes/types.go @@ -15,6 +15,7 @@ package ytypes import ( + "errors" "reflect" "github.com/openconfig/goyang/pkg/yang" @@ -41,5 +42,13 @@ func (s *Schema) RootSchema() *yang.Entry { return s.SchemaTree[reflect.TypeOf(s.Root).Elem().Name()] } +// Validate performs schema validation on the schema root. +func (s *Schema) Validate(vopts ...ygot.ValidationOption) error { + if !s.IsValid() { + return errors.New("invalid schema: not fully populated") + } + return ygot.ValidateGoStruct(s.Root, vopts...) +} + // UnmarshalFunc defines a common signature for an RFC7951 to ygot.GoStruct unmarshalling function type UnmarshalFunc func([]byte, ygot.GoStruct, ...UnmarshalOpt) error diff --git a/ytypes/types_test.go b/ytypes/types_test.go index dc99026ea..72d61c775 100644 --- a/ytypes/types_test.go +++ b/ytypes/types_test.go @@ -68,6 +68,10 @@ func TestSchema(t *testing.T) { t.Errorf("did not get expected valid status, got: %v, want: %v", got, tt.wantValid) } + if got := tt.in.Validate(); (got == nil) != tt.wantValid { + t.Errorf("did not get expected validate return, got: %v, want: %v", got, tt.wantValid) + } + if !tt.wantValid { return }