2 * Copyright (c) 2016 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.yangtools.yang.data.codec.xml;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
16 import java.io.IOException;
17 import java.io.InputStream;
19 import java.net.URISyntaxException;
20 import java.text.ParseException;
21 import java.util.HashMap;
23 import javax.xml.parsers.ParserConfigurationException;
24 import javax.xml.stream.XMLInputFactory;
25 import javax.xml.stream.XMLStreamException;
26 import javax.xml.stream.XMLStreamReader;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.opendaylight.yangtools.yang.common.QName;
30 import org.opendaylight.yangtools.yang.common.QNameModule;
31 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
35 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
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.stream.NormalizedNodeStreamWriter;
42 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
43 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
44 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
45 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
46 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
47 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
48 import org.xml.sax.SAXException;
50 public class XmlToNormalizedNodesTest {
52 private QNameModule bazModule;
54 private QName outerContainer;
56 private QName myContainer1;
57 private QName myKeyedList;
58 private QName myKeyLeaf;
59 private QName myLeafInList1;
60 private QName myLeafInList2;
61 private QName myLeaf1;
62 private QName myLeafList;
64 private QName myContainer2;
65 private QName innerContainer;
66 private QName myLeaf2;
67 private QName myLeaf3;
68 private QName myChoice;
69 private QName myLeafInCase2;
71 private QName myContainer3;
72 private QName myDoublyKeyedList;
73 private QName myFirstKeyLeaf;
74 private QName mySecondKeyLeaf;
75 private QName myLeafInList3;
78 public void setup() throws URISyntaxException, ParseException {
79 bazModule = QNameModule.create(new URI("baz-namespace"), SimpleDateFormatUtil.getRevisionFormat().parse
82 outerContainer = QName.create(bazModule, "outer-container");
84 myContainer1 = QName.create(bazModule, "my-container-1");
85 myKeyedList = QName.create(bazModule, "my-keyed-list");
86 myKeyLeaf = QName.create(bazModule, "my-key-leaf");
87 myLeafInList1 = QName.create(bazModule, "my-leaf-in-list-1");
88 myLeafInList2 = QName.create(bazModule, "my-leaf-in-list-2");
89 myLeaf1 = QName.create(bazModule, "my-leaf-1");
90 myLeafList = QName.create(bazModule, "my-leaf-list");
92 myContainer2 = QName.create(bazModule, "my-container-2");
93 innerContainer = QName.create(bazModule, "inner-container");
94 myLeaf2 = QName.create(bazModule, "my-leaf-2");
95 myLeaf3 = QName.create(bazModule, "my-leaf-3");
96 myChoice = QName.create(bazModule, "my-choice");
97 myLeafInCase2 = QName.create(bazModule, "my-leaf-in-case-2");
99 myContainer3 = QName.create(bazModule, "my-container-3");
100 myDoublyKeyedList = QName.create(bazModule, "my-doubly-keyed-list");
101 myFirstKeyLeaf = QName.create(bazModule, "my-first-key-leaf");
102 mySecondKeyLeaf = QName.create(bazModule, "my-second-key-leaf");
103 myLeafInList3 = QName.create(bazModule, "my-leaf-in-list-3");
107 public void testComplexXmlParsing() throws IOException, URISyntaxException, ReactorException, XMLStreamException,
108 ParserConfigurationException, SAXException {
109 SchemaContext schemaContext = YangParserTestUtils.parseYangSource("/baz.yang");
111 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/baz.xml");
113 final XMLInputFactory factory = XMLInputFactory.newInstance();
114 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
116 final NormalizedNodeResult result = new NormalizedNodeResult();
117 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
119 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
120 xmlParser.parse(reader);
125 final NormalizedNode<?, ?> transformedInput = result.getResult();
126 assertNotNull(transformedInput);
128 final NormalizedNode<?, ?> expectedNormalizedNode = buildOuterContainerNode();
129 assertNotNull(expectedNormalizedNode);
131 assertEquals(expectedNormalizedNode, transformedInput);
135 public void testSimpleXmlParsing() throws IOException, URISyntaxException, ReactorException, XMLStreamException,
136 ParserConfigurationException, SAXException {
137 SchemaContext schemaContext = YangParserTestUtils.parseYangSource("/foo.yang");
139 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/foo.xml");
141 final XMLInputFactory factory = XMLInputFactory.newInstance();
142 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
144 final NormalizedNodeResult result = new NormalizedNodeResult();
145 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
147 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
148 xmlParser.parse(reader);
150 final NormalizedNode<?, ?> transformedInput = result.getResult();
151 assertNotNull(transformedInput);
155 public void shouldFailOnDuplicateLeaf() throws ReactorException, XMLStreamException, IOException,
156 ParserConfigurationException, SAXException, URISyntaxException {
157 SchemaContext schemaContext = YangParserTestUtils.parseYangSource("/foo.yang");
159 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo.xml");
161 final XMLInputFactory factory = XMLInputFactory.newInstance();
162 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
164 final NormalizedNodeResult result = new NormalizedNodeResult();
165 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
167 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
169 xmlParser.parse(reader);
170 fail("IllegalStateException should have been thrown because of duplicate leaf.");
171 } catch (IllegalStateException ex) {
172 assertTrue(ex.getMessage().contains("Duplicate element \"decimal64-leaf\" in XML input"));
178 public void shouldFailOnDuplicateAnyXml() throws ReactorException, XMLStreamException, IOException,
179 ParserConfigurationException, SAXException, URISyntaxException {
180 SchemaContext schemaContext = YangParserTestUtils.parseYangSource("/foo.yang");
182 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo-2.xml");
184 final XMLInputFactory factory = XMLInputFactory.newInstance();
185 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
187 final NormalizedNodeResult result = new NormalizedNodeResult();
188 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
190 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
192 xmlParser.parse(reader);
193 fail("IllegalStateException should have been thrown because of duplicate anyxml");
194 } catch (IllegalStateException ex) {
195 assertTrue(ex.getMessage().contains("Duplicate element \"my-anyxml\" in XML input"));
200 public void shouldFailOnDuplicateContainer() throws ReactorException, XMLStreamException, IOException,
201 ParserConfigurationException, SAXException, URISyntaxException {
202 SchemaContext schemaContext = YangParserTestUtils.parseYangSource("/foo.yang");
204 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo-3.xml");
206 final XMLInputFactory factory = XMLInputFactory.newInstance();
207 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
209 final NormalizedNodeResult result = new NormalizedNodeResult();
210 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
212 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
214 xmlParser.parse(reader);
215 fail("IllegalStateException should have been thrown because of duplicate container");
216 } catch (IllegalStateException ex) {
217 assertTrue(ex.getMessage().contains("Duplicate element \"leaf-container\" in XML input"));
222 public void shouldFailOnUnterminatedLeafElement() throws ReactorException, XMLStreamException, IOException,
223 ParserConfigurationException, SAXException, URISyntaxException {
224 SchemaContext schemaContext = YangParserTestUtils.parseYangSource("/baz.yang");
226 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz.xml");
228 final XMLInputFactory factory = XMLInputFactory.newInstance();
229 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
231 final NormalizedNodeResult result = new NormalizedNodeResult();
232 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
234 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
236 xmlParser.parse(reader);
237 fail("XMLStreamException should have been thrown because of unterminated leaf element.");
238 } catch (XMLStreamException ex) {
239 assertTrue(ex.getMessage().contains("elementGetText() function expects text only elment but " +
240 "START_ELEMENT was encountered."));
245 public void shouldFailOnUnterminatedLeafElement2() throws ReactorException, XMLStreamException, IOException,
246 ParserConfigurationException, SAXException, URISyntaxException {
247 SchemaContext schemaContext = YangParserTestUtils.parseYangSource("/baz.yang");
249 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-2.xml");
251 final XMLInputFactory factory = XMLInputFactory.newInstance();
252 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
254 final NormalizedNodeResult result = new NormalizedNodeResult();
255 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
257 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
259 xmlParser.parse(reader);
260 fail("XMLStreamException should have been thrown because of unterminated leaf element.");
261 } catch (XMLStreamException ex) {
262 assertTrue(ex.getMessage().contains("The element type \"my-leaf-1\" must be terminated by the matching " +
263 "end-tag \"</my-leaf-1>\"."));
268 public void shouldFailOnUnterminatedContainerElement() throws ReactorException, XMLStreamException, IOException,
269 ParserConfigurationException, SAXException, URISyntaxException {
270 SchemaContext schemaContext = YangParserTestUtils.parseYangSource("/baz.yang");
272 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-4.xml");
274 final XMLInputFactory factory = XMLInputFactory.newInstance();
275 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
277 final NormalizedNodeResult result = new NormalizedNodeResult();
278 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
280 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
282 xmlParser.parse(reader);
283 fail("XMLStreamException should have been thrown because of unterminated container element.");
284 } catch (XMLStreamException ex) {
285 assertTrue(ex.getMessage().contains("The element type \"my-container-1\" must be terminated by the " +
286 "matching end-tag \"</my-container-1>\"."));
291 public void shouldFailOnUnexistingContainerElement() throws ReactorException, XMLStreamException, IOException,
292 ParserConfigurationException, SAXException, URISyntaxException {
293 SchemaContext schemaContext = YangParserTestUtils.parseYangSource("/baz.yang");
295 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-3.xml");
297 final XMLInputFactory factory = XMLInputFactory.newInstance();
298 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
300 final NormalizedNodeResult result = new NormalizedNodeResult();
301 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
303 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, schemaContext);
305 xmlParser.parse(reader);
306 fail("IllegalStateException should have been thrown because of an unexisting container element.");
307 } catch (IllegalStateException ex) {
308 assertTrue(ex.getMessage().contains("Schema for node with name my-container-1 and namespace baz-namespace" +
313 private NormalizedNode<?, ?> buildOuterContainerNode() {
315 MapNode myKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myKeyedList))
316 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
317 new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue1"))
318 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
319 .withValue("listleafvalue1").build())
320 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
321 .withValue("listleafvalue2").build()).build())
322 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
323 new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue2"))
324 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
325 .withValue("listleafvalue12").build())
326 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
327 .withValue("listleafvalue22").build()).build()).build();
329 LeafNode<?> myLeaf1Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf1))
330 .withValue("value1").build();
332 LeafSetNode<?> myLeafListNode = Builders.leafSetBuilder().withNodeIdentifier(new NodeIdentifier(myLeafList))
333 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
334 new NodeWithValue<>(myLeafList, "lflvalue1")).withValue("lflvalue1").build())
335 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
336 new NodeWithValue<>(myLeafList, "lflvalue2")).withValue("lflvalue2").build()).build();
338 ContainerNode myContainer1Node = Builders.containerBuilder().withNodeIdentifier(
339 new NodeIdentifier(myContainer1))
340 .withChild(myKeyedListNode)
341 .withChild(myLeaf1Node)
342 .withChild(myLeafListNode).build();
345 ContainerNode innerContainerNode = Builders.containerBuilder().withNodeIdentifier(
346 new NodeIdentifier(innerContainer))
347 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf2))
348 .withValue("value2").build()).build();
350 LeafNode<?> myLeaf3Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf3))
351 .withValue("value3").build();
353 ChoiceNode myChoiceNode = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(myChoice))
354 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInCase2))
355 .withValue("case2value").build()).build();
357 ContainerNode myContainer2Node = Builders.containerBuilder().withNodeIdentifier(
358 new NodeIdentifier(myContainer2))
359 .withChild(innerContainerNode)
360 .withChild(myLeaf3Node)
361 .withChild(myChoiceNode).build();
364 Map<QName, Object> keys = new HashMap<>();
365 keys.put(myFirstKeyLeaf, "listkeyvalue1");
366 keys.put(mySecondKeyLeaf, "listkeyvalue2");
368 MapNode myDoublyKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myDoublyKeyedList))
369 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
370 new NodeIdentifierWithPredicates(myDoublyKeyedList, keys))
371 .withChild(Builders.leafBuilder().withNodeIdentifier(
372 new NodeIdentifier(myLeafInList3)).withValue("listleafvalue1").build()).build())
375 ContainerNode myContainer3Node = Builders.containerBuilder().withNodeIdentifier(
376 new NodeIdentifier(myContainer3))
377 .withChild(myDoublyKeyedListNode).build();
379 ContainerNode outerContainerNode = Builders.containerBuilder().withNodeIdentifier(
380 new NodeIdentifier(outerContainer))
381 .withChild(myContainer1Node)
382 .withChild(myContainer2Node)
383 .withChild(myContainer3Node).build();
385 return outerContainerNode;