diff options
author | Jim Hahn <jrh3@att.com> | 2020-02-18 12:25:37 -0500 |
---|---|---|
committer | Jim Hahn <jrh3@att.com> | 2020-02-19 12:45:30 -0500 |
commit | cbbc4a71ce71f22439b083107c65c22cc63bc9cc (patch) | |
tree | 5123d1b22ddd887d693b5007060cb3bdc7f0bad6 /models-interactions/model-actors/actor.so/src/test | |
parent | 4ccc26577b51545b4b4db6823c6d926bc0ffc5a4 (diff) |
Add SO actor
Issue-ID: POLICY-2371
Signed-off-by: Jim Hahn <jrh3@att.com>
Change-Id: I3faf0276e8039dc43a976d18ff8e704fdbec3d49
Diffstat (limited to 'models-interactions/model-actors/actor.so/src/test')
11 files changed, 1113 insertions, 0 deletions
diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/BasicSoOperation.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/BasicSoOperation.java new file mode 100644 index 000000000..089470420 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/BasicSoOperation.java @@ -0,0 +1,144 @@ +/*- + * ============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.controlloop.actor.so; + +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import org.mockito.Mock; +import org.onap.policy.controlloop.actor.test.BasicHttpOperation; +import org.onap.policy.controlloop.actorserviceprovider.Util; +import org.onap.policy.controlloop.policy.Target; +import org.onap.policy.so.SoRequest; +import org.onap.policy.so.SoRequestParameters; +import org.onap.policy.so.SoRequestReferences; +import org.onap.policy.so.SoRequestStatus; +import org.onap.policy.so.SoResponse; + +/** + * Superclass for various operator tests. + */ +public abstract class BasicSoOperation extends BasicHttpOperation<SoRequest> { + protected static final String[] IGNORE_FIELDS = {"RequestID", "subRequestID", "seconds", "nanos"}; + + public static final String MODEL_CUSTOM_ID = "my-model-customization-id"; + public static final String MODEL_INVAR_ID = "my-model-invariant-id"; + public static final String MODEL_NAME = "my-model-name"; + public static final String MODEL_VERSION = "my-model-version"; + public static final String MODEL_VERS_ID = "my-model-version-id"; + public static final String SUBSCRIPTION_SVC_TYPE = "my-subscription-service-type"; + public static final String PATH_GET = "my-path-get/"; + public static final int MAX_GETS = 3; + public static final int WAIT_SEC_GETS = 20; + + @Mock + protected SoOperator soOperator; + + protected Target target; + protected SoResponse response; + + /** + * Constructs the object using a default actor and operation name. + */ + public BasicSoOperation() { + super(); + } + + /** + * Constructs the object. + * + * @param actor actor name + * @param operation operation name + */ + public BasicSoOperation(String actor, String operation) { + super(actor, operation); + } + + /** + * Initializes mocks and sets up. + */ + public void setUp() throws Exception { + super.setUp(); + + response = new SoResponse(); + + SoRequest request = new SoRequest(); + response.setRequest(request); + + SoRequestStatus status = new SoRequestStatus(); + request.setRequestStatus(status); + status.setRequestState(SoOperation.COMPLETE); + + SoRequestReferences ref = new SoRequestReferences(); + response.setRequestReferences(ref); + ref.setRequestId(REQ_ID.toString()); + + when(rawResponse.getStatus()).thenReturn(200); + when(rawResponse.readEntity(String.class)).thenReturn(coder.encode(response)); + + operator = soOperator; + + initOperator(); + } + + @Override + protected void initOperator() { + super.initOperator(); + when(soOperator.getMaxGets()).thenReturn(MAX_GETS); + when(soOperator.getPathGet()).thenReturn(PATH_GET); + when(soOperator.getWaitSecGet()).thenReturn(WAIT_SEC_GETS); + } + + @Override + protected void makeContext() { + super.makeContext(); + + target = new Target(); + target.setModelCustomizationId(MODEL_CUSTOM_ID); + target.setModelInvariantId(MODEL_INVAR_ID); + target.setModelName(MODEL_NAME); + target.setModelVersion(MODEL_VERSION); + target.setModelVersionId(MODEL_VERS_ID); + + params = params.toBuilder().target(target).build(); + } + + @Override + protected Map<String, String> makePayload() { + Map<String, String> payload = new HashMap<>(); + + // request parameters + SoRequestParameters reqParams = new SoRequestParameters(); + reqParams.setSubscriptionServiceType(SUBSCRIPTION_SVC_TYPE); + payload.put(SoOperation.REQ_PARAM_NM, Util.translate("", reqParams, String.class)); + + // config parameters + List<Map<String, String>> config = new LinkedList<>(); + config.add(Collections.emptyMap()); + payload.put(SoOperation.CONFIG_PARAM_NM, Util.translate("", config, String.class)); + + return payload; + } +} diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorParamsTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorParamsTest.java new file mode 100644 index 000000000..f463fcb94 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorParamsTest.java @@ -0,0 +1,116 @@ +/*- + * ============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.controlloop.actor.so; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Map; +import java.util.TreeMap; +import java.util.function.Consumer; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.common.parameters.ValidationResult; +import org.onap.policy.controlloop.actorserviceprovider.Util; + + +public class SoActorParamsTest { + private static final String CONTAINER = "my-container"; + private static final String CLIENT = "my-client"; + private static final String PATH_GET = "my-path-get"; + private static final int MAX_GETS = 3; + private static final int WAIT_SEC_GETS = 20; + private static final int TIMEOUT = 10; + + private static final String PATH1 = "path #1"; + private static final String PATH2 = "path #2"; + private static final String URI1 = "uri #1"; + private static final String URI2 = "uri #2"; + + private Map<String, Map<String, Object>> operations; + private SoActorParams params; + + /** + * Initializes {@link #operations} with two items and {@link params} with a fully + * populated object. + */ + @Before + public void setUp() { + operations = new TreeMap<>(); + operations.put(PATH1, Map.of("path", URI1)); + operations.put(PATH2, Map.of("path", URI2)); + + params = makeSoActorParams(); + } + + @Test + public void testValidate() { + assertTrue(params.validate(CONTAINER).isValid()); + + // only a few fields are required + SoActorParams sparse = Util.translate(CONTAINER, Map.of("operation", operations), SoActorParams.class); + assertTrue(sparse.validate(CONTAINER).isValid()); + + testValidateField("maxGets", "minimum", params2 -> params2.setMaxGets(-1)); + testValidateField("waitSecGet", "minimum", params2 -> params2.setWaitSecGet(0)); + + // check fields from superclass + testValidateField("operation", "null", params2 -> params2.setOperation(null)); + testValidateField("timeoutSec", "minimum", params2 -> params2.setTimeoutSec(-1)); + + // check edge cases + params.setMaxGets(0); + assertTrue(params.validate(CONTAINER).isValid()); + params.setMaxGets(MAX_GETS); + + params.setWaitSecGet(1); + assertTrue(params.validate(CONTAINER).isValid()); + params.setWaitSecGet(WAIT_SEC_GETS); + } + + private void testValidateField(String fieldName, String expected, Consumer<SoActorParams> makeInvalid) { + + // original params should be valid + ValidationResult result = params.validate(CONTAINER); + assertTrue(fieldName, result.isValid()); + + // make invalid params + SoActorParams params2 = makeSoActorParams(); + makeInvalid.accept(params2); + result = params2.validate(CONTAINER); + assertFalse(fieldName, result.isValid()); + assertThat(result.getResult()).contains(CONTAINER).contains(fieldName).contains(expected); + } + + private SoActorParams makeSoActorParams() { + SoActorParams params2 = new SoActorParams(); + params2.setClientName(CLIENT); + params2.setTimeoutSec(TIMEOUT); + params2.setOperation(operations); + + params2.setWaitSecGet(WAIT_SEC_GETS); + params2.setMaxGets(MAX_GETS); + params2.setPathGet(PATH_GET); + + return params2; + } +} diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java index b46ac52fb..a9d5b8192 100644 --- a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoActorServiceProviderTest.java @@ -29,11 +29,13 @@ import static org.junit.Assert.assertNull; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.UUID; +import java.util.stream.Collectors; import org.apache.commons.io.IOUtils; import org.junit.Test; import org.onap.policy.aai.AaiCqResponse; @@ -66,6 +68,17 @@ public class SoActorServiceProviderTest { } @Test + public void testConstructor() { + SoActorServiceProvider prov = new SoActorServiceProvider(); + + // verify that it has the operators we expect + var expected = Arrays.asList(VfModuleCreate.NAME).stream().sorted().collect(Collectors.toList()); + var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); + + assertEquals(expected.toString(), actual.toString()); + } + + @Test public void testSendRequest() { SoActorServiceProvider.sendRequest(UUID.randomUUID().toString(), null, null, null, null, null); } diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java new file mode 100644 index 000000000..e70413876 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperationTest.java @@ -0,0 +1,353 @@ +/*- + * ============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.controlloop.actor.so; + +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.junit.Assert.assertEquals; +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.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; +import java.util.function.Supplier; +import org.junit.Before; +import org.junit.Test; +import org.onap.aai.domain.yang.CloudRegion; +import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aai.domain.yang.Tenant; +import org.onap.policy.aai.AaiCqResponse; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.controlloop.ControlLoopOperation; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.so.SoModelInfo; +import org.onap.policy.so.SoRequest; +import org.onap.policy.so.SoRequestInfo; +import org.onap.policy.so.SoRequestParameters; +import org.onap.policy.so.SoRequestReferences; +import org.onap.policy.so.SoRequestStatus; +import org.onap.policy.so.SoResponse; + +public class SoOperationTest extends BasicSoOperation { + + private SoOperation oper; + + /** + * Sets up. + */ + @Before + public void setUp() throws Exception { + super.setUp(); + + initOperator(); + + oper = new SoOperation(params, soOperator) {}; + } + + @Test + public void testConstructor_testGetWaitMsGet() { + assertEquals(DEFAULT_ACTOR, oper.getActorName()); + assertEquals(DEFAULT_OPERATION, oper.getName()); + assertSame(soOperator, oper.getOperator()); + assertEquals(1000 * WAIT_SEC_GETS, oper.getWaitMsGet()); + } + + @Test + public void testStartPreprocessorAsync() { + AtomicBoolean guardStarted = new AtomicBoolean(); + + oper = new SoOperation(params, soOperator) { + @Override + protected CompletableFuture<OperationOutcome> startGuardAsync() { + guardStarted.set(true); + return super.startGuardAsync(); + } + }; + + assertNull(oper.startPreprocessorAsync()); + assertTrue(guardStarted.get()); + } + + @Test + public void testPostProcess() throws Exception { + // completed + CompletableFuture<OperationOutcome> future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response); + assertTrue(future2.isDone()); + assertSame(outcome, future2.get()); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + + // failed + response.getRequest().getRequestStatus().setRequestState(SoOperation.FAILED); + future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response); + assertTrue(future2.isDone()); + assertSame(outcome, future2.get()); + assertEquals(PolicyResult.FAILURE, outcome.getResult()); + + // no request id in the response + response.getRequestReferences().setRequestId(null); + response.getRequest().getRequestStatus().setRequestState("unknown"); + assertThatIllegalArgumentException() + .isThrownBy(() -> oper.postProcessResponse(outcome, PATH, rawResponse, response)) + .withMessage("missing request ID in response"); + response.getRequestReferences().setRequestId(REQ_ID.toString()); + + // status = 500 + when(rawResponse.getStatus()).thenReturn(500); + + // null request reference + SoRequestReferences ref = response.getRequestReferences(); + response.setRequestReferences(null); + assertThatIllegalArgumentException() + .isThrownBy(() -> oper.postProcessResponse(outcome, PATH, rawResponse, response)) + .withMessage("missing request ID in response"); + response.setRequestReferences(ref); + } + + /** + * Tests postProcess() when the "get" is repeated a couple of times. + */ + @Test + public void testPostProcessRepeated_testResetGetCount() throws Exception { + /* + * Two failures and then a success - should result in two "get" calls. + * + * Note: getStatus() is invoked twice during each call, so have to double up the + * return values. + */ + when(rawResponse.getStatus()).thenReturn(500, 500, 500, 500, 200, 200); + + when(client.get(any(), any(), any())).thenAnswer(provideResponse(rawResponse)); + + // use a real executor + params = params.toBuilder().executor(ForkJoinPool.commonPool()).build(); + + oper = new SoOperation(params, soOperator) { + @Override + public long getWaitMsGet() { + return 1; + } + }; + + CompletableFuture<OperationOutcome> future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response); + + assertSame(outcome, future2.get(5, TimeUnit.SECONDS)); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + assertEquals(2, oper.getGetCount()); + + /* + * repeat - this time, the "get" operations will be exhausted, so it should fail + */ + when(rawResponse.getStatus()).thenReturn(500); + + future2 = oper.postProcessResponse(outcome, PATH, rawResponse, response); + + assertSame(outcome, future2.get(5, TimeUnit.SECONDS)); + assertEquals(PolicyResult.FAILURE_TIMEOUT, outcome.getResult()); + assertEquals(MAX_GETS + 1, oper.getGetCount()); + + oper.resetGetCount(); + assertEquals(0, oper.getGetCount()); + } + + @Test + public void testGetRequestState() { + SoResponse resp = new SoResponse(); + assertNull(oper.getRequestState(resp)); + + SoRequest req = new SoRequest(); + resp.setRequest(req); + assertNull(oper.getRequestState(resp)); + + SoRequestStatus status = new SoRequestStatus(); + req.setRequestStatus(status); + assertNull(oper.getRequestState(resp)); + + status.setRequestState("my-state"); + assertEquals("my-state", oper.getRequestState(resp)); + } + + @Test + public void testIsSuccess() { + // always true + + assertTrue(oper.isSuccess(rawResponse, response)); + + when(rawResponse.getStatus()).thenReturn(500); + assertTrue(oper.isSuccess(rawResponse, response)); + } + + @Test + public void testSetOutcome() { + // success case + when(rawResponse.getStatus()).thenReturn(200); + assertSame(outcome, oper.setOutcome(outcome, PolicyResult.SUCCESS, rawResponse, response)); + + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + assertEquals("200 " + ControlLoopOperation.SUCCESS_MSG, outcome.getMessage()); + + // failure case + when(rawResponse.getStatus()).thenReturn(500); + assertSame(outcome, oper.setOutcome(outcome, PolicyResult.FAILURE, rawResponse, response)); + + assertEquals(PolicyResult.FAILURE, outcome.getResult()); + assertEquals("500 " + ControlLoopOperation.FAILED_MSG, outcome.getMessage()); + } + + @Test + public void testPrepareSoModelInfo() throws CoderException { + verifyMissingModelInfo(target::getModelCustomizationId, target::setModelCustomizationId); + verifyMissingModelInfo(target::getModelInvariantId, target::setModelInvariantId); + verifyMissingModelInfo(target::getModelName, target::setModelName); + verifyMissingModelInfo(target::getModelVersion, target::setModelVersion); + verifyMissingModelInfo(target::getModelVersionId, target::setModelVersionId); + + // valid data + SoModelInfo info = oper.prepareSoModelInfo(); + verifyRequest("model.json", info); + + // try with null target + params = params.toBuilder().target(null).build(); + oper = new SoOperation(params, soOperator) {}; + + assertThatIllegalArgumentException().isThrownBy(() -> oper.prepareSoModelInfo()).withMessage("missing Target"); + } + + private void verifyMissingModelInfo(Supplier<String> getter, Consumer<String> setter) { + String original = getter.get(); + + setter.accept(null); + assertThatIllegalArgumentException().isThrownBy(() -> oper.prepareSoModelInfo()) + .withMessage("missing VF Module model"); + + setter.accept(original); + } + + @Test + public void testConstructRequestInfo() throws CoderException { + SoRequestInfo info = oper.constructRequestInfo(); + verifyRequest("reqinfo.json", info); + } + + @Test + public void testBuildRequestParameters() throws CoderException { + // valid data + SoRequestParameters reqParams = oper.buildRequestParameters(); + verifyRequest("reqparams.json", reqParams); + + // invalid json + params.getPayload().put(SoOperation.REQ_PARAM_NM, "{invalid json"); + assertThatIllegalArgumentException().isThrownBy(() -> oper.buildRequestParameters()) + .withMessage("invalid payload value: " + SoOperation.REQ_PARAM_NM); + + // missing data + params.getPayload().remove(SoOperation.REQ_PARAM_NM); + assertNull(oper.buildRequestParameters()); + + // null payload + params = params.toBuilder().payload(null).build(); + oper = new SoOperation(params, soOperator) {}; + assertNull(oper.buildRequestParameters()); + } + + @Test + public void testBuildConfigurationParameters() { + // valid data + List<Map<String, String>> result = oper.buildConfigurationParameters(); + assertEquals(List.of(Collections.emptyMap()), result); + + // invalid json + params.getPayload().put(SoOperation.CONFIG_PARAM_NM, "{invalid json"); + assertThatIllegalArgumentException().isThrownBy(() -> oper.buildConfigurationParameters()) + .withMessage("invalid payload value: " + SoOperation.CONFIG_PARAM_NM); + + // missing data + params.getPayload().remove(SoOperation.CONFIG_PARAM_NM); + assertNull(oper.buildConfigurationParameters()); + + // null payload + params = params.toBuilder().payload(null).build(); + oper = new SoOperation(params, soOperator) {}; + assertNull(oper.buildConfigurationParameters()); + } + + @Test + public void testGetVnfItem() { + // missing data + AaiCqResponse cq = mock(AaiCqResponse.class); + assertThatIllegalArgumentException().isThrownBy(() -> oper.getVnfItem(cq, oper.prepareSoModelInfo())) + .withMessage("missing generic VNF"); + + // valid data + GenericVnf vnf = new GenericVnf(); + when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(vnf); + assertSame(vnf, oper.getVnfItem(cq, oper.prepareSoModelInfo())); + } + + @Test + public void testGetServiceInstance() { + // missing data + AaiCqResponse cq = mock(AaiCqResponse.class); + assertThatIllegalArgumentException().isThrownBy(() -> oper.getServiceInstance(cq)) + .withMessage("missing VNF Service Item"); + + // valid data + ServiceInstance instance = new ServiceInstance(); + when(cq.getServiceInstance()).thenReturn(instance); + assertSame(instance, oper.getServiceInstance(cq)); + } + + @Test + public void testGetDefaultTenant() { + // missing data + AaiCqResponse cq = mock(AaiCqResponse.class); + assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultTenant(cq)) + .withMessage("missing Tenant Item"); + + // valid data + Tenant tenant = new Tenant(); + when(cq.getDefaultTenant()).thenReturn(tenant); + assertSame(tenant, oper.getDefaultTenant(cq)); + } + + @Test + public void testGetDefaultCloudRegion() { + // missing data + AaiCqResponse cq = mock(AaiCqResponse.class); + assertThatIllegalArgumentException().isThrownBy(() -> oper.getDefaultCloudRegion(cq)) + .withMessage("missing Cloud Region"); + + // valid data + CloudRegion region = new CloudRegion(); + when(cq.getDefaultCloudRegion()).thenReturn(region); + assertSame(region, oper.getDefaultCloudRegion(cq)); + } +} diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperatorTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperatorTest.java new file mode 100644 index 000000000..16bbdea2a --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoOperatorTest.java @@ -0,0 +1,146 @@ +/*- + * ============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.controlloop.actor.so; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.mockito.Mockito.when; + +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.common.endpoints.http.client.HttpClient; +import org.onap.policy.common.endpoints.http.client.HttpClientFactory; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.Util; +import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ParameterValidationRuntimeException; + +public class SoOperatorTest { + private static final String ACTOR = "my-actor"; + private static final String OPERATION = "my-name"; + private static final String CLIENT = "my-client"; + private static final String PATH = "/my-path"; + private static final String PATH_GET = "my-path-get/"; + private static final int MAX_GETS = 3; + private static final int WAIT_SEC_GETS = 20; + private static final int TIMEOUT = 100; + + @Mock + private HttpClient client; + + @Mock + private HttpClientFactory factory; + + + private SoOperator oper; + + /** + * Initializes fields, including {@link #oper}, and resets the static fields used by + * the REST server. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(factory.get(CLIENT)).thenReturn(client); + + oper = new MyOperator(); + + SoParams params = SoParams.builder().pathGet(PATH_GET).maxGets(MAX_GETS).waitSecGet(WAIT_SEC_GETS) + .clientName(CLIENT).path(PATH).timeoutSec(TIMEOUT).build(); + Map<String, Object> paramMap = Util.translateToMap(OPERATION, params); + oper.configure(paramMap); + } + + @Test + public void testConstructor() { + assertEquals(ACTOR, oper.getActorName()); + assertEquals(OPERATION, oper.getName()); + assertEquals(ACTOR + "." + OPERATION, oper.getFullName()); + } + + @Test + public void testMakeSoOperator() { + oper = SoOperator.makeSoOperator(ACTOR, OPERATION, MyOperation::new); + + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + ControlLoopEventContext context = new ControlLoopEventContext(event); + ControlLoopOperationParams params = + ControlLoopOperationParams.builder().actor(ACTOR).operation(OPERATION).context(context).build(); + + Operation operation1 = oper.buildOperation(params); + assertNotNull(operation1); + + Operation operation2 = oper.buildOperation(params); + assertNotNull(operation2); + assertNotSame(operation1, operation2); + } + + @Test + public void testDoConfigure_testGetters() { + // should use given values + assertSame(client, oper.getClient()); + assertEquals(PATH_GET, oper.getPathGet()); + assertEquals(MAX_GETS, oper.getMaxGets()); + assertEquals(WAIT_SEC_GETS, oper.getWaitSecGet()); + + SoParams params = SoParams.builder().pathGet("unslashed").maxGets(MAX_GETS).waitSecGet(WAIT_SEC_GETS) + .clientName(CLIENT).path(PATH).timeoutSec(TIMEOUT).build(); + Map<String, Object> paramMap = Util.translateToMap(OPERATION, params); + oper.configure(paramMap); + assertEquals("unslashed/", oper.getPathGet()); + + // test invalid parameters + Map<String, Object> paramMap2 = Util.translateToMap(OPERATION, SoParams.builder().build()); + assertThatThrownBy(() -> oper.configure(paramMap2)).isInstanceOf(ParameterValidationRuntimeException.class); + } + + + private class MyOperator extends SoOperator { + public MyOperator() { + super(ACTOR, OPERATION); + } + + @Override + public Operation buildOperation(ControlLoopOperationParams params) { + return null; + } + + @Override + protected HttpClientFactory getClientFactory() { + return factory; + } + } + + private class MyOperation extends SoOperation { + public MyOperation(ControlLoopOperationParams params, SoOperator operator) { + super(params, operator); + } + } +} diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoParamsTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoParamsTest.java new file mode 100644 index 000000000..2b02ad8ff --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/SoParamsTest.java @@ -0,0 +1,92 @@ +/*- + * ============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.controlloop.actor.so; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.function.Function; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.common.parameters.ValidationResult; +import org.onap.policy.controlloop.actor.so.SoParams.SoParamsBuilder; +import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams.HttpParamsBuilder; + +public class SoParamsTest { + private static final String CONTAINER = "my-container"; + private static final String CLIENT = "my-client"; + private static final String PATH = "my-path"; + private static final String PATH_GET = "my-path-get"; + private static final int MAX_GETS = 3; + private static final int WAIT_SEC_GETS = 20; + private static final int TIMEOUT = 10; + + private SoParams params; + + @Before + public void setUp() { + params = SoParams.builder().pathGet(PATH_GET).maxGets(MAX_GETS).waitSecGet(WAIT_SEC_GETS).clientName(CLIENT) + .path(PATH).timeoutSec(TIMEOUT).build(); + } + + @Test + public void testValidate() { + assertTrue(params.validate(CONTAINER).isValid()); + + testValidateField("pathGet", "null", bldr -> bldr.pathGet(null)); + testValidateField("maxGets", "minimum", bldr -> bldr.maxGets(-1)); + testValidateField("waitSecGet", "minimum", bldr -> bldr.waitSecGet(-1)); + + // validate one of the superclass fields + testValidateField("clientName", "null", bldr -> bldr.clientName(null)); + + // check edge cases + assertTrue(params.toBuilder().maxGets(0).build().validate(CONTAINER).isValid()); + assertFalse(params.toBuilder().waitSecGet(0).build().validate(CONTAINER).isValid()); + assertTrue(params.toBuilder().waitSecGet(1).build().validate(CONTAINER).isValid()); + } + + @Test + public void testBuilder_testToBuilder() { + assertEquals(CLIENT, params.getClientName()); + + assertEquals(PATH_GET, params.getPathGet()); + assertEquals(MAX_GETS, params.getMaxGets()); + assertEquals(WAIT_SEC_GETS, params.getWaitSecGet()); + + assertEquals(params, params.toBuilder().build()); + } + + private void testValidateField(String fieldName, String expected, + @SuppressWarnings("rawtypes") Function<SoParamsBuilder, HttpParamsBuilder> makeInvalid) { + + // original params should be valid + ValidationResult result = params.validate(CONTAINER); + assertTrue(fieldName, result.isValid()); + + // make invalid params + result = makeInvalid.apply(params.toBuilder()).build().validate(CONTAINER); + assertFalse(fieldName, result.isValid()); + assertThat(result.getResult()).contains(fieldName).contains(expected); + } +} diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java new file mode 100644 index 000000000..40efdc880 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleCreateTest.java @@ -0,0 +1,182 @@ +/*- + * ============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.controlloop.actor.so; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.Before; +import org.junit.Test; +import org.onap.aai.domain.yang.CloudRegion; +import org.onap.aai.domain.yang.GenericVnf; +import org.onap.aai.domain.yang.ModelVer; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aai.domain.yang.Tenant; +import org.onap.policy.aai.AaiCqResponse; +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.so.SoRequest; + +public class VfModuleCreateTest extends BasicSoOperation { + private static final String MODEL_NAME2 = "my-model-name-B"; + private static final String MODEL_VERS2 = "my-model-version-B"; + private static final String SVC_INSTANCE_ID = "my-service-instance-id"; + private static final String VNF_ID = "my-vnf-id"; + + private VfModuleCreate oper; + + public VfModuleCreateTest() { + super(DEFAULT_ACTOR, VfModuleCreate.NAME); + } + + + @Before + public void setUp() throws Exception { + super.setUp(); + oper = new VfModuleCreate(params, soOperator); + } + + @Test + public void testConstructor() { + assertEquals(DEFAULT_ACTOR, oper.getActorName()); + assertEquals(VfModuleCreate.NAME, oper.getName()); + } + + @Test + public void testStartPreprocessorAsync() { + CompletableFuture<OperationOutcome> future = new CompletableFuture<>(); + context = mock(ControlLoopEventContext.class); + when(context.obtain(eq(AaiCqResponse.CONTEXT_KEY), any())).thenReturn(future); + params = params.toBuilder().context(context).build(); + + AtomicBoolean guardStarted = new AtomicBoolean(); + + oper = new VfModuleCreate(params, soOperator) { + @Override + protected CompletableFuture<OperationOutcome> startGuardAsync() { + guardStarted.set(true); + return super.startGuardAsync(); + } + }; + + assertSame(future, oper.startPreprocessorAsync()); + assertFalse(future.isDone()); + assertTrue(guardStarted.get()); + } + + @Test + public void testStartOperationAsync() throws Exception { + when(client.post(any(), any(), any(), any())).thenAnswer(provideResponse(rawResponse)); + + // use a real executor + params = params.toBuilder().executor(ForkJoinPool.commonPool()).build(); + + oper = new VfModuleCreate(params, soOperator) { + @Override + public long getWaitMsGet() { + return 1; + } + }; + + CompletableFuture<OperationOutcome> future2 = oper.start(); + + outcome = future2.get(500, TimeUnit.SECONDS); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + } + + /** + * Tests startOperationAsync() when "get" operations are required. + */ + @Test + public void testStartOperationAsyncWithGets() throws Exception { + when(rawResponse.getStatus()).thenReturn(500, 500, 500, 500, 200, 200); + + when(client.post(any(), any(), any(), any())).thenAnswer(provideResponse(rawResponse)); + when(client.get(any(), any(), any())).thenAnswer(provideResponse(rawResponse)); + + // use a real executor + params = params.toBuilder().executor(ForkJoinPool.commonPool()).build(); + + oper = new VfModuleCreate(params, soOperator) { + @Override + public long getWaitMsGet() { + return 1; + } + }; + + CompletableFuture<OperationOutcome> future2 = oper.start(); + + outcome = future2.get(500, TimeUnit.SECONDS); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + } + + @Test + public void testMakeRequest() throws CoderException { + Pair<String, SoRequest> pair = oper.makeRequest(); + + // @formatter:off + assertEquals( + "/serviceInstantiation/v7/serviceInstances/my-service-instance-id/vnfs/my-vnf-id/vfModules/scaleOut", + pair.getLeft()); + // @formatter:on + + verifyRequest("vfModuleCreate.json", pair.getRight()); + } + + + @Override + protected void makeContext() { + super.makeContext(); + + AaiCqResponse cq = mock(AaiCqResponse.class); + + GenericVnf vnf = new GenericVnf(); + when(cq.getGenericVnfByVfModuleModelInvariantId(MODEL_INVAR_ID)).thenReturn(vnf); + vnf.setVnfId(VNF_ID); + + ServiceInstance instance = new ServiceInstance(); + when(cq.getServiceInstance()).thenReturn(instance); + instance.setServiceInstanceId(SVC_INSTANCE_ID); + + when(cq.getDefaultTenant()).thenReturn(new Tenant()); + when(cq.getDefaultCloudRegion()).thenReturn(new CloudRegion()); + + ModelVer modelVers = new ModelVer(); + when(cq.getModelVerByVersionId(any())).thenReturn(modelVers); + modelVers.setModelName(MODEL_NAME2); + modelVers.setModelVersion(MODEL_VERS2); + + params.getContext().setProperty(AaiCqResponse.CONTEXT_KEY, cq); + } +} diff --git a/models-interactions/model-actors/actor.so/src/test/resources/model.json b/models-interactions/model-actors/actor.so/src/test/resources/model.json new file mode 100644 index 000000000..133b0fe91 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/resources/model.json @@ -0,0 +1,8 @@ +{ + "modelType": "vfModule", + "modelInvariantId": "my-model-invariant-id", + "modelVersionId": "my-model-version-id", + "modelName": "my-model-name", + "modelVersion": "my-model-version", + "modelCustomizationId": "my-model-customization-id" +}
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.so/src/test/resources/reqinfo.json b/models-interactions/model-actors/actor.so/src/test/resources/reqinfo.json new file mode 100644 index 000000000..62d6eb1e6 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/resources/reqinfo.json @@ -0,0 +1,5 @@ +{ + "source": "POLICY", + "suppressRollback": false, + "requestorId": "policy" +}
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.so/src/test/resources/reqparams.json b/models-interactions/model-actors/actor.so/src/test/resources/reqparams.json new file mode 100644 index 000000000..44598ac81 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/resources/reqparams.json @@ -0,0 +1,5 @@ +{ + "subscriptionServiceType": "my-subscription-service-type", + "usePreload": false, + "userParams": [] +}
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.so/src/test/resources/vfModuleCreate.json b/models-interactions/model-actors/actor.so/src/test/resources/vfModuleCreate.json new file mode 100644 index 000000000..06258f3f3 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/resources/vfModuleCreate.json @@ -0,0 +1,49 @@ +{ + "requestDetails": { + "modelInfo": { + "modelType": "vfModule", + "modelInvariantId": "my-model-invariant-id", + "modelVersionId": "my-model-version-id", + "modelName": "my-model-name", + "modelVersion": "my-model-version", + "modelCustomizationId": "my-model-customization-id" + }, + "cloudConfiguration": {}, + "requestInfo": { + "instanceName": "vfModuleName", + "source": "POLICY", + "suppressRollback": false, + "requestorId": "policy" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "my-service-instance-id", + "modelInfo": { + "modelType": "service", + "modelName": "my-model-name-B", + "modelVersion": "my-model-version-B" + } + } + }, + { + "relatedInstance": { + "instanceId": "my-vnf-id", + "modelInfo": { + "modelType": "vnf", + "modelName": "my-model-name-B", + "modelVersion": "my-model-version-B" + } + } + } + ], + "requestParameters": { + "subscriptionServiceType": "my-subscription-service-type", + "usePreload": false, + "userParams": [] + }, + "configurationParameters": [ + {} + ] + } +}
\ No newline at end of file |