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