Update new SDNR actor with v2.0 structures 70/104170/2
authorJim Hahn <jrh3@att.com>
Mon, 23 Mar 2020 15:36:09 +0000 (11:36 -0400)
committerJim Hahn <jrh3@att.com>
Mon, 23 Mar 2020 16:19:00 +0000 (12:19 -0400)
SDNR v2.0 introduced an extra "input" and "output" layer within
the body of the messages.  Added POJOs to match that, and updated
the actor to use the new POJOs so that no extra steps are needed
during serialization or deserialization.
Also modified the SDNR and APPC-LCM simulators to discard request messages
when looking for the response, if the sink and source topics happen to
be the same.
Added the SDNR simulator.
Added more coverage to the SDNR actor.
Fixed a sonar issue in the SDNR junit code:
- use a constant instead of a literal (i.e., for "ModifyConfig")

Issue-ID: POLICY-2434
Signed-off-by: Jim Hahn <jrh3@att.com>
Change-Id: I70914a299dd5e9ee8eaccb5d42a2596cab814091

15 files changed:
models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/ModifyConfigOperation.java
models-interactions/model-actors/actor.sdnr/src/main/java/org/onap/policy/controlloop/actor/sdnr/SdnrOperation.java
models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/BasicSdnrOperation.java
models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/ModifyConfigOperationTest.java
models-interactions/model-actors/actor.sdnr/src/test/java/org/onap/policy/controlloop/actor/sdnr/SdnrOperationTest.java
models-interactions/model-impl/sdnr/src/main/java/org/onap/policy/sdnr/PciBody.java [new file with mode: 0644]
models-interactions/model-impl/sdnr/src/main/java/org/onap/policy/sdnr/PciMessage.java [new file with mode: 0644]
models-interactions/model-simulators/pom.xml
models-interactions/model-simulators/src/main/java/org/onap/policy/simulators/AppcLcmTopicServer.java
models-interactions/model-simulators/src/main/java/org/onap/policy/simulators/SdnrTopicServer.java [new file with mode: 0644]
models-interactions/model-simulators/src/main/resources/org/onap/policy/simulators/sdnr/vpci.sdnr.success.json [new file with mode: 0644]
models-interactions/model-simulators/src/test/java/org/onap/policy/simulators/AppcLcmTopicServerTest.java
models-interactions/model-simulators/src/test/java/org/onap/policy/simulators/SdnrTopicServerTest.java [new file with mode: 0644]
models-interactions/model-simulators/src/test/resources/org/onap/policy/simulators/sdnr/vpci.sdnr.request.json [new file with mode: 0644]
models-sim/policy-models-simulators/src/test/resources/simParameters.json

index 21f1562..a5193ec 100644 (file)
@@ -23,7 +23,7 @@ package org.onap.policy.controlloop.actor.sdnr;
 import org.apache.commons.lang3.tuple.Pair;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
-import org.onap.policy.sdnr.PciRequestWrapper;
+import org.onap.policy.sdnr.PciMessage;
 
 public class ModifyConfigOperation extends SdnrOperation {
     public static final String NAME = "ModifyConfig";
@@ -39,14 +39,14 @@ public class ModifyConfigOperation extends SdnrOperation {
     }
 
     @Override
-    protected Pair<String, PciRequestWrapper> makeRequest(int attempt) {
-        final Pair<String, PciRequestWrapper> req = super.makeRequest(attempt);
-        final PciRequestWrapper request = req.getRight();
+    protected Pair<String, PciMessage> makeRequest(int attempt) {
+        final Pair<String, PciMessage> req = super.makeRequest(attempt);
+        final PciMessage request = req.getRight();
         //
         // Set the recipe and action information
         //
         request.setRpcName(NAME.toLowerCase());
-        request.getBody().setAction(NAME);
+        request.getBody().getInput().setAction(NAME);
         return req;
     }
 }
index b11c701..de498e6 100644 (file)
@@ -31,37 +31,38 @@ import org.onap.policy.controlloop.actorserviceprovider.parameters.Bidirectional
 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
 import org.onap.policy.controlloop.actorserviceprovider.topic.SelectorKey;
 import org.onap.policy.controlloop.policy.PolicyResult;
+import org.onap.policy.sdnr.PciBody;
 import org.onap.policy.sdnr.PciCommonHeader;
+import org.onap.policy.sdnr.PciMessage;
 import org.onap.policy.sdnr.PciRequest;
-import org.onap.policy.sdnr.PciRequestWrapper;
 import org.onap.policy.sdnr.PciResponse;
-import org.onap.policy.sdnr.PciResponseWrapper;
 import org.onap.policy.sdnr.util.StatusCodeEnum;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class SdnrOperation extends BidirectionalTopicOperation<PciRequestWrapper, PciResponseWrapper> {
+public abstract class SdnrOperation extends BidirectionalTopicOperation<PciMessage, PciMessage> {
     private static final Logger logger = LoggerFactory.getLogger(SdnrOperation.class);
 
     /**
      * Keys used to match the response with the request listener. The sub request ID is a
      * UUID, so it can be used to uniquely identify the response.
      * <p/>
-     * Note: if these change, then {@link #getExpectedKeyValues(int, Request)} must be
+     * Note: if these change, then {@link #getExpectedKeyValues(int, PciMessage)} must be
      * updated accordingly.
      */
-    public static final List<SelectorKey> SELECTOR_KEYS = List.of(new SelectorKey("CommonHeader", "SubRequestID"));
+    public static final List<SelectorKey> SELECTOR_KEYS =
+                    List.of(new SelectorKey("body", "output", "CommonHeader", "SubRequestID"));
 
     public SdnrOperation(ControlLoopOperationParams params, BidirectionalTopicConfig config) {
-        super(params, config, PciResponseWrapper.class);
+        super(params, config, PciMessage.class);
     }
 
     /**
-     * Note: these values must match {@link #SELECTOR_KEYS}.
+     * Note: these values must be in correspondence with {@link #SELECTOR_KEYS}.
      */
     @Override
-    protected List<String> getExpectedKeyValues(int attempt, PciRequestWrapper request) {
-        return List.of(request.getBody().getCommonHeader().getSubRequestId());
+    protected List<String> getExpectedKeyValues(int attempt, PciMessage request) {
+        return List.of(request.getBody().getInput().getCommonHeader().getSubRequestId());
     }
 
     @Override
@@ -70,18 +71,17 @@ public abstract class SdnrOperation extends BidirectionalTopicOperation<PciReque
     }
 
     @Override
-    protected Status detmStatus(String rawResponse, PciResponseWrapper responseWrapper) {
-        PciResponse response = responseWrapper.getBody();
+    protected Status detmStatus(String rawResponse, PciMessage responseWrapper) {
+        PciResponse response = responseWrapper.getBody().getOutput();
 
-        if (response == null || response.getStatus() == null) {
+        if (response.getStatus() == null) {
             throw new IllegalArgumentException("SDNR response is missing the response status");
         }
 
         StatusCodeEnum code = StatusCodeEnum.fromStatusCode(response.getStatus().getCode());
 
         if (code == null) {
-            throw new IllegalArgumentException(
-                            "unknown SDNR response status code: " + response.getStatus().getCode());
+            throw new IllegalArgumentException("unknown SDNR response status code: " + response.getStatus().getCode());
         }
 
         /*
@@ -112,9 +112,12 @@ public abstract class SdnrOperation extends BidirectionalTopicOperation<PciReque
      * Sets the message to the status description, if available.
      */
     @Override
-    public OperationOutcome setOutcome(OperationOutcome outcome, PolicyResult result,
-            PciResponseWrapper responseWrapper) {
-        PciResponse response = responseWrapper.getBody();
+    public OperationOutcome setOutcome(OperationOutcome outcome, PolicyResult result, PciMessage responseWrapper) {
+        if (responseWrapper.getBody() == null || responseWrapper.getBody().getOutput() == null) {
+            return setOutcome(outcome, result);
+        }
+
+        PciResponse response = responseWrapper.getBody().getOutput();
         if (response.getStatus() == null || response.getStatus().getValue() == null) {
             return setOutcome(outcome, result);
         }
@@ -125,17 +128,13 @@ public abstract class SdnrOperation extends BidirectionalTopicOperation<PciReque
     }
 
     @Override
-    protected Pair<String, PciRequestWrapper> makeRequest(int attempt) {
+    protected Pair<String, PciMessage> makeRequest(int attempt) {
         VirtualControlLoopEvent onset = params.getContext().getEvent();
         String subRequestId = UUID.randomUUID().toString();
 
         /* Construct an SDNR request using pci Model */
 
-        /*
-         * The actual pci request is placed in a wrapper used to send through dmaap. The
-         * current version is 2.0 as of R1.
-         */
-        PciRequestWrapper dmaapRequest = new PciRequestWrapper();
+        PciMessage dmaapRequest = new PciMessage();
         dmaapRequest.setVersion("1.0");
         dmaapRequest.setCorrelationId(onset.getRequestId() + "-" + subRequestId);
         dmaapRequest.setType("request");
@@ -152,10 +151,11 @@ public abstract class SdnrOperation extends BidirectionalTopicOperation<PciReque
         sdnrRequest.setPayload(onset.getPayload());
 
         /*
-         * Once the pci request is constructed, add it into the body of the dmaap
-         * wrapper.
+         * Once the pci request is constructed, add it into the body of the dmaap wrapper.
          */
-        dmaapRequest.setBody(sdnrRequest);
+        PciBody body = new PciBody();
+        body.setInput(sdnrRequest);
+        dmaapRequest.setBody(body);
         logger.info("SDNR Request to be sent is {}", dmaapRequest);
 
         /* Return the request to be sent through dmaap. */
index 0aea35f..27d7d43 100644 (file)
@@ -38,15 +38,16 @@ import org.onap.policy.controlloop.actorserviceprovider.Util;
 import org.onap.policy.controlloop.actorserviceprovider.impl.OperationMaker;
 import org.onap.policy.controlloop.actorserviceprovider.parameters.BidirectionalTopicConfig;
 import org.onap.policy.controlloop.policy.PolicyResult;
+import org.onap.policy.sdnr.PciBody;
+import org.onap.policy.sdnr.PciMessage;
 import org.onap.policy.sdnr.PciResponse;
-import org.onap.policy.sdnr.PciResponseWrapper;
 import org.onap.policy.sdnr.Status;
 import org.onap.policy.sdnr.util.StatusCodeEnum;
 import org.powermock.reflect.Whitebox;
 
 public abstract class BasicSdnrOperation extends BasicBidirectionalTopicOperation {
 
-    protected PciResponseWrapper response;
+    protected PciMessage response;
 
     /**
      * Constructs the object using a default actor and operation name.
@@ -71,14 +72,18 @@ public abstract class BasicSdnrOperation extends BasicBidirectionalTopicOperatio
     public void setUp() throws Exception {
         super.setUpBasic();
 
-        response = new PciResponseWrapper();
+        response = new PciMessage();
+
+        PciBody body = new PciBody();
+        response.setBody(body);
+
+        PciResponse output = new PciResponse();
+        body.setOutput(output);
 
-        PciResponse body = new PciResponse();
         Status status = new Status();
+        output.setStatus(status);
         status.setCode(100);
         status.setValue(StatusCodeEnum.SUCCESS.toString());
-        body.setStatus(status);
-        response.setBody(body);
     }
 
     /**
index 19b2063..3165d58 100644 (file)
@@ -36,7 +36,7 @@ import org.onap.policy.common.utils.coder.CoderException;
 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 import org.onap.policy.controlloop.policy.PolicyResult;
-import org.onap.policy.sdnr.PciRequestWrapper;
+import org.onap.policy.sdnr.PciMessage;
 
 public class ModifyConfigOperationTest extends BasicSdnrOperation {
 
@@ -89,7 +89,7 @@ public class ModifyConfigOperationTest extends BasicSdnrOperation {
 
     @Test
     public void testMakeRequest() throws CoderException {
-        Pair<String, PciRequestWrapper> result = oper.makeRequest(1);
+        Pair<String, PciMessage> result = oper.makeRequest(1);
         assertNotNull(result.getLeft());
         assertNotNull(result.getRight());
     }
index a7bfa33..5f6a5df 100644 (file)
@@ -32,7 +32,7 @@ import org.junit.Test;
 import org.onap.policy.controlloop.actorserviceprovider.impl.BidirectionalTopicOperation.Status;
 import org.onap.policy.controlloop.policy.PolicyResult;
 import org.onap.policy.sdnr.PciCommonHeader;
-import org.onap.policy.sdnr.PciRequestWrapper;
+import org.onap.policy.sdnr.PciMessage;
 import org.onap.policy.sdnr.util.StatusCodeEnum;
 
 public class SdnrOperationTest extends BasicSdnrOperation {
@@ -57,37 +57,41 @@ public class SdnrOperationTest extends BasicSdnrOperation {
 
     @Test
     public void testMakeRequest() {
-        Pair<String, PciRequestWrapper> result = operation.makeRequest(1);
+        Pair<String, PciMessage> result = operation.makeRequest(1);
         assertNotNull(result.getLeft());
 
-        PciRequestWrapper request = result.getRight();
+        PciMessage request = result.getRight();
 
         assertNotNull(request.getBody());
         assertEquals("1.0", request.getVersion());
         assertEquals("request", request.getType());
 
-        PciCommonHeader header = request.getBody().getCommonHeader();
+        PciCommonHeader header = request.getBody().getInput().getCommonHeader();
         assertNotNull(header);
         assertEquals(params.getRequestId(), header.getRequestId());
     }
 
     @Test
     public void testGetExpectedKeyValues() {
-        PciRequestWrapper request = operation.makeRequest(1).getRight();
-        assertEquals(Arrays.asList(request.getBody().getCommonHeader().getSubRequestId()),
-                operation.getExpectedKeyValues(50, request));
+        PciMessage request = operation.makeRequest(1).getRight();
+        assertEquals(Arrays.asList(request.getBody().getInput().getCommonHeader().getSubRequestId()),
+                        operation.getExpectedKeyValues(50, request));
+    }
 
+    @Test
+    public void testStartPreprocessorAsync() {
+        assertNotNull(operation.startPreprocessorAsync());
     }
 
     @Test
     public void testDetmStatusStringResponse() {
-        final org.onap.policy.sdnr.Status status = response.getBody().getStatus();
+        final org.onap.policy.sdnr.Status status = response.getBody().getOutput().getStatus();
 
         // null status
-        response.getBody().setStatus(null);
+        response.getBody().getOutput().setStatus(null);
         assertThatIllegalArgumentException().isThrownBy(() -> operation.detmStatus("", response))
                         .withMessage("SDNR response is missing the response status");
-        response.getBody().setStatus(status);
+        response.getBody().getOutput().setStatus(status);
 
         // invalid code
         status.setCode(-45);
@@ -106,17 +110,17 @@ public class SdnrOperationTest extends BasicSdnrOperation {
         status.setValue(StatusCodeEnum.REJECT.toString());
         status.setCode(StatusCodeEnum.toValue(StatusCodeEnum.REJECT));
         assertThatIllegalArgumentException().isThrownBy(() -> operation.detmStatus("", response))
-            .withMessage("SDNR request was not accepted, code=" + StatusCodeEnum.REJECT.toString());
+                        .withMessage("SDNR request was not accepted, code=" + StatusCodeEnum.REJECT.toString());
 
         status.setValue(StatusCodeEnum.REJECT.toString());
         status.setCode(313);
         assertThatIllegalArgumentException().isThrownBy(() -> operation.detmStatus("", response))
-            .withMessage("SDNR request was not accepted, code=" + StatusCodeEnum.REJECT.toString());
+                        .withMessage("SDNR request was not accepted, code=" + StatusCodeEnum.REJECT.toString());
 
         status.setValue(StatusCodeEnum.ERROR.toString());
         status.setCode(StatusCodeEnum.toValue(StatusCodeEnum.ERROR));
         assertThatIllegalArgumentException().isThrownBy(() -> operation.detmStatus("", response))
-            .withMessage("SDNR request was not accepted, code=" + StatusCodeEnum.ERROR.toString());
+                        .withMessage("SDNR request was not accepted, code=" + StatusCodeEnum.ERROR.toString());
 
         status.setValue(StatusCodeEnum.FAILURE.toString());
         status.setCode(450);
@@ -125,14 +129,30 @@ public class SdnrOperationTest extends BasicSdnrOperation {
 
     @Test
     public void testSetOutcome() {
-        final org.onap.policy.sdnr.Status status = response.getBody().getStatus();
+        // with a status value
+        checkOutcome();
+        assertEquals(StatusCodeEnum.SUCCESS.toString(), outcome.getMessage());
+
+        // null status value
+        response.getBody().getOutput().getStatus().setValue(null);
+        checkOutcome();
 
         // null status
-        response.getBody().setStatus(null);
+        response.getBody().getOutput().setStatus(null);
+        checkOutcome();
+
+        // null output
+        response.getBody().setOutput(null);
+        checkOutcome();
+
+        // null body
+        response.setBody(null);
+        checkOutcome();
+    }
+
+    protected void checkOutcome() {
         assertSame(outcome, operation.setOutcome(outcome, PolicyResult.SUCCESS, response));
         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
         assertNotNull(outcome.getMessage());
-        response.getBody().setStatus(status);
-
     }
 }
diff --git a/models-interactions/model-impl/sdnr/src/main/java/org/onap/policy/sdnr/PciBody.java b/models-interactions/model-impl/sdnr/src/main/java/org/onap/policy/sdnr/PciBody.java
new file mode 100644 (file)
index 0000000..c264166
--- /dev/null
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.sdnr;
+
+import java.io.Serializable;
+import lombok.Data;
+
+@Data
+public class PciBody implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private PciRequest input;
+    private PciResponse output;
+}
diff --git a/models-interactions/model-impl/sdnr/src/main/java/org/onap/policy/sdnr/PciMessage.java b/models-interactions/model-impl/sdnr/src/main/java/org/onap/policy/sdnr/PciMessage.java
new file mode 100644 (file)
index 0000000..413de8d
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.sdnr;
+
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * Generic PCI message, which can contain a request or a response.
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class PciMessage extends PciWrapper implements Serializable {
+    private static final long serialVersionUID = 879766924715980798L;
+
+    private PciBody body;
+}
index d74aa05..d91d9cc 100644 (file)
             <artifactId>appclcm</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+            <artifactId>sdnc</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+            <artifactId>sdnr</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
             <artifactId>so</artifactId>
             <artifactId>gson</artifactId>
             <scope>provided</scope>
         </dependency>
-        <dependency>
-            <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
-            <artifactId>sdnc</artifactId>
-            <version>${project.version}</version>
-        </dependency>
         <dependency>
             <groupId>org.onap.policy.models</groupId>
             <artifactId>policy-models-decisions</artifactId>
index df4cbb3..6b2eabe 100644 (file)
@@ -36,6 +36,15 @@ public class AppcLcmTopicServer extends TopicServer<AppcLcmDmaapWrapper> {
 
     @Override
     protected String process(AppcLcmDmaapWrapper request) {
+        /*
+         * In case the request and response are on the same topic, this may be invoked
+         * with a request or with a response object. If the "output" is not null, then we
+         * know it's a response.
+         */
+        if (request.getBody().getOutput() != null) {
+            return null;
+        }
+
         String response = ResourceUtils.getResourceAsString("org/onap/policy/simulators/appclcm/appc.lcm.success.json");
         return response.replace("${replaceMe}", request.getBody().getInput().getCommonHeader().getSubRequestId());
     }
diff --git a/models-interactions/model-simulators/src/main/java/org/onap/policy/simulators/SdnrTopicServer.java b/models-interactions/model-simulators/src/main/java/org/onap/policy/simulators/SdnrTopicServer.java
new file mode 100644 (file)
index 0000000..043a2c5
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.simulators;
+
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.event.comm.TopicSource;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.sdnr.PciMessage;
+
+/**
+ * SDNR topic server.
+ */
+public class SdnrTopicServer extends TopicServer<PciMessage> {
+    public SdnrTopicServer(TopicSink sink, TopicSource source) {
+        super(sink, source, new StandardCoder(), PciMessage.class);
+    }
+
+    @Override
+    protected String process(PciMessage request) {
+        /*
+         * In case the request and response are on the same topic, this may be invoked
+         * with a request or with a response object. If the "output" is null, then we know
+         * it's a response.
+         */
+        if (request.getBody().getOutput() != null) {
+            return null;
+        }
+
+        String response = ResourceUtils.getResourceAsString("org/onap/policy/simulators/sdnr/vpci.sdnr.success.json");
+        return response.replace("${replaceMe}", request.getBody().getInput().getCommonHeader().getSubRequestId());
+    }
+}
diff --git a/models-interactions/model-simulators/src/main/resources/org/onap/policy/simulators/sdnr/vpci.sdnr.success.json b/models-interactions/model-simulators/src/main/resources/org/onap/policy/simulators/sdnr/vpci.sdnr.success.json
new file mode 100644 (file)
index 0000000..b9137d2
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    "body": {
+        "output": {
+            "CommonHeader": {
+                "TimeStamp": "2018-09-10T07:10:05.614Z",
+                "APIver": "1.0",
+                "RequestID": "9d2d790e-a5f0-11e8-98d0-529269fb1459",
+                "SubRequestID": "${replaceMe}",
+                "RequestTrack": [],
+                "Flags": []
+            },
+            "Status": {
+                "Code": 200,
+                "Value": "SUCCESS"
+            },
+            "Payload": "{ \"Configurations\":[ { \"Status\": { \"Code\": 200, \"Value\": \"SUCCESS\" }, \"data\":{\"FAPService\":{\"alias\":\"Chn0330\",\"X0005b9Lte\":{\"phyCellIdInUse\":6,\"pnfName\":\"ncserver23\"},\"CellConfig\":{\"LTE\":{\"RAN\":{\"Common\":{\"CellIdentity\":\"Chn0330\"}}}}}} } ] }"
+        }
+    },
+    "version": "1.0",
+    "rpc-name": "ModifyConfig",
+    "correlation-id": "9d2d790e-a5f0-11e8-98d0-529269fb1459-1",
+    "type": "response"
+}
index bc80315..f3f546a 100644 (file)
@@ -22,6 +22,8 @@ package org.onap.policy.simulators;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
 import org.junit.Before;
@@ -66,4 +68,18 @@ public class AppcLcmTopicServerTest {
 
         assertThat(respCaptor.getValue()).contains("111be3d2").doesNotContain("replaceMe");
     }
+
+    /**
+     * Tests process() when the message is a response.
+     */
+    @Test
+    public void testProcessNoResponse() {
+        // NOTE: this json file is a RESPONSE, not a request
+        String request = ResourceUtils.getResourceAsString("org/onap/policy/simulators/appclcm/appc.lcm.success.json");
+        assertNotNull(request);
+
+        server.onTopicEvent(CommInfrastructure.NOOP, MY_TOPIC, request);
+
+        verify(sink, never()).send(any());
+    }
 }
diff --git a/models-interactions/model-simulators/src/test/java/org/onap/policy/simulators/SdnrTopicServerTest.java b/models-interactions/model-simulators/src/test/java/org/onap/policy/simulators/SdnrTopicServerTest.java
new file mode 100644 (file)
index 0000000..d8f6d11
--- /dev/null
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.simulators;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.event.comm.TopicSource;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+
+public class SdnrTopicServerTest {
+    private static final String MY_TOPIC = "my-topic";
+
+    @Mock
+    private TopicSink sink;
+    @Mock
+    private TopicSource source;
+
+    private SdnrTopicServer server;
+
+    /**
+     * Sets up.
+     */
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        server = new SdnrTopicServer(sink, source);
+    }
+
+    @Test
+    public void testProcess() {
+        String request = ResourceUtils.getResourceAsString("org/onap/policy/simulators/sdnr/vpci.sdnr.request.json");
+        assertNotNull(request);
+
+        server.onTopicEvent(CommInfrastructure.NOOP, MY_TOPIC, request);
+
+        ArgumentCaptor<String> respCaptor = ArgumentCaptor.forClass(String.class);
+        verify(sink).send(respCaptor.capture());
+
+        assertThat(respCaptor.getValue()).contains("111be3d2").doesNotContain("replaceMe");
+    }
+
+    /**
+     * Tests process() when the message is a response.
+     */
+    @Test
+    public void testProcessNoResponse() {
+        // NOTE: this json file is a RESPONSE, not a request
+        String request = ResourceUtils.getResourceAsString("org/onap/policy/simulators/sdnr/vpci.sdnr.success.json");
+        assertNotNull(request);
+
+        server.onTopicEvent(CommInfrastructure.NOOP, MY_TOPIC, request);
+
+        verify(sink, never()).send(any());
+    }
+}
diff --git a/models-interactions/model-simulators/src/test/resources/org/onap/policy/simulators/sdnr/vpci.sdnr.request.json b/models-interactions/model-simulators/src/test/resources/org/onap/policy/simulators/sdnr/vpci.sdnr.request.json
new file mode 100644 (file)
index 0000000..fa78c6d
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "body": {
+        "input": {
+            "CommonHeader": {
+                "TimeStamp": "2018-09-10T07:10:05.614Z",
+                "APIver": "1.0",
+                "RequestID": "664be3d2-6c12-4f4b-a3e7-c349acced200",
+                "SubRequestID": "111be3d2-6c12-4f4b-a3e7-c349acced200",
+                "RequestTrack": [],
+                "Flags": []
+            }
+        }
+    },
+    "version": "1.0",
+    "rpc-name": "modifyconfig",
+    "correlation-id": "9d2d790e-a5f0-11e8-98d0-529269fb1459-1",
+    "type": "response"
+}
index 5f946f1..33821a5 100644 (file)
             "servers": ["localhost"],
             "topicCommInfrastructure": "DMAAP",
             "useHttps": true
+        },
+        {
+            "topic": "SDNR-CL",
+            "servers": ["localhost"],
+            "topicCommInfrastructure": "DMAAP",
+            "useHttps": true
         }
     ],
     "topicSources": [
             "servers": ["localhost"],
             "topicCommInfrastructure": "DMAAP",
             "useHttps": true
+        },
+        {
+            "topic": "SDNR-CL-RSP",
+            "servers": ["localhost"],
+            "topicCommInfrastructure": "DMAAP",
+            "useHttps": true
         }
     ],
     "topicServers": [
             "providerClass": "org.onap.policy.simulators.AppcLcmTopicServer",
             "sink": "APPC-LCM-WRITE",
             "source": "APPC-LCM-READ"
+        },
+        {
+            "name": "SDNR simulator",
+            "providerClass": "org.onap.policy.simulators.SdnrTopicServer",
+            "sink": "SDNR-CL",
+            "source": "SDNR-CL-RSP"
         }
     ]
 }