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