Migrate yang-model-util to JUnit5
[yangtools.git] / model / yang-model-util / src / test / java / org / opendaylight / yangtools / yang / model / util / LeafrefStaticAnalysisTest.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.model.util;
9
10 import static org.hamcrest.CoreMatchers.startsWith;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.junit.jupiter.api.Assertions.assertEquals;
13 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
14 import static org.junit.jupiter.api.Assertions.assertThrows;
15
16 import org.junit.jupiter.api.BeforeAll;
17 import org.junit.jupiter.api.Test;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
21 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
22 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.Module;
25 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
26 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
27
28 class LeafrefStaticAnalysisTest {
29     private static final QName FOO = QName.create("leafrefs", "foo");
30
31     private static EffectiveModelContext context;
32     private static GroupingDefinition grp;
33     private static ListSchemaNode foo;
34     private static ContainerSchemaNode bar;
35     private static Module module;
36
37     @BeforeAll
38     static void beforeClass() {
39         context = YangParserTestUtils.parseYangResource("/leafrefs.yang");
40         module = context.getModules().iterator().next();
41
42         foo = assertInstanceOf(ListSchemaNode.class, module.getDataChildByName(FOO));
43         bar = assertInstanceOf(ContainerSchemaNode.class, foo.getDataChildByName(QName.create(FOO, "bar")));
44         grp = module.getGroupings().iterator().next();
45     }
46
47     @Test
48     void testGrpOuterId() {
49         final var leaf = assertInstanceOf(LeafSchemaNode.class, grp.getDataChildByName(QName.create(FOO, "outer-id")));
50         // Cannot be found as the reference goes outside of the grouping
51         final var stack = SchemaInferenceStack.of(context);
52         stack.enterGrouping(grp.getQName());
53         stack.enterSchemaTree(QName.create(FOO, "outer-id"));
54         assertThrowsInvalidPath(stack, leaf);
55     }
56
57     @Test
58     void testFooOuterId() {
59         final var leaf = assertInstanceOf(LeafSchemaNode.class, bar.getDataChildByName(QName.create(FOO, "outer-id")));
60         final var leafType = assertInstanceOf(LeafrefTypeDefinition.class, leaf.getType());
61         final var stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
62         stack.enterSchemaTree(QName.create(FOO, "outer-id"));
63         final var found = assertInstanceOf(LeafSchemaNode.class,
64             stack.resolvePathExpression(leafType.getPathStatement()));
65         assertEquals(QName.create(FOO, "id"), found.getQName());
66     }
67
68     @Test
69     void testGrpOuterIndirectProp() {
70         final var leaf = assertInstanceOf(LeafSchemaNode.class,
71             grp.getDataChildByName(QName.create(FOO, "outer-indirect-prop")));
72         final var stack = SchemaInferenceStack.of(context);
73         stack.enterGrouping(grp.getQName());
74         stack.enterSchemaTree(QName.create(FOO, "outer-indirect-prop"));
75         // Cannot resolve deref outer-id
76         assertThrowsInvalidPath(stack, leaf);
77     }
78
79     @Test
80     void testFooOuterIndirectProp() {
81         final var leaf = assertInstanceOf(LeafSchemaNode.class,
82             bar.getDataChildByName(QName.create(FOO, "outer-indirect-prop")));
83         final var leafType = assertInstanceOf(LeafrefTypeDefinition.class, leaf.getType());
84         final var stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
85         stack.enterSchemaTree(QName.create(FOO, "outer-indirect-prop"));
86         final var found = assertInstanceOf(LeafSchemaNode.class,
87             stack.resolvePathExpression(leafType.getPathStatement()));
88         assertEquals(QName.create(FOO, "prop"), found.getQName());
89     }
90
91     @Test
92     void testGrpIndirect() {
93         final var leaf = assertInstanceOf(LeafSchemaNode.class, grp.getDataChildByName(QName.create(FOO, "indirect")));
94         final var leafType = assertInstanceOf(LeafrefTypeDefinition.class, leaf.getType());
95         final var stack = SchemaInferenceStack.of(context);
96         stack.enterGrouping(grp.getQName());
97         stack.enterSchemaTree(QName.create(FOO, "indirect"));
98         final var found = assertInstanceOf(LeafSchemaNode.class,
99             stack.resolvePathExpression(leafType.getPathStatement()));
100         assertEquals(QName.create(FOO, "prop"), found.getQName());
101     }
102
103     @Test
104     void testFooIndirect() {
105         final var leaf = assertInstanceOf(LeafSchemaNode.class, bar.getDataChildByName(QName.create(FOO, "indirect")));
106         final var leafType = assertInstanceOf(LeafrefTypeDefinition.class, leaf.getType());
107         final var stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
108         stack.enterSchemaTree(QName.create(FOO, "indirect"));
109         final var found = assertInstanceOf(LeafSchemaNode.class,
110             stack.resolvePathExpression(leafType.getPathStatement()));
111         assertEquals(QName.create(FOO, "prop"), found.getQName());
112     }
113
114     @Test
115     void testGrpDerefNonExistent() {
116         final var leaf = assertInstanceOf(LeafSchemaNode.class,
117             grp.getDataChildByName(QName.create(FOO, "deref-non-existent")));
118         final var stack = SchemaInferenceStack.of(context);
119         stack.enterGrouping(grp.getQName());
120         stack.enterSchemaTree(QName.create(FOO, "deref-non-existent"));
121         assertThrowsMissingXyzzy(stack, leaf, "grouping (leafrefs)grp");
122     }
123
124     @Test
125     void testFooDerefNonExistent() {
126         final var leaf = assertInstanceOf(LeafSchemaNode.class,
127             bar.getDataChildByName(QName.create(FOO, "deref-non-existent")));
128         final var stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
129         stack.enterSchemaTree(QName.create(FOO, "deref-non-existent"));
130         assertThrowsMissingXyzzy(stack, leaf, "schema parent (leafrefs)bar");
131     }
132
133     @Test
134     void testGrpNonExistentDeref() {
135         final var leaf = assertInstanceOf(LeafSchemaNode.class,
136             grp.getDataChildByName(QName.create(FOO, "non-existent-deref")));
137         final var stack = SchemaInferenceStack.of(context);
138         stack.enterGrouping(grp.getQName());
139         stack.enterSchemaTree(QName.create(FOO, "non-existent-deref"));
140         assertThrowsMissingXyzzy(stack, leaf, "schema parent (leafrefs)foo");
141     }
142
143     @Test
144     void testFooNonExistentDeref() {
145         final var leaf = assertInstanceOf(LeafSchemaNode.class,
146             bar.getDataChildByName(QName.create(FOO, "non-existent-deref")));
147         final var stack = SchemaInferenceStack.ofDataTreePath(context, foo.getQName(), bar.getQName());
148         stack.enterSchemaTree(QName.create(FOO, "non-existent-deref"));
149         assertThrowsMissingXyzzy(stack, leaf, "schema parent (leafrefs)foo");
150     }
151
152     @Test
153     void testNonExistentRelativeXpath() {
154         final var leaf = assertInstanceOf(LeafSchemaNode.class,
155             bar.getDataChildByName(QName.create(FOO, "indirect-with-current")));
156         final var stack = SchemaInferenceStack.ofDataTreePath(context,
157             foo.getQName(), bar.getQName(), QName.create(FOO, "indirect-with-current"));
158         assertThrowsMissingChild(stack, leaf, "(leafrefs)n", "module (leafrefs)leafrefs");
159     }
160
161     private static void assertThrowsInvalidPath(final SchemaInferenceStack stack, final LeafSchemaNode leaf) {
162         final var ex = assertThrowsIAE(stack, leaf);
163         assertThat(ex.getMessage(), startsWith("Illegal parent access in "));
164         final var cause = assertInstanceOf(IllegalStateException.class, ex.getCause());
165         assertEquals("Unexpected current EmptyGroupingEffectiveStatement{argument=(leafrefs)grp}", cause.getMessage());
166     }
167
168     private static void assertThrowsMissingXyzzy(final SchemaInferenceStack stack, final LeafSchemaNode leaf,
169             final String parentDesc) {
170         assertThrowsMissingChild(stack, leaf, "(leafrefs)xyzzy", parentDesc);
171     }
172
173     private static void assertThrowsMissingChild(final SchemaInferenceStack stack, final LeafSchemaNode leaf,
174             final String childName, final String parentDesc) {
175         assertEquals("Data tree child " + childName + " not present in " + parentDesc,
176             assertThrowsIAE(stack, leaf).getMessage());
177     }
178
179     private static IllegalArgumentException assertThrowsIAE(final SchemaInferenceStack stack,
180             final LeafSchemaNode leaf) {
181         return assertThrows(IllegalArgumentException.class, () -> stack.resolvePathExpression(
182             assertInstanceOf(LeafrefTypeDefinition.class, leaf.getType()).getPathStatement()));
183     }
184 }