Avoid module namespace/submodule name conflict when using lib sources 34/63034/2
authorIgor Foltin <igor.foltin@pantheon.tech>
Tue, 12 Sep 2017 12:34:12 +0000 (14:34 +0200)
committerRobert Varga <nite@hq.sk>
Wed, 13 Sep 2017 08:48:07 +0000 (08:48 +0000)
The issue comes up when using yang-system-test artifact as a single
YANG file validator:

A parent module or a submodule is specified as its argument
and the same directory is specified as one of the library dirs
using the -p option.

The parent module/submodule ends up being added twice to the parsed
sources which causes a module namespace/submodule name collision later
in the parsing process.

Therefore remove the conflicting lib sources from the collection of
required lib sources before they cause any trouble.

Change-Id: Id41d9f57006adec7ff658904792f9bc319b8c11e
Signed-off-by: Igor Foltin <igor.foltin@pantheon.tech>
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug7480Test.java
yang/yang-parser-impl/src/test/resources/bugs/bug7480/main-source-lib-source-conflict-test/child-module.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug7480/main-source-lib-source-conflict-test/parent-module.yang [new file with mode: 0644]

index 3e77b2cd4603935e460b46227fac5d65f1c9e4a6..156fbe8c7cedd5a181584083bfd03a9eb1b78466 100644 (file)
@@ -427,6 +427,7 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh
         final Set<SourceSpecificContext> requiredLibs = new HashSet<>();
         for (final SourceSpecificContext source : sources) {
             collectRequiredSourcesFromLib(libSourcesTable, requiredLibs, source);
+            removeConflictingLibSources(source, requiredLibs);
         }
         return requiredLibs;
     }
@@ -455,6 +456,22 @@ class BuildGlobalContext extends NamespaceStorageSupport implements NamespaceBeh
         return sourceMap != null && !sourceMap.isEmpty() ? sourceMap.get(sourceMap.lastKey()) : null;
     }
 
+    // removes required library sources which would cause namespace/name conflict with one of the main sources
+    // later in the parsing process. this can happen if we add a parent module or a submodule as a main source
+    // and the same parent module or submodule is added as one of the library sources.
+    // such situation may occur when using the yang-system-test artifact - if a parent module/submodule is specified
+    // as its argument and the same dir is specified as one of the library dirs through -p option).
+    private static void removeConflictingLibSources(final SourceSpecificContext source,
+            final Set<SourceSpecificContext> requiredLibs) {
+        final Iterator<SourceSpecificContext> requiredLibsIter = requiredLibs.iterator();
+        while (requiredLibsIter.hasNext()) {
+            final SourceSpecificContext currentReqSource = requiredLibsIter.next();
+            if (source.getRootIdentifier().equals(currentReqSource.getRootIdentifier())) {
+                requiredLibsIter.remove();
+            }
+        }
+    }
+
     private void endPhase(final ModelProcessingPhase phase) {
         Preconditions.checkState(currentPhase == phase);
         finishedPhase = currentPhase;
index 1c393dba8ea75b82c81a965a5923c395c708197e..3384c5902982da99a76d6e812756c28c3d92b5e7 100644 (file)
@@ -19,6 +19,8 @@ import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
 
 public class Bug7480Test {
     @Test
@@ -59,4 +61,34 @@ public class Bug7480Test {
             assertTrue(message.startsWith("Imported module [missing-lib] was not found."));
         }
     }
+
+    @Test
+    public void testHandlingOfMainSourceConflictingWithLibSource() throws Exception {
+        // parent module as main source and as lib source at the same time
+        // parser should remove it from the required lib sources and thus avoid module namespace collision
+        final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+        reactor.addSource(StmtTestUtils.sourceForResource(
+                "/bugs/bug7480/main-source-lib-source-conflict-test/parent-module.yang"));
+        reactor.addLibSources(StmtTestUtils.sourceForResource(
+                "/bugs/bug7480/main-source-lib-source-conflict-test/child-module.yang"),
+                StmtTestUtils.sourceForResource(
+                        "/bugs/bug7480/main-source-lib-source-conflict-test/parent-module.yang"));
+        final SchemaContext schemaContext = reactor.buildEffective();
+        assertNotNull(schemaContext);
+    }
+
+    @Test
+    public void testHandlingOfMainSourceConflictingWithLibSource2() throws Exception {
+        // submodule as main source and as lib source at the same time
+        // parser should remove it from the required lib sources and thus avoid submodule name collision
+        final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+        reactor.addSource(StmtTestUtils.sourceForResource(
+                "/bugs/bug7480/main-source-lib-source-conflict-test/child-module.yang"));
+        reactor.addLibSources(StmtTestUtils.sourceForResource(
+                "/bugs/bug7480/main-source-lib-source-conflict-test/parent-module.yang"),
+                StmtTestUtils.sourceForResource(
+                        "/bugs/bug7480/main-source-lib-source-conflict-test/child-module.yang"));
+        final SchemaContext schemaContext = reactor.buildEffective();
+        assertNotNull(schemaContext);
+    }
 }
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug7480/main-source-lib-source-conflict-test/child-module.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug7480/main-source-lib-source-conflict-test/child-module.yang
new file mode 100644 (file)
index 0000000..10c1e21
--- /dev/null
@@ -0,0 +1,7 @@
+submodule child-module {
+    belongs-to parent-module {
+        prefix pm;
+    }
+
+    container child-mod-cont {}
+}
\ No newline at end of file
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug7480/main-source-lib-source-conflict-test/parent-module.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug7480/main-source-lib-source-conflict-test/parent-module.yang
new file mode 100644 (file)
index 0000000..677cb02
--- /dev/null
@@ -0,0 +1,8 @@
+module parent-module {
+    namespace pm-ns;
+    prefix pm;
+
+    include child-module;
+
+    container parent-mod-cont {}
+}
\ No newline at end of file