4181c9afb94cb1d347217afa21edeae202341fd9
[yangtools.git] / yang / yang-data-impl / src / test / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / Bug4454Test.java
1 /*
2  * Copyright (c) 2015 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 junit.framework.TestCase.assertFalse;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13
14 import com.google.common.base.Optional;
15 import com.google.common.collect.ImmutableMap;
16 import java.io.IOException;
17 import java.net.URISyntaxException;
18 import java.util.HashMap;
19 import java.util.Map;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.opendaylight.yangtools.util.UnmodifiableCollection;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
28 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
35 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
36 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
37 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
38 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
39 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
40 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
41 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
42 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
43 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
44 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
45 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
46 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
47
48 public class Bug4454Test {
49
50     private static final QName MASTER_CONTAINER_QNAME = QName
51             .create("urn:opendaylight:params:xml:ns:yang:list-constraints-validation-test-model", "2015-02-02",
52                     "master-container");
53     private static final QName MIN_MAX_LIST_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-list");
54     private static final QName MIN_MAX_LEAF_LIST_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-leaf-list");
55     private static final QName MIN_MAX_LIST_QNAME_NO_MINMAX = QName
56             .create(MASTER_CONTAINER_QNAME, "min-max-list-no-minmax");
57     private static final QName MIN_MAX_KEY_LEAF_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-key-leaf");
58     private static final QName MIN_MAX_VALUE_LEAF_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-value-leaf");
59
60     private static final YangInstanceIdentifier MASTER_CONTAINER_PATH = YangInstanceIdentifier
61             .of(MASTER_CONTAINER_QNAME);
62     private static final YangInstanceIdentifier MIN_MAX_LIST_PATH = YangInstanceIdentifier
63             .builder(MASTER_CONTAINER_PATH)
64             .node(MIN_MAX_LIST_QNAME).build();
65     private static final YangInstanceIdentifier MIN_MAX_LIST_NO_MINMAX_PATH = YangInstanceIdentifier
66             .builder(MASTER_CONTAINER_PATH)
67             .node(MIN_MAX_LIST_QNAME_NO_MINMAX).build();
68     private static final YangInstanceIdentifier MIN_MAX_LEAF_LIST_PATH = YangInstanceIdentifier
69             .builder(MASTER_CONTAINER_PATH).node(MIN_MAX_LEAF_LIST_QNAME).build();
70
71     private static final Map<QName, Object> FOO_PREDICATES = ImmutableMap.of(MIN_MAX_KEY_LEAF_QNAME, "foo");
72     private static final Map<QName, Object> BAZ_PREDICATES = ImmutableMap.of(MIN_MAX_KEY_LEAF_QNAME, "baz");
73
74     private final MapEntryNode fooEntryNodeWithValue = ImmutableMapEntryNodeBuilder.create().withNodeIdentifier(
75         new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME, FOO_PREDICATES))
76             .withChild(ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "footest")).build();
77     private final MapEntryNode bazEntryNodeWithValue = ImmutableMapEntryNodeBuilder.create().withNodeIdentifier(
78         new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME, BAZ_PREDICATES))
79             .withChild(ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "baztest")).build();
80     private final MapEntryNode fooEntryNode = ImmutableNodes.mapEntry(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME,
81             "foo");
82     private final MapEntryNode barEntryNode = ImmutableNodes.mapEntry(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME,
83             "bar");
84     private final MapEntryNode bazEntryNode = ImmutableNodes.mapEntry(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME,
85             "baz");
86     private final MapNode mapNodeBazFuzWithNodes = ImmutableNodes.mapNodeBuilder()
87             .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
88             .withChild(bazEntryNode).withChild(bazEntryNodeWithValue).withChild(fooEntryNode)
89             .build();
90     private final MapNode mapNodeFooWithNodes = ImmutableNodes.mapNodeBuilder()
91             .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
92             .withChild(fooEntryNode).withChild(fooEntryNodeWithValue).withChild(barEntryNode).withChild(bazEntryNode)
93             .build();
94     private final MapNode mapNodeBar = ImmutableNodes.mapNodeBuilder()
95             .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
96             .withChild(barEntryNode).build();
97     private final MapNode mapNodeBaz = ImmutableNodes.mapNodeBuilder()
98             .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
99             .withChild(bazEntryNode).build();
100
101     private InMemoryDataTree inMemoryDataTree;
102
103     @Before
104     public void prepare() throws IOException, YangSyntaxErrorException, ReactorException, URISyntaxException {
105         SchemaContext schemaContext = createTestContext();
106         assertNotNull("Schema context must not be null.", schemaContext);
107         inMemoryDataTree =  (InMemoryDataTree) InMemoryDataTreeFactory.getInstance().create(TreeType.OPERATIONAL);
108         inMemoryDataTree.setSchemaContext(schemaContext);
109         final InMemoryDataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
110         final DataTreeModification modificationTree = initialDataTreeSnapshot.newModification();
111
112         modificationTree.write(MASTER_CONTAINER_PATH, ImmutableNodes.containerNode(MASTER_CONTAINER_QNAME));
113         modificationTree.ready();
114         inMemoryDataTree.commit(inMemoryDataTree.prepare(modificationTree));
115     }
116
117     public static SchemaContext createTestContext() throws IOException, YangSyntaxErrorException, ReactorException,
118             URISyntaxException {
119         return YangParserTestUtils.parseYangResource("/bug-4454-test.yang");
120     }
121
122     @Test
123     public void minMaxListDeleteWriteTest() throws DataValidationFailedException {
124         final InMemoryDataTreeModification modificationTree1 = inMemoryDataTree.takeSnapshot().newModification();
125
126         Map<QName, Object> key = new HashMap<>();
127         key.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
128
129         NodeIdentifierWithPredicates mapEntryPath2 = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME , key);
130
131         final YangInstanceIdentifier minMaxLeafFoo = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
132                 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2).build();
133
134         key.clear();
135         key.put(MIN_MAX_KEY_LEAF_QNAME, "NON-EXISTING-LEAF");
136
137         mapEntryPath2 = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME, key);
138
139         final YangInstanceIdentifier minMaxLeafNel = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
140                 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2).build();
141
142         final Map<QName, Object> keyTemp = new HashMap<>();
143         keyTemp.put(MIN_MAX_KEY_LEAF_QNAME, "baz");
144
145         NodeIdentifierWithPredicates mapEntryPathTest = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME , keyTemp);
146
147         final YangInstanceIdentifier pathToBaz = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
148                 .node(MIN_MAX_LIST_QNAME).node(mapEntryPathTest).node(MIN_MAX_VALUE_LEAF_QNAME).build();
149
150         keyTemp.clear();
151         keyTemp.put(MIN_MAX_KEY_LEAF_QNAME, "bar");
152
153         mapEntryPathTest = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME , keyTemp);
154
155         final YangInstanceIdentifier pathToBar = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
156                 .node(MIN_MAX_LIST_QNAME).node(mapEntryPathTest).node(MIN_MAX_VALUE_LEAF_QNAME).build();
157
158         keyTemp.clear();
159         keyTemp.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
160
161         final NodeIdentifierWithPredicates mapEntryPathTestKey = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME,
162             keyTemp);
163
164         final YangInstanceIdentifier pathToKeyFoo = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
165                 .node(MIN_MAX_LIST_QNAME).node(mapEntryPathTestKey).node(MIN_MAX_KEY_LEAF_QNAME).build();
166
167         final LeafNode<String> newNode = ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "test");
168         final LeafNode<String> newNode1 = ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "test1");
169         final LeafNode<String> newNode2 = ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "test2");
170         final LeafNode<String> newNodekey = ImmutableNodes.leafNode(MIN_MAX_KEY_LEAF_QNAME, "foo");
171
172         assertFalse(inMemoryDataTree.toString().contains("list"));
173
174         InMemoryDataTreeSnapshot snapshotAfterCommit = inMemoryDataTree.takeSnapshot();
175         Optional<NormalizedNode<?, ?>> minMaxListRead = snapshotAfterCommit.readNode(MIN_MAX_LIST_PATH);
176         assertTrue(!minMaxListRead.isPresent());
177
178         modificationTree1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
179         modificationTree1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
180         modificationTree1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
181         modificationTree1.merge(MIN_MAX_LIST_PATH, mapNodeBar);
182         modificationTree1.merge(MIN_MAX_LIST_PATH, mapNodeBaz);
183         modificationTree1.write(pathToKeyFoo, newNodekey);
184         modificationTree1.write(pathToBaz, newNode2);
185         modificationTree1.write(pathToBaz, newNode1);
186         modificationTree1.write(pathToBaz, newNode);
187         modificationTree1.delete(minMaxLeafFoo);
188         modificationTree1.delete(minMaxLeafNel);
189
190         modificationTree1.ready();
191         inMemoryDataTree.validate(modificationTree1);
192         final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree1);
193         inMemoryDataTree.commit(prepare);
194
195         InMemoryDataTreeSnapshot test = inMemoryDataTree.takeSnapshot();
196         testLoop(test, "bar", "test");
197
198         InMemoryDataTreeModification tempMod = test.newModification();
199         tempMod.write(pathToBaz, newNode2);
200         tempMod.write(pathToBaz, newNode1);
201         tempMod.merge(pathToBaz, newNode2);
202         tempMod.write(pathToBaz, newNode1);
203
204         tempMod.ready();
205         inMemoryDataTree.validate(tempMod);
206         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(tempMod);
207         inMemoryDataTree.commit(prepare1);
208
209         InMemoryDataTreeSnapshot test1 = inMemoryDataTree.takeSnapshot();
210         testLoop(test1, "bar", "test1");
211
212         InMemoryDataTreeModification tempMod1 = test1.newModification();
213         tempMod1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
214
215         tempMod1.ready();
216         inMemoryDataTree.validate(tempMod1);
217         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(tempMod1);
218         inMemoryDataTree.commit(prepare2);
219
220         InMemoryDataTreeSnapshot test2 = inMemoryDataTree.takeSnapshot();
221         minMaxListRead = test2.readNode(MIN_MAX_LIST_PATH);
222         assertTrue(minMaxListRead.isPresent());
223         assertTrue(((NormalizedNodeContainer<?, ?, ?>) minMaxListRead.get()).getValue().size() == 3);
224
225         InMemoryDataTreeModification tempMod2 = test2.newModification();
226         tempMod2.write(MIN_MAX_LIST_PATH, mapNodeBaz);
227         tempMod2.write(pathToBaz, newNode2);
228
229         tempMod2.ready();
230         inMemoryDataTree.validate(tempMod2);
231         final DataTreeCandidate prepare3 = inMemoryDataTree.prepare(tempMod2);
232         inMemoryDataTree.commit(prepare3);
233
234         InMemoryDataTreeSnapshot test3 = inMemoryDataTree.takeSnapshot();
235         minMaxListRead = test3.readNode(MIN_MAX_LIST_PATH);
236         assertTrue(minMaxListRead.isPresent());
237         assertTrue(((NormalizedNodeContainer<?, ?, ?>) minMaxListRead.get()).getValue().size() == 1);
238         assertTrue(minMaxListRead.get().getValue().toString().contains("test2"));
239
240         InMemoryDataTreeModification tempMod3 = test3.newModification();
241         tempMod3.merge(MIN_MAX_LIST_PATH, mapNodeBar);
242         tempMod3.merge(pathToBar, newNode1);
243
244         tempMod3.ready();
245         inMemoryDataTree.validate(tempMod3);
246         final DataTreeCandidate prepare4 = inMemoryDataTree.prepare(tempMod3);
247         inMemoryDataTree.commit(prepare4);
248
249         InMemoryDataTreeSnapshot test4 = inMemoryDataTree.takeSnapshot();
250         testLoop(test4, "test1", "test2");
251     }
252
253     @Test
254     public void minMaxLeafListPass() throws DataValidationFailedException {
255         final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
256
257         final NodeWithValue<?> barPath = new NodeWithValue<>(MIN_MAX_LIST_QNAME, "bar");
258         final NodeWithValue<?> gooPath = new NodeWithValue<>(MIN_MAX_LIST_QNAME, "goo");
259
260         final LeafSetEntryNode<Object> barLeafSetEntry = ImmutableLeafSetEntryNodeBuilder.create()
261                 .withNodeIdentifier(barPath)
262                 .withValue("bar").build();
263         final LeafSetEntryNode<Object> gooLeafSetEntry = ImmutableLeafSetEntryNodeBuilder.create()
264                 .withNodeIdentifier(gooPath)
265                 .withValue("goo").build();
266
267         final LeafSetNode<Object> fooLeafSetNode = ImmutableLeafSetNodeBuilder.create()
268                 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LEAF_LIST_QNAME))
269                 .withChildValue("foo").build();
270
271         modificationTree.write(MIN_MAX_LEAF_LIST_PATH, fooLeafSetNode);
272         modificationTree.write(MIN_MAX_LEAF_LIST_PATH.node(barPath), barLeafSetEntry);
273         modificationTree.ready();
274
275         inMemoryDataTree.validate(modificationTree);
276         final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree);
277         inMemoryDataTree.commit(prepare1);
278
279         InMemoryDataTreeSnapshot test1 = inMemoryDataTree.takeSnapshot();
280
281         InMemoryDataTreeModification tempMod1 = test1.newModification();
282         tempMod1.write(MIN_MAX_LEAF_LIST_PATH.node(gooPath), gooLeafSetEntry);
283         tempMod1.write(MIN_MAX_LEAF_LIST_PATH.node(barPath), barLeafSetEntry);
284         tempMod1.ready();
285
286         inMemoryDataTree.validate(tempMod1);
287         final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(tempMod1);
288         inMemoryDataTree.commit(prepare2);
289
290         final InMemoryDataTreeSnapshot snapshotAfterCommit = inMemoryDataTree.takeSnapshot();
291         final Optional<NormalizedNode<?, ?>> masterContainer = snapshotAfterCommit.readNode(MASTER_CONTAINER_PATH);
292         assertTrue(masterContainer.isPresent());
293         final Optional<NormalizedNodeContainer<?, ?, ?>> leafList = ((NormalizedNodeContainer) masterContainer.get())
294                 .getChild(new NodeIdentifier(MIN_MAX_LEAF_LIST_QNAME));
295         assertTrue(leafList.isPresent());
296         assertTrue(leafList.get().getValue().size() == 3);
297     }
298
299
300     @Test(expected = DataValidationFailedException.class)
301     public void minMaxListDeleteExceptionTest() throws DataValidationFailedException {
302         final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
303
304         Map<QName, Object> key = new HashMap<>();
305         key.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
306
307         NodeIdentifierWithPredicates mapEntryPath2 = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME, key);
308
309         final YangInstanceIdentifier minMaxLeafFoo = MASTER_CONTAINER_PATH
310                 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
311
312         key.clear();
313         key.put(MIN_MAX_KEY_LEAF_QNAME, "bar");
314
315         mapEntryPath2 = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME, key);
316
317         final YangInstanceIdentifier minMaxLeafBar = MASTER_CONTAINER_PATH
318                 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
319
320         key.clear();
321         key.put(MIN_MAX_KEY_LEAF_QNAME, "baz");
322
323         mapEntryPath2 = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME, key);
324
325         final YangInstanceIdentifier minMaxLeafBaz = MASTER_CONTAINER_PATH
326                 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
327
328         modificationTree.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
329         modificationTree.merge(MIN_MAX_LIST_PATH, mapNodeBar);
330         modificationTree.merge(MIN_MAX_LIST_PATH, mapNodeBaz);
331         modificationTree.delete(minMaxLeafFoo);
332         modificationTree.delete(minMaxLeafBar);
333         modificationTree.delete(minMaxLeafBaz);
334
335         modificationTree.ready();
336
337         inMemoryDataTree.validate(modificationTree);
338         final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
339         inMemoryDataTree.commit(prepare);
340     }
341
342     @Test
343     public void minMaxListNoMinMaxDeleteTest() throws DataValidationFailedException {
344         final MapEntryNode fooEntryNode = ImmutableNodes.mapEntry(MIN_MAX_LIST_QNAME_NO_MINMAX, MIN_MAX_KEY_LEAF_QNAME,
345             "foo");
346         final MapNode mapNode1 = ImmutableNodes.mapNodeBuilder()
347                 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME_NO_MINMAX))
348                 .withChild(fooEntryNode).build();
349
350         final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
351
352         Map<QName, Object> key = new HashMap<>();
353         key.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
354
355         NodeIdentifierWithPredicates mapEntryPath2 = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME_NO_MINMAX,
356             key);
357
358         final YangInstanceIdentifier minMaxLeafFoo = MASTER_CONTAINER_PATH
359                 .node(MIN_MAX_LIST_QNAME_NO_MINMAX).node(mapEntryPath2);
360
361         key.clear();
362         key.put(MIN_MAX_KEY_LEAF_QNAME, "non-existing-leaf");
363
364         mapEntryPath2 = new NodeIdentifierWithPredicates(MIN_MAX_LIST_QNAME_NO_MINMAX, key);
365
366         YangInstanceIdentifier minMaxLeafNel = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
367                 .node(MIN_MAX_LIST_QNAME_NO_MINMAX).node(mapEntryPath2).build();
368
369         modificationTree.write(MIN_MAX_LIST_NO_MINMAX_PATH, mapNode1);
370         modificationTree.delete(minMaxLeafFoo);
371         modificationTree.delete(minMaxLeafNel);
372
373         modificationTree.ready();
374
375         inMemoryDataTree.validate(modificationTree);
376         final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
377         inMemoryDataTree.commit(prepare);
378
379         final InMemoryDataTreeSnapshot snapshotAfterCommit = inMemoryDataTree.takeSnapshot();
380         final Optional<NormalizedNode<?, ?>> minMaxListRead = snapshotAfterCommit.readNode(MIN_MAX_LIST_NO_MINMAX_PATH);
381         assertTrue(minMaxListRead.isPresent());
382         assertTrue(((NormalizedNodeContainer<?, ?, ?>) minMaxListRead.get()).getValue().size() == 0);
383     }
384
385     private static void testLoop(final InMemoryDataTreeSnapshot snapshot, final String first, final String second) {
386         Optional<NormalizedNode<?, ?>> minMaxListRead = snapshot.readNode(MIN_MAX_LIST_PATH);
387         assertTrue(minMaxListRead.isPresent());
388         assertTrue(((NormalizedNodeContainer<?, ?, ?>) minMaxListRead.get()).getValue().size() == 2);
389         UnmodifiableCollection<?> collectionChildren = (UnmodifiableCollection<?>) minMaxListRead.get().getValue();
390
391         for (Object collectionChild : collectionChildren) {
392             if (collectionChild.toString().contains(first)) {
393                 assertTrue(collectionChild.toString().contains(first));
394             } else {
395                 assertTrue(collectionChild.toString().contains(second));
396             }
397         }
398     }
399 }