Fix static methods and convert to lambdas
[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.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.mockito.Mockito.mock;
15 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
16 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
17 import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
18 import com.google.common.collect.Sets;
19 import java.io.IOException;
20 import java.util.concurrent.atomic.AtomicInteger;
21 import javax.xml.transform.dom.DOMSource;
22 import org.junit.Assert;
23 import org.junit.Before;
24 import org.junit.Test;
25 import org.mockito.MockitoAnnotations;
26 import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeNavigator;
27 import org.opendaylight.controller.cluster.datastore.util.TestModel;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
32 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
38 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
39 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
40 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
41 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
42 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
43
44 public class NormalizedNodePrunerTest {
45     private static final SchemaContext NO_TEST_SCHEMA = TestModel.createTestContextWithoutTestSchema();
46     private static final SchemaContext NO_AUG_SCHEMA = TestModel.createTestContextWithoutAugmentationSchema();
47     private static final SchemaContext FULL_SCHEMA = TestModel.createTestContext();
48
49     @Before
50     public void setUp(){
51         MockitoAnnotations.initMocks(this);
52     }
53
54     private static NormalizedNodePruner prunerFullSchema(YangInstanceIdentifier path) {
55         return new NormalizedNodePruner(path, FULL_SCHEMA);
56     }
57
58     private static NormalizedNodePruner prunerNoAugSchema(YangInstanceIdentifier path) {
59         return new NormalizedNodePruner(path, NO_AUG_SCHEMA);
60     }
61
62     private static NormalizedNodePruner prunerNoTestSchema(YangInstanceIdentifier path) {
63         return new NormalizedNodePruner(path, NO_TEST_SCHEMA);
64     }
65
66     @Test
67     public void testNodesNotPrunedWhenSchemaPresent() throws IOException {
68         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
69
70         NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
71
72         NormalizedNode<?, ?> expected = createTestContainer();
73
74         normalizedNodeWriter.write(expected);
75
76         NormalizedNode<?, ?> actual = pruner.normalizedNode();
77
78         assertEquals(expected, actual);
79
80     }
81
82     @Test(expected = IllegalStateException.class)
83     public void testReusePruner() throws IOException {
84         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
85
86         NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
87
88         NormalizedNode<?, ?> expected = createTestContainer();
89
90         normalizedNodeWriter.write(expected);
91
92         NormalizedNode<?, ?> actual = pruner.normalizedNode();
93
94         assertEquals(expected, actual);
95
96         NormalizedNodeWriter.forStreamWriter(pruner).write(expected);
97
98     }
99
100
101     @Test
102     public void testNodesPrunedWhenAugmentationSchemaMissing() throws IOException {
103         NormalizedNodePruner pruner = prunerNoAugSchema(TestModel.TEST_PATH);
104
105         NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
106
107         NormalizedNode<?, ?> expected = createTestContainer();
108
109         normalizedNodeWriter.write(expected);
110
111         NormalizedNode<?, ?> actual = pruner.normalizedNode();
112
113         Assert.assertNotEquals(expected, actual);
114
115         // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
116         assertTrue(countNodes(expected, "store:aug") > 0);
117
118         // All nodes from the augmentation module are gone from the resulting node
119         assertEquals(0, countNodes(actual, "store:aug"));
120     }
121
122     @Test
123     public void testNodesPrunedWhenTestSchemaMissing() throws IOException {
124         NormalizedNodePruner pruner = prunerNoTestSchema(TestModel.TEST_PATH);
125
126         NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
127
128         NormalizedNode<?, ?> expected = createTestContainer();
129
130         normalizedNodeWriter.write(expected);
131
132         NormalizedNode<?, ?> actual = pruner.normalizedNode();
133
134         // Since top level schema is missing null is returned
135         assertNull(actual);
136
137         // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
138         assertTrue(countNodes(expected, "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test") > 0);
139
140     }
141
142     private static int countNodes(NormalizedNode<?,?> normalizedNode, final String namespaceFilter){
143         if(normalizedNode == null){
144             return 0;
145         }
146         final AtomicInteger count = new AtomicInteger();
147         new NormalizedNodeNavigator((level, parentPath, normalizedNode1) -> {
148             if(!(normalizedNode1.getIdentifier() instanceof AugmentationIdentifier)) {
149                 if (normalizedNode1.getIdentifier().getNodeType().getNamespace().toString().contains(namespaceFilter)) {
150                     count.incrementAndGet();
151                 }
152             }
153         }).navigate(YangInstanceIdentifier.EMPTY.toString(), normalizedNode);
154
155         return count.get();
156     }
157
158     @Test
159     public void testLeafNodeNotPrunedWhenHasNoParent() throws IOException {
160         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.DESC_QNAME));
161         NormalizedNode<?, ?> input = Builders.leafBuilder().withNodeIdentifier(
162                 new NodeIdentifier(TestModel.DESC_QNAME)).withValue("test").build();
163         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
164
165         NormalizedNode<?, ?> actual = pruner.normalizedNode();
166         assertEquals("normalizedNode", input, actual);
167     }
168
169     @Test
170     public void testLeafNodePrunedWhenHasAugmentationParentAndSchemaMissing() throws IOException {
171         AugmentationIdentifier augId = new AugmentationIdentifier(Sets.newHashSet(TestModel.AUG_CONT_QNAME));
172         NormalizedNodePruner pruner = prunerFullSchema(YangInstanceIdentifier.builder().
173                 node(TestModel.TEST_QNAME).node(TestModel.AUGMENTED_LIST_QNAME).
174                         node(TestModel.AUGMENTED_LIST_QNAME).node(augId).build());
175         LeafNode<Object> child = Builders.leafBuilder().withNodeIdentifier(
176                 new NodeIdentifier(TestModel.INVALID_QNAME)).withValue("test").build();
177         NormalizedNode<?, ?> input = Builders.augmentationBuilder().withNodeIdentifier(augId).withChild(child).build();
178         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
179
180         NormalizedNode<?, ?> actual = pruner.normalizedNode();
181         assertEquals("normalizedNode", Builders.augmentationBuilder().withNodeIdentifier(augId).build(), actual);
182     }
183
184     @Test
185     public void testLeafNodePrunedWhenHasNoParentAndSchemaMissing() throws IOException {
186         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.INVALID_QNAME));
187         NormalizedNode<?, ?> input = Builders.leafBuilder().withNodeIdentifier(
188                 new NodeIdentifier(TestModel.INVALID_QNAME)).withValue("test").build();
189         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
190
191         NormalizedNode<?, ?> actual = pruner.normalizedNode();
192         assertNull(actual);
193     }
194
195
196     @Test
197     public void testLeafSetEntryNodeNotPrunedWhenHasNoParent() throws IOException {
198         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.SHOE_QNAME));
199         NormalizedNode<?, ?> input = Builders.leafSetEntryBuilder().withValue("puma").withNodeIdentifier(
200                 new NodeWithValue<>(TestModel.SHOE_QNAME, "puma")).build();
201         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
202
203         NormalizedNode<?, ?> actual = pruner.normalizedNode();
204         assertEquals("normalizedNode", input, actual);
205     }
206
207     @Test
208     public void testLeafSetEntryNodeNotPrunedWhenHasParent() throws IOException {
209         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.SHOE_QNAME));
210         LeafSetEntryNode<Object> child = Builders.leafSetEntryBuilder().withValue("puma").withNodeIdentifier(
211                 new NodeWithValue<>(TestModel.SHOE_QNAME, "puma")).build();
212         NormalizedNode<?, ?> input = Builders.leafSetBuilder().withNodeIdentifier(
213                 new NodeIdentifier(TestModel.SHOE_QNAME)).withChild(child).build();
214         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
215
216         NormalizedNode<?, ?> actual = pruner.normalizedNode();
217         assertEquals("normalizedNode", input, actual);
218     }
219
220     @Test
221     public void testLeafSetEntryNodePrunedWhenHasNoParentAndSchemaMissing() throws IOException {
222         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.INVALID_QNAME));
223         NormalizedNode<?, ?> input = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
224                 new NodeWithValue<>(TestModel.INVALID_QNAME, "test")).build();
225         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
226
227         NormalizedNode<?, ?> actual = pruner.normalizedNode();
228         assertNull(actual);
229     }
230
231     @Test
232     public void testLeafSetEntryNodePrunedWhenHasParentAndSchemaMissing() throws IOException {
233         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.INVALID_QNAME));
234         LeafSetEntryNode<Object> child = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
235                 new NodeWithValue<>(TestModel.INVALID_QNAME, "test")).build();
236         NormalizedNode<?, ?> input = Builders.leafSetBuilder().withNodeIdentifier(
237                 new NodeIdentifier(TestModel.INVALID_QNAME)).withChild(child).build();
238         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
239
240         NormalizedNode<?, ?> actual = pruner.normalizedNode();
241         assertNull(actual);
242     }
243
244     @Test
245     public void testAnyXMLNodeNotPrunedWhenHasNoParent() throws IOException {
246         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.ANY_XML_QNAME));
247         NormalizedNode<?, ?> input = Builders.anyXmlBuilder().withNodeIdentifier(
248                 new NodeIdentifier(TestModel.ANY_XML_QNAME)).withValue(mock(DOMSource.class)).build();
249         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
250
251         NormalizedNode<?, ?> actual = pruner.normalizedNode();
252         assertEquals("normalizedNode", input, actual);
253     }
254
255
256     @Test
257     public void testAnyXMLNodeNotPrunedWhenHasParent() throws IOException {
258         NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
259         AnyXmlNode child = Builders.anyXmlBuilder().withNodeIdentifier(
260                 new NodeIdentifier(TestModel.ANY_XML_QNAME)).withValue(mock(DOMSource.class)).build();
261         NormalizedNode<?, ?> input = Builders.containerBuilder().withNodeIdentifier(
262                 new NodeIdentifier(TestModel.TEST_QNAME)).withChild(child).build();
263         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
264
265         NormalizedNode<?, ?> actual = pruner.normalizedNode();
266         assertEquals("normalizedNode", input, actual);
267     }
268
269     @Test
270     public void testAnyXmlNodePrunedWhenHasNoParentAndSchemaMissing() throws IOException {
271         NormalizedNodePruner pruner = prunerNoTestSchema(TestModel.TEST_PATH.node(TestModel.ANY_XML_QNAME));
272         NormalizedNode<?, ?> input = Builders.anyXmlBuilder().withNodeIdentifier(
273                 new NodeIdentifier(TestModel.ANY_XML_QNAME)).withValue(mock(DOMSource.class)).build();
274         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
275
276         NormalizedNode<?, ?> actual = pruner.normalizedNode();
277         assertNull(actual);
278     }
279
280     @Test
281     public void testInnerContainerNodeWithFullPathPathNotPruned() throws IOException {
282         YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
283                 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
284                     node(TestModel.INNER_LIST_QNAME).nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").
285                         node(TestModel.INNER_CONTAINER_QNAME).build();
286         NormalizedNodePruner pruner = prunerFullSchema(path);
287
288         NormalizedNode<?, ?> input = ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME);
289         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
290
291         NormalizedNode<?, ?> actual = pruner.normalizedNode();
292         assertEquals("normalizedNode", input, actual);
293     }
294
295     @Test
296     public void testInnerContainerNodeWithFullPathPrunedWhenSchemaMissing() throws IOException {
297         YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
298                 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
299                     node(TestModel.INNER_LIST_QNAME).nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").
300                         node(TestModel.INVALID_QNAME).build();
301         NormalizedNodePruner pruner = prunerFullSchema(path);
302
303         NormalizedNode<?, ?> input = ImmutableNodes.containerNode(TestModel.INVALID_QNAME);
304         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
305
306         NormalizedNode<?, ?> actual = pruner.normalizedNode();
307         assertNull(actual);
308     }
309
310     @Test
311     public void testInnerContainerNodeWithParentPathPrunedWhenSchemaMissing() throws IOException {
312         YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
313                 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).build();
314         NormalizedNodePruner pruner = prunerFullSchema(path);
315
316         MapNode innerList = mapNodeBuilder(TestModel.INNER_LIST_QNAME).withChild(mapEntryBuilder(
317                 TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").withChild(
318                         ImmutableNodes.containerNode(TestModel.INVALID_QNAME)).build()).build();
319         NormalizedNode<?, ?> input = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
320                 withChild(innerList).build();
321         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
322
323         NormalizedNode<?, ?> expected = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
324                 withChild(mapNodeBuilder(TestModel.INNER_LIST_QNAME).withChild(mapEntryBuilder(
325                 TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").build()).build()).build();
326         NormalizedNode<?, ?> actual = pruner.normalizedNode();
327         assertEquals("normalizedNode", expected, actual);
328     }
329
330     @Test
331     public void testInnerListNodeWithFullPathNotPruned() throws IOException {
332         YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
333                 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
334                     node(TestModel.INNER_LIST_QNAME).build();
335         NormalizedNodePruner pruner = prunerFullSchema(path);
336
337         MapNode input = mapNodeBuilder(TestModel.INNER_LIST_QNAME).withChild(mapEntryBuilder(
338                 TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").withChild(
339                         ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME)).build()).build();
340         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
341
342         NormalizedNode<?, ?> actual = pruner.normalizedNode();
343         assertEquals("normalizedNode", input, actual);
344     }
345
346     @Test
347     public void testInnerListNodeWithFullPathPrunedWhenSchemaMissing() throws IOException {
348         YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
349                 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
350                     node(TestModel.INVALID_QNAME).build();
351         NormalizedNodePruner pruner = prunerFullSchema(path);
352
353         MapNode input = mapNodeBuilder(TestModel.INVALID_QNAME).withChild(mapEntryBuilder(
354                 TestModel.INVALID_QNAME, TestModel.NAME_QNAME, "one").withChild(
355                         ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME)).build()).build();
356         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
357
358         NormalizedNode<?, ?> actual = pruner.normalizedNode();
359         assertNull(actual);
360     }
361
362     @Test
363     public void testInnerListNodeWithParentPathPrunedWhenSchemaMissing() throws IOException {
364         YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
365                 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).build();
366         NormalizedNodePruner pruner = prunerFullSchema(path);
367
368         MapNode innerList = mapNodeBuilder(TestModel.INVALID_QNAME).withChild(mapEntryBuilder(
369                 TestModel.INVALID_QNAME, TestModel.NAME_QNAME, "one").withChild(
370                         ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME)).build()).build();
371         NormalizedNode<?, ?> input = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
372                 withChild(innerList).build();
373         NormalizedNodeWriter.forStreamWriter(pruner).write(input);
374
375         NormalizedNode<?, ?> expected = mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1);
376         NormalizedNode<?, ?> actual = pruner.normalizedNode();
377         assertEquals("normalizedNode", expected, actual);
378     }
379
380     private static NormalizedNode<?, ?> createTestContainer() {
381         byte[] bytes1 = {1,2,3};
382         LeafSetEntryNode<Object> entry1 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
383                 new NodeWithValue<>(TestModel.BINARY_LEAF_LIST_QNAME, bytes1)).
384                 withValue(bytes1).build();
385
386         byte[] bytes2 = {};
387         LeafSetEntryNode<Object> entry2 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
388                 new NodeWithValue<>(TestModel.BINARY_LEAF_LIST_QNAME, bytes2)).
389                 withValue(bytes2).build();
390
391         LeafSetEntryNode<Object> entry3 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
392                 new NodeWithValue<>(TestModel.BINARY_LEAF_LIST_QNAME, null)).withValue(null).build();
393
394
395         return TestModel.createBaseTestContainerBuilder().
396                 withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(
397                         new NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME)).
398                         withChild(entry1).withChild(entry2).withChild(entry3).build()).
399                 withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATA_QNAME, new byte[]{1, 2, 3, 4})).
400                 build();
401     }
402 }