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
8 package org.opendaylight.yangtools.yang.data.codec.xml;
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertNotNull;
13 import java.util.List;
14 import javax.xml.stream.XMLOutputFactory;
15 import javax.xml.transform.dom.DOMResult;
16 import org.custommonkey.xmlunit.Diff;
17 import org.custommonkey.xmlunit.ElementNameAndTextQualifier;
18 import org.custommonkey.xmlunit.IgnoreTextAndAttributeValuesDifferenceListener;
19 import org.custommonkey.xmlunit.XMLUnit;
20 import org.junit.jupiter.params.ParameterizedTest;
21 import org.junit.jupiter.params.provider.Arguments;
22 import org.junit.jupiter.params.provider.MethodSource;
23 import org.opendaylight.yangtools.util.xml.UntrustedXML;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.common.QNameModule;
26 import org.opendaylight.yangtools.yang.common.Revision;
27 import org.opendaylight.yangtools.yang.common.Uint32;
28 import org.opendaylight.yangtools.yang.common.XMLNamespace;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
31 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
33 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
34 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
35 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
36 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
37 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
39 public class NormalizedNodeXmlTranslationTest extends AbstractXmlTest {
40 private static final QNameModule MODULE = QNameModule.create(
41 XMLNamespace.of("urn:opendaylight:params:xml:ns:yang:controller:test"), Revision.of("2014-03-13"));
43 private static ContainerNode augmentChoiceHell2() {
44 final var container = getNodeIdentifier("container");
45 final var augmentChoice1QName = QName.create(container.getNodeType(), "augment-choice1");
46 final var augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2");
47 final var containerQName = QName.create(augmentChoice1QName, "case11-choice-case-container");
48 final var leafQName = QName.create(augmentChoice1QName, "case11-choice-case-leaf");
50 return ImmutableNodes.newContainerBuilder()
51 .withNodeIdentifier(container)
52 .withChild(ImmutableNodes.newChoiceBuilder()
53 .withNodeIdentifier(new NodeIdentifier(augmentChoice1QName))
54 .withChild(ImmutableNodes.newChoiceBuilder()
55 .withNodeIdentifier(new NodeIdentifier(augmentChoice2QName))
56 .withChild(ImmutableNodes.newContainerBuilder()
57 .withNodeIdentifier(new NodeIdentifier(containerQName))
58 .withChild(ImmutableNodes.leafNode(leafQName, "leaf-value"))
65 private static ContainerNode withAttributes() {
66 return ImmutableNodes.newContainerBuilder()
67 .withNodeIdentifier(getNodeIdentifier("container"))
68 .withChild(ImmutableNodes.newSystemMapBuilder()
69 .withNodeIdentifier(getNodeIdentifier("list"))
70 .withChild(ImmutableNodes.newMapEntryBuilder()
71 .withNodeIdentifier(NodeIdentifierWithPredicates.of(getNodeIdentifier("list").getNodeType(),
72 getNodeIdentifier("uint32InList").getNodeType(), Uint32.valueOf(3)))
73 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("uint32InList"), Uint32.valueOf(3)))
76 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("boolean"), Boolean.FALSE))
77 .withChild(ImmutableNodes.newSystemLeafSetBuilder()
78 .withNodeIdentifier(getNodeIdentifier("leafList"))
79 .withChild(ImmutableNodes.leafSetEntry(getNodeIdentifier("leafList").getNodeType(), "a"))
84 private static ContainerNode augmentChoiceHell() {
85 return ImmutableNodes.newContainerBuilder()
86 .withNodeIdentifier(getNodeIdentifier("container"))
87 .withChild(ImmutableNodes.newChoiceBuilder()
88 .withNodeIdentifier(getNodeIdentifier("ch2"))
89 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c2Leaf"), "2"))
90 .withChild(ImmutableNodes.newChoiceBuilder()
91 .withNodeIdentifier(getNodeIdentifier("c2DeepChoice"))
92 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c2DeepChoiceCase1Leaf2"), "2"))
95 .withChild(ImmutableNodes.newChoiceBuilder()
96 .withNodeIdentifier(getNodeIdentifier("ch3"))
97 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c3Leaf"), "3"))
99 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("augLeaf"), "augment"))
100 .withChild(ImmutableNodes.newChoiceBuilder()
101 .withNodeIdentifier(getNodeIdentifier("ch"))
102 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c1Leaf"), "1"))
103 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c1Leaf_AnotherAugment"), "1"))
104 .withChild(ImmutableNodes.newChoiceBuilder()
105 .withNodeIdentifier(getNodeIdentifier("deepChoice"))
106 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("deepLeafc1"), "1"))
112 private static NodeIdentifier getNodeIdentifier(final String localName) {
113 return new NodeIdentifier(QName.create(MODULE, localName));
117 @MethodSource("data")
118 void testTranslationRepairing(final String yangPath, final String xmlPath, final ContainerNode expectedNode)
120 testTranslation(TestFactories.REPAIRING_OUTPUT_FACTORY, yangPath, xmlPath, expectedNode);
124 @MethodSource("data")
125 void testTranslation(final String yangPath, final String xmlPath, final ContainerNode expectedNode)
127 testTranslation(TestFactories.DEFAULT_OUTPUT_FACTORY, yangPath, xmlPath, expectedNode);
130 private static void testTranslation(final XMLOutputFactory factory, final String yangPath, final String xmlPath,
131 final ContainerNode expectedNode) throws Exception {
132 final var schema = YangParserTestUtils.parseYangResource(yangPath);
133 final var resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream(xmlPath);
135 final var reader = UntrustedXML.createXMLStreamReader(resourceAsStream);
137 final var result = new NormalizationResultHolder();
138 final var streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
139 final var xmlParser = XmlParserStream.create(streamWriter,
140 Inference.ofDataTreePath(schema, QName.create(MODULE, "container")));
141 xmlParser.parse(reader);
143 final var built = result.getResult().data();
144 assertNotNull(built);
146 if (expectedNode != null) {
147 assertEquals(expectedNode, built);
150 final var document = UntrustedXML.newDocumentBuilder().newDocument();
151 final var domResult = new DOMResult(document);
152 final var xmlStreamWriter = factory.createXMLStreamWriter(domResult);
153 final var xmlNormalizedNodeStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlStreamWriter, schema);
154 final var normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(xmlNormalizedNodeStreamWriter);
155 normalizedNodeWriter.write(built);
157 final var doc = loadDocument(xmlPath);
159 XMLUnit.setIgnoreWhitespace(true);
160 XMLUnit.setIgnoreComments(true);
161 XMLUnit.setIgnoreAttributeOrder(true);
162 XMLUnit.setNormalize(true);
164 final String expectedXml = toString(doc.getDocumentElement());
165 final String serializedXml = toString(domResult.getNode());
167 final Diff diff = new Diff(expectedXml, serializedXml);
168 diff.overrideDifferenceListener(new IgnoreTextAndAttributeValuesDifferenceListener());
169 diff.overrideElementQualifier(new ElementNameAndTextQualifier());
171 // FIXME the comparison cannot be performed, since the qualifiers supplied by XMLUnit do not work correctly in
173 // We need to implement custom qualifier so that the element ordering does not mess the DIFF
174 // dd.overrideElementQualifier(new MultiLevelElementNameAndTextQualifier(100, true));
175 // assertTrue(dd.toString(), dd.similar());
177 // XMLAssert.assertXMLEqual(diff, true);
180 static List<Arguments> data() {
182 Arguments.of("/schema/augment_choice_hell.yang", "/schema/augment_choice_hell_ok.xml", augmentChoiceHell()),
183 Arguments.of("/schema/augment_choice_hell.yang", "/schema/augment_choice_hell_ok2.xml", null),
184 Arguments.of("/schema/augment_choice_hell.yang", "/schema/augment_choice_hell_ok3.xml",
185 augmentChoiceHell2()),
186 Arguments.of("/schema/test.yang", "/schema/simple.xml", null),
187 Arguments.of("/schema/test.yang", "/schema/simple2.xml", null),
188 // TODO check attributes
189 Arguments.of("/schema/test.yang", "/schema/simple_xml_with_attributes.xml", withAttributes()));