Validate cross-revision imports and includes 97/97697/11
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 1 Oct 2021 13:37:27 +0000 (15:37 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 5 Oct 2021 12:06:14 +0000 (14:06 +0200)
We are not performing no YANG version validation during include/import
linkage. RFC7950 section 12 specifically forbids a number of cases which
are invalid. Make sure we are enforcing them.

This flushes out a few violations in our test suite, which is also
updated.

JIRA: YANGTOOLS-1339
Change-Id: I7799f08291f9ffc9646b19922af512e28a2c7589
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
35 files changed:
model/yang-model-export/src/test/resources/bugs/bug2444/yang/submodule.yang
model/yang-model-export/src/test/resources/bugs/bug2444/yin/submodule.yin
parser/rfc8040-parser-support/src/test/resources/yang-data-extension-test/bar.yang
parser/rfc8040-parser-support/src/test/resources/yang-data-extension-test/baz.yang
parser/rfc8040-parser-support/src/test/resources/yang-data-extension-test/foo-invalid-1.yang
parser/rfc8040-parser-support/src/test/resources/yang-data-extension-test/foo-invalid-2.yang
parser/rfc8040-parser-support/src/test/resources/yang-data-extension-test/foo-invalid-3.yang
parser/rfc8040-parser-support/src/test/resources/yang-data-extension-test/foo.yang
parser/rfc8040-parser-support/src/test/resources/yang-data-extension-test/foobar.yang
parser/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/YT1193Test.java
parser/yang-parser-impl/src/test/resources/yt1193/baz.yang
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/import_/ImportStatementSupport.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/IncludeStatementSupport.java
parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1339Test.java [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1262/bar.yang
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-norev/new.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-norev/old.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-norev/sub.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev-sub/new.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev-sub/old.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev-sub/sub.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev/new.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev/old.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import/new.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import/old.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import/sub.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/new-sub/mod.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/new-sub/sub.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/old-sub/mod.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/old-sub/sub.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/bug7480/files/foo.yang
parser/yang-parser-rfc7950/src/test/resources/bugs/bug7480/lib/lib-1.yang
parser/yang-parser-rfc7950/src/test/resources/deviation-resolution-test/deviation-replace/foo.yang
parser/yang-parser-rfc7950/src/test/resources/rfc7950/include-import-stmt-test/invalid-import-10/import-test-root.yang
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/YangVersionLinkageException.java [new file with mode: 0644]

index 1347d6799faaa870633efd60700175575c9d6d54..44b64967c896a5b02afb761035b69ec40f0f005e 100644 (file)
@@ -1,4 +1,6 @@
 submodule submodule {
+    yang-version 1.1;
+
     belongs-to include {
         prefix incl;
     }
index 7be82fb8eae46284f1dc6c99189e0eb923dbfdab..6f9b39db01bacb4a1b58f2613a432e56ca75f34e 100644 (file)
@@ -1,5 +1,6 @@
 <submodule name="submodule" xmlns="urn:ietf:params:xml:ns:yang:yin:1"
     xmlns:incl="include">
+    <yang-version value="1.1"/>
     <belongs-to module="include">
         <prefix value="incl" />
     </belongs-to>
index 2fe429872873252eb7c6e9fc3e744b42c8e8e020..5e8b9cbe9602f1b6c2f3b82f0381082c92e3ce6e 100644 (file)
@@ -4,7 +4,6 @@ module bar {
 
     import ietf-restconf {
         prefix rc;
-        revision-date 2017-01-26;
     }
 
     revision 2017-06-01;
@@ -17,4 +16,4 @@ module bar {
             container another-top-level-cont {}
         }
     }
-}
\ No newline at end of file
+}
index f4835844d89ccc87289ec8efbeff3774468f117a..d56d796b9880d5462f7dff832f428309e05e5593 100644 (file)
@@ -4,7 +4,6 @@ module baz {
 
     import ietf-restconf {
         prefix rc;
-        revision-date 2017-01-26;
     }
 
     revision 2017-06-01;
@@ -26,4 +25,4 @@ module baz {
             config false;
         }
     }
-}
\ No newline at end of file
+}
index b56ac4d21d7c494b4d3b63a082a59359c7a4a457..00c66ed733ba87e9bc8e71ab3eb4fcc28d7364a9 100644 (file)
@@ -4,7 +4,6 @@ module foo {
 
     import ietf-restconf {
         prefix rc;
-        revision-date 2017-01-26;
     }
 
     revision 2017-06-01;
@@ -12,4 +11,4 @@ module foo {
     rc:yang-data "my-yang-data" {
         // missing top level container = should throw an exception
     }
-}
\ No newline at end of file
+}
index 33eb4e1590fc249eb01fbd55541d00240ab2d44d..f4e50dede561c3f05ff43ca182a703a9db297d2b 100644 (file)
@@ -4,7 +4,6 @@ module foo {
 
     import ietf-restconf {
         prefix rc;
-        revision-date 2017-01-26;
     }
 
     revision 2017-06-01;
@@ -22,4 +21,4 @@ module foo {
     grouping grp-2 {
         container cont-2 {}
     }
-}
\ No newline at end of file
+}
index 98ae30fb36eb5112685338a39133a3fc0c8e32b1..0242770a19cbf0ba63ecd7f9c6e44c329c73b55b 100644 (file)
@@ -4,7 +4,6 @@ module foo {
 
     import ietf-restconf {
         prefix rc;
-        revision-date 2017-01-26;
     }
 
     revision 2017-06-01;
@@ -15,4 +14,4 @@ module foo {
             type string;
         }
     }
-}
\ No newline at end of file
+}
index 250cb3a8345668596b9a2dae4e86d81a0dbc0d00..1db6599d2d0b6dbd0759ccb4ff2e328d4ff9e1e8 100644 (file)
@@ -4,7 +4,6 @@ module foo {
 
     import ietf-restconf {
         prefix rc;
-        revision-date 2017-01-26;
     }
 
     revision 2017-06-01;
@@ -20,4 +19,4 @@ module foo {
     grouping grp {
         container grp-cont {}
     }
-}
\ No newline at end of file
+}
index 8d34f0724012c149471e808c40a5e606a66bbff9..4042ed71b2eb0b3dec258daa1de3cbcf8c7a297f 100644 (file)
@@ -4,7 +4,6 @@ module foobar {
 
     import ietf-restconf {
         prefix rc;
-        revision-date 2017-01-26;
     }
 
     revision 2017-06-01;
index 2164fd3a77c8e7e53cbbd1e0e4097ef70afa5aeb..7e4ff36001cca541e566df7f0ac7e561b56ac97b 100644 (file)
@@ -119,8 +119,9 @@ public class YT1193Test {
         assertReference(baz, YangStmtMapping.SUBMODULE, 1, 1);
 
         final Iterator<? extends DeclaredStatement<?>> it = baz.declaredSubstatements().iterator();
-        assertReference(it.next(), YangStmtMapping.BELONGS_TO, 2, 3);
-        assertReference(it.next(), YangStmtMapping.EXTENSION, 6, 3);
+        assertReference(it.next(), YangStmtMapping.YANG_VERSION, 2, 3);
+        assertReference(it.next(), YangStmtMapping.BELONGS_TO, 4, 3);
+        assertReference(it.next(), YangStmtMapping.EXTENSION, 8, 3);
         assertFalse(it.hasNext());
     }
 
index 187b5d07f1958430fad5a2a3be7ff98b01c8b8b2..7aded5aee62e6e1030e266aeb9ff717245a39009 100644 (file)
@@ -1,4 +1,6 @@
 submodule baz {
+  yang-version 1.1;
+
   belongs-to bar {
     prefix bar;
   }
index 0ec75ec6ad323cf18008b5ec78723c5d3ffb68a9..39c3930feb569dd02af19d499cd5c6b9f19dd1f0 100644 (file)
@@ -19,6 +19,7 @@ import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.openconfig.model.api.OpenConfigStatements;
 import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.XMLNamespace;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
@@ -26,6 +27,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ImportEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ImportStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatementDecorators;
 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatements;
 import org.opendaylight.yangtools.yang.model.ri.stmt.EffectiveStatements;
@@ -45,6 +47,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.spi.source.YangVersionLinkageException;
 
 @Beta
 public final class ImportStatementSupport
@@ -86,13 +89,14 @@ public final class ImportStatementSupport
          * Based on this information, required modules are searched from library
          * sources.
          */
-        stmt.addRequiredSource(RevisionImport.getImportedSourceIdentifier(stmt));
+        final SourceIdentifier importId = RevisionImport.getImportedSourceIdentifier(stmt);
+        stmt.addRequiredSource(importId);
 
         final String moduleName = stmt.getArgument();
         final ModelActionBuilder importAction = stmt.newInferenceAction(SOURCE_PRE_LINKAGE);
         final Prerequisite<StmtContext<?, ?, ?>> imported = importAction.requiresCtx(stmt,
                 PreLinkageModuleNamespace.class, moduleName, SOURCE_PRE_LINKAGE);
-        importAction.mutatesCtx(stmt.getRoot(), SOURCE_PRE_LINKAGE);
+        final Prerequisite<Mutable<?, ?, ?>> rootPrereq = importAction.mutatesCtx(stmt.getRoot(), SOURCE_PRE_LINKAGE);
 
         importAction.apply(new InferenceAction() {
             @Override
@@ -105,6 +109,16 @@ public final class ImportStatementSupport
                     firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class), stmt,
                     "Missing prefix statement");
 
+                final Mutable<?, ?, ?> root = rootPrereq.resolve(ctx);
+                // Version 1 sources must not import-by-revision Version 1.1 modules
+                if (importId.getRevision().isPresent() && root.yangVersion() == YangVersion.VERSION_1) {
+                    final YangVersion importedVersion = importedModuleContext.yangVersion();
+                    if (importedVersion != YangVersion.VERSION_1) {
+                        throw new YangVersionLinkageException(stmt,
+                            "Cannot import by revision version %s module %s", importedVersion, moduleName);
+                    }
+                }
+
                 stmt.addToNs(ImpPrefixToNamespace.class, impPrefix, importedModuleNamespace);
             }
 
index 2701a3069c112a3e2c45a8c73b64de162e69f5b1..6fa9e74171e640bd26850c446f1187e4cad21c93 100644 (file)
@@ -16,6 +16,7 @@ import java.util.Collection;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
@@ -42,6 +43,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.source.IncludedModuleContext;
 import org.opendaylight.yangtools.yang.parser.spi.source.IncludedSubmoduleNameToModuleCtx;
+import org.opendaylight.yangtools.yang.parser.spi.source.YangVersionLinkageException;
 
 @Beta
 public final class IncludeStatementSupport
@@ -96,6 +98,12 @@ public final class IncludeStatementSupport
             @Override
             public void apply(final InferenceContext ctx) {
                 final StmtContext<?, ?, ?> includedSubModuleContext = requiresCtxPrerequisite.resolve(ctx);
+                final YangVersion modVersion = stmt.getRoot().yangVersion();
+                final YangVersion subVersion = includedSubModuleContext.yangVersion();
+                if (subVersion != modVersion) {
+                    throw new YangVersionLinkageException(stmt,
+                        "Cannot include a version %s submodule in a version %s module", subVersion, modVersion);
+                }
 
                 stmt.addToNs(IncludedModuleContext.class, revision != null
                         ? RevisionSourceIdentifier.create(submoduleName, revision.argument())
diff --git a/parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1339Test.java b/parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1339Test.java
new file mode 100644 (file)
index 0000000..ec06bc9
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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 static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.source.YangVersionLinkageException;
+
+/**
+ * Tests for {@code MUST NOT} statements around include/import interop of RFC6020 and RFC7950, as per
+ * <a href="https://datatracker.ietf.org/doc/html/rfc7950#section-12">RFC7950 section 12</a>.
+ */
+public class YT1339Test {
+    @Test
+    public void testInclude() {
+        // A YANG version 1.1 module MUST NOT include a YANG version 1 submodule,
+        assertFailedInclude("old-sub", YangVersion.VERSION_1, YangVersion.VERSION_1_1);
+        // ... and a YANG version 1 module MUST NOT include a YANG version 1.1 submodule
+        assertFailedInclude("new-sub", YangVersion.VERSION_1_1, YangVersion.VERSION_1);
+    }
+
+    @Test
+    public void testImportNewByRev() throws Exception {
+        // A YANG version 1 module or submodule MUST NOT import a YANG version 1.1 module by revision.
+        assertFailedImport("import-rev");
+        assertFailedImport("import-rev-sub");
+    }
+
+    @Test
+    public void testImportOldByRev() throws Exception {
+        // A YANG version 1.1 module or submodule MAY import a YANG version 1 module by revision.
+        compile("import");
+    }
+
+    @Test
+    public void testImportNoRev() throws Exception {
+        // no language forbidding imports without revision
+        compile("import-norev");
+    }
+
+    private static void assertFailedImport(final String subdir) {
+        assertThat(assertYangVersionLinkageException(subdir),
+            startsWith("Cannot import by revision version 1.1 module new [at "));
+    }
+
+    private static void assertFailedInclude(final String subdir, final YangVersion subVer, final YangVersion modVer) {
+        assertThat(assertYangVersionLinkageException(subdir),
+            startsWith("Cannot include a version " + subVer + " submodule in a version " + modVer + " module [at "));
+    }
+
+    private static String assertYangVersionLinkageException(final String subdir) {
+        final var cause = assertThrows(ReactorException.class, () -> compile(subdir)).getCause();
+        assertThat(cause, instanceOf(YangVersionLinkageException.class));
+        return cause.getMessage();
+    }
+
+    private static void compile(final String subdir) throws Exception {
+        StmtTestUtils.parseYangSources("/bugs/YT1339/" + subdir);
+    }
+}
index 86186970fe7319bb2f5187f1efa7fb94617d84cf..9e83b22513f900cec4a27ba82c82d6f841604e1c 100644 (file)
@@ -1,4 +1,6 @@
 submodule bar {
+  yang-version 1.1;
+
   belongs-to foo {
     prefix foo;
   }
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-norev/new.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-norev/new.yang
new file mode 100644 (file)
index 0000000..9003828
--- /dev/null
@@ -0,0 +1,6 @@
+module new {
+  namespace new;
+  prefix new;
+  yang-version 1.1;
+  revision 2021-10-01;
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-norev/old.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-norev/old.yang
new file mode 100644 (file)
index 0000000..62caf0f
--- /dev/null
@@ -0,0 +1,10 @@
+module old {
+  namespace old;
+  prefix old;
+
+  import new {
+    prefix new;
+  }
+
+  include sub;
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-norev/sub.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-norev/sub.yang
new file mode 100644 (file)
index 0000000..b49d81f
--- /dev/null
@@ -0,0 +1,9 @@
+submodule sub {
+  belongs-to old {
+    prefix old;
+  }
+
+  import new {
+    prefix new;
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev-sub/new.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev-sub/new.yang
new file mode 100644 (file)
index 0000000..9003828
--- /dev/null
@@ -0,0 +1,6 @@
+module new {
+  namespace new;
+  prefix new;
+  yang-version 1.1;
+  revision 2021-10-01;
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev-sub/old.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev-sub/old.yang
new file mode 100644 (file)
index 0000000..6db3f27
--- /dev/null
@@ -0,0 +1,6 @@
+module old {
+  namespace old;
+  prefix old;
+
+  include sub;
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev-sub/sub.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev-sub/sub.yang
new file mode 100644 (file)
index 0000000..8272a28
--- /dev/null
@@ -0,0 +1,10 @@
+submodule sub {
+  belongs-to old {
+    prefix old;
+  }
+
+  import new {
+    prefix new;
+    revision-date 2021-10-01;
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev/new.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev/new.yang
new file mode 100644 (file)
index 0000000..9003828
--- /dev/null
@@ -0,0 +1,6 @@
+module new {
+  namespace new;
+  prefix new;
+  yang-version 1.1;
+  revision 2021-10-01;
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev/old.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import-rev/old.yang
new file mode 100644 (file)
index 0000000..5ba6ff2
--- /dev/null
@@ -0,0 +1,9 @@
+module old {
+  namespace old;
+  prefix old;
+
+  import new {
+    prefix new;
+    revision-date 2021-10-01;
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import/new.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import/new.yang
new file mode 100644 (file)
index 0000000..4cc3943
--- /dev/null
@@ -0,0 +1,12 @@
+module new {
+  namespace new;
+  prefix new;
+  yang-version 1.1;
+
+  import old {
+    prefix old;
+    revision-date 2021-10-01;
+  }
+
+  include sub;
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import/old.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import/old.yang
new file mode 100644 (file)
index 0000000..54d1588
--- /dev/null
@@ -0,0 +1,6 @@
+module old {
+  namespace old;
+  prefix old;
+  revision 2021-10-01;
+
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import/sub.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/import/sub.yang
new file mode 100644 (file)
index 0000000..52d81c0
--- /dev/null
@@ -0,0 +1,12 @@
+submodule sub {
+  yang-version 1.1;
+
+  belongs-to new {
+    prefix new;
+  }
+
+  import old {
+    prefix old;
+    revision-date 2021-10-01;
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/new-sub/mod.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/new-sub/mod.yang
new file mode 100644 (file)
index 0000000..f3f5844
--- /dev/null
@@ -0,0 +1,6 @@
+module mod {
+  namespace mod;
+  prefix mod;
+
+  include sub;
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/new-sub/sub.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/new-sub/sub.yang
new file mode 100644 (file)
index 0000000..5bc8aa3
--- /dev/null
@@ -0,0 +1,7 @@
+submodule sub {
+  yang-version 1.1;
+
+  belongs-to mod {
+    prefix mod;
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/old-sub/mod.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/old-sub/mod.yang
new file mode 100644 (file)
index 0000000..ba1cc5e
--- /dev/null
@@ -0,0 +1,7 @@
+module mod {
+  namespace mod;
+  prefix mod;
+  yang-version 1.1;
+
+  include sub;
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/old-sub/sub.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1339/old-sub/sub.yang
new file mode 100644 (file)
index 0000000..85af4e3
--- /dev/null
@@ -0,0 +1,5 @@
+submodule sub {
+  belongs-to mod {
+    prefix mod;
+  }
+}
index d130ce65228f67bad4c82b79ab1fc75818fffa96..9ab0b7fe95643bf7508d16b7ed03f5b71d512a97 100644 (file)
@@ -3,7 +3,7 @@ module foo {
     prefix foo;
     yang-version 1;
 
-    import foo-imp-1 { prefix foo-imp-1; revision-date 2017-01-23; }
+    import foo-imp-1 { prefix foo-imp-1; }
     import foo-imp-2 { prefix foo-imp-2; revision-date 2017-01-23; }
     include sub-foo {
         revision-date 2017-01-20;
index 26cbcaf89617f733640174a1d8d80a36b21573af..a5eeb1a0eccee2bb71bb27a1b2030b14dfc01bfa 100644 (file)
@@ -2,7 +2,7 @@ module lib-1 {
     namespace lib-1;
     prefix lib-1;
 
-    import lib-2 { prefix lib-2; revision-date 2000-01-01; }
+    import lib-2 { prefix lib-2; }
     import missing-lib { prefix missing; revision-date 2000-01-01; }
 
     revision 2000-01-01;
index 5375af4d3bc917f523b471a877e580ad4eefc275..6d6ac93fd78af82bba4e55c730cdd0646813c6dc 100644 (file)
@@ -4,7 +4,6 @@ module foo {
 
     import bar {
         prefix bar;
-        revision-date 2017-01-20;
     }
 
     revision 2017-01-20;
@@ -49,4 +48,4 @@ module foo {
             units "weeks";
         }
     }
-}
\ No newline at end of file
+}
index 732bcbe59fe899f0e91a1b0dad43b324055ed3e5..2bf36eeee7fc7a86cccbd852ad960055a239e4e4 100644 (file)
@@ -8,8 +8,7 @@ module import-test-root {
 
     import import-test-imported {
         prefix "imported-module";
-        revision-date "2016-12-12";
         description "Yang 1.1: Allow description and reference in include and import.";
         reference "https://tools.ietf.org/html/rfc7950 section-7.1.5/6";
     }
-}
\ No newline at end of file
+}
diff --git a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/YangVersionLinkageException.java b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/YangVersionLinkageException.java
new file mode 100644 (file)
index 0000000..201b570
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.parser.spi.source;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CommonStmtCtx;
+
+/**
+ * An exception indicating source-level problem across multiple YANG sources relating to how they are allowed to be
+ * linked between YANG versions. This typically indicates a direct violation of
+ * <a href="https://datatracker.ietf.org/doc/html/rfc7950#section-12">RFC7950 section 12</a>.
+ */
+@Beta
+public class YangVersionLinkageException extends SourceException {
+    private static final long serialVersionUID = 1L;
+
+    public YangVersionLinkageException(final @NonNull StatementSourceReference source, final @NonNull String format,
+            final Object... args) {
+        super(source, format, args);
+    }
+
+    public YangVersionLinkageException(final @NonNull CommonStmtCtx stmt, final @NonNull String format,
+            final Object... args) {
+        this(stmt.sourceReference(), format, args);
+    }
+}