diff options
author | Jim Hahn <jrh3@att.com> | 2020-03-03 21:02:13 -0500 |
---|---|---|
committer | Jim Hahn <jrh3@att.com> | 2020-03-05 15:42:01 -0500 |
commit | 03248c4de4197dac33c156e6a7a6538c9943305c (patch) | |
tree | 3224aa774d09649ed83d91a9a36f9bd969e701cf /models-interactions/model-actors/actor.so/src/test | |
parent | 7f1903bae3069d5e14b4c322c09c1317d90114b6 (diff) |
Add SO VF Module Delete Operation
Redesigned the SO Operation classes; moved some code from the subclass
to the superclass so it could be reused by the VF Module Delete Operation.
JerseyClient does not support DELETE with a request body, so had to
implement a delete() method using java11 HttpClient.
Fix some issues found while testing with drools-apps.
Added "delete" operation to SO simulator.
Issue-ID: POLICY-2371
Signed-off-by: Jim Hahn <jrh3@att.com>
Change-Id: I269fe13cf90c295ec2bbac92bc5a59b3820ea265
Diffstat (limited to 'models-interactions/model-actors/actor.so/src/test')
7 files changed, 577 insertions, 5 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 index 35f1ef823..f33d501b6 100644 --- 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 @@ -51,6 +51,7 @@ public abstract class BasicSoOperation extends BasicHttpOperation<SoRequest> { 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 MY_PATH = "my-path"; public static final String PATH_GET = "my-path-get/"; public static final int MAX_GETS = 3; public static final int WAIT_SEC_GETS = 20; @@ -108,6 +109,7 @@ public abstract class BasicSoOperation extends BasicHttpOperation<SoRequest> { protected void initConfig() { super.initConfig(); when(config.getClient()).thenReturn(client); + when(config.getPath()).thenReturn(MY_PATH); when(config.getMaxGets()).thenReturn(MAX_GETS); when(config.getPathGet()).thenReturn(PATH_GET); when(config.getWaitSecGet()).thenReturn(WAIT_SEC_GETS); diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/RestManagerResponseTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/RestManagerResponseTest.java new file mode 100644 index 000000000..7a9541cc4 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/RestManagerResponseTest.java @@ -0,0 +1,109 @@ +/*- + * ============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.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import javax.ws.rs.core.GenericType; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.StandardCoder; + +public class RestManagerResponseTest { + private static final Coder coder = new StandardCoder(); + + private static final int MY_STATUS = 200; + private static final String MY_TEXT = "{'text': 'hello'}".replace('\'', '"'); + + private RestManagerResponse resp; + + @Before + public void setUp() { + resp = new RestManagerResponse(MY_STATUS, MY_TEXT, coder); + } + + @Test + public void testGetStatus() { + assertEquals(MY_STATUS, resp.getStatus()); + } + + @Test + public void testClose() { + assertThatCode(() -> resp.close()).doesNotThrowAnyException(); + } + + @Test + public void testReadEntityClassOfT() { + // try with JSON + MyObject obj = resp.readEntity(MyObject.class); + assertNotNull(obj); + assertEquals("hello", obj.text); + + // try plain string + resp = new RestManagerResponse(MY_STATUS, "some text", coder); + assertEquals("some text", resp.readEntity(String.class)); + + // coder throws an exception + resp = new RestManagerResponse(MY_STATUS, "{invalid-json", coder); + assertThatIllegalArgumentException().isThrownBy(() -> resp.readEntity(MyObject.class)) + .withMessage("cannot decode response"); + } + + @Test + @SuppressWarnings("unchecked") + public void testUnsupported() { + GenericType<String> generic = GenericType.forInstance(String.class); + + assertThatThrownBy(() -> resp.hasEntity()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.bufferEntity()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getLength()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.readEntity(generic)).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.readEntity(generic, null)).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getStatusInfo()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getEntity()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getMediaType()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getLanguage()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getAllowedMethods()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getCookies()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getEntityTag()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getDate()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getLanguage()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getLastModified()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getLocation()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getLinks()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.hasLink(null)).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getLink(null)).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getLinkBuilder(null)).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getMetadata()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getStringHeaders()).isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> resp.getHeaderString(null)).isInstanceOf(UnsupportedOperationException.class); + } + + + private static class MyObject { + private String text; + } +} 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 b73a65e44..cdd8a334c 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 @@ -74,7 +74,8 @@ public class SoActorServiceProviderTest extends BasicActor { SoActorServiceProvider prov = new SoActorServiceProvider(); // verify that it has the operators we expect - var expected = Arrays.asList(VfModuleCreate.NAME).stream().sorted().collect(Collectors.toList()); + var expected = Arrays.asList(VfModuleCreate.NAME, VfModuleDelete.NAME).stream().sorted() + .collect(Collectors.toList()); var actual = prov.getOperationNames().stream().sorted().collect(Collectors.toList()); assertEquals(expected.toString(), actual.toString()); 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 index 8bd607f32..8c084b8dc 100644 --- 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 @@ -164,7 +164,7 @@ public class VfModuleCreateTest extends BasicSoOperation { CompletableFuture<OperationOutcome> future2 = oper.start(); - outcome = future2.get(500, TimeUnit.SECONDS); + outcome = future2.get(5, TimeUnit.SECONDS); assertEquals(PolicyResult.SUCCESS, outcome.getResult()); assertEquals(origCount + 1, oper.getVfCount()); @@ -192,7 +192,7 @@ public class VfModuleCreateTest extends BasicSoOperation { CompletableFuture<OperationOutcome> future2 = oper.start(); - outcome = future2.get(500, TimeUnit.SECONDS); + outcome = future2.get(5, TimeUnit.SECONDS); assertEquals(PolicyResult.SUCCESS, outcome.getResult()); } @@ -202,7 +202,7 @@ public class VfModuleCreateTest extends BasicSoOperation { // @formatter:off assertEquals( - "/serviceInstances/my-service-instance-id/vnfs/my-vnf-id/vfModules/scaleOut", + "/my-service-instance-id/vnfs/my-vnf-id/vfModules/scaleOut", pair.getLeft()); // @formatter:on diff --git a/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java new file mode 100644 index 000000000..c08fa37d1 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/java/org/onap/policy/controlloop/actor/so/VfModuleDeleteTest.java @@ -0,0 +1,440 @@ +/*- + * ============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.assertFalse; +import static org.junit.Assert.assertNotNull; +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.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.net.http.HttpHeaders; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.Builder; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +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 javax.ws.rs.client.InvocationCallback; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +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.Coder; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome; +import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams; +import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.so.SoRequest; +import org.onap.policy.so.SoResponse; + +public class VfModuleDeleteTest extends BasicSoOperation { + private static final String EXPECTED_EXCEPTION = "expected exception"; + 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"; + + @Mock + private java.net.http.HttpClient javaClient; + @Mock + private HttpResponse<String> javaResp; + @Mock + private InvocationCallback<Response> callback; + + private CompletableFuture<HttpResponse<String>> javaFuture; + private VfModuleDelete oper; + + public VfModuleDeleteTest() { + super(DEFAULT_ACTOR, VfModuleDelete.NAME); + } + + + /** + * Sets up. + */ + @Before + public void setUp() throws Exception { + super.setUp(); + + initHostPort(); + + configureResponse(coder.encode(response)); + + oper = new MyOperation(params, config); + } + + @Test + public void testConstructor() { + assertEquals(DEFAULT_ACTOR, oper.getActorName()); + assertEquals(VfModuleDelete.NAME, oper.getName()); + + // verify that target validation is done + params = params.toBuilder().target(null).build(); + assertThatIllegalArgumentException().isThrownBy(() -> new VfModuleDelete(params, config)) + .withMessageContaining("Target information"); + } + + @Test + public void testStartPreprocessorAsync() throws Exception { + // insert CQ data so it's there for the check + context.setProperty(AaiCqResponse.CONTEXT_KEY, makeCqResponse()); + + AtomicBoolean guardStarted = new AtomicBoolean(); + + oper = new MyOperation(params, config) { + @Override + protected CompletableFuture<OperationOutcome> startGuardAsync() { + guardStarted.set(true); + return super.startGuardAsync(); + } + }; + + CompletableFuture<OperationOutcome> future3 = oper.startPreprocessorAsync(); + assertNotNull(future3); + assertTrue(guardStarted.get()); + } + + @Test + public void testStartGuardAsync() throws Exception { + // remove CQ data so it's forced to query + context.removeProperty(AaiCqResponse.CONTEXT_KEY); + + CompletableFuture<OperationOutcome> future2 = oper.startPreprocessorAsync(); + assertTrue(executor.runAll(100)); + assertFalse(future2.isDone()); + + provideCqResponse(makeCqResponse()); + assertTrue(executor.runAll(100)); + assertTrue(future2.isDone()); + assertEquals(PolicyResult.SUCCESS, future2.get().getResult()); + } + + @Test + public void testMakeGuardPayload() { + final int origCount = 30; + oper.setVfCount(origCount); + + CompletableFuture<OperationOutcome> future2 = oper.startPreprocessorAsync(); + assertTrue(executor.runAll(100)); + assertTrue(future2.isDone()); + + // get the payload from the request + ArgumentCaptor<ControlLoopOperationParams> captor = ArgumentCaptor.forClass(ControlLoopOperationParams.class); + verify(guardOperator).buildOperation(captor.capture()); + + Map<String, Object> payload = captor.getValue().getPayload(); + assertNotNull(payload); + + @SuppressWarnings("unchecked") + Map<String, Object> resource = (Map<String, Object>) payload.get("resource"); + assertNotNull(resource); + + @SuppressWarnings("unchecked") + Map<String, Object> guard = (Map<String, Object>) resource.get("guard"); + assertNotNull(guard); + + Integer newCount = (Integer) guard.get(VfModuleDelete.PAYLOAD_KEY_VF_COUNT); + assertNotNull(newCount); + assertEquals(origCount - 1, newCount.intValue()); + } + + @Test + public void testStartOperationAsync_testSuccessfulCompletion() throws Exception { + final int origCount = 30; + oper.setVfCount(origCount); + + // use a real executor + params = params.toBuilder().executor(ForkJoinPool.commonPool()).build(); + + oper = new MyOperation(params, config) { + @Override + public long getWaitMsGet() { + return 1; + } + }; + + CompletableFuture<OperationOutcome> future2 = oper.start(); + + outcome = future2.get(5, TimeUnit.SECONDS); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + + assertEquals(origCount - 1, oper.getVfCount()); + } + + /** + * Tests startOperationAsync() when "get" operations are required. + */ + @Test + public void testStartOperationAsyncWithGets() throws Exception { + + // indicate that the response was incomplete + configureResponse(coder.encode(response).replace("COMPLETE", "incomplete")); + + when(rawResponse.getStatus()).thenReturn(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 MyOperation(params, config) { + @Override + public long getWaitMsGet() { + return 1; + } + }; + + CompletableFuture<OperationOutcome> future2 = oper.start(); + + outcome = future2.get(5, TimeUnit.SECONDS); + assertEquals(PolicyResult.SUCCESS, outcome.getResult()); + } + + @Test + public void testMakeRequest() throws CoderException { + Pair<String, SoRequest> pair = oper.makeRequest(); + + assertEquals("/my-service-instance-id/vnfs/my-vnf-id/vfModules/null", pair.getLeft()); + + verifyRequest("VfModuleDelete.json", pair.getRight()); + } + + @Test + public void testDelete() throws Exception { + SoRequest req = new SoRequest(); + req.setRequestId(REQ_ID); + + Map<String, Object> headers = Map.of("key-A", "value-A"); + + final CompletableFuture<Response> delFuture = + oper.delete("my-uri", headers, MediaType.APPLICATION_JSON, req, callback); + + ArgumentCaptor<HttpRequest> reqCaptor = ArgumentCaptor.forClass(HttpRequest.class); + verify(javaClient).sendAsync(reqCaptor.capture(), any()); + + HttpRequest req2 = reqCaptor.getValue(); + assertEquals("http://my-host:6969/my-uri", req2.uri().toString()); + assertEquals("DELETE", req2.method()); + + HttpHeaders headers2 = req2.headers(); + assertEquals("value-A", headers2.firstValue("key-A").orElse("missing-key")); + assertEquals(MediaType.APPLICATION_JSON, headers2.firstValue("Content-type").orElse("missing-key")); + + assertTrue(delFuture.isDone()); + Response resp = delFuture.get(); + + verify(callback).completed(resp); + + assertEquals(200, resp.getStatus()); + + SoResponse resp2 = resp.readEntity(SoResponse.class); + assertEquals(SoOperation.COMPLETE, resp2.getRequest().getRequestStatus().getRequestState()); + } + + /** + * Tests delete() when an exception is thrown in the future. + */ + @Test + @SuppressWarnings("unchecked") + public void testDeleteException() throws Exception { + Throwable thrown = new IllegalStateException(EXPECTED_EXCEPTION); + + // need a new future, with an exception + javaFuture = CompletableFuture.failedFuture(thrown); + when(javaClient.sendAsync(any(), any(BodyHandlers.ofString().getClass()))).thenReturn(javaFuture); + + SoRequest req = new SoRequest(); + req.setRequestId(REQ_ID); + + CompletableFuture<Response> delFuture = + oper.delete("/my-uri", Map.of(), MediaType.APPLICATION_JSON, req, callback); + + assertTrue(delFuture.isCompletedExceptionally()); + + ArgumentCaptor<Throwable> thrownCaptor = ArgumentCaptor.forClass(Throwable.class); + verify(callback).failed(thrownCaptor.capture()); + assertSame(thrown, thrownCaptor.getValue().getCause()); + } + + @Test + public void testEncodeBody() { + // try when request is already a string + assertEquals("hello", oper.encodeRequest("hello")); + + // try with a real request + SoRequest req = new SoRequest(); + req.setRequestId(REQ_ID); + assertEquals("{\"requestId\":\"" + REQ_ID.toString() + "\"}", oper.encodeRequest(req)); + + // coder throws an exception + oper = new MyOperation(params, config) { + @Override + protected Coder makeCoder() { + return new StandardCoder() { + @Override + public String encode(Object object) throws CoderException { + throw new CoderException(EXPECTED_EXCEPTION); + } + }; + } + }; + + assertThatIllegalArgumentException().isThrownBy(() -> oper.encodeRequest(req)) + .withMessage("cannot encode request"); + } + + /** + * Tests addAuthHeader() when there is a username, but no password. + */ + @Test + public void testAddAuthHeader() { + Builder builder = mock(Builder.class); + when(client.getUserName()).thenReturn("the-user"); + when(client.getPassword()).thenReturn("the-password"); + oper.addAuthHeader(builder); + + ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class); + + verify(builder).header(keyCaptor.capture(), valueCaptor.capture()); + + assertEquals("Authorization", keyCaptor.getValue()); + + String encoded = Base64.getEncoder().encodeToString("the-user:the-password".getBytes(StandardCharsets.UTF_8)); + assertEquals("Basic " + encoded, valueCaptor.getValue()); + } + + /** + * Tests addAuthHeader() when there is no username. + */ + @Test + public void testAddAuthHeaderNoUser() { + Builder builder = mock(Builder.class); + when(client.getPassword()).thenReturn("world"); + oper.addAuthHeader(builder); + verify(builder, never()).header(any(), any()); + + // repeat with empty username + when(client.getUserName()).thenReturn(""); + oper.addAuthHeader(builder); + verify(builder, never()).header(any(), any()); + } + + /** + * Tests addAuthHeader() when there is a username, but no password. + */ + @Test + public void testAddAuthHeaderUserOnly() { + Builder builder = mock(Builder.class); + when(client.getUserName()).thenReturn("my-user"); + oper.addAuthHeader(builder); + + ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class); + + verify(builder).header(keyCaptor.capture(), valueCaptor.capture()); + + assertEquals("Authorization", keyCaptor.getValue()); + + String encoded = Base64.getEncoder().encodeToString("my-user:".getBytes(StandardCharsets.UTF_8)); + assertEquals("Basic " + encoded, valueCaptor.getValue()); + } + + @Test + public void testMakeHttpClient() { + // must use a real operation to invoke this method + assertNotNull(new VfModuleDelete(params, config).makeHttpClient()); + } + + + @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); + } + + private void initHostPort() { + when(client.getBaseUrl()).thenReturn("http://my-host:6969/"); + } + + @SuppressWarnings("unchecked") + private void configureResponse(String responseText) throws CoderException { + // indicate that the response was completed + when(javaResp.statusCode()).thenReturn(200); + when(javaResp.body()).thenReturn(responseText); + + javaFuture = CompletableFuture.completedFuture(javaResp); + when(javaClient.sendAsync(any(), any(BodyHandlers.ofString().getClass()))).thenReturn(javaFuture); + } + + private class MyOperation extends VfModuleDelete { + + public MyOperation(ControlLoopOperationParams params, HttpConfig config) { + super(params, config); + } + + @Override + protected java.net.http.HttpClient makeHttpClient() { + return javaClient; + } + } +} diff --git a/models-interactions/model-actors/actor.so/src/test/resources/VfModuleDelete.json b/models-interactions/model-actors/actor.so/src/test/resources/VfModuleDelete.json new file mode 100644 index 000000000..5b7cce5f3 --- /dev/null +++ b/models-interactions/model-actors/actor.so/src/test/resources/VfModuleDelete.json @@ -0,0 +1,18 @@ +{ + "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": { + "source": "POLICY", + "suppressRollback": false, + "requestorId": "policy" + } + } +}
\ No newline at end of file diff --git a/models-interactions/model-actors/actor.so/src/test/resources/service.yaml b/models-interactions/model-actors/actor.so/src/test/resources/service.yaml index 4bf074fc5..e1cb0d9f3 100644 --- a/models-interactions/model-actors/actor.so/src/test/resources/service.yaml +++ b/models-interactions/model-actors/actor.so/src/test/resources/service.yaml @@ -28,4 +28,6 @@ actors: clientName: my-client operations: VF Module Create: - path: serviceInstantiation/v7
\ No newline at end of file + path: serviceInstantiation/v7/serviceInstances + VF Module Delete: + path: serviceInstances/v7
\ No newline at end of file |