From ec273a725045c821914771593e72390dfa4a389c Mon Sep 17 00:00:00 2001 From: Wen Bo Li <50884368+wenovus@users.noreply.github.com> Date: Wed, 28 Jun 2023 11:05:37 -0700 Subject: [PATCH] Add generation flag to ordered maps (#884) --- generator/generator.go | 2 + gogen/codegen.go | 4 + gogen/codegen_test.go | 37 +- gogen/gogen.go | 2 +- gogen/internal/gotypes/ordered_map.go | 2 +- .../openconfig-withlist-opstate.formatted-txt | 187 ++++++++++ ...penconfig-withlist-unordered.formatted-txt | 337 ++++++++++++++++++ .../structs/openconfig-withlist.formatted-txt | 187 ++++++++++ gogen/unordered_list.go | 4 +- testdata/modules/openconfig-withlist.yang | 22 ++ util/reflect.go | 4 +- ygot/diff_exported_test.go | 4 - ygot/struct_validation_map_exported_test.go | 2 +- ypathgen/pathgen_test.go | 32 +- ypathgen/testdata/modules/oc-list/list.txt | 91 +++++ ...nconfig-withlist-separate-package.path-txt | 120 +++++++ .../openconfig-withlist.builder.path-txt | 120 +++++++ .../openconfig-withlist.nowildcard.path-txt | 43 +++ .../structs/openconfig-withlist.path-txt | 120 +++++++ ...openconfig-withlist.simplifyallwc.path-txt | 120 +++++++ 20 files changed, 1417 insertions(+), 23 deletions(-) create mode 100644 gogen/testdata/structs/openconfig-withlist-unordered.formatted-txt diff --git a/generator/generator.go b/generator/generator.go index 682ee1208..123582de9 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -99,6 +99,7 @@ var ( includeModelData = flag.Bool("include_model_data", false, "If set to true, a slice of gNMI ModelData messages are included in the generated Go code containing the details of the input schemas from which the code was generated.") generatePopulateDefault = flag.Bool("generate_populate_defaults", false, "If set to true, a PopulateDefault method will be generated for all GoStructs which recursively populates default values.") generateValidateFnName = flag.String("validate_fn_name", "Validate", "The Name of the proxy function for the Validate functionality.") + generateOrderedMaps = flag.Bool("generate_ordered_maps", true, "If set to true, ordered map structures satisfying the interface ygot.GoOrderedMap will be generated for `ordered-by user` lists instead of Go built-in maps.") // Flags used for PathStruct generation only. schemaStructPath = flag.String("schema_struct_path", "", "The Go import path for the schema structs package. This should be specified if and only if schema structs are not being generated at the same time as path structs.") @@ -374,6 +375,7 @@ func main() { IncludeModelData: *includeModelData, AppendEnumSuffixForSimpleUnionEnums: *appendEnumSuffixForSimpleUnionEnums, IgnoreShadowSchemaPaths: *ignoreShadowSchemaPaths, + GenerateOrderedListsAsUnorderedMaps: !*generateOrderedMaps, }, ) diff --git a/gogen/codegen.go b/gogen/codegen.go index 8e03a202a..17533c7df 100644 --- a/gogen/codegen.go +++ b/gogen/codegen.go @@ -120,6 +120,10 @@ type GoOpts struct { // compression is enabled, that the shadowed paths are to be ignored // while while unmarshalling. IgnoreShadowSchemaPaths bool + // GenerateOrderedListsAsUnorderedMaps indicates that lists that are + // marked `ordered-by user` will be represented using built-in Go maps + // instead of an ordered map Go structure. + GenerateOrderedListsAsUnorderedMaps bool } // GeneratedCode contains generated code snippets that can be processed by the calling diff --git a/gogen/codegen_test.go b/gogen/codegen_test.go index c2d54b4a6..5b93216cb 100644 --- a/gogen/codegen_test.go +++ b/gogen/codegen_test.go @@ -3,8 +3,9 @@ package gogen import ( "bytes" "encoding/json" + "flag" "fmt" - "io/ioutil" + "os" "path/filepath" "testing" @@ -25,6 +26,8 @@ const ( deflakeRuns int = 10 ) +var updateGolden = flag.Bool("update_golden", false, "Update golden files") + // yangTestCase describs a test case for which code generation is performed // through Goyang's API, it provides the input set of parameters in a way that // can be reused across tests. @@ -307,6 +310,25 @@ func TestSimpleStructs(t *testing.T) { }, }, wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-withlist-opstate.formatted-txt"), + }, { + name: "OpenConfig schema test - list and associated method (rename, new) - using unordered list", + inFiles: []string{filepath.Join(datapath, "openconfig-withlist.yang")}, + inConfig: CodeGenerator{ + IROptions: ygen.IROptions{ + TransformationOptions: ygen.TransformationOpts{ + CompressBehaviour: genutil.PreferIntendedConfig, + ShortenEnumLeafNames: true, + UseDefiningModuleForTypedefEnumNames: true, + EnumerationsUseUnderscores: true, + }, + }, + GoOptions: GoOpts{ + GenerateRenameMethod: true, + GenerateSimpleUnions: true, + GenerateOrderedListsAsUnorderedMaps: true, + }, + }, + wantStructsCodeFile: filepath.Join(TestRoot, "testdata/structs/openconfig-withlist-unordered.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")}, @@ -1161,9 +1183,9 @@ func TestSimpleStructs(t *testing.T) { } if tt.wantSchemaFile != "" { - wantSchema, rferr := ioutil.ReadFile(tt.wantSchemaFile) + wantSchema, rferr := os.ReadFile(tt.wantSchemaFile) if rferr != nil { - t.Fatalf("%s: ioutil.ReadFile(%q) error: %v", tt.name, tt.wantSchemaFile, rferr) + t.Fatalf("%s: os.ReadFile(%q) error: %v", tt.name, tt.wantSchemaFile, rferr) } var wantJSON map[string]interface{} @@ -1177,14 +1199,19 @@ func TestSimpleStructs(t *testing.T) { } } - wantCodeBytes, rferr := ioutil.ReadFile(tt.wantStructsCodeFile) + wantCodeBytes, rferr := os.ReadFile(tt.wantStructsCodeFile) if rferr != nil { - t.Fatalf("%s: ioutil.ReadFile(%q) error: %v", tt.name, tt.wantStructsCodeFile, rferr) + t.Fatalf("%s: os.ReadFile(%q) error: %v", tt.name, tt.wantStructsCodeFile, rferr) } wantCode := string(wantCodeBytes) if gotCode != wantCode { + if *updateGolden { + if err := os.WriteFile(tt.wantStructsCodeFile, []byte(gotCode), 0644); err != nil { + t.Fatal(err) + } + } // Use difflib to generate a unified diff between the // two code snippets such that this is simpler to debug // in the test output. diff --git a/gogen/gogen.go b/gogen/gogen.go index 2345add4b..ec6d818a4 100644 --- a/gogen/gogen.go +++ b/gogen/gogen.go @@ -1045,7 +1045,7 @@ func writeGoStruct(targetStruct *ygen.ParsedDirectory, goStructElements map[stri // If the field within the struct is a list, then generate code for this list. This // includes extracting any new types that are required to represent the key of a // list that has multiple keys. - fieldType, multiKeyListKey, listMethods, orderedMapSpec, listErr := yangListFieldToGoType(field, fieldName, targetStruct, goStructElements) + fieldType, multiKeyListKey, listMethods, orderedMapSpec, listErr := yangListFieldToGoType(field, fieldName, targetStruct, goStructElements, !goOpts.GenerateOrderedListsAsUnorderedMaps) if listErr != nil { errs = append(errs, listErr) } diff --git a/gogen/internal/gotypes/ordered_map.go b/gogen/internal/gotypes/ordered_map.go index 3553004a3..0a3f70e40 100644 --- a/gogen/internal/gotypes/ordered_map.go +++ b/gogen/internal/gotypes/ordered_map.go @@ -72,7 +72,7 @@ type RoutingPolicy_PolicyDefinition_Statement struct { type RoutingPolicy_PolicyDefinition_Statement_OrderedMap struct { // TODO: Add a mutex here and add race tests after implementing // ygot.Equal and evaluating the thread-safety of ygot. - //mu sync.RWmutex + // mu sync.RWmutex // keys contain the key order of the map. keys []string // valueMap contains the mapping from the statement key to each of the diff --git a/gogen/testdata/structs/openconfig-withlist-opstate.formatted-txt b/gogen/testdata/structs/openconfig-withlist-opstate.formatted-txt index 0700e8d33..523ac0f19 100644 --- a/gogen/testdata/structs/openconfig-withlist-opstate.formatted-txt +++ b/gogen/testdata/structs/openconfig-withlist-opstate.formatted-txt @@ -73,6 +73,7 @@ type UnionUnsupported struct { type Model struct { MultiKey map[Model_MultiKey_Key]*Model_MultiKey `path:"b/multi-key" module:"openconfig-withlist/openconfig-withlist"` SingleKey map[string]*Model_SingleKey `path:"a/single-key" module:"openconfig-withlist/openconfig-withlist"` + SingleKeyOrdered *Model_SingleKeyOrdered_OrderedMap `path:"c/single-key-ordered" module:"openconfig-withlist/openconfig-withlist"` } // IsYANGGoStruct ensures that Model implements the yang.GoStruct @@ -196,6 +197,165 @@ func (t *Model) RenameSingleKey(oldK, newK string) error { return nil } +// AppendNewSingleKeyOrdered creates a new entry in the SingleKeyOrdered +// ordered map of the Model struct. The keys of the list are +// populated from the input arguments. +func (s *Model) AppendNewSingleKeyOrdered(Key string) (*Model_SingleKeyOrdered, error) { + if s.SingleKeyOrdered == nil { + s.SingleKeyOrdered = &Model_SingleKeyOrdered_OrderedMap{} + } + return s.SingleKeyOrdered.AppendNew(Key) +} + +// AppendSingleKeyOrdered appends the supplied Model_SingleKeyOrdered struct +// to the list SingleKeyOrdered of Model. If the key value(s) +// specified in the supplied Model_SingleKeyOrdered already exist in the list, an +// error is returned. +func (s *Model) AppendSingleKeyOrdered(v *Model_SingleKeyOrdered) error { + if s.SingleKeyOrdered == nil { + s.SingleKeyOrdered = &Model_SingleKeyOrdered_OrderedMap{} + } + return s.SingleKeyOrdered.Append(v) +} + +// GetSingleKeyOrdered retrieves the value with the specified key from the +// SingleKeyOrdered map field of Model. If the receiver +// is nil, or the specified key is not present in the list, nil is returned +// such that Get* methods may be safely chained. +func (s *Model) GetSingleKeyOrdered(Key string) *Model_SingleKeyOrdered { + key := Key + return s.SingleKeyOrdered.Get(key) +} + +// DeleteSingleKeyOrdered deletes the value with the specified keys from +// the receiver Model. If there is no such element, the +// function is a no-op. +func (s *Model) DeleteSingleKeyOrdered(Key string) bool { + key := Key + return s.SingleKeyOrdered.Delete(key) +} + +// Model_SingleKeyOrdered_OrderedMap is an ordered map that represents the "ordered-by user" +// list elements at /openconfig-withlist/model/c/single-key-ordered. +type Model_SingleKeyOrdered_OrderedMap struct { + keys []string + valueMap map[string]*Model_SingleKeyOrdered +} + +// IsYANGOrderedList ensures that Model_SingleKeyOrdered_OrderedMap implements the +// ygot.GoOrderedMap interface. +func (*Model_SingleKeyOrdered_OrderedMap) IsYANGOrderedList() {} + +// init initializes any uninitialized values. +func (o *Model_SingleKeyOrdered_OrderedMap) init() { + if o == nil { + return + } + if o.valueMap == nil { + o.valueMap = map[string]*Model_SingleKeyOrdered{} + } +} + +// Keys returns a copy of the list's keys. +func (o *Model_SingleKeyOrdered_OrderedMap) Keys() []string { + if o == nil { + return nil + } + return append([]string{}, o.keys...) +} + +// Values returns the current set of the list's values in order. +func (o *Model_SingleKeyOrdered_OrderedMap) Values() []*Model_SingleKeyOrdered { + if o == nil { + return nil + } + var values []*Model_SingleKeyOrdered + for _, key := range o.keys { + values = append(values, o.valueMap[key]) + } + return values +} + +// Len returns a size of Model_SingleKeyOrdered_OrderedMap +func (o *Model_SingleKeyOrdered_OrderedMap) Len() int { + if o == nil { + return 0 + } + return len(o.keys) +} + +// Get returns the value corresponding to the key. If the key is not found, nil +// is returned. +func (o *Model_SingleKeyOrdered_OrderedMap) Get(key string) *Model_SingleKeyOrdered { + if o == nil { + return nil + } + val, _ := o.valueMap[key] + return val +} + +// Delete deletes an element. +func (o *Model_SingleKeyOrdered_OrderedMap) Delete(key string) bool { + if o == nil { + return false + } + if _, ok := o.valueMap[key]; !ok { + return false + } + for i, k := range o.keys { + if k == key { + o.keys = append(o.keys[:i], o.keys[i+1:]...) + delete(o.valueMap, key) + return true + } + } + return false +} + +// Append appends a Model_SingleKeyOrdered, returning an error if the key +// already exists in the ordered list or if the key is unspecified. +func (o *Model_SingleKeyOrdered_OrderedMap) Append(v *Model_SingleKeyOrdered) error { + if o == nil { + return fmt.Errorf("nil ordered map, cannot append Model_SingleKeyOrdered") + } + if v == nil { + return fmt.Errorf("nil Model_SingleKeyOrdered") + } + if v.Key == nil { + return fmt.Errorf("invalid nil key received for Key") + } + + key := *v.Key + + if _, ok := o.valueMap[key]; ok { + return fmt.Errorf("duplicate key for list Statement %v", key) + } + o.keys = append(o.keys, key) + o.init() + o.valueMap[key] = v + return nil +} + +// AppendNew creates and appends a new Model_SingleKeyOrdered, returning the +// newly-initialized v. It returns an error if the v already exists. +func (o *Model_SingleKeyOrdered_OrderedMap) AppendNew(Key string) (*Model_SingleKeyOrdered, error) { + if o == nil { + return nil, fmt.Errorf("nil ordered map, cannot append Model_SingleKeyOrdered") + } + key := Key + + if _, ok := o.valueMap[key]; ok { + return nil, fmt.Errorf("duplicate key for list Statement %v", key) + } + o.keys = append(o.keys, key) + newElement := &Model_SingleKeyOrdered{ + Key: &Key, + } + o.init() + o.valueMap[key] = newElement + return newElement, nil +} + // ΛBelongingModule returns the name of the module that defines the namespace // of Model. func (*Model) ΛBelongingModule() string { @@ -261,3 +421,30 @@ func (t *Model_SingleKey) ΛListKeyMap() (map[string]interface{}, error) { func (*Model_SingleKey) ΛBelongingModule() string { return "openconfig-withlist" } + +// Model_SingleKeyOrdered represents the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrdered struct { + Key *string `path:"state/key|key" module:"openconfig-withlist/openconfig-withlist|openconfig-withlist"` +} + +// IsYANGGoStruct ensures that Model_SingleKeyOrdered implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Model_SingleKeyOrdered) IsYANGGoStruct() {} + +// ΛListKeyMap returns the keys of the Model_SingleKeyOrdered struct, which is a YANG list entry. +func (t *Model_SingleKeyOrdered) ΛListKeyMap() (map[string]interface{}, error) { + if t.Key == nil { + return nil, fmt.Errorf("nil value for key Key") + } + + return map[string]interface{}{ + "key": *t.Key, + }, nil +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Model_SingleKeyOrdered. +func (*Model_SingleKeyOrdered) ΛBelongingModule() string { + return "openconfig-withlist" +} diff --git a/gogen/testdata/structs/openconfig-withlist-unordered.formatted-txt b/gogen/testdata/structs/openconfig-withlist-unordered.formatted-txt new file mode 100644 index 000000000..f00a7820c --- /dev/null +++ b/gogen/testdata/structs/openconfig-withlist-unordered.formatted-txt @@ -0,0 +1,337 @@ +/* +Package ocstructs is a generated package which contains definitions +of structs which represent a YANG schema. The generated schema can be +compressed by a series of transformations (compression was true +in this case). + +This package was generated by codegen-tests +using the following YANG input files: + - ../testdata/modules/openconfig-withlist.yang +Imported modules were sourced from: +*/ +package ocstructs + +import ( + "encoding/json" + "fmt" + "reflect" + + "github.com/openconfig/ygot/ygot" +) + +// Binary is a type that is used for fields that have a YANG type of +// binary. It is used such that binary fields can be distinguished from +// leaf-lists of uint8s (which are mapped to []uint8, equivalent to +// []byte in reflection). +type Binary []byte + +// YANGEmpty is a type that is used for fields that have a YANG type of +// empty. It is used such that empty fields can be distinguished from boolean fields +// in the generated code. +type YANGEmpty bool + +// UnionInt8 is an int8 type assignable to unions of which it is a subtype. +type UnionInt8 int8 + +// UnionInt16 is an int16 type assignable to unions of which it is a subtype. +type UnionInt16 int16 + +// UnionInt32 is an int32 type assignable to unions of which it is a subtype. +type UnionInt32 int32 + +// UnionInt64 is an int64 type assignable to unions of which it is a subtype. +type UnionInt64 int64 + +// UnionUint8 is a uint8 type assignable to unions of which it is a subtype. +type UnionUint8 uint8 + +// UnionUint16 is a uint16 type assignable to unions of which it is a subtype. +type UnionUint16 uint16 + +// UnionUint32 is a uint32 type assignable to unions of which it is a subtype. +type UnionUint32 uint32 + +// UnionUint64 is a uint64 type assignable to unions of which it is a subtype. +type UnionUint64 uint64 + +// UnionFloat64 is a float64 type assignable to unions of which it is a subtype. +type UnionFloat64 float64 + +// UnionString is a string type assignable to unions of which it is a subtype. +type UnionString string + +// UnionBool is a bool type assignable to unions of which it is a subtype. +type UnionBool bool + +// UnionUnsupported is an interface{} wrapper type for unsupported types. It is +// assignable to unions of which it is a subtype. +type UnionUnsupported struct { + Value interface{} +} + +// Model represents the /openconfig-withlist/model YANG schema element. +type Model struct { + MultiKey map[Model_MultiKey_Key]*Model_MultiKey `path:"b/multi-key" module:"openconfig-withlist/openconfig-withlist"` + SingleKey map[string]*Model_SingleKey `path:"a/single-key" module:"openconfig-withlist/openconfig-withlist"` + SingleKeyOrdered map[string]*Model_SingleKeyOrdered `path:"c/single-key-ordered" module:"openconfig-withlist/openconfig-withlist"` +} + +// IsYANGGoStruct ensures that Model implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Model) IsYANGGoStruct() {} + +// Model_MultiKey_Key represents the key for list MultiKey of element /openconfig-withlist/model. +type Model_MultiKey_Key struct { + Key1 uint32 `path:"key1"` + Key2 uint64 `path:"key2"` +} + +// IsYANGGoKeyStruct ensures that Model_MultiKey_Key partially implements the +// yang.GoKeyStruct interface. This allows functions that need to +// handle this key struct to identify it as being generated by gogen. +func (Model_MultiKey_Key) IsYANGGoKeyStruct() {} + +// ΛListKeyMap returns the values of the Model_MultiKey_Key key struct. +func (t Model_MultiKey_Key) ΛListKeyMap() (map[string]interface{}, error) { + return map[string]interface{}{ + "key1": t.Key1, + "key2": t.Key2, + }, nil +} + +// NewMultiKey creates a new entry in the MultiKey list of the +// Model struct. The keys of the list are populated from the input +// arguments. +func (t *Model) NewMultiKey(Key1 uint32, Key2 uint64) (*Model_MultiKey, error){ + + // Initialise the list within the receiver struct if it has not already been + // created. + if t.MultiKey == nil { + t.MultiKey = make(map[Model_MultiKey_Key]*Model_MultiKey) + } + + key := Model_MultiKey_Key{ + Key1: Key1, + Key2: Key2, + } + + // Ensure that this key has not already been used in the + // list. Keyed YANG lists do not allow duplicate keys to + // be created. + if _, ok := t.MultiKey[key]; ok { + return nil, fmt.Errorf("duplicate key %v for list MultiKey", key) + } + + t.MultiKey[key] = &Model_MultiKey{ + Key1: &Key1, + Key2: &Key2, + } + + return t.MultiKey[key], nil +} + +// RenameMultiKey renames an entry in the list MultiKey within +// the Model struct. The entry with key oldK is renamed to newK updating +// the key within the value. +func (t *Model) RenameMultiKey(oldK, newK Model_MultiKey_Key) error { + if _, ok := t.MultiKey[newK]; ok { + return fmt.Errorf("key %v already exists in MultiKey", newK) + } + + e, ok := t.MultiKey[oldK] + if !ok { + return fmt.Errorf("key %v not found in MultiKey", oldK) + } + e.Key1 = &newK.Key1 + e.Key2 = &newK.Key2 + + t.MultiKey[newK] = e + delete(t.MultiKey, oldK) + return nil +} + +// NewSingleKey creates a new entry in the SingleKey list of the +// Model struct. The keys of the list are populated from the input +// arguments. +func (t *Model) NewSingleKey(Key string) (*Model_SingleKey, error){ + + // Initialise the list within the receiver struct if it has not already been + // created. + if t.SingleKey == nil { + t.SingleKey = make(map[string]*Model_SingleKey) + } + + key := Key + + // Ensure that this key has not already been used in the + // list. Keyed YANG lists do not allow duplicate keys to + // be created. + if _, ok := t.SingleKey[key]; ok { + return nil, fmt.Errorf("duplicate key %v for list SingleKey", key) + } + + t.SingleKey[key] = &Model_SingleKey{ + Key: &Key, + } + + return t.SingleKey[key], nil +} + +// RenameSingleKey renames an entry in the list SingleKey within +// the Model struct. The entry with key oldK is renamed to newK updating +// the key within the value. +func (t *Model) RenameSingleKey(oldK, newK string) error { + if _, ok := t.SingleKey[newK]; ok { + return fmt.Errorf("key %v already exists in SingleKey", newK) + } + + e, ok := t.SingleKey[oldK] + if !ok { + return fmt.Errorf("key %v not found in SingleKey", oldK) + } + e.Key = &newK + + t.SingleKey[newK] = e + delete(t.SingleKey, oldK) + return nil +} + +// NewSingleKeyOrdered creates a new entry in the SingleKeyOrdered list of the +// Model struct. The keys of the list are populated from the input +// arguments. +func (t *Model) NewSingleKeyOrdered(Key string) (*Model_SingleKeyOrdered, error){ + + // Initialise the list within the receiver struct if it has not already been + // created. + if t.SingleKeyOrdered == nil { + t.SingleKeyOrdered = make(map[string]*Model_SingleKeyOrdered) + } + + key := Key + + // Ensure that this key has not already been used in the + // list. Keyed YANG lists do not allow duplicate keys to + // be created. + if _, ok := t.SingleKeyOrdered[key]; ok { + return nil, fmt.Errorf("duplicate key %v for list SingleKeyOrdered", key) + } + + t.SingleKeyOrdered[key] = &Model_SingleKeyOrdered{ + Key: &Key, + } + + return t.SingleKeyOrdered[key], nil +} + +// RenameSingleKeyOrdered renames an entry in the list SingleKeyOrdered within +// the Model struct. The entry with key oldK is renamed to newK updating +// the key within the value. +func (t *Model) RenameSingleKeyOrdered(oldK, newK string) error { + if _, ok := t.SingleKeyOrdered[newK]; ok { + return fmt.Errorf("key %v already exists in SingleKeyOrdered", newK) + } + + e, ok := t.SingleKeyOrdered[oldK] + if !ok { + return fmt.Errorf("key %v not found in SingleKeyOrdered", oldK) + } + e.Key = &newK + + t.SingleKeyOrdered[newK] = e + delete(t.SingleKeyOrdered, oldK) + return nil +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Model. +func (*Model) ΛBelongingModule() string { + return "openconfig-withlist" +} + +// Model_MultiKey represents the /openconfig-withlist/model/b/multi-key YANG schema element. +type Model_MultiKey struct { + Key1 *uint32 `path:"config/key1|key1" module:"openconfig-withlist/openconfig-withlist|openconfig-withlist"` + Key2 *uint64 `path:"config/key2|key2" module:"openconfig-withlist/openconfig-withlist|openconfig-withlist"` +} + +// IsYANGGoStruct ensures that Model_MultiKey implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Model_MultiKey) IsYANGGoStruct() {} + +// ΛListKeyMap returns the keys of the Model_MultiKey struct, which is a YANG list entry. +func (t *Model_MultiKey) ΛListKeyMap() (map[string]interface{}, error) { + if t.Key1 == nil { + return nil, fmt.Errorf("nil value for key Key1") + } + + if t.Key2 == nil { + return nil, fmt.Errorf("nil value for key Key2") + } + + return map[string]interface{}{ + "key1": *t.Key1, + "key2": *t.Key2, + }, nil +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Model_MultiKey. +func (*Model_MultiKey) ΛBelongingModule() string { + return "openconfig-withlist" +} + +// Model_SingleKey represents the /openconfig-withlist/model/a/single-key YANG schema element. +type Model_SingleKey struct { + Key *string `path:"config/key|key" module:"openconfig-withlist/openconfig-withlist|openconfig-withlist"` +} + +// IsYANGGoStruct ensures that Model_SingleKey implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Model_SingleKey) IsYANGGoStruct() {} + +// ΛListKeyMap returns the keys of the Model_SingleKey struct, which is a YANG list entry. +func (t *Model_SingleKey) ΛListKeyMap() (map[string]interface{}, error) { + if t.Key == nil { + return nil, fmt.Errorf("nil value for key Key") + } + + return map[string]interface{}{ + "key": *t.Key, + }, nil +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Model_SingleKey. +func (*Model_SingleKey) ΛBelongingModule() string { + return "openconfig-withlist" +} + +// Model_SingleKeyOrdered represents the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrdered struct { + Key *string `path:"config/key|key" module:"openconfig-withlist/openconfig-withlist|openconfig-withlist"` +} + +// IsYANGGoStruct ensures that Model_SingleKeyOrdered implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Model_SingleKeyOrdered) IsYANGGoStruct() {} + +// ΛListKeyMap returns the keys of the Model_SingleKeyOrdered struct, which is a YANG list entry. +func (t *Model_SingleKeyOrdered) ΛListKeyMap() (map[string]interface{}, error) { + if t.Key == nil { + return nil, fmt.Errorf("nil value for key Key") + } + + return map[string]interface{}{ + "key": *t.Key, + }, nil +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Model_SingleKeyOrdered. +func (*Model_SingleKeyOrdered) ΛBelongingModule() string { + return "openconfig-withlist" +} diff --git a/gogen/testdata/structs/openconfig-withlist.formatted-txt b/gogen/testdata/structs/openconfig-withlist.formatted-txt index 64a56fbda..1b47f9c51 100644 --- a/gogen/testdata/structs/openconfig-withlist.formatted-txt +++ b/gogen/testdata/structs/openconfig-withlist.formatted-txt @@ -73,6 +73,7 @@ type UnionUnsupported struct { type Model struct { MultiKey map[Model_MultiKey_Key]*Model_MultiKey `path:"b/multi-key" module:"openconfig-withlist/openconfig-withlist"` SingleKey map[string]*Model_SingleKey `path:"a/single-key" module:"openconfig-withlist/openconfig-withlist"` + SingleKeyOrdered *Model_SingleKeyOrdered_OrderedMap `path:"c/single-key-ordered" module:"openconfig-withlist/openconfig-withlist"` } // IsYANGGoStruct ensures that Model implements the yang.GoStruct @@ -196,6 +197,165 @@ func (t *Model) RenameSingleKey(oldK, newK string) error { return nil } +// AppendNewSingleKeyOrdered creates a new entry in the SingleKeyOrdered +// ordered map of the Model struct. The keys of the list are +// populated from the input arguments. +func (s *Model) AppendNewSingleKeyOrdered(Key string) (*Model_SingleKeyOrdered, error) { + if s.SingleKeyOrdered == nil { + s.SingleKeyOrdered = &Model_SingleKeyOrdered_OrderedMap{} + } + return s.SingleKeyOrdered.AppendNew(Key) +} + +// AppendSingleKeyOrdered appends the supplied Model_SingleKeyOrdered struct +// to the list SingleKeyOrdered of Model. If the key value(s) +// specified in the supplied Model_SingleKeyOrdered already exist in the list, an +// error is returned. +func (s *Model) AppendSingleKeyOrdered(v *Model_SingleKeyOrdered) error { + if s.SingleKeyOrdered == nil { + s.SingleKeyOrdered = &Model_SingleKeyOrdered_OrderedMap{} + } + return s.SingleKeyOrdered.Append(v) +} + +// GetSingleKeyOrdered retrieves the value with the specified key from the +// SingleKeyOrdered map field of Model. If the receiver +// is nil, or the specified key is not present in the list, nil is returned +// such that Get* methods may be safely chained. +func (s *Model) GetSingleKeyOrdered(Key string) *Model_SingleKeyOrdered { + key := Key + return s.SingleKeyOrdered.Get(key) +} + +// DeleteSingleKeyOrdered deletes the value with the specified keys from +// the receiver Model. If there is no such element, the +// function is a no-op. +func (s *Model) DeleteSingleKeyOrdered(Key string) bool { + key := Key + return s.SingleKeyOrdered.Delete(key) +} + +// Model_SingleKeyOrdered_OrderedMap is an ordered map that represents the "ordered-by user" +// list elements at /openconfig-withlist/model/c/single-key-ordered. +type Model_SingleKeyOrdered_OrderedMap struct { + keys []string + valueMap map[string]*Model_SingleKeyOrdered +} + +// IsYANGOrderedList ensures that Model_SingleKeyOrdered_OrderedMap implements the +// ygot.GoOrderedMap interface. +func (*Model_SingleKeyOrdered_OrderedMap) IsYANGOrderedList() {} + +// init initializes any uninitialized values. +func (o *Model_SingleKeyOrdered_OrderedMap) init() { + if o == nil { + return + } + if o.valueMap == nil { + o.valueMap = map[string]*Model_SingleKeyOrdered{} + } +} + +// Keys returns a copy of the list's keys. +func (o *Model_SingleKeyOrdered_OrderedMap) Keys() []string { + if o == nil { + return nil + } + return append([]string{}, o.keys...) +} + +// Values returns the current set of the list's values in order. +func (o *Model_SingleKeyOrdered_OrderedMap) Values() []*Model_SingleKeyOrdered { + if o == nil { + return nil + } + var values []*Model_SingleKeyOrdered + for _, key := range o.keys { + values = append(values, o.valueMap[key]) + } + return values +} + +// Len returns a size of Model_SingleKeyOrdered_OrderedMap +func (o *Model_SingleKeyOrdered_OrderedMap) Len() int { + if o == nil { + return 0 + } + return len(o.keys) +} + +// Get returns the value corresponding to the key. If the key is not found, nil +// is returned. +func (o *Model_SingleKeyOrdered_OrderedMap) Get(key string) *Model_SingleKeyOrdered { + if o == nil { + return nil + } + val, _ := o.valueMap[key] + return val +} + +// Delete deletes an element. +func (o *Model_SingleKeyOrdered_OrderedMap) Delete(key string) bool { + if o == nil { + return false + } + if _, ok := o.valueMap[key]; !ok { + return false + } + for i, k := range o.keys { + if k == key { + o.keys = append(o.keys[:i], o.keys[i+1:]...) + delete(o.valueMap, key) + return true + } + } + return false +} + +// Append appends a Model_SingleKeyOrdered, returning an error if the key +// already exists in the ordered list or if the key is unspecified. +func (o *Model_SingleKeyOrdered_OrderedMap) Append(v *Model_SingleKeyOrdered) error { + if o == nil { + return fmt.Errorf("nil ordered map, cannot append Model_SingleKeyOrdered") + } + if v == nil { + return fmt.Errorf("nil Model_SingleKeyOrdered") + } + if v.Key == nil { + return fmt.Errorf("invalid nil key received for Key") + } + + key := *v.Key + + if _, ok := o.valueMap[key]; ok { + return fmt.Errorf("duplicate key for list Statement %v", key) + } + o.keys = append(o.keys, key) + o.init() + o.valueMap[key] = v + return nil +} + +// AppendNew creates and appends a new Model_SingleKeyOrdered, returning the +// newly-initialized v. It returns an error if the v already exists. +func (o *Model_SingleKeyOrdered_OrderedMap) AppendNew(Key string) (*Model_SingleKeyOrdered, error) { + if o == nil { + return nil, fmt.Errorf("nil ordered map, cannot append Model_SingleKeyOrdered") + } + key := Key + + if _, ok := o.valueMap[key]; ok { + return nil, fmt.Errorf("duplicate key for list Statement %v", key) + } + o.keys = append(o.keys, key) + newElement := &Model_SingleKeyOrdered{ + Key: &Key, + } + o.init() + o.valueMap[key] = newElement + return newElement, nil +} + // ΛBelongingModule returns the name of the module that defines the namespace // of Model. func (*Model) ΛBelongingModule() string { @@ -261,3 +421,30 @@ func (t *Model_SingleKey) ΛListKeyMap() (map[string]interface{}, error) { func (*Model_SingleKey) ΛBelongingModule() string { return "openconfig-withlist" } + +// Model_SingleKeyOrdered represents the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrdered struct { + Key *string `path:"config/key|key" module:"openconfig-withlist/openconfig-withlist|openconfig-withlist"` +} + +// IsYANGGoStruct ensures that Model_SingleKeyOrdered implements the yang.GoStruct +// interface. This allows functions that need to handle this struct to +// identify it as being generated by ygen. +func (*Model_SingleKeyOrdered) IsYANGGoStruct() {} + +// ΛListKeyMap returns the keys of the Model_SingleKeyOrdered struct, which is a YANG list entry. +func (t *Model_SingleKeyOrdered) ΛListKeyMap() (map[string]interface{}, error) { + if t.Key == nil { + return nil, fmt.Errorf("nil value for key Key") + } + + return map[string]interface{}{ + "key": *t.Key, + }, nil +} + +// ΛBelongingModule returns the name of the module that defines the namespace +// of Model_SingleKeyOrdered. +func (*Model_SingleKeyOrdered) ΛBelongingModule() string { + return "openconfig-withlist" +} diff --git a/gogen/unordered_list.go b/gogen/unordered_list.go index 0c1b4c59e..8a9250b0c 100644 --- a/gogen/unordered_list.go +++ b/gogen/unordered_list.go @@ -594,7 +594,7 @@ func UnorderedMapTypeName(listYANGPath, listFieldName, parentName string, goStru // // In the case that the list has multiple keys, the type generated as the key of the list is returned. // If errors are encountered during the type generation for the list, the error is returned. -func yangListFieldToGoType(listField *ygen.NodeDetails, listFieldName string, parent *ygen.ParsedDirectory, goStructElements map[string]*ygen.ParsedDirectory) (string, *generatedGoMultiKeyListStruct, *generatedGoListMethod, *generatedOrderedMapStruct, error) { +func yangListFieldToGoType(listField *ygen.NodeDetails, listFieldName string, parent *ygen.ParsedDirectory, goStructElements map[string]*ygen.ParsedDirectory, generateOrderedMaps bool) (string, *generatedGoMultiKeyListStruct, *generatedGoListMethod, *generatedOrderedMapStruct, error) { // The list itself, since it is a container, has a struct associated with it. Retrieve // this from the set of Directory structs for which code (a Go struct) will be // generated such that additional details can be used in the code generation. @@ -665,7 +665,7 @@ func yangListFieldToGoType(listField *ygen.NodeDetails, listFieldName string, pa var listMethodSpec *generatedGoListMethod var orderedMapSpec *generatedOrderedMapStruct - if listField.YANGDetails.OrderedByUser { + if listField.YANGDetails.OrderedByUser && generateOrderedMaps { structName := OrderedMapTypeName(listElem.Name) listType = fmt.Sprintf("*%s", structName) // Create spec for generating ordered maps. diff --git a/testdata/modules/openconfig-withlist.yang b/testdata/modules/openconfig-withlist.yang index 7004f664a..01a14061e 100644 --- a/testdata/modules/openconfig-withlist.yang +++ b/testdata/modules/openconfig-withlist.yang @@ -66,6 +66,28 @@ module openconfig-withlist { } } } + + container c { + list single-key-ordered { + key "key"; + ordered-by user; + + leaf key { + type leafref { + path "../config/key"; + } + } + + container config { + uses single-key-config; + } + + container state { + config false; + uses single-key-config; + } + } + } } } diff --git a/util/reflect.go b/util/reflect.go index 7141190d7..e2779df6a 100644 --- a/util/reflect.go +++ b/util/reflect.go @@ -610,7 +610,7 @@ func (node *PathQueryNodeMemo) GetRoot() *PathQueryNodeMemo { } // FieldIteratorFunc is an iteration function for arbitrary field traversals. -// in, out are passed through from the caller to the iteration vistior function +// in, out are passed through from the caller to the iteration visitor function // and can be used to pass state in and out. They are not otherwise touched. // It returns a slice of errors encountered while processing the field. type FieldIteratorFunc func(ni *NodeInfo, in, out interface{}) Errors @@ -629,7 +629,7 @@ const ( ) // FieldIteratorFunc2 is an iteration function for arbitrary field traversals. -// in, out are passed through from the caller to the iteration vistior function +// in, out are passed through from the caller to the iteration visitor function // and can be used to pass state in and out. They are not otherwise touched. // It returns what next iteration action to take as well as an error. type FieldIteratorFunc2 func(ni *NodeInfo, in, out any) (IterationAction, Errors) diff --git a/ygot/diff_exported_test.go b/ygot/diff_exported_test.go index 3e3b07d48..6f7298238 100644 --- a/ygot/diff_exported_test.go +++ b/ygot/diff_exported_test.go @@ -42,7 +42,6 @@ func mustPath(s string) *gnmipb.Path { } func TestDiffOrderedMap(t *testing.T) { - // TODO: Test for uncompressed structs. tests := []struct { name string inOrig, inMod ygot.GoStruct @@ -656,9 +655,6 @@ func TestDiffOrderedMap(t *testing.T) { return } - if err != nil { - return - } // To re-use the NotificationSetEqual helper, we put the want and got into // a slice. if !testutil.NotificationSetEqual([]*gnmipb.Notification{got}, []*gnmipb.Notification{tt.want}) { diff --git a/ygot/struct_validation_map_exported_test.go b/ygot/struct_validation_map_exported_test.go index 7ad3fc644..1e3537e85 100644 --- a/ygot/struct_validation_map_exported_test.go +++ b/ygot/struct_validation_map_exported_test.go @@ -118,7 +118,7 @@ func (*mapStructTestFourCOtherSet) ΛBelongingModule() string { r // an enumeration in the YANG schema. type ECTest int64 -// IsYANGEnumeration ensures that the ECTest derived enum type implemnts +// IsYANGEnumeration ensures that the ECTest derived enum type implements // the GoEnum interface. func (ECTest) IsYANGGoEnum() {} diff --git a/ypathgen/pathgen_test.go b/ypathgen/pathgen_test.go index a4363ae85..2ff385424 100644 --- a/ypathgen/pathgen_test.go +++ b/ypathgen/pathgen_test.go @@ -15,7 +15,8 @@ package ypathgen import ( - "io/ioutil" + "flag" + "os" "path/filepath" "strings" "testing" @@ -39,6 +40,8 @@ const ( datapath = "../testdata/modules" ) +var updateGolden = flag.Bool("update_golden", false, "Update golden files") + func TestGeneratePathCode(t *testing.T) { tests := []struct { // Name is the identifier for the test. @@ -974,14 +977,19 @@ func TestGeneratePathCode(t *testing.T) { } } - wantCodeBytes, rferr := ioutil.ReadFile(tt.wantStructsCodeFile) + wantCodeBytes, rferr := os.ReadFile(tt.wantStructsCodeFile) if rferr != nil { - t.Fatalf("ioutil.ReadFile(%q) error: %v", tt.wantStructsCodeFile, rferr) + t.Fatalf("os.ReadFile(%q) error: %v", tt.wantStructsCodeFile, rferr) } wantCode := string(wantCodeBytes) if gotCode != wantCode { + if *updateGolden { + if err := os.WriteFile(tt.wantStructsCodeFile, []byte(gotCode), 0644); err != nil { + t.Fatal(err) + } + } // Use difflib to generate a unified diff between the // two code snippets such that this is simpler to debug // in the test output. @@ -1083,9 +1091,9 @@ func TestGeneratePathCodeSplitFiles(t *testing.T) { var wantCode []string for _, codeFile := range tt.wantStructsCodeFiles { - wantCodeBytes, rferr := ioutil.ReadFile(codeFile) + wantCodeBytes, rferr := os.ReadFile(codeFile) if rferr != nil { - t.Fatalf("ioutil.ReadFile(%q) error: %v", tt.wantStructsCodeFiles, rferr) + t.Fatalf("os.ReadFile(%q) error: %v", tt.wantStructsCodeFiles, rferr) } wantCode = append(wantCode, string(wantCodeBytes)) } @@ -1096,6 +1104,11 @@ func TestGeneratePathCodeSplitFiles(t *testing.T) { } else { for i := range gotCode { if gotCode[i] != wantCode[i] { + if *updateGolden { + if err := os.WriteFile(tt.wantStructsCodeFiles[i], []byte(gotCode[i]), 0644); err != nil { + t.Fatal(err) + } + } // Use difflib to generate a unified diff between the // two code snippets such that this is simpler to debug // in the test output. @@ -1186,9 +1199,9 @@ func TestGeneratePathCodeSplitModules(t *testing.T) { wantCode := map[string]string{} for pkg, codeFile := range tt.wantStructsCodeFiles { - wantCodeBytes, rferr := ioutil.ReadFile(codeFile) + wantCodeBytes, rferr := os.ReadFile(codeFile) if rferr != nil { - t.Fatalf("ioutil.ReadFile(%q) error: %v", tt.wantStructsCodeFiles, rferr) + t.Fatalf("os.ReadFile(%q) error: %v", tt.wantStructsCodeFiles, rferr) } wantCode[pkg] = string(wantCodeBytes) } @@ -1199,6 +1212,11 @@ func TestGeneratePathCodeSplitModules(t *testing.T) { } else { for pkg := range gotCode { if gotCode[pkg] != wantCode[pkg] { + if *updateGolden { + if err := os.WriteFile(tt.wantStructsCodeFiles[pkg], []byte(gotCode[pkg]), 0644); err != nil { + t.Fatal(err) + } + } // Use difflib to generate a unified diff between the // two code snippets such that this is simpler to debug // in the test output. diff --git a/ypathgen/testdata/modules/oc-list/list.txt b/ypathgen/testdata/modules/oc-list/list.txt index ee3f05d5d..04ac6853b 100644 --- a/ypathgen/testdata/modules/oc-list/list.txt +++ b/ypathgen/testdata/modules/oc-list/list.txt @@ -109,6 +109,45 @@ func (n *Model_SingleKeyPathAny) WithKey(Key string) *Model_SingleKeyPathAny { return n } +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +func (n *ModelPath) SingleKeyOrderedAny() *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": "*"}, + n, + ), + } +} + +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +func (n *ModelPathAny) SingleKeyOrderedAny() *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": "*"}, + n, + ), + } +} + +// WithKey sets Model_SingleKeyOrderedPathAny's key "key" to the specified value. +// Key: string +func (n *Model_SingleKeyOrderedPathAny) WithKey(Key string) *Model_SingleKeyOrderedPathAny { + ygot.ModifyKey(n.NodePath, "key", Key) + return n +} + // Model_MultiKeyPath represents the /openconfig-withlist/model/b/multi-key YANG schema element. type Model_MultiKeyPath struct { *ygot.NodePath @@ -254,3 +293,55 @@ func (n *Model_SingleKeyPathAny) Key() *Model_SingleKey_KeyPathAny { ), } } + +// Model_SingleKeyOrderedPath represents the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedPath struct { + *ygot.NodePath +} + +// Model_SingleKeyOrderedPathAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedPathAny struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyPath represents the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyPath struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyPathAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyPathAny struct { + *ygot.NodePath +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedPath) Key() *Model_SingleKeyOrdered_KeyPath { + return &Model_SingleKeyOrdered_KeyPath{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedPathAny) Key() *Model_SingleKeyOrdered_KeyPathAny { + return &Model_SingleKeyOrdered_KeyPathAny{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} diff --git a/ypathgen/testdata/structs/openconfig-withlist-separate-package.path-txt b/ypathgen/testdata/structs/openconfig-withlist-separate-package.path-txt index 510831d51..e34d17304 100644 --- a/ypathgen/testdata/structs/openconfig-withlist-separate-package.path-txt +++ b/ypathgen/testdata/structs/openconfig-withlist-separate-package.path-txt @@ -263,6 +263,74 @@ func (n *ModelAny) SingleKey(Key string) *Model_SingleKeyAny { } } +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key (wildcarded): string +func (n *Model) SingleKeyOrderedAny() *Model_SingleKeyOrderedAny { + return &Model_SingleKeyOrderedAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": "*"}, + n, + ), + } +} + +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key (wildcarded): string +func (n *ModelAny) SingleKeyOrderedAny() *Model_SingleKeyOrderedAny { + return &Model_SingleKeyOrderedAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": "*"}, + n, + ), + } +} + +// SingleKeyOrdered (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key: string +func (n *Model) SingleKeyOrdered(Key string) *Model_SingleKeyOrdered { + return &Model_SingleKeyOrdered{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": Key}, + n, + ), + } +} + +// SingleKeyOrdered (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key: string +func (n *ModelAny) SingleKeyOrdered(Key string) *Model_SingleKeyOrderedAny { + return &Model_SingleKeyOrderedAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": Key}, + n, + ), + } +} + // Model_MultiKey represents the /openconfig-withlist/model/b/multi-key YANG schema element. type Model_MultiKey struct { *ygot.NodePath @@ -408,3 +476,55 @@ func (n *Model_SingleKeyAny) Key() *Model_SingleKey_KeyAny { ), } } + +// Model_SingleKeyOrdered represents the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrdered struct { + *ygot.NodePath +} + +// Model_SingleKeyOrderedAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedAny struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_Key represents the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_Key struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyAny struct { + *ygot.NodePath +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrdered) Key() *Model_SingleKeyOrdered_Key { + return &Model_SingleKeyOrdered_Key{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedAny) Key() *Model_SingleKeyOrdered_KeyAny { + return &Model_SingleKeyOrdered_KeyAny{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} diff --git a/ypathgen/testdata/structs/openconfig-withlist.builder.path-txt b/ypathgen/testdata/structs/openconfig-withlist.builder.path-txt index 203a6e212..109dfcbcd 100644 --- a/ypathgen/testdata/structs/openconfig-withlist.builder.path-txt +++ b/ypathgen/testdata/structs/openconfig-withlist.builder.path-txt @@ -164,6 +164,74 @@ func (n *ModelPathAny) SingleKey(Key string) *Model_SingleKeyPathAny { } } +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key (wildcarded): string +func (n *ModelPath) SingleKeyOrderedAny() *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": "*"}, + n, + ), + } +} + +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key (wildcarded): string +func (n *ModelPathAny) SingleKeyOrderedAny() *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": "*"}, + n, + ), + } +} + +// SingleKeyOrdered (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key: string +func (n *ModelPath) SingleKeyOrdered(Key string) *Model_SingleKeyOrderedPath { + return &Model_SingleKeyOrderedPath{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": Key}, + n, + ), + } +} + +// SingleKeyOrdered (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key: string +func (n *ModelPathAny) SingleKeyOrdered(Key string) *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": Key}, + n, + ), + } +} + // Model_MultiKeyPath represents the /openconfig-withlist/model/b/multi-key YANG schema element. type Model_MultiKeyPath struct { *ygot.NodePath @@ -309,3 +377,55 @@ func (n *Model_SingleKeyPathAny) Key() *Model_SingleKey_KeyPathAny { ), } } + +// Model_SingleKeyOrderedPath represents the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedPath struct { + *ygot.NodePath +} + +// Model_SingleKeyOrderedPathAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedPathAny struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyPath represents the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyPath struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyPathAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyPathAny struct { + *ygot.NodePath +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedPath) Key() *Model_SingleKeyOrdered_KeyPath { + return &Model_SingleKeyOrdered_KeyPath{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedPathAny) Key() *Model_SingleKeyOrdered_KeyPathAny { + return &Model_SingleKeyOrdered_KeyPathAny{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} diff --git a/ypathgen/testdata/structs/openconfig-withlist.nowildcard.path-txt b/ypathgen/testdata/structs/openconfig-withlist.nowildcard.path-txt index 13f2b1687..b5903a333 100644 --- a/ypathgen/testdata/structs/openconfig-withlist.nowildcard.path-txt +++ b/ypathgen/testdata/structs/openconfig-withlist.nowildcard.path-txt @@ -80,6 +80,23 @@ func (n *ModelPath) SingleKey(Key string) *Model_SingleKeyPath { } } +// SingleKeyOrdered (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key: string +func (n *ModelPath) SingleKeyOrdered(Key string) *Model_SingleKeyOrderedPath { + return &Model_SingleKeyOrderedPath{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": Key}, + n, + ), + } +} + // Model_MultiKeyPath represents the /openconfig-withlist/model/b/multi-key YANG schema element. type Model_MultiKeyPath struct { *ygot.NodePath @@ -152,3 +169,29 @@ func (n *Model_SingleKeyPath) Key() *Model_SingleKey_KeyPath { ), } } + +// Model_SingleKeyOrderedPath represents the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedPath struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyPath represents the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyPath struct { + *ygot.NodePath +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedPath) Key() *Model_SingleKeyOrdered_KeyPath { + return &Model_SingleKeyOrdered_KeyPath{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} diff --git a/ypathgen/testdata/structs/openconfig-withlist.path-txt b/ypathgen/testdata/structs/openconfig-withlist.path-txt index 4efa99e77..a4459eb24 100644 --- a/ypathgen/testdata/structs/openconfig-withlist.path-txt +++ b/ypathgen/testdata/structs/openconfig-withlist.path-txt @@ -262,6 +262,74 @@ func (n *ModelPathAny) SingleKey(Key string) *Model_SingleKeyPathAny { } } +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key (wildcarded): string +func (n *ModelPath) SingleKeyOrderedAny() *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": "*"}, + n, + ), + } +} + +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key (wildcarded): string +func (n *ModelPathAny) SingleKeyOrderedAny() *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": "*"}, + n, + ), + } +} + +// SingleKeyOrdered (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key: string +func (n *ModelPath) SingleKeyOrdered(Key string) *Model_SingleKeyOrderedPath { + return &Model_SingleKeyOrderedPath{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": Key}, + n, + ), + } +} + +// SingleKeyOrdered (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key: string +func (n *ModelPathAny) SingleKeyOrdered(Key string) *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": Key}, + n, + ), + } +} + // Model_MultiKeyPath represents the /openconfig-withlist/model/b/multi-key YANG schema element. type Model_MultiKeyPath struct { *ygot.NodePath @@ -407,3 +475,55 @@ func (n *Model_SingleKeyPathAny) Key() *Model_SingleKey_KeyPathAny { ), } } + +// Model_SingleKeyOrderedPath represents the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedPath struct { + *ygot.NodePath +} + +// Model_SingleKeyOrderedPathAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedPathAny struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyPath represents the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyPath struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyPathAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyPathAny struct { + *ygot.NodePath +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedPath) Key() *Model_SingleKeyOrdered_KeyPath { + return &Model_SingleKeyOrdered_KeyPath{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedPathAny) Key() *Model_SingleKeyOrdered_KeyPathAny { + return &Model_SingleKeyOrdered_KeyPathAny{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} diff --git a/ypathgen/testdata/structs/openconfig-withlist.simplifyallwc.path-txt b/ypathgen/testdata/structs/openconfig-withlist.simplifyallwc.path-txt index 521ee5909..2c7965206 100644 --- a/ypathgen/testdata/structs/openconfig-withlist.simplifyallwc.path-txt +++ b/ypathgen/testdata/structs/openconfig-withlist.simplifyallwc.path-txt @@ -262,6 +262,74 @@ func (n *ModelPathAny) SingleKey(Key string) *Model_SingleKeyPathAny { } } +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key (wildcarded): string +func (n *ModelPath) SingleKeyOrderedAny() *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{}, + n, + ), + } +} + +// SingleKeyOrderedAny (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key (wildcarded): string +func (n *ModelPathAny) SingleKeyOrderedAny() *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{}, + n, + ), + } +} + +// SingleKeyOrdered (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key: string +func (n *ModelPath) SingleKeyOrdered(Key string) *Model_SingleKeyOrderedPath { + return &Model_SingleKeyOrderedPath{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": Key}, + n, + ), + } +} + +// SingleKeyOrdered (list): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "c/single-key-ordered" +// Path from root: "/model/c/single-key-ordered" +// Key: string +func (n *ModelPathAny) SingleKeyOrdered(Key string) *Model_SingleKeyOrderedPathAny { + return &Model_SingleKeyOrderedPathAny{ + NodePath: ygot.NewNodePath( + []string{"c", "single-key-ordered"}, + map[string]interface{}{"key": Key}, + n, + ), + } +} + // Model_MultiKeyPath represents the /openconfig-withlist/model/b/multi-key YANG schema element. type Model_MultiKeyPath struct { *ygot.NodePath @@ -407,3 +475,55 @@ func (n *Model_SingleKeyPathAny) Key() *Model_SingleKey_KeyPathAny { ), } } + +// Model_SingleKeyOrderedPath represents the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedPath struct { + *ygot.NodePath +} + +// Model_SingleKeyOrderedPathAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered YANG schema element. +type Model_SingleKeyOrderedPathAny struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyPath represents the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyPath struct { + *ygot.NodePath +} + +// Model_SingleKeyOrdered_KeyPathAny represents the wildcard version of the /openconfig-withlist/model/c/single-key-ordered/state/key YANG schema element. +type Model_SingleKeyOrdered_KeyPathAny struct { + *ygot.NodePath +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedPath) Key() *Model_SingleKeyOrdered_KeyPath { + return &Model_SingleKeyOrdered_KeyPath{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +} + +// Key (leaf): +// ---------------------------------------- +// Defining module: "openconfig-withlist" +// Instantiating module: "openconfig-withlist" +// Path from parent: "state/key" +// Path from root: "/model/c/single-key-ordered/state/key" +func (n *Model_SingleKeyOrderedPathAny) Key() *Model_SingleKeyOrdered_KeyPathAny { + return &Model_SingleKeyOrdered_KeyPathAny{ + NodePath: ygot.NewNodePath( + []string{"state", "key"}, + map[string]interface{}{}, + n, + ), + } +}