2 * Copyright (c) 2021 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.data.tree.impl;
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertThrows;
13 import java.util.function.Consumer;
14 import org.junit.jupiter.api.BeforeAll;
15 import org.junit.jupiter.api.Test;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
19 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
20 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
21 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
22 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
23 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
24 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
25 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
26 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
29 private static final QName FOO = QName.create("foo", "foo");
30 private static final QName BAR = QName.create(FOO, "bar");
31 private static final QName BAZ = QName.create(FOO, "baz");
32 private static final QName XYZZY_LEAF = QName.create(FOO, "xyzzy-leaf");
33 private static final QName XYZZY_AUGMENT = QName.create(FOO, "xyzzy-augment");
34 private static final QName XYZZY_AUGMENT_CONT = QName.create(FOO, "xyzzy-augment-container");
35 private static final QName XYZZY_AUGMENT_CONT_INNER = QName.create(FOO, "xyzzy-augment-container-inner");
36 private static final QName XYZZY_AUGMENT_CONT_LEAF = QName.create(FOO, "xyzzy-augment-container-leaf");
37 private static final QName BAZ_AUG_CASE_MANDAT_LEAF = QName.create(FOO, "augmented-case-mandatory");
38 private static final QName BAZ_AUG_CASE_NON_MANDAT_LEAF = QName.create(FOO, "augmented-case-non-mandatory");
39 private static final QName NESTED_BAZ_CHOICE = QName.create(FOO, "nested-baz");
40 private static final QName NESTED_BAZ_XYZ_CASE_MANDATORY = QName.create(FOO, "nested-xyz-mandatory");
41 private static final QName NESTED_BAZ_XYZ_CASE_NON_MANDATORY = QName.create(FOO, "nested-xyz-non-mandatory");
43 private static EffectiveModelContext MODEL;
45 private final DataTree tree = new InMemoryDataTreeFactory()
46 .create(DataTreeConfiguration.DEFAULT_CONFIGURATION, MODEL);
49 static void beforeClass() {
50 MODEL = YangParserTestUtils.parseYangResource("/yt1276.yang");
54 void testFooWithBar() throws DataValidationFailedException {
55 applyOperation(mod -> {
56 mod.write(YangInstanceIdentifier.of(FOO), ImmutableNodes.newContainerBuilder()
57 .withNodeIdentifier(new NodeIdentifier(FOO))
58 .withChild(ImmutableNodes.leafNode(BAR, "xyzzy"))
65 void testFooWithBarLegacy() throws DataValidationFailedException {
66 applyOperation(mod -> {
67 mod.write(YangInstanceIdentifier.of(FOO), ImmutableNodes.newContainerBuilder()
68 .withNodeIdentifier(new NodeIdentifier(FOO))
69 .withChild(ImmutableNodes.leafNode(BAR, "xyzzy"))
75 void testFooWithoutBar() {
76 final IllegalArgumentException ex = assertFailsReady(mod -> {
77 mod.write(YangInstanceIdentifier.of(FOO), ImmutableNodes.newContainerBuilder()
78 .withNodeIdentifier(new NodeIdentifier(FOO))
81 assertEquals("Node (foo)foo is missing mandatory descendant /(foo)bar", ex.getMessage());
85 void testBarWithXyzzyWithSubtree() throws DataValidationFailedException {
86 applyOperation(mod -> {
87 mod.write(YangInstanceIdentifier.of(BAR), ImmutableNodes.newContainerBuilder()
88 .withNodeIdentifier(new NodeIdentifier(BAR))
89 .withChild(ImmutableNodes.newChoiceBuilder()
90 .withNodeIdentifier(new NodeIdentifier(BAZ))
91 .withChild(ImmutableNodes.leafNode(XYZZY_LEAF, "xyzzy"))
92 .withChild(ImmutableNodes.leafNode(XYZZY_AUGMENT, "xyzzy"))
93 .withChild(ImmutableNodes.newContainerBuilder()
94 .withNodeIdentifier(new NodeIdentifier(XYZZY_AUGMENT_CONT))
95 .withChild(ImmutableNodes.newContainerBuilder()
96 .withNodeIdentifier(new NodeIdentifier(XYZZY_AUGMENT_CONT_INNER))
97 .withChild(ImmutableNodes.leafNode(XYZZY_AUGMENT_CONT_LEAF, "aug-cont-leaf"))
106 void testBazWithAugmentedCaseWithMandatoryLeaf() throws DataValidationFailedException {
107 applyOperation(mod -> {
108 mod.write(YangInstanceIdentifier.of(BAR), ImmutableNodes.newContainerBuilder()
109 .withNodeIdentifier(new NodeIdentifier(BAR))
110 .withChild(ImmutableNodes.newChoiceBuilder()
111 .withNodeIdentifier(new NodeIdentifier(BAZ))
112 .withChild(ImmutableNodes.leafNode(BAZ_AUG_CASE_MANDAT_LEAF, "augmentedCaseMandatory"))
113 .withChild(ImmutableNodes.leafNode(BAZ_AUG_CASE_NON_MANDAT_LEAF, "augmentedCaseNonMandatory"))
120 void testBazWithAugmentedCaseWithoutMandatoryLeaf() throws DataValidationFailedException {
121 assertThrows(IllegalArgumentException.class, () -> {
122 applyOperation(mod -> {
123 mod.write(YangInstanceIdentifier.of(BAR), ImmutableNodes.newContainerBuilder()
124 .withNodeIdentifier(new NodeIdentifier(BAR))
125 .withChild(ImmutableNodes.newChoiceBuilder()
126 .withNodeIdentifier(new NodeIdentifier(BAZ))
127 .withChild(ImmutableNodes.leafNode(BAZ_AUG_CASE_NON_MANDAT_LEAF, "augmentedCaseNonMandatory"))
135 void testWithAugmentedNestedBazWithMandatoryLeaf() throws DataValidationFailedException {
136 applyOperation(mod -> {
137 mod.write(YangInstanceIdentifier.of(BAR), ImmutableNodes.newContainerBuilder()
138 .withNodeIdentifier(new NodeIdentifier(BAR))
139 .withChild(ImmutableNodes.newChoiceBuilder()
140 .withNodeIdentifier(new NodeIdentifier(BAZ))
141 .withChild(ImmutableNodes.newChoiceBuilder()
142 .withNodeIdentifier(new NodeIdentifier(NESTED_BAZ_CHOICE))
143 .withChild(ImmutableNodes.leafNode(NESTED_BAZ_XYZ_CASE_MANDATORY, "nestedMandatory"))
144 .withChild(ImmutableNodes.leafNode(NESTED_BAZ_XYZ_CASE_NON_MANDATORY, "nestedNonMandatory"))
152 void testWithAugmentedNestedBazWithhoutMandatoryLeaf() throws DataValidationFailedException {
153 assertThrows(IllegalArgumentException.class, () -> {
154 applyOperation(mod -> {
155 mod.write(YangInstanceIdentifier.of(BAR), ImmutableNodes.newContainerBuilder()
156 .withNodeIdentifier(new NodeIdentifier(BAR))
157 .withChild(ImmutableNodes.newChoiceBuilder()
158 .withNodeIdentifier(new NodeIdentifier(BAZ))
159 .withChild(ImmutableNodes.newChoiceBuilder()
160 .withNodeIdentifier(new NodeIdentifier(NESTED_BAZ_CHOICE))
161 .withChild(ImmutableNodes.leafNode(NESTED_BAZ_XYZ_CASE_NON_MANDATORY, "nestedNonMandatory"))
171 void testBarWithXyzzyLegacy() throws DataValidationFailedException {
172 applyOperation(mod -> {
173 mod.write(YangInstanceIdentifier.of(BAR), ImmutableNodes.newContainerBuilder()
174 .withNodeIdentifier(new NodeIdentifier(BAR))
175 .withChild(ImmutableNodes.newChoiceBuilder()
176 .withNodeIdentifier(new NodeIdentifier(BAZ))
177 .withChild(ImmutableNodes.leafNode(XYZZY_LEAF, "xyzzy"))
178 .withChild(ImmutableNodes.leafNode(XYZZY_AUGMENT, "xyzzy"))
179 .withChild(ImmutableNodes.newContainerBuilder()
180 .withNodeIdentifier(NodeIdentifier.create(XYZZY_AUGMENT_CONT))
181 .withChild(ImmutableNodes.newContainerBuilder()
182 .withNodeIdentifier(NodeIdentifier.create(XYZZY_AUGMENT_CONT_INNER))
183 .withChild(ImmutableNodes.leafNode(XYZZY_AUGMENT_CONT_LEAF, "aug-cont-leaf"))
192 void testBarWithoutXyzzyLeaf() {
193 final var ex = assertFailsReady(mod -> {
194 mod.write(YangInstanceIdentifier.of(BAR), ImmutableNodes.newContainerBuilder()
195 .withNodeIdentifier(new NodeIdentifier(BAR))
196 .withChild(ImmutableNodes.newChoiceBuilder()
197 .withNodeIdentifier(new NodeIdentifier(BAZ))
198 .withChild(ImmutableNodes.leafNode(XYZZY_AUGMENT, "xyzzy"))
199 .withChild(ImmutableNodes.newContainerBuilder()
200 .withNodeIdentifier(NodeIdentifier.create(XYZZY_AUGMENT_CONT))
201 .withChild(ImmutableNodes.newContainerBuilder()
202 .withNodeIdentifier(NodeIdentifier.create(XYZZY_AUGMENT_CONT_INNER))
203 .withChild(ImmutableNodes.leafNode(XYZZY_AUGMENT_CONT_LEAF, "aug-cont-leaf"))
210 "Node (foo)baz is missing mandatory descendant /(foo)xyzzy-leaf",
215 void testBarWithoutXyzzyAugment() {
216 final var ex = assertFailsReady(mod -> {
217 mod.write(YangInstanceIdentifier.of(BAR), ImmutableNodes.newContainerBuilder()
218 .withNodeIdentifier(new NodeIdentifier(BAR))
219 .withChild(ImmutableNodes.newChoiceBuilder()
220 .withNodeIdentifier(new NodeIdentifier(BAZ))
221 .withChild(ImmutableNodes.leafNode(XYZZY_LEAF, "xyzzy"))
225 assertEquals("Node (foo)baz is missing mandatory descendant /(foo)xyzzy-augment", ex.getMessage());
229 private IllegalArgumentException assertFailsReady(final Consumer<DataTreeModification> operation) {
230 return assertThrows(IllegalArgumentException.class, () -> applyOperation(operation));
233 private void applyOperation(final Consumer<DataTreeModification> operation)
234 throws DataValidationFailedException {
235 final var mod = tree.takeSnapshot().newModification();
236 operation.accept(mod);
238 tree.commit(tree.prepare(mod));