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