From 89712e2e30161966b8568080ec798321b4f15d10 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 22 Nov 2022 18:47:49 +0100 Subject: [PATCH] Fix isSupportedToBuildEffective() propagation 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 (cherry picked from commit e31531765d8ae6e3bc36f3de4ae4e14e06568e83) --- .../reactor/InferredStatementContext.java | 13 ++++ .../parser/stmt/reactor/ReactorStmtCtx.java | 2 +- .../yangtools/yang/stmt/YT1465Test.java | 62 +++++++++++++++++++ .../src/test/resources/bugs/YT1465/foo.yang | 25 ++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1465Test.java create mode 100644 parser/yang-parser-rfc7950/src/test/resources/bugs/YT1465/foo.yang diff --git a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java index 144d6b5c03..ba888efc4b 100644 --- a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java +++ b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java @@ -705,6 +705,19 @@ final class InferredStatementContext, 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(); diff --git a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java index ba338a37cd..2f64a78763 100644 --- a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java +++ b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java @@ -472,7 +472,7 @@ abstract class ReactorStmtCtx, 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 index 0000000000..42dbf7937f --- /dev/null +++ b/parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YT1465Test.java @@ -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 index 0000000000..03c5f46088 --- /dev/null +++ b/parser/yang-parser-rfc7950/src/test/resources/bugs/YT1465/foo.yang @@ -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; + } + } + } + } +} -- 2.36.6