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.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;
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();
51 MockitoAnnotations.initMocks(this);
54 private static NormalizedNodePruner prunerFullSchema(YangInstanceIdentifier path) {
55 return new NormalizedNodePruner(path, FULL_SCHEMA);
58 private static NormalizedNodePruner prunerNoAugSchema(YangInstanceIdentifier path) {
59 return new NormalizedNodePruner(path, NO_AUG_SCHEMA);
62 private static NormalizedNodePruner prunerNoTestSchema(YangInstanceIdentifier path) {
63 return new NormalizedNodePruner(path, NO_TEST_SCHEMA);
67 public void testNodesNotPrunedWhenSchemaPresent() throws IOException {
68 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
70 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
72 NormalizedNode<?, ?> expected = createTestContainer();
74 normalizedNodeWriter.write(expected);
76 NormalizedNode<?, ?> actual = pruner.normalizedNode();
78 assertEquals(expected, actual);
82 @Test(expected = IllegalStateException.class)
83 public void testReusePruner() throws IOException {
84 NormalizedNodePruner pruner = prunerFullSchema(TestModel.TEST_PATH);
86 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
88 NormalizedNode<?, ?> expected = createTestContainer();
90 normalizedNodeWriter.write(expected);
92 NormalizedNode<?, ?> actual = pruner.normalizedNode();
94 assertEquals(expected, actual);
96 NormalizedNodeWriter.forStreamWriter(pruner).write(expected);
102 public void testNodesPrunedWhenAugmentationSchemaMissing() throws IOException {
103 NormalizedNodePruner pruner = prunerNoAugSchema(TestModel.TEST_PATH);
105 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
107 NormalizedNode<?, ?> expected = createTestContainer();
109 normalizedNodeWriter.write(expected);
111 NormalizedNode<?, ?> actual = pruner.normalizedNode();
113 Assert.assertNotEquals(expected, actual);
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);
118 // All nodes from the augmentation module are gone from the resulting node
119 assertEquals(0, countNodes(actual, "store:aug"));
123 public void testNodesPrunedWhenTestSchemaMissing() throws IOException {
124 NormalizedNodePruner pruner = prunerNoTestSchema(TestModel.TEST_PATH);
126 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
128 NormalizedNode<?, ?> expected = createTestContainer();
130 normalizedNodeWriter.write(expected);
132 NormalizedNode<?, ?> actual = pruner.normalizedNode();
134 // Since top level schema is missing null is returned
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);
142 private static int countNodes(NormalizedNode<?,?> normalizedNode, final String namespaceFilter){
143 if(normalizedNode == null){
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();
153 }).navigate(YangInstanceIdentifier.EMPTY.toString(), normalizedNode);
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);
165 NormalizedNode<?, ?> actual = pruner.normalizedNode();
166 assertEquals("normalizedNode", input, actual);
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);
180 NormalizedNode<?, ?> actual = pruner.normalizedNode();
181 assertEquals("normalizedNode", Builders.augmentationBuilder().withNodeIdentifier(augId).build(), actual);
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);
191 NormalizedNode<?, ?> actual = pruner.normalizedNode();
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);
203 NormalizedNode<?, ?> actual = pruner.normalizedNode();
204 assertEquals("normalizedNode", input, actual);
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);
216 NormalizedNode<?, ?> actual = pruner.normalizedNode();
217 assertEquals("normalizedNode", input, actual);
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);
227 NormalizedNode<?, ?> actual = pruner.normalizedNode();
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);
240 NormalizedNode<?, ?> actual = pruner.normalizedNode();
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);
251 NormalizedNode<?, ?> actual = pruner.normalizedNode();
252 assertEquals("normalizedNode", input, actual);
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);
265 NormalizedNode<?, ?> actual = pruner.normalizedNode();
266 assertEquals("normalizedNode", input, actual);
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);
276 NormalizedNode<?, ?> actual = pruner.normalizedNode();
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);
288 NormalizedNode<?, ?> input = ImmutableNodes.containerNode(TestModel.INNER_CONTAINER_QNAME);
289 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
291 NormalizedNode<?, ?> actual = pruner.normalizedNode();
292 assertEquals("normalizedNode", input, actual);
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);
303 NormalizedNode<?, ?> input = ImmutableNodes.containerNode(TestModel.INVALID_QNAME);
304 NormalizedNodeWriter.forStreamWriter(pruner).write(input);
306 NormalizedNode<?, ?> actual = pruner.normalizedNode();
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);
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);
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);
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);
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);
342 NormalizedNode<?, ?> actual = pruner.normalizedNode();
343 assertEquals("normalizedNode", input, actual);
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);
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);
358 NormalizedNode<?, ?> actual = pruner.normalizedNode();
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);
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);
375 NormalizedNode<?, ?> expected = mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1);
376 NormalizedNode<?, ?> actual = pruner.normalizedNode();
377 assertEquals("normalizedNode", expected, actual);
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();
387 LeafSetEntryNode<Object> entry2 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
388 new NodeWithValue<>(TestModel.BINARY_LEAF_LIST_QNAME, bytes2)).
389 withValue(bytes2).build();
391 LeafSetEntryNode<Object> entry3 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
392 new NodeWithValue<>(TestModel.BINARY_LEAF_LIST_QNAME, null)).withValue(null).build();
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})).