2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.cluster.datastore.node.utils.transformer;
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.node.utils.NormalizedNodeVisitor;
28 import org.opendaylight.controller.cluster.datastore.util.TestModel;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
33 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
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.impl.ImmutableLeafSetEntryNodeBuilder;
42 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
43 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
45 public class NormalizedNodePrunerTest {
46 private static final SchemaContext NO_TEST_SCHEMA = TestModel.createTestContextWithoutTestSchema();
47 private static final SchemaContext NO_AUG_SCHEMA = TestModel.createTestContextWithoutAugmentationSchema();
48 private static final SchemaContext FULL_SCHEMA = TestModel.createTestContext();
52 MockitoAnnotations.initMocks(this);
55 private NormalizedNodePruner prunerFullSchema(YangInstanceIdentifier path) {
56 return new NormalizedNodePruner(path, FULL_SCHEMA);
59 private NormalizedNodePruner prunerNoAugSchema(YangInstanceIdentifier path) {
60 return new NormalizedNodePruner(path, NO_AUG_SCHEMA);
63 private NormalizedNodePruner prunerNoTestSchema(YangInstanceIdentifier path) {
64 return new NormalizedNodePruner(path, NO_TEST_SCHEMA);
68 public void testNodesNotPrunedWhenSchemaPresent() throws IOException {
69 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
71 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
73 NormalizedNode<?, ?> expected = createTestContainer();
75 normalizedNodeWriter.write(expected);
77 NormalizedNode<?, ?> actual = pruner.normalizedNode();
79 assertEquals(expected, actual);
83 @Test(expected = IllegalStateException.class)
84 public void testReusePruner() throws IOException {
85 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
87 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
89 NormalizedNode<?, ?> expected = createTestContainer();
91 normalizedNodeWriter.write(expected);
93 NormalizedNode<?, ?> actual = pruner.normalizedNode();
95 assertEquals(expected, actual);
97 NormalizedNodeWriter.forStreamWriter(pruner).write(expected);
103 public void testNodesPrunedWhenAugmentationSchemaMissing() throws IOException {
104 NormalizedNodePruner pruner = prunerNoAugSchema(TestModel.TEST_PATH);
106 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
108 NormalizedNode<?, ?> expected = createTestContainer();
110 normalizedNodeWriter.write(expected);
112 NormalizedNode<?, ?> actual = pruner.normalizedNode();
114 Assert.assertNotEquals(expected, actual);
116 // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
117 assertTrue(countNodes(expected, "store:aug") > 0);
119 // All nodes from the augmentation module are gone from the resulting node
120 assertEquals(0, countNodes(actual, "store:aug"));
124 public void testNodesPrunedWhenTestSchemaMissing() throws IOException {
125 NormalizedNodePruner pruner = prunerNoTestSchema(TestModel.TEST_PATH);
127 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
129 NormalizedNode<?, ?> expected = createTestContainer();
131 normalizedNodeWriter.write(expected);
133 NormalizedNode<?, ?> actual = pruner.normalizedNode();
135 // Since top level schema is missing null is returned
138 // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
139 assertTrue(countNodes(expected, "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test") > 0);
143 private static int countNodes(NormalizedNode<?,?> normalizedNode, final String namespaceFilter){
144 if(normalizedNode == null){
147 final AtomicInteger count = new AtomicInteger();
148 new NormalizedNodeNavigator(new NormalizedNodeVisitor() {
151 public void visitNode(int level, String parentPath, NormalizedNode<?, ?> normalizedNode) {
152 if(!(normalizedNode.getIdentifier() instanceof AugmentationIdentifier)) {
153 if (normalizedNode.getIdentifier().getNodeType().getNamespace().toString().contains(namespaceFilter)) {
154 count.incrementAndGet();
158 }).navigate(YangInstanceIdentifier.EMPTY.toString(), normalizedNode);
164 public void testLeafNodeNotPrunedWhenHasNoParent() throws IOException {
165 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.DESC_QNAME));
166 NormalizedNode<?, ?> input = Builders.leafBuilder().withNodeIdentifier(
167 new NodeIdentifier(TestModel.DESC_QNAME)).withValue("test").build();
168 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
170 NormalizedNode<?, ?> actual = pruner.normalizedNode();
171 assertEquals("normalizedNode", input, actual);
175 public void testLeafNodePrunedWhenHasAugmentationParentAndSchemaMissing() throws IOException {
176 AugmentationIdentifier augId = new AugmentationIdentifier(Sets.newHashSet(TestModel.AUG_CONT_QNAME));
177 NormalizedNodePruner pruner = prunerFullSchema(YangInstanceIdentifier.builder().
178 node(TestModel.TEST_QNAME).node(TestModel.AUGMENTED_LIST_QNAME).
179 node(TestModel.AUGMENTED_LIST_QNAME).node(augId).build());
180 LeafNode<Object> child = Builders.leafBuilder().withNodeIdentifier(
181 new NodeIdentifier(TestModel.INVALID_QNAME)).withValue("test").build();
182 NormalizedNode<?, ?> input = Builders.augmentationBuilder().withNodeIdentifier(augId).withChild(child).build();
183 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
185 NormalizedNode<?, ?> actual = pruner.normalizedNode();
186 assertEquals("normalizedNode", Builders.augmentationBuilder().withNodeIdentifier(augId).build(), actual);
190 public void testLeafNodePrunedWhenHasNoParentAndSchemaMissing() throws IOException {
191 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.INVALID_QNAME));
192 NormalizedNode<?, ?> input = Builders.leafBuilder().withNodeIdentifier(
193 new NodeIdentifier(TestModel.INVALID_QNAME)).withValue("test").build();
194 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
196 NormalizedNode<?, ?> actual = pruner.normalizedNode();
202 public void testLeafSetEntryNodeNotPrunedWhenHasNoParent() throws IOException {
203 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.SHOE_QNAME));
204 NormalizedNode<?, ?> input = Builders.leafSetEntryBuilder().withValue("puma").withNodeIdentifier(
205 new NodeWithValue<>(TestModel.SHOE_QNAME, "puma")).build();
206 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
208 NormalizedNode<?, ?> actual = pruner.normalizedNode();
209 assertEquals("normalizedNode", input, actual);
213 public void testLeafSetEntryNodeNotPrunedWhenHasParent() throws IOException {
214 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.SHOE_QNAME));
215 LeafSetEntryNode<Object> child = Builders.leafSetEntryBuilder().withValue("puma").withNodeIdentifier(
216 new NodeWithValue<>(TestModel.SHOE_QNAME, "puma")).build();
217 NormalizedNode<?, ?> input = Builders.leafSetBuilder().withNodeIdentifier(
218 new NodeIdentifier(TestModel.SHOE_QNAME)).withChild(child).build();
219 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
221 NormalizedNode<?, ?> actual = pruner.normalizedNode();
222 assertEquals("normalizedNode", input, actual);
226 public void testLeafSetEntryNodePrunedWhenHasNoParentAndSchemaMissing() throws IOException {
227 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.INVALID_QNAME));
228 NormalizedNode<?, ?> input = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
229 new NodeWithValue<>(TestModel.INVALID_QNAME, "test")).build();
230 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
232 NormalizedNode<?, ?> actual = pruner.normalizedNode();
237 public void testLeafSetEntryNodePrunedWhenHasParentAndSchemaMissing() throws IOException {
238 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.INVALID_QNAME));
239 LeafSetEntryNode<Object> child = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
240 new NodeWithValue<>(TestModel.INVALID_QNAME, "test")).build();
241 NormalizedNode<?, ?> input = Builders.leafSetBuilder().withNodeIdentifier(
242 new NodeIdentifier(TestModel.INVALID_QNAME)).withChild(child).build();
243 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
245 NormalizedNode<?, ?> actual = pruner.normalizedNode();
250 public void testAnyXMLNodeNotPrunedWhenHasNoParent() throws IOException {
251 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH.node(TestModel.ANY_XML_QNAME));
252 NormalizedNode<?, ?> input = Builders.anyXmlBuilder().withNodeIdentifier(
253 new NodeIdentifier(TestModel.ANY_XML_QNAME)).withValue(mock(DOMSource.class)).build();
254 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
256 NormalizedNode<?, ?> actual = pruner.normalizedNode();
257 assertEquals("normalizedNode", input, actual);
262 public void testAnyXMLNodeNotPrunedWhenHasParent() throws IOException {
263 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
264 AnyXmlNode child = Builders.anyXmlBuilder().withNodeIdentifier(
265 new NodeIdentifier(TestModel.ANY_XML_QNAME)).withValue(mock(DOMSource.class)).build();
266 NormalizedNode<?, ?> input = Builders.containerBuilder().withNodeIdentifier(
267 new NodeIdentifier(TestModel.TEST_QNAME)).withChild(child).build();
268 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
270 NormalizedNode<?, ?> actual = pruner.normalizedNode();
271 assertEquals("normalizedNode", input, actual);
275 public void testAnyXmlNodePrunedWhenHasNoParentAndSchemaMissing() throws IOException {
276 NormalizedNodePruner pruner = prunerNoTestSchema(TestModel.TEST_PATH.node(TestModel.ANY_XML_QNAME));
277 NormalizedNode<?, ?> input = Builders.anyXmlBuilder().withNodeIdentifier(
278 new NodeIdentifier(TestModel.ANY_XML_QNAME)).withValue(mock(DOMSource.class)).build();
279 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
281 NormalizedNode<?, ?> actual = pruner.normalizedNode();
286 public void testInnerContainerNodeWithFullPathPathNotPruned() throws IOException {
287 YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
288 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
289 node(TestModel.INNER_LIST_QNAME).nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").
290 node(TestModel.INNER_CONTAINER_QNAME).build();
291 NormalizedNodePruner pruner = prunerFullSchema(path);
293 NormalizedNode<?, ?> input = ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME);
294 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
296 NormalizedNode<?, ?> actual = pruner.normalizedNode();
297 assertEquals("normalizedNode", input, actual);
301 public void testInnerContainerNodeWithFullPathPrunedWhenSchemaMissing() throws IOException {
302 YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
303 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
304 node(TestModel.INNER_LIST_QNAME).nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").
305 node(TestModel.INVALID_QNAME).build();
306 NormalizedNodePruner pruner = prunerFullSchema(path);
308 NormalizedNode<?, ?> input = ImmutableNodes.containerNode(TestModel.INVALID_QNAME);
309 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
311 NormalizedNode<?, ?> actual = pruner.normalizedNode();
316 public void testInnerContainerNodeWithParentPathPrunedWhenSchemaMissing() 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).build();
319 NormalizedNodePruner pruner = prunerFullSchema(path);
321 MapNode innerList = mapNodeBuilder(TestModel.INNER_LIST_QNAME).withChild(mapEntryBuilder(
322 TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").withChild(
323 ImmutableNodes.containerNode(TestModel.INVALID_QNAME)).build()).build();
324 NormalizedNode<?, ?> input = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
325 withChild(innerList).build();
326 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
328 NormalizedNode<?, ?> expected = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
329 withChild(mapNodeBuilder(TestModel.INNER_LIST_QNAME).withChild(mapEntryBuilder(
330 TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").build()).build()).build();
331 NormalizedNode<?, ?> actual = pruner.normalizedNode();
332 assertEquals("normalizedNode", expected, actual);
336 public void testInnerListNodeWithFullPathNotPruned() throws IOException {
337 YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
338 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
339 node(TestModel.INNER_LIST_QNAME).build();
340 NormalizedNodePruner pruner = prunerFullSchema(path);
342 MapNode input = mapNodeBuilder(TestModel.INNER_LIST_QNAME).withChild(mapEntryBuilder(
343 TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, "one").withChild(
344 ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME)).build()).build();
345 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
347 NormalizedNode<?, ?> actual = pruner.normalizedNode();
348 assertEquals("normalizedNode", input, actual);
352 public void testInnerListNodeWithFullPathPrunedWhenSchemaMissing() throws IOException {
353 YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
354 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
355 node(TestModel.INVALID_QNAME).build();
356 NormalizedNodePruner pruner = prunerFullSchema(path);
358 MapNode input = mapNodeBuilder(TestModel.INVALID_QNAME).withChild(mapEntryBuilder(
359 TestModel.INVALID_QNAME, TestModel.NAME_QNAME, "one").withChild(
360 ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME)).build()).build();
361 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
363 NormalizedNode<?, ?> actual = pruner.normalizedNode();
368 public void testInnerListNodeWithParentPathPrunedWhenSchemaMissing() throws IOException {
369 YangInstanceIdentifier path = YangInstanceIdentifier.builder().node(TestModel.TEST_QNAME).
370 node(TestModel.OUTER_LIST_QNAME).nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).build();
371 NormalizedNodePruner pruner = prunerFullSchema(path);
373 MapNode innerList = mapNodeBuilder(TestModel.INVALID_QNAME).withChild(mapEntryBuilder(
374 TestModel.INVALID_QNAME, TestModel.NAME_QNAME, "one").withChild(
375 ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME)).build()).build();
376 NormalizedNode<?, ?> input = mapEntryBuilder(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1).
377 withChild(innerList).build();
378 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
380 NormalizedNode<?, ?> expected = mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1);
381 NormalizedNode<?, ?> actual = pruner.normalizedNode();
382 assertEquals("normalizedNode", expected, actual);
385 private static NormalizedNode<?, ?> createTestContainer() {
386 byte[] bytes1 = {1,2,3};
387 LeafSetEntryNode<Object> entry1 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
388 new NodeWithValue<>(TestModel.BINARY_LEAF_LIST_QNAME, bytes1)).
389 withValue(bytes1).build();
392 LeafSetEntryNode<Object> entry2 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
393 new NodeWithValue<>(TestModel.BINARY_LEAF_LIST_QNAME, bytes2)).
394 withValue(bytes2).build();
396 LeafSetEntryNode<Object> entry3 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
397 new NodeWithValue<>(TestModel.BINARY_LEAF_LIST_QNAME, null)).withValue(null).build();
400 return TestModel.createBaseTestContainerBuilder().
401 withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(
402 new NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME)).
403 withChild(entry1).withChild(entry2).withChild(entry3).build()).
404 withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATA_QNAME, new byte[]{1, 2, 3, 4})).