Bug 6871: [YANG 1.1] Allow "must" in "input", "output" and "notification" statements 39/49339/5
authorIgor Foltin <ifoltin@cisco.com>
Wed, 14 Dec 2016 11:24:03 +0000 (12:24 +0100)
committerRobert Varga <nite@hq.sk>
Sat, 17 Dec 2016 12:41:06 +0000 (12:41 +0000)
Starting with YANG 1.1 (RFC7950), "must" statements can be defined in
"input", "output" and "notification" statements.

Yang statement parser can now parse models containing such statements.

Change-Id: I6b81dd3447bfc50f5a21b79fbdaacfb6e2bf9689
Signed-off-by: Igor Foltin <ifoltin@cisco.com>
12 files changed:
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/InputStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/NotificationStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/OutputStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/effective/NotificationEffectiveStatementImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/InputStatementRfc7950Support.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/NotificationStatementRfc7950Support.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/OutputStatementRfc7950Support.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6871Test.java [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/bar10.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/baz10.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo10.yang [new file with mode: 0644]

index 63fb8eba85d94dea6b83741008f9609f692fd87e..4bf181e7486a57c7150328ac230de8d26a563235 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.InputStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
 import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
@@ -102,4 +103,10 @@ public class InputStatementImpl extends AbstractDeclaredStatement<QName>
     public Collection<? extends DataDefinitionStatement> getDataDefinitions() {
         return allDeclared(DataDefinitionStatement.class);
     }
+
+    @Nonnull
+    @Override
+    public Collection<? extends MustStatement> getMusts() {
+        return allDeclared(MustStatement.class);
+    }
 }
index 792961d4e8bfa5070a11fa2412b1db1811b5a1fb..a67bfaa7836208f6170bca481b2c6806cbecf7ae 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.DescriptionStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.NotificationStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ReferenceStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.StatusStatement;
@@ -119,6 +120,12 @@ public class NotificationStatementImpl extends AbstractDeclaredStatement<QName>
         return allDeclared(DataDefinitionStatement.class);
     }
 
+    @Nonnull
+    @Override
+    public Collection<? extends MustStatement> getMusts() {
+        return allDeclared(MustStatement.class);
+    }
+
     @Nullable
     @Override
     public StatusStatement getStatus() {
index 9cf2652be1632b24ee066e087e19b0c61434faa2..a2b1d0446efd1459001ca90314bf624a96d5c413 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.DataDefinitionStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.MustStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.OutputStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
 import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
@@ -99,5 +100,11 @@ public class OutputStatementImpl extends AbstractDeclaredStatement<QName> implem
     public Collection<? extends DataDefinitionStatement> getDataDefinitions() {
         return allDeclared(DataDefinitionStatement.class);
     }
+
+    @Nonnull
+    @Override
+    public Collection<? extends MustStatement> getMusts() {
+        return allDeclared(MustStatement.class);
+    }
 }
 
index a33d19e7d77e3ff132dd7c83f7f026222864d634..c769f6265b0248d08b87c06cbf42d6229b580ca5 100644 (file)
@@ -18,6 +18,7 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
@@ -29,6 +30,7 @@ public class NotificationEffectiveStatementImpl extends
         AbstractEffectiveDocumentedDataNodeContainer<QName, NotificationStatement> implements NotificationDefinition {
     private final QName qname;
     private final SchemaPath path;
+    private final ConstraintDefinition constraints;
     private final Set<AugmentationSchema> augmentations;
     private final List<UnknownSchemaNode> unknownNodes;
 
@@ -38,6 +40,8 @@ public class NotificationEffectiveStatementImpl extends
         this.qname = ctx.getStatementArgument();
         this.path = ctx.getSchemaPath().get();
 
+        this.constraints = EffectiveConstraintDefinitionImpl.forParent(this);
+
         // initSubstatementCollections
         Collection<? extends EffectiveStatement<?, ?>> effectiveSubstatements = effectiveSubstatements();
         List<UnknownSchemaNode> unknownNodesInit = new LinkedList<>();
@@ -68,6 +72,11 @@ public class NotificationEffectiveStatementImpl extends
         return path;
     }
 
+    @Override
+    public ConstraintDefinition getConstraints() {
+        return constraints;
+    }
+
     @Override
     public Set<AugmentationSchema> getAvailableAugmentations() {
         return augmentations;
index 6cf96425edafff2a53e3bf01640bf37195bc811c..675518bb8326fd224a6cea75a10a7a24caf1086d 100644 (file)
@@ -27,6 +27,7 @@ public final class InputStatementRfc7950Support extends InputStatementImpl.Defin
             .addAny(YangStmtMapping.LEAF)
             .addAny(YangStmtMapping.LEAF_LIST)
             .addAny(YangStmtMapping.LIST)
+            .addAny(YangStmtMapping.MUST)
             .addAny(YangStmtMapping.TYPEDEF)
             .addAny(YangStmtMapping.USES)
             .build();
index 5464bf8018cf016696bb01485b4127c11bbec11b..bbb3dbbf893ded3b4ad76de5fe82518a3a430e2e 100644 (file)
@@ -40,6 +40,7 @@ public final class NotificationStatementRfc7950Support extends NotificationState
             .addAny(YangStmtMapping.LEAF)
             .addAny(YangStmtMapping.LEAF_LIST)
             .addAny(YangStmtMapping.LIST)
+            .addAny(YangStmtMapping.MUST)
             .addOptional(YangStmtMapping.REFERENCE)
             .addOptional(YangStmtMapping.STATUS)
             .addAny(YangStmtMapping.TYPEDEF)
index 92071cb3d8f34ea716bec31a2db87f287297acac..d0567da0cea1ac0818b202474addb8badf7f1a35 100644 (file)
@@ -27,6 +27,7 @@ public final class OutputStatementRfc7950Support extends OutputStatementImpl.Def
             .addAny(YangStmtMapping.LEAF)
             .addAny(YangStmtMapping.LEAF_LIST)
             .addAny(YangStmtMapping.LIST)
+            .addAny(YangStmtMapping.MUST)
             .addAny(YangStmtMapping.TYPEDEF)
             .addAny(YangStmtMapping.USES)
             .build();
diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6871Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/Bug6871Test.java
new file mode 100644 (file)
index 0000000..21e2e7f
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 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.parser.stmt.rfc7950;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.MustDefinition;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.stmt.StmtTestUtils;
+
+public class Bug6871Test {
+
+    @Test
+    public void testValidYang11Model() throws ReactorException, FileNotFoundException, URISyntaxException,
+            ParseException {
+        final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6871/foo.yang");
+        assertNotNull(schemaContext);
+
+        final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2016-12-14");
+
+        final Module foo = schemaContext.findModuleByName("foo", revision);
+        assertNotNull(foo);
+
+        final Set<NotificationDefinition> notifications = foo.getNotifications();
+        assertEquals(1, notifications.size());
+        final NotificationDefinition myNotification = notifications.iterator().next();
+        Set<MustDefinition> mustConstraints = myNotification.getConstraints().getMustConstraints();
+        assertEquals(2, mustConstraints.size());
+
+        final Set<RpcDefinition> rpcs = foo.getRpcs();
+        assertEquals(1, rpcs.size());
+        final RpcDefinition myRpc = rpcs.iterator().next();
+
+        final ContainerSchemaNode input = myRpc.getInput();
+        assertNotNull(input);
+        mustConstraints = input.getConstraints().getMustConstraints();
+        assertEquals(2, mustConstraints.size());
+
+        final ContainerSchemaNode output = myRpc.getOutput();
+        assertNotNull(output);
+        mustConstraints = output.getConstraints().getMustConstraints();
+        assertEquals(2, mustConstraints.size());
+    }
+
+    @Test
+    public void testInvalidYang10Model() throws FileNotFoundException, URISyntaxException {
+        assertException("/rfc7950/bug6871/foo10.yang", "MUST is not valid for NOTIFICATION");
+        assertException("/rfc7950/bug6871/bar10.yang", "MUST is not valid for INPUT");
+        assertException("/rfc7950/bug6871/baz10.yang", "MUST is not valid for OUTPUT");
+    }
+
+    private static void assertException(final String sourcePath, final String exceptionMessage)
+            throws FileNotFoundException, URISyntaxException {
+        try {
+            StmtTestUtils.parseYangSource(sourcePath);
+            fail("Test should fail due to invalid Yang 1.0");
+        } catch (final ReactorException ex) {
+            assertTrue(ex.getCause().getMessage().startsWith(exceptionMessage));
+        }
+    }
+}
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/bar10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/bar10.yang
new file mode 100644 (file)
index 0000000..a1ab5af
--- /dev/null
@@ -0,0 +1,14 @@
+module bar10 {
+    namespace bar10-namespace;
+    prefix bar10-prefix;
+    yang-version 1;
+
+    revision 2016-12-14;
+
+    rpc my-rpc {
+        input {
+            must "bar = foo";
+            must "c != d";
+        }
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/baz10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/baz10.yang
new file mode 100644 (file)
index 0000000..25e1640
--- /dev/null
@@ -0,0 +1,14 @@
+module baz10 {
+    namespace baz10-namespace;
+    prefix baz10-prefix;
+    yang-version 1;
+
+    revision 2016-12-14;
+
+    rpc my-rpc {
+        output {
+            must "baz != bar";
+            must "x = y";
+        }
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo.yang
new file mode 100644 (file)
index 0000000..fd48d5f
--- /dev/null
@@ -0,0 +1,24 @@
+module foo {
+    namespace foo-namespace;
+    prefix foo-prefix;
+    yang-version 1.1;
+
+    revision 2016-12-14;
+
+    notification my-notification {
+        must "foo != bar";
+        must "a = b";
+    }
+
+    rpc my-rpc {
+        input {
+            must "bar = foo";
+            must "c != d";
+        }
+
+        output {
+            must "baz != bar";
+            must "x = y";
+        }
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo10.yang b/yang/yang-parser-impl/src/test/resources/rfc7950/bug6871/foo10.yang
new file mode 100644 (file)
index 0000000..cfbd276
--- /dev/null
@@ -0,0 +1,12 @@
+module foo10 {
+    namespace foo10-namespace;
+    prefix foo10-prefix;
+    yang-version 1;
+
+    revision 2016-12-14;
+
+    notification my-notification {
+        must "foo != bar";
+        must "a = b";
+    }
+}
\ No newline at end of file