2 * Copyright (c) 2015 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.tree.impl;
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertFalse;
12 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
13 import static org.junit.jupiter.api.Assertions.assertTrue;
14 import static org.junit.jupiter.api.Assertions.fail;
16 import java.util.Collection;
17 import java.util.HashMap;
18 import java.util.Optional;
19 import org.junit.jupiter.api.AfterAll;
20 import org.junit.jupiter.api.BeforeAll;
21 import org.junit.jupiter.api.BeforeEach;
22 import org.junit.jupiter.api.Test;
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.ContainerNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
30 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
32 import org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode;
33 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
34 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
35 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
36 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeSnapshot;
37 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
38 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
39 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
40 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
44 private static final QName MASTER_CONTAINER_QNAME = QName
45 .create("urn:opendaylight:params:xml:ns:yang:list-constraints-validation-test-model", "2015-02-02",
47 private static final QName MIN_MAX_LIST_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-list");
48 private static final QName MIN_MAX_LEAF_LIST_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-leaf-list");
49 private static final QName MIN_MAX_LIST_QNAME_NO_MINMAX = QName
50 .create(MASTER_CONTAINER_QNAME, "min-max-list-no-minmax");
51 private static final QName MIN_MAX_KEY_LEAF_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-key-leaf");
52 private static final QName MIN_MAX_VALUE_LEAF_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-value-leaf");
53 private static final QName PRESENCE_QNAME = QName.create(MASTER_CONTAINER_QNAME, "presence");
55 private static final YangInstanceIdentifier MASTER_CONTAINER_PATH =
56 YangInstanceIdentifier.of(MASTER_CONTAINER_QNAME);
57 private static final YangInstanceIdentifier MIN_MAX_LIST_PATH =
58 YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH).node(MIN_MAX_LIST_QNAME).build();
59 private static final YangInstanceIdentifier PRESENCE_PATH = YangInstanceIdentifier.of(PRESENCE_QNAME);
60 private static final YangInstanceIdentifier PRESENCE_MIN_MAX_LIST_PATH = PRESENCE_PATH.node(MIN_MAX_LIST_QNAME);
61 private static final YangInstanceIdentifier MIN_MAX_LIST_NO_MINMAX_PATH =
62 YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH).node(MIN_MAX_LIST_QNAME_NO_MINMAX).build();
63 private static final YangInstanceIdentifier MIN_MAX_LEAF_LIST_PATH =
64 YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH).node(MIN_MAX_LEAF_LIST_QNAME).build();
66 private final MapEntryNode fooEntryNodeWithValue = ImmutableNodes.newMapEntryBuilder()
67 .withNodeIdentifier(NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "foo"))
68 .withChild(ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "footest"))
70 private final MapEntryNode bazEntryNodeWithValue = ImmutableNodes.newMapEntryBuilder()
71 .withNodeIdentifier(NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "baz"))
72 .withChild(ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "baztest"))
74 private final MapEntryNode fooEntryNode = ImmutableNodes.newMapEntryBuilder()
75 .withNodeIdentifier(NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "foo"))
76 .withChild(ImmutableNodes.leafNode(MIN_MAX_KEY_LEAF_QNAME, "foo"))
78 private final MapEntryNode barEntryNode = ImmutableNodes.newMapEntryBuilder()
79 .withNodeIdentifier(NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "bar"))
80 .withChild(ImmutableNodes.leafNode(MIN_MAX_KEY_LEAF_QNAME, "bar"))
82 private final MapEntryNode bazEntryNode = ImmutableNodes.newMapEntryBuilder()
83 .withNodeIdentifier(NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "baz"))
84 .withChild(ImmutableNodes.leafNode(MIN_MAX_KEY_LEAF_QNAME, "baz"))
86 private final SystemMapNode mapNodeBazFuzWithNodes = ImmutableNodes.newSystemMapBuilder()
87 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
88 .withChild(bazEntryNode).withChild(bazEntryNodeWithValue).withChild(fooEntryNode)
90 private final SystemMapNode mapNodeFooWithNodes = ImmutableNodes.newSystemMapBuilder()
91 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
92 .withChild(fooEntryNode).withChild(fooEntryNodeWithValue).withChild(barEntryNode).withChild(bazEntryNode)
94 private final SystemMapNode mapNodeBar = ImmutableNodes.newSystemMapBuilder()
95 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
96 .withChild(barEntryNode).build();
97 private final SystemMapNode mapNodeBaz = ImmutableNodes.newSystemMapBuilder()
98 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
99 .withChild(bazEntryNode).build();
101 private static EffectiveModelContext schemaContext;
103 private DataTree inMemoryDataTree;
106 static void beforeClass() {
107 schemaContext = YangParserTestUtils.parseYang("""
110 namespace "urn:opendaylight:params:xml:ns:yang:list-constraints-validation-test-model";
111 prefix "list-constraints-validation";
113 revision "2015-02-02" {
114 description "Initial revision.";
117 container master-container {
121 key "min-max-key-leaf";
122 leaf min-max-key-leaf {
125 leaf min-max-value-leaf {
130 list min-max-list-no-minmax {
131 key "min-max-key-leaf";
132 leaf min-max-key-leaf {
137 leaf-list min-max-leaf-list {
145 presence "anchor point";
151 key "min-max-key-leaf";
153 leaf min-max-key-leaf {
162 static void afterClass() {
163 schemaContext = null;
167 void prepare() throws DataValidationFailedException {
168 inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL,
170 final var initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
171 final var modificationTree = initialDataTreeSnapshot.newModification();
173 modificationTree.write(MASTER_CONTAINER_PATH, ImmutableNodes.newContainerBuilder()
174 .withNodeIdentifier(new NodeIdentifier(MASTER_CONTAINER_QNAME))
176 modificationTree.ready();
177 inMemoryDataTree.commit(inMemoryDataTree.prepare(modificationTree));
181 void minMaxListDeleteWriteTest() throws DataValidationFailedException {
182 final var modificationTree1 = inMemoryDataTree.takeSnapshot().newModification();
184 final var key = new HashMap<QName, Object>();
185 key.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
187 var mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME , key);
189 final var minMaxLeafFoo = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
190 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2).build();
193 key.put(MIN_MAX_KEY_LEAF_QNAME, "NON-EXISTING-LEAF");
195 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, key);
197 final var minMaxLeafNel = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
198 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2).build();
200 final var keyTemp = new HashMap<QName, Object>();
201 keyTemp.put(MIN_MAX_KEY_LEAF_QNAME, "baz");
203 var mapEntryPathTest = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME , keyTemp);
205 final var pathToBaz = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
206 .node(MIN_MAX_LIST_QNAME).node(mapEntryPathTest).node(MIN_MAX_VALUE_LEAF_QNAME).build();
209 keyTemp.put(MIN_MAX_KEY_LEAF_QNAME, "bar");
211 mapEntryPathTest = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME , keyTemp);
213 final var pathToBar = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
214 .node(MIN_MAX_LIST_QNAME).node(mapEntryPathTest).node(MIN_MAX_VALUE_LEAF_QNAME).build();
217 keyTemp.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
219 final var mapEntryPathTestKey = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME,
222 final var pathToKeyFoo = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
223 .node(MIN_MAX_LIST_QNAME).node(mapEntryPathTestKey).node(MIN_MAX_KEY_LEAF_QNAME).build();
225 final var newNode = ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "test");
226 final var newNode1 = ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "test1");
227 final var newNode2 = ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "test2");
228 final var newNodekey = ImmutableNodes.leafNode(MIN_MAX_KEY_LEAF_QNAME, "foo");
230 assertFalse(inMemoryDataTree.toString().contains("list"));
232 final var snapshotAfterCommit = inMemoryDataTree.takeSnapshot();
233 var minMaxListRead = snapshotAfterCommit.readNode(MIN_MAX_LIST_PATH);
234 assertFalse(minMaxListRead.isPresent());
236 modificationTree1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
237 modificationTree1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
238 modificationTree1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
239 modificationTree1.merge(MIN_MAX_LIST_PATH, mapNodeBar);
240 modificationTree1.merge(MIN_MAX_LIST_PATH, mapNodeBaz);
241 modificationTree1.write(pathToKeyFoo, newNodekey);
242 modificationTree1.write(pathToBaz, newNode2);
243 modificationTree1.write(pathToBaz, newNode1);
244 modificationTree1.write(pathToBaz, newNode);
245 modificationTree1.delete(minMaxLeafFoo);
246 modificationTree1.delete(minMaxLeafNel);
248 modificationTree1.ready();
249 inMemoryDataTree.validate(modificationTree1);
250 final var prepare = inMemoryDataTree.prepare(modificationTree1);
251 inMemoryDataTree.commit(prepare);
253 final var test = inMemoryDataTree.takeSnapshot();
254 testLoop(test, "bar", "test");
256 final var tempMod = test.newModification();
257 tempMod.write(pathToBaz, newNode2);
258 tempMod.write(pathToBaz, newNode1);
259 tempMod.merge(pathToBaz, newNode2);
260 tempMod.write(pathToBaz, newNode1);
263 inMemoryDataTree.validate(tempMod);
264 final var prepare1 = inMemoryDataTree.prepare(tempMod);
265 inMemoryDataTree.commit(prepare1);
267 final var test1 = inMemoryDataTree.takeSnapshot();
268 testLoop(test1, "bar", "test1");
270 final var tempMod1 = test1.newModification();
271 tempMod1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
274 inMemoryDataTree.validate(tempMod1);
275 final var prepare2 = inMemoryDataTree.prepare(tempMod1);
276 inMemoryDataTree.commit(prepare2);
278 final var test2 = inMemoryDataTree.takeSnapshot();
279 minMaxListRead = test2.readNode(MIN_MAX_LIST_PATH);
280 assertTrue(minMaxListRead.isPresent());
281 assertEquals(3, ((NormalizedNodeContainer<?>) minMaxListRead.orElseThrow()).size());
283 final var tempMod2 = test2.newModification();
284 tempMod2.write(MIN_MAX_LIST_PATH, mapNodeBaz);
285 tempMod2.write(pathToBaz, newNode2);
288 inMemoryDataTree.validate(tempMod2);
289 final var prepare3 = inMemoryDataTree.prepare(tempMod2);
290 inMemoryDataTree.commit(prepare3);
292 final var test3 = inMemoryDataTree.takeSnapshot();
293 minMaxListRead = test3.readNode(MIN_MAX_LIST_PATH);
294 assertTrue(minMaxListRead.isPresent());
295 assertEquals(1, ((NormalizedNodeContainer<?>) minMaxListRead.orElseThrow()).size());
296 assertTrue(minMaxListRead.orElseThrow().body().toString().contains("test2"));
298 final var tempMod3 = test3.newModification();
299 tempMod3.merge(MIN_MAX_LIST_PATH, mapNodeBar);
300 tempMod3.merge(pathToBar, newNode1);
303 inMemoryDataTree.validate(tempMod3);
304 final var prepare4 = inMemoryDataTree.prepare(tempMod3);
305 inMemoryDataTree.commit(prepare4);
307 final var test4 = inMemoryDataTree.takeSnapshot();
308 testLoop(test4, "test1", "test2");
312 void minMaxLeafListPass() throws DataValidationFailedException {
313 final var modificationTree = inMemoryDataTree.takeSnapshot().newModification();
315 final var barPath = new NodeWithValue<>(MIN_MAX_LIST_QNAME, "bar");
316 final var gooPath = new NodeWithValue<>(MIN_MAX_LIST_QNAME, "goo");
318 final var barLeafSetEntry = ImmutableNodes.leafSetEntry(barPath);
319 final var gooLeafSetEntry = ImmutableNodes.leafSetEntry(gooPath);
321 final var fooLeafSetNode = ImmutableNodes.newSystemLeafSetBuilder()
322 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LEAF_LIST_QNAME))
323 .withChildValue("foo")
326 modificationTree.write(MIN_MAX_LEAF_LIST_PATH, fooLeafSetNode);
327 modificationTree.write(MIN_MAX_LEAF_LIST_PATH.node(barPath), barLeafSetEntry);
328 modificationTree.ready();
330 inMemoryDataTree.validate(modificationTree);
331 final var prepare1 = inMemoryDataTree.prepare(modificationTree);
332 inMemoryDataTree.commit(prepare1);
334 final var test1 = inMemoryDataTree.takeSnapshot();
336 final var tempMod1 = test1.newModification();
337 tempMod1.write(MIN_MAX_LEAF_LIST_PATH.node(gooPath), gooLeafSetEntry);
338 tempMod1.write(MIN_MAX_LEAF_LIST_PATH.node(barPath), barLeafSetEntry);
341 inMemoryDataTree.validate(tempMod1);
342 final var prepare2 = inMemoryDataTree.prepare(tempMod1);
343 inMemoryDataTree.commit(prepare2);
345 final var snapshotAfterCommit = inMemoryDataTree.takeSnapshot();
346 final var masterContainer = snapshotAfterCommit.readNode(MASTER_CONTAINER_PATH);
347 assertTrue(masterContainer.isPresent());
348 final var leafList = ((DistinctNodeContainer) masterContainer.orElseThrow())
349 .findChildByArg(new NodeIdentifier(MIN_MAX_LEAF_LIST_QNAME));
350 assertTrue(leafList.isPresent());
351 assertEquals(3, ((Optional<NormalizedNodeContainer<?>>) leafList).orElseThrow().size());
355 void minMaxListDeleteTest() throws DataValidationFailedException {
356 final var modificationTree = inMemoryDataTree.takeSnapshot().newModification();
359 var mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME,
360 MIN_MAX_KEY_LEAF_QNAME, "foo");
362 final var minMaxLeafFoo = MASTER_CONTAINER_PATH
363 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
365 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "bar");
367 final var minMaxLeafBar = MASTER_CONTAINER_PATH
368 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
370 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "baz");
372 final var minMaxLeafBaz = MASTER_CONTAINER_PATH
373 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
375 modificationTree.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
376 modificationTree.merge(MIN_MAX_LIST_PATH, mapNodeBar);
377 modificationTree.merge(MIN_MAX_LIST_PATH, mapNodeBaz);
378 modificationTree.delete(minMaxLeafFoo);
379 modificationTree.delete(minMaxLeafBar);
380 modificationTree.delete(minMaxLeafBaz);
382 modificationTree.ready();
384 inMemoryDataTree.validate(modificationTree);
385 final var prepare = inMemoryDataTree.prepare(modificationTree);
386 inMemoryDataTree.commit(prepare);
388 // Empty list should have disappeared, along with the container, as we are not enforcing root
389 final var data = inMemoryDataTree.takeSnapshot().readNode(YangInstanceIdentifier.of()).orElseThrow();
390 assertInstanceOf(ContainerNode.class, data);
391 assertEquals(0, ((ContainerNode) data).size());
395 void minMaxListDeleteExceptionTest() throws DataValidationFailedException {
396 final var modificationTree = inMemoryDataTree.takeSnapshot().newModification();
398 var mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME,
399 MIN_MAX_KEY_LEAF_QNAME, "foo");
401 final var minMaxLeafFoo = PRESENCE_PATH.node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
403 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "bar");
405 final var minMaxLeafBar = PRESENCE_PATH.node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
407 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "baz");
409 final var minMaxLeafBaz = PRESENCE_PATH.node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
411 modificationTree.write(PRESENCE_PATH,
412 ImmutableNodes.newContainerBuilder().withNodeIdentifier(new NodeIdentifier(PRESENCE_QNAME)).build());
413 modificationTree.write(PRESENCE_MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
414 modificationTree.merge(PRESENCE_MIN_MAX_LIST_PATH, mapNodeBar);
415 modificationTree.merge(PRESENCE_MIN_MAX_LIST_PATH, mapNodeBaz);
416 modificationTree.delete(minMaxLeafFoo);
417 modificationTree.delete(minMaxLeafBar);
418 modificationTree.delete(minMaxLeafBaz);
421 // Unlike minMaxListDeleteTest(), presence container enforces the list to be present
422 modificationTree.ready();
423 fail("Should have failed with IAE");
424 } catch (IllegalArgumentException e) {
426 Node (urn:opendaylight:params:xml:ns:yang:list-constraints-validation-test-model?revision=2015-02-02)\
427 presence is missing mandatory descendant /(urn:opendaylight:params:xml:ns:yang:list-constraints-\
428 validation-test-model?revision=2015-02-02)min-max-list""", e.getMessage());
433 void minMaxListNoMinMaxDeleteTest() throws DataValidationFailedException {
434 final var fooEntryNoMinMaxNode = ImmutableNodes.newMapEntryBuilder()
436 NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME_NO_MINMAX, MIN_MAX_KEY_LEAF_QNAME, "foo"))
437 .withChild(ImmutableNodes.leafNode(MIN_MAX_KEY_LEAF_QNAME, "foo"))
439 final var mapNode1 = ImmutableNodes.newSystemMapBuilder()
440 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME_NO_MINMAX))
441 .withChild(fooEntryNoMinMaxNode).build();
443 final var modificationTree = inMemoryDataTree.takeSnapshot().newModification();
445 final var key = new HashMap<QName, Object>();
446 key.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
448 var mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME_NO_MINMAX, key);
450 final var minMaxLeafFoo = MASTER_CONTAINER_PATH
451 .node(MIN_MAX_LIST_QNAME_NO_MINMAX).node(mapEntryPath2);
454 key.put(MIN_MAX_KEY_LEAF_QNAME, "non-existing-leaf");
456 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME_NO_MINMAX, key);
458 final var minMaxLeafNel = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
459 .node(MIN_MAX_LIST_QNAME_NO_MINMAX).node(mapEntryPath2).build();
461 modificationTree.write(MIN_MAX_LIST_NO_MINMAX_PATH, mapNode1);
462 modificationTree.delete(minMaxLeafFoo);
463 modificationTree.delete(minMaxLeafNel);
465 modificationTree.ready();
467 inMemoryDataTree.validate(modificationTree);
468 final var prepare = inMemoryDataTree.prepare(modificationTree);
469 inMemoryDataTree.commit(prepare);
471 final var snapshotAfterCommit = inMemoryDataTree.takeSnapshot();
472 final var minMaxListRead = snapshotAfterCommit.readNode(MIN_MAX_LIST_NO_MINMAX_PATH);
474 // Empty list should have disappeared
475 assertFalse(minMaxListRead.isPresent());
478 private static void testLoop(final DataTreeSnapshot snapshot, final String first, final String second) {
479 final var minMaxListRead = snapshot.readNode(MIN_MAX_LIST_PATH);
480 assertTrue(minMaxListRead.isPresent());
481 assertEquals(2, ((NormalizedNodeContainer<?>) minMaxListRead.orElseThrow()).size());
483 for (var collectionChild : (Collection<?>) minMaxListRead.orElseThrow().body()) {
484 if (collectionChild.toString().contains(first)) {
485 assertTrue(collectionChild.toString().contains(first));
487 assertTrue(collectionChild.toString().contains(second));