2 * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.model.util;
10 import static org.hamcrest.CoreMatchers.instanceOf;
11 import static org.hamcrest.CoreMatchers.startsWith;
12 import static org.hamcrest.MatcherAssert.assertThat;
13 import static org.hamcrest.Matchers.isA;
14 import static org.junit.Assert.assertEquals;
15 import static org.junit.Assert.assertThrows;
17 import org.junit.BeforeClass;
18 import org.junit.Test;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
22 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
23 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.Module;
26 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
28 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
30 public class LeafrefStaticAnalysisTest {
31 private static final QName FOO = QName.create("leafrefs", "foo");
33 private static EffectiveModelContext context;
34 private static GroupingDefinition grp;
35 private static ListSchemaNode foo;
36 private static ContainerSchemaNode bar;
37 private static Module module;
40 public static void beforeClass() {
41 context = YangParserTestUtils.parseYangResource("/leafrefs.yang");
42 module = context.getModules().iterator().next();
44 foo = (ListSchemaNode) module.findDataChildByName(FOO).get();
45 bar = (ContainerSchemaNode) foo.findDataChildByName(QName.create(FOO, "bar")).get();
46 grp = module.getGroupings().iterator().next();
50 public void testGrpOuterId() {
51 final LeafSchemaNode leaf = (LeafSchemaNode) grp.findDataChildByName(QName.create(FOO, "outer-id")).get();
52 // Cannot be found as the reference goes outside of the grouping
53 final SchemaInferenceStack stack = SchemaInferenceStack.of(context);
54 stack.enterGrouping(grp.getQName());
55 stack.enterSchemaTree(QName.create(FOO, "outer-id"));
56 assertThrowsInvalidPath(stack, leaf);
60 public void testFooOuterId() {
61 final LeafSchemaNode leaf = (LeafSchemaNode) bar.findDataChildByName(QName.create(FOO, "outer-id")).get();
62 final SchemaInferenceStack stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
63 stack.enterSchemaTree(QName.create(FOO, "outer-id"));
64 final SchemaNode found = (SchemaNode) stack.resolvePathExpression(((LeafrefTypeDefinition) leaf.getType())
67 assertThat(found, isA(LeafSchemaNode.class));
68 assertEquals(QName.create(FOO, "id"), found.getQName());
72 public void testGrpOuterIndirectProp() {
73 final LeafSchemaNode leaf = (LeafSchemaNode) grp.findDataChildByName(
74 QName.create(FOO, "outer-indirect-prop")).get();
75 final SchemaInferenceStack stack = SchemaInferenceStack.of(context);
76 stack.enterGrouping(grp.getQName());
77 stack.enterSchemaTree(QName.create(FOO, "outer-indirect-prop"));
78 // Cannot resolve deref outer-id
79 assertThrowsInvalidPath(stack, leaf);
83 public void testFooOuterIndirectProp() {
84 final LeafSchemaNode leaf = (LeafSchemaNode) bar.findDataChildByName(
85 QName.create(FOO, "outer-indirect-prop")).get();
86 final SchemaInferenceStack stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
87 stack.enterSchemaTree(QName.create(FOO, "outer-indirect-prop"));
88 final SchemaNode found = (SchemaNode) stack.resolvePathExpression(((LeafrefTypeDefinition) leaf.getType())
91 assertThat(found, isA(LeafSchemaNode.class));
92 assertEquals(QName.create(FOO, "prop"), found.getQName());
96 public void testGrpIndirect() {
97 final LeafSchemaNode leaf = (LeafSchemaNode) grp.findDataChildByName(QName.create(FOO, "indirect")).get();
98 final SchemaInferenceStack stack = SchemaInferenceStack.of(context);
99 stack.enterGrouping(grp.getQName());
100 stack.enterSchemaTree(QName.create(FOO, "indirect"));
101 final SchemaNode found = (SchemaNode) stack.resolvePathExpression(((LeafrefTypeDefinition) leaf.getType())
102 .getPathStatement());
104 assertThat(found, isA(LeafSchemaNode.class));
105 assertEquals(QName.create(FOO, "prop"), found.getQName());
109 public void testFooIndirect() {
110 final LeafSchemaNode leaf = (LeafSchemaNode) bar.findDataChildByName(QName.create(FOO, "indirect")).get();
111 final SchemaInferenceStack stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
112 stack.enterSchemaTree(QName.create(FOO, "indirect"));
113 final SchemaNode found = (SchemaNode) stack.resolvePathExpression(((LeafrefTypeDefinition) leaf.getType())
114 .getPathStatement());
116 assertThat(found, isA(LeafSchemaNode.class));
117 assertEquals(QName.create(FOO, "prop"), found.getQName());
121 public void testGrpDerefNonExistent() {
122 final LeafSchemaNode leaf = (LeafSchemaNode) grp.findDataChildByName(
123 QName.create(FOO, "deref-non-existent")).get();
124 final SchemaInferenceStack stack = SchemaInferenceStack.of(context);
125 stack.enterGrouping(grp.getQName());
126 stack.enterSchemaTree(QName.create(FOO, "deref-non-existent"));
127 assertThrowsMissingXyzzy(stack, leaf);
131 public void testFooDerefNonExistent() {
132 final LeafSchemaNode leaf = (LeafSchemaNode) bar.findDataChildByName(
133 QName.create(FOO, "deref-non-existent")).get();
134 final SchemaInferenceStack stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
135 stack.enterSchemaTree(QName.create(FOO, "deref-non-existent"));
136 assertThrowsMissingXyzzy(stack, leaf);
140 public void testGrpNonExistentDeref() {
141 final LeafSchemaNode leaf = (LeafSchemaNode) grp.findDataChildByName(
142 QName.create(FOO, "non-existent-deref")).get();
143 final SchemaInferenceStack stack = SchemaInferenceStack.of(context);
144 stack.enterGrouping(grp.getQName());
145 stack.enterSchemaTree(QName.create(FOO, "non-existent-deref"));
146 assertThrowsMissingXyzzy(stack, leaf);
150 public void testFooNonExistentDeref() {
151 final LeafSchemaNode leaf = (LeafSchemaNode) bar.findDataChildByName(
152 QName.create(FOO, "non-existent-deref")).get();
153 final SchemaInferenceStack stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
154 stack.enterSchemaTree(QName.create(FOO, "non-existent-deref"));
155 assertThrowsMissingXyzzy(stack, leaf);
159 public void testNonExistentRelativeXpath() {
160 final LeafSchemaNode leaf = (LeafSchemaNode) bar.findDataChildByName(
161 QName.create(FOO, "indirect-with-current")).get();
162 final SchemaInferenceStack stack = SchemaInferenceStack.ofDataTreePath(context,
163 foo.getQName(), bar.getQName(), QName.create(FOO, "indirect-with-current"));
164 assertThrowsMissingChild(stack, leaf, "(leafrefs)n");
167 private static void assertThrowsInvalidPath(final SchemaInferenceStack stack, final LeafSchemaNode leaf) {
168 final IllegalArgumentException ex = assertThrowsIAE(stack, leaf);
169 assertThat(ex.getMessage(), startsWith("Illegal parent access in "));
170 final Throwable cause = ex.getCause();
171 assertThat(cause, instanceOf(IllegalStateException.class));
172 assertEquals("Unexpected current GroupingEffectiveStatementImpl[qname=(leafrefs)grp]", cause.getMessage());
175 private static void assertThrowsMissingXyzzy(final SchemaInferenceStack stack, final LeafSchemaNode leaf) {
176 assertThrowsMissingChild(stack, leaf, "(leafrefs)xyzzy");
179 private static void assertThrowsMissingChild(final SchemaInferenceStack stack, final LeafSchemaNode leaf,
180 final String childName) {
181 assertEquals("Data tree child " + childName + " not present", assertThrowsIAE(stack, leaf).getMessage());
184 private static IllegalArgumentException assertThrowsIAE(final SchemaInferenceStack stack,
185 final LeafSchemaNode leaf) {
186 return assertThrows(IllegalArgumentException.class,
187 () -> stack.resolvePathExpression(((LeafrefTypeDefinition) leaf.getType()).getPathStatement()));