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.ArgumentCaptor;
29 import org.mockito.Mock;
30 import org.mockito.MockitoAnnotations;
31 import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeNavigator;
32 import org.opendaylight.controller.cluster.datastore.node.utils.NormalizedNodeVisitor;
33 import org.opendaylight.controller.cluster.datastore.util.TestModel;
34 import org.opendaylight.yangtools.yang.common.QName;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
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.api.CollectionNodeBuilder;
42 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
43 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
44 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
45 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
46 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
47 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
49 public class NormalizedNodePrunerTest {
51 private NormalizedNodePruner prunerFullSchema;
53 private NormalizedNodePruner prunerNoAugSchema;
56 private NormalizedNodeBuilderWrapper normalizedNodeBuilderWrapper;
59 private NormalizedNodeContainerBuilder normalizedNodeContainerBuilder;
62 private NormalizedNode<?,?> normalizedNode;
66 MockitoAnnotations.initMocks(this);
67 prunerFullSchema = new NormalizedNodePruner(TestModel.createTestContext());
68 prunerNoAugSchema = new NormalizedNodePruner(TestModel.createTestContextWithoutAugmentationSchema());
69 doReturn(normalizedNodeContainerBuilder).when(normalizedNodeBuilderWrapper).builder();
70 doReturn(TestModel.BOOLEAN_LEAF_QNAME).when(normalizedNodeBuilderWrapper).nodeType();
71 doReturn(normalizedNode).when(normalizedNodeContainerBuilder).build();
72 doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
76 public void testNodesNotPrunedWhenSchemaPresent() throws IOException {
77 NormalizedNodePruner pruner = prunerFullSchema;
79 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
81 NormalizedNode<?, ?> expected = createTestContainer();
83 normalizedNodeWriter.write(expected);
85 NormalizedNode<?, ?> actual = pruner.normalizedNode();
87 assertEquals(expected, actual);
91 @Test(expected = IllegalStateException.class)
92 public void testReusePruner() throws IOException {
93 NormalizedNodePruner pruner = prunerFullSchema;
95 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
97 NormalizedNode<?, ?> expected = createTestContainer();
99 normalizedNodeWriter.write(expected);
101 NormalizedNode<?, ?> actual = pruner.normalizedNode();
103 assertEquals(expected, actual);
105 NormalizedNodeWriter.forStreamWriter(pruner).write(expected);
111 public void testNodesPrunedWhenAugmentationSchemaNotPresent() throws IOException {
112 NormalizedNodePruner pruner = prunerNoAugSchema;
114 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
116 NormalizedNode<?, ?> expected = createTestContainer();
118 normalizedNodeWriter.write(expected);
120 NormalizedNode<?, ?> actual = pruner.normalizedNode();
122 Assert.assertNotEquals(expected, actual);
124 // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
125 assertTrue(countNodes(expected, "store:aug") > 0);
127 // All nodes from the augmentation module are gone from the resulting node
128 assertEquals(0, countNodes(actual, "store:aug"));
132 public void testNodesPrunedWhenTestSchemaNotPresent() throws IOException {
133 NormalizedNodePruner pruner = new NormalizedNodePruner(TestModel.createTestContextWithoutTestSchema());
135 NormalizedNodeWriter normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(pruner);
137 NormalizedNode<?, ?> expected = createTestContainer();
139 normalizedNodeWriter.write(expected);
141 NormalizedNode<?, ?> actual = pruner.normalizedNode();
143 // Since top level schema is missing null is returned
146 // Asserting true here instead of checking actual value because I don't want this assertion to be fragile
147 assertTrue(countNodes(expected, "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test") > 0);
152 private static int countNodes(NormalizedNode<?,?> normalizedNode, final String namespaceFilter){
153 if(normalizedNode == null){
156 final AtomicInteger count = new AtomicInteger();
157 new NormalizedNodeNavigator(new NormalizedNodeVisitor() {
160 public void visitNode(int level, String parentPath, NormalizedNode<?, ?> normalizedNode) {
161 if(!(normalizedNode.getIdentifier() instanceof YangInstanceIdentifier.AugmentationIdentifier)) {
162 if (normalizedNode.getIdentifier().getNodeType().getNamespace().toString().contains(namespaceFilter)) {
163 count.incrementAndGet();
167 }).navigate(YangInstanceIdentifier.builder().build().toString(), normalizedNode);
172 @Test(expected = IllegalStateException.class)
173 public void testLeafNodeHasNoParent() throws IOException {
174 prunerFullSchema.leafNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), mock(Object.class));
178 public void testLeafNodeHasParent() throws IOException {
179 prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
180 Object o = mock(Object.class);
181 prunerFullSchema.leafNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), o);
183 ArgumentCaptor<NormalizedNode> captor = ArgumentCaptor.forClass(NormalizedNode.class);
185 verify(normalizedNodeContainerBuilder).addChild(captor.capture());
187 NormalizedNode<?, ?> value = captor.getValue();
188 assertEquals(normalizedNodeBuilderWrapper.identifier().getNodeType(), value.getNodeType());
189 assertEquals(normalizedNodeBuilderWrapper.identifier(), value.getIdentifier());
190 assertEquals(o, value.getValue());
195 public void testLeafNodeSchemaMissing() throws IOException {
196 prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
197 prunerNoAugSchema.leafNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME), mock(Object.class));
198 verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
201 @Test(expected = IllegalStateException.class)
202 public void testLeafSetEntryNodeHasNoParent() throws IOException {
203 prunerFullSchema.leafSetEntryNode(mock(Object.class));
207 public void testLeafSetEntryNodeHasParent() throws IOException {
208 prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
209 Object o = mock(Object.class);
210 YangInstanceIdentifier.PathArgument nodeIdentifier
211 = new YangInstanceIdentifier.NodeWithValue(normalizedNodeBuilderWrapper.identifier().getNodeType(), o);
212 prunerFullSchema.leafSetEntryNode(o);
214 ArgumentCaptor<NormalizedNode> captor = ArgumentCaptor.forClass(NormalizedNode.class);
216 verify(normalizedNodeContainerBuilder).addChild(captor.capture());
218 NormalizedNode<?, ?> value = captor.getValue();
219 assertEquals(nodeIdentifier.getNodeType(), value.getNodeType());
220 assertEquals(nodeIdentifier, value.getIdentifier());
221 assertEquals(o, value.getValue());
226 public void testLeafSetEntryNodeSchemaMissing() throws IOException {
227 doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
229 prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
230 prunerNoAugSchema.leafSetEntryNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME));
232 verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
235 @Test(expected = IllegalStateException.class)
236 public void testAnyXMLNodeHasNoParent() throws IOException {
237 prunerFullSchema.anyxmlNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), mock(Object.class));
241 public void testAnyXMLNodeHasParent() throws IOException {
242 prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
243 YangInstanceIdentifier.NodeIdentifier nodeIdentifier = new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME);
244 DOMSource o = mock(DOMSource.class);
245 prunerFullSchema.anyxmlNode(nodeIdentifier, o);
247 ArgumentCaptor<NormalizedNode> captor = ArgumentCaptor.forClass(NormalizedNode.class);
249 verify(normalizedNodeContainerBuilder).addChild(captor.capture());
251 NormalizedNode<?, ?> value = captor.getValue();
252 assertEquals(nodeIdentifier.getNodeType(), value.getNodeType());
253 assertEquals(nodeIdentifier, value.getIdentifier());
254 assertEquals(o, value.getValue());
258 public void testAnyXmlNodeSchemaMissing() throws IOException {
259 prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
260 prunerNoAugSchema.anyxmlNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME), mock(DOMSource.class));
262 verify(normalizedNodeContainerBuilder, never()).addChild(any(NormalizedNode.class));
267 public void testLeafSetPushesBuilderToStack() throws IOException {
268 prunerFullSchema.startLeafSet(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
270 assertEquals(1, prunerFullSchema.stack().size());
271 assertNotNull(prunerFullSchema.stack().peek());
272 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof ListNodeBuilder);
276 public void testStartContainerNodePushesBuilderToStack() throws IOException {
277 prunerFullSchema.startContainerNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
279 assertEquals(1, prunerFullSchema.stack().size());
280 assertNotNull(prunerFullSchema.stack().peek());
281 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
285 public void testStartUnkeyedListPushesBuilderToStack() throws IOException {
286 prunerFullSchema.startUnkeyedList(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
288 assertEquals(1, prunerFullSchema.stack().size());
289 assertNotNull(prunerFullSchema.stack().peek());
290 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
294 public void testStartUnkeyedListItemPushesBuilderToStack() throws IOException {
295 prunerFullSchema.startUnkeyedListItem(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
297 assertEquals(1, prunerFullSchema.stack().size());
298 assertNotNull(prunerFullSchema.stack().peek());
299 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
303 public void testStartMapNodePushesBuilderToStack() throws IOException {
304 prunerFullSchema.startMapNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
306 assertEquals(1, prunerFullSchema.stack().size());
307 assertNotNull(prunerFullSchema.stack().peek());
308 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
312 public void testStartMapEntryNodePushesBuilderToStack() throws IOException {
313 prunerFullSchema.startMapEntryNode(
314 new YangInstanceIdentifier.NodeIdentifierWithPredicates(TestModel.BOOLEAN_LEAF_QNAME,
315 ImmutableMap.<QName, Object>of(TestModel.BOOLEAN_LEAF_QNAME, "value")), 10);
317 assertEquals(1, prunerFullSchema.stack().size());
318 assertNotNull(prunerFullSchema.stack().peek());
319 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeAttrBuilder);
323 public void testStartOrderedMapNodePushesBuilderToStack() throws IOException {
324 prunerFullSchema.startOrderedMapNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
326 assertEquals(1, prunerFullSchema.stack().size());
327 assertNotNull(prunerFullSchema.stack().peek());
328 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof CollectionNodeBuilder);
332 public void testStartChoiceNodePushesBuilderToStack() throws IOException {
333 prunerFullSchema.startChoiceNode(new YangInstanceIdentifier.NodeIdentifier(TestModel.BOOLEAN_LEAF_QNAME), 10);
335 assertEquals(1, prunerFullSchema.stack().size());
336 assertNotNull(prunerFullSchema.stack().peek());
337 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeBuilder);
341 public void testStartAugmentationPushesBuilderToStack() throws IOException {
342 prunerFullSchema.startAugmentationNode(new YangInstanceIdentifier.AugmentationIdentifier(ImmutableSet.of(TestModel.AUG_CONT_QNAME)));
344 assertEquals(1, prunerFullSchema.stack().size());
345 assertNotNull(prunerFullSchema.stack().peek());
346 assertTrue(prunerFullSchema.stack().peek().builder().toString(), prunerFullSchema.stack().peek().builder() instanceof DataContainerNodeBuilder);
349 @Test(expected = IllegalStateException.class)
350 public void testEndNodeWhenNoBuildersOnStack() throws IOException {
351 prunerFullSchema.endNode();
355 public void testEndNodeWhenOneBuildersOnStack() throws IOException {
356 prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
357 prunerFullSchema.endNode();
358 assertEquals(normalizedNode, prunerFullSchema.normalizedNode());
362 public void testEndNodeSchemaMissing() throws IOException {
363 doReturn(new YangInstanceIdentifier.NodeIdentifier(TestModel.AUG_CONT_QNAME)).when(normalizedNodeBuilderWrapper).identifier();
365 prunerNoAugSchema.stack().push(normalizedNodeBuilderWrapper);
366 prunerNoAugSchema.endNode();
368 assertEquals(null, prunerNoAugSchema.normalizedNode());
372 public void testEndNodeWhenMoreThanOneBuilderOnStack() throws IOException {
373 // A little lazy in adding the "parent" builder
374 prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
375 prunerFullSchema.stack().push(normalizedNodeBuilderWrapper);
376 prunerFullSchema.endNode();
377 assertEquals(null, prunerFullSchema.normalizedNode());
379 verify(normalizedNodeContainerBuilder).addChild(any(NormalizedNode.class));
382 private static NormalizedNode<?, ?> createTestContainer() {
383 byte[] bytes1 = {1,2,3};
384 LeafSetEntryNode<Object> entry1 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
385 new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, bytes1)).
386 withValue(bytes1).build();
389 LeafSetEntryNode<Object> entry2 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
390 new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, bytes2)).
391 withValue(bytes2).build();
393 LeafSetEntryNode<Object> entry3 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
394 new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, null)).
395 withValue(null).build();
398 return TestModel.createBaseTestContainerBuilder().
399 withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(
400 new YangInstanceIdentifier.NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME)).
401 withChild(entry1).withChild(entry2).withChild(entry3).build()).
402 withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATA_QNAME, new byte[]{1, 2, 3, 4})).
403 withChild(Builders.orderedMapBuilder().
404 withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.ORDERED_LIST_QNAME)).
405 withChild(ImmutableNodes.mapEntry(TestModel.ORDERED_LIST_ENTRY_QNAME,
406 TestModel.ID_QNAME, 11)).build()).