From 6972537ac7c67657c518f5d74ad1d82f70efc8a3 Mon Sep 17 00:00:00 2001 From: Wen Bo Li <50884368+wenovus@users.noreply.github.com> Date: Thu, 9 Jun 2022 09:57:58 -0700 Subject: [PATCH] Delete unused variables and rephrase package comments for ygen. (#697) * Delete unused variables and rephrase package comments for ygen. * Fix `IdentityType` classification bug. (#699) * Fix `IdentityType` classification bug. Right now all typedefs are automatically categorized as `DerivedEnumerationType`; this is wrong because identity types could also be in a typedef. Fixed this bug and added tests. * Remove debugging statement * Add coverage for proto generation of typedef identityref * Run go generate ./... for CI check (#703) * Run go generate ./... for CI check * Regenerate exampleoc but don't depend on it for tests * Delete `StoreRawSchema` from `GeneratorConfig` since it's not being used (#705) * Delete `StoreRawSchema` from `GeneratorConfig` since it's not being used I don't see the value of why we need this flag: is it to save memory? For `exampleoc` this variable took 27MB, a negligible amount. * Reorganize Code Generation flags and Delete `ygen.GeneratorConfig` (#706) * ygen now only has `IROptions`. * `CodeGenerator` in gogen/protogen now carry IROptions and their language-specific post-IR generation options. * Code generation specific flags that are not used during IR generation are moved to `gogen` and `protogen`, duplicating if used by both (e.g. CallerName). * `SkipEnumDeduplication` is moved from ParseOptions to TransformationOptions. --- .github/workflows/go.yml | 4 + Makefile | 32 +- demo/getting_started/interfaces_test.go | 20 +- demo/protobuf_getting_started/demo.go | 2 + demo/protobuf_getting_started/update.sh | 2 - generator/generator.go | 44 +- gogen/codegen.go | 58 +- gogen/codegen_test.go | 1082 +++++++++-------- gogen/genir_test.go | 31 + gogen/goelements.go | 6 +- gogen/gogen.go | 37 +- gogen/gogen_test.go | 28 +- integration_tests/generate_errs_test.go | 6 +- proto_generator/protogenerator.go | 31 +- protogen/codegen.go | 44 +- protogen/codegen_test.go | 284 +++-- protogen/genir_test.go | 51 + protogen/protoelements.go | 4 +- protogen/protoelements_test.go | 2 - .../proto-enums-addid.enums.formatted-txt | 7 + .../proto/proto-enums-addid.formatted-txt | 1 + .../proto/proto-enums.enums.formatted-txt | 6 + .../testdata/proto/proto-enums.formatted-txt | 1 + protogen/testdata/proto/proto-enums.yang | 11 + testdata/modules/openconfig-complex.yang | 10 + ygen/codegen.go | 114 +- ygen/enumgen.go | 6 +- ygen/genir.go | 7 +- ygen/genstate_test.go | 9 +- ypathgen/pathgen.go | 6 +- 30 files changed, 1088 insertions(+), 858 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index a975f0e16..a3a8bf26b 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -118,6 +118,10 @@ jobs: test-go-build $f $go_file done + - name: Make sure exampleoc doesn't error or panic + run: go generate ./... + working-directory: go/src/github.com/openconfig/ygot + static_analysis: name: Static Analysis runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index 7f448505d..a0f4e33c9 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,20 @@ # ygot Makefile # -# This makefile is used by Travis CI to run tests against the ygot library. +# This makefile is used by GitHub Actions CI to run tests against the ygot library. # -ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) - test: go test ./... generate: - cd ${ROOT_DIR}/demo/getting_started && SRCDIR=${ROOT_DIR} go generate - cd ${ROOT_DIR}/proto/ywrapper && SRCDIR=${ROOT_DIR} go generate - cd $(ROOT_DIR)/proto/yext && SRCDIR=${ROOT_DIR} go generate - cd $(ROOT_DIR)/demo/uncompressed && SRCDIR=${ROOT_DIR} go generate - cd $(ROOT_DIR)/demo/protobuf_getting_started && SRCDIR=${ROOT_DIR} ./update.sh - cd $(ROOT_DIR)/integration_tests/uncompressed && SRCDIR=${ROOT_DIR} go generate - cd $(ROOT_DIR)/integration_tests/annotations/apb && SRCDIR=${ROOT_DIR} go generate - cd $(ROOT_DIR)/integration_tests/annotations/proto2apb && SRCDIR=${ROOT_DIR} go generate + go generate ./demo/getting_started + go generate ./proto/ywrapper + go generate ./proto/yext + go generate ./demo/uncompressed + go generate ./demo/protobuf_getting_started + go generate ./integration_tests/uncompressed + go generate ./integration_tests/annotations/apb + go generate ./integration_tests/annotations/proto2apb clean: - rm -f ${ROOT_DIR}/demo/getting_started/pkg/ocdemo/oc.go - rm -f ${ROOT_DIR}/demo/uncompressed/pkg/demo/uncompressed.go -deps: - go get -t -d ./ygot - go get -t -d ./ygen - go get -t -d ./generator - go get -t -d ./proto_generator - go get -t -d ./exampleoc - go get -t -d ./ytypes - go get -t -d ./demo/gnmi_telemetry + rm -f demo/getting_started/pkg/ocdemo/oc.go + rm -f demo/uncompressed/pkg/demo/uncompressed.go install: deps generate all: clean deps generate test diff --git a/demo/getting_started/interfaces_test.go b/demo/getting_started/interfaces_test.go index 4822cad9c..dfd05941d 100644 --- a/demo/getting_started/interfaces_test.go +++ b/demo/getting_started/interfaces_test.go @@ -22,13 +22,13 @@ var TestRoot string func TestGenerateCode(t *testing.T) { tests := []struct { name string - inConfig *ygen.GeneratorConfig - inGoOpts *gogen.GoOpts + inIROpts ygen.IROptions + inGoOpts gogen.GoOpts inFiles []string inPaths []string }{{ name: "openconfig interfaces", - inConfig: &ygen.GeneratorConfig{ + inIROpts: ygen.IROptions{ ParseOptions: ygen.ParseOpts{ ExcludeModules: []string{"ietf-interfaces"}, }, @@ -36,9 +36,9 @@ func TestGenerateCode(t *testing.T) { CompressBehaviour: genutil.PreferIntendedConfig, GenerateFakeRoot: true, }, - GenerateJSONSchema: true, }, - inGoOpts: &gogen.GoOpts{ + inGoOpts: gogen.GoOpts{ + GenerateJSONSchema: true, GenerateSimpleUnions: true, }, inFiles: []string{ @@ -48,16 +48,16 @@ func TestGenerateCode(t *testing.T) { inPaths: []string{filepath.Join(TestRoot, "yang")}, }, { name: "openconfig interfaces with no compression", - inConfig: &ygen.GeneratorConfig{ + inIROpts: ygen.IROptions{ ParseOptions: ygen.ParseOpts{ ExcludeModules: []string{"ietf-interfaces"}, }, TransformationOptions: ygen.TransformationOpts{ GenerateFakeRoot: true, }, - GenerateJSONSchema: true, }, - inGoOpts: &gogen.GoOpts{ + inGoOpts: gogen.GoOpts{ + GenerateJSONSchema: true, GenerateSimpleUnions: true, }, inFiles: []string{ @@ -68,10 +68,10 @@ func TestGenerateCode(t *testing.T) { }} for _, tt := range tests { - cg := gogen.NewCodeGenerator(tt.inConfig, tt.inGoOpts) + cg := gogen.New("", tt.inIROpts, tt.inGoOpts) got, err := cg.Generate(tt.inFiles, tt.inPaths) if err != nil { - t.Errorf("%s: Generate(%v, %v): Config: %v, got unexpected error: %v", tt.name, tt.inFiles, tt.inPaths, tt.inConfig, err) + t.Errorf("%s: Generate(%v, %v): Config: %v, got unexpected error: %v", tt.name, tt.inFiles, tt.inPaths, tt.inIROpts, err) continue } diff --git a/demo/protobuf_getting_started/demo.go b/demo/protobuf_getting_started/demo.go index 05d1dbca6..15e101619 100644 --- a/demo/protobuf_getting_started/demo.go +++ b/demo/protobuf_getting_started/demo.go @@ -17,6 +17,8 @@ // to generate a Protobuf form of the OpenConfig RIB model. package main +//go:generate ./update.sh + import ( "fmt" diff --git a/demo/protobuf_getting_started/update.sh b/demo/protobuf_getting_started/update.sh index 3d02941b7..08198c171 100755 --- a/demo/protobuf_getting_started/update.sh +++ b/demo/protobuf_getting_started/update.sh @@ -17,8 +17,6 @@ go run ../../proto_generator/protogenerator.go \ -base_import_path="github.com/openconfig/ygot/demo/protobuf_getting_started/ribproto" \ -go_package_base="github.com/openconfig/ygot/demo/protobuf_getting_started/ribproto" \ -path=yang -output_dir=ribproto \ - -typedef_enum_with_defmod \ - -consistent_union_enum_names \ -enum_package_name=enums -package_name=openconfig \ -exclude_modules=ietf-interfaces \ yang/rib/openconfig-rib-bgp.yang diff --git a/generator/generator.go b/generator/generator.go index 28b6515ed..0d1f90e23 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -325,29 +325,30 @@ func main() { } // Perform the code generation. - cg := gogen.NewCodeGenerator(&ygen.GeneratorConfig{ - ParseOptions: ygen.ParseOpts{ - ExcludeModules: modsExcluded, - SkipEnumDeduplication: *skipEnumDedup, - YANGParseOptions: yang.Options{ - IgnoreSubmoduleCircularDependencies: *ignoreCircDeps, + cg := gogen.New( + "", + ygen.IROptions{ + ParseOptions: ygen.ParseOpts{ + ExcludeModules: modsExcluded, + YANGParseOptions: yang.Options{ + IgnoreSubmoduleCircularDependencies: *ignoreCircDeps, + }, + }, + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: compressBehaviour, + GenerateFakeRoot: *generateFakeRoot, + FakeRootName: *fakeRootName, + SkipEnumDeduplication: *skipEnumDedup, + ShortenEnumLeafNames: *shortenEnumLeafNames, + EnumOrgPrefixesToTrim: enumOrgPrefixesToTrim, + UseDefiningModuleForTypedefEnumNames: *useDefiningModuleForTypedefEnumNames, + EnumerationsUseUnderscores: true, }, }, - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: compressBehaviour, - IgnoreShadowSchemaPaths: *ignoreShadowSchemaPaths, - GenerateFakeRoot: *generateFakeRoot, - FakeRootName: *fakeRootName, - ShortenEnumLeafNames: *shortenEnumLeafNames, - EnumOrgPrefixesToTrim: enumOrgPrefixesToTrim, - UseDefiningModuleForTypedefEnumNames: *useDefiningModuleForTypedefEnumNames, - EnumerationsUseUnderscores: true, - }, - PackageName: *packageName, - GenerateJSONSchema: *generateSchema, - IncludeDescriptions: *includeDescriptions, - }, - &gogen.GoOpts{ + gogen.GoOpts{ + PackageName: *packageName, + GenerateJSONSchema: *generateSchema, + IncludeDescriptions: *includeDescriptions, YgotImportPath: *ygotImportPath, YtypesImportPath: *ytypesImportPath, GoyangImportPath: *goyangImportPath, @@ -364,6 +365,7 @@ func main() { GenerateSimpleUnions: *generateSimpleUnions, IncludeModelData: *includeModelData, AppendEnumSuffixForSimpleUnionEnums: *appendEnumSuffixForSimpleUnionEnums, + IgnoreShadowSchemaPaths: *ignoreShadowSchemaPaths, }, ) diff --git a/gogen/codegen.go b/gogen/codegen.go index cc9e23f55..d14264bc1 100644 --- a/gogen/codegen.go +++ b/gogen/codegen.go @@ -15,19 +15,31 @@ import ( // CodeGenerator is a structure that is used to pass arguments as to // how the output Go code should be generated. type CodeGenerator struct { - // Config stores the configuration parameters used for code generation. - Config ygen.GeneratorConfig + // Caller is the name of the binary calling the generator library, it is + // included in the header of output files for debugging purposes. If a + // string is not specified, the location of the library is utilised. + Caller string + // IROptions stores the configuration parameters used for IR generation. + IROptions ygen.IROptions // GoOptions stores a struct which stores Go code generation specific - // options for the code generaton. + // options for code generaton post IR generation. GoOptions GoOpts } // GoOpts stores Go specific options for the code generation library. type GoOpts struct { + // PackageName is the name that should be used for the generating package. + PackageName string + // GenerateJSONSchema stores a boolean which defines whether to generate + // the JSON corresponding to the YANG schema parsed to generate the + // output code. + GenerateJSONSchema bool + // IncludeDescriptions specifies that YANG entry descriptions are added + // to the JSON schema. Is false by default, to reduce the size of generated schema + IncludeDescriptions bool // SchemaVarName is the name for the variable which stores the compressed // JSON schema in the generated Go code. JSON schema output is only - // produced if the GenerateJSONSchema YANGCodeGenerator field is set to - // true. + // produced if the GenerateJSONSchema field is set to true. SchemaVarName string // GoyangImportPath specifies the path that should be used in the generated // code for importing the goyang/pkg/yang package. @@ -100,6 +112,10 @@ type GoOpts struct { // only applies when useDefiningModuleForTypedefEnumNames is also set // to true. AppendEnumSuffixForSimpleUnionEnums bool + // IgnoreShadowSchemaPaths indicates whether when OpenConfig path + // compression is enabled, that the shadowed paths are to be ignored + // while while unmarshalling. + IgnoreShadowSchemaPaths bool } // GeneratedCode contains generated code snippets that can be processed by the calling @@ -133,25 +149,19 @@ type GeneratedCode struct { // - structname - the name of the struct that was generated for the schema element. JSONSchemaCode string // RawJSONSchema stores the JSON document which is serialised and stored in JSONSchemaCode. - // It is populated only if the StoreRawSchema CodeGenerator boolean is set to true. RawJSONSchema []byte // EnumTypeMap is a Go map that allows YANG schemapaths to be mapped to reflect.Type values. EnumTypeMap string } -// NewCodeGenerator returns a new instance of the CodeGenerator +// New returns a new instance of the CodeGenerator // struct to the calling function. -func NewCodeGenerator(c *ygen.GeneratorConfig, goopts *GoOpts) *CodeGenerator { - cg := &CodeGenerator{} - - if c != nil { - cg.Config = *c - } - if goopts != nil { - cg.GoOptions = *goopts +func New(callerName string, opts ygen.IROptions, goOpts GoOpts) *CodeGenerator { + return &CodeGenerator{ + Caller: callerName, + IROptions: opts, + GoOptions: goOpts, } - - return cg } // checkForBinaryKeys returns a non-empty list of errors if the input directory @@ -187,8 +197,8 @@ func checkForBinaryKeys(dir *ygen.ParsedDirectory) []error { // If errors are encountered during code generation, an error is returned. func (cg *CodeGenerator) Generate(yangFiles, includePaths []string) (*GeneratedCode, util.Errors) { opts := ygen.IROptions{ - ParseOptions: cg.Config.ParseOptions, - TransformationOptions: cg.Config.TransformationOptions, + ParseOptions: cg.IROptions.ParseOptions, + TransformationOptions: cg.IROptions.TransformationOptions, NestedDirectories: false, AbsoluteMapPaths: false, AppendEnumSuffixForSimpleUnionEnums: cg.GoOptions.AppendEnumSuffixForSimpleUnionEnums, @@ -201,8 +211,8 @@ func (cg *CodeGenerator) Generate(yangFiles, includePaths []string) (*GeneratedC } var rootName string - if cg.Config.TransformationOptions.GenerateFakeRoot { - rootName = cg.Config.TransformationOptions.FakeRootName + if cg.IROptions.TransformationOptions.GenerateFakeRoot { + rootName = cg.IROptions.TransformationOptions.FakeRootName if rootName == "" { rootName = igenutil.DefaultRootName } @@ -240,7 +250,7 @@ func (cg *CodeGenerator) Generate(yangFiles, includePaths []string) (*GeneratedC codegenErr = util.AppendErrs(codegenErr, errs) continue } - structOut, errs := writeGoStruct(dir, ir.Directories, generatedUnions, opts.TransformationOptions.IgnoreShadowSchemaPaths, cg.GoOptions, cg.Config.GenerateJSONSchema) + structOut, errs := writeGoStruct(dir, ir.Directories, generatedUnions, cg.GoOptions) if errs != nil { codegenErr = util.AppendErrs(codegenErr, errs) continue @@ -301,9 +311,9 @@ func (cg *CodeGenerator) Generate(yangFiles, includePaths []string) (*GeneratedC var rawSchema []byte var jsonSchema string var enumTypeMapCode string - if cg.Config.GenerateJSONSchema { + if cg.GoOptions.GenerateJSONSchema { var err error - rawSchema, err = ir.SchemaTree(cg.Config.IncludeDescriptions) + rawSchema, err = ir.SchemaTree(cg.GoOptions.IncludeDescriptions) if err != nil { codegenErr = util.AppendErr(codegenErr, fmt.Errorf("error marshalling JSON schema: %v", err)) } diff --git a/gogen/codegen_test.go b/gogen/codegen_test.go index bdf7d308f..d2c273ce4 100644 --- a/gogen/codegen_test.go +++ b/gogen/codegen_test.go @@ -28,15 +28,14 @@ const ( // through Goyang's API, it provides the input set of parameters in a way that // can be reused across tests. type yangTestCase struct { - name string // Name is the identifier for the test. - inFiles []string // inFiles is the set of inputFiles for the test. - inIncludePaths []string // inIncludePaths is the set of paths that should be searched for imports. - inExcludeModules []string // inExcludeModules is the set of modules that should be excluded from code generation. - inConfig ygen.GeneratorConfig // inConfig specifies the configuration that should be used for the generator test case. - inGoOptions GoOpts // inGoOpts specifies the go-specific configuration that should be used for the generator test case. - wantStructsCodeFile string // wantsStructsCodeFile is the path of the generated Go code that the output of the test should be compared to. - wantErrSubstring string // wantErrSubstring specifies whether the test should expect an error. - wantSchemaFile string // wantSchemaFile is the path to the schema JSON that the output of the test should be compared to. + name string // Name is the identifier for the test. + inFiles []string // inFiles is the set of inputFiles for the test. + inIncludePaths []string // inIncludePaths is the set of paths that should be searched for imports. + inExcludeModules []string // inExcludeModules is the set of modules that should be excluded from code generation. + inConfig CodeGenerator // inConfig specifies the configuration that should be used for the generator test case. + wantStructsCodeFile string // wantsStructsCodeFile is the path of the generated Go code that the output of the test should be compared to. + wantErrSubstring string // wantErrSubstring specifies whether the test should expect an error. + wantSchemaFile string // wantSchemaFile is the path to the schema JSON that the output of the test should be compared to. } // TestSimpleStructs tests the processModules, Generate and writeGoCode @@ -52,349 +51,393 @@ func TestSimpleStructs(t *testing.T) { tests := []yangTestCase{{ name: "simple openconfig test, with compression, with (useless) enum org name trimming", inFiles: []string{filepath.Join(datapath, "openconfig-simple.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - EnumOrgPrefixesToTrim: []string{"openconfig"}, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + EnumOrgPrefixesToTrim: []string{"openconfig"}, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + GenerateLeafGetters: true, + GeneratePopulateDefault: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - GenerateLeafGetters: true, - GeneratePopulateDefault: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-simple.formatted-txt"), }, { name: "simple openconfig test, with excluded state, with compression, with enum org name trimming", inFiles: []string{filepath.Join(datapath, "openconfig-simple.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.ExcludeDerivedState, - ShortenEnumLeafNames: true, - EnumOrgPrefixesToTrim: []string{"openconfig"}, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.ExcludeDerivedState, + ShortenEnumLeafNames: true, + EnumOrgPrefixesToTrim: []string{"openconfig"}, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + GenerateLeafGetters: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - GenerateLeafGetters: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-simple-excludestate.formatted-txt"), }, { name: "simple openconfig test, with no compression", inFiles: []string{filepath.Join(datapath, "openconfig-simple.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + GenerateLeafGetters: true, + GeneratePopulateDefault: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - GenerateLeafGetters: true, - GeneratePopulateDefault: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-simple-no-compress.formatted-txt"), }, { name: "simple openconfig test, with compression, without shortened enum leaf names, with enum org name trimming", inFiles: []string{filepath.Join(datapath, "openconfig-simple.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - EnumOrgPrefixesToTrim: []string{"openconfig"}, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + EnumOrgPrefixesToTrim: []string{"openconfig"}, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-simple.long-enum-names.trimmed-enum.formatted-txt"), }, { name: "simple openconfig test, with no compression, with enum org name trimming", inFiles: []string{filepath.Join(datapath, "openconfig-simple.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - ShortenEnumLeafNames: true, - EnumOrgPrefixesToTrim: []string{"openconfig"}, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + ShortenEnumLeafNames: true, + EnumOrgPrefixesToTrim: []string{"openconfig"}, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-simple-no-compress.trimmed-enum.formatted-txt"), }, { name: "OpenConfig leaf-list defaults test, with compression", inFiles: []string{filepath.Join(datapath, "openconfig-leaflist-default.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + GenerateLeafGetters: true, + GeneratePopulateDefault: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - GenerateLeafGetters: true, - GeneratePopulateDefault: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-leaflist-default.formatted-txt"), }, { name: "OpenConfig schema test - with annotations", inFiles: []string{filepath.Join(datapath, "openconfig-simple.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + AddAnnotationFields: true, + AnnotationPrefix: "ᗩ", + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - AddAnnotationFields: true, - AnnotationPrefix: "ᗩ", - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "openconfig-simple-annotations.formatted-txt"), }, { name: "OpenConfig schema test - list and associated method (rename, new)", inFiles: []string{filepath.Join(datapath, "openconfig-withlist.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateRenameMethod: true, + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateRenameMethod: true, - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-withlist.formatted-txt"), }, { name: "OpenConfig schema test - list and associated method (rename, new) - using operational state", inFiles: []string{filepath.Join(datapath, "openconfig-withlist.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferOperationalState, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferOperationalState, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateRenameMethod: true, + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateRenameMethod: true, - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-withlist-opstate.formatted-txt"), }, { name: "OpenConfig schema test - multi-keyed list key struct name conflict and associated method (rename, new)", inFiles: []string{filepath.Join(datapath, "openconfig-multikey-list-name-conflict.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateRenameMethod: true, + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateRenameMethod: true, - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-multikey-list-name-conflict.formatted-txt"), }, { name: "simple openconfig test, with a list that has an enumeration key", inFiles: []string{filepath.Join(datapath, "openconfig-list-enum-key.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - IgnoreShadowSchemaPaths: true, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + IgnoreShadowSchemaPaths: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-list-enum-key.formatted-txt"), }, { name: "simple openconfig test, with a list that has an enumeration key, with enum org name trimming", inFiles: []string{filepath.Join(datapath, "openconfig-list-enum-key.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - EnumOrgPrefixesToTrim: []string{"openconfig"}, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + EnumOrgPrefixesToTrim: []string{"openconfig"}, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-list-enum-key.trimmed-enum.formatted-txt"), }, { name: "openconfig test with a identityref union", inFiles: []string{filepath.Join(datapath, "openconfig-unione.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-unione.formatted-txt"), }, { name: "openconfig test with a identityref union (wrapper unions)", inFiles: []string{filepath.Join(datapath, "openconfig-unione.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, }, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-unione.wrapper-unions.formatted-txt"), }, { name: "openconfig tests with fakeroot", inFiles: []string{filepath.Join(datapath, "openconfig-fakeroot.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - GenerateFakeRoot: true, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + GenerateFakeRoot: true, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-fakeroot.formatted-txt"), }, { name: "openconfig noncompressed tests with fakeroot", inFiles: []string{filepath.Join(datapath, "openconfig-fakeroot.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-fakeroot-nc.formatted-txt"), }, { name: "schema test with compression", inFiles: []string{filepath.Join(TestRoot, "testdata/schema/openconfig-options.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateJSONSchema: true, + GenerateSimpleUnions: true, }, - GenerateJSONSchema: true, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-compress.formatted-txt"), wantSchemaFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-compress-schema.json"), }, { name: "schema test without compression", inFiles: []string{filepath.Join(TestRoot, "testdata/schema/openconfig-options.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateJSONSchema: true, + GenerateSimpleUnions: true, }, - GenerateJSONSchema: true, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-nocompress.formatted-txt"), wantSchemaFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-nocompress-schema.json"), }, { name: "schema test with fakeroot", inFiles: []string{filepath.Join(TestRoot, "testdata/schema/openconfig-options.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - GenerateFakeRoot: true, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + GenerateFakeRoot: true, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateJSONSchema: true, + GenerateSimpleUnions: true, }, - GenerateJSONSchema: true, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-compress-fakeroot.formatted-txt"), wantSchemaFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-compress-fakeroot-schema.json"), }, { name: "schema test with fakeroot and no compression", inFiles: []string{filepath.Join(TestRoot, "testdata/schema/openconfig-options.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateJSONSchema: true, + GenerateSimpleUnions: true, }, - GenerateJSONSchema: true, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-nocompress-fakeroot.formatted-txt"), wantSchemaFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-nocompress-fakeroot-schema.json"), }, { name: "schema test with camelcase annotations", inFiles: []string{filepath.Join(datapath, "openconfig-camelcase.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - GenerateFakeRoot: true, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + GenerateFakeRoot: true, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-camelcase-compress.formatted-txt"), }, { name: "structs test with camelcase annotations", inFiles: []string{filepath.Join(datapath, "openconfig-enumcamelcase.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-enumcamelcase-compress.formatted-txt"), }, { @@ -407,55 +450,60 @@ func TestSimpleStructs(t *testing.T) { filepath.Join(datapath, "openconfig-simple-target.yang"), filepath.Join(datapath, "openconfig-simple-augment.yang"), }, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - GenerateFakeRoot: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + GenerateFakeRoot: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-augmented.formatted-txt"), }, { name: "variable and import explicitly specified", inFiles: []string{filepath.Join(datapath, "openconfig-simple.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - GenerateFakeRoot: true, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - FakeRootName: "fakeroot", - EnumerationsUseUnderscores: true, - }, - Caller: "testcase", - StoreRawSchema: true, - GenerateJSONSchema: true, - }, - inGoOptions: GoOpts{ - SchemaVarName: "YANGSchema", - GoyangImportPath: "foo/goyang", - YgotImportPath: "bar/ygot", - YtypesImportPath: "baz/ytypes", - GenerateSimpleUnions: true, + inConfig: CodeGenerator{ + Caller: "testcase", + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + GenerateFakeRoot: true, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + FakeRootName: "fakeroot", + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateJSONSchema: true, + SchemaVarName: "YANGSchema", + GoyangImportPath: "foo/goyang", + YgotImportPath: "bar/ygot", + YtypesImportPath: "baz/ytypes", + GenerateSimpleUnions: true, + }, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-explicit.formatted-txt"), wantSchemaFile: filepath.Join(TestRoot, "testdata/schema/openconfig-options-explicit-schema.json"), }, { name: "module with entities at the root", inFiles: []string{filepath.Join(datapath, "root-entities.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - FakeRootName: "fakeroot", - GenerateFakeRoot: true, - EnumerationsUseUnderscores: true, - }, + inConfig: CodeGenerator{ Caller: "testcase", - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + FakeRootName: "fakeroot", + GenerateFakeRoot: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + }, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/root-entities.formatted-txt"), }, { @@ -466,232 +514,262 @@ func TestSimpleStructs(t *testing.T) { name: "module with excluded modules", inFiles: []string{filepath.Join(datapath, "excluded-module.yang")}, inExcludeModules: []string{"excluded-module-two"}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - FakeRootName: "office", - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + FakeRootName: "office", + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/excluded-module.formatted-txt"), }, { name: "module with excluded config false", inFiles: []string{filepath.Join(datapath, "", "openconfig-config-false.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.UncompressedExcludeDerivedState, - GenerateFakeRoot: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.UncompressedExcludeDerivedState, + GenerateFakeRoot: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "openconfig-config-false-uncompressed.formatted-txt"), }, { name: "module with excluded config false - with compression", inFiles: []string{filepath.Join(datapath, "", "openconfig-config-false.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - CompressBehaviour: genutil.ExcludeDerivedState, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + CompressBehaviour: genutil.ExcludeDerivedState, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "openconfig-config-false-compressed.formatted-txt"), }, { name: "module with getters, delete and append methods", inFiles: []string{filepath.Join(datapath, "", "openconfig-list-enum-key.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateAppendMethod: true, + GenerateGetters: true, + GenerateDeleteMethod: true, + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateAppendMethod: true, - GenerateGetters: true, - GenerateDeleteMethod: true, - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "openconfig-list-enum-key.getters-append.formatted-txt"), }, { name: "module with excluded state, with RO list, path compression on", inFiles: []string{filepath.Join(datapath, "", "exclude-state-ro-list.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - CompressBehaviour: genutil.ExcludeDerivedState, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + CompressBehaviour: genutil.ExcludeDerivedState, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "exclude-state-ro-list.formatted-txt"), }, { name: "different union enumeration types", inFiles: []string{filepath.Join(datapath, "", "enum-union.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + GenerateLeafGetters: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - GenerateLeafGetters: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-union.formatted-txt"), }, { name: "different union enumeration types with consistent naming for union-inlined enums", inFiles: []string{filepath.Join(datapath, "", "enum-union.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + GenerateLeafGetters: true, + AppendEnumSuffixForSimpleUnionEnums: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - GenerateLeafGetters: true, - AppendEnumSuffixForSimpleUnionEnums: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-union.consistent.formatted-txt"), }, { name: "different union enumeration types with default enum values", inFiles: []string{filepath.Join(datapath, "", "enum-union-with-enum-defaults.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + GenerateLeafGetters: true, + GeneratePopulateDefault: true, + AppendEnumSuffixForSimpleUnionEnums: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - GenerateLeafGetters: true, - GeneratePopulateDefault: true, - AppendEnumSuffixForSimpleUnionEnums: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-union-with-enum-defaults.formatted-txt"), }, { name: "different union enumeration types with default enum values (wrapper union)", inFiles: []string{filepath.Join(datapath, "", "enum-union-with-enum-defaults.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateLeafGetters: true, + GeneratePopulateDefault: true, + AppendEnumSuffixForSimpleUnionEnums: true, }, - }, - inGoOptions: GoOpts{ - GenerateLeafGetters: true, - GeneratePopulateDefault: true, - AppendEnumSuffixForSimpleUnionEnums: true, }, wantErrSubstring: "default value not supported for wrapper union values, please generate using simplified union leaves", }, { name: "enumeration behaviour - resolution across submodules and grouping re-use within union", inFiles: []string{filepath.Join(datapath, "", "enum-module.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + GenerateLeafGetters: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - GenerateLeafGetters: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-module.formatted-txt"), }, { name: "enumeration behaviour (wrapper unions) - resolution across submodules and grouping re-use within union", inFiles: []string{filepath.Join(datapath, "", "enum-module.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateLeafGetters: true, }, - }, - inGoOptions: GoOpts{ - GenerateLeafGetters: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-module.wrapper-unions.formatted-txt"), }, { name: "enumeration behaviour - resolution across submodules and grouping re-use within union, with enumeration leaf names not shortened", inFiles: []string{filepath.Join(datapath, "", "enum-module.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-module.long-enum-names.formatted-txt"), }, { name: "enumeration behaviour - resolution across submodules and grouping re-use within union, with typedef enum names being prefixed by the module of their use/residence rather than of their definition", inFiles: []string{filepath.Join(datapath, "", "enum-module.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-module.residing-module-typedef-enum-name.formatted-txt"), }, { name: "enumeration behaviour - resolution across submodules and grouping re-use within union, with typedef enum names being prefixed by the module of their use/residence rather than of their definition, and enumeration leaf names not shortened", inFiles: []string{filepath.Join(datapath, "", "enum-module.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-module.long-enum-names.residing-module-typedef-enum-name.formatted-txt"), }, { name: "enumeration behaviour - resolution across submodules and grouping re-use within union, with typedef enum names being prefixed by the module of their use/residence rather than of their definition, and enumeration leaf names not shortened", inFiles: []string{filepath.Join(datapath, "", "enum-module.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + EnumerationsUseUnderscores: true, + }, }, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-module.long-enum-names.residing-module-typedef-enum-name.wrapper-unions.formatted-txt"), @@ -699,167 +777,188 @@ func TestSimpleStructs(t *testing.T) { name: "enumeration behaviour - multiple enumerations within a union", inFiles: []string{filepath.Join(datapath, "", "enum-multi-module.yang")}, inIncludePaths: []string{filepath.Join(datapath, "modules")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateJSONSchema: true, + GenerateSimpleUnions: true, }, - GenerateJSONSchema: true, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-multi-module.formatted-txt"), }, { name: "module with leaf getters", inFiles: []string{filepath.Join(datapath, "", "openconfig-list-enum-key.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - CompressBehaviour: genutil.PreferIntendedConfig, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + CompressBehaviour: genutil.PreferIntendedConfig, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateLeafGetters: true, + GeneratePopulateDefault: true, + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateLeafGetters: true, - GeneratePopulateDefault: true, - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "openconfig-list-enum-key.leaf-getters.formatted-txt"), }, { name: "uncompressed module with two different enums", inFiles: []string{filepath.Join(datapath, "", "enum-list-uncompressed.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-list-uncompressed.formatted-txt"), }, { name: "uncompressed module with two different enums (wrapper unions)", inFiles: []string{filepath.Join(datapath, "", "enum-list-uncompressed.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + EnumerationsUseUnderscores: true, + }, }, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-list-uncompressed.wrapper-unions.formatted-txt"), }, { name: "with model data", inFiles: []string{filepath.Join(datapath, "", "openconfig-versioned-mod.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - CompressBehaviour: genutil.PreferIntendedConfig, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + CompressBehaviour: genutil.PreferIntendedConfig, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + IncludeModelData: true, + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - IncludeModelData: true, - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "openconfig-versioned-mod.formatted-txt"), }, { name: "model with deduplicated enums", inFiles: []string{filepath.Join(datapath, "enum-duplication.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-duplication-dedup.formatted-txt"), }, { name: "model with enums that are in the same grouping duplicated", inFiles: []string{filepath.Join(datapath, "enum-duplication.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + EnumerationsUseUnderscores: true, + SkipEnumDeduplication: true, + }, + ParseOptions: ygen.ParseOpts{}, }, - ParseOptions: ygen.ParseOpts{ - SkipEnumDeduplication: true, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, }, }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata", "structs", "enum-duplication-dup.formatted-txt"), }, { name: "OpenConfig schema test - list with binary key", inFiles: []string{filepath.Join(datapath, "openconfig-binary-list.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateRenameMethod: true, + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateRenameMethod: true, - GenerateSimpleUnions: true, }, wantErrSubstring: "has a binary key", }, { name: "OpenConfig schema test - multi-keyed list with binary key", inFiles: []string{filepath.Join(datapath, "openconfig-binary-multi-list.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateRenameMethod: true, + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateRenameMethod: true, - GenerateSimpleUnions: true, }, wantErrSubstring: "has a binary key", }, { name: "OpenConfig schema test - list with union key containing binary", inFiles: []string{filepath.Join(datapath, "openconfig-union-binary-list.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - ShortenEnumLeafNames: true, - UseDefiningModuleForTypedefEnumNames: true, - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateRenameMethod: true, + GenerateSimpleUnions: true, }, - }, - inGoOptions: GoOpts{ - GenerateRenameMethod: true, - GenerateSimpleUnions: true, }, wantErrSubstring: "has a union key containing a binary", }, { name: "module with presence containers", inFiles: []string{filepath.Join(datapath, "presence-container-example.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - FakeRootName: "device", - EnumerationsUseUnderscores: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + FakeRootName: "device", + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateSimpleUnions: true, + GenerateLeafGetters: true, + GeneratePopulateDefault: true, + AddYangPresence: true, }, - }, - inGoOptions: GoOpts{ - GenerateSimpleUnions: true, - GenerateLeafGetters: true, - GeneratePopulateDefault: true, - AddYangPresence: true, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/presence-container-example.formatted-txt"), }} @@ -873,10 +972,9 @@ func TestSimpleStructs(t *testing.T) { // the unit tests are called by external test entities. tt.inConfig.Caller = "codegen-tests" } - tt.inConfig.StoreRawSchema = true - tt.inConfig.ParseOptions.ExcludeModules = tt.inExcludeModules + tt.inConfig.IROptions.ParseOptions.ExcludeModules = tt.inExcludeModules - cg := NewCodeGenerator(&tt.inConfig, &tt.inGoOptions) + cg := New(tt.inConfig.Caller, tt.inConfig.IROptions, tt.inConfig.GoOptions) gotGeneratedCode, errs := cg.Generate(tt.inFiles, tt.inIncludePaths) var err error @@ -907,7 +1005,7 @@ func TestSimpleStructs(t *testing.T) { fmt.Fprint(&gotCode, gotGeneratedCode.EnumMap) var gotJSON map[string]interface{} - if tt.inConfig.GenerateJSONSchema { + if tt.inConfig.GoOptions.GenerateJSONSchema { // Write the schema byte array out. fmt.Fprint(&gotCode, gotGeneratedCode.JSONSchemaCode) fmt.Fprint(&gotCode, gotGeneratedCode.EnumTypeMap) diff --git a/gogen/genir_test.go b/gogen/genir_test.go index 527644c98..8a27edd84 100644 --- a/gogen/genir_test.go +++ b/gogen/genir_test.go @@ -1447,6 +1447,28 @@ func TestGenerateIR(t *testing.T) { ShadowMappedPaths: [][]string{{"state", "iref"}}, ShadowMappedPathModules: [][]string{{"openconfig-complex", "openconfig-complex"}}, }, + "iref2": { + Name: "Iref2", + YANGDetails: ygen.YANGNodeDetails{ + Name: "iref2", + BelongingModule: "openconfig-complex", + RootElementModule: "openconfig-complex", + DefiningModule: "openconfig-complex", + Path: "/openconfig-complex/model/a/single-key/config/iref2", + SchemaPath: "/model/a/single-key/config/iref2", + ShadowSchemaPath: "/model/a/single-key/state/iref2", + }, + Type: ygen.LeafNode, + LangType: &ygen.MappedType{ + NativeType: "E_Complex_Program", + IsEnumeratedValue: true, + ZeroValue: "0", + }, + MappedPaths: [][]string{{"config", "iref2"}}, + MappedPathModules: [][]string{{"openconfig-complex", "openconfig-complex"}}, + ShadowMappedPaths: [][]string{{"state", "iref2"}}, + ShadowMappedPathModules: [][]string{{"openconfig-complex", "openconfig-complex"}}, + }, "key": { Name: "Key", YANGDetails: ygen.YANGNodeDetails{ @@ -1795,6 +1817,15 @@ func TestGenerateIR(t *testing.T) { {Name: "OS", DefiningModule: "openconfig-complex"}, }, }, + "/openconfig-complex/program": { + Name: "Complex_Program", + Kind: ygen.IdentityType, + IdentityBaseName: "SOFTWARE", + TypeName: "program", + ValToYANGDetails: []ygot.EnumDefinition{ + {Name: "OS", DefiningModule: "openconfig-complex"}, + }, + }, "/openconfig-complex/multi-key-config/key2": { Name: "MultiKey_Key2", Kind: ygen.SimpleEnumerationType, diff --git a/gogen/goelements.go b/gogen/goelements.go index ebdcae0a7..9ecfb6def 100644 --- a/gogen/goelements.go +++ b/gogen/goelements.go @@ -255,12 +255,12 @@ func (s *GoLangMapper) FieldName(e *yang.Entry) (string, error) { // LeafType maps the input leaf entry to a MappedType object containing the // type information about the field. func (s *GoLangMapper) LeafType(e *yang.Entry, opts ygen.IROptions) (*ygen.MappedType, error) { - mtype, err := s.yangTypeToGoType(resolveTypeArgs{yangType: e.Type, contextEntry: e}, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), opts.ParseOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, opts.TransformationOptions.UseDefiningModuleForTypedefEnumNames, opts.TransformationOptions.EnumOrgPrefixesToTrim) + mtype, err := s.yangTypeToGoType(resolveTypeArgs{yangType: e.Type, contextEntry: e}, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), opts.TransformationOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, opts.TransformationOptions.UseDefiningModuleForTypedefEnumNames, opts.TransformationOptions.EnumOrgPrefixesToTrim) if err != nil { return nil, err } - defaultValue, err := generateGoDefaultValue(e, mtype, s, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), opts.ParseOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, opts.TransformationOptions.UseDefiningModuleForTypedefEnumNames, opts.TransformationOptions.EnumOrgPrefixesToTrim, s.simpleUnions) + defaultValue, err := generateGoDefaultValue(e, mtype, s, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), opts.TransformationOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, opts.TransformationOptions.UseDefiningModuleForTypedefEnumNames, opts.TransformationOptions.EnumOrgPrefixesToTrim, s.simpleUnions) if err != nil { return nil, err } @@ -272,7 +272,7 @@ func (s *GoLangMapper) LeafType(e *yang.Entry, opts ygen.IROptions) (*ygen.Mappe // LeafType maps the input list key entry to a MappedType object containing the // type information about the key field. func (s *GoLangMapper) KeyLeafType(e *yang.Entry, opts ygen.IROptions) (*ygen.MappedType, error) { - return s.yangTypeToGoType(resolveTypeArgs{yangType: e.Type, contextEntry: e}, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), opts.ParseOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, opts.TransformationOptions.UseDefiningModuleForTypedefEnumNames, opts.TransformationOptions.EnumOrgPrefixesToTrim) + return s.yangTypeToGoType(resolveTypeArgs{yangType: e.Type, contextEntry: e}, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), opts.TransformationOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, opts.TransformationOptions.UseDefiningModuleForTypedefEnumNames, opts.TransformationOptions.EnumOrgPrefixesToTrim) } // PackageName is not used by Go generation. diff --git a/gogen/gogen.go b/gogen/gogen.go index 36cbd14e9..1066e2977 100644 --- a/gogen/gogen.go +++ b/gogen/gogen.go @@ -1189,12 +1189,12 @@ func (t *{{ .ParentReceiver }}) To_{{ .Name }}(i interface{}) ({{ .Name }}, erro // be included in only one file of the package. func writeGoHeader(yangFiles, includePaths []string, cfg *CodeGenerator, rootName string, modelData []*gpb.ModelData) (string, string, error) { // Determine the running binary's name. - if cfg.Config.Caller == "" { - cfg.Config.Caller = genutil.CallerName() + if cfg.Caller == "" { + cfg.Caller = genutil.CallerName() } - if cfg.Config.PackageName == "" { - cfg.Config.PackageName = defaultPackageName + if cfg.GoOptions.PackageName == "" { + cfg.GoOptions.PackageName = defaultPackageName } if cfg.GoOptions.YgotImportPath == "" { @@ -1225,12 +1225,12 @@ func writeGoHeader(yangFiles, includePaths []string, cfg *CodeGenerator, rootNam FakeRootName string // FakeRootName is the name of the fake root struct in the YANG type ModelData []*gpb.ModelData // ModelData contains the gNMI ModelData definition for the input types. }{ - PackageName: cfg.Config.PackageName, + PackageName: cfg.GoOptions.PackageName, YANGFiles: yangFiles, IncludePaths: includePaths, - CompressEnabled: cfg.Config.TransformationOptions.CompressBehaviour.CompressEnabled(), - GeneratingBinary: cfg.Config.Caller, - GenerateSchema: cfg.Config.GenerateJSONSchema, + CompressEnabled: cfg.IROptions.TransformationOptions.CompressBehaviour.CompressEnabled(), + GeneratingBinary: cfg.Caller, + GenerateSchema: cfg.GoOptions.GenerateJSONSchema, GoOptions: cfg.GoOptions, BinaryTypeName: ygot.BinaryTypeName, EmptyTypeName: ygot.EmptyTypeName, @@ -1238,7 +1238,7 @@ func writeGoHeader(yangFiles, includePaths []string, cfg *CodeGenerator, rootNam } s.FakeRootName = "nil" - if cfg.Config.TransformationOptions.GenerateFakeRoot && rootName != "" { + if cfg.IROptions.TransformationOptions.GenerateFakeRoot && rootName != "" { s.FakeRootName = fmt.Sprintf("&%s{}", rootName) } @@ -1281,16 +1281,11 @@ func IsScalarField(field *ygen.NodeDetails) bool { // child container's struct name). // // writeGoStruct takes the following additional arguments: -// - state - the current generator state, as a genState pointer. -// - compressOCPaths - a bool indicating whether OpenConfig path compression is enabled for -// this schema. -// - ignoreShadowSchemaPaths - a bool indicating that when OpenConfig path compression is -// enabled, the shadowed paths are ignored while unmarshalling. -// - generateJSONSchema - a bool indicating whether the generated code should include the -// JSON representation of the YANG schema for this element. +// - targetStruct - the YANG directory (container/list) to be converted to generated code. +// - goStructElements - All existing YANG directories (for looking up children). +// - generatedUnions - Running map of generated unions to avoid generating the +// same union twice. // - goOpts - Go specific code generation options as a GoOpts struct. -// - skipEnumDedup -- a boolean that indicates whether leaves of type enumeration that are -// used in multiple places in the schema tree should share a common underlying type. // // writeGoStruct returns a GoStructCodeSnippet which contains // 1. The generated struct for targetStruct (structDef) @@ -1298,7 +1293,7 @@ func IsScalarField(field *ygen.NodeDetails) bool { // of targetStruct (listKeys). // 3. Methods with the struct corresponding to targetStruct as a receiver, e.g., for each // list a NewListMember() method is generated. -func writeGoStruct(targetStruct *ygen.ParsedDirectory, goStructElements map[string]*ygen.ParsedDirectory, generatedUnions map[string]bool, ignoreShadowSchemaPaths bool, goOpts GoOpts, generateJSONSchema bool) (GoStructCodeSnippet, []error) { +func writeGoStruct(targetStruct *ygen.ParsedDirectory, goStructElements map[string]*ygen.ParsedDirectory, generatedUnions map[string]bool, goOpts GoOpts) (GoStructCodeSnippet, []error) { if targetStruct == nil { return GoStructCodeSnippet{}, []error{fmt.Errorf("cannot create code for nil targetStruct")} } @@ -1547,7 +1542,7 @@ func writeGoStruct(targetStruct *ygen.ParsedDirectory, goStructElements map[stri tagBuf.WriteString(` module:"`) addSchemaPathsToBuffers(field.MappedPathModules, false) - if ignoreShadowSchemaPaths { + if goOpts.IgnoreShadowSchemaPaths { if len(field.ShadowMappedPaths) > 0 { tagBuf.WriteString(` shadow-path:"`) addSchemaPathsToBuffers(field.ShadowMappedPaths, false) @@ -1687,7 +1682,7 @@ func writeGoStruct(targetStruct *ygen.ParsedDirectory, goStructElements map[stri } } - if generateJSONSchema { + if goOpts.GenerateJSONSchema { if err := generateValidator(&methodBuf, structDef, goOpts.ValidateFunctionName); err != nil { errs = append(errs, err) } diff --git a/gogen/gogen_test.go b/gogen/gogen_test.go index 5a60f32d5..3021ec8a3 100644 --- a/gogen/gogen_test.go +++ b/gogen/gogen_test.go @@ -102,6 +102,7 @@ func TestGoCodeStructGeneration(t *testing.T) { BelongingModule: "exmod", }, inGoOpts: GoOpts{ + GenerateJSONSchema: true, ValidateFunctionName: "ValidateProxyFunction", }, want: wantGoStructOut{ @@ -195,7 +196,10 @@ func (*Tstruct) ΛBelongingModule() string { Path: "/root-module/tstruct", BelongingModule: "exmod", }, - inIgnoreShadowSchemaPaths: true, + inGoOpts: GoOpts{ + GenerateJSONSchema: true, + IgnoreShadowSchemaPaths: true, + }, want: wantGoStructOut{ structs: ` // Tstruct represents the /root-module/tstruct YANG schema element. @@ -267,6 +271,9 @@ func (*Tstruct) ΛBelongingModule() string { Path: "/module/input-struct", BelongingModule: "exmod", }, + inGoOpts: GoOpts{ + GenerateJSONSchema: true, + }, want: wantGoStructOut{ structs: ` // InputStruct represents the /module/input-struct YANG schema element. @@ -373,6 +380,9 @@ func (t *InputStruct) To_InputStruct_U1_Union(i interface{}) (InputStruct_U1_Uni BelongingModule: "exmod", }, }, + inGoOpts: GoOpts{ + GenerateJSONSchema: true, + }, want: wantGoStructOut{ structs: ` // InputStruct represents the /root-module/input-struct YANG schema element. @@ -440,7 +450,8 @@ func (*InputStruct) ΛBelongingModule() string { }, }, inGoOpts: GoOpts{ - AddYangPresence: true, + GenerateJSONSchema: true, + AddYangPresence: true, }, want: wantGoStructOut{ structs: ` @@ -557,6 +568,9 @@ func (*InputStruct) ΛBelongingModule() string { BelongingModule: "exmod", }, }, + inGoOpts: GoOpts{ + GenerateJSONSchema: true, + }, want: wantGoStructOut{ structs: ` // QStruct represents the /root-module/q-struct YANG schema element. @@ -657,6 +671,7 @@ func (*QStruct) ΛBelongingModule() string { }, }, inGoOpts: GoOpts{ + GenerateJSONSchema: true, GenerateRenameMethod: true, }, want: wantGoStructOut{ @@ -898,6 +913,7 @@ func (*Tstruct) ΛBelongingModule() string { }, }, inGoOpts: GoOpts{ + GenerateJSONSchema: true, GenerateRenameMethod: true, }, want: wantGoStructOut{ @@ -1023,6 +1039,7 @@ func (*Tstruct) ΛBelongingModule() string { BelongingModule: "exmod", }, inGoOpts: GoOpts{ + GenerateJSONSchema: true, AddAnnotationFields: true, AnnotationPrefix: "Ω", }, @@ -1156,6 +1173,7 @@ func (*Tstruct) ΛBelongingModule() string { }, }, inGoOpts: GoOpts{ + GenerateJSONSchema: true, GenerateAppendMethod: true, GenerateGetters: true, GenerateDeleteMethod: true, @@ -1385,6 +1403,7 @@ func (*Tstruct) ΛBelongingModule() string { }, }, inGoOpts: GoOpts{ + GenerateJSONSchema: true, GenerateAppendMethod: true, GenerateGetters: true, GenerateDeleteMethod: true, @@ -1567,6 +1586,7 @@ func (*Tstruct) ΛBelongingModule() string { }, }, inGoOpts: GoOpts{ + GenerateJSONSchema: true, GenerateGetters: true, GeneratePopulateDefault: true, }, @@ -1665,6 +1685,7 @@ func (*InputStruct) ΛBelongingModule() string { BelongingModule: "m1", }, inGoOpts: GoOpts{ + GenerateJSONSchema: true, GenerateLeafGetters: true, GeneratePopulateDefault: true, }, @@ -1758,6 +1779,7 @@ func (*Container) ΛBelongingModule() string { BelongingModule: "m1", }, inGoOpts: GoOpts{ + GenerateJSONSchema: true, GenerateLeafGetters: true, GeneratePopulateDefault: true, }, @@ -1834,7 +1856,7 @@ func (*Container) ΛBelongingModule() string { tt.inOtherStructMap[tt.inStructToMap.Path] = tt.inStructToMap // Always generate the JSON schema for this test. generatedUnions := map[string]bool{} - got, errs := writeGoStruct(tt.inStructToMap, tt.inOtherStructMap, generatedUnions, tt.inIgnoreShadowSchemaPaths, tt.inGoOpts, true) + got, errs := writeGoStruct(tt.inStructToMap, tt.inOtherStructMap, generatedUnions, tt.inGoOpts) if len(errs) != 0 && !tt.want.wantErr { t.Fatalf("%s writeGoStruct(targetStruct: %v): received unexpected errors: %v", diff --git a/integration_tests/generate_errs_test.go b/integration_tests/generate_errs_test.go index 6baeea038..fd90a587d 100644 --- a/integration_tests/generate_errs_test.go +++ b/integration_tests/generate_errs_test.go @@ -15,7 +15,7 @@ func TestGenerateErrs(t *testing.T) { name string inFiles []string inPath []string - inConfig ygen.GeneratorConfig + inIROptions ygen.IROptions wantGoOK bool wantGoErrSubstring string wantProtoOK bool @@ -45,7 +45,7 @@ func TestGenerateErrs(t *testing.T) { }} for _, tt := range tests { - gcg := gogen.NewCodeGenerator(&tt.inConfig, nil) + gcg := gogen.New("", tt.inIROptions, gogen.GoOpts{}) _, goErr := gcg.Generate(tt.inFiles, tt.inPath) switch { @@ -58,7 +58,7 @@ func TestGenerateErrs(t *testing.T) { } } - pcg := protogen.New(&tt.inConfig, nil) + pcg := protogen.New("", tt.inIROptions, protogen.ProtoOpts{}) if tt.wantSameErrSubstring { tt.wantProtoErrSubstring = tt.wantGoErrSubstring diff --git a/proto_generator/protogenerator.go b/proto_generator/protogenerator.go index e3eb4784a..687542da5 100644 --- a/proto_generator/protogenerator.go +++ b/proto_generator/protogenerator.go @@ -101,23 +101,24 @@ func main() { } // Perform the code generation. - cg := protogen.New(&ygen.GeneratorConfig{ - ParseOptions: ygen.ParseOpts{ - ExcludeModules: modsExcluded, - SkipEnumDeduplication: *skipEnumDedup, - YANGParseOptions: yang.Options{ - IgnoreSubmoduleCircularDependencies: *ignoreCircDeps, + cg := protogen.New( + *callerName, + ygen.IROptions{ + ParseOptions: ygen.ParseOpts{ + ExcludeModules: modsExcluded, + YANGParseOptions: yang.Options{ + IgnoreSubmoduleCircularDependencies: *ignoreCircDeps, + }, + }, + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: compressBehaviour, + GenerateFakeRoot: *generateFakeRoot, + FakeRootName: *fakeRootName, + SkipEnumDeduplication: *skipEnumDedup, }, }, - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: compressBehaviour, - GenerateFakeRoot: *generateFakeRoot, - FakeRootName: *fakeRootName, - }, - PackageName: *packageName, - Caller: *callerName, - }, - &protogen.ProtoOpts{ + protogen.ProtoOpts{ + PackageName: *packageName, BaseImportPath: *baseImportPath, YwrapperPath: *ywrapperPath, YextPath: *yextPath, diff --git a/protogen/codegen.go b/protogen/codegen.go index bb21c1f6e..0f2310702 100644 --- a/protogen/codegen.go +++ b/protogen/codegen.go @@ -12,14 +12,21 @@ import ( // CodeGenerator is a structure that is used to pass arguments as to // how the output protobuf code should be generated. type CodeGenerator struct { - // Config stores the configuration parameters used for code generation. - Config ygen.GeneratorConfig - // ProtoOptions stores a struct which contains Protobuf specific options. + // Caller is the name of the binary calling the generator library, it is + // included in the header of output files for debugging purposes. If a + // string is not specified, the location of the library is utilised. + Caller string + // IROptions stores the configuration parameters used for IR generation. + IROptions ygen.IROptions + // ProtoOptions stores a struct which contains Protobuf specific + // options for code generation post IR generation. ProtoOptions ProtoOpts } // ProtoOpts stores Protobuf specific options for the code generation library. type ProtoOpts struct { + // PackageName is the name that should be used for the generating package. + PackageName string // BaseImportPath stores the root URL or path for imports that are // relative within the imported protobufs. BaseImportPath string @@ -58,19 +65,14 @@ type ProtoOpts struct { GoPackageBase string } -// New returns a new instance of the protobuf code generator +// New returns a new instance of the CodeGenerator // struct to the calling function. -func New(c *ygen.GeneratorConfig, protoopts *ProtoOpts) *CodeGenerator { - cg := &CodeGenerator{} - - if c != nil { - cg.Config = *c - } - if protoopts != nil { - cg.ProtoOptions = *protoopts +func New(callerName string, opts ygen.IROptions, protoOpts ProtoOpts) *CodeGenerator { + return &CodeGenerator{ + Caller: callerName, + IROptions: opts, + ProtoOptions: protoOpts, } - - return cg } // GeneratedCode stores a set of generated Protobuf packages. @@ -97,7 +99,7 @@ type Proto3Package struct { // It returns a GeneratedCode struct containing the messages that are to be // output, along with any associated values (e.g., enumerations). func (cg *CodeGenerator) Generate(yangFiles, includePaths []string) (*GeneratedCode, util.Errors) { - basePackageName := cg.Config.PackageName + basePackageName := cg.ProtoOptions.PackageName if basePackageName == "" { basePackageName = DefaultBasePackageName } @@ -115,10 +117,10 @@ func (cg *CodeGenerator) Generate(yangFiles, includePaths []string) (*GeneratedC } // This flag is always true for proto generation. - cg.Config.TransformationOptions.UseDefiningModuleForTypedefEnumNames = true + cg.IROptions.TransformationOptions.UseDefiningModuleForTypedefEnumNames = true opts := ygen.IROptions{ - ParseOptions: cg.Config.ParseOptions, - TransformationOptions: cg.Config.TransformationOptions, + ParseOptions: cg.IROptions.ParseOptions, + TransformationOptions: cg.IROptions.TransformationOptions, NestedDirectories: cg.ProtoOptions.NestedMessages, AbsoluteMapPaths: true, AppendEnumSuffixForSimpleUnionEnums: true, @@ -164,7 +166,7 @@ func (cg *CodeGenerator) Generate(yangFiles, includePaths []string) (*GeneratedC m := ir.Directories[directoryPath] genMsg, errs := writeProto3Msg(m, ir, &protoMsgConfig{ - compressPaths: cg.Config.TransformationOptions.CompressBehaviour.CompressEnabled(), + compressPaths: cg.IROptions.TransformationOptions.CompressBehaviour.CompressEnabled(), basePackageName: basePackageName, enumPackageName: enumPackageName, baseImportPath: cg.ProtoOptions.BaseImportPath, @@ -235,8 +237,8 @@ func (cg *CodeGenerator) Generate(yangFiles, includePaths []string) (*GeneratedC Imports: stringKeys(pkgImports[n]), SourceYANGFiles: yangFiles, SourceYANGIncludePaths: includePaths, - CompressPaths: cg.Config.TransformationOptions.CompressBehaviour.CompressEnabled(), - CallerName: cg.Config.Caller, + CompressPaths: cg.IROptions.TransformationOptions.CompressBehaviour.CompressEnabled(), + CallerName: cg.Caller, YwrapperPath: ywrapperPath, YextPath: yextPath, GoPackageName: gpn, diff --git a/protogen/codegen_test.go b/protogen/codegen_test.go index f6ddc0d6b..ce003b462 100644 --- a/protogen/codegen_test.go +++ b/protogen/codegen_test.go @@ -28,8 +28,7 @@ func TestGenerateProto3(t *testing.T) { name string inFiles []string inIncludePaths []string - inConfig ygen.GeneratorConfig - inProtoOpts ProtoOpts + inConfig CodeGenerator // wantOutputFiles is a map keyed on protobuf package name with a path // to the file that is expected for each package. wantOutputFiles map[string]string @@ -37,9 +36,11 @@ func TestGenerateProto3(t *testing.T) { }{{ name: "simple protobuf test with compression", inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-a.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + }, }, }, wantOutputFiles: map[string]string{ @@ -57,36 +58,46 @@ func TestGenerateProto3(t *testing.T) { }, { name: "enumeration under unions test with compression", inFiles: []string{filepath.Join(datapath, "enum-union.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - GenerateFakeRoot: true, - UseDefiningModuleForTypedefEnumNames: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + GenerateFakeRoot: true, + UseDefiningModuleForTypedefEnumNames: true, + }, + }, + ProtoOptions: ProtoOpts{ + AnnotateEnumNames: true, + NestedMessages: true, + GoPackageBase: "github.com/foo/bar", }, - }, - inProtoOpts: ProtoOpts{ - AnnotateEnumNames: true, - NestedMessages: true, - GoPackageBase: "github.com/foo/bar", }, wantOutputFiles: map[string]string{ "openconfig": filepath.Join(TestRoot, "testdata", "proto", "enum-union.compress.formatted-txt"), "openconfig.enums": filepath.Join(TestRoot, "testdata", "proto", "enum-union.compress.enums.formatted-txt"), }, }, { - name: "yang schema with a list", - inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-b.yang")}, - inConfig: ygen.GeneratorConfig{TransformationOptions: ygen.TransformationOpts{CompressBehaviour: genutil.PreferIntendedConfig}}, + name: "yang schema with a list", + inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-b.yang")}, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + }, + }, + }, wantOutputFiles: map[string]string{ "openconfig": filepath.Join(TestRoot, "testdata", "proto", "proto-test-b.compress.formatted-txt"), "openconfig.device": filepath.Join(TestRoot, "testdata", "proto", "proto-test-b.compress.device.formatted-txt"), }, }, { - name: "yang schema with simple enumerations", - inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-c.yang")}, - inConfig: ygen.GeneratorConfig{}, - inProtoOpts: ProtoOpts{ - GoPackageBase: "github.com/foo/baz", + name: "yang schema with simple enumerations", + inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-c.yang")}, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{}, + ProtoOptions: ProtoOpts{ + GoPackageBase: "github.com/foo/baz", + }, }, wantOutputFiles: map[string]string{ "openconfig.proto_test_c": filepath.Join(TestRoot, "testdata", "proto", "proto-test-c.proto-test-c.formatted-txt"), @@ -106,9 +117,11 @@ func TestGenerateProto3(t *testing.T) { }, { name: "yang schema with unions", inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-e.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - UseDefiningModuleForTypedefEnumNames: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + UseDefiningModuleForTypedefEnumNames: true, + }, }, }, wantOutputFiles: map[string]string{ @@ -129,11 +142,13 @@ func TestGenerateProto3(t *testing.T) { "openconfig.proto_anydata_test.e": filepath.Join(TestRoot, "testdata", "proto", "proto_anydata_test.e.formatted-txt"), }, }, { - name: "yang schema with path annotations", - inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-f.yang")}, - inConfig: ygen.GeneratorConfig{}, - inProtoOpts: ProtoOpts{ - AnnotateSchemaPaths: true, + name: "yang schema with path annotations", + inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-f.yang")}, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{}, + ProtoOptions: ProtoOpts{ + AnnotateSchemaPaths: true, + }, }, wantOutputFiles: map[string]string{ "openconfig.proto_test_f": filepath.Join(TestRoot, "testdata", "proto", "proto_test_f.uncompressed.proto_test_f.formatted-txt"), @@ -141,12 +156,14 @@ func TestGenerateProto3(t *testing.T) { "openconfig.proto_test_f.a.c": filepath.Join(TestRoot, "testdata", "proto", "proto_test_f.uncompressed.proto_test_f.a.c.formatted-txt"), }, }, { - name: "yang schema with leafrefs that point to the same path", - inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-g.yang")}, - inConfig: ygen.GeneratorConfig{}, - inProtoOpts: ProtoOpts{ - GoPackageBase: "github.com/foo/baz", - NestedMessages: true, + name: "yang schema with leafrefs that point to the same path", + inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-test-g.yang")}, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{}, + ProtoOptions: ProtoOpts{ + GoPackageBase: "github.com/foo/baz", + NestedMessages: true, + }, }, wantOutputFiles: map[string]string{ "openconfig.proto_test_g": filepath.Join(TestRoot, "testdata", "proto", "proto-test-g.proto-test-g.formatted-txt"), @@ -154,14 +171,16 @@ func TestGenerateProto3(t *testing.T) { }, { name: "yang schema with fake root, path compression and union list key", inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-union-list-key.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - GenerateFakeRoot: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + GenerateFakeRoot: true, + }, + }, + ProtoOptions: ProtoOpts{ + AnnotateSchemaPaths: true, }, - }, - inProtoOpts: ProtoOpts{ - AnnotateSchemaPaths: true, }, wantOutputFiles: map[string]string{ "openconfig": filepath.Join(TestRoot, "testdata", "proto", "proto-union-list-key.compressed.openconfig.formatted-txt"), @@ -170,13 +189,15 @@ func TestGenerateProto3(t *testing.T) { }, { name: "yang schema with fakeroot, and union list key", inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-union-list-key.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + }, + }, + ProtoOptions: ProtoOpts{ + AnnotateSchemaPaths: true, }, - }, - inProtoOpts: ProtoOpts{ - AnnotateSchemaPaths: true, }, wantOutputFiles: map[string]string{ "openconfig": filepath.Join(TestRoot, "testdata", "proto", "proto-union-list_key.uncompressed.openconfig.formatted-txt"), @@ -189,9 +210,11 @@ func TestGenerateProto3(t *testing.T) { }, { name: "enums: yang schema with various types of enums with underscores", inFiles: []string{filepath.Join(TestRoot, "testdata", "proto", "proto-enums.yang")}, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - UseDefiningModuleForTypedefEnumNames: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + UseDefiningModuleForTypedefEnumNames: true, + }, }, }, wantOutputFiles: map[string]string{ @@ -204,13 +227,15 @@ func TestGenerateProto3(t *testing.T) { filepath.Join(TestRoot, "testdata", "proto", "proto-enums.yang"), filepath.Join(TestRoot, "testdata", "proto", "proto-enums-addid.yang"), }, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - UseDefiningModuleForTypedefEnumNames: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + UseDefiningModuleForTypedefEnumNames: true, + }, + }, + ProtoOptions: ProtoOpts{ + AnnotateEnumNames: true, }, - }, - inProtoOpts: ProtoOpts{ - AnnotateEnumNames: true, }, wantOutputFiles: map[string]string{ "openconfig.enums": filepath.Join(TestRoot, "testdata", "proto", "proto-enums-addid.enums.formatted-txt"), @@ -221,16 +246,18 @@ func TestGenerateProto3(t *testing.T) { inFiles: []string{ filepath.Join(TestRoot, "testdata", "proto", "nested-messages.yang"), }, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - UseDefiningModuleForTypedefEnumNames: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + UseDefiningModuleForTypedefEnumNames: true, + }, + }, + ProtoOptions: ProtoOpts{ + AnnotateEnumNames: true, + AnnotateSchemaPaths: true, + NestedMessages: true, }, - }, - inProtoOpts: ProtoOpts{ - AnnotateEnumNames: true, - AnnotateSchemaPaths: true, - NestedMessages: true, }, wantOutputFiles: map[string]string{ "openconfig": filepath.Join(TestRoot, "testdata", "proto", "nested-messages.openconfig.formatted-txt"), @@ -242,18 +269,19 @@ func TestGenerateProto3(t *testing.T) { inFiles: []string{ filepath.Join(TestRoot, "testdata", "proto", "nested-messages.yang"), }, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - CompressBehaviour: genutil.PreferIntendedConfig, - IgnoreShadowSchemaPaths: true, - GenerateFakeRoot: true, - UseDefiningModuleForTypedefEnumNames: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + GenerateFakeRoot: true, + UseDefiningModuleForTypedefEnumNames: true, + }, + }, + ProtoOptions: ProtoOpts{ + AnnotateEnumNames: true, + AnnotateSchemaPaths: true, + NestedMessages: true, }, - }, - inProtoOpts: ProtoOpts{ - AnnotateEnumNames: true, - AnnotateSchemaPaths: true, - NestedMessages: true, }, wantOutputFiles: map[string]string{ "openconfig.enums": filepath.Join(TestRoot, "testdata", "proto", "nested-messages.compressed.enums.formatted-txt"), @@ -264,16 +292,18 @@ func TestGenerateProto3(t *testing.T) { inFiles: []string{ filepath.Join(TestRoot, "testdata", "proto", "union-list-key.yang"), }, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - UseDefiningModuleForTypedefEnumNames: true, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + UseDefiningModuleForTypedefEnumNames: true, + }, + }, + ProtoOptions: ProtoOpts{ + AnnotateEnumNames: true, + AnnotateSchemaPaths: true, + NestedMessages: true, }, - }, - inProtoOpts: ProtoOpts{ - AnnotateEnumNames: true, - AnnotateSchemaPaths: true, - NestedMessages: true, }, wantOutputFiles: map[string]string{ "openconfig.enums": filepath.Join(TestRoot, "testdata", "proto", "union-list-key.enums.formatted-txt"), @@ -285,16 +315,18 @@ func TestGenerateProto3(t *testing.T) { inFiles: []string{ filepath.Join(datapath, "openconfig-config-false.yang"), }, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - CompressBehaviour: genutil.UncompressedExcludeDerivedState, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + CompressBehaviour: genutil.UncompressedExcludeDerivedState, + }, + }, + ProtoOptions: ProtoOpts{ + AnnotateEnumNames: true, + AnnotateSchemaPaths: true, + NestedMessages: true, }, - }, - inProtoOpts: ProtoOpts{ - AnnotateEnumNames: true, - AnnotateSchemaPaths: true, - NestedMessages: true, }, wantOutputFiles: map[string]string{ "openconfig": filepath.Join(TestRoot, "testdata", "proto", "excluded-config-false.compressed.formatted-txt"), @@ -305,17 +337,19 @@ func TestGenerateProto3(t *testing.T) { inFiles: []string{ filepath.Join(datapath, "openconfig-config-false.yang"), }, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - CompressBehaviour: genutil.ExcludeDerivedState, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + CompressBehaviour: genutil.ExcludeDerivedState, + }, + }, + ProtoOptions: ProtoOpts{ + AnnotateEnumNames: true, + AnnotateSchemaPaths: true, + NestedMessages: true, + GoPackageBase: "github.com/openconfig/a/package", }, - }, - inProtoOpts: ProtoOpts{ - AnnotateEnumNames: true, - AnnotateSchemaPaths: true, - NestedMessages: true, - GoPackageBase: "github.com/openconfig/a/package", }, wantOutputFiles: map[string]string{ "openconfig": filepath.Join(TestRoot, "testdata", "proto", "excluded-config-false.uncompressed.formatted-txt"), @@ -326,13 +360,15 @@ func TestGenerateProto3(t *testing.T) { filepath.Join(TestRoot, "testdata", "proto", "cross-ref-target.yang"), filepath.Join(TestRoot, "testdata", "proto", "cross-ref-src.yang"), }, - inConfig: ygen.GeneratorConfig{ - ParseOptions: ygen.ParseOpts{ - ExcludeModules: []string{"cross-ref-target"}, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + ParseOptions: ygen.ParseOpts{ + ExcludeModules: []string{"cross-ref-target"}, + }, + }, + ProtoOptions: ProtoOpts{ + NestedMessages: true, }, - }, - inProtoOpts: ProtoOpts{ - NestedMessages: true, }, wantOutputFiles: map[string]string{ "openconfig.cross_ref_src": filepath.Join(TestRoot, "testdata", "proto", "cross-ref-src.formatted-txt"), @@ -343,16 +379,18 @@ func TestGenerateProto3(t *testing.T) { filepath.Join(TestRoot, "testdata", "proto", "fakeroot-multimod-one.yang"), filepath.Join(TestRoot, "testdata", "proto", "fakeroot-multimod-two.yang"), }, - inConfig: ygen.GeneratorConfig{ - TransformationOptions: ygen.TransformationOpts{ - GenerateFakeRoot: true, - CompressBehaviour: genutil.PreferIntendedConfig, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + GenerateFakeRoot: true, + CompressBehaviour: genutil.PreferIntendedConfig, + }, + }, + ProtoOptions: ProtoOpts{ + NestedMessages: true, + AnnotateEnumNames: true, + AnnotateSchemaPaths: true, }, - }, - inProtoOpts: ProtoOpts{ - NestedMessages: true, - AnnotateEnumNames: true, - AnnotateSchemaPaths: true, }, wantOutputFiles: map[string]string{ "openconfig": filepath.Join(TestRoot, "testdata", "proto", "fakeroot-multimod.formatted-txt"), @@ -378,7 +416,7 @@ func TestGenerateProto3(t *testing.T) { tt.inConfig.Caller = "codegen-tests" } - cg := New(&tt.inConfig, &tt.inProtoOpts) + cg := New(tt.inConfig.Caller, tt.inConfig.IROptions, tt.inConfig.ProtoOptions) gotProto, err := cg.Generate(tt.inFiles, tt.inIncludePaths) if (err != nil) != tt.wantErr { t.Fatalf("cg.Generate(%v, %v), config: %v: got unexpected error: %v", tt.inFiles, tt.inIncludePaths, tt.inConfig, err) diff --git a/protogen/genir_test.go b/protogen/genir_test.go index f9bf71d3d..8a97a529e 100644 --- a/protogen/genir_test.go +++ b/protogen/genir_test.go @@ -308,6 +308,48 @@ func protoIR(nestedDirectories bool) *ygen.IR { }, }, }, + "iref2": { + Name: "iref2", + YANGDetails: ygen.YANGNodeDetails{ + Name: "iref2", + Defaults: nil, + BelongingModule: "openconfig-complex", + RootElementModule: "openconfig-complex", + DefiningModule: "openconfig-complex", + Path: "/openconfig-complex/model/a/single-key/config/iref2", + SchemaPath: "/model/a/single-key/config/iref2", + ShadowSchemaPath: "/model/a/single-key/state/iref2", + LeafrefTargetPath: "", + Description: "", + }, + Type: ygen.LeafNode, + LangType: &ygen.MappedType{ + NativeType: "openconfig.enums.ComplexProgram", + UnionTypes: nil, + IsEnumeratedValue: true, + EnumeratedYANGTypeKey: "/openconfig-complex/program", + ZeroValue: "", + DefaultValue: nil, + }, + MappedPaths: [][]string{ + {"", "model", "a", "single-key", "config", "iref2"}, + }, + MappedPathModules: [][]string{ + { + "", "openconfig-complex", "openconfig-complex", "openconfig-complex", + "openconfig-complex", "openconfig-complex", + }, + }, + ShadowMappedPaths: [][]string{ + {"", "model", "a", "single-key", "state", "iref2"}, + }, + ShadowMappedPathModules: [][]string{ + { + "", "openconfig-complex", "openconfig-complex", "openconfig-complex", + "openconfig-complex", "openconfig-complex", + }, + }, + }, "key": { Name: "key", YANGDetails: ygen.YANGNodeDetails{ @@ -830,6 +872,15 @@ func protoIR(nestedDirectories bool) *ygen.IR { {Name: "OS", DefiningModule: "openconfig-complex"}, }, }, + "/openconfig-complex/program": { + Name: "ComplexProgram", + Kind: ygen.IdentityType, + IdentityBaseName: "SOFTWARE", + TypeName: "program", + ValToYANGDetails: []ygot.EnumDefinition{ + {Name: "OS", DefiningModule: "openconfig-complex"}, + }, + }, "/openconfig-complex/multi-key-config/key2": { Name: "MultiKeyKey2", Kind: ygen.SimpleEnumerationType, diff --git a/protogen/protoelements.go b/protogen/protoelements.go index 8c68d4cc0..4bce3a97f 100644 --- a/protogen/protoelements.go +++ b/protogen/protoelements.go @@ -309,7 +309,7 @@ func (s *ProtoLangMapper) yangTypeToProtoType(args resolveTypeArgs, pargs resolv if err != nil { return nil, err } - _, key, err := s.EnumName(args.contextEntry, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), !opts.TransformationOptions.EnumerationsUseUnderscores, opts.ParseOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, false, opts.TransformationOptions.EnumOrgPrefixesToTrim) + _, key, err := s.EnumName(args.contextEntry, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), !opts.TransformationOptions.EnumerationsUseUnderscores, opts.TransformationOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, false, opts.TransformationOptions.EnumOrgPrefixesToTrim) if err != nil { return nil, err } @@ -387,7 +387,7 @@ func (s *ProtoLangMapper) yangTypeToProtoScalarType(args resolveTypeArgs, pargs if err != nil { return nil, err } - _, key, err := s.EnumName(args.contextEntry, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), !opts.TransformationOptions.EnumerationsUseUnderscores, opts.ParseOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, false, opts.TransformationOptions.EnumOrgPrefixesToTrim) + _, key, err := s.EnumName(args.contextEntry, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), !opts.TransformationOptions.EnumerationsUseUnderscores, opts.TransformationOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, false, opts.TransformationOptions.EnumOrgPrefixesToTrim) if err != nil { return nil, err } diff --git a/protogen/protoelements_test.go b/protogen/protoelements_test.go index 14ddab50e..7e593d4eb 100644 --- a/protogen/protoelements_test.go +++ b/protogen/protoelements_test.go @@ -669,7 +669,6 @@ func TestYangTypeToProtoType(t *testing.T) { gotWrapper, err := s.yangTypeToProtoType(st, rpt, ygen.IROptions{ TransformationOptions: ygen.TransformationOpts{ CompressBehaviour: genutil.Uncompressed, - IgnoreShadowSchemaPaths: false, GenerateFakeRoot: true, ExcludeState: false, ShortenEnumLeafNames: false, @@ -695,7 +694,6 @@ func TestYangTypeToProtoType(t *testing.T) { gotScalar, err := s.yangTypeToProtoScalarType(st, rpt, ygen.IROptions{ TransformationOptions: ygen.TransformationOpts{ CompressBehaviour: genutil.Uncompressed, - IgnoreShadowSchemaPaths: false, GenerateFakeRoot: true, ExcludeState: false, ShortenEnumLeafNames: false, diff --git a/protogen/testdata/proto/proto-enums-addid.enums.formatted-txt b/protogen/testdata/proto/proto-enums-addid.enums.formatted-txt index d83611f41..2cec76bb8 100644 --- a/protogen/testdata/proto/proto-enums-addid.enums.formatted-txt +++ b/protogen/testdata/proto/proto-enums-addid.enums.formatted-txt @@ -28,3 +28,10 @@ enum ProtoEnumsEnumUnionTypedefEnum { PROTOENUMSENUMUNIONTYPEDEFENUM_UNSET = 0; PROTOENUMSENUMUNIONTYPEDEFENUM_B_VAL = 1 [(yext.yang_name) = "B_VAL"]; } + +// ProtoEnumsIrefTypedef represents an enumerated type generated for the YANG identity BASE_IDENTITY. +enum ProtoEnumsIrefTypedef { + PROTOENUMSIREFTYPEDEF_UNSET = 0; + PROTOENUMSIREFTYPEDEF_DERIVED_IDENTITY = 191733515 [(yext.yang_name) = "DERIVED_IDENTITY"]; + PROTOENUMSIREFTYPEDEF_REMOTE_IDENTITY = 494029318 [(yext.yang_name) = "REMOTE_IDENTITY"]; +} diff --git a/protogen/testdata/proto/proto-enums-addid.formatted-txt b/protogen/testdata/proto/proto-enums-addid.formatted-txt index 0caaff0c4..5552ab40c 100644 --- a/protogen/testdata/proto/proto-enums-addid.formatted-txt +++ b/protogen/testdata/proto/proto-enums-addid.formatted-txt @@ -28,4 +28,5 @@ message A { openconfig.enums.ProtoEnumsBASEIDENTITY e_protoenumsbaseidentity = 261975251; string e_string = 222327361; } + openconfig.enums.ProtoEnumsIrefTypedef f = 314438328; } diff --git a/protogen/testdata/proto/proto-enums.enums.formatted-txt b/protogen/testdata/proto/proto-enums.enums.formatted-txt index c302ac098..569b01644 100644 --- a/protogen/testdata/proto/proto-enums.enums.formatted-txt +++ b/protogen/testdata/proto/proto-enums.enums.formatted-txt @@ -24,3 +24,9 @@ enum ProtoEnumsEnumUnionTypedefEnum { PROTOENUMSENUMUNIONTYPEDEFENUM_UNSET = 0; PROTOENUMSENUMUNIONTYPEDEFENUM_B_VAL = 1; } + +// ProtoEnumsIrefTypedef represents an enumerated type generated for the YANG identity BASE_IDENTITY. +enum ProtoEnumsIrefTypedef { + PROTOENUMSIREFTYPEDEF_UNSET = 0; + PROTOENUMSIREFTYPEDEF_DERIVED_IDENTITY = 191733515; +} diff --git a/protogen/testdata/proto/proto-enums.formatted-txt b/protogen/testdata/proto/proto-enums.formatted-txt index aa3694748..d53c600c6 100644 --- a/protogen/testdata/proto/proto-enums.formatted-txt +++ b/protogen/testdata/proto/proto-enums.formatted-txt @@ -26,4 +26,5 @@ message A { openconfig.enums.ProtoEnumsBASEIDENTITY e_protoenumsbaseidentity = 261975251; string e_string = 222327361; } + openconfig.enums.ProtoEnumsIrefTypedef f = 314438328; } diff --git a/protogen/testdata/proto/proto-enums.yang b/protogen/testdata/proto/proto-enums.yang index e381e0a47..df0f4e05a 100644 --- a/protogen/testdata/proto/proto-enums.yang +++ b/protogen/testdata/proto/proto-enums.yang @@ -31,6 +31,12 @@ module proto-enums { } } + typedef iref-typedef { + type identityref { + base BASE_IDENTITY; + } + } + container a { leaf a { type enumeration { @@ -55,5 +61,10 @@ module proto-enums { leaf e { type union-identityref-typedef; } + + leaf f { + type iref-typedef; + } + } } diff --git a/testdata/modules/openconfig-complex.yang b/testdata/modules/openconfig-complex.yang index ade53d669..e75192487 100644 --- a/testdata/modules/openconfig-complex.yang +++ b/testdata/modules/openconfig-complex.yang @@ -17,6 +17,12 @@ module openconfig-complex { default 5; } + typedef program { + type identityref { + base SOFTWARE; + } + } + typedef weekend-days { type enumeration { enum SATURDAY; @@ -61,6 +67,10 @@ module openconfig-complex { type identityref { base "SOFTWARE"; } } + leaf iref2 { + type program; + } + leaf simple-union-enum { type union { type uint64; diff --git a/ygen/codegen.go b/ygen/codegen.go index 76c676636..bad983fb9 100644 --- a/ygen/codegen.go +++ b/ygen/codegen.go @@ -12,9 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package ygen contains a library to generate Go structs from a YANG model. +// Package ygen contains a library and base configuration options that can be +// extended to generate language-specific structs from a YANG model. // The Goyang parsing library is used to parse YANG. The output can consider // OpenConfig-specific conventions such that the schema is compressed. +// The output of this library is an intermediate representation (IR) designed +// to reduce the need for working with the Goyang parsing library's AST. package ygen import ( @@ -31,41 +34,6 @@ import ( gpb "github.com/openconfig/gnmi/proto/gnmi" ) -// YANGCodeGenerator is a structure that is used to pass arguments as to -// how the output Go code should be generated. -// TODO(wenbli): Delete this. -type YANGCodeGenerator struct { - // Config stores the configuration parameters used for code generation. - Config GeneratorConfig -} - -// GeneratorConfig stores the configuration options used for code generation. -type GeneratorConfig struct { - // PackageName is the name that should be used for the generating package. - PackageName string - // Caller is the name of the binary calling the generator library, it is - // included in the header of output files for debugging purposes. If a - // string is not specified, the location of the library is utilised. - Caller string - // GenerateJSONSchema stores a boolean which defines whether to generate - // the JSON corresponding to the YANG schema parsed to generate the - // output code. - GenerateJSONSchema bool - // StoreRawSchema the raw JSON schema should be returned by the code - // generation function, such that it can be handled by an external - // library. - StoreRawSchema bool - // ParseOptions contains parsing options for a given set of schema files. - ParseOptions ParseOpts - // TransformationOptions contains options for how the generated code - // may be transformed from a simple 1:1 mapping with respect to the - // given YANG schema. - TransformationOptions TransformationOpts - // IncludeDescriptions specifies that YANG entry descriptions are added - // to the JSON schema. Is false by default, to reduce the size of generated schema - IncludeDescriptions bool -} - // ParseOpts contains parsing configuration for a given schema. type ParseOpts struct { // ExcludeModules specifies any modules that are included within the set of @@ -77,6 +45,27 @@ type ParseOpts struct { // github.com/openconfig/goyang/pkg/yang library. These specify how the // input YANG files should be parsed. YANGParseOptions yang.Options +} + +// TransformationOpts specifies transformations to the generated code with +// respect to the input schema. +type TransformationOpts struct { + // CompressBehaviour specifies how the set of direct children of any + // entry should determined. Specifically, whether compression is + // enabled, and whether state fields in the schema should be excluded. + CompressBehaviour genutil.CompressBehaviour + // GenerateFakeRoot specifies whether an entity that represents the + // root of the YANG schema tree should be generated in the generated + // code. + GenerateFakeRoot bool + // FakeRootName specifies the name of the struct that should be generated + // representing the root. + FakeRootName string + // ExcludeState specifies whether config false values should be + // included in the generated code output. When set, all values that are + // not writeable (i.e., config false) within the YANG schema and their + // children are excluded from the generated code. + ExcludeState bool // SkipEnumDeduplication specifies whether leaves of type 'enumeration' that // are used in multiple places in the schema should share a common type within // the generated code that is output by ygen. By default (false), a common type @@ -105,31 +94,6 @@ type ParseOpts struct { // When it is disabled, two different enumerations (ModuleName_(State|Config)_Enabled) // will be output in the generated code. SkipEnumDeduplication bool -} - -// TransformationOpts specifies transformations to the generated code with -// respect to the input schema. -type TransformationOpts struct { - // CompressBehaviour specifies how the set of direct children of any - // entry should determined. Specifically, whether compression is - // enabled, and whether state fields in the schema should be excluded. - CompressBehaviour genutil.CompressBehaviour - // IgnoreShadowSchemaPaths indicates whether when OpenConfig path - // compression is enabled, that the shadowed paths are to be ignored - // while while unmarshalling. - IgnoreShadowSchemaPaths bool - // GenerateFakeRoot specifies whether an entity that represents the - // root of the YANG schema tree should be generated in the generated - // code. - GenerateFakeRoot bool - // FakeRootName specifies the name of the struct that should be generated - // representing the root. - FakeRootName string - // ExcludeState specifies whether config false values should be - // included in the generated code output. When set, all values that are - // not writeable (i.e., config false) within the YANG schema and their - // children are excluded from the generated code. - ExcludeState bool // ShortenEnumLeafNames removes the module name from the name of // enumeration leaves. ShortenEnumLeafNames bool @@ -145,18 +109,6 @@ type TransformationOpts struct { EnumerationsUseUnderscores bool } -// NewYANGCodeGenerator returns a new instance of the YANGCodeGenerator -// struct to the calling function. -func NewYANGCodeGenerator(c *GeneratorConfig) *YANGCodeGenerator { - cg := &YANGCodeGenerator{} - - if c != nil { - cg.Config = *c - } - - return cg -} - // yangEnum represents an enumerated type in YANG that is to be output in the // Go code. The enumerated type may be a YANG 'identity' or enumeration. type yangEnum struct { @@ -250,18 +202,18 @@ type mappedYANGDefinitions struct { // - yangFiles: an input set of YANG schema files and the paths that // - includePaths: the set of paths that are to be searched for included or // imported YANG modules. -// - cfg: the current generator's configuration. +// - opts: the current generator's configuration. // It returns a mappedYANGDefinitions struct populated with the directory, enum // entries in the input schemas as well as the calculated schema tree. -func mappedDefinitions(yangFiles, includePaths []string, cfg *GeneratorConfig) (*mappedYANGDefinitions, util.Errors) { - modules, errs := processModules(yangFiles, includePaths, cfg.ParseOptions.YANGParseOptions) +func mappedDefinitions(yangFiles, includePaths []string, opts IROptions) (*mappedYANGDefinitions, util.Errors) { + modules, errs := processModules(yangFiles, includePaths, opts.ParseOptions.YANGParseOptions) if errs != nil { return nil, errs } // Build a map of excluded modules to simplify lookup. excluded := map[string]bool{} - for _, e := range cfg.ParseOptions.ExcludeModules { + for _, e := range opts.ParseOptions.ExcludeModules { excluded[e] = true } @@ -272,9 +224,9 @@ func mappedDefinitions(yangFiles, includePaths []string, cfg *GeneratorConfig) ( var rootElems, treeElems []*yang.Entry for _, module := range modules { // Need to transform the AST based on compression behaviour. - genutil.TransformEntry(module, cfg.TransformationOptions.CompressBehaviour) + genutil.TransformEntry(module, opts.TransformationOptions.CompressBehaviour) - errs = append(errs, findMappableEntities(module, dirs, enums, cfg.ParseOptions.ExcludeModules, cfg.TransformationOptions.CompressBehaviour.CompressEnabled(), modules)...) + errs = append(errs, findMappableEntities(module, dirs, enums, opts.ParseOptions.ExcludeModules, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), modules)...) if module == nil { errs = append(errs, errors.New("found a nil module in the returned module set")) continue @@ -301,8 +253,8 @@ func mappedDefinitions(yangFiles, includePaths []string, cfg *GeneratorConfig) ( // If we were asked to generate a fake root entity, then go and find the top-level entities that // we were asked for. - if cfg.TransformationOptions.GenerateFakeRoot { - if err := createFakeRoot(dirs, rootElems, cfg.TransformationOptions.FakeRootName, cfg.TransformationOptions.CompressBehaviour.CompressEnabled()); err != nil { + if opts.TransformationOptions.GenerateFakeRoot { + if err := createFakeRoot(dirs, rootElems, opts.TransformationOptions.FakeRootName, opts.TransformationOptions.CompressBehaviour.CompressEnabled()); err != nil { return nil, []error{err} } } diff --git a/ygen/enumgen.go b/ygen/enumgen.go index 53acf46dc..c34f15019 100644 --- a/ygen/enumgen.go +++ b/ygen/enumgen.go @@ -592,10 +592,14 @@ func findEnumSet(entries map[string]*yang.Entry, compressPaths, noUnderscores, s continue } if _, ok := genEnums[typeName]; !ok { + kind := DerivedEnumerationType + if e.Type.IdentityBase != nil { + kind = IdentityType + } genEnums[typeName] = &yangEnum{ name: typeName, entry: e, - kind: DerivedEnumerationType, + kind: kind, id: key, } } diff --git a/ygen/genir.go b/ygen/genir.go index 866445006..1f69508eb 100644 --- a/ygen/genir.go +++ b/ygen/genir.go @@ -71,15 +71,12 @@ func GenerateIR(yangFiles, includePaths []string, langMapper LangMapper, opts IR // Extract the entities to be mapped into structs and enumerations in the output // Go code. Extract the schematree from the modules provided such that it can be // used to reference entities within the tree. - mdef, errs := mappedDefinitions(yangFiles, includePaths, &GeneratorConfig{ - ParseOptions: opts.ParseOptions, - TransformationOptions: opts.TransformationOptions, - }) + mdef, errs := mappedDefinitions(yangFiles, includePaths, opts) if errs != nil { return nil, errs } - enumSet, genEnums, errs := findEnumSet(mdef.enumEntries, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), !opts.TransformationOptions.EnumerationsUseUnderscores, opts.ParseOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, opts.TransformationOptions.UseDefiningModuleForTypedefEnumNames, opts.AppendEnumSuffixForSimpleUnionEnums, opts.TransformationOptions.EnumOrgPrefixesToTrim) + enumSet, genEnums, errs := findEnumSet(mdef.enumEntries, opts.TransformationOptions.CompressBehaviour.CompressEnabled(), !opts.TransformationOptions.EnumerationsUseUnderscores, opts.TransformationOptions.SkipEnumDeduplication, opts.TransformationOptions.ShortenEnumLeafNames, opts.TransformationOptions.UseDefiningModuleForTypedefEnumNames, opts.AppendEnumSuffixForSimpleUnionEnums, opts.TransformationOptions.EnumOrgPrefixesToTrim) if errs != nil { return nil, errs } diff --git a/ygen/genstate_test.go b/ygen/genstate_test.go index 71dc8d96f..8f0f1a75d 100644 --- a/ygen/genstate_test.go +++ b/ygen/genstate_test.go @@ -1396,11 +1396,11 @@ func TestBuildDirectoryDefinitions(t *testing.T) { case golang: got, errs = buildDirectoryDefinitions(gogen, structs, IROptions{ ParseOptions: ParseOpts{ - SkipEnumDeduplication: false, }, TransformationOptions: TransformationOpts{ CompressBehaviour: c.compressBehaviour, GenerateFakeRoot: false, + SkipEnumDeduplication: false, ShortenEnumLeafNames: true, UseDefiningModuleForTypedefEnumNames: true, EnumOrgPrefixesToTrim: nil, @@ -1412,11 +1412,11 @@ func TestBuildDirectoryDefinitions(t *testing.T) { case protobuf: got, errs = buildDirectoryDefinitions(protogen, structs, IROptions{ ParseOptions: ParseOpts{ - SkipEnumDeduplication: false, }, TransformationOptions: TransformationOpts{ CompressBehaviour: c.compressBehaviour, GenerateFakeRoot: false, + SkipEnumDeduplication: false, ShortenEnumLeafNames: true, UseDefiningModuleForTypedefEnumNames: true, EnumOrgPrefixesToTrim: nil, @@ -2157,12 +2157,11 @@ func TestBuildListKey(t *testing.T) { } got, err := buildListKey(tt.in, s, IROptions{ - ParseOptions: ParseOpts{ - SkipEnumDeduplication: tt.inSkipEnumDedup, - }, + ParseOptions: ParseOpts{}, TransformationOptions: TransformationOpts{ CompressBehaviour: compressBehaviour, GenerateFakeRoot: true, + SkipEnumDeduplication: tt.inSkipEnumDedup, ShortenEnumLeafNames: true, UseDefiningModuleForTypedefEnumNames: true, EnumOrgPrefixesToTrim: nil, diff --git a/ypathgen/pathgen.go b/ypathgen/pathgen.go index e395072f1..6c3047e73 100644 --- a/ypathgen/pathgen.go +++ b/ypathgen/pathgen.go @@ -249,14 +249,14 @@ func (cg *GenConfig) GeneratePathCode(yangFiles, includePaths []string) (map[str opts := ygen.IROptions{ ParseOptions: ygen.ParseOpts{ - YANGParseOptions: cg.YANGParseOptions, - ExcludeModules: cg.ExcludeModules, - SkipEnumDeduplication: cg.SkipEnumDeduplication, + YANGParseOptions: cg.YANGParseOptions, + ExcludeModules: cg.ExcludeModules, }, TransformationOptions: ygen.TransformationOpts{ CompressBehaviour: compressBehaviour, GenerateFakeRoot: true, FakeRootName: cg.FakeRootName, + SkipEnumDeduplication: cg.SkipEnumDeduplication, ShortenEnumLeafNames: cg.ShortenEnumLeafNames, EnumOrgPrefixesToTrim: cg.EnumOrgPrefixesToTrim, UseDefiningModuleForTypedefEnumNames: cg.UseDefiningModuleForTypedefEnumNames,