From: msunal Date: Wed, 20 Nov 2013 16:49:08 +0000 (+0100) Subject: Response for PUT and POST operations X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~363 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=6a796ca360be200816e4b8f7724227a6ee1929fe Response for PUT and POST operations - added response as is written in http://tools.ietf.org/html/draft-bierman-netconf-restconf-02#page-37 - tests Change-Id: Ice0a698f08b7512ea7ee29c1a534bff068e3b6bd Signed-off-by: Martin Sunal --- diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java index c36a79c5d9..a22ea62397 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java @@ -15,10 +15,9 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; -import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.restconf.impl.StructuredData; -import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; /** @@ -57,7 +56,6 @@ public interface RestconfService extends RestconfServiceLegacy { @GET public Object getRoot(); - @GET @Path("/modules") @Produces({API+JSON,API+XML}) @@ -68,23 +66,20 @@ public interface RestconfService extends RestconfServiceLegacy { @Produces({Draft02.MediaTypes.API+JSON,Draft02.MediaTypes.API+XML,API+JSON,API+XML}) public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload); - @GET @Path("/config/{identifier:.+}") @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML}) public StructuredData readConfigurationData(@PathParam("identifier") String identifier); - - @PUT @Path("/config/{identifier:.+}") @Produces({API+JSON,API+XML}) - public RpcResult createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload); + public Response createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload); @POST @Path("/config/{identifier:.+}") @Produces({API+JSON,API+XML}) - public RpcResult updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload); + public Response updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload); @GET @Path("/operational/{identifier:.+}") @@ -94,12 +89,11 @@ public interface RestconfService extends RestconfServiceLegacy { @PUT @Path("/operational/{identifier:.+}") @Produces({API+JSON,API+XML}) - public RpcResult createOperationalData(@PathParam("identifier") String identifier, CompositeNode payload); + public Response createOperationalData(@PathParam("identifier") String identifier, CompositeNode payload); @POST @Path("/operational/{identifier:.+}") @Produces({API+JSON,API+XML}) - public RpcResult updateOperationalData(@PathParam("identifier") String identifier, CompositeNode payload); + public Response updateOperationalData(@PathParam("identifier") String identifier, CompositeNode payload); - } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java index 6683fd1835..242e7f3150 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java @@ -8,10 +8,9 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; -import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.restconf.impl.StructuredData; -import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; public interface RestconfServiceLegacy { @@ -35,12 +34,12 @@ public interface RestconfServiceLegacy { @PUT @Path("/datastore/{identifier:.+}") @Produces({API+JSON,API+XML}) - public RpcResult createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload); + public Response createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload); @Deprecated @POST @Path("/datastore/{identifier:.+}") @Produces({API+JSON,API+XML}) - public RpcResult updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload); + public Response updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend index a41a48287d..d9ac53589f 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend @@ -1,10 +1,12 @@ package org.opendaylight.controller.sal.restconf.impl import java.util.List +import javax.ws.rs.core.Response import org.opendaylight.controller.sal.rest.api.RestconfService import org.opendaylight.yangtools.yang.data.api.CompositeNode import org.opendaylight.yangtools.yang.model.api.DataNodeContainer import org.opendaylight.yangtools.yang.model.api.DataSchemaNode +import org.opendaylight.controller.md.sal.common.api.TransactionStatus class RestconfImpl implements RestconfService { @@ -48,13 +50,21 @@ class RestconfImpl implements RestconfService { override createConfigurationData(String identifier, CompositeNode payload) { val identifierWithSchemaNode = identifier.toInstanceIdentifier val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode) - return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); + val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); + switch status.result { + case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build + default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build + } } override updateConfigurationData(String identifier, CompositeNode payload) { val identifierWithSchemaNode = identifier.toInstanceIdentifier val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode) - return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); + val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); + switch status.result { + case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build + default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build + } } override invokeRpc(String identifier, CompositeNode payload) { @@ -88,13 +98,21 @@ class RestconfImpl implements RestconfService { override createOperationalData(String identifier, CompositeNode payload) { val identifierWithSchemaNode = identifier.toInstanceIdentifier val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode) - return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); + val status = broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); + switch status.result { + case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build + default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build + } } override updateOperationalData(String identifier, CompositeNode payload) { val identifierWithSchemaNode = identifier.toInstanceIdentifier val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode) - return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); + val status = broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get(); + switch status.result { + case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build + default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build + } } private def CompositeNode resolveNodeNamespaceBySchema(CompositeNode node, DataSchemaNode schema) { diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyFuture.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyFuture.java index a32a3479ba..251b212513 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyFuture.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyFuture.java @@ -6,30 +6,85 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.yangtools.yang.common.RpcResult; public class DummyFuture implements Future> { + + private final boolean cancel; + private final boolean isCancelled; + private final boolean isDone; + private final RpcResult result; + + public DummyFuture() { + cancel = false; + isCancelled = false; + isDone = false; + result = null; + } + + private DummyFuture(Builder builder) { + cancel = builder.cancel; + isCancelled = builder.isCancelled; + isDone = builder.isDone; + result = builder.result; + } + + public static Builder builder() { + return new DummyFuture.Builder(); + } @Override public boolean cancel(boolean mayInterruptIfRunning) { - return false; + return cancel; } @Override public boolean isCancelled() { - return false; + return isCancelled; } @Override public boolean isDone() { - return false; + return isDone; } @Override public RpcResult get() throws InterruptedException, ExecutionException { - return null; + return result; } @Override public RpcResult get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - return null; + return result; + } + + public static class Builder { + + private boolean cancel; + private boolean isCancelled; + private boolean isDone; + private RpcResult result; + + public Builder cancel(boolean cancel) { + this.cancel = cancel; + return this; + } + + public Builder isCancelled(boolean isCancelled) { + this.isCancelled = isCancelled; + return this; + } + + public Builder isDone(boolean isDone) { + this.isDone = isDone; + return this; + } + + public Builder rpcResult(RpcResult result) { + this.result = result; + return this; + } + + public Future> build() { + return new DummyFuture(this); + } } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyRpcResult.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyRpcResult.java new file mode 100644 index 0000000000..5ab4f99fdc --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/DummyRpcResult.java @@ -0,0 +1,72 @@ +package org.opendaylight.controller.sal.restconf.impl.test; + +import java.util.Collection; + +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.RpcResult; + +public class DummyRpcResult implements RpcResult { + + private final boolean isSuccessful; + private final TransactionStatus result; + private final Collection errors; + + public DummyRpcResult() { + isSuccessful = false; + result = null; + errors = null; + } + + private DummyRpcResult(Builder builder) { + isSuccessful = builder.isSuccessful; + result = builder.result; + errors = builder.errors; + } + + public static Builder builder() { + return new DummyRpcResult.Builder(); + } + + @Override + public boolean isSuccessful() { + return isSuccessful; + } + + @Override + public TransactionStatus getResult() { + return result; + } + + @Override + public Collection getErrors() { + return errors; + } + + public static class Builder { + private boolean isSuccessful; + private TransactionStatus result; + private Collection errors; + + public Builder isSuccessful(boolean isSuccessful) { + this.isSuccessful = isSuccessful; + return this; + } + + public Builder result(TransactionStatus result) { + this.result = result; + return this; + } + + public Builder errors(Collection errors) { + this.errors = errors; + return this; + } + + public RpcResult build() { + return new DummyRpcResult(this); + } + + } + +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java index 3d06e4a759..1d8d7495f9 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java @@ -10,16 +10,22 @@ import java.io.*; import java.net.*; import java.sql.Date; import java.util.*; +import java.util.concurrent.Future; import javax.ws.rs.WebApplicationException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLStreamException; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider; import org.opendaylight.controller.sal.restconf.impl.*; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.*; import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder; import org.opendaylight.yangtools.yang.model.api.*; @@ -27,6 +33,9 @@ import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser; import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; import org.slf4j.*; import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import com.google.common.base.Preconditions; final class TestUtils { @@ -90,8 +99,20 @@ final class TestUtils { } return (CompositeNode) dataTree; } + + public static Document loadDocumentFrom(InputStream inputStream) { + try { + DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); + return docBuilder.parse(inputStream); + } catch (SAXException | IOException | ParserConfigurationException e) { + logger.error("Error during loading Document from XML", e); + return null; + } + } public static String getDocumentInPrintableForm(Document doc) { + Preconditions.checkNotNull(doc); try { ByteArrayOutputStream out = new ByteArrayOutputStream(); TransformerFactory tf = TransformerFactory.newInstance(); @@ -272,9 +293,10 @@ final class TestUtils { ControllerContext controllerContext = mock(ControllerContext.class); BrokerFacade broker = mock(BrokerFacade.class); + RpcResult rpcResult = DummyRpcResult.builder().result(TransactionStatus.COMMITED).build(); + Future> future = DummyFuture.builder().rpcResult(rpcResult).build(); when(controllerContext.toInstanceIdentifier(any(String.class))).thenReturn(instIdAndSchema); - when(broker.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn( - new DummyFuture()); + when(broker.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(future); restconf.setControllerContext(controllerContext); restconf.setBroker(broker); diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java index baf226712f..7b63c5fd94 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java @@ -1,22 +1,19 @@ package org.opendaylight.controller.sal.restconf.impl.test; -import static org.mockito.Mockito.*; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.io.FileNotFoundException; -import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; -import java.util.Collection; import java.util.List; import java.util.Set; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.LogRecord; @@ -24,11 +21,7 @@ import javax.ws.rs.client.Entity; import javax.ws.rs.core.Application; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.TestProperties; @@ -43,15 +36,11 @@ import org.opendaylight.controller.sal.restconf.impl.BrokerFacade; import org.opendaylight.controller.sal.restconf.impl.ControllerContext; import org.opendaylight.controller.sal.restconf.impl.MediaTypes; import org.opendaylight.controller.sal.restconf.impl.RestconfImpl; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.w3c.dom.Document; -import org.xml.sax.SAXException; import com.google.common.base.Charsets; @@ -60,15 +49,11 @@ public class XmlProvidersTest extends JerseyTest { private static ControllerContext controllerContext; private static BrokerFacade brokerFacade; private static RestconfImpl restconfImpl; + private static final MediaType MEDIA_TYPE = new MediaType("application", "vnd.yang.api+xml"); @BeforeClass - public static void init() { - Set allModules = null; - try { - allModules = TestUtils.loadModules(RestconfImplTest.class.getResource("/full-versions/yangs").getPath()); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } + public static void init() throws FileNotFoundException { + Set allModules = TestUtils.loadModules(RestconfImplTest.class.getResource("/full-versions/yangs").getPath()); SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules); controllerContext = ControllerContext.getInstance(); controllerContext.setSchemas(schemaContext); @@ -87,96 +72,100 @@ public class XmlProvidersTest extends JerseyTest { } @Test - public void testStructuredDataToXmlProvider() throws FileNotFoundException { - URI uri = null; - try { - uri = new URI("/datastore/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString()); - } catch (UnsupportedEncodingException | URISyntaxException e) { - e.printStackTrace(); - } + public void testStructuredDataToXmlProvider() throws FileNotFoundException, UnsupportedEncodingException { + String uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0"); InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml"); CompositeNode loadedCompositeNode = TestUtils.loadCompositeNode(xmlStream); when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode); - Response response = target(uri.toASCIIString()).request(MediaTypes.API+RestconfService.XML).get(); + Response response = target(uri).request(MEDIA_TYPE).get(); assertEquals(200, response.getStatus()); } @Test - public void testXmlToCompositeNodeProvider() throws ParserConfigurationException, SAXException, IOException { - URI uri = null; - try { - uri = new URI("/config/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString()); - } catch (UnsupportedEncodingException | URISyntaxException e) { - e.printStackTrace(); - } - InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml"); - final CompositeNode loadedCompositeNode = TestUtils.loadCompositeNode(xmlStream); - when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(new Future>() { - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - @Override - public boolean isCancelled() { - return false; - } - @Override - public boolean isDone() { - return false; - } - @Override - public RpcResult get() throws InterruptedException, ExecutionException { - return null; - } - @Override - public RpcResult get(long timeout, TimeUnit unit) throws InterruptedException, - ExecutionException, TimeoutException { - return null; - } - }); + public void testBadFormatXmlToCompositeNodeProvider() throws UnsupportedEncodingException, URISyntaxException { + String uri = createUri("/operations/", "ietf-interfaces:interfaces/interface/eth0"); - DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); - xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml"); - Document doc = docBuilder.parse(xmlStream); + Response response = target(uri).request(MediaTypes.API + RestconfService.XML).post( + Entity.entity("", MEDIA_TYPE)); + assertEquals(400, response.getStatus()); - Response response = target(uri.toASCIIString()).request(MediaTypes.API+RestconfService.XML).post(Entity.entity(TestUtils.getDocumentInPrintableForm(doc), new MediaType("application","vnd.yang.api+xml"))); - assertEquals(204, response.getStatus()); + response = target(uri).request(MediaTypes.API + RestconfService.XML).post( + Entity.entity("", MEDIA_TYPE)); + assertEquals(400, response.getStatus()); } @Test - public void testXmlToCompositeNodeProviderExceptions() { - URI uri = null; - try { - uri = new URI("/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString()); - } catch (UnsupportedEncodingException | URISyntaxException e) { - e.printStackTrace(); - } + public void testXmlToCompositeNode404NotFound() throws UnsupportedEncodingException, URISyntaxException { + String uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0"); - Response response = target(uri.toASCIIString()).request(MediaTypes.API + RestconfService.XML).post( - Entity.entity("", new MediaType("application", "vnd.yang.api+xml"))); - assertEquals(400, response.getStatus()); + when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(null); - response = target(uri.toASCIIString()).request(MediaTypes.API + RestconfService.XML).post( - Entity.entity("", new MediaType("application", "vnd.yang.api+xml"))); - assertEquals(400, response.getStatus()); + Response response = target(uri).request(MediaTypes.API+RestconfService.XML).get(); + assertEquals(404, response.getStatus()); } @Test - public void testXmlToCompositeNode404NotFound() { - URI uri = null; - try { - uri = new URI("/datastore/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString()); - } catch (UnsupportedEncodingException | URISyntaxException e) { - e.printStackTrace(); - } + public void testRpcResultCommitedToStatusCodes() throws UnsupportedEncodingException { + InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml"); + String xml = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(xmlStream)); + Entity entity = Entity.entity(xml, MEDIA_TYPE); + RpcResult rpcResult = DummyRpcResult.builder().result(TransactionStatus.COMMITED).build(); + Future> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build(); + when(brokerFacade.commitOperationalDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture); + when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture); - when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(null); + String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0"); + Response response = target(uri).request(MEDIA_TYPE).put(entity); + assertEquals(200, response.getStatus()); + response = target(uri).request(MEDIA_TYPE).post(entity); + assertEquals(204, response.getStatus()); - Response response = target(uri.toASCIIString()).request(MediaTypes.API+RestconfService.XML).get(); - assertEquals(404, response.getStatus()); + uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0"); + response = target(uri).request(MEDIA_TYPE).put(entity); + assertEquals(200, response.getStatus()); + response = target(uri).request(MEDIA_TYPE).post(entity); + assertEquals(204, response.getStatus()); + + uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0"); + response = target(uri).request(MEDIA_TYPE).put(entity); + assertEquals(200, response.getStatus()); + response = target(uri).request(MEDIA_TYPE).post(entity); + assertEquals(204, response.getStatus()); + } + + @Test + public void testRpcResultOtherToStatusCodes() throws UnsupportedEncodingException { + InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml"); + String xml = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(xmlStream)); + Entity entity = Entity.entity(xml, MEDIA_TYPE); + RpcResult rpcResult = DummyRpcResult.builder().result(TransactionStatus.FAILED).build(); + Future> dummyFuture = DummyFuture.builder().rpcResult(rpcResult).build(); + when(brokerFacade.commitOperationalDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture); + when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(dummyFuture); + + String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0"); + Response response = target(uri).request(MEDIA_TYPE).put(entity); + assertEquals(500, response.getStatus()); + response = target(uri).request(MEDIA_TYPE).post(entity); + assertEquals(500, response.getStatus()); + + uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0"); + response = target(uri).request(MEDIA_TYPE).put(entity); + assertEquals(500, response.getStatus()); + response = target(uri).request(MEDIA_TYPE).post(entity); + assertEquals(500, response.getStatus()); + + uri = createUri("/datastore/", "ietf-interfaces:interfaces/interface/eth0"); + response = target(uri).request(MEDIA_TYPE).put(entity); + assertEquals(500, response.getStatus()); + response = target(uri).request(MEDIA_TYPE).post(entity); + assertEquals(500, response.getStatus()); + } + + private String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException { + return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString(); } @Override