Fix SchemaInferenceStack.exitToDataTree() 78/95978/3
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 2 May 2021 14:21:32 +0000 (16:21 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 3 May 2021 09:16:19 +0000 (11:16 +0200)
When we are exiting along data tree axis we need to make sure we skip
any choice/case node hierarchy, so that we arrive at the correct data
tree parent -- even if we arrived via the schema tree.

JIRA: YANGTOOLS-1283
Change-Id: I9d84f59447971fcdfb0cc187e5d2c4a35579bfa6
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
model/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaInferenceStack.java
model/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/YT1283Test.java [new file with mode: 0644]
model/yang-model-util/src/test/resources/yt1283.yang [new file with mode: 0644]

index 75a8f50d675c67e92362066117e3ecd31d7a62ec..4a6c97a2113a23305be0c63bc617c1d68bd0bab1 100644 (file)
@@ -481,7 +481,12 @@ public final class SchemaInferenceStack implements Mutable, EffectiveModelContex
     public @NonNull DataTreeEffectiveStatement<?> exitToDataTree() {
         final EffectiveStatement<?, ?> child = exit();
         checkState(child instanceof DataTreeEffectiveStatement, "Unexpected current %s", child);
-        final EffectiveStatement<?, ?> parent = deque.peekFirst();
+        EffectiveStatement<?, ?> parent = deque.peekFirst();
+        while (parent instanceof ChoiceEffectiveStatement || parent instanceof CaseEffectiveStatement) {
+            deque.pollFirst();
+            parent = deque.peekFirst();
+        }
+
         checkState(parent == null || parent instanceof DataTreeAwareEffectiveStatement, "Unexpected parent %s", parent);
         return (DataTreeEffectiveStatement<?>) child;
     }
diff --git a/model/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/YT1283Test.java b/model/yang-model-util/src/test/java/org/opendaylight/yangtools/yang/model/util/YT1283Test.java
new file mode 100644 (file)
index 0000000..2493c07
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.model.util;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.BeforeClass;
+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.meta.EffectiveStatement;
+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.LeafEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PathEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public class YT1283Test {
+    private static final QName FOO = QName.create("foo", "foo");
+    private static final QName BAR = QName.create("foo", "bar");
+
+    private static EffectiveModelContext context;
+
+    private final SchemaInferenceStack stack = SchemaInferenceStack.of(context);
+
+    @BeforeClass
+    public static void beforeClass() {
+        context = YangParserTestUtils.parseYangResource("/yt1283.yang");
+    }
+
+    @Test
+    public void testResolveUnderCaseViaDataTree() {
+        assertThat(stack.enterDataTree(FOO), instanceOf(ContainerEffectiveStatement.class));
+        assertResolve(stack.enterDataTree(FOO));
+    }
+
+    @Test
+    public void testResolveUnderCaseViaSchemaTree() {
+        assertThat(stack.enterSchemaTree(FOO), instanceOf(ContainerEffectiveStatement.class));
+        assertThat(stack.enterSchemaTree(FOO), instanceOf(ChoiceEffectiveStatement.class));
+        assertThat(stack.enterSchemaTree(FOO), instanceOf(CaseEffectiveStatement.class));
+        assertResolve(stack.enterSchemaTree(FOO));
+    }
+
+    private void assertResolve(final EffectiveStatement<?, ?> foo) {
+        assertThat(foo, instanceOf(LeafEffectiveStatement.class));
+
+        final TypeEffectiveStatement<?> type = foo.findFirstEffectiveSubstatement(TypeEffectiveStatement.class)
+            .orElseThrow();
+        final EffectiveStatement<?, ?> bar = stack.resolvePathExpression(
+            type.findFirstEffectiveSubstatementArgument(PathEffectiveStatement.class).orElseThrow());
+        assertThat(bar, instanceOf(LeafEffectiveStatement.class));
+        assertEquals(BAR, bar.argument());
+    }
+}
diff --git a/model/yang-model-util/src/test/resources/yt1283.yang b/model/yang-model-util/src/test/resources/yt1283.yang
new file mode 100644 (file)
index 0000000..ef7685b
--- /dev/null
@@ -0,0 +1,20 @@
+module foo {
+  namespace foo;
+  prefix foo;
+
+  container foo {
+    choice foo {
+      case foo {
+        leaf foo {
+          type leafref {
+            path ../../bar;
+          }
+        }
+      }
+    }
+  }
+
+  leaf bar {
+    type string;
+  }
+}