Remove checks for NormalizedNodeBuilderWrapper
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / test / java / org / opendaylight / controller / cluster / datastore / node / utils / transformer / NormalizedNodePrunerTest.java
1 /*
2  * Copyright (c) 2015 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
9 package org.opendaylight.controller.cluster.datastore.node.utils.transformer;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.mockito.Matchers.any;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.mock;
18 import static org.mockito.Mockito.never;
19 import static org.mockito.Mockito.verify;
20 import com.google.common.collect.ImmutableMap;
21 import com.google.common.collect.ImmutableSet;
22 import java.io.IOException;
23 import java.util.concurrent.atomic.AtomicInteger;
24 import javax.xml.transform.dom.DOMSource;
25 import org.junit.Assert;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.mockito.ArgumentCaptor;
29 import org.mockito.Mock;
30 import org.mockito.MockitoAnnotations;
31 import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeNavigator;
32 import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeVisitor;
33 import org.opendaylight.controller.cluster.datastore.util.TestModel;
34 import org.opendaylight.yangtools.yang.common.QName;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
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.impl.schema.builder.api.CollectionNodeBuilder;
42 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
43 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
44 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
45 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
46 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
47 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
48
49 public class NormalizedNodePrunerTest {
50
51     private NormalizedNodePruner prunerFullSchema;
52
53     private NormalizedNodePruner prunerNoAugSchema;
54
55     @Mock
56     private NormalizedNodeBuilderWrapper normalizedNodeBuilderWrapper;
57
58     @Mock
59     private NormalizedNodeContainerBuilder normalizedNodeContainerBuilder;
60
61     @Mock
62     private NormalizedNode<?,?> normalizedNode;
63
64     @Before
65     public void setUp(){
66         MockitoAnnotations.initMocks(this);
67         prunerFullSchema = new NormalizedNodePruner(TestModel.createTestContext());
68         prunerNoAugSchema = new NormalizedNodePruner(TestModel.createTestContextWithoutAugmentationSchema());
69         doReturn(normalizedNodeContainerBuilder).when(normalizedNodeBuilderWrapper).builder();
70         doReturn(TestModel.BOOLEAN_LEAF_QNAME).when(normalizedNodeBuilderWrapper).nodeType();
71         doReturn(normalizedNode).when(normalizedNodeContainerBuilder).build();
72         doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
73     }
74
75     @Test
76     public void testNodesNotPrunedWhenSchemaPresent() throws IOException {
77         NormalizedNodePruner pruner = prunerFullSchema;
78
79         NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
80
81         NormalizedNode<?, ?> expected = createTestContainer();
82
83         normalizedNodeWriter.write(expected);
84
85         NormalizedNode<?, ?> actual = pruner.normalizedNode();
86
87         assertEquals(expected, actual);
88
89     }
90
91     @Test(expected = IllegalStateException.class)
92     public void testReusePruner() throws IOException {
93         NormalizedNodePruner pruner = prunerFullSchema;
94
95         NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
96
97         NormalizedNode<?, ?> expected = createTestContainer();
98
99         normalizedNodeWriter.write(expected);
100
101         NormalizedNode<?, ?> actual = pruner.normalizedNode();
102
103         assertEquals(expected, actual);
104
105         NormalizedNodeWriter.forStreamWriter(pruner).write(expected);
106
107     }
108
109
110     @Test
111     public void testNodesPrunedWhenAugmentationSchemaNotPresent() throws IOException {
112         NormalizedNodePruner pruner = prunerNoAugSchema;
113
114         NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
115
116         NormalizedNode<?, ?> expected = createTestContainer();
117
118         normalizedNodeWriter.write(expected);
119
120         NormalizedNode<?, ?> actual = pruner.normalizedNode();
121
122         Assert.assertNotEquals(expected, actual);
123
124         // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
125         assertTrue(countNodes(expected, "store:aug") > 0);
126
127         // All nodes from the augmentation module are gone from the resulting node
128         assertEquals(0, countNodes(actual, "store:aug"));
129     }
130
131     @Test
132     public void testNodesPrunedWhenTestSchemaNotPresent() throws IOException {
133         NormalizedNodePruner pruner = new NormalizedNodePruner(TestModel.createTestContextWithoutTestSchema());
134
135         NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
136
137         NormalizedNode<?, ?> expected = createTestContainer();
138
139         normalizedNodeWriter.write(expected);
140
141         NormalizedNode<?, ?> actual = pruner.normalizedNode();
142
143         // Since top level schema is missing null is returned
144         assertNull(actual);
145
146         // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
147         assertTrue(countNodes(expected, "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test") > 0);
148
149     }
150
151
152     private static int countNodes(NormalizedNode<?,?> normalizedNode, final String namespaceFilter){
153         if(normalizedNode == null){
154             return 0;
155         }
156         final AtomicInteger count = new AtomicInteger();
157         new NormalizedNodeNavigator(new NormalizedNodeVisitor() {
158
159             @Override
160             public void visitNode(int level, String parentPath, NormalizedNode<?, ?> normalizedNode) {
161                 if(!(normalizedNode.getIdentifier() instanceof YangInstanceIdentifier.AugmentationIdentifier)) {
162                     if (normalizedNode.getIdentifier().getNodeType().getNamespace().toString().contains(namespaceFilter)) {
163                         count.incrementAndGet();
164                     }
165                 }
166             }
167         }).navigate(YangInstanceIdentifier.builder().build().toString(), normalizedNode);
168
169         return count.get();
170     }
171
172     @Test(expected = IllegalStateException.class)
173     public void testLeafNodeHasNoParent() throws IOException {
174         prunerFullSchema.leafNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), mock(Object.class));
175     }
176
177     @Test
178     public void testLeafNodeHasParent() throws IOException {
179         prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
180         Object o = mock(Object.class);
181         prunerFullSchema.leafNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), o);
182
183         ArgumentCaptor<NormalizedNode> captor = ArgumentCaptor.forClass(NormalizedNode.class);
184
185         verify(normalizedNodeContainerBuilder).addChild(captor.capture());
186
187         NormalizedNode<?, ?> value = captor.getValue();
188         assertEquals(normalizedNodeBuilderWrapper.identifier().getNodeType(), value.getNodeType());
189         assertEquals(normalizedNodeBuilderWrapper.identifier(), value.getIdentifier());
190         assertEquals(o, value.getValue());
191
192     }
193
194     @Test
195     public void testLeafNodeSchemaMissing() throws IOException {
196         prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
197         prunerNoAugSchema.leafNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME), mock(Object.class));
198         verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
199     }
200
201     @Test(expected = IllegalStateException.class)
202     public void testLeafSetEntryNodeHasNoParent() throws IOException {
203         prunerFullSchema.leafSetEntryNode(mock(Object.class));
204     }
205
206     @Test
207     public void testLeafSetEntryNodeHasParent() throws IOException {
208         prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
209         Object o = mock(Object.class);
210         YangInstanceIdentifier.PathArgument nodeIdentifier
211                 = new YangInstanceIdentifier.NodeWithValue(normalizedNodeBuilderWrapper.identifier().getNodeType(), o);
212         prunerFullSchema.leafSetEntryNode(o);
213
214         ArgumentCaptor<NormalizedNode> captor = ArgumentCaptor.forClass(NormalizedNode.class);
215
216         verify(normalizedNodeContainerBuilder).addChild(captor.capture());
217
218         NormalizedNode<?, ?> value = captor.getValue();
219         assertEquals(nodeIdentifier.getNodeType(), value.getNodeType());
220         assertEquals(nodeIdentifier, value.getIdentifier());
221         assertEquals(o, value.getValue());
222
223     }
224
225     @Test
226     public void testLeafSetEntryNodeSchemaMissing() throws IOException {
227         doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
228
229         prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
230         prunerNoAugSchema.leafSetEntryNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME));
231
232         verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
233     }
234
235     @Test(expected = IllegalStateException.class)
236     public void testAnyXMLNodeHasNoParent() throws IOException {
237         prunerFullSchema.anyxmlNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), mock(Object.class));
238     }
239
240     @Test
241     public void testAnyXMLNodeHasParent() throws IOException {
242         prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
243         YangInstanceIdentifier.NodeIdentifier nodeIdentifier = new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME);
244         DOMSource o = mock(DOMSource.class);
245         prunerFullSchema.anyxmlNode(nodeIdentifier, o);
246
247         ArgumentCaptor<NormalizedNode> captor = ArgumentCaptor.forClass(NormalizedNode.class);
248
249         verify(normalizedNodeContainerBuilder).addChild(captor.capture());
250
251         NormalizedNode<?, ?> value = captor.getValue();
252         assertEquals(nodeIdentifier.getNodeType(), value.getNodeType());
253         assertEquals(nodeIdentifier, value.getIdentifier());
254         assertEquals(o, value.getValue());
255     }
256
257     @Test
258     public void testAnyXmlNodeSchemaMissing() throws IOException {
259         prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
260         prunerNoAugSchema.anyxmlNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME), mock(DOMSource.class));
261
262         verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
263     }
264
265
266     @Test
267     public void testLeafSetPushesBuilderToStack() throws IOException {
268         prunerFullSchema.startLeafSet(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
269
270         assertEquals(1, prunerFullSchema.stack().size());
271         assertNotNull(prunerFullSchema.stack().peek());
272         assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof ListNodeBuilder);
273     }
274
275     @Test
276     public void testStartContainerNodePushesBuilderToStack() throws IOException {
277         prunerFullSchema.startContainerNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
278
279         assertEquals(1, prunerFullSchema.stack().size());
280         assertNotNull(prunerFullSchema.stack().peek());
281         assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
282     }
283
284     @Test
285     public void testStartUnkeyedListPushesBuilderToStack() throws IOException {
286         prunerFullSchema.startUnkeyedList(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
287
288         assertEquals(1, prunerFullSchema.stack().size());
289         assertNotNull(prunerFullSchema.stack().peek());
290         assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
291     }
292
293     @Test
294     public void testStartUnkeyedListItemPushesBuilderToStack() throws IOException {
295         prunerFullSchema.startUnkeyedListItem(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
296
297         assertEquals(1, prunerFullSchema.stack().size());
298         assertNotNull(prunerFullSchema.stack().peek());
299         assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
300     }
301
302     @Test
303     public void testStartMapNodePushesBuilderToStack() throws IOException {
304         prunerFullSchema.startMapNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
305
306         assertEquals(1, prunerFullSchema.stack().size());
307         assertNotNull(prunerFullSchema.stack().peek());
308         assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
309     }
310
311     @Test
312     public void testStartMapEntryNodePushesBuilderToStack() throws IOException {
313         prunerFullSchema.startMapEntryNode(
314                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(TestModel.BOOLEAN_LEAF_QNAME,
315                         ImmutableMap.<QName, Object>of(TestModel.BOOLEAN_LEAF_QNAME, "value")), 10);
316
317         assertEquals(1, prunerFullSchema.stack().size());
318         assertNotNull(prunerFullSchema.stack().peek());
319         assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
320     }
321
322     @Test
323     public void testStartOrderedMapNodePushesBuilderToStack() throws IOException {
324         prunerFullSchema.startOrderedMapNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
325
326         assertEquals(1, prunerFullSchema.stack().size());
327         assertNotNull(prunerFullSchema.stack().peek());
328         assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
329     }
330
331     @Test
332     public void testStartChoiceNodePushesBuilderToStack() throws IOException {
333         prunerFullSchema.startChoiceNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
334
335         assertEquals(1, prunerFullSchema.stack().size());
336         assertNotNull(prunerFullSchema.stack().peek());
337         assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeBuilder);
338     }
339
340     @Test
341     public void testStartAugmentationPushesBuilderToStack() throws IOException {
342         prunerFullSchema.startAugmentationNode(new YangInstanceIdentifier.AugmentationIdentifier(ImmutableSet.of(TestModel.AUG_CONT_QNAME)));
343
344         assertEquals(1, prunerFullSchema.stack().size());
345         assertNotNull(prunerFullSchema.stack().peek());
346         assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeBuilder);
347     }
348
349     @Test(expected = IllegalStateException.class)
350     public void testEndNodeWhenNoBuildersOnStack() throws IOException {
351         prunerFullSchema.endNode();
352     }
353
354     @Test
355     public void testEndNodeWhenOneBuildersOnStack() throws IOException {
356         prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
357         prunerFullSchema.endNode();
358         assertEquals(normalizedNode, prunerFullSchema.normalizedNode());
359     }
360
361     @Test
362     public void testEndNodeSchemaMissing() throws IOException {
363         doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
364
365         prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
366         prunerNoAugSchema.endNode();
367
368         assertEquals(null, prunerNoAugSchema.normalizedNode());
369     }
370
371     @Test
372     public void testEndNodeWhenMoreThanOneBuilderOnStack() throws IOException {
373         // A little lazy in adding the "parent" builder
374         prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
375         prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
376         prunerFullSchema.endNode();
377         assertEquals(null, prunerFullSchema.normalizedNode());
378
379         verify(normalizedNodeContainerBuilder).addChild(any(NormalizedNode.class));
380     }
381
382     private static NormalizedNode<?, ?> createTestContainer() {
383         byte[] bytes1 = {1,2,3};
384         LeafSetEntryNode<Object> entry1 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
385                 new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, bytes1)).
386                 withValue(bytes1).build();
387
388         byte[] bytes2 = {};
389         LeafSetEntryNode<Object> entry2 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
390                 new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, bytes2)).
391                 withValue(bytes2).build();
392
393         LeafSetEntryNode<Object> entry3 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
394                 new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, null)).
395                 withValue(null).build();
396
397
398         return TestModel.createBaseTestContainerBuilder().
399                 withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(
400                         new YangInstanceIdentifier.NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME)).
401                         withChild(entry1).withChild(entry2).withChild(entry3).build()).
402                 withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATA_QNAME, new byte[]{1, 2, 3, 4})).
403                 withChild(Builders.orderedMapBuilder().
404                         withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.ORDERED_LIST_QNAME)).
405                         withChild(ImmutableNodes.mapEntry(TestModel.ORDERED_LIST_ENTRY_QNAME,
406                                 TestModel.ID_QNAME, 11)).build()).
407                 build();
408     }
409 }