Update DataObjectStep class hierarchy
[yangtools.git] / codec / yang-data-codec-xml / src / test / java / org / opendaylight / yangtools / yang / data / codec / xml / NormalizedNodeXmlTranslationTest.java
1 /*
2  * Copyright (c) 2016 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.yangtools.yang.data.codec.xml;
9
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertNotNull;
12
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;
36
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");
40
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");
47
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"))
57                         .build())
58                     .build())
59                 .build())
60             .build();
61     }
62
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)))
72                     .build())
73                 .build())
74             .withChild(ImmutableNodes.leafNode(getNodeIdentifier("boolean"), Boolean.FALSE))
75             .withChild(ImmutableNodes.newSystemLeafSetBuilder()
76                 .withNodeIdentifier(getNodeIdentifier("leafList"))
77                 .withChild(ImmutableNodes.leafSetEntry(getNodeIdentifier("leafList").getNodeType(), "a"))
78                 .build())
79             .build();
80     }
81
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"))
91                     .build())
92                 .build())
93             .withChild(ImmutableNodes.newChoiceBuilder()
94                 .withNodeIdentifier(getNodeIdentifier("ch3"))
95                 .withChild(ImmutableNodes.leafNode(getNodeIdentifier("c3Leaf"), "3"))
96                 .build())
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"))
105                     .build())
106                 .build())
107             .build();
108     }
109
110     private static NodeIdentifier getNodeIdentifier(final String localName) {
111         return new NodeIdentifier(QName.create(MODULE, localName));
112     }
113
114     @ParameterizedTest
115     @MethodSource("data")
116     void testTranslationRepairing(final String yangPath, final String xmlPath, final ContainerNode expectedNode)
117             throws Exception {
118         testTranslation(TestFactories.REPAIRING_OUTPUT_FACTORY, yangPath, xmlPath, expectedNode);
119     }
120
121     @ParameterizedTest
122     @MethodSource("data")
123     void testTranslation(final String yangPath, final String xmlPath, final ContainerNode expectedNode)
124             throws Exception {
125         testTranslation(TestFactories.DEFAULT_OUTPUT_FACTORY, yangPath, xmlPath, expectedNode);
126     }
127
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);
132
133         final var reader = UntrustedXML.createXMLStreamReader(resourceAsStream);
134
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);
140
141         final var built = result.getResult().data();
142         assertNotNull(built);
143
144         if (expectedNode != null) {
145             assertEquals(expectedNode, built);
146         }
147
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);
154
155         final var doc = loadDocument(xmlPath);
156
157         XMLUnit.setIgnoreWhitespace(true);
158         XMLUnit.setIgnoreComments(true);
159         XMLUnit.setIgnoreAttributeOrder(true);
160         XMLUnit.setNormalize(true);
161
162         final String expectedXml = toString(doc.getDocumentElement());
163         final String serializedXml = toString(domResult.getNode());
164
165         final Diff diff = new Diff(expectedXml, serializedXml);
166         diff.overrideDifferenceListener(new IgnoreTextAndAttributeValuesDifferenceListener());
167         diff.overrideElementQualifier(new ElementNameAndTextQualifier());
168
169         // FIXME the comparison cannot be performed, since the qualifiers supplied by XMLUnit do not work correctly in
170         // this case
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());
174
175         // XMLAssert.assertXMLEqual(diff, true);
176     }
177
178     static List<Arguments> data() {
179         return List.of(
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()));
188     }
189 }