From: Ivan Hrasko Date: Thu, 28 Jul 2016 13:16:01 +0000 (+0200) Subject: Bug 6037 - Check if delete request was successful X-Git-Tag: release/boron~17^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=f1d62db358ac1368e580e165d669fe7237292763;p=netconf.git Bug 6037 - Check if delete request was successful - adaptation for Restconf draft 11+ - checking if data to delete exists, if not return error 404 - remove not needed method from POST utils and use method from common transaction utils - added unit tests Change-Id: I133c628a2e41f12d1db58fd06ff6c073ebfc6ece Signed-off-by: Ivan Hrasko --- diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java index 56e9b57408..a6187f5fa3 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java @@ -133,7 +133,7 @@ public class RestconfDataServiceImpl implements RestconfDataService { schemaContextRef.get()); final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint(); - DOMDataReadWriteTransaction transaction = null; + final DOMDataReadWriteTransaction transaction; if (mountPoint == null) { transaction = this.transactionChainHandler.get().newReadWriteTransaction(); } else { diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java index d23f692723..53c19c5fe9 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java @@ -11,7 +11,7 @@ import com.google.common.util.concurrent.CheckedFuture; import javax.ws.rs.core.Response; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -32,7 +32,6 @@ public final class DeleteDataTransactionUtil { * - Wrapper for data of transaction * @return {@link Response} */ - public static Response deleteData(final TransactionVarsWrapper transactionNode) { final CheckedFuture future = submitData( transactionNode.getTransaction(), transactionNode.getInstanceIdentifier().getInstanceIdentifier()); @@ -42,17 +41,19 @@ public final class DeleteDataTransactionUtil { } /** - * Delete data via transaction + * Delete data via transaction. Return error if data to delete does not exist. * - * @param writeTx - * - write transaction + * @param readWriteTx + * - read and write transaction * @param path * - path of data to delete * @return {@link CheckedFuture} */ private static CheckedFuture submitData( - final DOMDataWriteTransaction writeTx, final YangInstanceIdentifier path) { - writeTx.delete(LogicalDatastoreType.CONFIGURATION, path); - return writeTx.submit(); + final DOMDataReadWriteTransaction readWriteTx, final YangInstanceIdentifier path) { + TransactionUtil.checkItemExists(readWriteTx, LogicalDatastoreType.CONFIGURATION, path, + RestconfDataServiceConstant.DeleteData.DELETE_TX_TYPE); + readWriteTx.delete(LogicalDatastoreType.CONFIGURATION, path); + return readWriteTx.submit(); } } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java index 5a762ebb7b..778acd9734 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java @@ -8,9 +8,7 @@ package org.opendaylight.restconf.restful.utils; import com.google.common.util.concurrent.CheckedFuture; -import com.google.common.util.concurrent.ListenableFuture; import java.net.URI; -import java.util.concurrent.ExecutionException; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; @@ -18,9 +16,6 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; -import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; -import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag; -import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType; import org.opendaylight.restconf.common.references.SchemaContextRef; import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; import org.opendaylight.restconf.utils.parser.ParserIdentifier; @@ -136,32 +131,11 @@ public final class PostDataTransactionUtil { private static void putChild(final NormalizedNode child, final DOMDataReadWriteTransaction readWriteTx, final YangInstanceIdentifier path) { final YangInstanceIdentifier childPath = path.node(child.getIdentifier()); - checkItemDesNotExits(childPath, readWriteTx); + TransactionUtil.checkItemDoesNotExists(readWriteTx, LogicalDatastoreType.CONFIGURATION, childPath, + RestconfDataServiceConstant.PostData.POST_TX_TYPE); readWriteTx.put(LogicalDatastoreType.CONFIGURATION, childPath, child); } - /** - * Check if data posted to create doesn't exits. - * - * @param path - * - path to data - * @param readWriteTx - * - read write transaction - */ - private static void checkItemDesNotExits(final YangInstanceIdentifier path, - final DOMDataReadWriteTransaction readWriteTx) { - final ListenableFuture existData = readWriteTx.exists(LogicalDatastoreType.CONFIGURATION, path); - try { - if (existData.get()) { - readWriteTx.cancel(); - throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL, - ErrorTag.DATA_EXISTS); - } - } catch (InterruptedException | ExecutionException e) { - LOG.warn("It wasn't possible to get data loaded from datastore at path {}", path, e); - } - } - /** * Get location from {@link YangInstanceIdentifier} and {@link UriInfo} * @@ -187,4 +161,3 @@ public final class PostDataTransactionUtil { return uriBuilder.build(); } } - diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java new file mode 100644 index 0000000000..f867ab1d1a --- /dev/null +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java @@ -0,0 +1,78 @@ +/* + * 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.restconf.restful.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import com.google.common.util.concurrent.Futures; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext; +import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; +import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag; +import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType; +import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; + +public class DeleteDataTransactionUtilTest { + @Mock DOMDataReadWriteTransaction transaction; + @Mock InstanceIdentifierContext context; + + @Before + public void init() throws Exception { + MockitoAnnotations.initMocks(this); + Mockito.when(this.transaction.submit()).thenReturn(Futures.immediateCheckedFuture(null)); + Mockito.when(context.getInstanceIdentifier()).thenReturn(YangInstanceIdentifier.EMPTY); + } + + /** + * Test of successful DELETE operation. + */ + @Test + public void deleteData() throws Exception { + // assert that data to delete exists + Mockito.when(this.transaction.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY)) + .thenReturn(Futures.immediateCheckedFuture(Boolean.TRUE)); + + // test + final Response response = DeleteDataTransactionUtil.deleteData( + new TransactionVarsWrapper(this.context, null, this.transaction)); + + // assert success + assertEquals("Not expected response received", Status.OK.getStatusCode(), response.getStatus()); + } + + /** + * Negative test for DELETE operation when data to delete does not exist. Error 404 is expected. + */ + @Test + public void deleteDataNegativeTest() throws Exception { + // assert that data to delete does NOT exist + Mockito.when(this.transaction.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.EMPTY)) + .thenReturn(Futures.immediateCheckedFuture(Boolean.FALSE)); + + // test and assert error + try { + DeleteDataTransactionUtil.deleteData(new TransactionVarsWrapper(this.context, null, this.transaction)); + fail("Delete operation should fail due to missing data"); + } catch (final RestconfDocumentedException e) { + assertEquals(ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType()); + assertEquals(ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag()); + assertEquals(404, e.getErrors().get(0).getErrorTag().getStatusCode()); + } + } +} \ No newline at end of file