Fix isSupportedToBuildEffective() propagation 54/103354/2
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 22 Nov 2022 17:47:49 +0000 (18:47 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 24 Nov 2022 15:06:47 +0000 (16:06 +0100)
InferredStatementContext has bad interaction with ImplictStmtCtx -- the
latter fizzles when it is not supported by features. This leads to a
failure to build effective context, as the prototype cannot be built and
therefore an attempt to reuse it fails.

Adjust InferredStatementContext to check if its prototype can be built
and carry over that fact when it is not.

JIRA: YANGTOOLS-1465
Change-Id: Iad05b0c6a06b6d9f837b70ced0da8cdc8ed3ed97
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit e31531765d8ae6e3bc36f3de4ae4e14e06568e83)

parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java
parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1465Test.java [new file with mode: 0644]
parser/yang-parser-rfc7950/src/test/resources/bugs/YT1465/foo.yang [new file with mode: 0644]

index 144d6b5c03bd22ebe8ce72879baa0d45befb40e6..ba888efc4b9131916ed9486c2da2d14481d1d154 100644 (file)
@@ -705,6 +705,19 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
         return isIgnoringConfig(parent);
     }
 
+    @Override
+    public boolean isSupportedToBuildEffective() {
+        // Our prototype may have fizzled, for example due to it being a implicit statement guarded by if-feature which
+        // evaluates to false. If that happens, this statement also needs to report unsupported -- and we want to cache
+        // that information for future reuse.
+        boolean ret = super.isSupportedToBuildEffective();
+        if (ret && !prototype.isSupportedToBuildEffective()) {
+            setUnsupported();
+            ret = false;
+        }
+        return ret;
+    }
+
     @Override
     protected boolean isParentSupportedByFeatures() {
         return parent.isSupportedByFeatures();
index ba338a37cd62d8eda01073006a27089a1684341b..2f64a787637c8f2843624e3bc7079e0282e6d7b7 100644 (file)
@@ -472,7 +472,7 @@ abstract class ReactorStmtCtx<A, D extends DeclaredStatement<A>, E extends Effec
     //
     //
 
-    // Non-final form ImplicitStmtCtx
+    // Non-final for ImplicitStmtCtx/InferredStatementContext
     @Override
     public boolean isSupportedToBuildEffective() {
         return isSupportedToBuildEffective;
diff --git a/parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1465Test.java b/parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1465Test.java
new file mode 100644 (file)
index 0000000..42dbf79
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech s.r.o. 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.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement.SchemaTreeNamespace;
+
+public class YT1465Test extends AbstractYangTest {
+    @Test
+    public void supportedLeafInChoiceAugment() throws Exception {
+        final var baz = assertBaz(StmtTestUtils.parseYangSource("/bugs/YT1465/foo.yang", null));
+        final var schemas = baz.getAll(SchemaTreeNamespace.class).values();
+        assertEquals(2, schemas.size());
+        final var it = schemas.iterator();
+
+        final var first = it.next();
+        assertThat(first, instanceOf(CaseEffectiveStatement.class));
+        assertEquals(QName.create("foo", "one"), first.argument());
+
+        final var second = it.next();
+        assertThat(second, instanceOf(CaseEffectiveStatement.class));
+        assertEquals(QName.create("foo", "two"), second.argument());
+    }
+
+    @Test
+    public void unsupportedLeafInChoiceAugment() throws Exception {
+        final var baz = assertBaz(StmtTestUtils.parseYangSource("/bugs/YT1465/foo.yang", Set.of()));
+        final var schemas = baz.getAll(SchemaTreeNamespace.class).values();
+        assertEquals(1, schemas.size());
+        final var first = schemas.iterator().next();
+        assertThat(first, instanceOf(CaseEffectiveStatement.class));
+        assertEquals(QName.create("foo", "one"), first.argument());
+    }
+
+    private static ChoiceEffectiveStatement assertBaz(final EffectiveModelContext ctx) {
+        final var foo = ctx.findModuleStatements("foo").iterator().next()
+            .findFirstEffectiveSubstatement(ContainerEffectiveStatement.class).orElseThrow();
+        assertEquals(QName.create("foo", "foo"), foo.argument());
+
+        final var bar = foo.findFirstEffectiveSubstatement(ContainerEffectiveStatement.class).orElseThrow();
+        assertEquals(QName.create("foo", "bar"), bar.argument());
+
+        final var baz = bar.findFirstEffectiveSubstatement(ChoiceEffectiveStatement.class).orElseThrow();
+        assertEquals(QName.create("foo", "baz"), baz.argument());
+        return baz;
+    }
+}
diff --git a/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1465/foo.yang b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1465/foo.yang
new file mode 100644 (file)
index 0000000..03c5f46
--- /dev/null
@@ -0,0 +1,25 @@
+module foo {
+  namespace foo;
+  prefix foo;
+
+  feature foo;
+
+  container foo;
+
+  augment /foo {
+    container bar {
+      choice baz {
+        mandatory true;
+
+        leaf one {
+          type string;
+        }
+
+        leaf two {
+          if-feature foo;
+          type string;
+        }
+      }
+    }
+  }
+}