b1385d9d4114274d247b3738f94155466857865c
[netconf.git] / restconf / restconf-nb-bierman02 / src / test / java / org / opendaylight / controller / sal / restconf / impl / nn / to / xml / test / NnToXmlTest.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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.sal.restconf.impl.nn.to.xml.test;
9
10 import static org.hamcrest.CoreMatchers.instanceOf;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertThrows;
14 import static org.junit.Assert.assertTrue;
15
16 import com.google.common.base.Throwables;
17 import java.io.ByteArrayOutputStream;
18 import java.io.IOException;
19 import java.io.OutputStream;
20 import javax.ws.rs.core.MediaType;
21 import org.junit.BeforeClass;
22 import org.junit.Test;
23 import org.mockito.Mockito;
24 import org.opendaylight.controller.sal.rest.impl.test.providers.AbstractBodyReaderTest;
25 import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeContext;
26 import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeXmlBodyWriter;
27 import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
28 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
29 import org.opendaylight.yangtools.yang.common.QName;
30 import org.opendaylight.yangtools.yang.common.Uint32;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
32 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.builder.DataContainerNodeBuilder;
34 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
35 import org.opendaylight.yangtools.yang.data.impl.schema.SchemaAwareBuilders;
36 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
38 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
40 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
42 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
43 import org.opendaylight.yangtools.yang.model.ri.type.BaseTypes;
44 import org.opendaylight.yangtools.yang.model.ri.type.BitsTypeBuilder;
45 import org.opendaylight.yangtools.yang.model.ri.type.EnumerationTypeBuilder;
46 import org.opendaylight.yangtools.yang.model.ri.type.UnionTypeBuilder;
47 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
48
49 public class NnToXmlTest extends AbstractBodyReaderTest {
50     private static EffectiveModelContext schemaContext;
51
52     private final NormalizedNodeXmlBodyWriter xmlBodyWriter;
53
54     public NnToXmlTest() {
55         super(schemaContext, null);
56         xmlBodyWriter = new NormalizedNodeXmlBodyWriter();
57     }
58
59     @BeforeClass
60     public static void initialization() {
61         schemaContext = schemaContextLoader("/nn-to-xml/yang", schemaContext);
62     }
63
64     @Test
65     public void nnAsYangIdentityrefToXMLTest() throws Exception {
66         final NormalizedNodeContext normalizedNodeContext = prepareIdrefData(null, true);
67         nnToXml(normalizedNodeContext, "<lf11 xmlns:x=\"referenced:module\">x:iden</lf11>");
68     }
69
70     @Test
71     public void nnAsYangIdentityrefWithQNamePrefixToXMLTest() throws Exception {
72         final NormalizedNodeContext normalizedNodeContext = prepareIdrefData("prefix", true);
73         nnToXml(normalizedNodeContext, "<lf11 xmlns", "=\"referenced:module\">", ":iden</lf11>");
74     }
75
76     @Test
77     public void nnAsYangIdentityrefWithPrefixToXMLTest() throws Exception {
78         final NormalizedNodeContext normalizedNodeContext = prepareIdrefData("prefix", false);
79         nnToXml(normalizedNodeContext, "<lf11>no qname value</lf11>");
80     }
81
82     @Test
83     public void nnAsYangLeafrefWithPrefixToXMLTest() throws Exception {
84         nnToXml(prepareLeafrefData(), "<lfBoolean>true</lfBoolean>", "<lfLfref>true</lfLfref>");
85     }
86
87     /**
88      * Negative test when leaf of type leafref references to not-existing leaf.
89      * {@code VerifyException} is expected.
90      */
91     @Test
92     public void nnAsYangLeafrefWithPrefixToXMLNegativeTest() throws Exception {
93         final NormalizedNodeContext normalizedNodeContext = prepareLeafrefNegativeData();
94
95         final IOException ex = assertThrows(IOException.class, () -> nnToXml(normalizedNodeContext,
96             "<not-existing>value</not-existing>", "<lfLfrefNegative>value</lfLfrefnegative>"));
97         final Throwable rootCause = Throwables.getRootCause(ex);
98         assertThat(rootCause, instanceOf(IllegalArgumentException.class));
99         assertEquals("Data tree child (basic:module?revision=2013-12-02)not-existing not present in schema parent "
100             + "(basic:module?revision=2013-12-02)cont", rootCause.getMessage());
101     }
102
103     @Test
104     public void nnAsYangStringToXmlTest() throws Exception {
105         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
106                 TypeDefinitionAwareCodec.from(BaseTypes.stringType()).deserialize("lfStr value"), "lfStr");
107         nnToXml(normalizedNodeContext, "<lfStr>lfStr value</lfStr>");
108     }
109
110     @Test
111     public void nnAsYangInt8ToXmlTest() throws Exception {
112         final String elName = "lfInt8";
113
114         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
115                 TypeDefinitionAwareCodec.from(BaseTypes.int8Type()).deserialize("14"), elName);
116         nnToXml(normalizedNodeContext, "<" + elName + ">14</" + elName + ">");
117     }
118
119     @Test
120     public void nnAsYangInt16ToXmlTest() throws Exception {
121         final String elName = "lfInt16";
122
123         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
124                 TypeDefinitionAwareCodec.from(BaseTypes.int16Type()).deserialize("3000"), elName);
125         nnToXml(normalizedNodeContext, "<" + elName + ">3000</" + elName + ">");
126     }
127
128     @Test
129     public void nnAsYangInt32ToXmlTest() throws Exception {
130         final String elName = "lfInt32";
131
132         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
133                 TypeDefinitionAwareCodec.from(BaseTypes.int32Type()).deserialize("201234"), elName);
134         nnToXml(normalizedNodeContext, "<" + elName + ">201234</" + elName + ">");
135     }
136
137     @Test
138     public void nnAsYangInt64ToXmlTest() throws Exception {
139         final String elName = "lfInt64";
140
141         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
142                 TypeDefinitionAwareCodec.from(BaseTypes.int64Type()).deserialize("5123456789"), elName);
143         nnToXml(normalizedNodeContext, "<" + elName + ">5123456789</" + elName + ">");
144     }
145
146     @Test
147     public void nnAsYangUint8ToXmlTest() throws Exception {
148         final String elName = "lfUint8";
149
150         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
151                 TypeDefinitionAwareCodec.from(BaseTypes.uint8Type()).deserialize("200"), elName);
152         nnToXml(normalizedNodeContext, "<" + elName + ">200</" + elName + ">");
153     }
154
155     @Test
156     public void snAsYangUint16ToXmlTest() throws Exception {
157         final String elName = "lfUint16";
158
159         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
160                 TypeDefinitionAwareCodec.from(BaseTypes.uint16Type()).deserialize("4000"), elName);
161         nnToXml(normalizedNodeContext, "<" + elName + ">4000</" + elName + ">");
162     }
163
164     @Test
165     public void nnAsYangUint32ToXmlTest() throws Exception {
166         final String elName = "lfUint32";
167
168         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
169                 TypeDefinitionAwareCodec.from(BaseTypes.uint32Type()).deserialize("4123456789"), elName);
170         nnToXml(normalizedNodeContext, "<" + elName + ">4123456789</" + elName + ">");
171     }
172
173     @Test
174     public void snAsYangUint64ToXmlTest() throws Exception {
175         final String elName = "lfUint64";
176         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
177                 TypeDefinitionAwareCodec.from(BaseTypes.uint64Type()).deserialize("5123456789"), elName);
178         nnToXml(normalizedNodeContext, "<" + elName + ">5123456789</" + elName + ">");
179     }
180
181     @Test
182     public void nnAsYangBinaryToXmlTest() throws Exception {
183         final String elName = "lfBinary";
184         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
185                 TypeDefinitionAwareCodec.from(BaseTypes.binaryType())
186                         .deserialize("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"),
187                 elName);
188         nnToXml(normalizedNodeContext,
189                 "<" + elName + ">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567</" + elName + ">");
190     }
191
192     @Test
193     public void nnAsYangBitsToXmlTest() throws Exception {
194         final BitsTypeDefinition.Bit mockBit1 = Mockito.mock(BitsTypeDefinition.Bit.class);
195         Mockito.when(mockBit1.getName()).thenReturn("one");
196         Mockito.when(mockBit1.getPosition()).thenReturn(Uint32.ONE);
197         final BitsTypeDefinition.Bit mockBit2 = Mockito.mock(BitsTypeDefinition.Bit.class);
198         Mockito.when(mockBit2.getName()).thenReturn("two");
199         Mockito.when(mockBit2.getPosition()).thenReturn(Uint32.TWO);
200         final BitsTypeBuilder bitsTypeBuilder = BaseTypes.bitsTypeBuilder(QName.create("foo", "foo"));
201         bitsTypeBuilder.addBit(mockBit1);
202         bitsTypeBuilder.addBit(mockBit2);
203
204         final String elName = "lfBits";
205         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
206                 TypeDefinitionAwareCodec.from(bitsTypeBuilder.build()).deserialize("one two"), elName);
207         nnToXml(normalizedNodeContext, "<" + elName + ">one two</" + elName + ">");
208     }
209
210     @Test
211     public void nnAsYangEnumerationToXmlTest() throws Exception {
212         final EnumTypeDefinition.EnumPair mockEnum = Mockito.mock(EnumTypeDefinition.EnumPair.class);
213         Mockito.when(mockEnum.getName()).thenReturn("enum2");
214
215         final EnumerationTypeBuilder enumerationTypeBuilder = BaseTypes
216                 .enumerationTypeBuilder(QName.create("foo", "foo"));
217         enumerationTypeBuilder.addEnum(mockEnum);
218
219         final String elName = "lfEnumeration";
220         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
221                 TypeDefinitionAwareCodec.from(enumerationTypeBuilder.build()).deserialize("enum2"), elName);
222         nnToXml(normalizedNodeContext, "<" + elName + ">enum2</" + elName + ">");
223     }
224
225     @Test
226     public void nnAsYangEmptyToXmlTest() throws Exception {
227         final String elName = "lfEmpty";
228         final NormalizedNodeContext normalizedNodeContext = prepareNNC(
229                 TypeDefinitionAwareCodec.from(BaseTypes.emptyType()).deserialize(""), elName);
230         nnToXml(normalizedNodeContext, "<" + elName + "/>");
231     }
232
233     @Test
234     public void nnAsYangBooleanToXmlTest() throws Exception {
235         final String elName = "lfBoolean";
236         NormalizedNodeContext normalizedNodeContext = prepareNNC(
237                 TypeDefinitionAwareCodec.from(BaseTypes.booleanType()).deserialize("false"), elName);
238         nnToXml(normalizedNodeContext, "<" + elName + ">false</" + elName + ">");
239
240         normalizedNodeContext = prepareNNC(TypeDefinitionAwareCodec.from(BaseTypes.booleanType()).deserialize("true"),
241                 elName);
242         nnToXml(normalizedNodeContext, "<" + elName + ">true</" + elName + ">");
243     }
244
245     @Test
246     public void nnAsYangUnionToXmlTest() throws Exception {
247         final BitsTypeDefinition.Bit mockBit1 = Mockito.mock(BitsTypeDefinition.Bit.class);
248         Mockito.when(mockBit1.getName()).thenReturn("first");
249         Mockito.when(mockBit1.getPosition()).thenReturn(Uint32.ONE);
250         final BitsTypeDefinition.Bit mockBit2 = Mockito.mock(BitsTypeDefinition.Bit.class);
251         Mockito.when(mockBit2.getName()).thenReturn("second");
252         Mockito.when(mockBit2.getPosition()).thenReturn(Uint32.TWO);
253
254         final BitsTypeBuilder bitsTypeBuilder = BaseTypes.bitsTypeBuilder(QName.create("foo", "foo"));
255         bitsTypeBuilder.addBit(mockBit1);
256         bitsTypeBuilder.addBit(mockBit2);
257
258         final UnionTypeBuilder unionTypeBuilder = BaseTypes.unionTypeBuilder(QName.create("foo", "foo"));
259         unionTypeBuilder.addType(BaseTypes.int8Type());
260         unionTypeBuilder.addType(bitsTypeBuilder.build());
261         unionTypeBuilder.addType(BaseTypes.booleanType());
262         unionTypeBuilder.addType(BaseTypes.stringType());
263
264         final String elName = "lfUnion";
265
266         // test int8
267         final String int8 = "15";
268         NormalizedNodeContext normalizedNodeContext = prepareNNC(
269                 TypeDefinitionAwareCodec.from(unionTypeBuilder.build()).deserialize(int8), elName);
270         nnToXml(normalizedNodeContext, "<" + elName + ">15</" + elName + ">");
271
272         // test bits
273         final String bits = "first second";
274         normalizedNodeContext = prepareNNC(TypeDefinitionAwareCodec.from(unionTypeBuilder.build()).deserialize(bits),
275                 elName);
276         nnToXml(normalizedNodeContext, "<" + elName + ">[first, second]</" + elName + ">");
277
278         // test boolean
279         final String bool = "true";
280         normalizedNodeContext = prepareNNC(TypeDefinitionAwareCodec.from(unionTypeBuilder.build()).deserialize(bool),
281                 elName);
282         nnToXml(normalizedNodeContext, "<" + elName + ">true</" + elName + ">");
283
284         // test string
285         final String s = "Hi!";
286         normalizedNodeContext = prepareNNC(TypeDefinitionAwareCodec.from(unionTypeBuilder.build()).deserialize(s),
287                 elName);
288         nnToXml(normalizedNodeContext, "<" + elName + ">Hi!</" + elName + ">");
289     }
290
291     private static NormalizedNodeContext prepareNNC(final Object object, final String name) {
292         final QName cont = QName.create("basic:module", "2013-12-02", "cont");
293         final QName lf = QName.create("basic:module", "2013-12-02", name);
294
295         final DataSchemaNode contSchema = schemaContext.getDataChildByName(cont);
296
297         final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> contData = SchemaAwareBuilders
298                 .containerBuilder((ContainerSchemaNode) contSchema);
299
300         final var instanceLf = ControllerContext
301                 .findInstanceDataChildrenByName((DataNodeContainer) contSchema, lf.getLocalName());
302         final DataSchemaNode schemaLf = instanceLf.get(0).child;
303
304         contData.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue(object).build());
305
306         return new NormalizedNodeContext(
307             InstanceIdentifierContext.ofStack(SchemaInferenceStack.ofDataTreePath(schemaContext, cont)),
308                 contData.build());
309     }
310
311     private void nnToXml(final NormalizedNodeContext normalizedNodeContext, final String... xmlRepresentation)
312             throws Exception {
313         final OutputStream output = new ByteArrayOutputStream();
314         xmlBodyWriter.writeTo(normalizedNodeContext, null, null, null, mediaType, null, output);
315
316         for (String element : xmlRepresentation) {
317             assertTrue(output.toString().contains(element));
318         }
319     }
320
321     private static NormalizedNodeContext prepareLeafrefData() {
322         final QName cont = QName.create("basic:module", "2013-12-02", "cont");
323         final QName lfBoolean = QName.create("basic:module", "2013-12-02", "lfBoolean");
324         final QName lfLfref = QName.create("basic:module", "2013-12-02", "lfLfref");
325
326         final DataSchemaNode contSchema = schemaContext.getDataChildByName(cont);
327
328         final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> contData = SchemaAwareBuilders
329                 .containerBuilder((ContainerSchemaNode) contSchema);
330
331         var instanceLf = ControllerContext
332                 .findInstanceDataChildrenByName((DataNodeContainer) contSchema, lfBoolean.getLocalName());
333         DataSchemaNode schemaLf = instanceLf.get(0).child;
334
335         contData.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue(Boolean.TRUE).build());
336
337         instanceLf = ControllerContext.findInstanceDataChildrenByName((DataNodeContainer) contSchema,
338                 lfLfref.getLocalName());
339         schemaLf = instanceLf.get(0).child;
340
341         contData.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue("true").build());
342
343         return new NormalizedNodeContext(
344                 InstanceIdentifierContext.ofStack(SchemaInferenceStack.ofDataTreePath(schemaContext, cont)),
345                 contData.build());
346     }
347
348     private static NormalizedNodeContext prepareLeafrefNegativeData() {
349         final QName cont = QName.create("basic:module", "2013-12-02", "cont");
350         final QName lfLfref = QName.create("basic:module", "2013-12-02", "lfLfrefNegative");
351
352         final DataSchemaNode contSchema = schemaContext.getDataChildByName(cont);
353         final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> contData = SchemaAwareBuilders
354                 .containerBuilder((ContainerSchemaNode) contSchema);
355
356         final var instanceLf = ControllerContext.findInstanceDataChildrenByName((DataNodeContainer)
357                 contSchema, lfLfref.getLocalName());
358         final DataSchemaNode schemaLf = instanceLf.get(0).child;
359
360         contData.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue("value").build());
361
362         return new NormalizedNodeContext(
363             InstanceIdentifierContext.ofStack(SchemaInferenceStack.ofDataTreePath(schemaContext, cont)),
364             contData.build());
365     }
366
367     private static NormalizedNodeContext prepareIdrefData(final String prefix, final boolean valueAsQName) {
368         final QName cont = QName.create("basic:module", "2013-12-02", "cont");
369         final QName cont1 = QName.create("basic:module", "2013-12-02", "cont1");
370         final QName lf11 = QName.create("basic:module", "2013-12-02", "lf11");
371
372         final DataSchemaNode contSchema = schemaContext.getDataChildByName(cont);
373
374         final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> contData = SchemaAwareBuilders
375                 .containerBuilder((ContainerSchemaNode) contSchema);
376
377         final DataSchemaNode cont1Schema = ((ContainerSchemaNode) contSchema).getDataChildByName(cont1);
378
379         final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> cont1Data = SchemaAwareBuilders
380                 .containerBuilder((ContainerSchemaNode) cont1Schema);
381
382         Object value = null;
383         if (valueAsQName) {
384             value = QName.create("referenced:module", "2013-12-02", "iden");
385         } else {
386             value = "no qname value";
387         }
388
389         final var instanceLf = ControllerContext
390                 .findInstanceDataChildrenByName((DataNodeContainer) cont1Schema, lf11.getLocalName());
391         final DataSchemaNode schemaLf = instanceLf.get(0).child;
392
393         cont1Data.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue(value).build());
394
395         contData.withChild(cont1Data.build());
396
397         final NormalizedNodeContext testNormalizedNodeContext = new NormalizedNodeContext(
398                 InstanceIdentifierContext.ofStack(SchemaInferenceStack.ofDataTreePath(schemaContext, cont)),
399                 contData.build());
400         return testNormalizedNodeContext;
401     }
402
403     @Override
404     protected MediaType getMediaType() {
405         return null;
406     }
407 }