diff options
Diffstat (limited to 'netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest')
12 files changed, 1756 insertions, 0 deletions
diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/InstanceIdentifierTypeLeafTest.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/InstanceIdentifierTypeLeafTest.java new file mode 100644 index 0000000..3c46201 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/InstanceIdentifierTypeLeafTest.java @@ -0,0 +1,55 @@ +/* + * 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.controller.sal.rest.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.netconf.sal.restconf.impl.ControllerContext; +import org.opendaylight.restconf.common.context.InstanceIdentifierContext; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class InstanceIdentifierTypeLeafTest { + + @Test + public void stringToInstanceIdentifierTest() throws Exception { + final EffectiveModelContext schemaContext = + YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/instanceidentifier")); + ControllerContext controllerContext = TestRestconfUtils.newControllerContext(schemaContext); + final InstanceIdentifierContext instanceIdentifier = + controllerContext.toInstanceIdentifier( + "/iid-value-module:cont-iid/iid-list/%2Fiid-value-module%3Acont-iid%2Fiid-value-module%3A" + + "values-iid%5Biid-value-module:value-iid='value'%5D"); + final YangInstanceIdentifier yiD = instanceIdentifier.getInstanceIdentifier(); + assertNotNull(yiD); + final PathArgument lastPathArgument = yiD.getLastPathArgument(); + assertTrue(lastPathArgument.getNodeType().getNamespace().toString().equals("iid:value:module")); + assertTrue(lastPathArgument.getNodeType().getLocalName().equals("iid-list")); + + final NodeIdentifierWithPredicates list = (NodeIdentifierWithPredicates) lastPathArgument; + final YangInstanceIdentifier value = (YangInstanceIdentifier) list.getValue( + QName.create(lastPathArgument.getNodeType(), "iid-leaf")); + final PathArgument lastPathArgumentOfValue = value.getLastPathArgument(); + assertTrue(lastPathArgumentOfValue.getNodeType().getNamespace().toString().equals("iid:value:module")); + assertTrue(lastPathArgumentOfValue.getNodeType().getLocalName().equals("values-iid")); + + final NodeIdentifierWithPredicates valueList = (NodeIdentifierWithPredicates) lastPathArgumentOfValue; + final String valueIid = (String) valueList.getValue( + QName.create(lastPathArgumentOfValue.getNodeType(), "value-iid")); + assertEquals("value", valueIid); + } + +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/AbstractBodyReaderTest.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/AbstractBodyReaderTest.java new file mode 100644 index 0000000..5bbd161 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/AbstractBodyReaderTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Field; +import java.net.URI; +import java.util.List; +import java.util.Optional; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.UriInfo; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.mdsal.dom.api.DOMMountPoint; +import org.opendaylight.mdsal.dom.api.DOMSchemaService; +import org.opendaylight.netconf.sal.rest.api.RestconfConstants; +import org.opendaylight.netconf.sal.rest.impl.AbstractIdentifierAwareJaxRsProvider; +import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeContext; +import org.opendaylight.netconf.sal.restconf.impl.ControllerContext; +import org.opendaylight.restconf.common.patch.PatchContext; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; + +public abstract class AbstractBodyReaderTest { + private static Field uriField; + private static Field requestField; + + static { + try { + uriField = AbstractIdentifierAwareJaxRsProvider.class.getDeclaredField("uriInfo"); + uriField.setAccessible(true); + requestField = AbstractIdentifierAwareJaxRsProvider.class.getDeclaredField("request"); + requestField.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + protected final ControllerContext controllerContext; + protected final MediaType mediaType; + + protected AbstractBodyReaderTest(final EffectiveModelContext schemaContext, final DOMMountPoint mountInstance) { + mediaType = getMediaType(); + + controllerContext = TestRestconfUtils.newControllerContext(schemaContext, mountInstance); + } + + protected abstract MediaType getMediaType(); + + protected static EffectiveModelContext schemaContextLoader(final String yangPath, + final EffectiveModelContext schemaContext) { + return TestRestconfUtils.loadSchemaContext(yangPath, schemaContext); + } + + protected static <T extends AbstractIdentifierAwareJaxRsProvider> void mockBodyReader( + final String identifier, final T normalizedNodeProvider, final boolean isPost) throws Exception { + final UriInfo uriInfoMock = mock(UriInfo.class); + final MultivaluedMap<String, String> pathParm = new MultivaluedHashMap<>(1); + + if (!identifier.isEmpty()) { + pathParm.put(RestconfConstants.IDENTIFIER, List.of(identifier)); + } + + when(uriInfoMock.getPathParameters()).thenReturn(pathParm); + when(uriInfoMock.getPathParameters(false)).thenReturn(pathParm); + when(uriInfoMock.getPathParameters(true)).thenReturn(pathParm); + when(uriInfoMock.getAbsolutePath()).thenReturn(URI.create("restconf")); + uriField.set(normalizedNodeProvider, uriInfoMock); + + final Request request = mock(Request.class); + if (isPost) { + when(request.getMethod()).thenReturn("POST"); + } else { + when(request.getMethod()).thenReturn("PUT"); + } + + requestField.set(normalizedNodeProvider, request); + } + + protected static void checkMountPointNormalizedNodeContext(final NormalizedNodeContext nnContext) { + checkNormalizedNodeContext(nnContext); + assertNotNull(nnContext.getInstanceIdentifierContext().getMountPoint()); + } + + protected static void checkNormalizedNodeContext(final NormalizedNodeContext nnContext) { + assertNotNull(nnContext.getData()); + assertNotNull(nnContext.getInstanceIdentifierContext().getInstanceIdentifier()); + assertNotNull(nnContext.getInstanceIdentifierContext().getSchemaContext()); + assertNotNull(nnContext.getInstanceIdentifierContext().getSchemaNode()); + } + + protected static void checkNormalizedNodeContextRpc(final NormalizedNodeContext nnContext) { + assertNotNull(nnContext.getData()); + assertNull(nnContext.getInstanceIdentifierContext().getInstanceIdentifier()); + assertNotNull(nnContext.getInstanceIdentifierContext().getSchemaContext()); + assertNotNull(nnContext.getInstanceIdentifierContext().getSchemaNode()); + } + + protected static void checkPatchContext(final PatchContext patchContext) { + assertNotNull(patchContext.getData()); + assertNotNull(patchContext.getInstanceIdentifierContext().getInstanceIdentifier()); + assertNotNull(patchContext.getInstanceIdentifierContext().getSchemaContext()); + assertNotNull(patchContext.getInstanceIdentifierContext().getSchemaNode()); + } + + protected static void checkPatchContextMountPoint(final PatchContext patchContext) { + checkPatchContext(patchContext); + assertNotNull(patchContext.getInstanceIdentifierContext().getMountPoint()); + } + + protected static EffectiveModelContext modelContext(final DOMMountPoint mountPoint) { + return mountPoint.getService(DOMSchemaService.class) + .flatMap(svc -> Optional.ofNullable(svc.getGlobalContext())) + .orElse(null); + } + +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonBodyReader.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonBodyReader.java new file mode 100644 index 0000000..fe50c68 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonBodyReader.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.InputStream; +import java.util.Collection; +import java.util.Optional; +import java.util.Set; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader; +import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeContext; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.Revision; +import org.opendaylight.yangtools.yang.common.XMLNamespace; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class TestJsonBodyReader extends AbstractBodyReaderTest { + + private final JsonNormalizedNodeBodyReader jsonBodyReader; + private static EffectiveModelContext schemaContext; + + private static final QNameModule INSTANCE_IDENTIFIER_MODULE_QNAME = QNameModule.create( + XMLNamespace.of("instance:identifier:module"), Revision.of("2014-01-17")); + + public TestJsonBodyReader() { + super(schemaContext, null); + jsonBodyReader = new JsonNormalizedNodeBodyReader(controllerContext); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @BeforeClass + public static void initialization() + throws Exception { + final Collection<File> testFiles = TestRestconfUtils.loadFiles("/instanceidentifier/yang"); + testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc")); + schemaContext = YangParserTestUtils.parseYangFiles(testFiles); + } + + @Test + public void moduleDataTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, jsonBodyReader, false); + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsondata.json"); + final NormalizedNodeContext returnValue = jsonBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerDataPutTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final QName cont1QName = QName.create(dataSchemaNode.getQName(), "cont1"); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName); + final DataSchemaNode dataSchemaNodeOnPath = ((DataNodeContainer) dataSchemaNode).getDataChildByName(cont1QName); + final String uri = "instance-identifier-module:cont/cont1"; + mockBodyReader(uri, jsonBodyReader, false); + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/json_sub_container.json"); + final NormalizedNodeContext returnValue = jsonBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNodeOnPath, returnValue, dataII); + } + + @Test + public void moduleSubContainerDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final QName cont1QName = QName.create(dataSchemaNode.getQName(), "cont1"); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, jsonBodyReader, true); + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/json_sub_container.json"); + final NormalizedNodeContext returnValue = jsonBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerAugmentDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final Module augmentModule = schemaContext.findModules(XMLNamespace.of("augment:module")).iterator().next(); + final QName contAugmentQName = QName.create(augmentModule.getQNameModule(), "cont-augment"); + final AugmentationIdentifier augII = new AugmentationIdentifier(Set.of(contAugmentQName)); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()) + .node(augII).node(contAugmentQName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, jsonBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/json/json_augment_container.json"); + final NormalizedNodeContext returnValue = jsonBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + //FIXME: Uncomment this when JsonParserStream works correctly with case augmentation with choice + //@Test + public void moduleSubContainerChoiceAugmentDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final Module augmentModule = schemaContext.findModules(XMLNamespace.of("augment:module")).iterator().next(); + final QName augmentChoice1QName = QName.create(augmentModule.getQNameModule(), "augment-choice1"); + final QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2"); + final QName containerQName = QName.create(augmentChoice1QName, "case-choice-case-container1"); + final AugmentationIdentifier augChoice1II = new AugmentationIdentifier(Set.of(augmentChoice1QName)); + final AugmentationIdentifier augChoice2II = new AugmentationIdentifier(Set.of(augmentChoice2QName)); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()) + .node(augChoice1II).node(augmentChoice1QName).node(augChoice2II).node(augmentChoice2QName) + .node(containerQName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, jsonBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/json/json_augment_choice_container.json"); + final NormalizedNodeContext returnValue = jsonBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void rpcModuleInputTest() throws Exception { + final String uri = "invoke-rpc-module:rpc-test"; + mockBodyReader(uri, jsonBodyReader, true); + final InputStream inputStream = TestJsonBodyReader.class.getResourceAsStream("/invoke-rpc/json/rpc-input.json"); + final NormalizedNodeContext returnValue = jsonBodyReader.readFrom(null, null, null, mediaType, null, + inputStream); + checkNormalizedNodeContextRpc(returnValue); + final ContainerNode inputNode = (ContainerNode) returnValue.getData(); + final YangInstanceIdentifier yangCont = YangInstanceIdentifier.of( + QName.create(inputNode.getIdentifier().getNodeType(), "cont")); + final Optional<DataContainerChild> contDataNode = inputNode.findChildByArg(yangCont.getLastPathArgument()); + assertTrue(contDataNode.isPresent()); + assertTrue(contDataNode.get() instanceof ContainerNode); + final YangInstanceIdentifier yangleaf = YangInstanceIdentifier.of( + QName.create(inputNode.getIdentifier().getNodeType(), "lf")); + final Optional<DataContainerChild> leafDataNode = ((ContainerNode) contDataNode.get()) + .findChildByArg(yangleaf.getLastPathArgument()); + assertTrue(leafDataNode.isPresent()); + assertTrue("lf-test".equalsIgnoreCase(leafDataNode.get().body().toString())); + } + + private static void checkExpectValueNormalizeNodeContext(final DataSchemaNode dataSchemaNode, + final NormalizedNodeContext nnContext, final YangInstanceIdentifier dataNodeIdent) { + assertEquals(dataSchemaNode, nnContext.getInstanceIdentifierContext().getSchemaNode()); + assertEquals(dataNodeIdent, nnContext.getInstanceIdentifierContext().getInstanceIdentifier()); + assertNotNull(NormalizedNodes.findNode(nnContext.getData(), dataNodeIdent)); + } +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonBodyReaderMountPoint.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonBodyReaderMountPoint.java new file mode 100644 index 0000000..e8776c8 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonBodyReaderMountPoint.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import java.io.File; +import java.io.InputStream; +import java.util.Collection; +import java.util.Optional; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.mdsal.dom.api.DOMMountPoint; +import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader; +import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeContext; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.Revision; +import org.opendaylight.yangtools.yang.common.XMLNamespace; +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.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class TestJsonBodyReaderMountPoint extends AbstractBodyReaderTest { + + private final JsonNormalizedNodeBodyReader jsonBodyReader; + private static EffectiveModelContext schemaContext; + + private static final QNameModule INSTANCE_IDENTIFIER_MODULE_QNAME = QNameModule.create( + XMLNamespace.of("instance:identifier:module"), Revision.of("2014-01-17")); + + public TestJsonBodyReaderMountPoint() throws NoSuchFieldException, SecurityException { + super(schemaContext, mock(DOMMountPoint.class)); + jsonBodyReader = new JsonNormalizedNodeBodyReader(controllerContext); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @BeforeClass + public static void initialization() throws Exception { + final Collection<File> testFiles = TestRestconfUtils.loadFiles("/instanceidentifier/yang"); + testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc")); + schemaContext = YangParserTestUtils.parseYangFiles(testFiles); + } + + @Test + public void moduleDataTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final String uri = "instance-identifier-module:cont/yang-ext:mount/instance-identifier-module:cont"; + mockBodyReader(uri, jsonBodyReader, false); + final InputStream inputStream = TestJsonBodyReaderMountPoint.class + .getResourceAsStream("/instanceidentifier/json/jsondata.json"); + final NormalizedNodeContext returnValue = jsonBodyReader.readFrom(null, + null, null, mediaType, null, inputStream); + checkMountPointNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue); + } + + @Test + public void moduleSubContainerDataPutTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final String uri = "instance-identifier-module:cont/yang-ext:mount/instance-identifier-module:cont/cont1"; + mockBodyReader(uri, jsonBodyReader, false); + final InputStream inputStream = TestJsonBodyReaderMountPoint.class + .getResourceAsStream("/instanceidentifier/json/json_sub_container.json"); + final NormalizedNodeContext returnValue = jsonBodyReader.readFrom(null, + null, null, mediaType, null, inputStream); + checkMountPointNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, + QName.create(dataSchemaNode.getQName(), "cont1")); + } + + @Test + public void moduleSubContainerDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final String uri = "instance-identifier-module:cont/yang-ext:mount/instance-identifier-module:cont"; + mockBodyReader(uri, jsonBodyReader, true); + final InputStream inputStream = TestJsonBodyReaderMountPoint.class + .getResourceAsStream("/instanceidentifier/json/json_sub_container.json"); + final NormalizedNodeContext returnValue = jsonBodyReader.readFrom(null, + null, null, mediaType, null, inputStream); + checkMountPointNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue); + } + + @Test + public void rpcModuleInputTest() throws Exception { + final String uri = "instance-identifier-module:cont/yang-ext:mount/invoke-rpc-module:rpc-test"; + mockBodyReader(uri, jsonBodyReader, true); + final InputStream inputStream = TestJsonBodyReaderMountPoint.class.getResourceAsStream( + "/invoke-rpc/json/rpc-input.json"); + final NormalizedNodeContext returnValue = jsonBodyReader.readFrom(null, null, null, mediaType, null, + inputStream); + checkNormalizedNodeContextRpc(returnValue); + final ContainerNode inputNode = (ContainerNode) returnValue.getData(); + final YangInstanceIdentifier yangCont = YangInstanceIdentifier.of( + QName.create(inputNode.getIdentifier().getNodeType(), "cont")); + final Optional<DataContainerChild> contDataNode = inputNode.findChildByArg(yangCont.getLastPathArgument()); + assertTrue(contDataNode.isPresent()); + assertTrue(contDataNode.get() instanceof ContainerNode); + final YangInstanceIdentifier yangleaf = YangInstanceIdentifier.of( + QName.create(inputNode.getIdentifier().getNodeType(), "lf")); + final Optional<DataContainerChild> leafDataNode = + ((ContainerNode) contDataNode.get()).findChildByArg(yangleaf.getLastPathArgument()); + assertTrue(leafDataNode.isPresent()); + assertTrue("lf-test".equalsIgnoreCase(leafDataNode.get().body().toString())); + } + + private void checkExpectValueNormalizeNodeContext(final DataSchemaNode dataSchemaNode, + final NormalizedNodeContext nnContext) { + checkExpectValueNormalizeNodeContext(dataSchemaNode, nnContext, null); + } + + protected void checkExpectValueNormalizeNodeContext(final DataSchemaNode dataSchemaNode, + final NormalizedNodeContext nnContext, final QName qualifiedName) { + YangInstanceIdentifier dataNodeIdent = YangInstanceIdentifier.of(dataSchemaNode.getQName()); + final DOMMountPoint mountPoint = nnContext.getInstanceIdentifierContext().getMountPoint(); + final DataSchemaNode mountDataSchemaNode = modelContext(mountPoint).getDataChildByName( + dataSchemaNode.getQName()); + assertNotNull(mountDataSchemaNode); + if (qualifiedName != null && dataSchemaNode instanceof DataNodeContainer) { + final DataSchemaNode child = ((DataNodeContainer) dataSchemaNode).getDataChildByName(qualifiedName); + dataNodeIdent = YangInstanceIdentifier.builder(dataNodeIdent).node(child.getQName()).build(); + assertTrue(nnContext.getInstanceIdentifierContext().getSchemaNode().equals(child)); + } else { + assertTrue(mountDataSchemaNode.equals(dataSchemaNode)); + } + assertNotNull(NormalizedNodes.findNode(nnContext.getData(), + dataNodeIdent)); + } +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonBodyWriter.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonBodyWriter.java new file mode 100644 index 0000000..121a7d6 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonBodyWriter.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collection; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.netconf.sal.rest.impl.JsonNormalizedNodeBodyReader; +import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeContext; +import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeJsonBodyWriter; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class TestJsonBodyWriter extends AbstractBodyReaderTest { + + private final JsonNormalizedNodeBodyReader jsonBodyReader; + private final NormalizedNodeJsonBodyWriter jsonBodyWriter; + private static EffectiveModelContext schemaContext; + + public TestJsonBodyWriter() { + super(schemaContext, null); + this.jsonBodyWriter = new NormalizedNodeJsonBodyWriter(); + this.jsonBodyReader = new JsonNormalizedNodeBodyReader(controllerContext); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @BeforeClass + public static void initialization() throws Exception { + final Collection<File> testFiles = TestRestconfUtils.loadFiles("/instanceidentifier/yang"); + testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc")); + schemaContext = YangParserTestUtils.parseYangFiles(testFiles); + } + + @Test + public void rpcModuleInputTest() throws Exception { + final String uri = "invoke-rpc-module:rpc-test"; + mockBodyReader(uri, this.jsonBodyReader, true); + final InputStream inputStream = TestJsonBodyWriter.class + .getResourceAsStream("/invoke-rpc/json/rpc-output.json"); + final NormalizedNodeContext returnValue = this.jsonBodyReader.readFrom(null, + null, null, this.mediaType, null, inputStream); + final OutputStream output = new ByteArrayOutputStream(); + this.jsonBodyWriter.writeTo(returnValue, null, null, null, this.mediaType, null, + output); + assertTrue(output.toString().contains("lf-test")); + } +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPatchBodyReader.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPatchBodyReader.java new file mode 100644 index 0000000..f2a6c41 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPatchBodyReader.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import java.io.InputStream; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.netconf.sal.rest.impl.JsonToPatchBodyReader; +import org.opendaylight.restconf.common.errors.RestconfDocumentedException; +import org.opendaylight.restconf.common.patch.PatchContext; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; + +public class TestJsonPatchBodyReader extends AbstractBodyReaderTest { + private static EffectiveModelContext schemaContext; + + private final JsonToPatchBodyReader jsonToPatchBodyReader; + + public TestJsonPatchBodyReader() { + super(schemaContext, null); + jsonToPatchBodyReader = new JsonToPatchBodyReader(controllerContext); + } + + @BeforeClass + public static void initialization() { + schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(APPLICATION_JSON, null); + } + + @Test + public void modulePatchDataTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class.getResourceAsStream( + "/instanceidentifier/json/jsonPATCHdata.json"); + + final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } + + /** + * Test of successful Patch consisting of create and delete Patch operations. + */ + @Test + public void modulePatchCreateAndDeleteTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class.getResourceAsStream( + "/instanceidentifier/json/jsonPATCHdataCreateAndDelete.json"); + + final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } + + /** + * Test trying to use Patch create operation which requires value without value. Test should fail with + * {@link RestconfDocumentedException} with error code 400. + */ + @Test + public void modulePatchValueMissingNegativeTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class.getResourceAsStream( + "/instanceidentifier/json/jsonPATCHdataValueMissing.json"); + + final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class, + () -> jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag()); + } + + /** + * Test trying to use value with Patch delete operation which does not support value. Test should fail with + * {@link RestconfDocumentedException} with error code 400. + */ + @Test + public void modulePatchValueNotSupportedNegativeTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class.getResourceAsStream( + "/instanceidentifier/json/jsonPATCHdataValueNotSupported.json"); + + final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class, + () -> jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag()); + } + + /** + * Test using Patch when target is completely specified in request URI and thus target leaf contains only '/' sign. + */ + @Test + public void modulePatchCompleteTargetInURITest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class.getResourceAsStream( + "/instanceidentifier/json/jsonPATCHdataCompleteTargetInURI.json"); + + final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } + + /** + * Test of Yang Patch merge operation on list. Test consists of two edit operations - replace and merge. + */ + @Test + public void modulePatchMergeOperationOnListTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHMergeOperationOnList.json"); + + final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } + + /** + * Test of Yang Patch merge operation on container. Test consists of two edit operations - create and merge. + */ + @Test + public void modulePatchMergeOperationOnContainerTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class.getResourceAsStream( + "/instanceidentifier/json/jsonPATCHMergeOperationOnContainer.json"); + + final PatchContext returnValue = jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } + + /** + * Test reading simple leaf value. + */ + @Test + public void modulePatchSimpleLeafValueTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHSimpleLeafValue.json"); + + final PatchContext returnValue = jsonToPatchBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPatchBodyReaderMountPoint.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPatchBodyReaderMountPoint.java new file mode 100644 index 0000000..4ad1a65 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestJsonPatchBodyReaderMountPoint.java @@ -0,0 +1,172 @@ +/* + * 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.controller.sal.rest.impl.test.providers; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.mock; + +import java.io.InputStream; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.mdsal.dom.api.DOMMountPoint; +import org.opendaylight.netconf.sal.rest.impl.JsonToPatchBodyReader; +import org.opendaylight.restconf.common.errors.RestconfDocumentedException; +import org.opendaylight.restconf.common.patch.PatchContext; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; + +public class TestJsonPatchBodyReaderMountPoint extends AbstractBodyReaderTest { + private final JsonToPatchBodyReader jsonToPatchBodyReader; + private static EffectiveModelContext schemaContext; + private static final String MOUNT_POINT = "instance-identifier-module:cont/yang-ext:mount"; + + public TestJsonPatchBodyReaderMountPoint() { + super(schemaContext, mock(DOMMountPoint.class)); + jsonToPatchBodyReader = new JsonToPatchBodyReader(controllerContext); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(APPLICATION_JSON, null); + } + + @BeforeClass + public static void initialization() { + schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext); + } + + @Test + public void modulePatchDataTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHdata.json"); + + final PatchContext returnValue = jsonToPatchBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContextMountPoint(returnValue); + } + + /** + * Test of successful Patch consisting of create and delete Patch operations. + */ + @Test + public void modulePatchCreateAndDeleteTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataCreateAndDelete.json"); + + final PatchContext returnValue = jsonToPatchBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContextMountPoint(returnValue); + } + + /** + * Test trying to use Patch create operation which requires value without value. Test should fail with + * {@link RestconfDocumentedException} with error code 400. + */ + @Test + public void modulePatchValueMissingNegativeTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class.getResourceAsStream( + "/instanceidentifier/json/jsonPATCHdataValueMissing.json"); + + final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class, + () -> jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag()); + } + + /** + * Test trying to use value with Patch delete operation which does not support value. Test should fail with + * {@link RestconfDocumentedException} with error code 400. + */ + @Test + public void modulePatchValueNotSupportedNegativeTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataValueNotSupported.json"); + + final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class, + () -> jsonToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag()); + } + + /** + * Test using Patch when target is completely specified in request URI and thus target leaf contains only '/' sign. + */ + @Test + public void modulePatchCompleteTargetInURITest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHdataCompleteTargetInURI.json"); + + final PatchContext returnValue = jsonToPatchBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContextMountPoint(returnValue); + } + + /** + * Test of Yang Patch merge operation on list. Test consists of two edit operations - replace and merge. + */ + @Test + public void modulePatchMergeOperationOnListTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHMergeOperationOnList.json"); + + final PatchContext returnValue = jsonToPatchBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContextMountPoint(returnValue); + } + + /** + * Test of Yang Patch merge operation on container. Test consists of two edit operations - create and merge. + */ + @Test + public void modulePatchMergeOperationOnContainerTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHMergeOperationOnContainer.json"); + + final PatchContext returnValue = jsonToPatchBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContextMountPoint(returnValue); + } + + /** + * Test reading simple leaf value. + */ + @Test + public void modulePatchSimpleLeafValueTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, jsonToPatchBodyReader, false); + + final InputStream inputStream = TestJsonBodyReader.class + .getResourceAsStream("/instanceidentifier/json/jsonPATCHSimpleLeafValue.json"); + + final PatchContext returnValue = jsonToPatchBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlBodyReader.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlBodyReader.java new file mode 100644 index 0000000..7ff353e --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlBodyReader.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +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 java.io.File; +import java.io.InputStream; +import java.util.Collection; +import java.util.Optional; +import java.util.Set; +import javax.ws.rs.core.MediaType; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeContext; +import org.opendaylight.netconf.sal.rest.impl.XmlNormalizedNodeBodyReader; +import org.opendaylight.restconf.common.errors.RestconfDocumentedException; +import org.opendaylight.restconf.common.errors.RestconfError; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.common.ErrorType; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.Revision; +import org.opendaylight.yangtools.yang.common.XMLNamespace; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class TestXmlBodyReader extends AbstractBodyReaderTest { + + private final XmlNormalizedNodeBodyReader xmlBodyReader; + private static EffectiveModelContext schemaContext; + private static final QNameModule INSTANCE_IDENTIFIER_MODULE_QNAME = QNameModule.create( + XMLNamespace.of("instance:identifier:module"), Revision.of("2014-01-17")); + + public TestXmlBodyReader() { + super(schemaContext, null); + xmlBodyReader = new XmlNormalizedNodeBodyReader(controllerContext); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @BeforeClass + public static void initialization() throws Exception { + final Collection<File> testFiles = TestRestconfUtils.loadFiles("/instanceidentifier/yang"); + testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc")); + testFiles.addAll(TestRestconfUtils.loadFiles("/foo-xml-test/yang")); + schemaContext = YangParserTestUtils.parseYangFiles(testFiles); + } + + @Test + public void putXmlTest() throws Exception { + runXmlTest(false, "foo:top-level-list/key-value"); + } + + @Test + public void postXmlTest() throws Exception { + runXmlTest(true, ""); + } + + private void runXmlTest(final boolean isPost, final String path) throws Exception { + mockBodyReader(path, xmlBodyReader, isPost); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream("/foo-xml-test/foo.xml"); + final NormalizedNodeContext nnc = xmlBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + assertNotNull(nnc); + + assertTrue(nnc.getData() instanceof MapEntryNode); + final MapEntryNode data = (MapEntryNode) nnc.getData(); + assertEquals(2, data.size()); + for (final DataContainerChild child : data.body()) { + switch (child.getIdentifier().getNodeType().getLocalName()) { + case "key-leaf": + assertEquals("key-value", child.body()); + break; + + case "ordinary-leaf": + assertEquals("leaf-value", child.body()); + break; + default: + fail(); + } + } + } + + @Test + public void moduleDataTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, xmlBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmldata.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerDataPutTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final QName cont1QName = QName.create(dataSchemaNode.getQName(), "cont1"); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName); + final DataSchemaNode dataSchemaNodeOnPath = ((DataNodeContainer) dataSchemaNode).getDataChildByName(cont1QName); + final String uri = "instance-identifier-module:cont/cont1"; + mockBodyReader(uri, xmlBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xml_sub_container.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNodeOnPath, returnValue, dataII); + } + + @Test + public void moduleSubContainerDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final QName cont1QName = QName.create(dataSchemaNode.getQName(), "cont1"); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()).node(cont1QName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xml_sub_container.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerAugmentDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final Module augmentModule = schemaContext.findModules(XMLNamespace.of("augment:module")).iterator().next(); + final QName contAugmentQName = QName.create(augmentModule.getQNameModule(), "cont-augment"); + final AugmentationIdentifier augII = new AugmentationIdentifier(Set.of(contAugmentQName)); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()) + .node(augII).node(contAugmentQName); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xml_augment_container.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void moduleSubContainerChoiceAugmentDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = + schemaContext.getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final Module augmentModule = schemaContext.findModules(XMLNamespace.of("augment:module")).iterator().next(); + final QName augmentChoice1QName = QName.create(augmentModule.getQNameModule(), "augment-choice1"); + final QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2"); + final YangInstanceIdentifier dataII = YangInstanceIdentifier.of(dataSchemaNode.getQName()) + .node(new AugmentationIdentifier(Set.of(augmentChoice1QName))) + .node(augmentChoice1QName) + // FIXME: DataSchemaTreeNode intepretation seems to have a bug + //.node(new AugmentationIdentifier(Set.of(augmentChoice2QName))) + .node(augmentChoice2QName) + .node(QName.create(augmentChoice1QName, "case-choice-case-container1")); + final String uri = "instance-identifier-module:cont"; + mockBodyReader(uri, xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xml_augment_choice_container.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, dataII); + } + + @Test + public void rpcModuleInputTest() throws Exception { + final String uri = "invoke-rpc-module:rpc-test"; + mockBodyReader(uri, xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream("/invoke-rpc/xml/rpc-input.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader.readFrom(null, null, null, mediaType, null, + inputStream); + checkNormalizedNodeContextRpc(returnValue); + final ContainerNode contNode = (ContainerNode) returnValue.getData(); + final Optional<DataContainerChild> contDataNodePotential = contNode.findChildByArg(new NodeIdentifier( + QName.create(contNode.getIdentifier().getNodeType(), "cont"))); + assertTrue(contDataNodePotential.isPresent()); + final ContainerNode contDataNode = (ContainerNode) contDataNodePotential.get(); + final Optional<DataContainerChild> leafDataNode = contDataNode.findChildByArg(new NodeIdentifier( + QName.create(contDataNode.getIdentifier().getNodeType(), "lf"))); + assertTrue(leafDataNode.isPresent()); + assertTrue("lf-test".equalsIgnoreCase(leafDataNode.get().body().toString())); + } + + private static void checkExpectValueNormalizeNodeContext(final DataSchemaNode dataSchemaNode, + final NormalizedNodeContext nnContext, final YangInstanceIdentifier dataNodeIdent) { + assertEquals(dataSchemaNode, nnContext.getInstanceIdentifierContext().getSchemaNode()); + assertEquals(dataNodeIdent, nnContext.getInstanceIdentifierContext().getInstanceIdentifier()); + assertNotNull(NormalizedNodes.findNode(nnContext.getData(), dataNodeIdent)); + } + + /** + * Test when container with the same name is placed in two modules (foo-module and bar-module). Namespace must be + * used to distinguish between them to find correct one. Check if container was found not only according to its name + * but also by correct namespace used in payload. + */ + @Test + public void findFooContainerUsingNamespaceTest() throws Exception { + mockBodyReader("", xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlDataFindFooContainer.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + + // check return value + checkNormalizedNodeContext(returnValue); + // check if container was found both according to its name and namespace + assertEquals("Not correct container found, name was ignored", + "foo-bar-container", returnValue.getData().getIdentifier().getNodeType().getLocalName()); + assertEquals("Not correct container found, namespace was ignored", + "foo:module", returnValue.getData().getIdentifier().getNodeType().getNamespace().toString()); + } + + /** + * Test when container with the same name is placed in two modules (foo-module and bar-module). Namespace must be + * used to distinguish between them to find correct one. Check if container was found not only according to its name + * but also by correct namespace used in payload. + */ + @Test + public void findBarContainerUsingNamespaceTest() throws Exception { + mockBodyReader("", xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlDataFindBarContainer.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + + // check return value + checkNormalizedNodeContext(returnValue); + // check if container was found both according to its name and namespace + assertEquals("Not correct container found, name was ignored", + "foo-bar-container", returnValue.getData().getIdentifier().getNodeType().getLocalName()); + assertEquals("Not correct container found, namespace was ignored", + "bar:module", returnValue.getData().getIdentifier().getNodeType().getNamespace().toString()); + } + + /** + * Test PUT operation when message root element is not the same as the last element in request URI. + * PUT operation message should always start with schema node from URI otherwise exception should be + * thrown. + */ + @Test + public void wrongRootElementTest() throws Exception { + mockBodyReader("instance-identifier-module:cont", xmlBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/bug7933.xml"); + try { + xmlBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + Assert.fail("Test should fail due to malformed PUT operation message"); + } catch (final RestconfDocumentedException exception) { + final RestconfError restconfError = exception.getErrors().get(0); + assertEquals(ErrorType.PROTOCOL, restconfError.getErrorType()); + assertEquals(ErrorTag.MALFORMED_MESSAGE, restconfError.getErrorTag()); + } + } +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlBodyReaderMountPoint.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlBodyReaderMountPoint.java new file mode 100644 index 0000000..fe257db --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlBodyReaderMountPoint.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import java.io.File; +import java.io.InputStream; +import java.util.Collection; +import java.util.Optional; +import javax.ws.rs.core.MediaType; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.mdsal.dom.api.DOMMountPoint; +import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeContext; +import org.opendaylight.netconf.sal.rest.impl.XmlNormalizedNodeBodyReader; +import org.opendaylight.restconf.common.errors.RestconfDocumentedException; +import org.opendaylight.restconf.common.errors.RestconfError; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.common.ErrorType; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.Revision; +import org.opendaylight.yangtools.yang.common.XMLNamespace; +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.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class TestXmlBodyReaderMountPoint extends AbstractBodyReaderTest { + private final XmlNormalizedNodeBodyReader xmlBodyReader; + private static EffectiveModelContext schemaContext; + + private static final QNameModule INSTANCE_IDENTIFIER_MODULE_QNAME = QNameModule.create( + XMLNamespace.of("instance:identifier:module"), Revision.of("2014-01-17")); + + public TestXmlBodyReaderMountPoint() { + super(schemaContext, mock(DOMMountPoint.class)); + xmlBodyReader = new XmlNormalizedNodeBodyReader(controllerContext); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @BeforeClass + public static void initialization() throws Exception { + final Collection<File> testFiles = TestRestconfUtils.loadFiles("/instanceidentifier/yang"); + testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc")); + schemaContext = YangParserTestUtils.parseYangFiles(testFiles); + } + + @Test + public void moduleDataTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final String uri = "instance-identifier-module:cont/yang-ext:mount/instance-identifier-module:cont"; + mockBodyReader(uri, xmlBodyReader, false); + final InputStream inputStream = TestXmlBodyReaderMountPoint.class + .getResourceAsStream("/instanceidentifier/xml/xmldata.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader.readFrom(null, + null, null, mediaType, null, inputStream); + checkMountPointNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue); + } + + @Test + public void moduleSubContainerDataPutTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final String uri = "instance-identifier-module:cont/yang-ext:mount/instance-identifier-module:cont/cont1"; + mockBodyReader(uri, xmlBodyReader, false); + final InputStream inputStream = TestXmlBodyReaderMountPoint.class + .getResourceAsStream("/instanceidentifier/xml/xml_sub_container.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader.readFrom(null, + null, null, mediaType, null, inputStream); + checkMountPointNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue, + QName.create(dataSchemaNode.getQName(), "cont1")); + } + + @Test + public void moduleSubContainerDataPostTest() throws Exception { + final DataSchemaNode dataSchemaNode = schemaContext + .getDataChildByName(QName.create(INSTANCE_IDENTIFIER_MODULE_QNAME, "cont")); + final String uri = "instance-identifier-module:cont/yang-ext:mount/instance-identifier-module:cont"; + mockBodyReader(uri, xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReaderMountPoint.class + .getResourceAsStream("/instanceidentifier/xml/xml_sub_container.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader.readFrom(null, + null, null, mediaType, null, inputStream); + checkMountPointNormalizedNodeContext(returnValue); + checkExpectValueNormalizeNodeContext(dataSchemaNode, returnValue); + } + + @Test + public void rpcModuleInputTest() throws Exception { + final String uri = "instance-identifier-module:cont/yang-ext:mount/invoke-rpc-module:rpc-test"; + mockBodyReader(uri, xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReaderMountPoint.class + .getResourceAsStream("/invoke-rpc/xml/rpc-input.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader.readFrom(null, + null, null, mediaType, null, inputStream); + checkNormalizedNodeContextRpc(returnValue); + final ContainerNode contNode = (ContainerNode) returnValue.getData(); + final YangInstanceIdentifier yangCont = YangInstanceIdentifier.of( + QName.create(contNode.getIdentifier().getNodeType(), "cont")); + final Optional<DataContainerChild> contDataNodePotential = + contNode.findChildByArg(yangCont.getLastPathArgument()); + assertTrue(contDataNodePotential.isPresent()); + final ContainerNode contDataNode = (ContainerNode) contDataNodePotential.get(); + final YangInstanceIdentifier yangLeaf = YangInstanceIdentifier.of( + QName.create(contDataNode.getIdentifier().getNodeType(), "lf")); + final Optional<DataContainerChild> leafDataNode = contDataNode.findChildByArg(yangLeaf.getLastPathArgument()); + assertTrue(leafDataNode.isPresent()); + assertTrue("lf-test".equalsIgnoreCase(leafDataNode.get().body().toString())); + } + + private void checkExpectValueNormalizeNodeContext( + final DataSchemaNode dataSchemaNode, + final NormalizedNodeContext nnContext) { + checkExpectValueNormalizeNodeContext(dataSchemaNode, nnContext, null); + } + + protected void checkExpectValueNormalizeNodeContext( + final DataSchemaNode dataSchemaNode, final NormalizedNodeContext nnContext, final QName qualifiedName) { + YangInstanceIdentifier dataNodeIdent = YangInstanceIdentifier.of(dataSchemaNode.getQName()); + final DOMMountPoint mountPoint = nnContext.getInstanceIdentifierContext().getMountPoint(); + final DataSchemaNode mountDataSchemaNode = + modelContext(mountPoint).getDataChildByName(dataSchemaNode.getQName()); + assertNotNull(mountDataSchemaNode); + if (qualifiedName != null && dataSchemaNode instanceof DataNodeContainer) { + final DataSchemaNode child = ((DataNodeContainer) dataSchemaNode).getDataChildByName(qualifiedName); + dataNodeIdent = YangInstanceIdentifier.builder(dataNodeIdent).node(child.getQName()).build(); + assertTrue(nnContext.getInstanceIdentifierContext().getSchemaNode().equals(child)); + } else { + assertTrue(mountDataSchemaNode.equals(dataSchemaNode)); + } + assertNotNull(NormalizedNodes.findNode(nnContext.getData(), dataNodeIdent)); + } + + /** + * Test when container with the same name is placed in two modules (foo-module and bar-module). Namespace must be + * used to distinguish between them to find correct one. Check if container was found not only according to its name + * but also by correct namespace used in payload. + */ + @Test + public void findFooContainerUsingNamespaceTest() throws Exception { + mockBodyReader("instance-identifier-module:cont/yang-ext:mount", xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlDataFindFooContainer.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + + // check return value + checkMountPointNormalizedNodeContext(returnValue); + // check if container was found both according to its name and namespace + assertEquals("Not correct container found, name was ignored", + "foo-bar-container", returnValue.getData().getIdentifier().getNodeType().getLocalName()); + assertEquals("Not correct container found, namespace was ignored", + "foo:module", returnValue.getData().getIdentifier().getNodeType().getNamespace().toString()); + } + + /** + * Test when container with the same name is placed in two modules (foo-module and bar-module). Namespace must be + * used to distinguish between them to find correct one. Check if container was found not only according to its name + * but also by correct namespace used in payload. + */ + @Test + public void findBarContainerUsingNamespaceTest() throws Exception { + mockBodyReader("instance-identifier-module:cont/yang-ext:mount", xmlBodyReader, true); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlDataFindBarContainer.xml"); + final NormalizedNodeContext returnValue = xmlBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + + // check return value + checkMountPointNormalizedNodeContext(returnValue); + // check if container was found both according to its name and namespace + assertEquals("Not correct container found, name was ignored", + "foo-bar-container", returnValue.getData().getIdentifier().getNodeType().getLocalName()); + assertEquals("Not correct container found, namespace was ignored", + "bar:module", returnValue.getData().getIdentifier().getNodeType().getNamespace().toString()); + } + + /** + * Test PUT operation when message root element is not the same as the last element in request URI. + * PUT operation message should always start with schema node from URI otherwise exception should be + * thrown. + */ + @Test + public void wrongRootElementTest() throws Exception { + mockBodyReader("instance-identifier-module:cont/yang-ext:mount", xmlBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/bug7933.xml"); + try { + xmlBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + Assert.fail("Test should fail due to malformed PUT operation message"); + } catch (final RestconfDocumentedException exception) { + final RestconfError restconfError = exception.getErrors().get(0); + assertEquals(ErrorType.PROTOCOL, restconfError.getErrorType()); + assertEquals(ErrorTag.MALFORMED_MESSAGE, restconfError.getErrorTag()); + } + } +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlBodyWriter.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlBodyWriter.java new file mode 100644 index 0000000..169d806 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlBodyWriter.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.OutputStream; +import java.util.Collection; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils; +import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeContext; +import org.opendaylight.netconf.sal.rest.impl.NormalizedNodeXmlBodyWriter; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class TestXmlBodyWriter extends AbstractBodyReaderTest { + + private final NormalizedNodeXmlBodyWriter xmlBodyWriter; + private static EffectiveModelContext schemaContext; + + public TestXmlBodyWriter() { + super(schemaContext, null); + this.xmlBodyWriter = new NormalizedNodeXmlBodyWriter(); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @BeforeClass + public static void initialization() throws Exception { + final Collection<File> testFiles = TestRestconfUtils.loadFiles("/instanceidentifier/yang"); + testFiles.addAll(TestRestconfUtils.loadFiles("/invoke-rpc")); + schemaContext = YangParserTestUtils.parseYangFiles(testFiles); + } + + @Test + public void rpcModuleInputTest() throws Exception { + final String uri = "invoke-rpc-module:rpc-test"; + final String pathToInputFile = "/invoke-rpc/xml/rpc-output.xml"; + final NormalizedNodeContext nnContext = TestRestconfUtils + .loadNormalizedContextFromXmlFile(pathToInputFile, uri, controllerContext); + final OutputStream output = new ByteArrayOutputStream(); + this.xmlBodyWriter.writeTo(nnContext, null, null, null, this.mediaType, null, output); + assertTrue(output.toString().contains("lf-test")); + } +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPatchBodyReader.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPatchBodyReader.java new file mode 100644 index 0000000..8b37ba4 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPatchBodyReader.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2015 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import java.io.InputStream; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.netconf.sal.rest.impl.XmlToPatchBodyReader; +import org.opendaylight.restconf.common.errors.RestconfDocumentedException; +import org.opendaylight.restconf.common.patch.PatchContext; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; + +public class TestXmlPatchBodyReader extends AbstractBodyReaderTest { + + private final XmlToPatchBodyReader xmlToPatchBodyReader; + private static EffectiveModelContext schemaContext; + + public TestXmlPatchBodyReader() { + super(schemaContext, null); + xmlToPatchBodyReader = new XmlToPatchBodyReader(controllerContext); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @BeforeClass + public static void initialization() throws NoSuchFieldException, SecurityException { + schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext); + } + + @Test + public void moduleDataTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/xmlPATCHdata.xml"); + final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } + + /** + * Test trying to use Patch create operation which requires value without value. Error code 400 should be returned. + */ + @Test + public void moduleDataValueMissingNegativeTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/xmlPATCHdataValueMissing.xml"); + final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class, + () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + assertEquals(1, ex.getErrors().size()); + assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag()); + } + + /** + * Test trying to use value with Patch delete operation which does not support value. Error code 400 should be + * returned. + */ + @Test + public void moduleDataNotValueNotSupportedNegativeTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/xmlPATCHdataValueNotSupported.xml"); + + final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class, + () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + assertEquals(1, ex.getErrors().size()); + assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag()); + } + + /** + * Test of Yang Patch with absolute target path. + */ + @Test + public void moduleDataAbsoluteTargetPathTest() throws Exception { + final String uri = ""; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml"); + final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } + + /** + * Test using Patch when target is completely specified in request URI and thus target leaf contains only '/' sign. + */ + @Test + public void modulePatchCompleteTargetInURITest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataCompleteTargetInURI.xml"); + final PatchContext returnValue = xmlToPatchBodyReader + .readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } + + /** + * Test of Yang Patch merge operation on list. Test consists of two edit operations - replace and merge. + */ + @Test + public void moduleDataMergeOperationOnListTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml"); + final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } + + /** + * Test of Yang Patch merge operation on container. Test consists of two edit operations - create and merge. + */ + @Test + public void moduleDataMergeOperationOnContainerTest() throws Exception { + final String uri = "instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml"); + final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContext(returnValue); + } +} diff --git a/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPatchBodyReaderMountPoint.java b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPatchBodyReaderMountPoint.java new file mode 100644 index 0000000..614f36e --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/controller/sal/rest/impl/test/providers/TestXmlPatchBodyReaderMountPoint.java @@ -0,0 +1,133 @@ +/* + * 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.controller.sal.rest.impl.test.providers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.mock; + +import java.io.InputStream; +import javax.ws.rs.core.MediaType; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.mdsal.dom.api.DOMMountPoint; +import org.opendaylight.netconf.sal.rest.impl.XmlToPatchBodyReader; +import org.opendaylight.restconf.common.errors.RestconfDocumentedException; +import org.opendaylight.restconf.common.patch.PatchContext; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; + +public class TestXmlPatchBodyReaderMountPoint extends AbstractBodyReaderTest { + + private final XmlToPatchBodyReader xmlToPatchBodyReader; + private static EffectiveModelContext schemaContext; + private static final String MOUNT_POINT = "instance-identifier-module:cont/yang-ext:mount"; + + public TestXmlPatchBodyReaderMountPoint() { + super(schemaContext, mock(DOMMountPoint.class)); + xmlToPatchBodyReader = new XmlToPatchBodyReader(controllerContext); + } + + @BeforeClass + public static void initialization() throws NoSuchFieldException, SecurityException { + schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext); + } + + @Override + protected MediaType getMediaType() { + return new MediaType(MediaType.APPLICATION_XML, null); + } + + @Test + public void moduleDataTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/xmlPATCHdata.xml"); + checkPatchContextMountPoint(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + } + + /** + * Test trying to use Patch create operation which requires value without value. Error code 400 should be returned. + */ + @Test + public void moduleDataValueMissingNegativeTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/xmlPATCHdataValueMissing.xml"); + final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class, + () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag()); + } + + /** + * Test trying to use value with Patch delete operation which does not support value. Error code 400 should be + * returned. + */ + @Test + public void moduleDataNotValueNotSupportedNegativeTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class + .getResourceAsStream("/instanceidentifier/xml/xmlPATCHdataValueNotSupported.xml"); + final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class, + () -> xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + assertEquals(ErrorTag.MALFORMED_MESSAGE, ex.getErrors().get(0).getErrorTag()); + } + + /** + * Test of Yang Patch with absolute target path. + */ + @Test + public void moduleDataAbsoluteTargetPathTest() throws Exception { + final String uri = MOUNT_POINT; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/xmlPATCHdataAbsoluteTargetPath.xml"); + final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContextMountPoint(returnValue); + } + + /** + * Test using Patch when target is completely specified in request URI and thus target leaf contains only '/' sign. + */ + @Test + public void modulePatchCompleteTargetInURITest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/xmlPATCHdataCompleteTargetInURI.xml"); + final PatchContext returnValue = xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream); + checkPatchContextMountPoint(returnValue); + } + + /** + * Test of Yang Patch merge operation on list. Test consists of two edit operations - replace and merge. + */ + @Test + public void moduleDataMergeOperationOnListTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont/my-list1/leaf1"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/xmlPATCHdataMergeOperationOnList.xml"); + checkPatchContextMountPoint(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + } + + /** + * Test of Yang Patch merge operation on container. Test consists of two edit operations - create and merge. + */ + @Test + public void moduleDataMergeOperationOnContainerTest() throws Exception { + final String uri = MOUNT_POINT + "/instance-identifier-patch-module:patch-cont"; + mockBodyReader(uri, xmlToPatchBodyReader, false); + final InputStream inputStream = TestXmlBodyReader.class.getResourceAsStream( + "/instanceidentifier/xml/xmlPATCHdataMergeOperationOnContainer.xml"); + checkPatchContextMountPoint(xmlToPatchBodyReader.readFrom(null, null, null, mediaType, null, inputStream)); + } +} |