X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=models-interactions%2Fmodel-actors%2Factor.cds%2Fsrc%2Ftest%2Fjava%2Forg%2Fonap%2Fpolicy%2Fcontrolloop%2Factor%2Fcds%2FGrpcOperationTest.java;h=709e179e6f508c4311833604720aeed4d6ac4881;hb=f456cc5c8e1efd15edb6da718e1428d8fd7c66c5;hp=9477a1585054073e64ddbdaea6953a567de17279;hpb=8e3dfc00ee7e443862069b7424b31bd73bc1988d;p=policy%2Fmodels.git diff --git a/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/GrpcOperationTest.java b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/GrpcOperationTest.java index 9477a1585..709e179e6 100644 --- a/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/GrpcOperationTest.java +++ b/models-interactions/model-actors/actor.cds/src/test/java/org/onap/policy/controlloop/actor/cds/GrpcOperationTest.java @@ -19,9 +19,12 @@ package org.onap.policy.controlloop.actor.cds; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -29,22 +32,29 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.Pnf; import org.onap.aai.domain.yang.ServiceInstance; import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput; +import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput; import org.onap.policy.aai.AaiCqResponse; import org.onap.policy.cds.client.CdsProcessorGrpcClient; import org.onap.policy.cds.properties.CdsServerProperties; @@ -58,11 +68,13 @@ import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation; import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants; import org.onap.policy.controlloop.actorserviceprovider.ActorService; import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.actorserviceprovider.OperationResult; +import org.onap.policy.controlloop.actorserviceprovider.TargetType; import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; -import org.onap.policy.controlloop.policy.PolicyResult; -import org.onap.policy.controlloop.policy.Target; -import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.simulators.CdsSimulator; +import org.onap.policy.simulators.Util; public class GrpcOperationTest { private static final String TARGET_ENTITY = "entity"; @@ -74,14 +86,38 @@ public class GrpcOperationTest { private static final UUID REQUEST_ID = UUID.randomUUID(); private static final Coder coder = new StandardCoder(); + protected static final Executor blockingExecutor = command -> { + Thread thread = new Thread(command); + thread.setDaemon(true); + thread.start(); + }; + + private static CdsSimulator sim; + @Mock private CdsProcessorGrpcClient cdsClient; + @Mock + private ControlLoopEventContext context; private CdsServerProperties cdsProps; private VirtualControlLoopEvent onset; private PseudoExecutor executor; - private Target target; + private TargetType targetType; + private Map targetEntityIds; + private ControlLoopOperationParams params; + private GrpcConfig config; + private CompletableFuture cqFuture; private GrpcOperation operation; + @BeforeClass + public static void setUpBeforeClass() throws Exception { + sim = Util.buildCdsSim(); + } + + @AfterClass + public static void tearDownAfterClass() { + sim.stop(); + } + /** * Sets up the fields. */ @@ -107,31 +143,190 @@ public class GrpcOperationTest { // Setup executor executor = new PseudoExecutor(); - target = new Target(); - target.setType(TargetType.VM); - target.setResourceID(RESOURCE_ID); + targetType = TargetType.VM; + targetEntityIds = new HashMap<>(); + targetEntityIds.put(ControlLoopOperationParams.PARAMS_ENTITY_RESOURCEID, RESOURCE_ID); + + cqFuture = new CompletableFuture<>(); + when(context.obtain(eq(AaiCqResponse.CONTEXT_KEY), any())).thenReturn(cqFuture); + when(context.getEvent()).thenReturn(onset); + + params = ControlLoopOperationParams.builder().actor(CdsActorConstants.CDS_ACTOR) + .operation(GrpcOperation.NAME).context(context).actorService(new ActorService()) + .targetEntity(TARGET_ENTITY).targetType(targetType).targetEntityIds(targetEntityIds) + .build(); } + /** + * Tests "success" case with simulator. + */ @Test - public void testStartPreprocessorAsync() throws InterruptedException, ExecutionException, TimeoutException { + public void testSuccess() throws Exception { + ControlLoopEventContext context = new ControlLoopEventContext(onset); + loadCqData(context); - CompletableFuture future2 = new CompletableFuture<>(); - ControlLoopEventContext context = mock(ControlLoopEventContext.class); - when(context.obtain(eq(AaiCqResponse.CONTEXT_KEY), any())).thenReturn(future2); - when(context.getEvent()).thenReturn(onset); + Map payload = Map.of("artifact_name", "my_artifact", "artifact_version", "1.0"); - AtomicBoolean guardStarted = new AtomicBoolean(); + params = ControlLoopOperationParams.builder().actor(CdsActorConstants.CDS_ACTOR).operation("subscribe") + .context(context).actorService(new ActorService()).targetEntity(TARGET_ENTITY) + .targetType(targetType).targetEntityIds(targetEntityIds) + .retry(0).timeoutSec(5).executor(blockingExecutor).payload(payload).build(); - ControlLoopOperationParams params = ControlLoopOperationParams.builder().actor(CdsActorConstants.CDS_ACTOR) - .operation(GrpcOperation.NAME).context(context).actorService(new ActorService()) - .targetEntity(TARGET_ENTITY).target(target).build(); - GrpcConfig config = new GrpcConfig(executor, cdsProps); + cdsProps.setHost("localhost"); + cdsProps.setPort(sim.getPort()); + cdsProps.setTimeout(3); + + GrpcConfig config = new GrpcConfig(blockingExecutor, cdsProps); + + operation = new GrpcOperation(params, config) { + @Override + protected CompletableFuture startGuardAsync() { + // indicate that guard completed successfully + return CompletableFuture.completedFuture(params.makeOutcome(null)); + } + }; + + OperationOutcome outcome = operation.start().get(); + assertEquals(OperationResult.SUCCESS, outcome.getResult()); + assertTrue(outcome.getResponse() instanceof ExecutionServiceOutput); + } + + /** + * Tests "success" case with simulator using properties. + */ + @Test + public void testSuccessViaProperties() throws Exception { + ControlLoopEventContext context = new ControlLoopEventContext(onset); + loadCqData(context); + + Map payload = Map.of("artifact_name", "my_artifact", "artifact_version", "1.0"); + + params = ControlLoopOperationParams.builder().actor(CdsActorConstants.CDS_ACTOR).operation("subscribe") + .context(context).actorService(new ActorService()).targetEntity(TARGET_ENTITY) + .targetType(targetType).targetEntityIds(targetEntityIds) + .retry(0).timeoutSec(5).executor(blockingExecutor).payload(payload).preprocessed(true).build(); + + cdsProps.setHost("localhost"); + cdsProps.setPort(sim.getPort()); + cdsProps.setTimeout(3); + + GrpcConfig config = new GrpcConfig(blockingExecutor, cdsProps); + + operation = new GrpcOperation(params, config); + + // set the properties + operation.setProperty(OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES, Collections.emptyMap()); + + OperationOutcome outcome = operation.start().get(); + assertEquals(OperationResult.SUCCESS, outcome.getResult()); + assertTrue(outcome.getResponse() instanceof ExecutionServiceOutput); + } + + @Test + public void testGetPropertyNames() { + + /* + * check VNF case + */ + operation = new GrpcOperation(params, config); + + // @formatter:off + assertThat(operation.getPropertyNames()).isEqualTo( + List.of( + OperationProperties.AAI_RESOURCE_VNF, + OperationProperties.AAI_SERVICE, + OperationProperties.EVENT_ADDITIONAL_PARAMS, + OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES)); + // @formatter:on + + /* + * check PNF case + */ + params = params.toBuilder().targetType(TargetType.PNF).build(); + operation = new GrpcOperation(params, config); + + // @formatter:off + assertThat(operation.getPropertyNames()).isEqualTo( + List.of( + OperationProperties.AAI_PNF, + OperationProperties.EVENT_ADDITIONAL_PARAMS, + OperationProperties.OPT_CDS_GRPC_AAI_PROPERTIES)); + // @formatter:on + } + + @Test + public void testGetPnf() { + ControlLoopEventContext context = new ControlLoopEventContext(onset); + params = params.toBuilder().context(context).build(); + operation = new GrpcOperation(params, config); + + // in neither property nor context + assertThatIllegalArgumentException().isThrownBy(() -> operation.getPnfData()).withMessage("missing PNF data"); + + // only in context + Pnf pnf = new Pnf(); + params.getContext().setProperty(AaiGetPnfOperation.getKey(params.getTargetEntity()), pnf); + assertSame(pnf, operation.getPnfData()); + + // both - should choose the property + Pnf pnf2 = new Pnf(); + operation.setProperty(OperationProperties.AAI_PNF, pnf2); + assertSame(pnf2, operation.getPnfData()); + } + + @Test + public void testGetServiceInstanceId() { + ControlLoopEventContext context = new ControlLoopEventContext(onset); + params = params.toBuilder().context(context).build(); + operation = new GrpcOperation(params, config); + + // in neither property nor custom query + context.setProperty(AaiCqResponse.CONTEXT_KEY, mock(AaiCqResponse.class)); + assertThatIllegalArgumentException().isThrownBy(() -> operation.getServiceInstanceId()) + .withMessage("Target service instance could not be found"); + + // only in custom query + loadCqData(params.getContext()); + assertEquals(MY_SVC_ID, operation.getServiceInstanceId()); + + // both - should choose the property + ServiceInstance serviceInstance = new ServiceInstance(); + serviceInstance.setServiceInstanceId("another-service-id"); + operation.setProperty(OperationProperties.AAI_SERVICE, serviceInstance); + assertEquals("another-service-id", operation.getServiceInstanceId()); + } + + @Test + public void testGetVnfId() { + ControlLoopEventContext context = new ControlLoopEventContext(onset); + params = params.toBuilder().context(context).build(); + operation = new GrpcOperation(params, config); + + // in neither property nor custom query + context.setProperty(AaiCqResponse.CONTEXT_KEY, mock(AaiCqResponse.class)); + assertThatIllegalArgumentException().isThrownBy(() -> operation.getVnfId()) + .withMessage("Target generic vnf could not be found"); + + // only in custom query + loadCqData(params.getContext()); + assertEquals(MY_VNF, operation.getVnfId()); + + // both - should choose the property + GenericVnf vnf = new GenericVnf(); + vnf.setVnfId("another-vnf-id"); + operation.setProperty(OperationProperties.AAI_RESOURCE_VNF, vnf); + assertEquals("another-vnf-id", operation.getVnfId()); + } + + @Test + public void testStartPreprocessorAsync() throws InterruptedException, ExecutionException, TimeoutException { + AtomicBoolean guardStarted = new AtomicBoolean(); operation = new GrpcOperation(params, config) { @Override protected CompletableFuture startGuardAsync() { guardStarted.set(true); - return future2; + return cqFuture; } }; @@ -140,9 +335,9 @@ public class GrpcOperationTest { assertTrue(guardStarted.get()); verify(context).obtain(eq(AaiCqResponse.CONTEXT_KEY), any()); - future2.complete(params.makeOutcome()); + cqFuture.complete(params.makeOutcome(null)); assertTrue(executor.runAll(100)); - assertEquals(PolicyResult.SUCCESS, future3.get(2, TimeUnit.SECONDS).getResult()); + assertEquals(OperationResult.SUCCESS, future3.get(2, TimeUnit.SECONDS).getResult()); assertTrue(future3.isDone()); } @@ -151,26 +346,15 @@ public class GrpcOperationTest { */ @Test public void testStartPreprocessorAsyncPnf() throws InterruptedException, ExecutionException, TimeoutException { - - CompletableFuture future2 = new CompletableFuture<>(); - ControlLoopEventContext context = mock(ControlLoopEventContext.class); - when(context.obtain(eq(AaiCqResponse.CONTEXT_KEY), any())).thenReturn(future2); - when(context.getEvent()).thenReturn(onset); - AtomicBoolean guardStarted = new AtomicBoolean(); - target.setType(TargetType.PNF); - - ControlLoopOperationParams params = ControlLoopOperationParams.builder().actor(CdsActorConstants.CDS_ACTOR) - .operation(GrpcOperation.NAME).context(context).actorService(new ActorService()) - .targetEntity(TARGET_ENTITY).target(target).build(); - GrpcConfig config = new GrpcConfig(executor, cdsProps); + params = params.toBuilder().targetType(TargetType.PNF).build(); operation = new GrpcOperation(params, config) { @Override protected CompletableFuture startGuardAsync() { guardStarted.set(true); - return future2; + return cqFuture; } }; @@ -179,12 +363,21 @@ public class GrpcOperationTest { assertTrue(guardStarted.get()); verify(context).obtain(eq(AaiGetPnfOperation.getKey(TARGET_ENTITY)), any()); - future2.complete(params.makeOutcome()); + cqFuture.complete(params.makeOutcome(null)); assertTrue(executor.runAll(100)); - assertEquals(PolicyResult.SUCCESS, future3.get(2, TimeUnit.SECONDS).getResult()); + assertEquals(OperationResult.SUCCESS, future3.get(2, TimeUnit.SECONDS).getResult()); assertTrue(future3.isDone()); } + /** + * Tests startPreprocessorAsync(), when preprocessing is disabled. + */ + @Test + public void testStartPreprocessorAsyncDisabled() { + params = params.toBuilder().preprocessed(true).build(); + assertNull(new GrpcOperation(params, config).startPreprocessorAsync()); + } + @Test public void testStartOperationAsync() throws Exception { @@ -200,7 +393,7 @@ public class GrpcOperationTest { @Test public void testStartOperationAsyncPnf() throws Exception { - target.setType(TargetType.PNF); + targetType = TargetType.PNF; ControlLoopEventContext context = new ControlLoopEventContext(onset); loadPnfData(context); @@ -221,15 +414,32 @@ public class GrpcOperationTest { @Test public void testStartOperationAsyncError() throws Exception { + operation = new GrpcOperation(params, config); + assertThatIllegalArgumentException() + .isThrownBy(() -> operation.startOperationAsync(1, params.makeOutcome(null))); + } - ControlLoopEventContext context = new ControlLoopEventContext(onset); - ControlLoopOperationParams params = ControlLoopOperationParams.builder().actor(CdsActorConstants.CDS_ACTOR) - .operation(GrpcOperation.NAME).context(context).actorService(new ActorService()) - .targetEntity(TARGET_ENTITY).target(target).build(); - - GrpcConfig config = new GrpcConfig(executor, cdsProps); + @Test + public void testGetAdditionalEventParams() { operation = new GrpcOperation(params, config); - assertThatIllegalArgumentException().isThrownBy(() -> operation.startOperationAsync(1, params.makeOutcome())); + + // in neither property nor context + assertNull(operation.getAdditionalEventParams()); + + final Map eventParams = Collections.emptyMap(); + + // only in context + onset.setAdditionalEventParams(eventParams); + assertSame(eventParams, operation.getAdditionalEventParams()); + + // both - should choose the property, even if it's null + operation.setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, null); + assertNull(operation.getAdditionalEventParams()); + + // both - should choose the property + final Map propParams = Collections.emptyMap(); + operation.setProperty(OperationProperties.EVENT_ADDITIONAL_PARAMS, propParams); + assertSame(propParams, operation.getAdditionalEventParams()); } private void verifyOperation(ControlLoopEventContext context) { @@ -240,7 +450,8 @@ public class GrpcOperationTest { ControlLoopOperationParams params = ControlLoopOperationParams.builder().actor(CdsActorConstants.CDS_ACTOR) .operation(GrpcOperation.NAME).context(context).actorService(new ActorService()) - .targetEntity(TARGET_ENTITY).target(target).payload(payloadMap).build(); + .targetEntity(TARGET_ENTITY).targetType(targetType).targetEntityIds(targetEntityIds) + .payload(payloadMap).build(); GrpcConfig config = new GrpcConfig(executor, cdsProps); operation = new GrpcOperation(params, config); @@ -248,7 +459,7 @@ public class GrpcOperationTest { assertEquals(1000, operation.getTimeoutMs(0)); assertEquals(2000, operation.getTimeoutMs(2)); operation.generateSubRequestId(1); - CompletableFuture future3 = operation.startOperationAsync(1, params.makeOutcome()); + CompletableFuture future3 = operation.startOperationAsync(1, params.makeOutcome(null)); assertNotNull(future3); }