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