Convert yang-data-impl to a JPMS module
[yangtools.git] / yang / yang-data-impl / src / test / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / YT776Test.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, 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.data.impl.schema.tree;
9
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;
18
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.EffectiveModelContext;
35
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 = NodeIdentifierWithPredicates.of(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"));
47
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 = NodeIdentifierWithPredicates.of(NESTED,
52         ImmutableMap.of(NESTED_ATTRIBUTE, "foo"));
53
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 = NodeIdentifierWithPredicates.of(SOME_LIST,
60                 ImmutableMap.of(SOME_LEAF, "foo"));
61     private static EffectiveModelContext SCHEMA_CONTEXT;
62
63     private DataTree dataTree;
64
65     @BeforeClass
66     public static void beforeClass() {
67         SCHEMA_CONTEXT = TestModel.createTestContext("/yt776.yang");
68     }
69
70     @AfterClass
71     public static void afterClass() {
72         SCHEMA_CONTEXT = null;
73     }
74
75     @Before
76     public void init() {
77         dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION, SCHEMA_CONTEXT);
78     }
79
80     @Test
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)
87                     .build())
88                 .build())
89             .build());
90
91         try {
92             mod.ready();
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",
98                 e.getMessage());
99         }
100     }
101
102     @Test
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())
109                     .build())
110                 .build())
111             .build());
112
113         try {
114             mod.ready();
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());
118         }
119     }
120
121     @Test
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")
129                         .build())
130                     .build())
131                 .build())
132             .build());
133     }
134
135     @Test
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")
144                         .build())
145                     .build())
146                 .build())
147             .build());
148     }
149
150     @Test
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")
160                         .build())
161                     .build())
162                 .build())
163             .build());
164
165         try {
166             mod.ready();
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());
170         }
171     }
172
173     @Test
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)
180                     .build())
181                 .build())
182             .build());
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")
189                         .build())
190                     .build())
191                 .build())
192             .build());
193
194         commit(mod);
195     }
196
197     @Test
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)
204                     .build())
205                 .build())
206             .build());
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")
213                         .build())
214                     .build())
215                 .build())
216             .build());
217
218         mod.delete(YangInstanceIdentifier.create(BOX, OBJECT_LIST, OBJECT_ITEM, NESTED_LIST, NESTED_ITEM));
219
220         commit(mod);
221     }
222
223     @Test
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())
233                         .build())
234                     .build())
235                 .build())
236             .build());
237         commit(mod);
238
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());
244
245         commit(mod);
246     }
247
248     private DataTreeModification write(final ContainerNode data) throws DataValidationFailedException {
249         final DataTreeModification mod = dataTree.takeSnapshot().newModification();
250         mod.write(YangInstanceIdentifier.create(BOX), data);
251         return mod;
252     }
253
254     private void writeAndCommit(final ContainerNode data) throws DataValidationFailedException {
255         final DataTreeModification mod = dataTree.takeSnapshot().newModification();
256         mod.write(YangInstanceIdentifier.create(BOX), data);
257         commit(mod);
258     }
259
260     private void commit(final DataTreeModification mod) throws DataValidationFailedException {
261         mod.ready();
262         dataTree.validate(mod);
263         dataTree.commit(dataTree.prepare(mod));
264     }
265 }