Add RestconfServer.dataDELETE() 11/109011/2
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 17 Nov 2023 18:22:45 +0000 (19:22 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sat, 18 Nov 2023 08:00:58 +0000 (09:00 +0100)
Add a the delete operation and move its implementation into
RestconfImpl. Also unify test mocking.

JIRA: NETCONF-773
Change-Id: Iecbe8219fdd72266b78e466859b593ff341f177b
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/MdsalRestconfServer.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfImpl.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/api/RestconfServer.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/AbstractRestconfTest.java [new file with mode: 0644]
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/Netconf822Test.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataDeleteTest.java [new file with mode: 0644]
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataGetTest.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImplTest.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfOperationsGetTest.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfOperationsPostTest.java

index a55aaf2f7e68cf44ebdce9c0ddc1b6db98140af9..ef896539cb498eae32464e7842472366c990e133 100644 (file)
@@ -63,6 +63,7 @@ import org.opendaylight.restconf.server.spi.RpcImplementation;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev170126.YangApi;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev170126.restconf.Restconf;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.YangLibrary;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -136,6 +137,13 @@ public final class MdsalRestconfServer implements RestconfServer {
         this(databindProvider, dataBroker, rpcService, actionService, mountPointService, List.of(localRpcs));
     }
 
+    @Override
+    public RestconfFuture<Empty> dataDELETE(final String identifier) {
+        final var reqPath = bindRequestPath(identifier);
+        final var strategy = getRestconfStrategy(reqPath.getSchemaContext(), reqPath.getMountPoint());
+        return strategy.delete(reqPath.getInstanceIdentifier());
+    }
+
     @Override
     public RestconfFuture<NormalizedNodePayload> dataGET(final ReadDataParams readParams) {
         return readData(bindRequestRoot(), readParams);
index 8d2c466f2ab4204a47a9d3611468febe4287e709..16621c130d0b4416a05369de1074ccfafb1c871c 100644 (file)
@@ -15,7 +15,6 @@ import java.io.InputStream;
 import java.net.URI;
 import java.util.List;
 import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
 import javax.ws.rs.Encoded;
 import javax.ws.rs.PATCH;
 import javax.ws.rs.POST;
@@ -338,27 +337,6 @@ public final class RestconfDataServiceImpl {
         return uriInfo.getBaseUriBuilder().path("data").path(IdentifierCodec.serialize(path, schemaContext)).build();
     }
 
-    /**
-     * Delete the target data resource.
-     *
-     * @param identifier path to target
-     * @param ar {@link AsyncResponse} which needs to be completed
-     */
-    @DELETE
-    @Path("/data/{identifier:.+}")
-    public void deleteData(@Encoded @PathParam("identifier") final String identifier,
-            @Suspended final AsyncResponse ar) {
-        final var reqPath = server.bindRequestPath(identifier);
-        final var strategy = server.getRestconfStrategy(reqPath.getSchemaContext(), reqPath.getMountPoint());
-
-        strategy.delete(reqPath.getInstanceIdentifier()).addCallback(new JaxRsRestconfCallback<>(ar) {
-            @Override
-            Response transform(final Empty result) {
-                return Response.noContent().build();
-            }
-        });
-    }
-
     /**
      * Partially modify the target data store, as defined in
      * <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.6.1">RFC8040, section 4.6.1</a>.
index 4ed09bf55c1dafc099845bbb7784ae7797752097..f51abaa36888b08de51072ce688e692d1f1d661d 100644 (file)
@@ -14,6 +14,7 @@ import java.time.Clock;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.Encoded;
 import javax.ws.rs.GET;
 import javax.ws.rs.NotFoundException;
@@ -38,7 +39,9 @@ import org.opendaylight.restconf.nb.rfc8040.databind.XmlOperationInputBody;
 import org.opendaylight.restconf.nb.rfc8040.databind.jaxrs.QueryParams;
 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
 import org.opendaylight.restconf.server.api.OperationsContent;
+import org.opendaylight.restconf.server.api.RestconfServer;
 import org.opendaylight.restconf.server.spi.OperationOutput;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.Revision;
 
 /**
@@ -48,12 +51,31 @@ import org.opendaylight.yangtools.yang.common.Revision;
 public final class RestconfImpl {
     private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm:ss");
 
-    private final MdsalRestconfServer server;
+    private final RestconfServer server;
 
-    public RestconfImpl(final MdsalRestconfServer server) {
+    public RestconfImpl(final RestconfServer server) {
         this.server = requireNonNull(server);
     }
 
+    /**
+     * Delete the target data resource.
+     *
+     * @param identifier path to target
+     * @param ar {@link AsyncResponse} which needs to be completed
+     */
+    @DELETE
+    @Path("/data/{identifier:.+}")
+    @SuppressWarnings("checkstyle:abbreviationAsWordInName")
+    public void dataDELETE(@Encoded @PathParam("identifier") final String identifier,
+            @Suspended final AsyncResponse ar) {
+        server.dataDELETE(identifier).addCallback(new JaxRsRestconfCallback<>(ar) {
+            @Override
+            Response transform(final Empty result) {
+                return Response.noContent().build();
+            }
+        });
+    }
+
     /**
      * Get target data resource from data root.
      *
index ac3b1479eb7fcac838c2091f7482a9cb3a91f270..4c266dd4673bb11723c7791ae67f47df13f85965 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.restconf.nb.rfc8040.ReadDataParams;
 import org.opendaylight.restconf.nb.rfc8040.databind.OperationInputBody;
 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
 import org.opendaylight.restconf.server.spi.OperationOutput;
+import org.opendaylight.yangtools.yang.common.Empty;
 
 /**
  * An implementation of a RESTCONF server, implementing the
@@ -23,6 +24,15 @@ import org.opendaylight.restconf.server.spi.OperationOutput;
  */
 @NonNullByDefault
 public interface RestconfServer {
+    /**
+     * Delete a data resource.
+     *
+     * @param identifier resource identifier
+     * @return A {@link RestconfFuture} of the operation
+     */
+    @SuppressWarnings("checkstyle:abbreviationAsWordInName")
+    RestconfFuture<Empty> dataDELETE(String identifier);
+
     /**
      * Return the content of the datastore.
      *
@@ -32,7 +42,7 @@ public interface RestconfServer {
     RestconfFuture<NormalizedNodePayload> dataGET(ReadDataParams readParams);
 
     /**
-     * Return the content of a resource.
+     * Return the content of a data resource.
      *
      * @param identifier resource identifier
      * @param readParams {@link ReadDataParams} for this request
diff --git a/restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/AbstractRestconfTest.java b/restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/AbstractRestconfTest.java
new file mode 100644 (file)
index 0000000..bc172c2
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.nb.rfc8040.rests.services.impl;
+
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import org.eclipse.jdt.annotation.NonNull;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.opendaylight.mdsal.dom.api.DOMActionService;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMMountPoint;
+import org.opendaylight.mdsal.dom.api.DOMMountPointService;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
+import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+
+@ExtendWith(MockitoExtension.class)
+abstract class AbstractRestconfTest extends AbstractJukeboxTest {
+    @Mock
+    UriInfo uriInfo;
+    @Mock
+    AsyncResponse asyncResponse;
+    @Mock
+    DOMDataBroker dataBroker;
+    @Mock
+    DOMActionService actionService;
+    @Mock
+    DOMRpcService rpcService;
+    @Mock
+    DOMMountPointService mountPointService;
+    @Mock
+    DOMMountPoint mountPoint;
+    @Captor
+    ArgumentCaptor<Response> responseCaptor;
+    @Captor
+    ArgumentCaptor<RestconfDocumentedException> exceptionCaptor;
+
+    MdsalRestconfServer server;
+    RestconfImpl restconf;
+
+    @BeforeEach
+    final void setupRestconf() {
+        server = new MdsalRestconfServer(() -> DatabindContext.ofModel(modelContext()), dataBroker, rpcService,
+            actionService, mountPointService);
+        restconf = new RestconfImpl(server);
+    }
+
+    @NonNull EffectiveModelContext modelContext() {
+        return JUKEBOX_SCHEMA;
+    }
+}
index 8961860380c3e9f90b00034a8cfd9be7d4c52af3..fbf4beaa23724360608a8447baaa4a816fd3be48 100644 (file)
@@ -11,37 +11,20 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import org.eclipse.jdt.annotation.NonNull;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
-import org.opendaylight.mdsal.dom.api.DOMActionService;
-import org.opendaylight.mdsal.dom.api.DOMDataBroker;
-import org.opendaylight.mdsal.dom.api.DOMMountPointService;
-import org.opendaylight.mdsal.dom.api.DOMRpcService;
-import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 
 @ExtendWith(MockitoExtension.class)
-class Netconf822Test {
-    private static final @NonNull DatabindContext DATABIND =
-        DatabindContext.ofModel(YangParserTestUtils.parseYangResourceDirectory("/nc822"));
+class Netconf822Test extends AbstractRestconfTest {
+    private static final @NonNull EffectiveModelContext MODEL_CONTEXT =
+        YangParserTestUtils.parseYangResourceDirectory("/nc822");
 
-    @Mock
-    private DOMDataBroker dataBroker;
-    @Mock
-    private DOMRpcService rpcService;
-    @Mock
-    private DOMActionService actionService;
-    @Mock
-    private DOMMountPointService mountPointService;
-
-    private MdsalRestconfServer server;
-
-    @BeforeEach
-    void beforeEach() {
-        server = new MdsalRestconfServer(() -> DATABIND, dataBroker, rpcService, actionService, mountPointService);
+    @Override
+    @NonNull EffectiveModelContext modelContext() {
+        return MODEL_CONTEXT;
     }
 
     @Test
diff --git a/restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataDeleteTest.java b/restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataDeleteTest.java
new file mode 100644 (file)
index 0000000..68b121a
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.nb.rfc8040.rests.services.impl;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
+import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
+
+import java.util.Optional;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
+import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
+import org.opendaylight.yangtools.yang.common.ErrorTag;
+import org.opendaylight.yangtools.yang.common.ErrorType;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+@ExtendWith(MockitoExtension.class)
+class RestconfDataDeleteTest extends AbstractRestconfTest {
+    @Mock
+    private DOMDataTreeReadWriteTransaction tx;
+
+    @BeforeEach
+    void beforeEach() {
+        doReturn(tx).when(dataBroker).newReadWriteTransaction();
+    }
+
+    @Test
+    public void testDeleteData() {
+        doNothing().when(tx).delete(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
+        doReturn(immediateTrueFluentFuture())
+                .when(tx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
+        doReturn(CommitInfo.emptyFluentFuture()).when(tx).commit();
+        doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
+        restconf.dataDELETE("example-jukebox:jukebox", asyncResponse);
+
+        assertEquals(204, responseCaptor.getValue().getStatus());
+    }
+
+    @Test
+    public void testDeleteDataNotExisting() {
+        doReturn(immediateFalseFluentFuture())
+                .when(tx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
+        doReturn(true).when(tx).cancel();
+
+        doReturn(true).when(asyncResponse).resume(exceptionCaptor.capture());
+        restconf.dataDELETE("example-jukebox:jukebox", asyncResponse);
+
+        final var errors = exceptionCaptor.getValue().getErrors();
+        assertEquals(1, errors.size());
+        final var error = errors.get(0);
+        assertEquals(ErrorType.PROTOCOL, error.getErrorType());
+        assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
+    }
+
+    /**
+     * Test of deleting data on mount point.
+     */
+    @Test
+    public void testDeleteDataMountPoint() {
+        doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(any(YangInstanceIdentifier.class));
+        doReturn(Optional.of(FixedDOMSchemaService.of(JUKEBOX_SCHEMA))).when(mountPoint)
+            .getService(DOMSchemaService.class);
+        doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
+        doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
+        doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
+
+        doNothing().when(tx).delete(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
+        doReturn(immediateTrueFluentFuture())
+                .when(tx).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
+        doReturn(CommitInfo.emptyFluentFuture()).when(tx).commit();
+        doReturn(true).when(asyncResponse).resume(responseCaptor.capture());
+        restconf.dataDELETE("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", asyncResponse);
+
+        assertEquals(204, responseCaptor.getValue().getStatus());
+    }
+}
index 215d8097481c4868bc13d1f8d94071a01807031d..b8155a397c1912f4c1b4da85faaed0ca9af72f37 100644 (file)
@@ -17,30 +17,19 @@ import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediate
 
 import java.util.List;
 import java.util.Optional;
-import javax.ws.rs.container.AsyncResponse;
 import javax.ws.rs.core.MultivaluedHashMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
-import org.opendaylight.mdsal.dom.api.DOMActionService;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
-import org.opendaylight.mdsal.dom.api.DOMMountPoint;
-import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.mdsal.dom.api.DOMRpcService;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
-import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
-import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
-import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
@@ -52,7 +41,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 @ExtendWith(MockitoExtension.class)
-class RestconfDataGetTest extends AbstractJukeboxTest {
+class RestconfDataGetTest extends AbstractRestconfTest {
     private static final NodeIdentifier PLAYLIST_NID = new NodeIdentifier(PLAYLIST_QNAME);
     private static final NodeIdentifier LIBRARY_NID = new NodeIdentifier(LIBRARY_QNAME);
 
@@ -69,33 +58,11 @@ class RestconfDataGetTest extends AbstractJukeboxTest {
             .withChild(Builders.mapBuilder().withNodeIdentifier(PLAYLIST_NID).build())
             .build();
 
-    @Mock
-    private UriInfo uriInfo;
-    @Mock
-    private AsyncResponse asyncResponse;
-    @Mock
-    private DOMDataBroker dataBroker;
-    @Mock
-    private DOMActionService actionService;
-    @Mock
-    private DOMRpcService rpcService;
-    @Mock
-    private DOMMountPointService mountPointService;
     @Mock
     private DOMDataTreeReadTransaction tx;
-    @Mock
-    private DOMMountPoint mountPoint;
-    @Captor
-    private ArgumentCaptor<Response> responseCaptor;
-    @Captor
-    private ArgumentCaptor<RestconfDocumentedException> exceptionCaptor;
-
-    private RestconfImpl restconf;
 
     @BeforeEach
     void beforeEach() {
-        restconf = new RestconfImpl(new MdsalRestconfServer(() -> DatabindContext.ofModel(JUKEBOX_SCHEMA), dataBroker,
-            rpcService, actionService, mountPointService));
         doReturn(tx).when(dataBroker).newReadOnlyTransaction();
     }
 
index 74d187a990a300e9fe068f7890afc89430563420..f544f9547c20c00a2a9af75eaabb477419594068 100644 (file)
@@ -51,7 +51,6 @@ import org.opendaylight.mdsal.dom.api.DOMRpcService;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
-import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.common.patch.PatchContext;
 import org.opendaylight.restconf.common.patch.PatchEntity;
 import org.opendaylight.restconf.common.patch.PatchStatusContext;
@@ -59,8 +58,6 @@ import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
 import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
 import org.opendaylight.restconf.nb.rfc8040.databind.DatabindProvider;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.patch.rev170222.yang.patch.yang.patch.Edit.Operation;
-import org.opendaylight.yangtools.yang.common.ErrorTag;
-import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
@@ -203,48 +200,6 @@ public class RestconfDataServiceImplTest extends AbstractJukeboxTest {
             response.getLocation());
     }
 
-    @Test
-    public void testDeleteData() {
-        doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
-        doReturn(immediateTrueFluentFuture())
-                .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
-        final var captor = ArgumentCaptor.forClass(Response.class);
-        doReturn(true).when(asyncResponse).resume(captor.capture());
-        dataService.deleteData("example-jukebox:jukebox", asyncResponse);
-
-        assertEquals(204, captor.getValue().getStatus());
-    }
-
-    @Test
-    public void testDeleteDataNotExisting() {
-        doReturn(immediateFalseFluentFuture())
-                .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
-        final var captor = ArgumentCaptor.forClass(RestconfDocumentedException.class);
-        doReturn(true).when(asyncResponse).resume(captor.capture());
-        dataService.deleteData("example-jukebox:jukebox", asyncResponse);
-
-        final var errors = captor.getValue().getErrors();
-        assertEquals(1, errors.size());
-        final var error = errors.get(0);
-        assertEquals(ErrorType.PROTOCOL, error.getErrorType());
-        assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
-    }
-
-    /**
-     * Test of deleting data on mount point.
-     */
-    @Test
-    public void testDeleteDataMountPoint() {
-        doNothing().when(readWrite).delete(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
-        doReturn(immediateTrueFluentFuture())
-                .when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
-        final var captor = ArgumentCaptor.forClass(Response.class);
-        doReturn(true).when(asyncResponse).resume(captor.capture());
-        dataService.deleteData("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", asyncResponse);
-
-        assertEquals(204, captor.getValue().getStatus());
-    }
-
     @Test
     public void testPatchData() {
         final var patch = new PatchContext("test patch id", List.of(
index 6d5b2e4b61ec381ca95f390d0c7ba6c862278dfd..3bf40c1fa400bd31673756d705ac72ccf7165793 100644 (file)
@@ -12,25 +12,19 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 
 import java.util.Optional;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers;
-import org.opendaylight.mdsal.dom.api.DOMActionService;
-import org.opendaylight.mdsal.dom.api.DOMDataBroker;
-import org.opendaylight.mdsal.dom.api.DOMMountPoint;
-import org.opendaylight.mdsal.dom.api.DOMMountPointService;
-import org.opendaylight.mdsal.dom.api.DOMRpcService;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
-import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
 import org.opendaylight.yang.gen.v1.module._1.rev140101.Module1Data;
 import org.opendaylight.yang.gen.v1.module._2.rev140102.Module2Data;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 
 @ExtendWith(MockitoExtension.class)
-class RestconfOperationsGetTest {
+class RestconfOperationsGetTest extends AbstractRestconfTest {
     private static final String DEVICE_ID = "network-topology:network-topology/topology=topology-netconf/"
         + "node=device/yang-ext:mount";
     private static final String DEVICE_RPC1_MODULE1_ID = DEVICE_ID + "module1:dummy-rpc1-module1";
@@ -51,28 +45,15 @@ class RestconfOperationsGetTest {
           <dummy-rpc2-module2 xmlns="module:2"/>
         </operations>""";
 
-    private static final DatabindContext DATABIND = DatabindContext.ofModel(BindingRuntimeHelpers.createRuntimeContext(
-        Module1Data.class, Module2Data.class, NetworkTopology.class).getEffectiveModelContext());
+    private static final EffectiveModelContext MODEL_CONTEXT = BindingRuntimeHelpers.createRuntimeContext(
+        Module1Data.class, Module2Data.class, NetworkTopology.class).getEffectiveModelContext();
 
-    @Mock
-    private DOMMountPointService mountPointService;
-    @Mock
-    private DOMMountPoint mountPoint;
     @Mock
     private DOMSchemaService schemaService;
-    @Mock
-    private DOMDataBroker dataBroker;
-    @Mock
-    private DOMRpcService rpcService;
-    @Mock
-    private DOMActionService actionService;
-
-    private RestconfImpl restconf;
 
-    @BeforeEach
-    void beforeEach() {
-        restconf = new RestconfImpl(
-            new MdsalRestconfServer(() -> DATABIND, dataBroker, rpcService, actionService, mountPointService));
+    @Override
+    EffectiveModelContext modelContext() {
+        return MODEL_CONTEXT;
     }
 
     @Test
@@ -88,7 +69,7 @@ class RestconfOperationsGetTest {
     }
 
     private void mockMountPoint() {
-        doReturn(DATABIND.modelContext()).when(schemaService).getGlobalContext();
+        doReturn(MODEL_CONTEXT).when(schemaService).getGlobalContext();
         doReturn(Optional.of(schemaService)).when(mountPoint).getService(DOMSchemaService.class);
         doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(any());
     }
index 6a91904d7ff0579869d9e1ada4ae0a6d1772a8f0..1868f618dcfa5604f36e2140b7aa650e9e486efb 100644 (file)
@@ -27,16 +27,12 @@ import java.util.concurrent.ExecutionException;
 import javax.ws.rs.container.AsyncResponse;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
-import org.opendaylight.mdsal.dom.api.DOMActionService;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
-import org.opendaylight.mdsal.dom.api.DOMMountPoint;
-import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.mdsal.dom.api.DOMNotificationService;
 import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException;
 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
@@ -54,12 +50,13 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 
 @ExtendWith(MockitoExtension.class)
-class RestconfOperationsPostTest {
+class RestconfOperationsPostTest extends AbstractRestconfTest {
     private static final URI RESTCONF_URI = URI.create("/restconf");
     private static final QName RPC = QName.create("invoke:rpc:module", "2013-12-03", "rpc-test");
     private static final ContainerNode INPUT = Builders.containerBuilder()
@@ -70,31 +67,17 @@ class RestconfOperationsPostTest {
         .withNodeIdentifier(new NodeIdentifier(QName.create(RPC, "output")))
         .withChild(ImmutableNodes.leafNode(QName.create(RPC, "content"), "operation result"))
         .build();
-    private static final DatabindContext CONTEXT =
-        DatabindContext.ofModel(YangParserTestUtils.parseYangResourceDirectory("/invoke-rpc"));
-    private static final OperationInput OPER_INPUT = new OperationInput(CONTEXT,
-            SchemaInferenceStack.of(CONTEXT.modelContext(), Absolute.of(RPC)).toInference(), INPUT);
+    private static final EffectiveModelContext MODEL_CONTEXT =
+        YangParserTestUtils.parseYangResourceDirectory("/invoke-rpc");
+    private static final OperationInput OPER_INPUT = new OperationInput(DatabindContext.ofModel(MODEL_CONTEXT),
+            SchemaInferenceStack.of(MODEL_CONTEXT, Absolute.of(RPC)).toInference(), INPUT);
 
-    @Mock
-    private DOMDataBroker dataBroker;
-    @Mock
-    private DOMRpcService rpcService;
-    @Mock
-    private DOMActionService actionService;
-    @Mock
-    private DOMMountPoint mountPoint;
-    @Mock
-    private DOMMountPointService mountPointService;
     @Mock
     private DOMNotificationService notificationService;
 
-    private RestconfImpl restconf;
-    private MdsalRestconfServer server;
-
-    @BeforeEach
-    void beforeEach() {
-        server = new MdsalRestconfServer(() -> CONTEXT, dataBroker, rpcService, actionService, mountPointService);
-        restconf = new RestconfImpl(server);
+    @Override
+    EffectiveModelContext modelContext() {
+        return MODEL_CONTEXT;
     }
 
     @Test
@@ -140,8 +123,7 @@ class RestconfOperationsPostTest {
         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of()))).when(rpcService)
             .invokeRpc(RPC, INPUT);
         assertEquals(OUTPUT,
-            Futures.getDone(
-                server.getRestconfStrategy(CONTEXT.modelContext(), null).invokeRpc(RESTCONF_URI, RPC, OPER_INPUT))
+            Futures.getDone(server.getRestconfStrategy(MODEL_CONTEXT, null).invokeRpc(RESTCONF_URI, RPC, OPER_INPUT))
             .output());
     }
 
@@ -153,7 +135,7 @@ class RestconfOperationsPostTest {
         doReturn(Futures.immediateFailedFuture(exception)).when(rpcService).invokeRpc(errorRpc, INPUT);
         final var ex = assertInstanceOf(RestconfDocumentedException.class,
             assertThrows(ExecutionException.class,
-                () -> Futures.getDone(server.getRestconfStrategy(CONTEXT.modelContext(), null)
+                () -> Futures.getDone(server.getRestconfStrategy(MODEL_CONTEXT, null)
                     .invokeRpc(RESTCONF_URI, errorRpc, OPER_INPUT))).getCause());
         final var errorList = ex.getErrors();
         assertEquals(1, errorList.size());
@@ -172,7 +154,7 @@ class RestconfOperationsPostTest {
             .invokeRpc(RPC, INPUT);
         assertEquals(OUTPUT,
             Futures.getDone(
-                server.getRestconfStrategy(CONTEXT.modelContext(), mountPoint).invokeRpc(RESTCONF_URI, RPC, OPER_INPUT))
+                server.getRestconfStrategy(MODEL_CONTEXT, mountPoint).invokeRpc(RESTCONF_URI, RPC, OPER_INPUT))
             .output());
     }
 
@@ -181,7 +163,7 @@ class RestconfOperationsPostTest {
         doReturn(Optional.empty()).when(mountPoint).getService(DOMRpcService.class);
         doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
         doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
-        final var strategy = server.getRestconfStrategy(CONTEXT.modelContext(), mountPoint);
+        final var strategy = server.getRestconfStrategy(MODEL_CONTEXT, mountPoint);
         final var ex = assertInstanceOf(RestconfDocumentedException.class,
             assertThrows(ExecutionException.class,
                 () -> Futures.getDone(strategy.invokeRpc(RESTCONF_URI, RPC, OPER_INPUT))).getCause());
@@ -198,8 +180,7 @@ class RestconfOperationsPostTest {
         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult(OUTPUT, List.of())))
             .when(rpcService).invokeRpc(RPC, INPUT);
         assertEquals(OUTPUT,
-            Futures.getDone(server.getRestconfStrategy(CONTEXT.modelContext(), null)
-                .invokeRpc(RESTCONF_URI, RPC, OPER_INPUT))
+            Futures.getDone(server.getRestconfStrategy(MODEL_CONTEXT, null).invokeRpc(RESTCONF_URI, RPC, OPER_INPUT))
             .output());
     }