2d4751a31449b0ba0c2692553fbd25d3b3742981
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / test / java / org / opendaylight / controller / cluster / datastore / node / utils / stream / SerializationUtilsTest.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.stream;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12
13 import com.google.common.collect.ImmutableSet;
14 import java.io.ByteArrayInputStream;
15 import java.io.ByteArrayOutputStream;
16 import java.io.DataInputStream;
17 import java.io.DataOutput;
18 import java.io.DataOutputStream;
19 import java.io.IOException;
20 import java.nio.charset.Charset;
21 import java.util.Arrays;
22 import java.util.Set;
23 import java.util.concurrent.atomic.AtomicBoolean;
24 import java.util.stream.Collectors;
25 import javax.xml.transform.dom.DOMSource;
26 import org.custommonkey.xmlunit.Diff;
27 import org.custommonkey.xmlunit.XMLUnit;
28 import org.junit.Test;
29 import org.opendaylight.yangtools.util.xml.UntrustedXML;
30 import org.opendaylight.yangtools.yang.common.QName;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.DOMSourceAnyxmlNode;
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.LeafSetNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
43 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
44 import org.opendaylight.yangtools.yang.data.api.schema.UserMapNode;
45 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
46 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
47 import org.w3c.dom.Document;
48
49 public class SerializationUtilsTest {
50
51     private static final QName CONTAINER_Q_NAME = QName.create("ns-1", "2017-03-17", "container1");
52
53     @Test
54     public void testSerializeDeserializeNodes() throws IOException {
55         final NormalizedNode normalizedNode = createNormalizedNode();
56         final byte[] bytes = serializeNormalizedNode(normalizedNode);
57         assertEquals(10564, bytes.length);
58         assertEquals(normalizedNode, deserializeNormalizedNode(bytes));
59     }
60
61     @Test
62     public void testSerializeDeserializeAnyXmlNode() throws Exception {
63         final ByteArrayInputStream is =
64                 new ByteArrayInputStream("<xml><data/></xml>".getBytes(Charset.defaultCharset()));
65         final Document parse = UntrustedXML.newDocumentBuilder().parse(is);
66         final DOMSourceAnyxmlNode anyXmlNode = Builders.anyXmlBuilder()
67                   .withNodeIdentifier(id("anyXmlNode"))
68                 .withValue(new DOMSource(parse))
69                 .build();
70         final byte[] bytes = serializeNormalizedNode(anyXmlNode);
71         assertEquals(113, bytes.length);
72         final NormalizedNode deserialized = deserializeNormalizedNode(bytes);
73         final DOMSource value = (DOMSource) deserialized.body();
74         final Diff diff = XMLUnit.compareXML((Document) anyXmlNode.body().getNode(),
75                 value.getNode().getOwnerDocument());
76         assertTrue(diff.toString(), diff.similar());
77     }
78
79     @Test
80     public void testSerializeDeserializePath() throws IOException {
81         final ByteArrayOutputStream bos = new ByteArrayOutputStream();
82         final DataOutput out = new DataOutputStream(bos);
83         final YangInstanceIdentifier path = YangInstanceIdentifier.builder()
84                 .node(id("container1"))
85                 .node(autmentationId("list1", "list2"))
86                 .node(listId("list1", "keyName1", "keyValue1"))
87                 .node(leafSetId("leafSer1", "leafSetValue1"))
88                 .build();
89         SerializationUtils.writePath(out, path);
90
91         final byte[] bytes = bos.toByteArray();
92         assertEquals(119, bytes.length);
93
94         final YangInstanceIdentifier deserialized =
95                 SerializationUtils.readPath(new DataInputStream(new ByteArrayInputStream(bytes)));
96         assertEquals(path, deserialized);
97     }
98
99     @Test
100     public void testSerializeDeserializePathAndNode() throws IOException {
101         final ByteArrayOutputStream bos = new ByteArrayOutputStream();
102         final DataOutput out = new DataOutputStream(bos);
103         final NormalizedNode node = createNormalizedNode();
104         final YangInstanceIdentifier path = YangInstanceIdentifier.create(id("container1"));
105         SerializationUtils.writeNodeAndPath(out, path, node);
106
107         final byte[] bytes = bos.toByteArray();
108         assertEquals(10566, bytes.length);
109
110         final DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
111         final AtomicBoolean applierCalled = new AtomicBoolean(false);
112         SerializationUtils.readNodeAndPath(in, applierCalled, (instance, deserializedPath, deserializedNode) -> {
113             assertEquals(path, deserializedPath);
114             assertEquals(node, deserializedNode);
115             applierCalled.set(true);
116         });
117         assertTrue(applierCalled.get());
118     }
119
120     @Test
121     public void testSerializeDeserializeAugmentNoref() throws IOException {
122         final YangInstanceIdentifier expected = YangInstanceIdentifier.create(
123             AugmentationIdentifier.create(ImmutableSet.of(
124                 QName.create("foo", "leaf1"),
125                 QName.create("bar", "leaf2"))));
126
127         final ByteArrayOutputStream bos = new ByteArrayOutputStream();
128         final DataOutput out = new DataOutputStream(bos);
129         SerializationUtils.writePath(out, expected);
130
131         final byte[] bytes = bos.toByteArray();
132         assertEquals(37, bytes.length);
133
134         final DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
135         final YangInstanceIdentifier read = SerializationUtils.readPath(in);
136         assertEquals(expected, read);
137     }
138
139     private static NormalizedNode deserializeNormalizedNode(final byte[] bytes) throws IOException {
140         return SerializationUtils.readNormalizedNode(new DataInputStream(new ByteArrayInputStream(bytes)))
141             .orElseThrow();
142     }
143
144     private static byte[] serializeNormalizedNode(final NormalizedNode node) throws IOException {
145         ByteArrayOutputStream bos = new ByteArrayOutputStream();
146         SerializationUtils.writeNormalizedNode(new DataOutputStream(bos), node);
147         return bos.toByteArray();
148     }
149
150     private static NormalizedNode createNormalizedNode() {
151         final LeafSetNode<Object> leafSetNode = Builders.leafSetBuilder()
152                 .withNodeIdentifier(id("leafSetNode"))
153                 .withChild(createLeafSetEntry("leafSetNode", "leafSetValue1"))
154                 .withChild(createLeafSetEntry("leafSetNode", "leafSetValue2"))
155                 .build();
156         final LeafSetNode<Object> orderedLeafSetNode = Builders.orderedLeafSetBuilder()
157                 .withNodeIdentifier(id("orderedLeafSetNode"))
158                 .withChild(createLeafSetEntry("orderedLeafSetNode", "value1"))
159                 .withChild(createLeafSetEntry("orderedLeafSetNode", "value2"))
160                 .build();
161         final LeafNode<Boolean> booleanLeaf = createLeaf("booleanLeaf", true);
162         final LeafNode<Byte> byteLeaf = createLeaf("byteLeaf", (byte) 0);
163         final LeafNode<Short> shortLeaf = createLeaf("shortLeaf", (short) 55);
164         final LeafNode<Integer> intLeaf = createLeaf("intLeaf", 11);
165         final LeafNode<Long> longLeaf = createLeaf("longLeaf", 151515L);
166         final LeafNode<String> stringLeaf = createLeaf("stringLeaf", "stringValue");
167         final LeafNode<String> longStringLeaf = createLeaf("longStringLeaf", getLongString());
168         final LeafNode<QName> qNameLeaf = createLeaf("stringLeaf", QName.create("base", "qName"));
169         final LeafNode<YangInstanceIdentifier> idLeaf = createLeaf("stringLeaf", YangInstanceIdentifier.empty());
170         final MapEntryNode entry1 = Builders.mapEntryBuilder()
171                 .withNodeIdentifier(listId("mapNode", "key", "key1"))
172                 .withChild(stringLeaf)
173                 .build();
174         final MapEntryNode entry2 = Builders.mapEntryBuilder()
175                 .withNodeIdentifier(listId("mapNode", "key", "key2"))
176                 .withChild(stringLeaf)
177                 .build();
178         final MapNode mapNode = Builders.mapBuilder()
179                 .withNodeIdentifier(id("mapNode"))
180                 .withChild(entry1)
181                 .withChild(entry2)
182                 .build();
183         final UserMapNode orderedMapNode = Builders.orderedMapBuilder()
184                 .withNodeIdentifier(id("orderedMapNode"))
185                 .withChild(entry2)
186                 .withChild(entry1)
187                 .build();
188         final UnkeyedListEntryNode unkeyedListEntry1 = Builders.unkeyedListEntryBuilder()
189                 .withNodeIdentifier(id("unkeyedList"))
190                 .withChild(stringLeaf)
191                 .build();
192         final UnkeyedListEntryNode unkeyedListEntry2 = Builders.unkeyedListEntryBuilder()
193                 .withNodeIdentifier(id("unkeyedList"))
194                 .withChild(stringLeaf)
195                 .build();
196         final UnkeyedListNode unkeyedListNode = Builders.unkeyedListBuilder()
197                 .withNodeIdentifier(id("unkeyedList"))
198                 .withChild(unkeyedListEntry1)
199                 .withChild(unkeyedListEntry2)
200                 .build();
201         final ImmutableSet<QName> childNames =
202                 ImmutableSet.of(QName.create(CONTAINER_Q_NAME, "aug1"), QName.create(CONTAINER_Q_NAME, "aug1"));
203         final AugmentationNode augmentationNode = Builders.augmentationBuilder()
204                 .withNodeIdentifier(new YangInstanceIdentifier.AugmentationIdentifier(childNames))
205                 .withChild(createLeaf("aug1", "aug1Value"))
206                 .withChild(createLeaf("aug2", "aug2Value"))
207                 .build();
208         final ChoiceNode choiceNode = Builders.choiceBuilder()
209                 .withNodeIdentifier(id("choiceNode"))
210                 .withChild(createLeaf("choiceLeaf", 12))
211                 .build();
212         return Builders.containerBuilder()
213                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CONTAINER_Q_NAME))
214                 .withChild(booleanLeaf)
215                 .withChild(byteLeaf)
216                 .withChild(shortLeaf)
217                 .withChild(intLeaf)
218                 .withChild(longLeaf)
219                 .withChild(stringLeaf)
220                 .withChild(longStringLeaf)
221                 .withChild(qNameLeaf)
222                 .withChild(idLeaf)
223                 .withChild(mapNode)
224                 .withChild(orderedMapNode)
225                 .withChild(unkeyedListNode)
226                 .withChild(leafSetNode)
227                 .withChild(orderedLeafSetNode)
228                 .withChild(augmentationNode)
229                 .withChild(choiceNode)
230                 .build();
231     }
232
233     private static <T> LeafNode<T> createLeaf(final String name, final T value) {
234         return ImmutableNodes.leafNode(id(name), value);
235     }
236
237     private static LeafSetEntryNode<Object> createLeafSetEntry(final String leafSet, final String value) {
238         return Builders.leafSetEntryBuilder()
239                 .withNodeIdentifier(leafSetId(leafSet, value))
240                 .withValue(value)
241                 .build();
242     }
243
244     private static YangInstanceIdentifier.NodeIdentifier id(final String name) {
245         return new YangInstanceIdentifier.NodeIdentifier(QName.create(CONTAINER_Q_NAME, name));
246     }
247
248     private static YangInstanceIdentifier.NodeIdentifierWithPredicates listId(final String listName,
249                                                                               final String keyName,
250                                                                               final Object keyValue) {
251         return YangInstanceIdentifier.NodeIdentifierWithPredicates.of(QName.create(CONTAINER_Q_NAME, listName),
252                 QName.create(CONTAINER_Q_NAME, keyName), keyValue);
253     }
254
255     private static <T> YangInstanceIdentifier.NodeWithValue<T> leafSetId(final String node, final T value) {
256         return new YangInstanceIdentifier.NodeWithValue<>(QName.create(CONTAINER_Q_NAME, node), value);
257     }
258
259     private static YangInstanceIdentifier.AugmentationIdentifier autmentationId(final String... nodes) {
260         final Set<QName> qNames = Arrays.stream(nodes)
261                 .map(node -> QName.create(CONTAINER_Q_NAME, node))
262                 .collect(Collectors.toSet());
263         return new YangInstanceIdentifier.AugmentationIdentifier(qNames);
264     }
265
266     private static String getLongString() {
267         final StringBuilder builder = new StringBuilder(10000);
268         for (int i = 0; i < 1000; i++) {
269             builder.append("0123456789");
270         }
271         return builder.toString();
272     }
273 }