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