Migrate yang-data-tree-ri to JUnit5
[yangtools.git] / data / yang-data-tree-ri / src / test / java / org / opendaylight / yangtools / yang / data / tree / impl / DataTreeCandidatesTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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.tree.impl;
9
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertThrows;
12
13 import java.util.Collection;
14 import java.util.List;
15 import org.junit.jupiter.api.BeforeEach;
16 import org.junit.jupiter.api.Test;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
21 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
22 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
23 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
24 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
25 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode;
26 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
27 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
28 import org.opendaylight.yangtools.yang.data.tree.api.ModificationType;
29 import org.opendaylight.yangtools.yang.data.tree.api.TreeType;
30 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
31 import org.opendaylight.yangtools.yang.data.tree.spi.DataTreeCandidates;
32 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33
34 class DataTreeCandidatesTest extends AbstractTestModelTest {
35     private DataTree dataTree;
36
37     @BeforeEach
38     void setUp() throws Exception {
39         dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL, SCHEMA_CONTEXT);
40
41         final var testContainer = Builders.containerBuilder()
42             .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME))
43             .withChild(Builders.containerBuilder()
44                 .withNodeIdentifier(new NodeIdentifier(SchemaContext.NAME))
45                 .build())
46             .build();
47
48         final var modification = (InMemoryDataTreeModification) dataTree.takeSnapshot()
49                 .newModification();
50         final var cursor = modification.openCursor();
51         cursor.write(TestModel.TEST_PATH.getLastPathArgument(), testContainer);
52         modification.ready();
53
54         dataTree.validate(modification);
55         final var candidate = dataTree.prepare(modification);
56         dataTree.commit(candidate);
57     }
58
59     @Test
60     void testRootedCandidate() throws DataValidationFailedException {
61         final var innerDataTree = new InMemoryDataTreeFactory().create(
62             new DataTreeConfiguration.Builder(TreeType.OPERATIONAL)
63             .setMandatoryNodesValidation(true)
64             .setRootPath(TestModel.INNER_CONTAINER_PATH)
65             .setUniqueIndexes(true).build(), SCHEMA_CONTEXT);
66
67         final var leaf = ImmutableNodes.leafNode(TestModel.VALUE_QNAME, "testing-value");
68
69         final var modification = innerDataTree.takeSnapshot().newModification();
70         modification.write(TestModel.VALUE_PATH, leaf);
71
72         modification.ready();
73         dataTree.validate(modification);
74         final var candidate = dataTree.prepare(modification);
75         dataTree.commit(candidate);
76
77         final var newModification = dataTree.takeSnapshot().newModification();
78         final var newCandidate = DataTreeCandidates.newDataTreeCandidate(TestModel.INNER_CONTAINER_PATH,
79             candidate.getRootNode());
80
81         // lets see if getting the identifier of the root node throws an exception
82         assertThrows(IllegalStateException.class, () ->  newCandidate.getRootNode().name());
83
84         // lets see if we can apply this rooted candidate to a new dataTree
85         DataTreeCandidates.applyToModification(newModification,
86                 newCandidate);
87
88         final var readLeaf = (LeafNode<?>) newModification.readNode(TestModel.INNER_VALUE_PATH).orElseThrow();
89         assertEquals(readLeaf, leaf);
90     }
91
92     @Test
93     void testEmptyMergeOnContainer() throws DataValidationFailedException {
94         final var modification = dataTree.takeSnapshot().newModification();
95         modification.merge(TestModel.NON_PRESENCE_PATH, ImmutableNodes.containerNode(TestModel.NON_PRESENCE_QNAME));
96         modification.ready();
97         dataTree.validate(modification);
98
99         // The entire transaction needs to fizzle to a no-op
100         final var candidate = dataTree.prepare(modification);
101         final var node = candidate.getRootNode();
102         assertEquals(ModificationType.UNMODIFIED, node.modificationType());
103
104         // 'test'
105         assertUnmodified(1, node.childNodes());
106     }
107
108     @Test
109     void testEmptyWriteOnContainer() throws DataValidationFailedException {
110         final var modification = dataTree.takeSnapshot().newModification();
111         modification.write(TestModel.NON_PRESENCE_PATH, ImmutableNodes.containerNode(TestModel.NON_PRESENCE_QNAME));
112         modification.ready();
113         dataTree.validate(modification);
114
115         // The entire transaction needs to fizzle to a no-op
116         final var candidate = dataTree.prepare(modification);
117         final var node = candidate.getRootNode();
118         assertEquals(ModificationType.UNMODIFIED, node.modificationType());
119
120         // 'test'
121         assertUnmodified(1, node.childNodes());
122     }
123
124     @Test
125     void testEmptyMergesOnDeleted() throws DataValidationFailedException {
126         final var modification = dataTree.takeSnapshot().newModification();
127         modification.delete(TestModel.NON_PRESENCE_PATH);
128         modification.merge(TestModel.DEEP_CHOICE_PATH, ImmutableNodes.choiceNode(TestModel.DEEP_CHOICE_QNAME));
129         modification.ready();
130         dataTree.validate(modification);
131
132         final var candidate = dataTree.prepare(modification);
133         assertEquals(YangInstanceIdentifier.of(), candidate.getRootPath());
134         final var node = candidate.getRootNode();
135         assertEquals(ModificationType.UNMODIFIED, node.modificationType());
136
137         // 'test'
138         assertUnmodified(1, node.childNodes());
139     }
140
141     @Test
142     void testEmptyMergesOnExisting() throws DataValidationFailedException {
143         // Make sure 'non-presence' is present
144         var modification = dataTree.takeSnapshot().newModification();
145         modification.write(TestModel.NAME_PATH, ImmutableNodes.leafNode(TestModel.NAME_QNAME, "foo"));
146         modification.ready();
147         dataTree.validate(modification);
148         dataTree.commit(dataTree.prepare(modification));
149
150         // Issue an empty merge on it and a child choice
151         modification = dataTree.takeSnapshot().newModification();
152         modification.merge(TestModel.NON_PRESENCE_PATH, ImmutableNodes.containerNode(TestModel.NON_PRESENCE_QNAME));
153         modification.merge(TestModel.DEEP_CHOICE_PATH, ImmutableNodes.choiceNode(TestModel.DEEP_CHOICE_QNAME));
154         modification.ready();
155         dataTree.validate(modification);
156
157         // The entire transaction needs to fizzle to a no-op
158         final var candidate = dataTree.prepare(modification);
159         assertEquals(YangInstanceIdentifier.of(), candidate.getRootPath());
160         final var node = candidate.getRootNode();
161         assertEquals(ModificationType.UNMODIFIED, node.modificationType());
162
163         // 'non-presence' and 'test'
164         assertUnmodified(2, node.childNodes());
165     }
166
167     @Test
168     void testAggregateWithoutChanges() throws DataValidationFailedException {
169         final var modification1 = dataTree.takeSnapshot().newModification();
170         modification1.write(
171                 TestModel.INNER_CONTAINER_PATH.node(QName.create(TestModel.INNER_CONTAINER_QNAME,"value")),
172                 ImmutableNodes.leafNode(QName.create(TestModel.INNER_CONTAINER_QNAME,"value"),"value1"));
173         modification1.ready();
174         dataTree.validate(modification1);
175         DataTreeCandidate candidate1 = dataTree.prepare(modification1);
176         dataTree.commit(candidate1);
177
178         final var modification2 = dataTree.takeSnapshot().newModification();
179         modification2.delete(TestModel.INNER_CONTAINER_PATH);
180         modification2.ready();
181         dataTree.validate(modification2);
182         final var candidate2 = dataTree.prepare(modification2);
183         dataTree.commit(candidate2);
184
185         final var aggregateCandidate = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
186
187         assertEquals(ModificationType.UNMODIFIED, aggregateCandidate.getRootNode().modificationType());
188     }
189
190     @Test
191     void testAggregate() throws DataValidationFailedException {
192         final var modification = dataTree.takeSnapshot().newModification();
193         modification.write(
194                 TestModel.INNER_CONTAINER_PATH.node(QName.create(TestModel.INNER_CONTAINER_QNAME,"value")),
195                 ImmutableNodes.leafNode(QName.create(TestModel.INNER_CONTAINER_QNAME,"value"),"value1"));
196         modification.ready();
197         dataTree.validate(modification);
198         final var candidate = dataTree.prepare(modification);
199         dataTree.commit(candidate);
200
201         final var modification1 = dataTree.takeSnapshot().newModification();
202         modification1.delete(TestModel.INNER_CONTAINER_PATH);
203         modification1.ready();
204         dataTree.validate(modification1);
205         DataTreeCandidate candidate1 = dataTree.prepare(modification1);
206         dataTree.commit(candidate1);
207
208         final var modification2 = dataTree.takeSnapshot().newModification();
209         modification2.write(
210                 TestModel.INNER_CONTAINER_PATH.node(QName.create(TestModel.INNER_CONTAINER_QNAME,"value")),
211                 ImmutableNodes.leafNode(QName.create(TestModel.INNER_CONTAINER_QNAME,"value"),"value2"));
212         modification2.ready();
213         dataTree.validate(modification2);
214         final var candidate2 = dataTree.prepare(modification2);
215         dataTree.commit(candidate2);
216
217         final var aggregateCandidate = DataTreeCandidates.aggregate(List.of(candidate1, candidate2));
218
219         assertEquals(ModificationType.SUBTREE_MODIFIED,aggregateCandidate.getRootNode().modificationType());
220     }
221
222     private static void assertUnmodified(final int expSize, final Collection<DataTreeCandidateNode> nodes) {
223         assertEquals(expSize, nodes.size());
224         nodes.forEach(node -> assertEquals(ModificationType.UNMODIFIED, node.modificationType()));
225     }
226 }