2 * Copyright (c) 2014 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
8 package org.opendaylight.controller.sal.restconf.impl.nn.to.xml.test;
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;
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;
49 public class NnToXmlTest extends AbstractBodyReaderTest {
50 private static EffectiveModelContext schemaContext;
52 private final NormalizedNodeXmlBodyWriter xmlBodyWriter;
54 public NnToXmlTest() {
55 super(schemaContext, null);
56 xmlBodyWriter = new NormalizedNodeXmlBodyWriter();
60 public static void initialization() {
61 schemaContext = schemaContextLoader("/nn-to-xml/yang", schemaContext);
65 public void nnAsYangIdentityrefToXMLTest() throws Exception {
66 final NormalizedNodeContext normalizedNodeContext = prepareIdrefData(null, true);
67 nnToXml(normalizedNodeContext, "<lf11 xmlns:x=\"referenced:module\">x:iden</lf11>");
71 public void nnAsYangIdentityrefWithQNamePrefixToXMLTest() throws Exception {
72 final NormalizedNodeContext normalizedNodeContext = prepareIdrefData("prefix", true);
73 nnToXml(normalizedNodeContext, "<lf11 xmlns", "=\"referenced:module\">", ":iden</lf11>");
77 public void nnAsYangIdentityrefWithPrefixToXMLTest() throws Exception {
78 final NormalizedNodeContext normalizedNodeContext = prepareIdrefData("prefix", false);
79 nnToXml(normalizedNodeContext, "<lf11>no qname value</lf11>");
83 public void nnAsYangLeafrefWithPrefixToXMLTest() throws Exception {
84 nnToXml(prepareLeafrefData(), "<lfBoolean>true</lfBoolean>", "<lfLfref>true</lfLfref>");
88 * Negative test when leaf of type leafref references to not-existing leaf.
89 * {@code VerifyException} is expected.
92 public void nnAsYangLeafrefWithPrefixToXMLNegativeTest() throws Exception {
93 final NormalizedNodeContext normalizedNodeContext = prepareLeafrefNegativeData();
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());
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>");
111 public void nnAsYangInt8ToXmlTest() throws Exception {
112 final String elName = "lfInt8";
114 final NormalizedNodeContext normalizedNodeContext = prepareNNC(
115 TypeDefinitionAwareCodec.from(BaseTypes.int8Type()).deserialize("14"), elName);
116 nnToXml(normalizedNodeContext, "<" + elName + ">14</" + elName + ">");
120 public void nnAsYangInt16ToXmlTest() throws Exception {
121 final String elName = "lfInt16";
123 final NormalizedNodeContext normalizedNodeContext = prepareNNC(
124 TypeDefinitionAwareCodec.from(BaseTypes.int16Type()).deserialize("3000"), elName);
125 nnToXml(normalizedNodeContext, "<" + elName + ">3000</" + elName + ">");
129 public void nnAsYangInt32ToXmlTest() throws Exception {
130 final String elName = "lfInt32";
132 final NormalizedNodeContext normalizedNodeContext = prepareNNC(
133 TypeDefinitionAwareCodec.from(BaseTypes.int32Type()).deserialize("201234"), elName);
134 nnToXml(normalizedNodeContext, "<" + elName + ">201234</" + elName + ">");
138 public void nnAsYangInt64ToXmlTest() throws Exception {
139 final String elName = "lfInt64";
141 final NormalizedNodeContext normalizedNodeContext = prepareNNC(
142 TypeDefinitionAwareCodec.from(BaseTypes.int64Type()).deserialize("5123456789"), elName);
143 nnToXml(normalizedNodeContext, "<" + elName + ">5123456789</" + elName + ">");
147 public void nnAsYangUint8ToXmlTest() throws Exception {
148 final String elName = "lfUint8";
150 final NormalizedNodeContext normalizedNodeContext = prepareNNC(
151 TypeDefinitionAwareCodec.from(BaseTypes.uint8Type()).deserialize("200"), elName);
152 nnToXml(normalizedNodeContext, "<" + elName + ">200</" + elName + ">");
156 public void snAsYangUint16ToXmlTest() throws Exception {
157 final String elName = "lfUint16";
159 final NormalizedNodeContext normalizedNodeContext = prepareNNC(
160 TypeDefinitionAwareCodec.from(BaseTypes.uint16Type()).deserialize("4000"), elName);
161 nnToXml(normalizedNodeContext, "<" + elName + ">4000</" + elName + ">");
165 public void nnAsYangUint32ToXmlTest() throws Exception {
166 final String elName = "lfUint32";
168 final NormalizedNodeContext normalizedNodeContext = prepareNNC(
169 TypeDefinitionAwareCodec.from(BaseTypes.uint32Type()).deserialize("4123456789"), elName);
170 nnToXml(normalizedNodeContext, "<" + elName + ">4123456789</" + elName + ">");
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 + ">");
182 public void nnAsYangBinaryToXmlTest() throws Exception {
183 final String elName = "lfBinary";
184 final NormalizedNodeContext normalizedNodeContext = prepareNNC(
185 TypeDefinitionAwareCodec.from(BaseTypes.binaryType())
186 .deserialize("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"),
188 nnToXml(normalizedNodeContext,
189 "<" + elName + ">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567</" + elName + ">");
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);
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 + ">");
211 public void nnAsYangEnumerationToXmlTest() throws Exception {
212 final EnumTypeDefinition.EnumPair mockEnum = Mockito.mock(EnumTypeDefinition.EnumPair.class);
213 Mockito.when(mockEnum.getName()).thenReturn("enum2");
215 final EnumerationTypeBuilder enumerationTypeBuilder = BaseTypes
216 .enumerationTypeBuilder(QName.create("foo", "foo"));
217 enumerationTypeBuilder.addEnum(mockEnum);
219 final String elName = "lfEnumeration";
220 final NormalizedNodeContext normalizedNodeContext = prepareNNC(
221 TypeDefinitionAwareCodec.from(enumerationTypeBuilder.build()).deserialize("enum2"), elName);
222 nnToXml(normalizedNodeContext, "<" + elName + ">enum2</" + elName + ">");
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 + "/>");
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 + ">");
240 normalizedNodeContext = prepareNNC(TypeDefinitionAwareCodec.from(BaseTypes.booleanType()).deserialize("true"),
242 nnToXml(normalizedNodeContext, "<" + elName + ">true</" + elName + ">");
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);
254 final BitsTypeBuilder bitsTypeBuilder = BaseTypes.bitsTypeBuilder(QName.create("foo", "foo"));
255 bitsTypeBuilder.addBit(mockBit1);
256 bitsTypeBuilder.addBit(mockBit2);
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());
264 final String elName = "lfUnion";
267 final String int8 = "15";
268 NormalizedNodeContext normalizedNodeContext = prepareNNC(
269 TypeDefinitionAwareCodec.from(unionTypeBuilder.build()).deserialize(int8), elName);
270 nnToXml(normalizedNodeContext, "<" + elName + ">15</" + elName + ">");
273 final String bits = "first second";
274 normalizedNodeContext = prepareNNC(TypeDefinitionAwareCodec.from(unionTypeBuilder.build()).deserialize(bits),
276 nnToXml(normalizedNodeContext, "<" + elName + ">[first, second]</" + elName + ">");
279 final String bool = "true";
280 normalizedNodeContext = prepareNNC(TypeDefinitionAwareCodec.from(unionTypeBuilder.build()).deserialize(bool),
282 nnToXml(normalizedNodeContext, "<" + elName + ">true</" + elName + ">");
285 final String s = "Hi!";
286 normalizedNodeContext = prepareNNC(TypeDefinitionAwareCodec.from(unionTypeBuilder.build()).deserialize(s),
288 nnToXml(normalizedNodeContext, "<" + elName + ">Hi!</" + elName + ">");
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);
295 final DataSchemaNode contSchema = schemaContext.getDataChildByName(cont);
297 final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> contData = SchemaAwareBuilders
298 .containerBuilder((ContainerSchemaNode) contSchema);
300 final var instanceLf = ControllerContext
301 .findInstanceDataChildrenByName((DataNodeContainer) contSchema, lf.getLocalName());
302 final DataSchemaNode schemaLf = instanceLf.get(0).child;
304 contData.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue(object).build());
306 return new NormalizedNodeContext(
307 InstanceIdentifierContext.ofStack(SchemaInferenceStack.ofDataTreePath(schemaContext, cont)),
311 private void nnToXml(final NormalizedNodeContext normalizedNodeContext, final String... xmlRepresentation)
313 final OutputStream output = new ByteArrayOutputStream();
314 xmlBodyWriter.writeTo(normalizedNodeContext, null, null, null, mediaType, null, output);
316 for (String element : xmlRepresentation) {
317 assertTrue(output.toString().contains(element));
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");
326 final DataSchemaNode contSchema = schemaContext.getDataChildByName(cont);
328 final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> contData = SchemaAwareBuilders
329 .containerBuilder((ContainerSchemaNode) contSchema);
331 var instanceLf = ControllerContext
332 .findInstanceDataChildrenByName((DataNodeContainer) contSchema, lfBoolean.getLocalName());
333 DataSchemaNode schemaLf = instanceLf.get(0).child;
335 contData.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue(Boolean.TRUE).build());
337 instanceLf = ControllerContext.findInstanceDataChildrenByName((DataNodeContainer) contSchema,
338 lfLfref.getLocalName());
339 schemaLf = instanceLf.get(0).child;
341 contData.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue("true").build());
343 return new NormalizedNodeContext(
344 InstanceIdentifierContext.ofStack(SchemaInferenceStack.ofDataTreePath(schemaContext, cont)),
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");
352 final DataSchemaNode contSchema = schemaContext.getDataChildByName(cont);
353 final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> contData = SchemaAwareBuilders
354 .containerBuilder((ContainerSchemaNode) contSchema);
356 final var instanceLf = ControllerContext.findInstanceDataChildrenByName((DataNodeContainer)
357 contSchema, lfLfref.getLocalName());
358 final DataSchemaNode schemaLf = instanceLf.get(0).child;
360 contData.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue("value").build());
362 return new NormalizedNodeContext(
363 InstanceIdentifierContext.ofStack(SchemaInferenceStack.ofDataTreePath(schemaContext, cont)),
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");
372 final DataSchemaNode contSchema = schemaContext.getDataChildByName(cont);
374 final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> contData = SchemaAwareBuilders
375 .containerBuilder((ContainerSchemaNode) contSchema);
377 final DataSchemaNode cont1Schema = ((ContainerSchemaNode) contSchema).getDataChildByName(cont1);
379 final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> cont1Data = SchemaAwareBuilders
380 .containerBuilder((ContainerSchemaNode) cont1Schema);
384 value = QName.create("referenced:module", "2013-12-02", "iden");
386 value = "no qname value";
389 final var instanceLf = ControllerContext
390 .findInstanceDataChildrenByName((DataNodeContainer) cont1Schema, lf11.getLocalName());
391 final DataSchemaNode schemaLf = instanceLf.get(0).child;
393 cont1Data.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) schemaLf).withValue(value).build());
395 contData.withChild(cont1Data.build());
397 final NormalizedNodeContext testNormalizedNodeContext = new NormalizedNodeContext(
398 InstanceIdentifierContext.ofStack(SchemaInferenceStack.ofDataTreePath(schemaContext, cont)),
400 return testNormalizedNodeContext;
404 protected MediaType getMediaType() {