Deleting missing vnf-list entry cause infiniteLoop 27/24927/1
authorJoey Sullivan <joey.sullivan@amdocs.com>
Wed, 22 Nov 2017 21:22:02 +0000 (21:22 +0000)
committerJoey Sullivan <joey.sullivan@amdocs.com>
Wed, 22 Nov 2017 21:37:44 +0000 (21:37 +0000)
Deleting a vnf-list entry that does not exist from
the databoker throws a
ModifiedNodeDoesNotExistException.  This
conflicted with the optimistic locking retry
mechanism causing a infinite loop.

Change-Id: I216a31eabf710ed365c8d928e4df0e866848eeca
Issue-ID: SDNC-156
Signed-off-by: Joey Sullivan <joey.sullivan@amdocs.com>
vnfapi/provider/pom.xml
vnfapi/provider/src/main/java/org/onap/sdnc/vnfapi/vnfapiProvider.java
vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/VnfApiProviderTest.java [new file with mode: 0644]
vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/VnfTopologyOperationRPCTest.java [new file with mode: 0644]
vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/DataBrokerUtil.java [new file with mode: 0644]
vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/MDSALUtil.java [new file with mode: 0644]
vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/PropBuilder.java [new file with mode: 0644]
vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/VNFSDNSvcLogicServiceClientMockUtil.java [new file with mode: 0644]

index aac430a..35021ad 100644 (file)
             <artifactId>sli-provider</artifactId>
             <version>${sdnctl.sli.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-test-model</artifactId>
+            <version>${odl.mdsal.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>sal-rest-connector</artifactId>
+            <version>${odl.mdsal.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <version>${odl.mdsal.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <version>${odl.mdsal.version}</version>
+            <type>test-jar</type>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
+
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
index e8a9e71..30f8585 100644 (file)
@@ -771,30 +771,33 @@ public class vnfapiProvider implements AutoCloseable, VNFAPIService, DataChangeL
             InstanceIdentifier.<Vnfs>builder(Vnfs.class).child(VnfList.class, entry.getKey());
         InstanceIdentifier<VnfList> path = vnfListIdBuilder.build();
 
-        int tries = 2;
-        while (true) {
+        int optimisticLockTries = 2;
+        boolean tryAgain =true;
+        while (tryAgain) {
+            tryAgain = false;
             try {
                 WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
                 tx.delete(storeType, path);
                 tx.submit().checkedGet();
                 log.debug("DataStore delete succeeded");
-                break;
             } catch (final TransactionCommitFailedException  e) {
                 if (e instanceof OptimisticLockFailedException) {
-                    if (--tries <= 0) {
+                    if (--optimisticLockTries <= 0) {
                         log.debug("Got OptimisticLockFailedException on last try - failing ");
                         throw new IllegalStateException(e);
                     }
                     log.debug("Got OptimisticLockFailedException - trying again ");
+                    tryAgain = true;
+                    continue;
                 }
-                else {
-                               if (e.getCause() instanceof ModifiedNodeDoesNotExistException) {
-                                       log.debug("Ignoring MpdifiedNodeDoesNotExistException");
-                               } else {
-                                       log.debug("Delete DataStore failed");
-                                       throw new IllegalStateException(e);
-                               }
+
+                if (e.getCause() instanceof ModifiedNodeDoesNotExistException) {
+                    log.debug("Ignoring MpdifiedNodeDoesNotExistException");
+                    break;
                 }
+
+                log.debug("Delete DataStore failed");
+                throw new IllegalStateException(e);
             }
         }
     }
diff --git a/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/VnfApiProviderTest.java b/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/VnfApiProviderTest.java
new file mode 100644 (file)
index 0000000..c74ce53
--- /dev/null
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 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.sdnc.vnfapi;
+
+import org.junit.Before;
+import org.mockito.Mock;
+import org.onap.sdnc.vnfapi.util.DataBrokerUtil;
+import org.onap.sdnc.vnfapi.util.PropBuilder;
+import org.onap.sdnc.vnfapi.util.VNFSDNSvcLogicServiceClientMockUtil;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.test.AbstractConcurrentDataBrokerTest;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class VnfApiProviderTest extends AbstractConcurrentDataBrokerTest {
+
+    protected vnfapiProvider vnfapiProvider;
+    protected DataBroker dataBroker;
+    protected @Mock NotificationPublishService mockNotificationPublishService;
+    protected @Mock RpcProviderRegistry mockRpcProviderRegistry;
+    protected @Mock VNFSDNSvcLogicServiceClient mockVNFSDNSvcLogicServiceClient;
+    protected static final Logger LOG = LoggerFactory.getLogger(vnfapiProvider.class);
+
+
+    protected DataBrokerUtil db;
+    protected VNFSDNSvcLogicServiceClientMockUtil svcClient;
+
+
+    @Before
+    public void setUp() throws Exception {
+        svcClient = new VNFSDNSvcLogicServiceClientMockUtil(mockVNFSDNSvcLogicServiceClient);
+        dataBroker = getDataBroker();
+        db = new DataBrokerUtil(dataBroker);
+         try {
+            vnfapiProvider = new vnfapiProvider(
+                    dataBroker,
+                    mockNotificationPublishService,
+                    mockRpcProviderRegistry,
+                    mockVNFSDNSvcLogicServiceClient
+            );
+        } catch (Exception e) {
+            LOG.error("Caught exception on setUp", e);
+            throw e;
+        }
+    }
+
+
+    public static PropBuilder prop(){
+        return (new PropBuilder());
+    }
+
+
+}
diff --git a/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/VnfTopologyOperationRPCTest.java b/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/VnfTopologyOperationRPCTest.java
new file mode 100644 (file)
index 0000000..422a6ad
--- /dev/null
@@ -0,0 +1,174 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 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.sdnc.vnfapi;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.sdnc.vnfapi.util.PropBuilder;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.VnfTopologyOperationInput;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.VnfTopologyOperationOutput;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.sdnc.request.header.SdncRequestHeader.SvcAction;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.vnf.model.infrastructure.VnfList;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.build;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.exec;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.sdncRequestHeader;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.serviceData;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.serviceInformation;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.vnfInformation;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.vnfList;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.vnfRequestInformation;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.vnfTopologyOperationInput;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.vnfTopologyOperationOutput;
+
+
+/**
+ * This class test the VnfTopologyOperation mdsal RPC.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class VnfTopologyOperationRPCTest extends VnfApiProviderTest {
+
+
+    final String SVC_OPERATION = "vnf-topology-operation";
+
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        svcClient.setScvOperation(SVC_OPERATION);
+    }
+
+
+    /**
+     * Verify  VnfTopologyOperation RPC executes Delete VNFList entry
+     * {@link VnfTopologyOperationOutput} and persisted the expected {@link VnfList} in the {@link DataBroker}
+     */
+    @Test
+    public void testVnfTopologyOperationRPC_Delete_VNFList_Entry_Success() throws Exception {
+
+
+        //mock svcClient to perform a successful execution with the expected parameters
+        svcClient.mockHasGraph(true);
+        PropBuilder svcResultProp = svcClient.createExecuteOKResult();
+        svcClient.mockExecute(svcResultProp);
+
+        // create the VnfTopologyOperationInput from the template
+        VnfTopologyOperationInput vnfTopologyOperationInput = createVTOI();
+
+        //persist a vnfList entry in the dataBroker
+        persistVnfListBroker(vnfTopologyOperationInput);
+
+        //execute the mdsal exec
+        VnfTopologyOperationOutput actualVnfTopologyOperationOutput = exec(
+                vnfapiProvider::vnfTopologyOperation
+                , vnfTopologyOperationInput
+                , RpcResult::getResult
+        );
+
+
+        //verify the returned VnfTopologyOperationOutput
+        VnfTopologyOperationOutput expectedVnfTopologyOperationOutput = createExpectedVTOO(svcResultProp,vnfTopologyOperationInput);
+        Assert.assertEquals(expectedVnfTopologyOperationOutput,actualVnfTopologyOperationOutput);
+
+
+        //verify the persisted VnfList
+        VnfList actualVnfList = db.read(vnfTopologyOperationInput.getVnfRequestInformation().getVnfId(), LogicalDatastoreType.CONFIGURATION);
+        VnfList expectedVnfList = null;
+        Assert.assertEquals(expectedVnfList,actualVnfList);
+
+        LOG.debug("done");
+    }
+
+
+    public VnfTopologyOperationInput createVTOI(){
+        return build(vnfTopologyOperationInput()
+                .setServiceInformation(
+                        build(serviceInformation()
+                                .setServiceId("serviceId: xyz")
+                                .setServiceInstanceId("serviceInstanceId: xyz")
+                                .setServiceType("serviceType: xyz")
+                                .setSubscriberName("subscriberName: xyz")
+                        )
+                )
+                .setVnfRequestInformation(
+                        build(vnfRequestInformation()
+                                .setVnfId("vnfId: xyz")
+                                .setVnfName("vnfName: xyz")//defect if missing
+                                .setVnfType("vnfType: xyz")//defect if missing
+
+
+                        )
+                )
+                .setSdncRequestHeader(
+                        build(sdncRequestHeader()
+                          .setSvcAction(SvcAction.Delete)
+                        )
+                )
+        );
+
+    }
+
+
+
+    private VnfList persistVnfListBroker(
+            VnfTopologyOperationInput vnfTopologyOperationInput
+    ) throws Exception{
+        VnfList service = build(
+                vnfList()
+                        .setVnfId(vnfTopologyOperationInput.getVnfRequestInformation().getVnfId())
+                        .setServiceData(
+                                build(serviceData()
+                                  .setVnfId(vnfTopologyOperationInput.getVnfRequestInformation().getVnfId())
+                                )
+                        )
+        );
+        db.write(true,service, LogicalDatastoreType.CONFIGURATION);
+        return service;
+    }
+
+
+
+
+
+    private VnfTopologyOperationOutput createExpectedVTOO(PropBuilder expectedSvcResultProp,VnfTopologyOperationInput expectedVnfTopologyOperationInput){
+        return build(
+                vnfTopologyOperationOutput()
+                        .setSvcRequestId(expectedVnfTopologyOperationInput.getSdncRequestHeader().getSvcRequestId())
+                        .setResponseCode(expectedSvcResultProp.get(svcClient.errorCode))
+                        .setAckFinalIndicator(expectedSvcResultProp.get(svcClient.ackFinal))
+                        .setResponseMessage(expectedSvcResultProp.get(svcClient.errorMessage))
+                        .setVnfInformation(build(vnfInformation()
+                                .setVnfId(expectedVnfTopologyOperationInput.getVnfRequestInformation().getVnfId())
+                        ))
+        );
+    }
+
+
+
+
+}
diff --git a/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/DataBrokerUtil.java b/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/DataBrokerUtil.java
new file mode 100644 (file)
index 0000000..d791fa9
--- /dev/null
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 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.sdnc.vnfapi.util;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.Vnfs;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.vnf.model.infrastructure.VnfList;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.vnf.model.infrastructure.VnfListKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+
+/**
+ * This util class provides utility to read and write {@link VnfList} data objects from the {@link DataBroker}
+ *
+ */
+public class DataBrokerUtil {
+
+
+    private final DataBroker dataBroker;
+
+    public DataBrokerUtil(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+    }
+
+    /** @return VnfList - the VnfList object read from the DataBroker or null if none was found */
+    public VnfList read(String VnfListKey, LogicalDatastoreType logicalDatastoreType) throws Exception {
+        InstanceIdentifier VnfListInstanceIdentifier = InstanceIdentifier.<Vnfs>builder(Vnfs.class)
+                .child(VnfList.class, new VnfListKey(VnfListKey)).build();
+        ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction();
+        Optional<VnfList> data = (Optional<VnfList>) readTx.read(logicalDatastoreType, VnfListInstanceIdentifier).get();
+        if(!data.isPresent()){
+            return null;
+        }
+        return data.get();
+    }
+
+
+    /**
+     * Write the {@link VnfList} object to the {@link DataBroker}
+     * @param isReplace - false specifies the new data is to be merged into existing data, where as true cause the
+     *                  existing data to be replaced.
+     * @param VnfList - the {@link VnfList} data object to be presisted in the db.
+     * @param logicalDatastoreType - The logicalDatastoreType
+     */
+    public void write(boolean isReplace,VnfList VnfList, LogicalDatastoreType logicalDatastoreType) throws Exception {
+        // Each entry will be identifiable by a unique key, we have to create that
+        // identifier
+        InstanceIdentifier.InstanceIdentifierBuilder<VnfList> VnfListBuilder = InstanceIdentifier
+                .<Vnfs>builder(Vnfs.class).child(VnfList.class, VnfList.getKey());
+        InstanceIdentifier<VnfList> path = VnfListBuilder.build();
+
+        WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+        if (!isReplace) {
+            tx.merge(logicalDatastoreType, path, VnfList);
+        } else {
+            tx.put(logicalDatastoreType, path, VnfList);
+        }
+        CheckedFuture<Void,TransactionCommitFailedException> cf = tx.submit();
+        cf.checkedGet();
+
+    }
+
+
+
+
+
+
+
+}
diff --git a/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/MDSALUtil.java b/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/MDSALUtil.java
new file mode 100644 (file)
index 0000000..b28139c
--- /dev/null
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 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.sdnc.vnfapi.util;
+
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.VnfTopologyOperationInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.VnfTopologyOperationOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.sdnc.request.header.SdncRequestHeaderBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.service.data.ServiceDataBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.service.information.ServiceInformationBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.vnf.information.VnfInformationBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.vnf.model.infrastructure.VnfListBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.vnf.request.information.VnfRequestInformationBuilder;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.concurrent.Future;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+
+/**
+ * This uill class provides utility to build yang objects using a recursive syntax that resembles the tree structure
+ * when defining the same yang object in json format.
+ *
+ * For Example
+ * <pre>
+ * {@code
+ * import static org.onap.sdnc.northbound.util.MDSALUtil.*;
+ * VnfTopologyOperationInput input = build(vnfTopologyOperationInput()
+ *                .setServiceInformation(
+ *                        build(serviceInformation()
+ *                                .setServiceId("serviceId: xyz")
+ *                                .setServiceInstanceId("serviceInstanceId: xyz")
+ *                                .setServiceType("serviceType: xyz")
+ *                                .setSubscriberName("subscriberName: xyz")
+ *                        )
+ *                )
+ *                .setVnfRequestInformation(
+ *                        build(vnfRequestInformation()
+ *                                .setVnfId("vnfId: xyz")
+ *                                .setVnfName("vnfName: xyz")//defect if missing
+ *                                .setVnfType("vnfType: xyz")//defect if missing
+ *                        )
+ *                )
+ *                .setSdncRequestHeader(
+ *                        build(sdncRequestHeader()
+ *                          .setSvcAction(SvcAction.Delete)
+ *                        )
+ *                )
+ *        );
+ * );
+ * }
+ * </pre>
+ */
+public class MDSALUtil {
+
+    public static VnfTopologyOperationInputBuilder vnfTopologyOperationInput(){return new VnfTopologyOperationInputBuilder();}
+    public static VnfTopologyOperationOutputBuilder vnfTopologyOperationOutput(){return new VnfTopologyOperationOutputBuilder();}
+
+    public static ServiceInformationBuilder serviceInformation(){return new ServiceInformationBuilder();}
+    public static VnfRequestInformationBuilder vnfRequestInformation(){return new VnfRequestInformationBuilder();}
+    public static VnfListBuilder vnfList(){return new VnfListBuilder();}
+    public static ServiceDataBuilder serviceData() { return new ServiceDataBuilder();}
+    public static SdncRequestHeaderBuilder sdncRequestHeader(){return new SdncRequestHeaderBuilder();}
+    public static VnfInformationBuilder vnfInformation(){return new VnfInformationBuilder();}
+
+
+    public static <P> P build(Builder<P> b) {
+        return b == null? null :b.build();
+    }
+
+    public static <P,B extends Builder<P>> P build(Function<P,B> builderConstructor,P sourceDataObject){
+        if(sourceDataObject == null){
+            return null;
+        }
+        B bp = builderConstructor.apply(sourceDataObject);
+        return bp.build();
+    }
+
+    public static <P,B extends Builder<P>> P build(Function<P,B> builderConstructor,P sourceDataObject,Consumer<B> builder){
+        if(sourceDataObject == null){
+            return null;
+        }
+        B bp = builderConstructor.apply(sourceDataObject);
+        builder.accept(bp);
+        return bp.build();
+    }
+
+    public static <I,O> O exec(Function<I,Future<RpcResult<O>>> rpc,I rpcParameter,Function<RpcResult<O>,O> rpcResult)  throws Exception {
+        Future<RpcResult<O>> future = rpc.apply(rpcParameter);
+        return rpcResult.apply(future.get());
+    }
+
+}
diff --git a/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/PropBuilder.java b/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/PropBuilder.java
new file mode 100644 (file)
index 0000000..6ecc94c
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 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.sdnc.vnfapi.util;
+
+import org.opendaylight.yangtools.concepts.Builder;
+
+import java.util.Properties;
+
+/**
+ * A Util class that adds method chaining to the {@link #set(String, String)} to reducing the syntax needed to populate
+ * {@link Properties}
+ */
+public class PropBuilder implements Builder<Properties> {
+
+
+    final Properties prop;
+
+    public PropBuilder(Properties prop) {
+        this.prop = prop;
+    }
+
+    public PropBuilder() {
+        this.prop = new Properties();
+    }
+
+    public Properties build(){
+        return prop;
+    }
+
+    public PropBuilder set(String key, String value) {
+        prop.setProperty(key, value);
+        return this;
+    }
+
+    public String get(String key) {
+        return prop.getProperty(key);
+    }
+
+
+    public static PropBuilder propBuilder(){
+        return (new PropBuilder());
+    }
+}
\ No newline at end of file
diff --git a/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/VNFSDNSvcLogicServiceClientMockUtil.java b/vnfapi/provider/src/test/java/org/onap/sdnc/vnfapi/util/VNFSDNSvcLogicServiceClientMockUtil.java
new file mode 100644 (file)
index 0000000..d4d94ca
--- /dev/null
@@ -0,0 +1,130 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 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.sdnc.vnfapi.util;
+
+import org.onap.sdnc.vnfapi.VNFSDNSvcLogicServiceClient;
+import org.opendaylight.yang.gen.v1.org.onap.sdnctl.vnf.rev150720.service.data.ServiceDataBuilder;
+
+import java.util.Properties;
+
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.isA;
+import static org.mockito.Mockito.when;
+import static org.onap.sdnc.vnfapi.util.MDSALUtil.build;
+import static org.onap.sdnc.vnfapi.util.PropBuilder.propBuilder;
+
+
+/**
+ * VNFSDNSvcLogicServiceClientMockUtil provides a set of util methods for quickly configuring method
+ * behaviour on the Mock VNFSDNSvcLogicServiceClient
+ */
+public class VNFSDNSvcLogicServiceClientMockUtil {
+
+
+    private final String MODULE = "VNF-API";
+    private final String MODE = "sync";
+    private final String VERSION = null;
+    private String scvOperation = null;
+
+
+    public final String errorCode = "error-code";
+    public final String errorMessage = "error-message";
+    public final String ackFinal = "ack-final";
+    public final String serviceObjectPath = "service-object-path";
+    public final String networkObjectPath = "network-object-path";
+    public final String networkId = "networkId";
+
+
+    private final VNFSDNSvcLogicServiceClient mockVNFSDNSvcLogicServiceClient;
+
+
+
+    public VNFSDNSvcLogicServiceClientMockUtil(VNFSDNSvcLogicServiceClient mockVNFSDNSvcLogicServiceClient) {
+        this.mockVNFSDNSvcLogicServiceClient = mockVNFSDNSvcLogicServiceClient;
+    }
+
+
+    /** @param scvOperation -  The scvOperation parameter to use on the {@link VNFSDNSvcLogicServiceClient} methods */
+    public void setScvOperation(String scvOperation) {
+        this.scvOperation = scvOperation;
+    }
+
+    /**
+     * Configure {@link VNFSDNSvcLogicServiceClient#hasGraph(String, String, String, String)}
+     * to return the specified value when when invoked with the parameters
+     * {@link #MODULE}, {@link #MODE}, {@link #VERSION} and {@link #scvOperation}
+     */
+    public void mockHasGraph(Boolean isHasGraph) throws Exception {
+        when(
+                mockVNFSDNSvcLogicServiceClient
+                        .hasGraph(
+                                eq(MODULE),
+                                eq(scvOperation),
+                                eq(VERSION),
+                                eq(MODE)
+                        )
+        )
+                .thenReturn(isHasGraph);
+    }
+
+
+    /**
+     * @return
+     * PropBuilder - A PropBuilder populated with the expected properties returned from
+     * {@link VNFSDNSvcLogicServiceClient#execute(String, String, String, String, ServiceDataBuilder, Properties)}
+     */
+    public PropBuilder createExecuteOKResult(){
+        return propBuilder()
+                .set(errorCode,"200")
+                .set(errorMessage,"OK")
+                .set(ackFinal,"Y")
+                .set(serviceObjectPath,"serviceObjectPath: XYZ")
+                .set(networkObjectPath,"networkObjectPath: XYZ")
+                .set(networkId,"networkId: XYZ");
+
+    }
+
+
+    /**
+     * Configure
+     * {@link VNFSDNSvcLogicServiceClient#execute(String, String, String, String, ServiceDataBuilder, Properties)}
+     * to return the specified svcResultProp when when invoked with the parameters
+     * {@link #MODULE}, {@link #MODE}, {@link #VERSION} and {@link #scvOperation}
+     */
+    public void mockExecute(PropBuilder svcResultProp) throws Exception{
+        when(
+                mockVNFSDNSvcLogicServiceClient
+                        .execute(
+                                eq(MODULE),
+                                eq(scvOperation),
+                                eq(VERSION),
+                                eq(MODE),
+                                isA(ServiceDataBuilder.class),
+                                isA(Properties.class)
+                        )
+        )
+                .thenReturn(build(
+                        svcResultProp
+                ));
+    }
+
+}