diff options
Diffstat (limited to 'models-interactions/model-actors/actor.cds')
6 files changed, 631 insertions, 0 deletions
diff --git a/models-interactions/model-actors/actor.cds/pom.xml b/models-interactions/model-actors/actor.cds/pom.xml new file mode 100644 index 000000000..5c4a04460 --- /dev/null +++ b/models-interactions/model-actors/actor.cds/pom.xml @@ -0,0 +1,71 @@ +<!-- + ============LICENSE_START======================================================= + Copyright (C) 2019 Bell Canada. 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========================================================= + --> + +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.policy.models.policy-models-interactions.model-actors</groupId> + <artifactId>model-actors</artifactId> + <version>2.1.3-SNAPSHOT</version> + </parent> + <artifactId>actor.cds</artifactId> + <dependencies> + <dependency> + <groupId>org.onap.policy.models.policy-models-interactions.model-actors</groupId> + <artifactId>actorServiceProvider</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId> + <artifactId>cds</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId> + <artifactId>events</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.models.policy-models-interactions</groupId> + <artifactId>simulators</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.common</groupId> + <artifactId>policy-endpoints</artifactId> + <version>${policy.common.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId> + <artifactId>aai</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java new file mode 100644 index 000000000..aaf07ac21 --- /dev/null +++ b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProvider.java @@ -0,0 +1,240 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Bell Canada. 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.controlloop.actor.cds; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Struct; +import com.google.protobuf.Struct.Builder; +import com.google.protobuf.util.JsonFormat; +import io.grpc.Status; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers; +import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader; +import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; +import org.onap.policy.cds.api.CdsProcessorListener; +import org.onap.policy.cds.client.CdsProcessorGrpcClient; +import org.onap.policy.cds.properties.CdsServerProperties; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.cds.beans.ConfigDeployRequest; +import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants; +import org.onap.policy.controlloop.actorserviceprovider.spi.Actor; +import org.onap.policy.controlloop.policy.Policy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * CDS Actor service-provider implementation. This is a deploy dark feature for El-Alto release. + */ +public class CdsActorServiceProvider implements Actor { + + private static final Logger LOGGER = LoggerFactory.getLogger(CdsActorServiceProvider.class); + + /** + * {@inheritDoc}. + */ + @Override + public String actor() { + return CdsActorConstants.CDS_ACTOR; + } + + /** + * {@inheritDoc}. Note: This is a placeholder for now. + */ + @Override + public List<String> recipes() { + return new ArrayList<>(); + } + + /** + * {@inheritDoc}. Note: This is a placeholder for now. + */ + @Override + public List<String> recipeTargets(final String recipe) { + return new ArrayList<>(); + } + + /** + * {@inheritDoc}. Note: This is a placeholder for now. + */ + @Override + public List<String> recipePayloads(final String recipe) { + return new ArrayList<>(); + } + + /** + * Build the CDS ExecutionServiceInput request from the policy object and the AAI enriched parameters. TO-DO: Avoid + * leaking Exceptions to the Kie Session thread. TBD item for Frankfurt release. + * + * @param onset the event that is reporting the alert for policy to perform an action. + * @param operation the control loop operation specifying the actor, operation, target, etc. + * @param policy the policy specified from the yaml generated by CLAMP or through Policy API. + * @param aaiParams Map of enriched AAI attributes in node.attribute notation. + * @return an Optional ExecutionServiceInput instance if valid else an Optional empty object is returned. + */ + public Optional<ExecutionServiceInput> constructRequest(VirtualControlLoopEvent onset, + ControlLoopOperation operation, Policy policy, Map<String, String> aaiParams) { + + // For the current operational TOSCA policy model (yaml) CBA name and version are embedded in the payload + // section, with the new policy type model being proposed in Frankfurt we will be able to move it out. + Map<String, String> payload = policy.getPayload(); + if (!validateCdsMandatoryParams(policy)) { + return Optional.empty(); + } + String cbaName = payload.get(CdsActorConstants.KEY_CBA_NAME); + String cbaVersion = payload.get(CdsActorConstants.KEY_CBA_VERSION); + String cbaActionName = policy.getRecipe(); + + // Embed payload from policy to ConfigDeployRequest object, serialize and inject into grpc request. + ConfigDeployRequest request = new ConfigDeployRequest(); + request.setConfigDeployProperties(payload); + + // Inject AAI properties into payload map. Offer flexibility to the usecase + // implementation to inject whatever AAI parameters are of interest to them. + // E.g. For vFW usecase El-Alto inject service-instance-id, generic-vnf-id as needed by CDS. + request.setAaiProperties(aaiParams); + + Builder struct = Struct.newBuilder(); + try { + String requestStr = request.toString(); + Preconditions.checkState(!Strings.isNullOrEmpty(requestStr), "Unable to build " + + "config-deploy-request from payload parameters: {}", payload); + JsonFormat.parser().merge(requestStr, struct); + } catch (InvalidProtocolBufferException e) { + LOGGER.error("Failed to parse received message. blueprint({}:{}) for action({})", cbaName, cbaVersion, + cbaActionName, e); + return Optional.empty(); + } + + // Build CDS gRPC request common-header + CommonHeader commonHeader = CommonHeader.newBuilder() + .setOriginatorId(CdsActorConstants.ORIGINATOR_ID) + .setRequestId(onset.getRequestId().toString()) + .setSubRequestId(operation.getSubRequestId()) + .build(); + + // Build CDS gRPC request action-identifier + ActionIdentifiers actionIdentifiers = ActionIdentifiers.newBuilder() + .setBlueprintName(cbaName) + .setBlueprintVersion(cbaVersion) + .setActionName(cbaActionName) + .setMode(CdsActorConstants.CDS_MODE) + .build(); + + // Finally build the ExecutionServiceInput gRPC request object. + ExecutionServiceInput executionServiceInput = ExecutionServiceInput.newBuilder() + .setCommonHeader(commonHeader) + .setActionIdentifiers(actionIdentifiers) + .setPayload(struct.build()) + .build(); + return Optional.of(executionServiceInput); + } + + private boolean validateCdsMandatoryParams(Policy policy) { + if (policy == null || policy.getPayload() == null) { + return false; + } + Map<String, String> payload = policy.getPayload(); + String cbaName = payload.get(CdsActorConstants.KEY_CBA_NAME); + String cbaVersion = payload.get(CdsActorConstants.KEY_CBA_VERSION); + String cbaActionName = policy.getRecipe(); + return !Strings.isNullOrEmpty(cbaName) && !Strings.isNullOrEmpty(cbaVersion) && !Strings + .isNullOrEmpty(cbaActionName); + } + + class CdsActorServiceManager implements CdsProcessorListener { + + private final AtomicReference<String> cdsResponse = new AtomicReference<>(); + + /** + * {@inheritDoc}. + */ + @Override + public void onMessage(final ExecutionServiceOutput message) { + LOGGER.info("Received notification from CDS: {}", message); + EventType eventType = message.getStatus().getEventType(); + switch (eventType) { + case EVENT_COMPONENT_FAILURE: + cdsResponse.compareAndSet(null, CdsActorConstants.FAILED); + break; + case EVENT_COMPONENT_PROCESSING: + cdsResponse.compareAndSet(null, CdsActorConstants.PROCESSING); + break; + case EVENT_COMPONENT_EXECUTED: + cdsResponse.compareAndSet(null, CdsActorConstants.SUCCESS); + break; + default: + cdsResponse.compareAndSet(null, CdsActorConstants.FAILED); + break; + } + } + + /** + * {@inheritDoc}. + */ + @Override + public void onError(final Throwable throwable) { + Status status = Status.fromThrowable(throwable); + cdsResponse.compareAndSet(null, CdsActorConstants.ERROR); + LOGGER.error("Failed processing blueprint {} {}", status, throwable); + } + + /** + * Send gRPC request to CDS to execute the blueprint. + * + * @param cdsClient CDS grpc client object. + * @param cdsProps CDS properties. + * @param executionServiceInput a valid CDS grpc request object. + * @return Status of the CDS request, null if timeout happens or onError is invoked for any reason. + */ + public String sendRequestToCds(CdsProcessorGrpcClient cdsClient, CdsServerProperties cdsProps, + ExecutionServiceInput executionServiceInput) { + try { + LOGGER.trace("Start CdsActorServiceProvider.executeCdsBlueprintProcessor {}.", executionServiceInput); + // TO-DO: Handle requests asynchronously once the callback support is added to actors. + CountDownLatch countDownLatch = cdsClient.sendRequest(executionServiceInput); + boolean status = countDownLatch.await(cdsProps.getTimeout(), TimeUnit.SECONDS); + if (!status) { + cdsResponse.compareAndSet(null, CdsActorConstants.TIMED_OUT); + } + LOGGER.info("CDS response {}", getCdsResponse()); + } catch (InterruptedException ex) { + LOGGER.error("Caught exception in executeCdsBlueprintProcessor in CdsActorServiceProvider: ", ex); + cdsResponse.compareAndSet(null, CdsActorConstants.INTERRUPTED); + Thread.currentThread().interrupt(); + } + LOGGER.info("Status of the CDS gRPC request is: {}", getCdsResponse()); + return getCdsResponse(); + } + + String getCdsResponse() { + return cdsResponse.get(); + } + } +} diff --git a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/beans/ConfigDeployRequest.java b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/beans/ConfigDeployRequest.java new file mode 100644 index 000000000..f33f226f9 --- /dev/null +++ b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/beans/ConfigDeployRequest.java @@ -0,0 +1,43 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Bell Canada. 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.controlloop.actor.cds.beans; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; +import java.util.Map; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ConfigDeployRequest { + + private static final Gson GSON = new Gson(); + + @SerializedName("config-deploy-properties") + private Map<String, String> configDeployProperties; + + @SerializedName("aai-properties") + private Map<String, String> aaiProperties; + + @Override + public String toString() { + return "{\"config-deploy-request\":" + GSON.toJson(this) + '}'; + } +} diff --git a/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/constants/CdsActorConstants.java b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/constants/CdsActorConstants.java new file mode 100644 index 000000000..b79aca061 --- /dev/null +++ b/models-interactions/model-actors/actor.cds/src/main/java/org/onap/policy/controlloop/actor/cds/constants/CdsActorConstants.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Bell Canada. 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.controlloop.actor.cds.constants; + +public class CdsActorConstants { + + public static final String CDS_ACTOR = "CDS"; + + // CDS Status + public static final String SUCCESS = "Success"; + public static final String FAILED = "Failed"; + public static final String PROCESSING = "Processing"; + public static final String TIMED_OUT = "Timed out"; + public static final String INTERRUPTED = "Thread interrupted"; + public static final String ERROR = "Error"; + + // CDS blueprint archive parameters + public static final String KEY_CBA_NAME = "artifact_name"; + public static final String KEY_CBA_VERSION = "artifact_version"; + public static final String ORIGINATOR_ID = "POLICY"; + // Temporarily set to synchronous mode to support current rules, since callbacks aren't supported yet + public static final String CDS_MODE = "sync"; +} diff --git a/models-interactions/model-actors/actor.cds/src/main/resources/META-INF.services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor b/models-interactions/model-actors/actor.cds/src/main/resources/META-INF.services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor new file mode 100644 index 000000000..e91d41989 --- /dev/null +++ b/models-interactions/model-actors/actor.cds/src/main/resources/META-INF.services/org.onap.policy.controlloop.actorserviceprovider.spi.Actor @@ -0,0 +1 @@ +org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider diff --git a/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java new file mode 100644 index 000000000..65fd60239 --- /dev/null +++ b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/CdsActorServiceProviderTest.java @@ -0,0 +1,237 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Bell Canada. 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.controlloop.actor.cds; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.common.collect.ImmutableMap; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers; +import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader; +import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType; +import org.onap.ccsdk.cds.controllerblueprints.common.api.Status; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; +import org.onap.policy.cds.client.CdsProcessorGrpcClient; +import org.onap.policy.cds.properties.CdsServerProperties; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider.CdsActorServiceManager; +import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants; +import org.onap.policy.controlloop.policy.Policy; + +@RunWith(MockitoJUnitRunner.class) +public class CdsActorServiceProviderTest { + + private static final String CDS_BLUEPRINT_NAME = "vfw-cds"; + private static final String CDS_BLUEPRINT_VERSION = "1.0.0"; + private static final UUID REQUEST_ID = UUID.randomUUID(); + private static final String SUBREQUEST_ID = "123456"; + + @Rule + public ExpectedException exceptionRule = ExpectedException.none(); + @Mock + private CdsProcessorGrpcClient cdsClient; + private CdsActorServiceProvider cdsActor; + private Policy policy; + private CdsServerProperties cdsProps; + private Map<String, String> aaiParams; + private VirtualControlLoopEvent onset; + private ControlLoopOperation operation; + + /** + * Test setup. + */ + @Before + public void setup() { + // Setup policy + policy = new Policy(); + Map<String, String> payloadMap = new HashMap<String, String>() { + { + put(CdsActorConstants.KEY_CBA_NAME, CDS_BLUEPRINT_NAME); + put(CdsActorConstants.KEY_CBA_VERSION, CDS_BLUEPRINT_VERSION); + put("data", "{\"mapInfo\":{\"key\":\"val\"},\"arrayInfo\":[\"one\",\"two\"],\"paramInfo\":\"val\"}"); + } + }; + policy.setPayload(payloadMap); + policy.setRecipe("CDS"); + + // Setup the CDS properties + cdsProps = new CdsServerProperties(); + cdsProps.setHost("10.10.10.10"); + cdsProps.setPort(2000); + cdsProps.setUsername("testUser"); + cdsProps.setPassword("testPassword"); + cdsProps.setTimeout(1); + + // Setup aaiParams + aaiParams = ImmutableMap.of("service-instance-id", "1234", "generic-vnf-id", "5678"); + + // Setup cdsClient + when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(mock(CountDownLatch.class)); + + // Setup the cdsActor + cdsActor = new CdsActorServiceProvider(); + + // Setup onset event + onset = new VirtualControlLoopEvent(); + onset.setRequestId(REQUEST_ID); + + // Setup controlloop operation object + operation = new ControlLoopOperation(); + operation.setSubRequestId(SUBREQUEST_ID); + } + + @Test + public void testActor() { + assertEquals(cdsActor.actor(), CdsActorConstants.CDS_ACTOR); + } + + @Test + public void testConstructRequest() { + policy.setPayload(new HashMap<>()); + Optional<ExecutionServiceInput> cdsRequestOpt = cdsActor + .constructRequest(onset, operation, policy, aaiParams); + + assertFalse(cdsRequestOpt.isPresent()); + } + + @Test + public void testConstructRequestWhenMissingCdsParamsInPolicyPayload() { + Optional<ExecutionServiceInput> cdsRequestOpt = cdsActor + .constructRequest(onset, operation, policy, aaiParams); + + assertTrue(cdsRequestOpt.isPresent()); + final ExecutionServiceInput cdsRequest = cdsRequestOpt.get(); + + assertTrue(cdsRequest.hasCommonHeader()); + CommonHeader commonHeader = cdsRequest.getCommonHeader(); + assertEquals(commonHeader.getRequestId(), REQUEST_ID.toString()); + assertEquals(commonHeader.getSubRequestId(), SUBREQUEST_ID); + + assertTrue(cdsRequest.hasPayload()); + + assertTrue(cdsRequest.hasActionIdentifiers()); + ActionIdentifiers actionIdentifiers = cdsRequest.getActionIdentifiers(); + assertEquals(actionIdentifiers.getActionName(), CdsActorConstants.CDS_ACTOR); + assertEquals(actionIdentifiers.getBlueprintName(), CDS_BLUEPRINT_NAME); + assertEquals(actionIdentifiers.getBlueprintVersion(), CDS_BLUEPRINT_VERSION); + } + + @Test + public void testRecipePayloads() { + assertEquals(cdsActor.recipePayloads("").size(), 0); + } + + @Test + public void testRecipes() { + assertEquals(cdsActor.recipes().size(), 0); + } + + @Test + public void testRecipeTargets() { + assertEquals(cdsActor.recipeTargets("").size(), 0); + } + + @Test + public void testSendRequestToCdsSuccess() { + sendRequestToCds(); + verify(cdsClient).sendRequest(any(ExecutionServiceInput.class)); + } + + @Test + public void testSendRequestToCdsLatchInterrupted() throws InterruptedException { + // Reset cdsClient + CountDownLatch countDownLatch = mock(CountDownLatch.class); + doThrow(new InterruptedException("Test latch interrupted failure")).when(countDownLatch) + .await(anyLong(), any(TimeUnit.class)); + when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(countDownLatch); + + CdsActorServiceProvider.CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager(); + String response = cdsActorSvcMgr + .sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build()); + assertTrue(Thread.interrupted()); + assertEquals(response, CdsActorConstants.INTERRUPTED); + } + + @Test + public void testSendRequestToCdsLatchTimedOut() { + CdsActorServiceProvider.CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager(); + String response = cdsActorSvcMgr + .sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build()); + assertEquals(response, CdsActorConstants.TIMED_OUT); + } + + @Test + public void testOnMessage() throws InterruptedException { + ExecutionServiceOutput message = ExecutionServiceOutput.newBuilder() + .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_FAILURE).build()).build(); + + // Test "no timeout" scenarios + CountDownLatch latch = mock(CountDownLatch.class); + when(latch.await(anyLong(), any(TimeUnit.class))).thenReturn(true); + when(cdsClient.sendRequest(any(ExecutionServiceInput.class))).thenReturn(latch); + + CdsActorServiceManager cdsActorSvcMgr = sendRequestToCds(); + + // #1: Failure test + cdsActorSvcMgr.onMessage(message); + assertEquals(cdsActorSvcMgr.getCdsResponse(), CdsActorConstants.FAILED); + + // #2: Success test + cdsActorSvcMgr = sendRequestToCds(); + message = ExecutionServiceOutput.newBuilder() + .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_EXECUTED).build()).build(); + cdsActorSvcMgr.onMessage(message); + assertEquals(cdsActorSvcMgr.getCdsResponse(), CdsActorConstants.SUCCESS); + + // #3: Processing test + cdsActorSvcMgr = sendRequestToCds(); + message = ExecutionServiceOutput.newBuilder() + .setStatus(Status.newBuilder().setEventType(EventType.EVENT_COMPONENT_PROCESSING).build()).build(); + cdsActorSvcMgr.onMessage(message); + assertEquals(cdsActorSvcMgr.getCdsResponse(), CdsActorConstants.PROCESSING); + } + + private CdsActorServiceManager sendRequestToCds() { + CdsActorServiceManager cdsActorSvcMgr = cdsActor.new CdsActorServiceManager(); + cdsActorSvcMgr.sendRequestToCds(cdsClient, cdsProps, ExecutionServiceInput.newBuilder().build()); + return cdsActorSvcMgr; + } +} |