BUG-7424: Disallow child namespace collisions 00/51400/9
authorPeter Kajsa <pkajsa@cisco.com>
Fri, 3 Feb 2017 13:25:27 +0000 (14:25 +0100)
committerRobert Varga <nite@hq.sk>
Thu, 9 Mar 2017 10:22:47 +0000 (10:22 +0000)
All leafs, leaf-lists, lists, containers, choices, rpcs,
notifications, and anyxmls defined (directly or through a uses
statement) within a parent node or at the top level of the module
or its submodules share the same identifier namespace.

Change-Id: I1852d2ca5ebd07ba6c1ed21a5ceded3e87d67467
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
Signed-off-by: Robert Varga <rovarga@cisco.com>
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChildSchemaNodes.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug7424Test.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-data.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-notification.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-rpc-uses.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-rpc.yang [new file with mode: 0644]

index d18f7565490552d4d4c1f4e5044178e4ae238303..f898e310a514c64e9e86edab76b08f6982974588 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
 /**
  * Statement local namespace, which holds direct schema node descendants.
@@ -50,8 +51,12 @@ public class ChildSchemaNodes<D extends DeclaredStatement<QName>, E extends Effe
     @SuppressWarnings("unchecked")
     @Override
     public void addTo(final NamespaceStorageNode storage, final QName key, final StmtContext<?, D, E> value) {
-        // FIXME: BUG-7424: usee putToLocalStorageIfAbsent()
-        globalOrStatementSpecific(storage).putToLocalStorage(ChildSchemaNodes.class, key, value);
+        final StmtContext<?, D, E> prev = globalOrStatementSpecific(storage).putToLocalStorageIfAbsent(
+            ChildSchemaNodes.class, key, value);
+
+        SourceException.throwIf(prev != null, value.getStatementSourceReference(),
+                "Error in module '%s': cannot add '%s'. Node name collision: '%s' already declared.", value.getRoot()
+                        .getStatementArgument(), key, prev != null ? prev.getStatementArgument() : null);
     }
 
     private static NamespaceStorageNode globalOrStatementSpecific(final NamespaceStorageNode storage) {
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug7424Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug7424Test.java
new file mode 100644 (file)
index 0000000..a0f4b83
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
+
+public class Bug7424Test {
+    @Test
+    public void testRpc() throws Exception {
+        try {
+            StmtTestUtils.parseYangSource("/bugs/bug7424/foo-rpc.yang");
+            fail("Test should fail due to invalid yang model.");
+        } catch (final SomeModifiersUnresolvedException e) {
+            assertTrue(e
+                    .getCause()
+                    .getMessage()
+                    .startsWith(
+                            "Error in module 'foo': cannot add '(foo?revision=1970-01-01)name'. "
+                                    + "Node name collision: '(foo?revision=1970-01-01)name' already declared."));
+        }
+    }
+
+    @Test
+    public void testNotification() throws Exception {
+        try {
+            StmtTestUtils.parseYangSource("/bugs/bug7424/foo-notification.yang");
+            fail("Test should fail due to invalid yang model.");
+        } catch (final SomeModifiersUnresolvedException e) {
+            assertTrue(e
+                    .getCause()
+                    .getMessage()
+                    .startsWith(
+                            "Error in module 'foo': cannot add '(foo?revision=1970-01-01)name'. "
+                                    + "Node name collision: '(foo?revision=1970-01-01)name' already declared."));
+        }
+    }
+
+    @Test
+    public void testData() throws Exception {
+        try {
+            StmtTestUtils.parseYangSource("/bugs/bug7424/foo-data.yang");
+            fail("Test should fail due to invalid yang model.");
+        } catch (final SomeModifiersUnresolvedException e) {
+            assertTrue(e
+                    .getCause()
+                    .getMessage()
+                    .startsWith(
+                            "Error in module 'foo': cannot add '(foo?revision=1970-01-01)name'. "
+                                    + "Node name collision: '(foo?revision=1970-01-01)name' already declared."));
+        }
+    }
+
+    @Test
+    public void testRpcUses() throws Exception {
+        try {
+            StmtTestUtils.parseYangSource("/bugs/bug7424/foo-rpc-uses.yang");
+            fail("Test should fail due to invalid yang model.");
+        } catch (final SomeModifiersUnresolvedException e) {
+            assertTrue(e
+                    .getCause()
+                    .getMessage()
+                    .startsWith(
+                            "Error in module 'foo': cannot add '(foo?revision=1970-01-01)name'. "
+                                    + "Node name collision: '(foo?revision=1970-01-01)name' already declared."));
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-data.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-data.yang
new file mode 100644 (file)
index 0000000..1c719b8
--- /dev/null
@@ -0,0 +1,11 @@
+module foo {
+    namespace foo;
+    prefix foo;
+
+    container root {
+        list name {
+        }
+        container name {
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-notification.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-notification.yang
new file mode 100644 (file)
index 0000000..39f2ff6
--- /dev/null
@@ -0,0 +1,12 @@
+module foo {
+    namespace foo;
+    prefix foo;
+    yang-version 1.1;
+
+    container root {
+        notification name {
+        }
+        action name {
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-rpc-uses.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-rpc-uses.yang
new file mode 100644 (file)
index 0000000..b4ff7fe
--- /dev/null
@@ -0,0 +1,14 @@
+module foo {
+    namespace foo;
+    prefix foo;
+
+    uses grp;
+
+    rpc name {
+    }
+
+    grouping grp {
+        container name {
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-rpc.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug7424/foo-rpc.yang
new file mode 100644 (file)
index 0000000..10828f9
--- /dev/null
@@ -0,0 +1,11 @@
+module foo {
+    namespace foo;
+    prefix foo;
+    yang-version 1.1;
+
+    container name {
+    }
+
+    rpc name {
+    }
+}