/*
* Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.yang.data.codec.gson;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadTextFile;
import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.augmentationBuilder;
import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.choiceBuilder;
import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.containerBuilder;
import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode;
import com.google.common.collect.Sets;
import com.google.gson.stream.JsonReader;
import java.io.IOException;
import java.io.StringReader;
import java.net.URISyntaxException;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
/**
*
* Each test tests whether json input is correctly transformed to normalized node structure
*/
public class JsonStreamToNormalizedNodeTest {
private static final QName CONT_1 = QName.create("ns:complex:json", "2014-08-11", "cont1");
private static final QName EMPTY_LEAF = QName.create(CONT_1,"empty");
private static SchemaContext schemaContext;
@BeforeClass
public static void initialization() throws IOException, URISyntaxException, ReactorException {
schemaContext = YangParserTestUtils.parseYangSources("/complexjson/yang");
}
@Test
public void leafNodeInContainer() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/leaf-node-in-container.json");
verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.leafNodeInContainer());
}
@Test
public void leafNodeViaAugmentationInContainer() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/leaf-node-via-augmentation-in-container.json");
verifyTransformationToNormalizedNode(inputJson,
TestingNormalizedNodeStructuresCreator.leafNodeViaAugmentationInContainer());
}
@Test
public void leafListNodeInContainer() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/leaflist-node-in-container.json");
verifyTransformationToNormalizedNode(inputJson,
TestingNormalizedNodeStructuresCreator.leafListNodeInContainer());
}
@Test
public void keyedListNodeInContainer() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/keyed-list-node-in-container.json");
verifyTransformationToNormalizedNode(inputJson,
TestingNormalizedNodeStructuresCreator.keyedListNodeInContainer());
}
@Test
public void choiceNodeInContainer() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/choice-node-in-container.json");
verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.choiceNodeInContainer());
}
/**
* Test of translating internal augmentations to normalized nodes structure
*
* 2 nodes are added via internal augmentation A, 1 node via internal augmentation B and one node is originally
* member of case.
*
*/
@Test
public void caseNodeAugmentationInChoiceInContainer() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/case-node-augmentation-in-choice-in-container.json");
verifyTransformationToNormalizedNode(inputJson,
TestingNormalizedNodeStructuresCreator.caseNodeAugmentationInChoiceInContainer());
}
/**
* also test using of namesakes (equal local names with different
*
* @throws IOException
* @throws URISyntaxException
*/
@Test
public void caseNodeExternalAugmentationInChoiceInContainer() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/case-node-external-augmentation-in-choice-in-container.json");
verifyTransformationToNormalizedNode(inputJson,
TestingNormalizedNodeStructuresCreator.caseNodeExternalAugmentationInChoiceInContainer());
}
/**
* augmentation of choice - adding new case
*/
@Test
public void choiceNodeAugmentationInContainer() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/choice-node-augmentation-in-container.json");
verifyTransformationToNormalizedNode(inputJson,
TestingNormalizedNodeStructuresCreator.choiceNodeAugmentationInContainer());
}
@Test
public void unkeyedNodeInContainer() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/unkeyed-node-in-container.json");
verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.unkeyedNodeInContainer());
}
/**
* Top level JSON element contains no information about module name.
*
* It should be possible to find out potential module name from available schema context.
*
*/
@Test
public void missingModuleInfoInTopLevelElement() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/missing-module-in-top-level.json");
verifyTransformationToNormalizedNode(inputJson, TestingNormalizedNodeStructuresCreator.topLevelContainer());
}
/**
*
* Exception expected.
*
* It tests case when several elements with the same name and various namespaces exists and are in JSON specified
* without module name prefix.
*/
@Test
public void leafNamesakes() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/namesakes.json");
try {
//second parameter isn't necessary because error will be raised before it is used.
verifyTransformationToNormalizedNode(inputJson, null);
fail("Expected exception not raised");
} catch (final IllegalStateException e) {
final String errorMessage = e.getMessage();
assertTrue(errorMessage.contains("Choose suitable module name for element lf11-namesake:"));
assertTrue(errorMessage.contains("complexjson-augmentation"));
assertTrue(errorMessage.contains("complexjson-augmentation-namesake"));
}
}
@Test
public void emptyTypeTest() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/type-empty.json");
final ContainerNode awaitedStructure = containerBuilder()
.withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CONT_1))
.addChild(leafNode(EMPTY_LEAF, null))
.build();
verifyTransformationToNormalizedNode(inputJson, awaitedStructure);
}
/**
*
* Exception expected.
*
* Json input contains element which doesn't exist in YANG schema
*/
@Test
public void parsingNotExistingElement() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/not-existing-element.json");
try {
//second parameter isn't necessary because error will be raised before it is used.
verifyTransformationToNormalizedNode(inputJson, null);
} catch (final IllegalStateException e) {
assertTrue(e.getMessage().contains("Schema node with name dummy-element wasn't found"));
}
}
@Test
public void listItemWithoutArray() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/keyed-list-restconf-behaviour.json");
final NormalizedNodeResult result = new NormalizedNodeResult();
final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
final SchemaNode parentNode = schemaContext.getDataChildByName(CONT_1);
final JsonParserStream jsonParser = JsonParserStream.create(streamWriter, schemaContext, parentNode);
jsonParser.parse(new JsonReader(new StringReader(inputJson)));
final NormalizedNode<?, ?> transformedInput = result.getResult();
assertNotNull(transformedInput);
}
@Test
public void listItemWithArray() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/keyed-list-yang-json-behaviour.json");
final NormalizedNodeResult result = new NormalizedNodeResult();
final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
final SchemaNode parentNode = schemaContext.getDataChildByName(CONT_1);
final JsonParserStream jsonParser = JsonParserStream.create(streamWriter, schemaContext, parentNode);
jsonParser.parse(new JsonReader(new StringReader(inputJson)));
final NormalizedNode<?, ?> transformedInput = result.getResult();
assertNotNull(transformedInput);
}
@Test
public void multipleChoiceAugmentation() throws IOException, URISyntaxException {
final String inputJson = loadTextFile("/complexjson/multiple-choice-augmentation-in-container.json");
final NormalizedNodeResult result = new NormalizedNodeResult();
final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
final SchemaNode parentNode = schemaContext.getDataChildByName(CONT_1);
final QName augmentChoice1QName = QName.create(parentNode.getQName(), "augment-choice1");
final QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2");
final QName containerQName = QName.create(augmentChoice1QName, "case11-choice-case-container");
final QName leafQName = QName.create(augmentChoice1QName, "case11-choice-case-leaf");
final YangInstanceIdentifier.AugmentationIdentifier aug1Id =
new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice1QName));
final YangInstanceIdentifier.AugmentationIdentifier aug2Id =
new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice2QName));
final YangInstanceIdentifier.NodeIdentifier augmentChoice1Id =
new YangInstanceIdentifier.NodeIdentifier(augmentChoice1QName);
final YangInstanceIdentifier.NodeIdentifier augmentChoice2Id =
new YangInstanceIdentifier.NodeIdentifier(augmentChoice2QName);
final YangInstanceIdentifier.NodeIdentifier containerId =
new YangInstanceIdentifier.NodeIdentifier(containerQName);
final NormalizedNode<?, ?> cont1Normalized =
containerBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(parentNode.getQName()))
.withChild(augmentationBuilder().withNodeIdentifier(aug1Id)
.withChild(choiceBuilder().withNodeIdentifier(augmentChoice1Id)
.withChild(augmentationBuilder().withNodeIdentifier(aug2Id)
.withChild(choiceBuilder().withNodeIdentifier(augmentChoice2Id)
.withChild(containerBuilder().withNodeIdentifier(containerId)
.withChild(leafNode(leafQName, "leaf-value"))
.build())
.build())
.build())
.build())
.build()).build();
final JsonParserStream jsonParser = JsonParserStream.create(streamWriter, schemaContext);
jsonParser.parse(new JsonReader(new StringReader(inputJson)));
final NormalizedNode<?, ?> transformedInput = result.getResult();
assertNotNull(transformedInput);
assertEquals(cont1Normalized, transformedInput);
}
private static void verifyTransformationToNormalizedNode(final String inputJson,
final NormalizedNode<?, ?> awaitedStructure) {
final NormalizedNodeResult result = new NormalizedNodeResult();
final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
final JsonParserStream jsonParser = JsonParserStream.create(streamWriter, schemaContext);
jsonParser.parse(new JsonReader(new StringReader(inputJson)));
final NormalizedNode<?, ?> transformedInput = result.getResult();
assertEquals("Transformation of json input to normalized node wasn't successful.", awaitedStructure,
transformedInput);
}
}