Do do not check unique in unsupported lists 83/104383/2
authorSangwook Ha <sangwook.ha@verizon.com>
Mon, 30 Jan 2023 21:50:33 +0000 (13:50 -0800)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 14 Feb 2023 09:08:51 +0000 (10:08 +0100)
Parsing of YANG models fails if a list conditional on a feature has a
unique statement and the feature is not supported.

Add test cases to reproduce the issue and fix
RequireEffectiveList.isApplicable() to also check for
isSupportedByFeatures().

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

parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/UniqueStatementSupport.java
parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1481Test.java [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1481/bar-feature/foo.yang [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1481/foo-feature/foo.yang [new file with mode: 0644]

index ad3900c2e23f6e7a16f9dfa5e3192796117a9975..de3273dd7487d0c2193004e155fbe87534e75314 100644 (file)
@@ -191,7 +191,8 @@ public final class UniqueStatementSupport
         }
 
         private boolean isApplicable() {
-            return list.isSupportedToBuildEffective() && unique.isSupportedToBuildEffective();
+            return list.isSupportedToBuildEffective() && list.isSupportedByFeatures()
+                && unique.isSupportedToBuildEffective();
         }
     }
 
diff --git a/parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1481Test.java b/parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1481Test.java
new file mode 100644 (file)
index 0000000..9f4565f
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2023 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 static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.KeyEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Descendant;
+import org.opendaylight.yangtools.yang.model.api.stmt.UniqueEffectiveStatement;
+
+public class YT1481Test extends AbstractYangTest {
+    private static final QName FOO = QName.create("urn:foo", "foo");
+    private static final QName BAR = QName.create("urn:foo", "bar");
+    private static final QName BAZ = QName.create("urn:foo", "baz");
+    private static final QName QUX = QName.create("urn:foo", "qux");
+
+    @Test
+    public void testFooFeatureSupported() {
+        assertBar("foo-feature");
+    }
+
+    @Test
+    public void testFooFeatureNotSupported() {
+        assertThat(assertFooModule("foo-feature", Set.of()).effectiveSubstatements(),
+            not(hasItem(instanceOf(ContainerEffectiveStatement.class))));
+    }
+
+    @Test
+    public void testBarFeatureSupported() {
+        assertBar("bar-feature");
+    }
+
+    @Test
+    public void testBarFeatureNotSupported() {
+        assertEquals(List.of(), assertFoo("bar-feature", Set.of()).effectiveSubstatements());
+    }
+
+    private static ModuleEffectiveStatement assertFooModule(final String dirName,
+            final Set<QName> supportedFeatures) {
+        return assertEffectiveModelDir("/bugs/YT1481/" + dirName, supportedFeatures)
+            .findModuleStatement(FOO).orElseThrow();
+    }
+
+    private static ContainerEffectiveStatement assertFoo(final String dirName,
+            final Set<QName> supportedFeatures) {
+        final var foo = assertFooModule(dirName, supportedFeatures)
+            .findFirstEffectiveSubstatement(ContainerEffectiveStatement.class).orElseThrow();
+        assertEquals(FOO, foo.argument());
+        return foo;
+    }
+
+    private static void assertBar(final String dirName) {
+        final var bar = assertFoo(dirName, null)
+            .findFirstEffectiveSubstatement(ListEffectiveStatement.class).orElseThrow();
+        assertEquals(BAR, bar.argument());
+
+        final var baz = bar.findFirstEffectiveSubstatement(KeyEffectiveStatement.class).orElseThrow();
+        assertEquals(Set.of(BAZ), baz.argument());
+
+        final var qux = bar.findFirstEffectiveSubstatement(UniqueEffectiveStatement.class).orElseThrow();
+        assertEquals(Set.of(Descendant.of(QUX)), qux.argument());
+    }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1481/bar-feature/foo.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1481/bar-feature/foo.yang
new file mode 100644 (file)
index 0000000..ada44de
--- /dev/null
@@ -0,0 +1,23 @@
+module foo {
+  namespace "urn:foo";
+  prefix "foo";
+
+  feature bar-feature;
+
+  container foo {
+    list bar {
+      if-feature bar-feature;
+
+      key baz;
+      unique qux;
+
+      leaf baz {
+        type string;
+      }
+
+      leaf qux {
+        type string;
+      }
+    }
+  }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1481/foo-feature/foo.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1481/foo-feature/foo.yang
new file mode 100644 (file)
index 0000000..c6e2c24
--- /dev/null
@@ -0,0 +1,23 @@
+module foo {
+  namespace "urn:foo";
+  prefix "foo";
+
+  feature foo-feature;
+
+  container foo {
+    if-feature foo-feature;
+
+    list bar {
+      key baz;
+      unique qux;
+
+      leaf baz {
+        type string;
+      }
+
+      leaf qux {
+        type string;
+      }
+    }
+  }
+}