Do not use substatements in StmtContextUtils.getRootModuleQName() 34/102134/1
authorSangwook Ha <sangwook.ha@verizon.com>
Tue, 7 Jun 2022 21:12:36 +0000 (14:12 -0700)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 17 Aug 2022 13:42:40 +0000 (15:42 +0200)
Building effective model fails when a grouping in a submodule
is augmented from another submodule or the unique statement points
to a leaf in a grouping from another submodule.

Add test cases to reproduce the issues, which points to us accessing
substatements of submodules after all references have been resolved.

Since we already rely on SOURCE_LINKAGE being complete in this method
(e.g. ModuleCtxToModuleQName being populated), switch from using
statement enumeration to also using the BelongsToPrefixToModuleCtx
namespace, which resolved during that same phase.

JIRA: YANGTOOLS-1436
Change-Id: I71eb1122bf7c3820043a3197249a3b2fba6e9e8c
Signed-off-by: Sangwook Ha <sangwook.ha@verizon.com>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 30f4e375338124bbb66d2bf1e1c65d0968fd1f0e)

parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1436Test.java [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/augment/foo-a.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/augment/foo-b.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/augment/foo.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/unique/bar-a.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/unique/bar-b.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/unique/bar.yang [new file with mode: 0644]
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java

diff --git a/parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1436Test.java b/parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1436Test.java
new file mode 100644 (file)
index 0000000..ee4bf1e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022 Verizon and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.stmt;
+
+import org.junit.Test;
+
+public class YT1436Test extends AbstractYangTest {
+    @Test
+    public void testUniqueLeafFromOtherSubmodule() {
+        assertEffectiveModelDir("/bugs/YT1436/unique");
+    }
+
+    @Test
+    public void testAugmentGroupingFromOtherSubmodule() {
+        assertEffectiveModelDir("/bugs/YT1436/augment");
+    }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/augment/foo-a.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/augment/foo-a.yang
new file mode 100644 (file)
index 0000000..1131344
--- /dev/null
@@ -0,0 +1,13 @@
+submodule foo-a {
+  belongs-to foo {
+    prefix "foo";
+  }
+
+  grouping foo-a {
+    container a {
+      leaf a1 {
+        type string;
+      }
+    }
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/augment/foo-b.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/augment/foo-b.yang
new file mode 100644 (file)
index 0000000..71b0d38
--- /dev/null
@@ -0,0 +1,17 @@
+submodule foo-b {
+  belongs-to foo {
+    prefix "foo";
+  }
+
+  include foo-a;
+
+  grouping foo-b {
+    uses foo-a {
+      augment a {
+        leaf b1 {
+          type string;
+        }
+      }
+    }
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/augment/foo.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/augment/foo.yang
new file mode 100644 (file)
index 0000000..b30e110
--- /dev/null
@@ -0,0 +1,11 @@
+module foo {
+  namespace "urn:foo";
+  prefix "foo";
+
+  include foo-a;
+  include foo-b;
+
+  container foo {
+    uses foo-b;
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/unique/bar-a.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/unique/bar-a.yang
new file mode 100644 (file)
index 0000000..05f637b
--- /dev/null
@@ -0,0 +1,11 @@
+submodule bar-a {
+  belongs-to bar {
+    prefix "bar";
+  }
+
+  grouping bar-a {
+    leaf a1 {
+      type string;
+    }
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/unique/bar-b.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/unique/bar-b.yang
new file mode 100644 (file)
index 0000000..6dc5600
--- /dev/null
@@ -0,0 +1,19 @@
+submodule bar-b {
+  belongs-to bar {
+    prefix "bar";
+  }
+
+  include bar-a;
+
+  grouping bar-b {
+    list b {
+      key b1;
+      unique a1;
+
+      uses bar-a;
+      leaf b1 {
+        type string;
+      }
+    }
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/unique/bar.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1436/unique/bar.yang
new file mode 100644 (file)
index 0000000..e983a6e
--- /dev/null
@@ -0,0 +1,11 @@
+module bar {
+  namespace "urn:bar";
+  prefix "bar";
+
+  include bar-a;
+  include bar-b;
+
+  container bar {
+    uses bar-b;
+  }
+}
index b2b47ad8db369bee2e300232724ae50769a1d66c..fa7c07842a75ca4cc0abf3ef7c51ee597436ac84 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.parser.spi.meta;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.base.Strings;
@@ -27,7 +26,6 @@ import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
-import org.opendaylight.yangtools.yang.model.api.stmt.BelongsToStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.KeyStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
@@ -42,6 +40,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Infere
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
+import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleCtx;
 import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleName;
 import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToModuleCtx;
 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
@@ -551,21 +550,26 @@ public final class StmtContextUtils {
             return null;
         }
 
-        final StmtContext<?, ?, ?> rootCtx = ctx.getRoot();
-        final QNameModule qnameModule;
-
+        final var rootCtx = ctx.getRoot();
         if (rootCtx.producesDeclared(ModuleStatement.class)) {
-            qnameModule = rootCtx.getFromNamespace(ModuleCtxToModuleQName.class, rootCtx);
+            return lookupModuleQName(rootCtx, rootCtx);
         } else if (rootCtx.producesDeclared(SubmoduleStatement.class)) {
-            final String belongsToModuleName = firstAttributeOf(rootCtx.declaredSubstatements(),
-                BelongsToStatement.class);
-            qnameModule = rootCtx.getFromNamespace(ModuleNameToModuleQName.class, belongsToModuleName);
+            final var belongsTo = rootCtx.getAllFromNamespace(BelongsToPrefixToModuleCtx.class);
+            if (belongsTo == null || belongsTo.isEmpty()) {
+                throw new IllegalArgumentException(rootCtx + " does not have belongs-to linkage resolved");
+            }
+            return lookupModuleQName(rootCtx, belongsTo.values().iterator().next());
         } else {
-            qnameModule = null;
+            throw new IllegalArgumentException("Unsupported root " + rootCtx);
         }
+    }
 
-        checkArgument(qnameModule != null, "Failed to look up root QNameModule for %s", ctx);
-        return qnameModule;
+    private static QNameModule lookupModuleQName(final NamespaceStmtCtx storage, final StmtContext<?, ?, ?> module) {
+        final var ret = storage.getFromNamespace(ModuleCtxToModuleQName.class, module);
+        if (ret == null) {
+            throw new IllegalArgumentException("Failed to look up QNameModule for " + module + " in " + storage);
+        }
+        return ret;
     }
 
     public static QNameModule getModuleQNameByPrefix(final StmtContext<?, ?, ?> ctx, final String prefix) {