2 * Copyright (c) 2018 Pantheon Technologies, 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.impl.schema.tree;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.fail;
12 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.choiceBuilder;
13 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.containerBuilder;
14 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.leafBuilder;
15 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.leafSetBuilder;
16 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.mapBuilder;
17 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.mapEntryBuilder;
19 import com.google.common.collect.ImmutableMap;
20 import org.junit.AfterClass;
21 import org.junit.Before;
22 import org.junit.BeforeClass;
23 import org.junit.Test;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
28 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
31 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
32 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
33 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
36 public class YT776Test {
37 private static final QName MODULE = QName.create("yt776", "yt776");
38 private static final NodeIdentifier BOX = new NodeIdentifier(QName.create(MODULE, "box"));
39 private static final QName OBJECT = QName.create(MODULE, "object");
40 private static final QName OBJECT_ID = QName.create(MODULE, "object-id");
41 private static final NodeIdentifier OBJECT_LIST = new NodeIdentifier(OBJECT);
42 private static final NodeIdentifierWithPredicates OBJECT_ITEM = new NodeIdentifierWithPredicates(OBJECT,
43 ImmutableMap.of(OBJECT_ID, "1"));
44 private static final LeafNode<?> OBJECT_ID_LEAF = leafBuilder().withNodeIdentifier(new NodeIdentifier(OBJECT_ID))
45 .withValue("1").build();
46 private static final NodeIdentifier ATTRIBUTES = new NodeIdentifier(QName.create(MODULE, "attributes"));
48 private static final QName NESTED = QName.create(MODULE, "nested");
49 private static final QName NESTED_ATTRIBUTE = QName.create(MODULE, "nested-attribute");
50 private static final NodeIdentifier NESTED_LIST = new NodeIdentifier(NESTED);
51 private static final NodeIdentifierWithPredicates NESTED_ITEM = new NodeIdentifierWithPredicates(NESTED,
52 ImmutableMap.of(NESTED_ATTRIBUTE, "foo"));
54 private static final NodeIdentifier ANY_OF = new NodeIdentifier(QName.create(MODULE, "any-of"));
55 private static final QName SOME_LEAF = QName.create(MODULE, "some-leaf");
56 private static final NodeIdentifier SOME_LEAF_ID = new NodeIdentifier(SOME_LEAF);
57 private static final QName SOME_LIST = QName.create(MODULE, "some-list");
58 private static final NodeIdentifier SOME_LIST_ID = new NodeIdentifier(SOME_LIST);
59 private static final NodeIdentifierWithPredicates SOME_LIST_ITEM = new NodeIdentifierWithPredicates(SOME_LIST,
60 ImmutableMap.of(SOME_LEAF, "foo"));
61 private static SchemaContext SCHEMA_CONTEXT;
63 private DataTree dataTree;
66 public static void beforeClass() {
67 SCHEMA_CONTEXT = TestModel.createTestContext("/yt776/yt776.yang");
71 public static void afterClass() {
72 SCHEMA_CONTEXT = null;
77 dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION, SCHEMA_CONTEXT);
81 public void testNoAttributes() {
82 final DataTreeModification mod = dataTree.takeSnapshot().newModification();
83 mod.write(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
84 .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
85 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
86 .withChild(OBJECT_ID_LEAF)
93 fail("Should fail with IAE");
94 } catch (IllegalArgumentException e) {
95 // FIXME: This is actually mandatory leaf enforcer kicking in: attributes have to be present. This is
96 // most probably not what we want.
97 assertEquals("Node (yt776)object[{(yt776)object-id=1}] is missing mandatory descendant /(yt776)attributes",
103 public void testEmptyAttributes() throws DataValidationFailedException {
104 final DataTreeModification mod = write(containerBuilder().withNodeIdentifier(BOX)
105 .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
106 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
107 .withChild(OBJECT_ID_LEAF)
108 .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES).build())
115 fail("Should fail with IAE");
116 } catch (IllegalArgumentException e) {
117 assertEquals("Node (yt776)attributes does not have enough elements (0), needs at least 1", e.getMessage());
122 public void testOneAttribute() throws DataValidationFailedException {
123 writeAndCommit(containerBuilder().withNodeIdentifier(BOX)
124 .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
125 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
126 .withChild(OBJECT_ID_LEAF)
127 .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
128 .withChildValue("object1")
136 public void testTwoAttributes() throws DataValidationFailedException {
137 writeAndCommit(containerBuilder().withNodeIdentifier(BOX)
138 .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
139 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
140 .withChild(OBJECT_ID_LEAF)
141 .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
142 .withChildValue("object1")
143 .withChildValue("object2")
151 public void testThreeAttributes() throws DataValidationFailedException {
152 final DataTreeModification mod = write(containerBuilder().withNodeIdentifier(BOX)
153 .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
154 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
155 .withChild(OBJECT_ID_LEAF)
156 .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
157 .withChildValue("object1")
158 .withChildValue("object2")
159 .withChildValue("object3")
167 fail("Should fail with IAE");
168 } catch (IllegalArgumentException e) {
169 assertEquals("Node (yt776)attributes has too many elements (3), can have at most 2", e.getMessage());
174 public void testEmptyAndMergeOne() throws DataValidationFailedException {
175 final DataTreeModification mod = dataTree.takeSnapshot().newModification();
176 mod.write(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
177 .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
178 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
179 .withChild(OBJECT_ID_LEAF)
183 mod.merge(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
184 .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
185 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
186 .withChild(OBJECT_ID_LEAF)
187 .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
188 .withChildValue("object1")
198 public void testEmptyAndMergeOneWithListTouched() throws DataValidationFailedException {
199 final DataTreeModification mod = dataTree.takeSnapshot().newModification();
200 mod.write(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
201 .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
202 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
203 .withChild(OBJECT_ID_LEAF)
207 mod.merge(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
208 .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
209 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
210 .withChild(OBJECT_ID_LEAF)
211 .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
212 .withChildValue("object1")
218 mod.delete(YangInstanceIdentifier.create(BOX, OBJECT_LIST, OBJECT_ITEM, NESTED_LIST, NESTED_ITEM));
224 public void testDisappearInChoice() throws DataValidationFailedException {
225 DataTreeModification mod = dataTree.takeSnapshot().newModification();
226 // Initialize choice with list
227 mod.write(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
228 .withChild(choiceBuilder().withNodeIdentifier(ANY_OF)
229 .withChild(mapBuilder().withNodeIdentifier(SOME_LIST_ID)
230 .withChild(mapEntryBuilder()
231 .withNodeIdentifier(SOME_LIST_ITEM)
232 .withChild(leafBuilder().withNodeIdentifier(SOME_LEAF_ID).withValue("foo").build())
239 // Now delete the single item, causing the list to fizzle, while creating the alterinative case
240 mod = dataTree.takeSnapshot().newModification();
241 mod.delete(YangInstanceIdentifier.create(BOX, ANY_OF, SOME_LIST_ID, SOME_LIST_ITEM));
242 mod.write(YangInstanceIdentifier.create(BOX, ANY_OF, SOME_LEAF_ID),
243 leafBuilder().withNodeIdentifier(SOME_LEAF_ID).withValue("foo").build());
248 private DataTreeModification write(final ContainerNode data) throws DataValidationFailedException {
249 final DataTreeModification mod = dataTree.takeSnapshot().newModification();
250 mod.write(YangInstanceIdentifier.create(BOX), data);
254 private void writeAndCommit(final ContainerNode data) throws DataValidationFailedException {
255 final DataTreeModification mod = dataTree.takeSnapshot().newModification();
256 mod.write(YangInstanceIdentifier.create(BOX), data);
260 private void commit(final DataTreeModification mod) throws DataValidationFailedException {
262 dataTree.validate(mod);
263 dataTree.commit(dataTree.prepare(mod));