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.Uint32;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
29 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
31 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
32 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
33 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
34 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
35 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
37 public class NormalizedNodeXmlTranslationTest extends AbstractXmlTest {
38 private static final QNameModule MODULE =
39 QNameModule.of("urn:opendaylight:params:xml:ns:yang:controller:test", "2014-03-13");
41 private static ContainerNode augmentChoiceHell2() {
42 final var container = getNodeIdentifier("container");
43 final var augmentChoice1QName = QName.create(container.getNodeType(), "augment-choice1");
44 final var augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2");
45 final var containerQName = QName.create(augmentChoice1QName, "case11-choice-case-container");
46 final var leafQName = QName.create(augmentChoice1QName, "case11-choice-case-leaf");
48 return ImmutableNodes.newContainerBuilder()
49 .withNodeIdentifier(container)
50 .withChild(ImmutableNodes.newChoiceBuilder()
51 .withNodeIdentifier(new NodeIdentifier(augmentChoice1QName))
52 .withChild(ImmutableNodes.newChoiceBuilder()
53 .withNodeIdentifier(new NodeIdentifier(augmentChoice2QName))
54 .withChild(ImmutableNodes.newContainerBuilder()
55 .withNodeIdentifier(new NodeIdentifier(containerQName))
56 .withChild(ImmutableNodes.leafNode(leafQName, "leaf-value"))
63 private static ContainerNode withAttributes() {
64 return ImmutableNodes.newContainerBuilder()
65 .withNodeIdentifier(getNodeIdentifier("container"))
66 .withChild(ImmutableNodes.newSystemMapBuilder()
67 .withNodeIdentifier(getNodeIdentifier("list"))
68 .withChild(ImmutableNodes.newMapEntryBuilder()
69 .withNodeIdentifier(NodeIdentifierWithPredicates.of(getNodeIdentifier("list").getNodeType(),
70 getNodeIdentifier("uint32InList").getNodeType(), Uint32.valueOf(3)))
71 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("uint32InList"), Uint32.valueOf(3)))
74 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("boolean"), Boolean.FALSE))
75 .withChild(ImmutableNodes.newSystemLeafSetBuilder()
76 .withNodeIdentifier(getNodeIdentifier("leafList"))
77 .withChild(ImmutableNodes.leafSetEntry(getNodeIdentifier("leafList").getNodeType(), "a"))
82 private static ContainerNode augmentChoiceHell() {
83 return ImmutableNodes.newContainerBuilder()
84 .withNodeIdentifier(getNodeIdentifier("container"))
85 .withChild(ImmutableNodes.newChoiceBuilder()
86 .withNodeIdentifier(getNodeIdentifier("ch2"))
87 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c2Leaf"), "2"))
88 .withChild(ImmutableNodes.newChoiceBuilder()
89 .withNodeIdentifier(getNodeIdentifier("c2DeepChoice"))
90 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c2DeepChoiceCase1Leaf2"), "2"))
93 .withChild(ImmutableNodes.newChoiceBuilder()
94 .withNodeIdentifier(getNodeIdentifier("ch3"))
95 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c3Leaf"), "3"))
97 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("augLeaf"), "augment"))
98 .withChild(ImmutableNodes.newChoiceBuilder()
99 .withNodeIdentifier(getNodeIdentifier("ch"))
100 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c1Leaf"), "1"))
101 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c1Leaf_AnotherAugment"), "1"))
102 .withChild(ImmutableNodes.newChoiceBuilder()
103 .withNodeIdentifier(getNodeIdentifier("deepChoice"))
104 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("deepLeafc1"), "1"))
110 private static NodeIdentifier getNodeIdentifier(final String localName) {
111 return new NodeIdentifier(QName.create(MODULE, localName));
115 @MethodSource("data")
116 void testTranslationRepairing(final String yangPath, final String xmlPath, final ContainerNode expectedNode)
118 testTranslation(TestFactories.REPAIRING_OUTPUT_FACTORY, yangPath, xmlPath, expectedNode);
122 @MethodSource("data")
123 void testTranslation(final String yangPath, final String xmlPath, final ContainerNode expectedNode)
125 testTranslation(TestFactories.DEFAULT_OUTPUT_FACTORY, yangPath, xmlPath, expectedNode);
128 private static void testTranslation(final XMLOutputFactory factory, final String yangPath, final String xmlPath,
129 final ContainerNode expectedNode) throws Exception {
130 final var schema = YangParserTestUtils.parseYangResource(yangPath);
131 final var resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream(xmlPath);
133 final var reader = UntrustedXML.createXMLStreamReader(resourceAsStream);
135 final var result = new NormalizationResultHolder();
136 final var streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
137 final var xmlParser = XmlParserStream.create(streamWriter,
138 Inference.ofDataTreePath(schema, QName.create(MODULE, "container")));
139 xmlParser.parse(reader);
141 final var built = result.getResult().data();
142 assertNotNull(built);
144 if (expectedNode != null) {
145 assertEquals(expectedNode, built);
148 final var document = UntrustedXML.newDocumentBuilder().newDocument();
149 final var domResult = new DOMResult(document);
150 final var xmlStreamWriter = factory.createXMLStreamWriter(domResult);
151 final var xmlNormalizedNodeStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlStreamWriter, schema);
152 final var normalizedNodeWriter = NormalizedNodeWriter.forStreamWriter(xmlNormalizedNodeStreamWriter);
153 normalizedNodeWriter.write(built);
155 final var doc = loadDocument(xmlPath);
157 XMLUnit.setIgnoreWhitespace(true);
158 XMLUnit.setIgnoreComments(true);
159 XMLUnit.setIgnoreAttributeOrder(true);
160 XMLUnit.setNormalize(true);
162 final String expectedXml = toString(doc.getDocumentElement());
163 final String serializedXml = toString(domResult.getNode());
165 final Diff diff = new Diff(expectedXml, serializedXml);
166 diff.overrideDifferenceListener(new IgnoreTextAndAttributeValuesDifferenceListener());
167 diff.overrideElementQualifier(new ElementNameAndTextQualifier());
169 // FIXME the comparison cannot be performed, since the qualifiers supplied by XMLUnit do not work correctly in
171 // We need to implement custom qualifier so that the element ordering does not mess the DIFF
172 // dd.overrideElementQualifier(new MultiLevelElementNameAndTextQualifier(100, true));
173 // assertTrue(dd.toString(), dd.similar());
175 // XMLAssert.assertXMLEqual(diff, true);
178 static List<Arguments> data() {
180 Arguments.of("/schema/augment_choice_hell.yang", "/schema/augment_choice_hell_ok.xml", augmentChoiceHell()),
181 Arguments.of("/schema/augment_choice_hell.yang", "/schema/augment_choice_hell_ok2.xml", null),
182 Arguments.of("/schema/augment_choice_hell.yang", "/schema/augment_choice_hell_ok3.xml",
183 augmentChoiceHell2()),
184 Arguments.of("/schema/test.yang", "/schema/simple.xml", null),
185 Arguments.of("/schema/test.yang", "/schema/simple2.xml", null),
186 // TODO check attributes
187 Arguments.of("/schema/test.yang", "/schema/simple_xml_with_attributes.xml", withAttributes()));