Bug 6037 - Check if delete request was successful 12/42712/25
authorIvan Hrasko <ihrasko@cisco.com>
Thu, 28 Jul 2016 13:16:01 +0000 (15:16 +0200)
committerIvan Hrasko <ihrasko@cisco.com>
Wed, 3 Aug 2016 13:14:53 +0000 (13:14 +0000)
- 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 <ihrasko@cisco.com>
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java [new file with mode: 0644]

index 56e9b57408ca6dd91a3e42b7aabdc849263850f2..a6187f5fa39f022513afaddf85a232315791db74 100644 (file)
@@ -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 {
index d23f6927234599d1c9d4d4f08048e729c7c5220d..53c19c5fe96fce213f6a983f777b5c43733ea8d9 100644 (file)
@@ -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<Void, TransactionCommitFailedException> 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<Void, TransactionCommitFailedException> 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();
     }
 }
index 5a762ebb7b2878fccaaa3addcb780c31145d2b7d..778acd9734df942d004e55a8c8c67c37ec4966a9 100644 (file)
@@ -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<Boolean> 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 (file)
index 0000000..f867ab1
--- /dev/null
@@ -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