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