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.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.Mock;
29 import org.mockito.MockitoAnnotations;
30 import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeNavigator;
31 import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeVisitor;
32 import org.opendaylight.controller.cluster.datastore.util.TestModel;
33 import org.opendaylight.yangtools.yang.common.QName;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
40 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
41 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
42 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
43 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
44 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
45 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
46 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
47 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
48 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
50 public class NormalizedNodePrunerTest {
52 private NormalizedNodePruner prunerFullSchema;
54 private NormalizedNodePruner prunerNoAugSchema;
57 private NormalizedNodeBuilderWrapper normalizedNodeBuilderWrapper;
60 private NormalizedNodeContainerBuilder normalizedNodeContainerBuilder;
63 private NormalizedNode<?,?> normalizedNode;
67 MockitoAnnotations.initMocks(this);
68 prunerFullSchema = new NormalizedNodePruner(TestModel.createTestContext());
69 prunerNoAugSchema = new NormalizedNodePruner(TestModel.createTestContextWithoutAugmentationSchema());
70 doReturn(normalizedNodeContainerBuilder).when(normalizedNodeBuilderWrapper).builder();
71 doReturn(TestModel.BOOLEAN_LEAF_QNAME).when(normalizedNodeBuilderWrapper).nodeType();
72 doReturn(normalizedNode).when(normalizedNodeContainerBuilder).build();
73 doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
77 public void testNodesNotPrunedWhenSchemaPresent() throws IOException {
78 NormalizedNodePruner pruner = prunerFullSchema;
80 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
82 NormalizedNode<?, ?> expected = createTestContainer();
84 normalizedNodeWriter.write(expected);
86 NormalizedNode<?, ?> actual = pruner.normalizedNode();
88 assertEquals(expected, actual);
92 @Test(expected = IllegalStateException.class)
93 public void testReusePruner() throws IOException {
94 NormalizedNodePruner pruner = prunerFullSchema;
96 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
98 NormalizedNode<?, ?> expected = createTestContainer();
100 normalizedNodeWriter.write(expected);
102 NormalizedNode<?, ?> actual = pruner.normalizedNode();
104 assertEquals(expected, actual);
106 NormalizedNodeWriter.forStreamWriter(pruner).write(expected);
112 public void testNodesPrunedWhenAugmentationSchemaNotPresent() throws IOException {
113 NormalizedNodePruner pruner = prunerNoAugSchema;
115 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
117 NormalizedNode<?, ?> expected = createTestContainer();
119 normalizedNodeWriter.write(expected);
121 NormalizedNode<?, ?> actual = pruner.normalizedNode();
123 Assert.assertNotEquals(expected, actual);
125 // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
126 assertTrue(countNodes(expected, "store:aug") > 0);
128 // All nodes from the augmentation module are gone from the resulting node
129 assertEquals(0, countNodes(actual, "store:aug"));
133 public void testNodesPrunedWhenTestSchemaNotPresent() throws IOException {
134 NormalizedNodePruner pruner = new NormalizedNodePruner(TestModel.createTestContextWithoutTestSchema());
136 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
138 NormalizedNode<?, ?> expected = createTestContainer();
140 normalizedNodeWriter.write(expected);
142 NormalizedNode<?, ?> actual = pruner.normalizedNode();
144 // Since top level schema is missing null is returned
147 // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
148 assertTrue(countNodes(expected, "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test") > 0);
153 private static int countNodes(NormalizedNode<?,?> normalizedNode, final String namespaceFilter){
154 if(normalizedNode == null){
157 final AtomicInteger count = new AtomicInteger();
158 new NormalizedNodeNavigator(new NormalizedNodeVisitor() {
161 public void visitNode(int level, String parentPath, NormalizedNode<?, ?> normalizedNode) {
162 if(!(normalizedNode.getIdentifier() instanceof YangInstanceIdentifier.AugmentationIdentifier)) {
163 if (normalizedNode.getIdentifier().getNodeType().getNamespace().toString().contains(namespaceFilter)) {
164 count.incrementAndGet();
168 }).navigate(YangInstanceIdentifier.builder().build().toString(), normalizedNode);
174 public void testLeafNodeHasNoParent() throws IOException {
175 NormalizedNode<?, ?> input = Builders.leafBuilder().withNodeIdentifier(
176 new YangInstanceIdentifier.NodeIdentifier(TestModel.DESC_QNAME)).withValue("test").build();
177 NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
179 NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
180 assertEquals("normalizedNode", input, actual);
184 public void testLeafNodeHasParent() throws IOException {
185 LeafNode<Object> child = Builders.leafBuilder().withNodeIdentifier(
186 new YangInstanceIdentifier.NodeIdentifier(TestModel.DESC_QNAME)).withValue("test").build();
187 NormalizedNode<?, ?> input = Builders.containerBuilder().withNodeIdentifier(
188 new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME)).withChild(child).build();
189 NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
191 NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
192 assertEquals("normalizedNode", input, actual);
196 public void testLeafNodeSchemaMissing() throws IOException {
197 prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
198 prunerNoAugSchema.leafNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME), mock(Object.class));
199 verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
203 public void testLeafSetEntryNodeHasNoParent() throws IOException {
204 NormalizedNode<?, ?> input = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
205 new YangInstanceIdentifier.NodeWithValue<>(TestModel.FAMILY_QNAME, "test")).build();
206 NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
208 NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
209 assertEquals("normalizedNode", input, actual);
213 public void testLeafSetEntryNodeHasParent() throws IOException {
214 LeafSetEntryNode<Object> child = Builders.leafSetEntryBuilder().withValue("test").withNodeIdentifier(
215 new YangInstanceIdentifier.NodeWithValue<>(TestModel.FAMILY_QNAME, "test")).build();
216 NormalizedNode<?, ?> input = Builders.leafSetBuilder().withNodeIdentifier(
217 new YangInstanceIdentifier.NodeIdentifier(TestModel.FAMILY_QNAME)).withChild(child).build();
218 NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
220 NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
221 assertEquals("normalizedNode", input, actual);
225 public void testLeafSetEntryNodeSchemaMissing() throws IOException {
226 doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
228 prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
229 prunerNoAugSchema.leafSetEntryNode(TestModel.AUG_CONT_QNAME, "");
231 verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
235 public void testAnyXMLNodeHasNoParent() throws IOException {
236 NormalizedNode<?, ?> input = Builders.anyXmlBuilder().withNodeIdentifier(
237 new YangInstanceIdentifier.NodeIdentifier(TestModel.CHILD_NAME_QNAME)).
238 withValue(mock(DOMSource.class)).build();
239 NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
241 NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
242 assertEquals("normalizedNode", input, actual);
246 public void testAnyXMLNodeHasParent() throws IOException {
247 AnyXmlNode child = Builders.anyXmlBuilder().withNodeIdentifier(
248 new YangInstanceIdentifier.NodeIdentifier(TestModel.CHILD_NAME_QNAME)).
249 withValue(mock(DOMSource.class)).build();
250 NormalizedNode<?, ?> input = Builders.containerBuilder().withNodeIdentifier(
251 new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME)).withChild(child).build();
252 NormalizedNodeWriter.forStreamWriter(prunerFullSchema).write(input);
254 NormalizedNode<?, ?> actual = prunerFullSchema.normalizedNode();
255 assertEquals("normalizedNode", input, actual);
259 public void testAnyXmlNodeSchemaMissing() throws IOException {
260 prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
261 prunerNoAugSchema.anyxmlNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME), mock(DOMSource.class));
263 verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
268 public void testLeafSetPushesBuilderToStack() throws IOException {
269 prunerFullSchema.startLeafSet(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
271 assertEquals(1, prunerFullSchema.stack().size());
272 assertNotNull(prunerFullSchema.stack().peek());
273 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof ListNodeBuilder);
277 public void testStartContainerNodePushesBuilderToStack() throws IOException {
278 prunerFullSchema.startContainerNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
280 assertEquals(1, prunerFullSchema.stack().size());
281 assertNotNull(prunerFullSchema.stack().peek());
282 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
286 public void testStartUnkeyedListPushesBuilderToStack() throws IOException {
287 prunerFullSchema.startUnkeyedList(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
289 assertEquals(1, prunerFullSchema.stack().size());
290 assertNotNull(prunerFullSchema.stack().peek());
291 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
295 public void testStartUnkeyedListItemPushesBuilderToStack() throws IOException {
296 prunerFullSchema.startUnkeyedListItem(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
298 assertEquals(1, prunerFullSchema.stack().size());
299 assertNotNull(prunerFullSchema.stack().peek());
300 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
304 public void testStartMapNodePushesBuilderToStack() throws IOException {
305 prunerFullSchema.startMapNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
307 assertEquals(1, prunerFullSchema.stack().size());
308 assertNotNull(prunerFullSchema.stack().peek());
309 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
313 public void testStartMapEntryNodePushesBuilderToStack() throws IOException {
314 prunerFullSchema.startMapEntryNode(
315 new YangInstanceIdentifier.NodeIdentifierWithPredicates(TestModel.BOOLEAN_LEAF_QNAME,
316 ImmutableMap.<QName, Object>of(TestModel.BOOLEAN_LEAF_QNAME, "value")), 10);
318 assertEquals(1, prunerFullSchema.stack().size());
319 assertNotNull(prunerFullSchema.stack().peek());
320 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
324 public void testStartOrderedMapNodePushesBuilderToStack() throws IOException {
325 prunerFullSchema.startOrderedMapNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
327 assertEquals(1, prunerFullSchema.stack().size());
328 assertNotNull(prunerFullSchema.stack().peek());
329 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
333 public void testStartChoiceNodePushesBuilderToStack() throws IOException {
334 prunerFullSchema.startChoiceNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
336 assertEquals(1, prunerFullSchema.stack().size());
337 assertNotNull(prunerFullSchema.stack().peek());
338 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeBuilder);
342 public void testStartAugmentationPushesBuilderToStack() throws IOException {
343 prunerFullSchema.startAugmentationNode(new YangInstanceIdentifier.AugmentationIdentifier(ImmutableSet.of(TestModel.AUG_CONT_QNAME)));
345 assertEquals(1, prunerFullSchema.stack().size());
346 assertNotNull(prunerFullSchema.stack().peek());
347 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeBuilder);
350 @Test(expected = IllegalStateException.class)
351 public void testEndNodeWhenNoBuildersOnStack() throws IOException {
352 prunerFullSchema.endNode();
356 public void testEndNodeWhenOneBuildersOnStack() throws IOException {
357 prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
358 prunerFullSchema.endNode();
359 assertEquals(normalizedNode, prunerFullSchema.normalizedNode());
363 public void testEndNodeSchemaMissing() throws IOException {
364 doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
366 prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
367 prunerNoAugSchema.endNode();
369 assertEquals(null, prunerNoAugSchema.normalizedNode());
373 public void testEndNodeWhenMoreThanOneBuilderOnStack() throws IOException {
374 // A little lazy in adding the "parent" builder
375 prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
376 prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
377 prunerFullSchema.endNode();
378 assertEquals(null, prunerFullSchema.normalizedNode());
380 verify(normalizedNodeContainerBuilder).addChild(any(NormalizedNode.class));
383 private static NormalizedNode<?, ?> createTestContainer() {
384 byte[] bytes1 = {1,2,3};
385 LeafSetEntryNode<Object> entry1 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
386 new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, bytes1)).
387 withValue(bytes1).build();
390 LeafSetEntryNode<Object> entry2 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
391 new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, bytes2)).
392 withValue(bytes2).build();
394 LeafSetEntryNode<Object> entry3 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
395 new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, null)).
396 withValue(null).build();
399 return TestModel.createBaseTestContainerBuilder().
400 withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(
401 new YangInstanceIdentifier.NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME)).
402 withChild(entry1).withChild(entry2).withChild(entry3).build()).
403 withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATA_QNAME, new byte[]{1, 2, 3, 4})).
404 withChild(Builders.orderedMapBuilder().
405 withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.ORDERED_LIST_QNAME)).
406 withChild(ImmutableNodes.mapEntry(TestModel.ORDERED_LIST_ENTRY_QNAME,
407 TestModel.ID_QNAME, 11)).build()).