Deprecate simple DataTreeFactory.create()
[yangtools.git] / codec / yang-data-codec-gson / src / test / java / org / opendaylight / yangtools / yang / data / codec / gson / JsonStreamToNormalizedNodeTest.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.gson;
9
10 import static org.hamcrest.CoreMatchers.containsString;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.junit.jupiter.api.Assertions.assertEquals;
13 import static org.junit.jupiter.api.Assertions.assertNotNull;
14 import static org.junit.jupiter.api.Assertions.assertThrows;
15 import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadTextFile;
16
17 import com.google.gson.stream.JsonReader;
18 import java.io.StringReader;
19 import org.junit.jupiter.api.Test;
20 import org.opendaylight.yangtools.yang.common.QName;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
23 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
24 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
25 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
26 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
27
28 /**
29  * Each test tests whether json input is correctly transformed to normalized node structure.
30  */
31 class JsonStreamToNormalizedNodeTest extends AbstractComplexJsonTest {
32     @Test
33     void leafNodeInContainer() throws Exception {
34         final var inputJson = loadTextFile("/complexjson/leaf-node-in-container.json");
35         verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.leafNodeInContainer());
36     }
37
38     @Test
39     void leafNodeViaAugmentationInContainer() throws Exception {
40         final var inputJson = loadTextFile("/complexjson/leaf-node-via-augmentation-in-container.json");
41         verifyTransformationToNormalizedNode(inputJson,
42                 TestingNormalizedNodeStructuresCreator.leafNodeViaAugmentationInContainer());
43     }
44
45     @Test
46     void leafListNodeInContainer() throws Exception {
47         final var inputJson = loadTextFile("/complexjson/leaflist-node-in-container.json");
48         verifyTransformationToNormalizedNode(inputJson,
49                 TestingNormalizedNodeStructuresCreator.leafListNodeInContainer());
50     }
51
52     @Test
53     void keyedListNodeInContainer() throws Exception {
54         final var inputJson = loadTextFile("/complexjson/keyed-list-node-in-container.json");
55         verifyTransformationToNormalizedNode(inputJson,
56                 TestingNormalizedNodeStructuresCreator.keyedListNodeInContainer());
57     }
58
59     @Test
60     void choiceNodeInContainer() throws Exception {
61         final var inputJson = loadTextFile("/complexjson/choice-node-in-container.json");
62         verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.choiceNodeInContainer());
63     }
64
65     /**
66      * Test of translating internal augmentations to normalized nodes structure.
67      *
68      * <p>
69      * 2 nodes are added via internal augmentation A, 1 node via internal augmentation B and one node is originally
70      * member of case.
71      */
72     @Test
73     void caseNodeAugmentationInChoiceInContainer() throws Exception {
74         final var inputJson = loadTextFile("/complexjson/case-node-augmentation-in-choice-in-container.json");
75         verifyTransformationToNormalizedNode(inputJson,
76                 TestingNormalizedNodeStructuresCreator.caseNodeAugmentationInChoiceInContainer());
77     }
78
79     /**
80      * also test using of namesakes (equal local names with different.
81      */
82     @Test
83     void caseNodeExternalAugmentationInChoiceInContainer() throws Exception {
84         final var inputJson =
85                 loadTextFile("/complexjson/case-node-external-augmentation-in-choice-in-container.json");
86         verifyTransformationToNormalizedNode(inputJson,
87                 TestingNormalizedNodeStructuresCreator.caseNodeExternalAugmentationInChoiceInContainer());
88     }
89
90     /**
91      * augmentation of choice - adding new case.
92      */
93     @Test
94     void choiceNodeAugmentationInContainer() throws Exception {
95         final var inputJson = loadTextFile("/complexjson/choice-node-augmentation-in-container.json");
96         verifyTransformationToNormalizedNode(inputJson,
97                 TestingNormalizedNodeStructuresCreator.choiceNodeAugmentationInContainer());
98     }
99
100     @Test
101     void unkeyedNodeInContainer() throws Exception {
102         final var inputJson = loadTextFile("/complexjson/unkeyed-node-in-container.json");
103         verifyTransformationToNormalizedNode(inputJson,
104             TestingNormalizedNodeStructuresCreator.unkeyedNodeInContainer());
105     }
106
107     /**
108      * Top level JSON element contains no information about module name.
109      *
110      * <p>
111      * It should be possible to find out potential module name from available schema context.
112      */
113     @Test
114     void missingModuleInfoInTopLevelElement() throws Exception {
115         final var inputJson = loadTextFile("/complexjson/missing-module-in-top-level.json");
116         verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.topLevelContainer());
117     }
118
119     /**
120      * Exception expected.
121      *
122      * <p>
123      * It tests case when several elements with the same name and various namespaces exists and are in JSON specified
124      * without module name prefix.
125      */
126     @Test
127     void leafNamesakes() throws Exception {
128         final var inputJson = loadTextFile("/complexjson/namesakes.json");
129         final var ex = assertThrows(IllegalStateException.class,
130             // second parameter isn't necessary because error will be raised before it is used.
131             () -> verifyTransformationToNormalizedNode(inputJson, null));
132
133         final var errorMessage = ex.getMessage();
134         assertThat(errorMessage, containsString("Choose suitable module name for element lf11-namesake:"));
135         assertThat(errorMessage, containsString("complexjson-augmentation"));
136         assertThat(errorMessage, containsString("complexjson-augmentation-namesake"));
137     }
138
139     @Test
140     void emptyTypeTest() throws Exception {
141         final var inputJson = loadTextFile("/complexjson/type-empty.json");
142         verifyTransformationToNormalizedNode(inputJson, CONT1_WITH_EMPTYLEAF);
143     }
144
145     /**
146      * Exception expected.
147      *
148      * <p>
149      * Json input contains element which doesn't exist in YANG schema
150      */
151     @Test
152     void parsingNotExistingElement() throws Exception {
153         final var inputJson = loadTextFile("/complexjson/not-existing-element.json");
154         final var ex = assertThrows(IllegalStateException.class,
155             //second parameter isn't necessary because error will be raised before it is used.
156             () -> verifyTransformationToNormalizedNode(inputJson, null));
157
158         assertThat(ex.getMessage(), containsString("Schema node with name dummy-element was not found"));
159     }
160
161     /**
162      * Should not fail as we set the parser to be lenient.
163      *
164      * <p>
165      * Json input contains element which doesn't exist in YANG schema
166      */
167     @Test
168     void parsingSkipNotExistingElement() throws Exception {
169         final var inputJson = loadTextFile("/complexjson/not-existing-element.json");
170         final var result = new NormalizationResultHolder();
171         final var streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
172         final var jsonParser = JsonParserStream.createLenient(streamWriter,
173             JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(schemaContext));
174         jsonParser.parse(new JsonReader(new StringReader(inputJson)));
175         final var transformedInput = result.getResult().data();
176         assertNotNull(transformedInput);
177     }
178
179     @Test
180     void listItemWithoutArray() throws Exception {
181         final var inputJson = loadTextFile("/complexjson/keyed-list-restconf-behaviour.json");
182         final var result = new NormalizationResultHolder();
183         final var streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
184         final var jsonParser = JsonParserStream.create(streamWriter, lhotkaCodecFactory,
185             Inference.ofDataTreePath(schemaContext, CONT_1));
186         jsonParser.parse(new JsonReader(new StringReader(inputJson)));
187         final var transformedInput = result.getResult().data();
188         assertNotNull(transformedInput);
189     }
190
191     @Test
192     void listItemWithArray() throws Exception {
193         final var inputJson = loadTextFile("/complexjson/keyed-list-yang-json-behaviour.json");
194         final var result = new NormalizationResultHolder();
195         final var streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
196         final var jsonParser = JsonParserStream.create(streamWriter, lhotkaCodecFactory,
197             Inference.ofDataTreePath(schemaContext, CONT_1));
198         jsonParser.parse(new JsonReader(new StringReader(inputJson)));
199         final var transformedInput = result.getResult().data();
200         assertNotNull(transformedInput);
201     }
202
203     @Test
204     void multipleChoiceAugmentation() throws Exception {
205         final var inputJson = loadTextFile("/complexjson/multiple-choice-augmentation-in-container.json");
206
207         final var result = new NormalizationResultHolder();
208         final var streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
209
210         final var augmentChoice1QName = QName.create(CONT_1, "augment-choice1");
211         final var augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2");
212         final var containerQName = QName.create(augmentChoice1QName, "case11-choice-case-container");
213         final var leafQName = QName.create(augmentChoice1QName, "case11-choice-case-leaf");
214
215         final var cont1Normalized = ImmutableNodes.newContainerBuilder()
216             .withNodeIdentifier(new NodeIdentifier(CONT_1))
217             .withChild(ImmutableNodes.newChoiceBuilder()
218                 .withNodeIdentifier(new NodeIdentifier(augmentChoice1QName))
219                 .withChild(ImmutableNodes.newChoiceBuilder()
220                     .withNodeIdentifier(new NodeIdentifier(augmentChoice2QName))
221                     .withChild(ImmutableNodes.newContainerBuilder()
222                         .withNodeIdentifier(new NodeIdentifier(containerQName))
223                         .withChild(ImmutableNodes.leafNode(leafQName, "leaf-value"))
224                         .build())
225                     .build())
226                 .build())
227             .build();
228
229         final var jsonParser = JsonParserStream.create(streamWriter, lhotkaCodecFactory);
230         jsonParser.parse(new JsonReader(new StringReader(inputJson)));
231         final var transformedInput = result.getResult().data();
232         assertNotNull(transformedInput);
233         assertEquals(cont1Normalized, transformedInput);
234     }
235
236     private static void verifyTransformationToNormalizedNode(final String inputJson,
237             final NormalizedNode awaitedStructure) {
238         final var result = new NormalizationResultHolder();
239         final var streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
240         final var jsonParser = JsonParserStream.create(streamWriter, lhotkaCodecFactory);
241         jsonParser.parse(new JsonReader(new StringReader(inputJson)));
242         assertEquals(awaitedStructure, result.getResult().data(),
243                 "Transformation of json input to normalized node wasn't successful.");
244     }
245 }