Closed hansthienpondt closed 2 years ago
Thanks for this - I suspect this is the confluence of uncompressed schema generation, and leafref
validation. @wenovus - might you have a moment to look at this at some point?
I think the fix is essentially correct: we handle the case of lists (a single level in YANG) being represented as two levels in Go (map -> element), but don't handle the case of leaf-lists also being represented as two levels in Go (slice -> element). The "two levels" is how ForEachField
processes elements, which creates this corner case for DataNodeAtPath
.
It turns out we already had a test case for this but it had an extra "../" so it was testing the wrong behaviour.
I made the fixes to the testcase and everything in ygot looks to be passing:
diff --git a/ytypes/leafref.go b/ytypes/leafref.go
index 1e0e67e..07b0c6b 100644
--- a/ytypes/leafref.go
+++ b/ytypes/leafref.go
@@ -189,7 +189,7 @@ func dataNodesAtPath(ni *util.NodeInfo, path *gpb.Path, pathQueryNode *util.Path
if root.Parent == nil {
return nil, fmt.Errorf("no parent for leafref path at %v, with remaining path %s", ni.Schema.Path(), path)
}
- if !util.IsCompressedSchema(root.Schema) && root.Parent.Schema.IsList() && util.IsValueMap(root.Parent.FieldValue) {
+ if !util.IsCompressedSchema(root.Schema) && ((root.Parent.Schema.IsList() && util.IsValueMap(root.Parent.FieldValue)) || (root.Parent.Schema.IsLeafList() && util.IsValueSlice(root.Parent.FieldValue))) {
// If we are in an uncompressed schema, then we have one more level of the data tree than
// the YANG expects, since our data tree layout is:
// struct (parent container)
diff --git a/ytypes/leafref_test.go b/ytypes/leafref_test.go
index 6c342a4..23c3ebc 100644
--- a/ytypes/leafref_test.go
+++ b/ytypes/leafref_test.go
@@ -152,7 +152,7 @@ func TestValidateLeafRefData(t *testing.T) {
Kind: yang.LeafEntry,
Type: &yang.YangType{
Kind: yang.Yleafref,
- Path: "../../../leaf-list",
+ Path: "../../leaf-list",
},
ListAttr: yang.NewDefaultListAttr(),
},
@@ -336,7 +336,7 @@ func TestValidateLeafRefData(t *testing.T) {
LeafList: []*int32{Int32(40), Int32(41), Int32(42)},
Container2: &Container2{LeafListRefToLeafList: []*int32{Int32(41), Int32(42), Int32(43)}},
},
- wantErr: `field name LeafListRefToLeafList value 43 (int32 ptr) schema path /leaf-list-ref-to-leaf-list has leafref path ../../../leaf-list not equal to any target nodes`,
+ wantErr: `field name LeafListRefToLeafList value 43 (int32 ptr) schema path /leaf-list-ref-to-leaf-list has leafref path ../../leaf-list not equal to any target nodes`,
},
{
desc: "keyed list match",
@hansthienpondt I think we're ready for a PR for this fix.
Hi,
Considering the following yang model, validation fails with following debugLibrary output:
I've used following generator args, ygot v0.15.1:
I suspect it's related to ytypes/leafref.go.
I've implemented a dirty workaround, but considering it's a breaking change, reaching out for help as I don't know the codebase well enough yet.