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 junit.framework.TestCase.assertFalse;
11 import static org.hamcrest.CoreMatchers.containsString;
12 import static org.hamcrest.MatcherAssert.assertThat;
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
17 import java.util.Collection;
18 import java.util.HashMap;
20 import java.util.Optional;
21 import org.junit.AfterClass;
22 import org.junit.Before;
23 import org.junit.BeforeClass;
24 import org.junit.Test;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
30 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer;
32 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
38 import org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode;
39 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
40 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
41 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
42 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
43 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
44 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
45 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeSnapshot;
46 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
47 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
48 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
49 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
51 public class Bug4454Test {
53 private static final QName MASTER_CONTAINER_QNAME = QName
54 .create("urn:opendaylight:params:xml:ns:yang:list-constraints-validation-test-model", "2015-02-02",
56 private static final QName MIN_MAX_LIST_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-list");
57 private static final QName MIN_MAX_LEAF_LIST_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-leaf-list");
58 private static final QName MIN_MAX_LIST_QNAME_NO_MINMAX = QName
59 .create(MASTER_CONTAINER_QNAME, "min-max-list-no-minmax");
60 private static final QName MIN_MAX_KEY_LEAF_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-key-leaf");
61 private static final QName MIN_MAX_VALUE_LEAF_QNAME = QName.create(MASTER_CONTAINER_QNAME, "min-max-value-leaf");
62 private static final QName PRESENCE_QNAME = QName.create(MASTER_CONTAINER_QNAME, "presence");
64 private static final YangInstanceIdentifier MASTER_CONTAINER_PATH =
65 YangInstanceIdentifier.of(MASTER_CONTAINER_QNAME);
66 private static final YangInstanceIdentifier MIN_MAX_LIST_PATH =
67 YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH).node(MIN_MAX_LIST_QNAME).build();
68 private static final YangInstanceIdentifier PRESENCE_PATH = YangInstanceIdentifier.of(PRESENCE_QNAME);
69 private static final YangInstanceIdentifier PRESENCE_MIN_MAX_LIST_PATH = PRESENCE_PATH.node(MIN_MAX_LIST_QNAME);
70 private static final YangInstanceIdentifier MIN_MAX_LIST_NO_MINMAX_PATH =
71 YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH).node(MIN_MAX_LIST_QNAME_NO_MINMAX).build();
72 private static final YangInstanceIdentifier MIN_MAX_LEAF_LIST_PATH =
73 YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH).node(MIN_MAX_LEAF_LIST_QNAME).build();
75 private final MapEntryNode fooEntryNodeWithValue = Builders.mapEntryBuilder()
76 .withNodeIdentifier(NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "foo"))
77 .withChild(ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "footest"))
79 private final MapEntryNode bazEntryNodeWithValue = Builders.mapEntryBuilder()
80 .withNodeIdentifier(NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "baz"))
81 .withChild(ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "baztest"))
83 private final MapEntryNode fooEntryNode = ImmutableNodes.mapEntry(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME,
85 private final MapEntryNode barEntryNode = ImmutableNodes.mapEntry(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME,
87 private final MapEntryNode bazEntryNode = ImmutableNodes.mapEntry(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME,
89 private final SystemMapNode mapNodeBazFuzWithNodes = ImmutableNodes.mapNodeBuilder()
90 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
91 .withChild(bazEntryNode).withChild(bazEntryNodeWithValue).withChild(fooEntryNode)
93 private final SystemMapNode mapNodeFooWithNodes = ImmutableNodes.mapNodeBuilder()
94 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
95 .withChild(fooEntryNode).withChild(fooEntryNodeWithValue).withChild(barEntryNode).withChild(bazEntryNode)
97 private final SystemMapNode mapNodeBar = ImmutableNodes.mapNodeBuilder()
98 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
99 .withChild(barEntryNode).build();
100 private final SystemMapNode mapNodeBaz = ImmutableNodes.mapNodeBuilder()
101 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME))
102 .withChild(bazEntryNode).build();
104 private static EffectiveModelContext schemaContext;
106 private DataTree inMemoryDataTree;
109 public static void beforeClass() {
110 schemaContext = YangParserTestUtils.parseYang("""
113 namespace "urn:opendaylight:params:xml:ns:yang:list-constraints-validation-test-model";
114 prefix "list-constraints-validation";
116 revision "2015-02-02" {
117 description "Initial revision.";
120 container master-container {
124 key "min-max-key-leaf";
125 leaf min-max-key-leaf {
128 leaf min-max-value-leaf {
133 list min-max-list-no-minmax {
134 key "min-max-key-leaf";
135 leaf min-max-key-leaf {
140 leaf-list min-max-leaf-list {
148 presence "anchor point";
154 key "min-max-key-leaf";
156 leaf min-max-key-leaf {
165 public static void afterClass() {
166 schemaContext = null;
170 public void prepare() throws DataValidationFailedException {
171 inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL,
173 final DataTreeSnapshot initialDataTreeSnapshot = inMemoryDataTree.takeSnapshot();
174 final DataTreeModification modificationTree = initialDataTreeSnapshot.newModification();
176 modificationTree.write(MASTER_CONTAINER_PATH, ImmutableNodes.containerNode(MASTER_CONTAINER_QNAME));
177 modificationTree.ready();
178 inMemoryDataTree.commit(inMemoryDataTree.prepare(modificationTree));
182 public void minMaxListDeleteWriteTest() throws DataValidationFailedException {
183 final DataTreeModification modificationTree1 = inMemoryDataTree.takeSnapshot().newModification();
185 Map<QName, Object> key = new HashMap<>();
186 key.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
188 NodeIdentifierWithPredicates mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME , key);
190 final YangInstanceIdentifier minMaxLeafFoo = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
191 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2).build();
194 key.put(MIN_MAX_KEY_LEAF_QNAME, "NON-EXISTING-LEAF");
196 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, key);
198 final YangInstanceIdentifier minMaxLeafNel = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
199 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2).build();
201 final Map<QName, Object> keyTemp = new HashMap<>();
202 keyTemp.put(MIN_MAX_KEY_LEAF_QNAME, "baz");
204 NodeIdentifierWithPredicates mapEntryPathTest = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME , keyTemp);
206 final YangInstanceIdentifier pathToBaz = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
207 .node(MIN_MAX_LIST_QNAME).node(mapEntryPathTest).node(MIN_MAX_VALUE_LEAF_QNAME).build();
210 keyTemp.put(MIN_MAX_KEY_LEAF_QNAME, "bar");
212 mapEntryPathTest = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME , keyTemp);
214 final YangInstanceIdentifier pathToBar = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
215 .node(MIN_MAX_LIST_QNAME).node(mapEntryPathTest).node(MIN_MAX_VALUE_LEAF_QNAME).build();
218 keyTemp.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
220 final NodeIdentifierWithPredicates mapEntryPathTestKey = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME,
223 final YangInstanceIdentifier pathToKeyFoo = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
224 .node(MIN_MAX_LIST_QNAME).node(mapEntryPathTestKey).node(MIN_MAX_KEY_LEAF_QNAME).build();
226 final LeafNode<String> newNode = ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "test");
227 final LeafNode<String> newNode1 = ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "test1");
228 final LeafNode<String> newNode2 = ImmutableNodes.leafNode(MIN_MAX_VALUE_LEAF_QNAME, "test2");
229 final LeafNode<String> newNodekey = ImmutableNodes.leafNode(MIN_MAX_KEY_LEAF_QNAME, "foo");
231 assertFalse(inMemoryDataTree.toString().contains("list"));
233 DataTreeSnapshot snapshotAfterCommit = inMemoryDataTree.takeSnapshot();
234 Optional<NormalizedNode> minMaxListRead = snapshotAfterCommit.readNode(MIN_MAX_LIST_PATH);
235 assertFalse(minMaxListRead.isPresent());
237 modificationTree1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
238 modificationTree1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
239 modificationTree1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
240 modificationTree1.merge(MIN_MAX_LIST_PATH, mapNodeBar);
241 modificationTree1.merge(MIN_MAX_LIST_PATH, mapNodeBaz);
242 modificationTree1.write(pathToKeyFoo, newNodekey);
243 modificationTree1.write(pathToBaz, newNode2);
244 modificationTree1.write(pathToBaz, newNode1);
245 modificationTree1.write(pathToBaz, newNode);
246 modificationTree1.delete(minMaxLeafFoo);
247 modificationTree1.delete(minMaxLeafNel);
249 modificationTree1.ready();
250 inMemoryDataTree.validate(modificationTree1);
251 final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree1);
252 inMemoryDataTree.commit(prepare);
254 DataTreeSnapshot test = inMemoryDataTree.takeSnapshot();
255 testLoop(test, "bar", "test");
257 DataTreeModification tempMod = test.newModification();
258 tempMod.write(pathToBaz, newNode2);
259 tempMod.write(pathToBaz, newNode1);
260 tempMod.merge(pathToBaz, newNode2);
261 tempMod.write(pathToBaz, newNode1);
264 inMemoryDataTree.validate(tempMod);
265 final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(tempMod);
266 inMemoryDataTree.commit(prepare1);
268 DataTreeSnapshot test1 = inMemoryDataTree.takeSnapshot();
269 testLoop(test1, "bar", "test1");
271 DataTreeModification tempMod1 = test1.newModification();
272 tempMod1.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
275 inMemoryDataTree.validate(tempMod1);
276 final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(tempMod1);
277 inMemoryDataTree.commit(prepare2);
279 DataTreeSnapshot test2 = inMemoryDataTree.takeSnapshot();
280 minMaxListRead = test2.readNode(MIN_MAX_LIST_PATH);
281 assertTrue(minMaxListRead.isPresent());
282 assertEquals(3, ((NormalizedNodeContainer<?>) minMaxListRead.orElseThrow()).size());
284 DataTreeModification tempMod2 = test2.newModification();
285 tempMod2.write(MIN_MAX_LIST_PATH, mapNodeBaz);
286 tempMod2.write(pathToBaz, newNode2);
289 inMemoryDataTree.validate(tempMod2);
290 final DataTreeCandidate prepare3 = inMemoryDataTree.prepare(tempMod2);
291 inMemoryDataTree.commit(prepare3);
293 DataTreeSnapshot test3 = inMemoryDataTree.takeSnapshot();
294 minMaxListRead = test3.readNode(MIN_MAX_LIST_PATH);
295 assertTrue(minMaxListRead.isPresent());
296 assertEquals(1, ((NormalizedNodeContainer<?>) minMaxListRead.orElseThrow()).size());
297 assertThat(minMaxListRead.orElseThrow().body().toString(), containsString("test2"));
299 DataTreeModification tempMod3 = test3.newModification();
300 tempMod3.merge(MIN_MAX_LIST_PATH, mapNodeBar);
301 tempMod3.merge(pathToBar, newNode1);
304 inMemoryDataTree.validate(tempMod3);
305 final DataTreeCandidate prepare4 = inMemoryDataTree.prepare(tempMod3);
306 inMemoryDataTree.commit(prepare4);
308 DataTreeSnapshot test4 = inMemoryDataTree.takeSnapshot();
309 testLoop(test4, "test1", "test2");
313 public void minMaxLeafListPass() throws DataValidationFailedException {
314 final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
316 final NodeWithValue<?> barPath = new NodeWithValue<>(MIN_MAX_LIST_QNAME, "bar");
317 final NodeWithValue<?> gooPath = new NodeWithValue<>(MIN_MAX_LIST_QNAME, "goo");
319 final LeafSetEntryNode<Object> barLeafSetEntry = Builders.leafSetEntryBuilder()
320 .withNodeIdentifier(barPath)
321 .withValue("bar").build();
322 final LeafSetEntryNode<Object> gooLeafSetEntry = Builders.leafSetEntryBuilder()
323 .withNodeIdentifier(gooPath)
324 .withValue("goo").build();
326 final LeafSetNode<Object> fooLeafSetNode = Builders.leafSetBuilder()
327 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LEAF_LIST_QNAME))
328 .withChildValue("foo")
331 modificationTree.write(MIN_MAX_LEAF_LIST_PATH, fooLeafSetNode);
332 modificationTree.write(MIN_MAX_LEAF_LIST_PATH.node(barPath), barLeafSetEntry);
333 modificationTree.ready();
335 inMemoryDataTree.validate(modificationTree);
336 final DataTreeCandidate prepare1 = inMemoryDataTree.prepare(modificationTree);
337 inMemoryDataTree.commit(prepare1);
339 DataTreeSnapshot test1 = inMemoryDataTree.takeSnapshot();
341 DataTreeModification tempMod1 = test1.newModification();
342 tempMod1.write(MIN_MAX_LEAF_LIST_PATH.node(gooPath), gooLeafSetEntry);
343 tempMod1.write(MIN_MAX_LEAF_LIST_PATH.node(barPath), barLeafSetEntry);
346 inMemoryDataTree.validate(tempMod1);
347 final DataTreeCandidate prepare2 = inMemoryDataTree.prepare(tempMod1);
348 inMemoryDataTree.commit(prepare2);
350 final DataTreeSnapshot snapshotAfterCommit = inMemoryDataTree.takeSnapshot();
351 final Optional<NormalizedNode> masterContainer = snapshotAfterCommit.readNode(MASTER_CONTAINER_PATH);
352 assertTrue(masterContainer.isPresent());
353 final Optional<NormalizedNodeContainer<?>> leafList = ((DistinctNodeContainer) masterContainer.orElseThrow())
354 .findChildByArg(new NodeIdentifier(MIN_MAX_LEAF_LIST_QNAME));
355 assertTrue(leafList.isPresent());
356 assertEquals(3, leafList.orElseThrow().size());
360 public void minMaxListDeleteTest() throws DataValidationFailedException {
361 final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
364 NodeIdentifierWithPredicates mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME,
365 MIN_MAX_KEY_LEAF_QNAME, "foo");
367 final YangInstanceIdentifier minMaxLeafFoo = MASTER_CONTAINER_PATH
368 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
370 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "bar");
372 final YangInstanceIdentifier minMaxLeafBar = MASTER_CONTAINER_PATH
373 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
375 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "baz");
377 final YangInstanceIdentifier minMaxLeafBaz = MASTER_CONTAINER_PATH
378 .node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
380 modificationTree.write(MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
381 modificationTree.merge(MIN_MAX_LIST_PATH, mapNodeBar);
382 modificationTree.merge(MIN_MAX_LIST_PATH, mapNodeBaz);
383 modificationTree.delete(minMaxLeafFoo);
384 modificationTree.delete(minMaxLeafBar);
385 modificationTree.delete(minMaxLeafBaz);
387 modificationTree.ready();
389 inMemoryDataTree.validate(modificationTree);
390 final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
391 inMemoryDataTree.commit(prepare);
393 // Empty list should have disappeared, along with the container, as we are not enforcing root
394 final NormalizedNode data = inMemoryDataTree.takeSnapshot().readNode(YangInstanceIdentifier.of()).orElseThrow();
395 assertTrue(data instanceof ContainerNode);
396 assertEquals(0, ((ContainerNode) data).size());
400 public void minMaxListDeleteExceptionTest() throws DataValidationFailedException {
401 final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
403 NodeIdentifierWithPredicates mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME,
404 MIN_MAX_KEY_LEAF_QNAME, "foo");
406 final YangInstanceIdentifier minMaxLeafFoo = PRESENCE_PATH.node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
408 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "bar");
410 final YangInstanceIdentifier minMaxLeafBar = PRESENCE_PATH.node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
412 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME, MIN_MAX_KEY_LEAF_QNAME, "baz");
414 final YangInstanceIdentifier minMaxLeafBaz = PRESENCE_PATH.node(MIN_MAX_LIST_QNAME).node(mapEntryPath2);
416 modificationTree.write(PRESENCE_PATH, ImmutableNodes.containerNode(PRESENCE_QNAME));
417 modificationTree.write(PRESENCE_MIN_MAX_LIST_PATH, mapNodeFooWithNodes);
418 modificationTree.merge(PRESENCE_MIN_MAX_LIST_PATH, mapNodeBar);
419 modificationTree.merge(PRESENCE_MIN_MAX_LIST_PATH, mapNodeBaz);
420 modificationTree.delete(minMaxLeafFoo);
421 modificationTree.delete(minMaxLeafBar);
422 modificationTree.delete(minMaxLeafBaz);
425 // Unlike minMaxListDeleteTest(), presence container enforces the list to be present
426 modificationTree.ready();
427 fail("Should have failed with IAE");
428 } catch (IllegalArgumentException e) {
430 Node (urn:opendaylight:params:xml:ns:yang:list-constraints-validation-test-model?revision=2015-02-02)\
431 presence is missing mandatory descendant /(urn:opendaylight:params:xml:ns:yang:list-constraints-\
432 validation-test-model?revision=2015-02-02)min-max-list""", e.getMessage());
437 public void minMaxListNoMinMaxDeleteTest() throws DataValidationFailedException {
438 final MapEntryNode fooEntryNoMinMaxNode =
439 ImmutableNodes.mapEntry(MIN_MAX_LIST_QNAME_NO_MINMAX, MIN_MAX_KEY_LEAF_QNAME, "foo");
440 final SystemMapNode mapNode1 = ImmutableNodes.mapNodeBuilder()
441 .withNodeIdentifier(new NodeIdentifier(MIN_MAX_LIST_QNAME_NO_MINMAX))
442 .withChild(fooEntryNoMinMaxNode).build();
444 final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
446 Map<QName, Object> key = new HashMap<>();
447 key.put(MIN_MAX_KEY_LEAF_QNAME, "foo");
449 NodeIdentifierWithPredicates mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME_NO_MINMAX, key);
451 final YangInstanceIdentifier minMaxLeafFoo = MASTER_CONTAINER_PATH
452 .node(MIN_MAX_LIST_QNAME_NO_MINMAX).node(mapEntryPath2);
455 key.put(MIN_MAX_KEY_LEAF_QNAME, "non-existing-leaf");
457 mapEntryPath2 = NodeIdentifierWithPredicates.of(MIN_MAX_LIST_QNAME_NO_MINMAX, key);
459 YangInstanceIdentifier minMaxLeafNel = YangInstanceIdentifier.builder(MASTER_CONTAINER_PATH)
460 .node(MIN_MAX_LIST_QNAME_NO_MINMAX).node(mapEntryPath2).build();
462 modificationTree.write(MIN_MAX_LIST_NO_MINMAX_PATH, mapNode1);
463 modificationTree.delete(minMaxLeafFoo);
464 modificationTree.delete(minMaxLeafNel);
466 modificationTree.ready();
468 inMemoryDataTree.validate(modificationTree);
469 final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
470 inMemoryDataTree.commit(prepare);
472 final DataTreeSnapshot snapshotAfterCommit = inMemoryDataTree.takeSnapshot();
473 final Optional<NormalizedNode> minMaxListRead = snapshotAfterCommit.readNode(MIN_MAX_LIST_NO_MINMAX_PATH);
475 // Empty list should have disappeared
476 assertFalse(minMaxListRead.isPresent());
479 private static void testLoop(final DataTreeSnapshot snapshot, final String first, final String second) {
480 Optional<NormalizedNode> minMaxListRead = snapshot.readNode(MIN_MAX_LIST_PATH);
481 assertTrue(minMaxListRead.isPresent());
482 assertEquals(2, ((NormalizedNodeContainer<?>) minMaxListRead.orElseThrow()).size());
484 for (Object collectionChild : (Collection<?>) minMaxListRead.orElseThrow().body()) {
485 if (collectionChild.toString().contains(first)) {
486 assertTrue(collectionChild.toString().contains(first));
488 assertTrue(collectionChild.toString().contains(second));