2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.data.codec.gson;
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;
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;
36 * Each test tests whether json input is correctly transformed to normalized node structure.
38 public class JsonStreamToNormalizedNodeTest extends AbstractComplexJsonTest {
40 public void leafNodeInContainer() throws IOException, URISyntaxException {
41 final String inputJson = loadTextFile("/complexjson/leaf-node-in-container.json");
42 verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.leafNodeInContainer());
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());
53 public void leafListNodeInContainer() throws IOException, URISyntaxException {
54 final String inputJson = loadTextFile("/complexjson/leaflist-node-in-container.json");
55 verifyTransformationToNormalizedNode(inputJson,
56 TestingNormalizedNodeStructuresCreator.leafListNodeInContainer());
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());
67 public void choiceNodeInContainer() throws IOException, URISyntaxException {
68 final String inputJson = loadTextFile("/complexjson/choice-node-in-container.json");
69 verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.choiceNodeInContainer());
73 * Test of translating internal augmentations to normalized nodes structure.
76 * 2 nodes are added via internal augmentation A, 1 node via internal augmentation B and one node is originally
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());
87 * also test using of namesakes (equal local names with different.
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());
98 * augmentation of choice - adding new case.
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());
108 public void unkeyedNodeInContainer() throws IOException, URISyntaxException {
109 final String inputJson = loadTextFile("/complexjson/unkeyed-node-in-container.json");
110 verifyTransformationToNormalizedNode(inputJson,
111 TestingNormalizedNodeStructuresCreator.unkeyedNodeInContainer());
115 * Top level JSON element contains no information about module name.
118 * It should be possible to find out potential module name from available schema context.
121 public void missingModuleInfoInTopLevelElement() throws IOException, URISyntaxException {
122 final String inputJson = loadTextFile("/complexjson/missing-module-in-top-level.json");
123 verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.topLevelContainer());
127 * Exception expected.
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.
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));
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"));
147 public void emptyTypeTest() throws IOException, URISyntaxException {
148 final String inputJson = loadTextFile("/complexjson/type-empty.json");
149 verifyTransformationToNormalizedNode(inputJson, CONT1_WITH_EMPTYLEAF);
153 * Exception expected.
156 * Json input contains element which doesn't exist in YANG schema
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));
165 assertThat(ex.getMessage(), containsString("Schema node with name dummy-element was not found"));
169 * Should not fail as we set the parser to be lenient.
172 * Json input contains element which doesn't exist in YANG schema
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);
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);
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);
211 public void multipleChoiceAugmentation() throws IOException, URISyntaxException {
212 final String inputJson = loadTextFile("/complexjson/multiple-choice-augmentation-in-container.json");
214 final var result = new NormalizationResultHolder();
215 final var streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
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");
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"))
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);
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,