From 960c11dc4a50f27718a163451c0da65995d5c850 Mon Sep 17 00:00:00 2001 From: Peter Kajsa Date: Fri, 10 Mar 2017 14:10:56 +0100 Subject: [PATCH 1/1] Bug 6183 - Shorthand case should create case node in schema tree According to Rfc7950, if a case statement is omitted and implicit case node is created, schema node identifiers MUST always explicitly include the implicit case node identifiers. This patch deals with both Yang 1.1 and Yang 1 in the same way. Change-Id: I64fef2aee85855cb6300318f7c97e694b3105a0a Signed-off-by: Peter Kajsa --- .../spi/meta/AbstractStatementSupport.java | 12 ++ .../parser/spi/meta/StatementSupport.java | 28 +++++ .../stmt/reactor/SourceSpecificContext.java | 6 +- .../stmt/reactor/StatementContextBase.java | 13 ++- .../stmt/reactor/StatementContextWriter.java | 8 +- .../reactor/StatementDefinitionContext.java | 7 ++ .../stmt/reactor/SubstatementContext.java | 2 +- .../stmt/rfc6020/ChoiceStatementImpl.java | 38 ++++++- .../ChoiceStatementRfc7950Support.java | 8 ++ .../yangtools/yang/stmt/Bug6183Test.java | 106 ++++++++++++++++++ .../resources/bugs/bug6183/yang10/foo.yang | 62 ++++++++++ .../resources/bugs/bug6183/yang11/foo.yang | 63 +++++++++++ 12 files changed, 342 insertions(+), 11 deletions(-) create mode 100644 yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6183Test.java create mode 100644 yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang10/foo.yang create mode 100644 yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang11/foo.yang diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/AbstractStatementSupport.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/AbstractStatementSupport.java index 02374622dd..4f5c6b3a41 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/AbstractStatementSupport.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/AbstractStatementSupport.java @@ -8,6 +8,7 @@ package org.opendaylight.yangtools.yang.parser.spi.meta; import com.google.common.base.Preconditions; +import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.yangtools.yang.common.QName; @@ -15,6 +16,9 @@ import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; +import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementDefinitionContext; /** * @@ -68,6 +72,14 @@ public abstract class AbstractStatementSupport return type; } + @Override + public Optional> beforeSubStatementCreated(final StmtContext.Mutable stmt, + final int offset, final StatementDefinitionContext def, final StatementSourceReference ref, + final String argument) { + // NOOP for most implementations and also no implicit statements + return Optional.empty(); + } + @Override public void onStatementAdded(final StmtContext.Mutable stmt) { // NOOP for most implementations diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupport.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupport.java index d8555dea68..4ccffedb2c 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupport.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupport.java @@ -8,10 +8,15 @@ package org.opendaylight.yangtools.yang.parser.spi.meta; +import java.util.Optional; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; +import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementDefinitionContext; /** * @@ -69,6 +74,29 @@ public interface StatementSupport, E extends E */ void onStatementAdded(StmtContext.Mutable stmt); + /** + * Invoked before a substatement with specified offset, definition, + * reference and argument is created and added to parent statement. This + * allows implementations of this interface perform any modifications to the + * build context hierarchy before a substatement is created. One such use is + * creating an implicit statement. + * + * @param stmt + * Context of parent statement where a new substatement should be + * created. No substatements are available. + * @param offset + * substatement offset + * @param def + * definition context + * @param ref + * source reference + * @param argument + * substatement argument + * @return optional of an implicit substatement + */ + Optional> beforeSubStatementCreated(final Mutable stmt, final int offset, + final StatementDefinitionContext def, final StatementSourceReference ref, final String argument); + /** * Invoked when statement is closed during * {@link ModelProcessingPhase#SOURCE_PRE_LINKAGE} phase, only substatements diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java index 5c1fa6329c..cfbd93377c 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java @@ -34,6 +34,7 @@ import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; +import org.opendaylight.yangtools.yang.model.api.meta.StatementSource; import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; @@ -130,7 +131,10 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh QName name, final String argument, final StatementSourceReference ref) { if (current != null) { // Fast path: we are entering a statement which was emitted in previous phase - final StatementContextBase existing = current.lookupSubstatement(childId); + StatementContextBase existing = current.lookupSubstatement(childId); + while (existing != null && StatementSource.CONTEXT == existing.getStatementSource()) { + existing = existing.lookupSubstatement(childId); + } if (existing != null) { return existing; } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java index d478818e2a..31c9333e56 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.EnumMap; import java.util.EventListener; import java.util.Iterator; +import java.util.Optional; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; @@ -356,13 +357,19 @@ public abstract class StatementContextBase, E * @param argument statement argument * @return A new substatement */ - public final , CE extends EffectiveStatement> StatementContextBase - createSubstatement(final int offset, final StatementDefinitionContext def, - final StatementSourceReference ref, final String argument) { + public final , CE extends EffectiveStatement> StatementContextBase createSubstatement( + final int offset, final StatementDefinitionContext def, final StatementSourceReference ref, + final String argument) { final ModelProcessingPhase inProgressPhase = getRoot().getSourceContext().getInProgressPhase(); Preconditions.checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL, "Declared statement cannot be added in effective phase at: %s", getStatementSourceReference()); + final Optional> implicitStatement = definition.beforeSubStatementCreated(this, offset, def, ref, argument); + if(implicitStatement.isPresent()) { + final StatementContextBase presentImplicitStmt = implicitStatement.get(); + return presentImplicitStmt.createSubstatement(offset, def, ref, argument); + } + final StatementContextBase ret = new SubstatementContext<>(this, def, ref, argument); substatements = substatements.put(offset, ret); def.onStatementAdded(ret); diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextWriter.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextWriter.java index 9b6bda0429..1eddffd827 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextWriter.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextWriter.java @@ -11,6 +11,7 @@ import com.google.common.base.Preconditions; import com.google.common.base.Verify; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.meta.StatementSource; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter; @@ -36,7 +37,12 @@ final class StatementContextWriter implements StatementWriter { public void endStatement(@Nonnull final StatementSourceReference ref) { Preconditions.checkState(current != null); current.endDeclared(ref, phase); - current = current.getParentContext(); + StatementContextBase parentContext = current.getParentContext(); + while (parentContext != null && StatementSource.CONTEXT == parentContext.getStatementSource()) { + parentContext.endDeclared(ref, phase); + parentContext = parentContext.getParentContext(); + } + current = parentContext; } @Nonnull diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementDefinitionContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementDefinitionContext.java index 08a97419b6..c1a1d2581a 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementDefinitionContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementDefinitionContext.java @@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor; import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Preconditions; +import java.util.Optional; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; @@ -20,6 +21,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StatementFactory; import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; +import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; public class StatementDefinitionContext, E extends EffectiveStatement> { private final StatementSupport support; @@ -44,6 +46,11 @@ public class StatementDefinitionContext, E ext return support.getPublicView(); } + public Optional> beforeSubStatementCreated(final Mutable stmt, final int offset, final StatementDefinitionContext def, final StatementSourceReference ref, + final String argument) { + return support.beforeSubStatementCreated(stmt, offset, def, ref, argument); + } + public boolean onStatementAdded(final Mutable stmt) { support.onStatementAdded(stmt); return false; diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java index 24a45628f3..5a009523e7 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java @@ -141,7 +141,7 @@ final class SubstatementContext, E extends Eff public StatementContextBase createCopy(final QNameModule newQNameModule, final StatementContextBase newParent, final CopyType typeOfCopy) { Preconditions.checkState(getCompletedPhase() == ModelProcessingPhase.EFFECTIVE_MODEL, - "Attempted to copy statement {} which has completed phase {}", this, getCompletedPhase()); + "Attempted to copy statement %s which has completed phase %s", this, getCompletedPhase()); final SubstatementContext copy = new SubstatementContext<>(this, newQNameModule, newParent, typeOfCopy); diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChoiceStatementImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChoiceStatementImpl.java index b45fc9238d..5918274c6a 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChoiceStatementImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/ChoiceStatementImpl.java @@ -8,6 +8,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; import java.util.Collection; +import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.yangtools.yang.common.QName; @@ -26,8 +27,13 @@ import org.opendaylight.yangtools.yang.model.api.stmt.WhenStatement; import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement; import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport; +import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; +import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement; +import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementDefinitionContext; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.ChoiceEffectiveStatementImpl; public class ChoiceStatementImpl extends AbstractDeclaredStatement @@ -54,9 +60,9 @@ public class ChoiceStatementImpl extends AbstractDeclaredStatement super(context); } - public static class Definition - extends + public static class Definition extends AbstractStatementSupport> { + private static final StatementSupport IMPLICIT_CASE = new CaseStatementImpl.Definition(); public Definition() { super(YangStmtMapping.CHOICE); @@ -68,13 +74,24 @@ public class ChoiceStatementImpl extends AbstractDeclaredStatement } @Override - public void onStatementAdded(final Mutable> stmt) { + public Optional> beforeSubStatementCreated( + final StmtContext.Mutable stmt, final int offset, + final StatementDefinitionContext def, final StatementSourceReference ref, final String argument) { + + if (YangValidationBundles.SUPPORTED_CASE_SHORTHANDS.contains(def.getPublicView())) { + return Optional.of(createImplicitCase((StatementContextBase) stmt, offset, ref, argument)); + } + return Optional.empty(); + } + + @Override + public void onStatementAdded( + final Mutable> stmt) { stmt.getParentContext().addToNs(ChildSchemaNodes.class, stmt.getStatementArgument(), stmt); } @Override - public ChoiceStatement createDeclared( - final StmtContext ctx) { + public ChoiceStatement createDeclared(final StmtContext ctx) { return new ChoiceStatementImpl(ctx); } @@ -88,6 +105,17 @@ public class ChoiceStatementImpl extends AbstractDeclaredStatement protected SubstatementValidator getSubstatementValidator() { return SUBSTATEMENT_VALIDATOR; } + + protected StatementSupport implictCase() { + return IMPLICIT_CASE; + } + + private StatementContextBase createImplicitCase(final StmtContext.Mutable stmt, + final int offset, final StatementSourceReference ref, final String argument) { + final StatementDefinitionContext def = new StatementDefinitionContext<>(implictCase()); + return ((StatementContextBase) stmt).createSubstatement(offset, def, ImplicitSubstatement.of(ref), + argument); + } } @Nonnull diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ChoiceStatementRfc7950Support.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ChoiceStatementRfc7950Support.java index 23f830ed80..15e79b0328 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ChoiceStatementRfc7950Support.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc7950/ChoiceStatementRfc7950Support.java @@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc7950; import com.google.common.annotations.Beta; import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator; +import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.ChoiceStatementImpl; /** @@ -36,6 +37,13 @@ public final class ChoiceStatementRfc7950Support extends ChoiceStatementImpl.Def .addOptional(YangStmtMapping.WHEN) .build(); + private static final StatementSupport IMPLICIT_CASE = new CaseStatementRfc7950Support(); + + @Override + protected StatementSupport implictCase() { + return IMPLICIT_CASE; + } + @Override protected SubstatementValidator getSubstatementValidator() { return SUBSTATEMENT_VALIDATOR; diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6183Test.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6183Test.java new file mode 100644 index 0000000000..c1b0c31bc6 --- /dev/null +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug6183Test.java @@ -0,0 +1,106 @@ +/* + * 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.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; +import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +public class Bug6183Test { + private static final String FOO_NS = "foo"; + private static final String FOO_REV = "1970-01-01"; + + @Test + public void testYang10() throws Exception { + assertSchemaContext(StmtTestUtils.parseYangSources("/bugs/bug6183/yang10")); + } + + @Test + public void testYang11() throws Exception { + assertSchemaContext(StmtTestUtils.parseYangSources("/bugs/bug6183/yang11")); + } + + public void assertSchemaContext(final SchemaContext context) throws Exception { + assertNotNull(context); + assertEquals(3, context.getChildNodes().size()); + assertEquals(1, context.getModules().size()); + assertEquals(4, context.getModules().iterator().next().getAugmentations().size()); + + assertTrue(context.getDataChildByName(foo("before")) instanceof ContainerSchemaNode); + assertTrue(context.getDataChildByName(foo("after")) instanceof ContainerSchemaNode); + + final DataSchemaNode dataChildByName = context.getDataChildByName(foo("my-choice")); + assertTrue(dataChildByName instanceof ChoiceSchemaNode); + final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) dataChildByName; + + assertEquals(4, myChoice.getCases().size()); + + final ChoiceCaseNode implCase = myChoice.getCaseNodeByName(foo("implicit-case-container")); + assertNotNull(implCase); + final ChoiceCaseNode declCaseOne = myChoice.getCaseNodeByName(foo("declared-case-one")); + assertNotNull(declCaseOne); + final ChoiceCaseNode secondImplCase = myChoice.getCaseNodeByName(foo("second-implicit-case-container")); + assertNotNull(secondImplCase); + final ChoiceCaseNode declCaseTwo = myChoice.getCaseNodeByName(foo("declared-case-two")); + assertNotNull(declCaseTwo); + + assertEquals(1, declCaseOne.getChildNodes().size()); + assertFalse(getLeafSchemaNode(declCaseOne, "leaf-in-declare-case-one").isAugmenting()); + assertEquals(1, declCaseTwo.getChildNodes().size()); + assertFalse(getLeafSchemaNode(declCaseTwo, "leaf-in-declare-case-two").isAugmenting()); + + assertEquals(2, implCase.getChildNodes().size()); + assertTrue(getLeafSchemaNode(implCase, "leaf-after-container").isAugmenting()); + final ContainerSchemaNode implCaseContainer = getContainerSchemaNode(implCase, "implicit-case-container"); + + assertEquals(3, implCaseContainer.getChildNodes().size()); + assertTrue(getLeafSchemaNode(implCaseContainer, "leaf-inside-container").isAugmenting()); + assertFalse(getLeafSchemaNode(implCaseContainer, "declared-leaf-in-case-container").isAugmenting()); + final ContainerSchemaNode declContInCaseCont = getContainerSchemaNode(implCaseContainer, + "declared-container-in-case-container"); + + assertEquals(1, declContInCaseCont.getChildNodes().size()); + assertFalse(getLeafSchemaNode(declContInCaseCont, "declared-leaf").isAugmenting()); + + assertEquals(2, secondImplCase.getChildNodes().size()); + assertTrue(getLeafSchemaNode(secondImplCase, "leaf-after-second-container").isAugmenting()); + final ContainerSchemaNode secondImplCaseContainer = getContainerSchemaNode(secondImplCase, + "second-implicit-case-container"); + + assertEquals(2, secondImplCaseContainer.getChildNodes().size()); + assertTrue(getLeafSchemaNode(secondImplCaseContainer, "leaf-inside-second-container").isAugmenting()); + assertFalse(getLeafSchemaNode(secondImplCaseContainer, "declared-leaf-in-second-case-container").isAugmenting()); + } + + private static ContainerSchemaNode getContainerSchemaNode(final DataNodeContainer parent, final String containerName) { + final DataSchemaNode dataChildByName = parent.getDataChildByName(foo(containerName)); + assertTrue(dataChildByName instanceof ContainerSchemaNode); + return (ContainerSchemaNode) dataChildByName; + } + + private static LeafSchemaNode getLeafSchemaNode(final DataNodeContainer parent, final String leafName) { + final DataSchemaNode dataChildByName = parent.getDataChildByName(foo(leafName)); + assertTrue(dataChildByName instanceof LeafSchemaNode); + return (LeafSchemaNode) dataChildByName; + } + + private static QName foo(final String localName) { + return QName.create(FOO_NS, FOO_REV, localName); + } +} diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang10/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang10/foo.yang new file mode 100644 index 0000000000..1b1961b495 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang10/foo.yang @@ -0,0 +1,62 @@ +module foo { + namespace "foo"; + prefix "foo"; + + container before { + } + + choice my-choice { + container implicit-case-container { + container declared-container-in-case-container { + leaf declared-leaf { + type empty; + } + } + leaf declared-leaf-in-case-container { + type empty; + } + } + case declared-case-one { + leaf leaf-in-declare-case-one { + type empty; + } + } + container second-implicit-case-container { + leaf declared-leaf-in-second-case-container { + type empty; + } + } + case declared-case-two { + leaf leaf-in-declare-case-two { + type empty; + } + } + } + + container after { + } + + augment "/my-choice/implicit-case-container" { + leaf leaf-after-container { + type empty; + } + } + + augment "/my-choice/implicit-case-container/implicit-case-container" { + leaf leaf-inside-container { + type empty; + } + } + + augment "/my-choice/second-implicit-case-container" { + leaf leaf-after-second-container { + type empty; + } + } + + augment "/my-choice/second-implicit-case-container/second-implicit-case-container" { + leaf leaf-inside-second-container { + type empty; + } + } +} diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang11/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang11/foo.yang new file mode 100644 index 0000000000..f1aa472206 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/bugs/bug6183/yang11/foo.yang @@ -0,0 +1,63 @@ +module foo { + namespace "foo"; + prefix "foo"; + yang-version 1.1; + + container before { + } + + choice my-choice { + container implicit-case-container { + container declared-container-in-case-container { + leaf declared-leaf { + type empty; + } + } + leaf declared-leaf-in-case-container { + type empty; + } + } + case declared-case-one { + leaf leaf-in-declare-case-one { + type empty; + } + } + container second-implicit-case-container { + leaf declared-leaf-in-second-case-container { + type empty; + } + } + case declared-case-two { + leaf leaf-in-declare-case-two { + type empty; + } + } + } + + container after { + } + + augment "/my-choice/implicit-case-container" { + leaf leaf-after-container { + type empty; + } + } + + augment "/my-choice/implicit-case-container/implicit-case-container" { + leaf leaf-inside-container { + type empty; + } + } + + augment "/my-choice/second-implicit-case-container" { + leaf leaf-after-second-container { + type empty; + } + } + + augment "/my-choice/second-implicit-case-container/second-implicit-case-container" { + leaf leaf-inside-second-container { + type empty; + } + } +} -- 2.36.6