diff options
Diffstat (limited to 'runtime-acm/src/test/java')
16 files changed, 3598 insertions, 0 deletions
diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java new file mode 100644 index 000000000..35731d0e0 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java @@ -0,0 +1,221 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.commissioning; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; +import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ServiceTemplateProvider; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.models.tosca.authorative.concepts.ToscaCapabilityType; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType; +import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeType; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; +import org.onap.policy.models.tosca.authorative.concepts.ToscaRelationshipType; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate; + +class CommissioningProviderTest { + private static final String TOSCA_SERVICE_TEMPLATE_YAML = + "src/test/resources/rest/servicetemplates/pmsh_multiple_ac_tosca.yaml"; + private static final String COMMON_TOSCA_SERVICE_TEMPLATE_YAML = + "src/test/resources/rest/servicetemplates/full-tosca-with-common-properties.yaml"; + + private static final Coder CODER = new StandardCoder(); + private final ObjectMapper mapper = new ObjectMapper(); + + /** + * Test the fetching of automation composition definitions (ToscaServiceTemplates). + * + * @throws Exception . + */ + @Test + void testGetAutomationCompositionDefinitions() throws Exception { + var acProvider = mock(AutomationCompositionProvider.class); + var participantProvider = mock(ParticipantProvider.class); + var serviceTemplateProvider = mock(ServiceTemplateProvider.class); + + CommissioningProvider provider = + new CommissioningProvider(serviceTemplateProvider, acProvider, null, participantProvider); + + List<ToscaNodeTemplate> listOfTemplates = provider.getAutomationCompositionDefinitions(null, null); + assertThat(listOfTemplates).isEmpty(); + + when(acProvider.getFilteredNodeTemplates(any())) + .thenReturn(List.of(new ToscaNodeTemplate(), new ToscaNodeTemplate())); + listOfTemplates = provider.getAutomationCompositionDefinitions(null, null); + assertThat(listOfTemplates).hasSize(2); + } + + /** + * Test the creation of automation composition definitions (ToscaServiceTemplates). + * + * @throws Exception . + */ + @Test + void testCreateAutomationCompositionDefinitions() throws Exception { + var serviceTemplateProvider = mock(ServiceTemplateProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + var participantProvider = mock(ParticipantProvider.class); + + CommissioningProvider provider = + new CommissioningProvider(serviceTemplateProvider, acProvider, null, participantProvider); + + List<ToscaNodeTemplate> listOfTemplates = provider.getAutomationCompositionDefinitions(null, null); + assertThat(listOfTemplates).isEmpty(); + + ToscaServiceTemplate serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + when(serviceTemplateProvider.createServiceTemplate(serviceTemplate)).thenReturn(serviceTemplate); + + // Response should return the number of node templates present in the service template + List<ToscaConceptIdentifier> affectedDefinitions = provider + .createAutomationCompositionDefinitions(serviceTemplate).getAffectedAutomationCompositionDefinitions(); + assertThat(affectedDefinitions).hasSize(13); + + when(acProvider.getFilteredNodeTemplates(any())) + .thenReturn(List.of(new ToscaNodeTemplate(), new ToscaNodeTemplate())); + + listOfTemplates = provider.getAutomationCompositionDefinitions(null, null); + assertThat(listOfTemplates).hasSize(2); + } + + /** + * Test the fetching of a full ToscaServiceTemplate object - as opposed to the reduced template that is being + * tested in the testGetToscaServiceTemplateReduced() test. + * + */ + @Test + void testGetToscaServiceTemplate() throws Exception { + var serviceTemplateProvider = mock(ServiceTemplateProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + var participantProvider = mock(ParticipantProvider.class); + + CommissioningProvider provider = + new CommissioningProvider(serviceTemplateProvider, acProvider, null, participantProvider); + ToscaServiceTemplate serviceTemplate = + InstantiationUtils.getToscaServiceTemplate(COMMON_TOSCA_SERVICE_TEMPLATE_YAML); + when(serviceTemplateProvider.createServiceTemplate(serviceTemplate)).thenReturn(serviceTemplate); + + provider.createAutomationCompositionDefinitions(serviceTemplate); + verify(serviceTemplateProvider).createServiceTemplate(serviceTemplate); + + when(serviceTemplateProvider.getToscaServiceTemplate(eq(null), eq(null))).thenReturn(serviceTemplate); + + ToscaServiceTemplate returnedServiceTemplate = provider.getToscaServiceTemplate(null, null); + assertThat(returnedServiceTemplate).isNotNull(); + + Map<String, ToscaNodeTemplate> nodeTemplates = + returnedServiceTemplate.getToscaTopologyTemplate().getNodeTemplates(); + + assertThat(nodeTemplates).hasSize(8); + } + + /** + * Test the fetching of a reduced ToscaServiceTemplate with only some of the objects from the full template. + * The reduced template does not contain: DataTypesAsMap or PolicyTypesAsMap. + * + */ + @Test + void testGetToscaServiceTemplateReduced() throws Exception { + var serviceTemplateProvider = mock(ServiceTemplateProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + var participantProvider = mock(ParticipantProvider.class); + + CommissioningProvider provider = + new CommissioningProvider(serviceTemplateProvider, acProvider, null, participantProvider); + ToscaServiceTemplate serviceTemplate = + InstantiationUtils.getToscaServiceTemplate(COMMON_TOSCA_SERVICE_TEMPLATE_YAML); + when(serviceTemplateProvider.createServiceTemplate(serviceTemplate)).thenReturn(serviceTemplate); + + provider.createAutomationCompositionDefinitions(serviceTemplate); + + when(serviceTemplateProvider.getServiceTemplateList(any(), any())).thenReturn(List.of(serviceTemplate)); + + String returnedServiceTemplate = provider.getToscaServiceTemplateReduced(null, null); + assertThat(returnedServiceTemplate).isNotNull(); + ToscaServiceTemplate parsedServiceTemplate = CODER.decode(returnedServiceTemplate, ToscaServiceTemplate.class); + + assertThat(parsedServiceTemplate.getToscaTopologyTemplate().getNodeTemplates()).hasSize(8); + } + + /** + * Tests the different schemas being returned from the schema endpoint. As schemas of the different + * sections of the Tosca Service Templates can be returned by the API, this test must cover all of the + * different sections. + * + */ + @Test + void testGetToscaServiceTemplateSchema() throws Exception { + var serviceTemplateProvider = mock(ServiceTemplateProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + var participantProvider = mock(ParticipantProvider.class); + + CommissioningProvider provider = + new CommissioningProvider(serviceTemplateProvider, acProvider, null, participantProvider); + ToscaServiceTemplate serviceTemplate = + InstantiationUtils.getToscaServiceTemplate(COMMON_TOSCA_SERVICE_TEMPLATE_YAML); + when(serviceTemplateProvider.createServiceTemplate(serviceTemplate)).thenReturn(serviceTemplate); + + provider.createAutomationCompositionDefinitions(serviceTemplate); + + mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + + Map<String, Class<?>> sections = Map.of("all", ToscaServiceTemplate.class, "data_types", ToscaDataType.class, + "capability_types", ToscaCapabilityType.class, "node_types", ToscaNodeType.class, "relationship_types", + ToscaRelationshipType.class, "policy_types", ToscaPolicyType.class, "topology_template", + ToscaTopologyTemplate.class, "node_templates", List.class); + + for (Map.Entry<String, Class<?>> entry : sections.entrySet()) { + String returnedServiceTemplateSchema = provider.getToscaServiceTemplateSchema(entry.getKey()); + assertThat(returnedServiceTemplateSchema).isNotNull(); + + var visitor = new SchemaFactoryWrapper(); + + if (entry.getKey().equals("node_templates")) { + mapper.acceptJsonFormatVisitor( + mapper.getTypeFactory().constructCollectionType(List.class, ToscaNodeTemplate.class), visitor); + } else { + mapper.acceptJsonFormatVisitor(mapper.constructType(entry.getValue()), visitor); + } + + var jsonSchema = visitor.finalSchema(); + String localServiceTemplateSchema = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema); + assertThat(localServiceTemplateSchema).isEqualTo(returnedServiceTemplateSchema); + } + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java new file mode 100644 index 000000000..2a49e04c1 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java @@ -0,0 +1,303 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.commissioning.rest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import java.util.Map; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; +import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; +import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse; +import org.onap.policy.clamp.models.acm.persistence.provider.ServiceTemplateProvider; +import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +@Execution(ExecutionMode.SAME_THREAD) +class CommissioningControllerTest extends CommonRestController { + + private static final String TOSCA_SERVICE_TEMPLATE_YAML = + "src/test/resources/rest/servicetemplates/pmsh_multiple_ac_tosca.yaml"; + private static final String COMMON_TOSCA_SERVICE_TEMPLATE_YAML = + "src/test/resources/rest/servicetemplates/full-tosca-with-common-properties.yaml"; + + private static final String COMMISSIONING_ENDPOINT = "commission"; + private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate(); + private static ToscaServiceTemplate commonPropertiesServiceTemplate = new ToscaServiceTemplate(); + + @Autowired + private ServiceTemplateProvider serviceTemplateProvider; + + @LocalServerPort + private int randomServerPort; + + /** + * starts Main and inserts a commissioning template. + * + * @throws Exception if an error occurs + */ + @BeforeAll + public static void setUpBeforeClass() throws Exception { + + serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + commonPropertiesServiceTemplate = + InstantiationUtils.getToscaServiceTemplate(COMMON_TOSCA_SERVICE_TEMPLATE_YAML); + } + + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); + } + + @AfterEach + public void cleanDatabase() throws Exception { + deleteEntryInDB(); + } + + @Test + void testSwagger() throws Exception { + super.testSwagger(COMMISSIONING_ENDPOINT); + } + + @Test + void testUnauthorizedCreate() throws Exception { + assertUnauthorizedPost(COMMISSIONING_ENDPOINT, Entity.json(serviceTemplate)); + } + + @Test + void testUnauthorizedQuery() throws Exception { + assertUnauthorizedGet(COMMISSIONING_ENDPOINT); + } + + @Test + void testUnauthorizedQueryElements() throws Exception { + assertUnauthorizedGet(COMMISSIONING_ENDPOINT + "/elements"); + } + + @Test + void testUnauthorizedDelete() throws Exception { + assertUnauthorizedDelete(COMMISSIONING_ENDPOINT); + } + + @Test + void testUnauthorizedQueryToscaServiceTemplate() throws Exception { + assertUnauthorizedGet(COMMISSIONING_ENDPOINT + "/toscaservicetemplate"); + } + + @Test + void testUnauthorizedQueryToscaServiceTemplateSchema() throws Exception { + assertUnauthorizedGet(COMMISSIONING_ENDPOINT + "/toscaServiceTemplateSchema"); + } + + @Test + void testUnauthorizedQueryToscaServiceCommonOrInstanceProperties() throws Exception { + assertUnauthorizedGet(COMMISSIONING_ENDPOINT + "/getCommonOrInstanceProperties"); + } + + @Test + void testQueryToscaServiceTemplate() throws Exception { + createFullEntryInDbWithCommonProps(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/toscaservicetemplate"); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + ToscaServiceTemplate template = rawresp.readEntity(ToscaServiceTemplate.class); + assertNotNull(template); + assertThat(template.getNodeTypes()).hasSize(8); + + } + + @Test + void testQueryToscaServiceTemplateSchema() throws Exception { + createFullEntryInDbWithCommonProps(); + + Invocation.Builder invocationBuilder = + super.sendRequest(COMMISSIONING_ENDPOINT + "/toscaServiceTemplateSchema"); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + String schema = rawresp.readEntity(String.class); + assertNotNull(schema); + + } + + @Test + void testQueryCommonOrInstanceProperties() throws Exception { + createFullEntryInDbWithCommonProps(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + + "/getCommonOrInstanceProperties" + "?common=true&name=ToscaServiceTemplateSimple&version=1.0.0"); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + + @SuppressWarnings("unchecked") + Map<String, ToscaNodeTemplate> commonProperties = rawresp.readEntity(Map.class); + + assertNotNull(commonProperties); + assertThat(commonProperties).hasSize(6); + + } + + @Test + void testCreateBadRequest() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); + Response resp = invocationBuilder.post(Entity.json("NotToscaServiceTempalte")); + + assertThat(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).isEqualTo(resp.getStatus()); + CommissioningResponse commissioningResponse = resp.readEntity(CommissioningResponse.class); + assertThat(commissioningResponse.getErrorDetails()).isNotNull(); + assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).isNull(); + } + + @Test + void testCreate() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); + Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + CommissioningResponse commissioningResponse = resp.readEntity(CommissioningResponse.class); + + assertNotNull(commissioningResponse); + assertNull(commissioningResponse.getErrorDetails()); + // Response should return the number of node templates present in the service template + assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(13); + for (String nodeTemplateName : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().keySet()) { + assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream() + .anyMatch(ac -> ac.getName().equals(nodeTemplateName))); + } + + } + + @Test + void testQuery_NoResultWithThisName() throws Exception { + createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=noResultWithThisName"); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + List<?> entityList = rawresp.readEntity(List.class); + assertThat(entityList).isEmpty(); + + } + + @Test + void testQuery() throws Exception { + createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + List<?> entityList = rawresp.readEntity(List.class); + assertNotNull(entityList); + assertThat(entityList).hasSize(2); + + } + + @Test + void testQueryElementsBadRequest() throws Exception { + createEntryInDB(); + + // Call get elements with no info + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/elements"); + Response resp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.NOT_ACCEPTABLE.getStatusCode(), resp.getStatus()); + + } + + @Test + void testQueryElements() throws Exception { + createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest( + COMMISSIONING_ENDPOINT + "/elements" + "?name=org.onap.domain.pmsh.PMSHAutomationCompositionDefinition"); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + List<?> entityList = rawresp.readEntity(List.class); + assertNotNull(entityList); + assertThat(entityList).hasSize(4); + + } + + @Test + void testDeleteBadRequest() throws Exception { + createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); + // Call delete with no info + Response resp = invocationBuilder.delete(); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + + } + + @Test + void testDelete() throws Exception { + var serviceTemplateCreated = createEntryInDB(); + + Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=" + + serviceTemplateCreated.getName() + "&version=" + serviceTemplateCreated.getVersion()); + // Call delete with no info + Response resp = invocationBuilder.delete(); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + + List<ToscaServiceTemplate> templatesInDB = serviceTemplateProvider.getAllServiceTemplates(); + assertThat(templatesInDB).isEmpty(); + } + + private synchronized ToscaServiceTemplate createEntryInDB() throws Exception { + deleteEntryInDB(); + return serviceTemplateProvider.createServiceTemplate(serviceTemplate); + } + + // Delete entries from the DB after relevant tests + private synchronized void deleteEntryInDB() throws Exception { + var list = serviceTemplateProvider.getAllServiceTemplates(); + if (!list.isEmpty()) { + serviceTemplateProvider.deleteServiceTemplate(list.get(0).getName(), list.get(0).getVersion()); + } + } + + private synchronized void createFullEntryInDbWithCommonProps() throws Exception { + deleteEntryInDB(); + serviceTemplateProvider.createServiceTemplate(commonPropertiesServiceTemplate); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/config/messaging/MessageDispatcherActivatorTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/config/messaging/MessageDispatcherActivatorTest.java new file mode 100644 index 000000000..dd070fc0b --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/config/messaging/MessageDispatcherActivatorTest.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.config.messaging; + +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantStatusListener; +import org.onap.policy.clamp.acm.runtime.util.CommonTestData; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.coder.StandardCoderObject; + +/** + * Class to perform unit test of {@link MessageDispatcherActivator}}. + * + */ +class MessageDispatcherActivatorTest { + + private static final Coder CODER = new StandardCoder(); + + private static final String TOPIC_FIRST = "TOPIC1"; + private static final String TOPIC_SECOND = "TOPIC2"; + + @Test + void testStartAndStop() throws Exception { + AcRuntimeParameterGroup parameterGroup = CommonTestData.geParameterGroup("dbtest"); + + var publisherFirst = spy(mock(Publisher.class)); + var publisherSecond = spy(mock(Publisher.class)); + var publishers = List.of(publisherFirst, publisherSecond); + + var listenerFirst = spy(mock(ParticipantStatusListener.class)); + when(listenerFirst.getType()).thenReturn(TOPIC_FIRST); + when(listenerFirst.getScoListener()).thenReturn(listenerFirst); + + var listenerSecond = spy(mock(ParticipantStatusListener.class)); + when(listenerSecond.getType()).thenReturn(TOPIC_SECOND); + when(listenerSecond.getScoListener()).thenReturn(listenerSecond); + + List<Listener<ParticipantStatus>> listeners = List.of(listenerFirst, listenerSecond); + + try (var activator = new MessageDispatcherActivator(parameterGroup, publishers, listeners)) { + + assertFalse(activator.isAlive()); + activator.start(); + assertTrue(activator.isAlive()); + + // repeat start - should throw an exception + assertThatIllegalStateException().isThrownBy(() -> activator.start()); + assertTrue(activator.isAlive()); + verify(publisherFirst, times(1)).active(anyList()); + verify(publisherSecond, times(1)).active(anyList()); + + StandardCoderObject sco = CODER.decode("{messageType:" + TOPIC_FIRST + "}", StandardCoderObject.class); + activator.getMsgDispatcher().onTopicEvent(null, "msg", sco); + verify(listenerFirst, times(1)).onTopicEvent(any(), any(), any()); + + sco = CODER.decode("{messageType:" + TOPIC_SECOND + "}", StandardCoderObject.class); + activator.getMsgDispatcher().onTopicEvent(null, "msg", sco); + verify(listenerSecond, times(1)).onTopicEvent(any(), any(), any()); + + activator.stop(); + assertFalse(activator.isAlive()); + + // repeat stop - should throw an exception + assertThatIllegalStateException().isThrownBy(() -> activator.stop()); + assertFalse(activator.isAlive()); + } + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java new file mode 100644 index 000000000..30ed89eac --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java @@ -0,0 +1,394 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.instantiation; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.onap.policy.clamp.acm.runtime.commissioning.CommissioningProvider; +import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler; +import org.onap.policy.clamp.acm.runtime.util.CommonTestData; +import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationCommand; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse; +import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +/** + * Class to perform unit test of {@link AutomationCompositionInstantiationProvider}}. + * + */ +class AutomationCompositionInstantiationProviderTest { + private static final String ID_NAME = "PMSH_Instance1"; + private static final String ID_VERSION = "1.2.3"; + private static final String AC_INSTANTIATION_CREATE_JSON = + "src/test/resources/rest/acm/AutomationCompositions.json"; + private static final String AC_INSTANTIATION_UPDATE_JSON = + "src/test/resources/rest/acm/AutomationCompositionsUpdate.json"; + private static final String AC_INSTANTIATION_CHANGE_STATE_JSON = "src/test/resources/rest/acm/PassiveCommand.json"; + private static final String AC_INSTANTIATION_DEFINITION_NAME_NOT_FOUND_JSON = + "src/test/resources/rest/acm/AutomationCompositionElementsNotFound.json"; + private static final String AC_INSTANTIATION_AC_DEFINITION_NOT_FOUND_JSON = + "src/test/resources/rest/acm/AutomationCompositionsNotFound.json"; + private static final String TOSCA_TEMPLATE_YAML = + "src/test/resources/rest/servicetemplates/pmsh_multiple_ac_tosca.yaml"; + private static final String AUTOMATION_COMPOSITION_NOT_FOUND = "Automation composition not found"; + private static final String DELETE_BAD_REQUEST = "Automation composition state is still %s"; + private static final String ORDERED_STATE_INVALID = "ordered state invalid or not specified on command"; + private static final String AC_ELEMENT_NAME_NOT_FOUND = + "\"AutomationCompositions\" INVALID, item has status INVALID\n" + + " \"entry org.onap.domain.pmsh.PMSHAutomationCompositionDefinition\" INVALID, item has status INVALID\n" + + " \"entry org.onap.domain.pmsh.DCAEMicroservice\" INVALID, Not found\n" + + " \"entry org.onap.domain.pmsh.PMSHAutomationCompositionDefinition\" INVALID, item has status INVALID\n" + + " \"entry org.onap.domain.pmsh.DCAEMicroservice\" INVALID, Not found\n"; + + private static final String AC_DEFINITION_NOT_FOUND = + "\"AutomationCompositions\" INVALID, item has status INVALID\n" + + " \"entry org.onap.domain.PMSHAutomationCompositionDefinition\" INVALID, item has status INVALID\n" + + " item \"AutomationComposition\" value \"org.onap.domain.PMSHAutomationCompositionDefinition\"" + + " INVALID, Commissioned automation composition definition not found\n" + + " \"entry org.onap.domain.PMSHAutomationCompositionDefinition\" INVALID, item has status INVALID\n" + + " item \"AutomationComposition\" value \"org.onap.domain.PMSHAutomationCompositionDefinition\"" + + " INVALID, Commissioned automation composition definition not found\n"; + + private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate(); + + @BeforeAll + public static void setUpBeforeClass() throws Exception { + serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML); + } + + @Test + void testIntanceResponses() throws Exception { + var participantProvider = Mockito.mock(ParticipantProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + var supervisionHandler = mock(SupervisionHandler.class); + var commissioningProvider = mock(CommissioningProvider.class); + + when(commissioningProvider.getAllToscaServiceTemplate()).thenReturn(List.of(serviceTemplate)); + when(commissioningProvider.getToscaServiceTemplate(ID_NAME, ID_VERSION)).thenReturn(serviceTemplate); + + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, commissioningProvider, + supervisionHandler, participantProvider); + var instancePropertyList = instantiationProvider.createInstanceProperties(serviceTemplate); + assertNull(instancePropertyList.getErrorDetails()); + var id = new ToscaConceptIdentifier(ID_NAME, ID_VERSION); + assertEquals(id, instancePropertyList.getAffectedInstanceProperties().get(0)); + + AutomationCompositions automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); + var automationComposition = automationCompositions.getAutomationCompositionList().get(0); + automationComposition.setName(ID_NAME); + automationComposition.setVersion(ID_VERSION); + when(acProvider.getAutomationCompositions(ID_NAME, ID_VERSION)).thenReturn(List.of(automationComposition)); + + var instanceOrderState = instantiationProvider.getInstantiationOrderState(ID_NAME, ID_VERSION); + assertEquals(AutomationCompositionOrderedState.UNINITIALISED, instanceOrderState.getOrderedState()); + assertEquals(ID_NAME, instanceOrderState.getAutomationCompositionIdentifierList().get(0).getName()); + + when(acProvider.findAutomationComposition(ID_NAME, ID_VERSION)).thenReturn(Optional.of(automationComposition)); + when(acProvider.deleteAutomationComposition(ID_NAME, ID_VERSION)).thenReturn(automationComposition); + + var instanceResponse = instantiationProvider.deleteInstanceProperties(ID_NAME, ID_VERSION); + assertEquals(ID_NAME, instanceResponse.getAffectedAutomationCompositions().get(0).getName()); + + } + + @Test + void testInstantiationCrud() throws Exception { + var participantProvider = Mockito.mock(ParticipantProvider.class); + var participants = CommonTestData.createParticipants(); + when(participantProvider.getParticipants()).thenReturn(participants); + + var commissioningProvider = mock(CommissioningProvider.class); + var toscaNodeTemplate1 = new ToscaNodeTemplate(); + toscaNodeTemplate1.setName("org.onap.domain.pmsh.PMSH_MonitoringPolicyAutomationCompositionElement"); + toscaNodeTemplate1.setVersion("1.2.3"); + when(commissioningProvider.getAutomationCompositionDefinitions(anyString(), anyString())) + .thenReturn(List.of(toscaNodeTemplate1)); + + var toscaNodeTemplate2 = new ToscaNodeTemplate(); + toscaNodeTemplate2.setName("org.onap.domain.pmsh.PMSH_OperationalPolicyAutomationCompositionElement"); + toscaNodeTemplate2.setVersion("1.2.3"); + var toscaNodeTemplate3 = new ToscaNodeTemplate(); + toscaNodeTemplate3.setName("org.onap.domain.pmsh.PMSH_CDS_AutomationCompositionElement"); + toscaNodeTemplate3.setVersion("1.2.3"); + var toscaNodeTemplate4 = new ToscaNodeTemplate(); + toscaNodeTemplate4.setName("org.onap.domain.pmsh.PMSH_DCAEMicroservice"); + toscaNodeTemplate4.setVersion("1.2.3"); + + when(commissioningProvider.getAutomationCompositionElementDefinitions(toscaNodeTemplate1)) + .thenReturn(List.of(toscaNodeTemplate1, toscaNodeTemplate2, toscaNodeTemplate3, toscaNodeTemplate4)); + + var supervisionHandler = mock(SupervisionHandler.class); + var acProvider = mock(AutomationCompositionProvider.class); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, commissioningProvider, + supervisionHandler, participantProvider); + AutomationCompositions automationCompositionsCreate = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); + InstantiationResponse instantiationResponse = + instantiationProvider.createAutomationCompositions(automationCompositionsCreate); + InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationCompositionsCreate); + + verify(acProvider).saveAutomationCompositions(automationCompositionsCreate.getAutomationCompositionList()); + + for (var automationComposition : automationCompositionsCreate.getAutomationCompositionList()) { + when(acProvider.getAutomationCompositions(automationComposition.getName(), + automationComposition.getVersion())).thenReturn(List.of(automationComposition)); + + AutomationCompositions automationCompositionsGet = instantiationProvider + .getAutomationCompositions(automationComposition.getName(), automationComposition.getVersion()); + assertThat(automationCompositionsGet.getAutomationCompositionList()).hasSize(1); + assertThat(automationComposition) + .isEqualTo(automationCompositionsGet.getAutomationCompositionList().get(0)); + } + + AutomationCompositions automationCompositionsUpdate = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); + + instantiationResponse = instantiationProvider.updateAutomationCompositions(automationCompositionsUpdate); + InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationCompositionsUpdate); + + verify(acProvider).saveAutomationCompositions(automationCompositionsUpdate.getAutomationCompositionList()); + + for (var automationComposition : automationCompositionsUpdate.getAutomationCompositionList()) { + when(acProvider.findAutomationComposition(automationComposition.getKey().asIdentifier())) + .thenReturn(Optional.of(automationComposition)); + when(acProvider.findAutomationComposition(automationComposition.getName(), + automationComposition.getVersion())).thenReturn(Optional.of(automationComposition)); + when(acProvider.deleteAutomationComposition(automationComposition.getName(), + automationComposition.getVersion())).thenReturn(automationComposition); + } + + InstantiationCommand instantiationCommand = + InstantiationUtils.getInstantiationCommandFromResource(AC_INSTANTIATION_CHANGE_STATE_JSON, "Crud"); + instantiationResponse = instantiationProvider.issueAutomationCompositionCommand(instantiationCommand); + InstantiationUtils.assertInstantiationResponse(instantiationResponse, instantiationCommand); + + verify(supervisionHandler) + .triggerAutomationCompositionSupervision(instantiationCommand.getAutomationCompositionIdentifierList()); + + // in order to delete a automationComposition the state must be UNINITIALISED + automationCompositionsCreate.getAutomationCompositionList() + .forEach(ac -> ac.setState(AutomationCompositionState.UNINITIALISED)); + instantiationProvider.updateAutomationCompositions(automationCompositionsCreate); + + for (AutomationComposition automationComposition : automationCompositionsCreate + .getAutomationCompositionList()) { + instantiationProvider.deleteAutomationComposition(automationComposition.getName(), + automationComposition.getVersion()); + + verify(acProvider).deleteAutomationComposition(automationComposition.getName(), + automationComposition.getVersion()); + } + } + + @Test + void testInstantiationDelete() throws Exception { + + AutomationCompositions automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Delete"); + + AutomationComposition automationComposition0 = automationCompositions.getAutomationCompositionList().get(0); + var participantProvider = Mockito.mock(ParticipantProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + var supervisionHandler = mock(SupervisionHandler.class); + var commissioningProvider = mock(CommissioningProvider.class); + + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, commissioningProvider, + supervisionHandler, participantProvider); + + assertThatThrownBy(() -> instantiationProvider.deleteAutomationComposition(automationComposition0.getName(), + automationComposition0.getVersion())).hasMessageMatching(AUTOMATION_COMPOSITION_NOT_FOUND); + + for (AutomationCompositionState state : AutomationCompositionState.values()) { + if (!AutomationCompositionState.UNINITIALISED.equals(state)) { + assertThatDeleteThrownBy(automationCompositions, state); + } + } + automationComposition0.setState(AutomationCompositionState.UNINITIALISED); + + for (AutomationComposition automationComposition : automationCompositions.getAutomationCompositionList()) { + when(acProvider.findAutomationComposition(automationComposition.getName(), + automationComposition.getVersion())).thenReturn(Optional.of(automationComposition)); + when(acProvider.deleteAutomationComposition(automationComposition.getName(), + automationComposition.getVersion())).thenReturn(automationComposition); + + instantiationProvider.deleteAutomationComposition(automationComposition.getName(), + automationComposition.getVersion()); + } + } + + private void assertThatDeleteThrownBy(AutomationCompositions automationCompositions, + AutomationCompositionState state) throws Exception { + AutomationComposition automationComposition = automationCompositions.getAutomationCompositionList().get(0); + automationComposition.setState(state); + var participantProvider = Mockito.mock(ParticipantProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + var supervisionHandler = mock(SupervisionHandler.class); + var commissioningProvider = mock(CommissioningProvider.class); + + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, commissioningProvider, + supervisionHandler, participantProvider); + + when(acProvider.findAutomationComposition(automationComposition.getName(), automationComposition.getVersion())) + .thenReturn(Optional.of(automationComposition)); + + assertThatThrownBy(() -> instantiationProvider.deleteAutomationComposition(automationComposition.getName(), + automationComposition.getVersion())).hasMessageMatching(String.format(DELETE_BAD_REQUEST, state)); + } + + @Test + void testCreateAutomationCompositions_NoDuplicates() throws Exception { + var commissioningProvider = mock(CommissioningProvider.class); + + var toscaNodeTemplate1 = new ToscaNodeTemplate(); + toscaNodeTemplate1.setName("org.onap.domain.pmsh.PMSH_MonitoringPolicyAutomationCompositionElement"); + toscaNodeTemplate1.setVersion("1.2.3"); + when(commissioningProvider.getAutomationCompositionDefinitions(anyString(), anyString())) + .thenReturn(List.of(toscaNodeTemplate1)); + + var toscaNodeTemplate2 = new ToscaNodeTemplate(); + toscaNodeTemplate2.setName("org.onap.domain.pmsh.PMSH_OperationalPolicyAutomationCompositionElement"); + toscaNodeTemplate2.setVersion("1.2.3"); + var toscaNodeTemplate3 = new ToscaNodeTemplate(); + toscaNodeTemplate3.setName("org.onap.domain.pmsh.PMSH_CDS_AutomationCompositionElement"); + toscaNodeTemplate3.setVersion("1.2.3"); + var toscaNodeTemplate4 = new ToscaNodeTemplate(); + toscaNodeTemplate4.setName("org.onap.domain.pmsh.PMSH_DCAEMicroservice"); + toscaNodeTemplate4.setVersion("1.2.3"); + + when(commissioningProvider.getAutomationCompositionElementDefinitions(toscaNodeTemplate1)) + .thenReturn(List.of(toscaNodeTemplate1, toscaNodeTemplate2, toscaNodeTemplate3, toscaNodeTemplate4)); + + AutomationCompositions automationCompositionsCreate = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "NoDuplicates"); + + var acProvider = mock(AutomationCompositionProvider.class); + var participantProvider = Mockito.mock(ParticipantProvider.class); + var supervisionHandler = mock(SupervisionHandler.class); + + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, commissioningProvider, + supervisionHandler, participantProvider); + + InstantiationResponse instantiationResponse = + instantiationProvider.createAutomationCompositions(automationCompositionsCreate); + InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationCompositionsCreate); + + when(acProvider.findAutomationComposition( + automationCompositionsCreate.getAutomationCompositionList().get(0).getKey().asIdentifier())) + .thenReturn(Optional.of(automationCompositionsCreate.getAutomationCompositionList().get(0))); + + assertThatThrownBy(() -> instantiationProvider.createAutomationCompositions(automationCompositionsCreate)) + .hasMessageMatching( + automationCompositionsCreate.getAutomationCompositionList().get(0).getKey().asIdentifier() + + " already defined"); + } + + @Test + void testCreateAutomationCompositions_CommissionedAcElementNotFound() throws Exception { + var toscaNodeTemplate1 = new ToscaNodeTemplate(); + toscaNodeTemplate1.setName("org.onap.domain.pmsh.PMSH_MonitoringPolicyAutomationCompositionElement"); + toscaNodeTemplate1.setVersion("1.2.3"); + + var toscaNodeTemplate2 = new ToscaNodeTemplate(); + toscaNodeTemplate2.setName("org.onap.domain.pmsh.PMSH_OperationalPolicyAutomationCompositionElement"); + toscaNodeTemplate2.setVersion("1.2.3"); + var toscaNodeTemplate3 = new ToscaNodeTemplate(); + toscaNodeTemplate3.setName("org.onap.domain.pmsh.PMSH_CDS_AutomationCompositionElement"); + toscaNodeTemplate3.setVersion("1.2.3"); + var commissioningProvider = mock(CommissioningProvider.class); + AutomationCompositions automationCompositions = InstantiationUtils.getAutomationCompositionsFromResource( + AC_INSTANTIATION_DEFINITION_NAME_NOT_FOUND_JSON, "AcElementNotFound"); + + when(commissioningProvider.getAutomationCompositionDefinitions( + automationCompositions.getAutomationCompositionList().get(0).getDefinition().getName(), + automationCompositions.getAutomationCompositionList().get(0).getDefinition().getVersion())) + .thenReturn(List.of(toscaNodeTemplate1)); + + when(commissioningProvider.getAutomationCompositionElementDefinitions(toscaNodeTemplate1)) + .thenReturn(List.of(toscaNodeTemplate1, toscaNodeTemplate2, toscaNodeTemplate3)); + + var acProvider = mock(AutomationCompositionProvider.class); + var participantProvider = mock(ParticipantProvider.class); + var supervisionHandler = mock(SupervisionHandler.class); + var provider = new AutomationCompositionInstantiationProvider(acProvider, commissioningProvider, + supervisionHandler, participantProvider); + + assertThatThrownBy(() -> provider.createAutomationCompositions(automationCompositions)) + .hasMessageMatching(AC_ELEMENT_NAME_NOT_FOUND); + + assertThatThrownBy(() -> provider.updateAutomationCompositions(automationCompositions)) + .hasMessageMatching(AC_ELEMENT_NAME_NOT_FOUND); + } + + @Test + void testCreateAutomationCompositions_CommissionedAcNotFound() throws Exception { + AutomationCompositions automationCompositions = InstantiationUtils + .getAutomationCompositionsFromResource(AC_INSTANTIATION_AC_DEFINITION_NOT_FOUND_JSON, "AcNotFound"); + + var participantProvider = Mockito.mock(ParticipantProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + var supervisionHandler = mock(SupervisionHandler.class); + var commissioningProvider = mock(CommissioningProvider.class); + var provider = new AutomationCompositionInstantiationProvider(acProvider, commissioningProvider, + supervisionHandler, participantProvider); + + assertThatThrownBy(() -> provider.createAutomationCompositions(automationCompositions)) + .hasMessageMatching(AC_DEFINITION_NOT_FOUND); + + assertThatThrownBy(() -> provider.updateAutomationCompositions(automationCompositions)) + .hasMessageMatching(AC_DEFINITION_NOT_FOUND); + } + + @Test + void testIssueAutomationCompositionCommand_OrderedStateInvalid() + throws AutomationCompositionRuntimeException, IOException { + var participantProvider = Mockito.mock(ParticipantProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + var supervisionHandler = mock(SupervisionHandler.class); + var commissioningProvider = mock(CommissioningProvider.class); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, commissioningProvider, + supervisionHandler, participantProvider); + assertThatThrownBy(() -> instantiationProvider.issueAutomationCompositionCommand(new InstantiationCommand())) + .hasMessageMatching(ORDERED_STATE_INVALID); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/InstantiationUtils.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/InstantiationUtils.java new file mode 100644 index 000000000..759685ad9 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/InstantiationUtils.java @@ -0,0 +1,147 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.instantiation; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.File; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationCommand; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse; +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.common.utils.coder.StandardYamlCoder; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +/** + * Utility methods supporting tests for Instantiation. + */ +public class InstantiationUtils { + + private static final Coder CODER = new StandardCoder(); + private static final StandardYamlCoder YAML_TRANSLATOR = new StandardYamlCoder(); + + /** + * Gets the AutomationCompositions from Resource. + * + * @param path path of the resource + * @param suffix suffix to add to all names in AutomationCompositions + * @return the AutomationCompositions from Resource + * @throws CoderException if an error occurs + */ + public static AutomationCompositions getAutomationCompositionsFromResource(final String path, final String suffix) + throws CoderException { + AutomationCompositions automationCompositions = CODER.decode(new File(path), AutomationCompositions.class); + + // add suffix to all names + automationCompositions.getAutomationCompositionList() + .forEach(automationComposition -> automationComposition.setName(automationComposition.getName() + suffix)); + return automationCompositions; + } + + /** + * Gets InstantiationCommand from Resource. + * + * @param path path of the resource + * @param suffix suffix to add to all names in AutomationCompositions + * @return the InstantiationCommand + * @throws CoderException if an error occurs + */ + public static InstantiationCommand getInstantiationCommandFromResource(final String path, final String suffix) + throws CoderException { + InstantiationCommand instantiationCommand = CODER.decode(new File(path), InstantiationCommand.class); + + // add suffix to all names + instantiationCommand.getAutomationCompositionIdentifierList().forEach(ac -> ac.setName(ac.getName() + suffix)); + return instantiationCommand; + } + + /** + * Assert that Instantiation Response contains proper AutomationCompositions. + * + * @param response InstantiationResponse + * @param automationCompositions AutomationCompositions + */ + public static void assertInstantiationResponse(InstantiationResponse response, + AutomationCompositions automationCompositions) { + assertThat(response).isNotNull(); + assertThat(response.getErrorDetails()).isNull(); + assertThat(response.getAffectedAutomationCompositions().size()) + .isEqualTo(automationCompositions.getAutomationCompositionList().size()); + for (AutomationComposition automationComposition : automationCompositions.getAutomationCompositionList()) { + assertTrue(response.getAffectedAutomationCompositions().stream() + .filter(ac -> ac.equals(automationComposition.getKey().asIdentifier())).findAny().isPresent()); + } + } + + /** + * Assert that Instantiation Response contains proper AutomationCompositions. + * + * @param response InstantiationResponse + * @param command InstantiationCommand + */ + public static void assertInstantiationResponse(InstantiationResponse response, InstantiationCommand command) { + assertThat(response).isNotNull(); + assertEquals(response.getAffectedAutomationCompositions().size(), + command.getAutomationCompositionIdentifierList().size()); + for (ToscaConceptIdentifier toscaConceptIdentifier : command.getAutomationCompositionIdentifierList()) { + assertTrue(response.getAffectedAutomationCompositions().stream() + .filter(ac -> ac.compareTo(toscaConceptIdentifier) == 0).findAny().isPresent()); + } + } + + /** + * Assert that Instantiation Response contains AutomationComposition equals to automationComposition. + * + * @param response InstantiationResponse + * @param automationComposition AutomationComposition + */ + public static void assertInstantiationResponse(InstantiationResponse response, + AutomationComposition automationComposition) { + assertThat(response).isNotNull(); + assertThat(response.getErrorDetails()).isNull(); + assertEquals(1, response.getAffectedAutomationCompositions().size()); + assertEquals(0, response.getAffectedAutomationCompositions().get(0) + .compareTo(automationComposition.getKey().asIdentifier())); + } + + /** + * Get ToscaServiceTemplate from resource. + * + * @param path path of the resource + */ + public static ToscaServiceTemplate getToscaServiceTemplate(String path) { + + try { + return YAML_TRANSLATOR.decode(ResourceUtils.getResourceAsStream(path), ToscaServiceTemplate.class); + } catch (CoderException e) { + fail("Cannot read or decode " + path); + return null; + } + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java new file mode 100644 index 000000000..2ad15bd48 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java @@ -0,0 +1,543 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.instantiation.rest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.policy.clamp.acm.runtime.instantiation.AutomationCompositionInstantiationProvider; +import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; +import org.onap.policy.clamp.acm.runtime.main.rest.InstantiationController; +import org.onap.policy.clamp.acm.runtime.util.CommonTestData; +import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AutomationCompositionOrderStateResponse; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AutomationCompositionPrimedResponse; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstancePropertiesResponse; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationCommand; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ServiceTemplateProvider; +import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionRepository; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Class to perform unit test of {@link InstantiationController}}. + * + */ +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +class InstantiationControllerTest extends CommonRestController { + + private static final String ID_NAME = "PMSH_Instance1"; + private static final String ID_VERSION = "1.2.3"; + + private static final String AC_INSTANTIATION_CREATE_JSON = + "src/test/resources/rest/acm/AutomationCompositions.json"; + + private static final String AC_INSTANTIATION_UPDATE_JSON = + "src/test/resources/rest/acm/AutomationCompositionsUpdate.json"; + + private static final String AC_INSTANTIATION_CHANGE_STATE_JSON = "src/test/resources/rest/acm/PassiveCommand.json"; + + private static final String TOSCA_TEMPLATE_YAML = + "src/test/resources/rest/servicetemplates/pmsh_multiple_ac_tosca.yaml"; + + private static final String INSTANTIATION_ENDPOINT = "instantiation"; + private static final String INSTANTIATION_COMMAND_ENDPOINT = "instantiation/command"; + private static final String PRIMING_ENDPOINT = "automationCompositionPriming"; + private static final String INSTANTIATION_PROPERTIES = "instanceProperties"; + private static final String INSTANTIATION_STATE = "instantiationState"; + + private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate(); + + @Autowired + private AutomationCompositionRepository automationCompositionRepository; + + @Autowired + private ServiceTemplateProvider serviceTemplateProvider; + + @Autowired + private AutomationCompositionInstantiationProvider instantiationProvider; + + @Autowired + private ParticipantProvider participantProvider; + + @LocalServerPort + private int randomServerPort; + + @BeforeAll + public static void setUpBeforeClass() throws Exception { + serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML); + } + + @BeforeEach + public void populateDb() throws Exception { + createEntryInDB(); + } + + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); + } + + @AfterEach + public void cleanDatabase() throws Exception { + deleteEntryInDB(); + } + + @Test + void testSwagger() throws Exception { + super.testSwagger(INSTANTIATION_ENDPOINT); + } + + @Test + void testCreate_Unauthorized() throws Exception { + AutomationCompositions automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Unauthorized"); + + assertUnauthorizedPost(INSTANTIATION_ENDPOINT, Entity.json(automationCompositions)); + } + + @Test + void testQuery_Unauthorized() throws Exception { + assertUnauthorizedGet(INSTANTIATION_ENDPOINT); + } + + @Test + void testUpdate_Unauthorized() throws Exception { + AutomationCompositions automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_UPDATE_JSON, "Unauthorized"); + + assertUnauthorizedPut(INSTANTIATION_ENDPOINT, Entity.json(automationCompositions)); + } + + @Test + void testDelete_Unauthorized() throws Exception { + assertUnauthorizedDelete(INSTANTIATION_ENDPOINT); + } + + @Test + void testCommand_Unauthorized() throws Exception { + InstantiationCommand instantiationCommand = + InstantiationUtils.getInstantiationCommandFromResource(AC_INSTANTIATION_CHANGE_STATE_JSON, "Unauthorized"); + + assertUnauthorizedPut(INSTANTIATION_COMMAND_ENDPOINT, Entity.json(instantiationCommand)); + } + + @Test + void testCreate() throws Exception { + + AutomationCompositions automationCompositionsFromRsc = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Create"); + + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT); + Response resp = invocationBuilder.post(Entity.json(automationCompositionsFromRsc)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionsFromRsc); + + for (AutomationComposition automationCompositionFromRsc : automationCompositionsFromRsc + .getAutomationCompositionList()) { + AutomationCompositions automationCompositionsFromDb = instantiationProvider.getAutomationCompositions( + automationCompositionFromRsc.getKey().getName(), automationCompositionFromRsc.getKey().getVersion()); + + assertNotNull(automationCompositionsFromDb); + assertThat(automationCompositionsFromDb.getAutomationCompositionList()).hasSize(1); + assertEquals(automationCompositionFromRsc, + automationCompositionsFromDb.getAutomationCompositionList().get(0)); + } + + invocationBuilder = + super.sendRequest(PRIMING_ENDPOINT + "?name=" + "PMSHInstance0Create" + "&version=" + "1.0.1"); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + AutomationCompositionPrimedResponse primResponse = + rawresp.readEntity(AutomationCompositionPrimedResponse.class); + assertEquals(false, primResponse.getPrimedAutomationCompositionsList().get(0).isPrimed()); + } + + @Test + void testCreateBadRequest() throws Exception { + + AutomationCompositions automationCompositionsFromRsc = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "CreateBadRequest"); + + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT); + Response resp = invocationBuilder.post(Entity.json(automationCompositionsFromRsc)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + + // testing Bad Request: AC already defined + resp = invocationBuilder.post(Entity.json(automationCompositionsFromRsc)); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + assertNotNull(instResponse.getErrorDetails()); + assertNull(instResponse.getAffectedAutomationCompositions()); + } + + @Test + void testQuery_NoResultWithThisName() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT + "?name=noResultWithThisName"); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + AutomationCompositions resp = rawresp.readEntity(AutomationCompositions.class); + assertThat(resp.getAutomationCompositionList()).isEmpty(); + } + + @Test + void testQuery() throws Exception { + + var automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Query"); + instantiationProvider.createAutomationCompositions(automationCompositions); + + for (AutomationComposition automationCompositionFromRsc : automationCompositions + .getAutomationCompositionList()) { + Invocation.Builder invocationBuilder = + super.sendRequest(INSTANTIATION_ENDPOINT + "?name=" + automationCompositionFromRsc.getKey().getName()); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + AutomationCompositions automationCompositionsQuery = rawresp.readEntity(AutomationCompositions.class); + assertNotNull(automationCompositionsQuery); + assertThat(automationCompositionsQuery.getAutomationCompositionList()).hasSize(1); + assertEquals(automationCompositionFromRsc, + automationCompositionsQuery.getAutomationCompositionList().get(0)); + } + } + + @Test + void testUpdate() throws Exception { + + AutomationCompositions automationCompositionsCreate = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Update"); + + var automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_UPDATE_JSON, "Update"); + instantiationProvider.createAutomationCompositions(automationCompositionsCreate); + + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT); + Response resp = invocationBuilder.put(Entity.json(automationCompositions)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositions); + + for (AutomationComposition automationCompositionUpdate : automationCompositions + .getAutomationCompositionList()) { + AutomationCompositions automationCompositionsFromDb = instantiationProvider.getAutomationCompositions( + automationCompositionUpdate.getKey().getName(), automationCompositionUpdate.getKey().getVersion()); + + assertNotNull(automationCompositionsFromDb); + assertThat(automationCompositionsFromDb.getAutomationCompositionList()).hasSize(1); + assertEquals(automationCompositionUpdate, + automationCompositionsFromDb.getAutomationCompositionList().get(0)); + } + } + + @Test + void testDelete_NoResultWithThisName() throws Exception { + Invocation.Builder invocationBuilder = + super.sendRequest(INSTANTIATION_ENDPOINT + "?name=noResultWithThisName&version=1.0.1"); + Response resp = invocationBuilder.delete(); + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus()); + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + assertNotNull(instResponse.getErrorDetails()); + assertNull(instResponse.getAffectedAutomationCompositions()); + } + + @Test + void testDelete() throws Exception { + + AutomationCompositions automationCompositionsFromRsc = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Delete"); + + instantiationProvider.createAutomationCompositions(automationCompositionsFromRsc); + + for (AutomationComposition automationCompositionFromRsc : automationCompositionsFromRsc + .getAutomationCompositionList()) { + Invocation.Builder invocationBuilder = + super.sendRequest(INSTANTIATION_ENDPOINT + "?name=" + automationCompositionFromRsc.getKey().getName() + + "&version=" + automationCompositionFromRsc.getKey().getVersion()); + Response resp = invocationBuilder.delete(); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc); + + AutomationCompositions automationCompositionsFromDb = instantiationProvider.getAutomationCompositions( + automationCompositionFromRsc.getKey().getName(), automationCompositionFromRsc.getKey().getVersion()); + assertThat(automationCompositionsFromDb.getAutomationCompositionList()).isEmpty(); + } + } + + @Test + void testDeleteBadRequest() throws Exception { + + AutomationCompositions automationCompositionsFromRsc = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "DelBadRequest"); + + instantiationProvider.createAutomationCompositions(automationCompositionsFromRsc); + + for (AutomationComposition automationCompositionFromRsc : automationCompositionsFromRsc + .getAutomationCompositionList()) { + Invocation.Builder invocationBuilder = + super.sendRequest(INSTANTIATION_ENDPOINT + "?name=" + automationCompositionFromRsc.getKey().getName()); + Response resp = invocationBuilder.delete(); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + } + } + + @Test + void testCreateInstanceProperties() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES); + Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + var instancePropertyList = resp.readEntity(InstancePropertiesResponse.class); + assertNull(instancePropertyList.getErrorDetails()); + var id = new ToscaConceptIdentifier(ID_NAME, ID_VERSION); + assertEquals(id, instancePropertyList.getAffectedInstanceProperties().get(0)); + + invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT); + resp = invocationBuilder.get(); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + var automationCompositionsGet = resp.readEntity(AutomationCompositions.class); + assertThat(automationCompositionsGet.getAutomationCompositionList()).hasSize(1); + } + + @Test + void testDeleteInstanceProperties() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES); + Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + + invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES + "?name=" + ID_NAME + "&version=" + ID_VERSION); + resp = invocationBuilder.delete(); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + var instanceResponse = resp.readEntity(InstantiationResponse.class); + assertEquals(ID_NAME, instanceResponse.getAffectedAutomationCompositions().get(0).getName()); + AutomationCompositions automationCompositionsGet = + instantiationProvider.getAutomationCompositions(ID_NAME, ID_VERSION); + assertThat(automationCompositionsGet.getAutomationCompositionList()).isEmpty(); + } + + @Test + void testDeleteInstancePropertiesBadRequest() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES); + Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + + invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES + "?name=" + ID_NAME); + resp = invocationBuilder.delete(); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + } + + @Test + void testDeleteInstancePropertiesPassiveMode() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES); + Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + + var automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Command"); + instantiationProvider.createAutomationCompositions(automationCompositions); + + var participants = CommonTestData.createParticipants(); + for (var participant : participants) { + participantProvider.saveParticipant(participant); + } + + InstantiationCommand command = + InstantiationUtils.getInstantiationCommandFromResource(AC_INSTANTIATION_CHANGE_STATE_JSON, "Command"); + + invocationBuilder = super.sendRequest(INSTANTIATION_COMMAND_ENDPOINT); + resp = invocationBuilder.put(Entity.json(command)); + assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus()); + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + InstantiationUtils.assertInstantiationResponse(instResponse, command); + + // check passive state on DB and delete properties + for (ToscaConceptIdentifier toscaConceptIdentifier : command.getAutomationCompositionIdentifierList()) { + AutomationCompositions automationCompositionsGet = instantiationProvider + .getAutomationCompositions(toscaConceptIdentifier.getName(), toscaConceptIdentifier.getVersion()); + assertThat(automationCompositionsGet.getAutomationCompositionList()).hasSize(1); + assertEquals(command.getOrderedState(), + automationCompositionsGet.getAutomationCompositionList().get(0).getOrderedState()); + + invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES + "?name=" + toscaConceptIdentifier.getName() + + "&version=" + toscaConceptIdentifier.getVersion()); + resp = invocationBuilder.delete(); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + } + } + + @Test + void testCommand_NotFound1() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_COMMAND_ENDPOINT); + Response resp = invocationBuilder.put(Entity.json(new InstantiationCommand())); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + } + + @Test + void testCommand_NotFound2() throws Exception { + InstantiationCommand command = + InstantiationUtils.getInstantiationCommandFromResource(AC_INSTANTIATION_CHANGE_STATE_JSON, "Command"); + command.setOrderedState(null); + + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_COMMAND_ENDPOINT); + Response resp = invocationBuilder.put(Entity.json(command)); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + } + + @Test + void testCommand() throws Exception { + var automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Command"); + instantiationProvider.createAutomationCompositions(automationCompositions); + + var participants = CommonTestData.createParticipants(); + for (var participant : participants) { + participantProvider.saveParticipant(participant); + } + + InstantiationCommand command = + InstantiationUtils.getInstantiationCommandFromResource(AC_INSTANTIATION_CHANGE_STATE_JSON, "Command"); + + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_COMMAND_ENDPOINT); + Response resp = invocationBuilder.put(Entity.json(command)); + assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus()); + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + InstantiationUtils.assertInstantiationResponse(instResponse, command); + + // check passive state on DB + for (ToscaConceptIdentifier toscaConceptIdentifier : command.getAutomationCompositionIdentifierList()) { + AutomationCompositions automationCompositionsGet = instantiationProvider + .getAutomationCompositions(toscaConceptIdentifier.getName(), toscaConceptIdentifier.getVersion()); + assertThat(automationCompositionsGet.getAutomationCompositionList()).hasSize(1); + assertEquals(command.getOrderedState(), + automationCompositionsGet.getAutomationCompositionList().get(0).getOrderedState()); + } + } + + @Test + void testIntanceProperties() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES); + Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + var instancePropertyList = resp.readEntity(InstancePropertiesResponse.class); + assertNull(instancePropertyList.getErrorDetails()); + var id = new ToscaConceptIdentifier(ID_NAME, ID_VERSION); + assertEquals(id, instancePropertyList.getAffectedInstanceProperties().get(0)); + + invocationBuilder = super.sendRequest(INSTANTIATION_STATE + "?name=" + ID_NAME + "&version=" + ID_VERSION); + resp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + var instanceOrderState = resp.readEntity(AutomationCompositionOrderStateResponse.class); + assertEquals(AutomationCompositionOrderedState.UNINITIALISED, instanceOrderState.getOrderedState()); + assertEquals(ID_NAME, instanceOrderState.getAutomationCompositionIdentifierList().get(0).getName()); + AutomationCompositions automationCompositionsGet = + instantiationProvider.getAutomationCompositions(ID_NAME, ID_VERSION); + assertThat(automationCompositionsGet.getAutomationCompositionList()).hasSize(1); + + invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES + "?name=" + ID_NAME + "&version=" + ID_VERSION); + resp = invocationBuilder.delete(); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + var instanceResponse = resp.readEntity(InstantiationResponse.class); + assertEquals(ID_NAME, instanceResponse.getAffectedAutomationCompositions().get(0).getName()); + automationCompositionsGet = instantiationProvider.getAutomationCompositions(ID_NAME, ID_VERSION); + assertThat(automationCompositionsGet.getAutomationCompositionList()).isEmpty(); + } + + @Test + void testChangeOrderStateFromUninitializedPassiveMode() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES); + Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + + var automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "CommandPassive"); + instantiationProvider.createAutomationCompositions(automationCompositions); + + var participants = CommonTestData.createParticipants(); + for (var participant : participants) { + participantProvider.saveParticipant(participant); + } + + InstantiationCommand command = InstantiationUtils + .getInstantiationCommandFromResource(AC_INSTANTIATION_CHANGE_STATE_JSON, "CommandPassive"); + + invocationBuilder = super.sendRequest(INSTANTIATION_COMMAND_ENDPOINT); + resp = invocationBuilder.put(Entity.json(command)); + assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus()); + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + InstantiationUtils.assertInstantiationResponse(instResponse, command); + } + + @Test + void testChangeOrderStateWithoutRegisteredParticipants() throws Exception { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_PROPERTIES); + Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + + var automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "CommandPassive"); + instantiationProvider.createAutomationCompositions(automationCompositions); + + InstantiationCommand command = InstantiationUtils + .getInstantiationCommandFromResource(AC_INSTANTIATION_CHANGE_STATE_JSON, "CommandPassive"); + + invocationBuilder = super.sendRequest(INSTANTIATION_COMMAND_ENDPOINT); + resp = invocationBuilder.put(Entity.json(command)); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + } + + private synchronized void deleteEntryInDB() throws Exception { + automationCompositionRepository.deleteAll(); + var list = serviceTemplateProvider.getAllServiceTemplates(); + if (!list.isEmpty()) { + serviceTemplateProvider.deleteServiceTemplate(list.get(0).getName(), list.get(0).getVersion()); + } + } + + private synchronized void createEntryInDB() throws Exception { + deleteEntryInDB(); + serviceTemplateProvider.createServiceTemplate(serviceTemplate); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/ActuatorControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/ActuatorControllerTest.java new file mode 100644 index 000000000..553a4721b --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/ActuatorControllerTest.java @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.main.rest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; +import org.springframework.boot.test.autoconfigure.actuate.metrics.AutoConfigureMetrics; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@AutoConfigureMetrics +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +class ActuatorControllerTest extends CommonRestController { + + private static final String HEALTH_ENDPOINT = "health"; + private static final String METRICS_ENDPOINT = "metrics"; + private static final String PROMETHEUS_ENDPOINT = "prometheus"; + + @LocalServerPort + private int randomServerPort; + + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); + } + + @Test + void testGetHealth_Unauthorized() throws Exception { + assertUnauthorizedActGet(HEALTH_ENDPOINT); + } + + @Test + void testGetMetrics_Unauthorized() throws Exception { + assertUnauthorizedActGet(METRICS_ENDPOINT); + } + + @Test + void testGetPrometheus_Unauthorized() throws Exception { + assertUnauthorizedActGet(PROMETHEUS_ENDPOINT); + } + + @Test + void testGetHealth() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(HEALTH_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGetMetrics() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(METRICS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGePrometheus() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(PROMETHEUS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/monitoring/TestMonitoringProvider.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/monitoring/TestMonitoringProvider.java new file mode 100644 index 000000000..aabc254c1 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/monitoring/TestMonitoringProvider.java @@ -0,0 +1,321 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.monitoring; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.time.Instant; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import javax.ws.rs.core.Response; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.onap.policy.clamp.models.acm.concepts.AcElementStatisticsList; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; +import org.onap.policy.clamp.models.acm.concepts.ParticipantStatisticsList; +import org.onap.policy.clamp.models.acm.persistence.provider.AcElementStatisticsProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantStatisticsProvider; +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.models.base.PfModelRuntimeException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class TestMonitoringProvider { + + private static final String AC_PARTICIPANT_STATISTICS_JSON = + "src/test/resources/rest/monitoring/TestParticipantStatistics.json"; + private static final String INVALID_PARTICIPANT_JSON_INPUT = + "src/test/resources/rest/monitoring/TestParticipantStatistics_Invalid.json"; + private static final String AC_ELEMENT_STATISTICS_JSON = + "src/test/resources/rest/monitoring/TestAcElementStatistics.json"; + private static final String INVALID_AC_ELEMENT_JSON_INPUT = + "src/test/resources/rest/monitoring/TestAcElementStatistics_Invalid.json"; + private static final Coder CODER = new StandardCoder(); + + private static final String STAT_LIST_IS_NULL = ".*StatisticsList is marked .*ull but is null"; + private static final String PARTICIPANT_STAT_LIST_IS_NULL = + "participantStatisticsList is marked .*null but is null"; + private static final String NAME_IS_NULL = "name is marked .*null but is null"; + private static final String AC_LIST_IS_NULL = "acElementStatisticsList is marked .*null but is null"; + private static final String ID_VERSION1 = "1.001"; + private static final String ID_VERSION2 = "1.002"; + private static final String ID_NAME1 = "name1"; + private static final String ID_NAME2 = "name2"; + private static final String SORT_DESC = "DESC"; + private static final String ID_NAME3 = "testACName"; + private static final String ID_INVALID_NAME = "invalidACName"; + private static ParticipantStatisticsList inputParticipantStatistics; + private static ParticipantStatisticsList invalidParticipantInput; + private static AcElementStatisticsList inputAcElementStatistics; + private static AcElementStatisticsList invalidAcElementInput; + + @BeforeAll + public static void beforeSetupStatistics() throws CoderException { + // Reading input json for statistics data + inputParticipantStatistics = + CODER.decode(new File(AC_PARTICIPANT_STATISTICS_JSON), ParticipantStatisticsList.class); + invalidParticipantInput = + CODER.decode(new File(INVALID_PARTICIPANT_JSON_INPUT), ParticipantStatisticsList.class); + inputAcElementStatistics = CODER.decode(new File(AC_ELEMENT_STATISTICS_JSON), AcElementStatisticsList.class); + invalidAcElementInput = CODER.decode(new File(INVALID_AC_ELEMENT_JSON_INPUT), AcElementStatisticsList.class); + } + + @Test + void testCreateParticipantStatistics() throws Exception { + var participantStatisticsProvider = mock(ParticipantStatisticsProvider.class); + var acElementStatisticsProvider = mock(AcElementStatisticsProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + MonitoringProvider provider = + new MonitoringProvider(participantStatisticsProvider, acElementStatisticsProvider, acProvider); + + when(participantStatisticsProvider.createParticipantStatistics(any())) + .thenReturn(inputParticipantStatistics.getStatisticsList()); + + when(participantStatisticsProvider.createParticipantStatistics(eq(null))) + .thenThrow(new PfModelRuntimeException(Response.Status.BAD_REQUEST, PARTICIPANT_STAT_LIST_IS_NULL)); + + // Creating statistics data in db with null input + + assertThatThrownBy(() -> { + provider.createParticipantStatistics(null); + }).hasMessageMatching(STAT_LIST_IS_NULL); + + assertThatThrownBy(() -> { + provider.createParticipantStatistics(invalidParticipantInput.getStatisticsList()); + }).hasMessageMatching(PARTICIPANT_STAT_LIST_IS_NULL); + + // Creating statistics data from input json + ParticipantStatisticsList createResponse = + provider.createParticipantStatistics(inputParticipantStatistics.getStatisticsList()); + + assertThat(createResponse.getStatisticsList()).hasSize(3); + assertEquals(createResponse.getStatisticsList().toString().replaceAll("\\s+", ""), + inputParticipantStatistics.getStatisticsList().toString().replaceAll("\\s+", "")); + } + + @Test + void testGetParticipantStatistics() throws Exception { + var participantStatisticsProvider = mock(ParticipantStatisticsProvider.class); + when(participantStatisticsProvider.getFilteredParticipantStatistics(eq(ID_NAME1), any(), any(), any(), eq(null), + eq(SORT_DESC), eq(0))).thenReturn(List.of(inputParticipantStatistics.getStatisticsList().get(0))); + + when(participantStatisticsProvider.getFilteredParticipantStatistics(eq(ID_NAME1), any(), + eq(Instant.parse("2021-01-11T12:00:00.000Z")), eq(Instant.parse("2021-01-11T16:00:00.000Z")), eq(null), + eq(SORT_DESC), eq(0))).thenReturn(List.of()); + + when(participantStatisticsProvider.getFilteredParticipantStatistics(eq(ID_NAME2), any(), any(), any(), eq(null), + eq(SORT_DESC), eq(1))).thenReturn(List.of(inputParticipantStatistics.getStatisticsList().get(2))); + + var acProvider = mock(AutomationCompositionProvider.class); + var acElementStatisticsProvider = mock(AcElementStatisticsProvider.class); + MonitoringProvider provider = + new MonitoringProvider(participantStatisticsProvider, acElementStatisticsProvider, acProvider); + provider.createParticipantStatistics(inputParticipantStatistics.getStatisticsList()); + + assertThatThrownBy(() -> { + provider.fetchFilteredParticipantStatistics(null, null, 0, null, null); + }).hasMessageMatching(NAME_IS_NULL); + + // Fetch specific statistics record with name, version and record count + ParticipantStatisticsList getResponse = + provider.fetchFilteredParticipantStatistics(ID_NAME2, ID_VERSION1, 1, null, null); + assertThat(getResponse.getStatisticsList()).hasSize(1); + assertEquals(getResponse.getStatisticsList().get(0).toString().replaceAll("\\s+", ""), + inputParticipantStatistics.getStatisticsList().get(2).toString().replaceAll("\\s+", "")); + + // Fetch statistics using timestamp + getResponse = provider.fetchFilteredParticipantStatistics(ID_NAME1, ID_VERSION1, 0, null, + Instant.parse("2021-01-10T15:00:00.000Z")); + assertThat(getResponse.getStatisticsList()).hasSize(1); + + getResponse = provider.fetchFilteredParticipantStatistics(ID_NAME1, ID_VERSION1, 0, + Instant.parse("2021-01-11T12:00:00.000Z"), Instant.parse("2021-01-11T16:00:00.000Z")); + + assertThat(getResponse.getStatisticsList()).isEmpty(); + } + + @Test + void testCreateAcElementStatistics() throws Exception { + var acElementStatisticsProvider = mock(AcElementStatisticsProvider.class); + when(acElementStatisticsProvider.createAcElementStatistics(any())) + .thenReturn(inputAcElementStatistics.getAcElementStatistics()); + + when(acElementStatisticsProvider.createAcElementStatistics(eq(null))) + .thenThrow(new PfModelRuntimeException(Response.Status.BAD_REQUEST, AC_LIST_IS_NULL)); + + var acProvider = mock(AutomationCompositionProvider.class); + + var participantStatisticsProvider = mock(ParticipantStatisticsProvider.class); + MonitoringProvider provider = + new MonitoringProvider(participantStatisticsProvider, acElementStatisticsProvider, acProvider); + // Creating statistics data in db with null input + assertThatThrownBy(() -> { + provider.createAcElementStatistics(null); + }).hasMessageMatching(STAT_LIST_IS_NULL); + + assertThatThrownBy(() -> { + provider.createAcElementStatistics(invalidAcElementInput.getAcElementStatistics()); + }).hasMessageMatching(AC_LIST_IS_NULL); + + // Creating acElement statistics data from input json + AcElementStatisticsList createResponse = + provider.createAcElementStatistics(inputAcElementStatistics.getAcElementStatistics()); + + assertThat(createResponse.getAcElementStatistics()).hasSize(4); + assertEquals(createResponse.getAcElementStatistics().toString().replaceAll("\\s+", ""), + inputAcElementStatistics.getAcElementStatistics().toString().replaceAll("\\s+", "")); + } + + @Test + void testGetAcElementStatistics() throws Exception { + var participantStatisticsProvider = mock(ParticipantStatisticsProvider.class); + var acElementStatisticsProvider = mock(AcElementStatisticsProvider.class); + var acProvider = mock(AutomationCompositionProvider.class); + + when(acElementStatisticsProvider.getFilteredAcElementStatistics(eq(ID_NAME1), any(), any(), any(), anyMap(), + eq(SORT_DESC), eq(0))) + .thenReturn(List.of(inputAcElementStatistics.getAcElementStatistics().get(0), + inputAcElementStatistics.getAcElementStatistics().get(1))); + + when(acElementStatisticsProvider.getFilteredAcElementStatistics(eq(ID_NAME1), any(), any(), any(), anyMap(), + eq(SORT_DESC), eq(0))) + .thenReturn(List.of(inputAcElementStatistics.getAcElementStatistics().get(0), + inputAcElementStatistics.getAcElementStatistics().get(1))); + + MonitoringProvider provider = + new MonitoringProvider(participantStatisticsProvider, acElementStatisticsProvider, acProvider); + assertThatThrownBy(() -> { + provider.fetchFilteredAcElementStatistics(null, null, null, null, null, 0); + }).hasMessageMatching(NAME_IS_NULL); + + provider.createAcElementStatistics(inputAcElementStatistics.getAcElementStatistics()); + + AcElementStatisticsList getResponse = + provider.fetchFilteredAcElementStatistics(ID_NAME1, null, null, null, null, 0); + + assertThat(getResponse.getAcElementStatistics()).hasSize(2); + assertEquals(getResponse.getAcElementStatistics().get(0).toString().replaceAll("\\s+", ""), + inputAcElementStatistics.getAcElementStatistics().get(0).toString().replaceAll("\\s+", "")); + + // Fetch specific statistics record with name, id and record count + getResponse = provider.fetchFilteredAcElementStatistics(ID_NAME1, ID_VERSION1, + "709c62b3-8918-41b9-a747-d21eb79c6c20", null, null, 0); + assertThat(getResponse.getAcElementStatistics()).hasSize(2); + + // Fetch statistics using timestamp + getResponse = provider.fetchFilteredAcElementStatistics(ID_NAME1, ID_VERSION1, null, + Instant.parse("2021-01-10T13:45:00.000Z"), null, 0); + assertThat(getResponse.getAcElementStatistics()).hasSize(2); + } + + @Test + void testGetParticipantStatsPerAc() throws Exception { + var participantStatisticsProvider = mock(ParticipantStatisticsProvider.class); + var acElementStatisticsProvider = mock(AcElementStatisticsProvider.class); + var mockAcProvider = Mockito.mock(AutomationCompositionProvider.class); + var provider = + new MonitoringProvider(participantStatisticsProvider, acElementStatisticsProvider, mockAcProvider); + + provider.createParticipantStatistics(inputParticipantStatistics.getStatisticsList()); + + var automationComposition = new AutomationComposition(); + var element = new AutomationCompositionElement(); + element.setParticipantId(new ToscaConceptIdentifier(ID_NAME1, ID_VERSION1)); + automationComposition.setElements(Map.of(UUID.randomUUID(), element)); + when(mockAcProvider.findAutomationComposition(new ToscaConceptIdentifier(ID_NAME2, ID_VERSION1))) + .thenReturn(Optional.of(automationComposition)); + + when(participantStatisticsProvider.getFilteredParticipantStatistics(eq(ID_NAME1), eq(ID_VERSION1), any(), any(), + eq(null), eq(SORT_DESC), eq(0))) + .thenReturn(List.of(inputParticipantStatistics.getStatisticsList().get(0), + inputParticipantStatistics.getStatisticsList().get(1))); + + ParticipantStatisticsList getResponse = + provider.fetchParticipantStatsPerAutomationComposition(ID_NAME2, ID_VERSION1); + assertThat(getResponse.getStatisticsList()).hasSize(2); + assertEquals(getResponse.getStatisticsList().get(0).toString().replaceAll("\\s+", ""), + inputParticipantStatistics.getStatisticsList().get(0).toString().replaceAll("\\s+", "")); + assertThat( + provider.fetchParticipantStatsPerAutomationComposition(ID_INVALID_NAME, ID_VERSION2).getStatisticsList()) + .isEmpty(); + } + + @Test + void testAcElementStatsPerAc() throws Exception { + // Setup a dummy automation composition data + var mockAcElement = new AutomationCompositionElement(); + mockAcElement.setId(inputAcElementStatistics.getAcElementStatistics().get(0).getId()); + mockAcElement.setParticipantId(new ToscaConceptIdentifier( + inputAcElementStatistics.getAcElementStatistics().get(0).getParticipantId().getName(), + inputAcElementStatistics.getAcElementStatistics().get(0).getParticipantId().getVersion())); + var mockAc = new AutomationComposition(); + mockAc.setElements(new LinkedHashMap<>()); + mockAc.getElements().put(mockAcElement.getId(), mockAcElement); + + var participantStatisticsProvider = mock(ParticipantStatisticsProvider.class); + var acElementStatisticsProvider = mock(AcElementStatisticsProvider.class); + var mockAcProvider = Mockito.mock(AutomationCompositionProvider.class); + var monitoringProvider = + new MonitoringProvider(participantStatisticsProvider, acElementStatisticsProvider, mockAcProvider); + + // Mock automation composition data to be returned for the given AC Id + when(mockAcProvider.findAutomationComposition(new ToscaConceptIdentifier(ID_NAME3, ID_VERSION1))) + .thenReturn(Optional.of(mockAc)); + + when(acElementStatisticsProvider.getFilteredAcElementStatistics(eq(ID_NAME1), eq(ID_VERSION1), any(), any(), + anyMap(), eq(SORT_DESC), eq(0))) + .thenReturn(List.of(inputAcElementStatistics.getAcElementStatistics().get(0), + inputAcElementStatistics.getAcElementStatistics().get(1))); + + monitoringProvider.createAcElementStatistics(inputAcElementStatistics.getAcElementStatistics()); + + AcElementStatisticsList getResponse = + monitoringProvider.fetchAcElementStatsPerAutomationComposition(ID_NAME3, ID_VERSION1); + + assertThat(getResponse.getAcElementStatistics()).hasSize(2); + assertEquals(getResponse.getAcElementStatistics().get(1).toString().replaceAll("\\s+", ""), + inputAcElementStatistics.getAcElementStatistics().get(1).toString().replaceAll("\\s+", "")); + + assertThat(monitoringProvider.fetchAcElementStatsPerAutomationComposition(ID_INVALID_NAME, ID_VERSION2) + .getAcElementStatistics()).isEmpty(); + + Map<String, ToscaConceptIdentifier> acElementIds = + monitoringProvider.getAllAcElementsIdPerAutomationComposition(ID_NAME3, ID_VERSION1); + assertThat(acElementIds) + .containsKey(inputAcElementStatistics.getAcElementStatistics().get(0).getId().toString()); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/monitoring/rest/MonitoringQueryControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/monitoring/rest/MonitoringQueryControllerTest.java new file mode 100644 index 000000000..7630e42d2 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/monitoring/rest/MonitoringQueryControllerTest.java @@ -0,0 +1,242 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.monitoring.rest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.io.File; +import java.time.Instant; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.policy.clamp.acm.runtime.monitoring.MonitoringProvider; +import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; +import org.onap.policy.clamp.models.acm.concepts.AcElementStatisticsList; +import org.onap.policy.clamp.models.acm.concepts.ParticipantStatisticsList; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +class MonitoringQueryControllerTest extends CommonRestController { + + private static final String AC_PARTICIPANT_STATISTICS_JSON = + "src/test/resources/rest/monitoring/TestParticipantStatistics.json"; + private static final String AC_ELEMENT_STATISTICS_JSON = + "src/test/resources/rest/monitoring/TestAcElementStatistics.json"; + + private static final Coder CODER = new StandardCoder(); + + private static ParticipantStatisticsList inputParticipantStatistics; + private static AcElementStatisticsList inputAcElementStatistics; + + private static ParticipantStatisticsList participantStatisticsList; + private static AcElementStatisticsList acElementStatisticsList; + + private static final String AC_ELEMENT_STATS_ENDPOINT = "monitoring/acelement"; + private static final String PARTICIPANT_STATS_ENDPOINT = "monitoring/participant"; + private static final String PARTICIPANT_STATS_PER_AC_ENDPOINT = "monitoring/participants/automationcomposition"; + private static final String AC_ELEMENT_STATS_PER_AC_ENDPOINT = "monitoring/acelements/automationcomposition"; + + @Autowired + private MonitoringProvider monitoringProvider; + + @LocalServerPort + private int randomServerPort; + + /** + * starts Main. + * + * @throws Exception if an error occurs + */ + @BeforeAll + public static void setUpBeforeAll() throws Exception { + + inputParticipantStatistics = + CODER.decode(new File(AC_PARTICIPANT_STATISTICS_JSON), ParticipantStatisticsList.class); + inputAcElementStatistics = CODER.decode(new File(AC_ELEMENT_STATISTICS_JSON), AcElementStatisticsList.class); + } + + @BeforeEach + public void setUpBeforeEach() throws Exception { + super.setHttpPrefix(randomServerPort); + + // Insert Participant statistics to DB + participantStatisticsList = + monitoringProvider.createParticipantStatistics(inputParticipantStatistics.getStatisticsList()); + // Insert AC Element statistics to DB + acElementStatisticsList = + monitoringProvider.createAcElementStatistics(inputAcElementStatistics.getAcElementStatistics()); + } + + @Test + void testQuery_Unauthorized_for_AcElementStats() throws Exception { + assertUnauthorizedGet(AC_ELEMENT_STATS_ENDPOINT); + } + + @Test + void testQuery_Unauthorized_for_AcParticipantStats() throws Exception { + assertUnauthorizedGet(PARTICIPANT_STATS_ENDPOINT); + } + + @Test + void testQuery_Unauthorized_for_ParticipantStatsPerAc() throws Exception { + assertUnauthorizedGet(PARTICIPANT_STATS_PER_AC_ENDPOINT); + } + + @Test + void testQuery_Unauthorized_for_AcElementStatsPerAc() throws Exception { + assertUnauthorizedGet(AC_ELEMENT_STATS_PER_AC_ENDPOINT); + } + + @Test + void testSwagger_AcStats() throws Exception { + super.testSwagger(AC_ELEMENT_STATS_ENDPOINT); + super.testSwagger(PARTICIPANT_STATS_ENDPOINT); + super.testSwagger(AC_ELEMENT_STATS_PER_AC_ENDPOINT); + super.testSwagger(PARTICIPANT_STATS_PER_AC_ENDPOINT); + } + + @Test + void testAcElementStatisticsEndpoint() throws Exception { + // Filter statistics only based on participant Id and UUID + Invocation.Builder invokeRequest1 = super.sendRequest(AC_ELEMENT_STATS_ENDPOINT + "?name=" + + acElementStatisticsList.getAcElementStatistics().get(0).getParticipantId().getName() + "&version=" + + acElementStatisticsList.getAcElementStatistics().get(0).getParticipantId().getVersion() + "&id=" + + acElementStatisticsList.getAcElementStatistics().get(0).getId().toString()); + Response response1 = invokeRequest1.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), response1.getStatus()); + + AcElementStatisticsList result1 = response1.readEntity(AcElementStatisticsList.class); + + assertNotNull(result1); + assertThat(result1.getAcElementStatistics()).hasSize(2); + + var acElementStat0 = acElementStatisticsList.getAcElementStatistics().get(0); + for (var acElement : result1.getAcElementStatistics()) { + assertEquals(acElement.getParticipantId().asConceptKey(), acElementStat0.getParticipantId().asConceptKey()); + assertEquals(acElement.getId(), acElementStat0.getId()); + } + + // Filter statistics based on timestamp + Invocation.Builder invokeRequest2 = super.sendRequest(AC_ELEMENT_STATS_ENDPOINT + "?name=" + + acElementStatisticsList.getAcElementStatistics().get(1).getParticipantId().getName() + "&version=" + + acElementStatisticsList.getAcElementStatistics().get(1).getParticipantId().getVersion() + + "&startTime=" + Instant.parse("2021-01-10T13:00:00.000Z") + "&endTime=" + + Instant.parse("2021-01-10T14:00:00.000Z")); + Response response2 = invokeRequest2.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), response2.getStatus()); + AcElementStatisticsList result2 = response2.readEntity(AcElementStatisticsList.class); + + assertNotNull(result2); + assertThat(result2.getAcElementStatistics()).hasSize(1); + assertEquals(result2.getAcElementStatistics().get(0), acElementStat0); + } + + @Test + void testAcElementStats_BadRequest() throws Exception { + Invocation.Builder invokeRequest1 = super.sendRequest(AC_ELEMENT_STATS_ENDPOINT + "?version=1.0.0"); + Response response1 = invokeRequest1.buildGet().invoke(); + assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response1.getStatus()); + } + + @Test + void testParticipantStatisticsEndpoint() throws Exception { + + // Filter statistics only based on participant Id + Invocation.Builder invokeRequest1 = super.sendRequest(PARTICIPANT_STATS_ENDPOINT + "?name=" + + participantStatisticsList.getStatisticsList().get(0).getParticipantId().getName() + "&version=" + + participantStatisticsList.getStatisticsList().get(0).getParticipantId().getVersion()); + Response response1 = invokeRequest1.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), response1.getStatus()); + ParticipantStatisticsList result1 = response1.readEntity(ParticipantStatisticsList.class); + + assertNotNull(result1); + assertThat(result1.getStatisticsList()).hasSize(2); + assertThat(result1.getStatisticsList()).contains(participantStatisticsList.getStatisticsList().get(0)); + + // Filter statistics based on timestamp + Invocation.Builder invokeRequest2 = super.sendRequest(PARTICIPANT_STATS_ENDPOINT + "?name=" + + participantStatisticsList.getStatisticsList().get(1).getParticipantId().getName() + "&version=" + + participantStatisticsList.getStatisticsList().get(1).getParticipantId().getVersion() + "&startTime=" + + Instant.parse("2021-01-10T13:00:00.000Z") + "&endTime=" + Instant.parse("2021-01-10T14:00:00.000Z")); + Response response2 = invokeRequest2.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), response2.getStatus()); + ParticipantStatisticsList result2 = response2.readEntity(ParticipantStatisticsList.class); + + assertNotNull(result2); + assertThat(result2.getStatisticsList()).hasSize(1); + assertEquals(result2.getStatisticsList().get(0), participantStatisticsList.getStatisticsList().get(0)); + } + + @Test + void testParticipantStats_BadRequest() throws Exception { + Invocation.Builder invokeRequest1 = super.sendRequest(PARTICIPANT_STATS_ENDPOINT + "?version=0.0"); + Response response1 = invokeRequest1.buildGet().invoke(); + assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response1.getStatus()); + } + + @Test + void testParticipantStatsPerAcEndpoint() throws Exception { + Invocation.Builder invokeRequest1 = + super.sendRequest(PARTICIPANT_STATS_PER_AC_ENDPOINT + "?name=dummyName&version=1.001"); + Response response1 = invokeRequest1.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), response1.getStatus()); + ParticipantStatisticsList result1 = response1.readEntity(ParticipantStatisticsList.class); + assertThat(result1.getStatisticsList()).isEmpty(); + } + + @Test + void testParticipantStatsPerAc_BadRequest() throws Exception { + Invocation.Builder invokeRequest1 = super.sendRequest(PARTICIPANT_STATS_PER_AC_ENDPOINT); + Response response1 = invokeRequest1.buildGet().invoke(); + assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response1.getStatus()); + } + + @Test + void testAcElementStatisticsPerAcEndpoint() throws Exception { + Invocation.Builder invokeRequest1 = + super.sendRequest(AC_ELEMENT_STATS_PER_AC_ENDPOINT + "?name=dummyName&version=1.001"); + Response response1 = invokeRequest1.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), response1.getStatus()); + AcElementStatisticsList result1 = response1.readEntity(AcElementStatisticsList.class); + assertThat(result1.getAcElementStatistics()).isEmpty(); + } + + @Test + void testAcElementStatsPerAc_BadRequest() throws Exception { + Invocation.Builder invokeRequest1 = super.sendRequest(AC_ELEMENT_STATS_PER_AC_ENDPOINT); + Response response1 = invokeRequest1.buildGet().invoke(); + assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response1.getStatus()); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/HandleCounterTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/HandleCounterTest.java new file mode 100644 index 000000000..a6474c9e3 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/HandleCounterTest.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.supervision; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class HandleCounterTest { + + private static final int ID = 1; + + @Test + void testCount() { + var handleCounter = new HandleCounter<Integer>(); + handleCounter.setMaxRetryCount(2); + assertThat(handleCounter.count(ID)).isTrue(); + assertThat(handleCounter.getCounter(ID)).isEqualTo(1); + assertThat(handleCounter.count(ID)).isTrue(); + assertThat(handleCounter.getCounter(ID)).isEqualTo(2); + assertThat(handleCounter.count(ID)).isFalse(); + assertThat(handleCounter.getCounter(ID)).isEqualTo(2); + + handleCounter.clear(ID); + assertThat(handleCounter.count(ID)).isTrue(); + assertThat(handleCounter.getCounter(ID)).isEqualTo(1); + } + + @Test + void testFault() { + var handleCounter = new HandleCounter<Integer>(); + handleCounter.setFault(ID); + assertThat(handleCounter.isFault(ID)).isTrue(); + handleCounter.clear(ID); + assertThat(handleCounter.isFault(ID)).isFalse(); + } + + @Test + void testDuration() throws InterruptedException { + + var handleCounter = new HandleCounter<Integer>() { + long epochMilli = 0; + + @Override + protected long getEpochMilli() { + return epochMilli; + } + }; + handleCounter.epochMilli = 100; + var result = handleCounter.getDuration(ID); + assertThat(result).isZero(); + + handleCounter.epochMilli += 100; + result = handleCounter.getDuration(ID); + assertThat(result).isEqualTo(100); + + handleCounter.epochMilli += 100; + result = handleCounter.getDuration(ID); + assertThat(result).isEqualTo(200); + + handleCounter.epochMilli += 100; + handleCounter.clear(ID); + result = handleCounter.getDuration(ID); + assertThat(result).isZero(); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAspectTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAspectTest.java new file mode 100644 index 000000000..487d41139 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAspectTest.java @@ -0,0 +1,66 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.supervision; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class SupervisionAspectTest { + + @Test + void testSchedule() throws Exception { + var supervisionScanner = spy(mock(SupervisionScanner.class)); + try (var supervisionAspect = new SupervisionAspect(supervisionScanner)) { + supervisionAspect.schedule(); + verify(supervisionScanner, timeout(500)).run(true); + } + } + + @Test + void testDoCheck() throws Exception { + var supervisionScanner = spy(mock(SupervisionScanner.class)); + try (var supervisionAspect = new SupervisionAspect(supervisionScanner)) { + supervisionAspect.doCheck(); + supervisionAspect.doCheck(); + verify(supervisionScanner, timeout(500).times(2)).run(false); + } + } + + @Test + void testHandleParticipantStatus() throws Exception { + var supervisionScanner = spy(mock(SupervisionScanner.class)); + var participantStatusMessage = new ParticipantStatus(); + var identifier = new ToscaConceptIdentifier("abc", "1.0.0"); + participantStatusMessage.setParticipantId(identifier); + + try (var supervisionAspect = new SupervisionAspect(supervisionScanner)) { + supervisionAspect.handleParticipantStatus(participantStatusMessage); + verify(supervisionScanner, timeout(500)).handleParticipantStatus(identifier); + } + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java new file mode 100644 index 000000000..99e509c0e --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java @@ -0,0 +1,319 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.supervision; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; +import org.onap.policy.clamp.acm.runtime.monitoring.MonitoringProvider; +import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionUpdatePublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantDeregisterAckPublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantRegisterAckPublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantUpdatePublisher; +import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState; +import org.onap.policy.clamp.models.acm.concepts.Participant; +import org.onap.policy.clamp.models.acm.concepts.ParticipantHealthStatus; +import org.onap.policy.clamp.models.acm.concepts.ParticipantState; +import org.onap.policy.clamp.models.acm.concepts.ParticipantStatistics; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.AutomationCompositionAck; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantDeregister; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantRegister; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantUpdateAck; +import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ServiceTemplateProvider; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class SupervisionHandlerTest { + private static final String TOSCA_TEMPLATE_YAML = + "src/test/resources/rest/servicetemplates/tosca-for-smoke-testing.yaml"; + private static final String AC_INSTANTIATION_CREATE_JSON = + "src/test/resources/rest/acm/AutomationCompositions.json"; + private static final ToscaConceptIdentifier identifier = new ToscaConceptIdentifier("PMSHInstance0Crud", "1.0.1"); + private static final ToscaConceptIdentifier participantId = new ToscaConceptIdentifier("ParticipantId", "1.0.0"); + private static final ToscaConceptIdentifier participantType = + new ToscaConceptIdentifier("ParticipantType", "1.0.0"); + + @Test + void testTriggerAutomationCompositionSupervisionEmpty() + throws AutomationCompositionException, PfModelException, CoderException { + var handler = + createSupervisionHandler(mock(AutomationCompositionProvider.class), mock(ParticipantProvider.class), + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionUpdatePublisher.class), + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE); + + assertThatThrownBy(() -> handler.triggerAutomationCompositionSupervision(List.of())) + .hasMessageMatching("The list of automation compositions for supervision is empty"); + } + + @Test + void testTriggerAutomationCompositionSupervision() + throws AutomationCompositionException, PfModelException, CoderException { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); + var handler = createSupervisionHandler(automationCompositionProvider, mock(ParticipantProvider.class), + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), automationCompositionUpdatePublisher, + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE); + + handler.triggerAutomationCompositionSupervision(List.of(identifier)); + + verify(automationCompositionUpdatePublisher).send(any(AutomationComposition.class)); + verify(automationCompositionProvider).saveAutomationComposition(any(AutomationComposition.class)); + } + + @Test + void testTriggerAutomationCompositionUninitialised() + throws AutomationCompositionException, PfModelException, CoderException { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); + var handler = createSupervisionHandler(automationCompositionProvider, mock(ParticipantProvider.class), + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), automationCompositionUpdatePublisher, + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.UNINITIALISED); + + assertThatThrownBy(() -> handler.triggerAutomationCompositionSupervision(List.of(identifier))) + .hasMessageMatching("Automation composition is already in state UNINITIALISED"); + } + + @Test + void testTriggerAutomationCompositionRunning() + throws AutomationCompositionException, PfModelException, CoderException { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); + var handler = createSupervisionHandler(automationCompositionProvider, mock(ParticipantProvider.class), + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), automationCompositionUpdatePublisher, + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.RUNNING); + + assertThatThrownBy(() -> handler.triggerAutomationCompositionSupervision(List.of(identifier))) + .hasMessageMatching("Automation composition can't transition from state UNINITIALISED to state RUNNING"); + } + + @Test + void testHandleAutomationCompositionStateChangeAckMessage() throws PfModelException, CoderException { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var handler = createSupervisionHandler(automationCompositionProvider, mock(ParticipantProvider.class), + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionUpdatePublisher.class), + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE); + var automationCompositionAckMessage = + new AutomationCompositionAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK); + automationCompositionAckMessage.setAutomationCompositionResultMap(Map.of()); + automationCompositionAckMessage.setAutomationCompositionId(identifier); + + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + verify(automationCompositionProvider).saveAutomationComposition(any(AutomationComposition.class)); + } + + @Test + void testHandleAutomationCompositionUpdateAckMessage() throws PfModelException, CoderException { + var automationCompositionAckMessage = + new AutomationCompositionAck(ParticipantMessageType.AUTOMATION_COMPOSITION_UPDATE_ACK); + automationCompositionAckMessage.setParticipantId(participantId); + automationCompositionAckMessage.setParticipantType(participantType); + automationCompositionAckMessage.setAutomationCompositionResultMap(Map.of()); + automationCompositionAckMessage.setAutomationCompositionId(identifier); + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var handler = createSupervisionHandler(automationCompositionProvider, mock(ParticipantProvider.class), + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionUpdatePublisher.class), + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE); + + handler.handleAutomationCompositionUpdateAckMessage(automationCompositionAckMessage); + + verify(automationCompositionProvider).saveAutomationComposition(any(AutomationComposition.class)); + } + + @Test + void testHandleParticipantDeregister() throws PfModelException, CoderException { + var participant = new Participant(); + participant.setName(participantId.getName()); + participant.setVersion(participantId.getVersion()); + participant.setParticipantType(participantType); + + var participantProvider = mock(ParticipantProvider.class); + when(participantProvider.findParticipant(participantId.getName(), participantId.getVersion())) + .thenReturn(Optional.of(participant)); + + var participantDeregisterMessage = new ParticipantDeregister(); + participantDeregisterMessage.setMessageId(UUID.randomUUID()); + participantDeregisterMessage.setParticipantId(participantId); + participantDeregisterMessage.setParticipantType(participantType); + var participantDeregisterAckPublisher = mock(ParticipantDeregisterAckPublisher.class); + var handler = createSupervisionHandler(mock(AutomationCompositionProvider.class), participantProvider, + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + participantDeregisterAckPublisher, mock(AutomationCompositionUpdatePublisher.class), + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE); + + handler.handleParticipantMessage(participantDeregisterMessage); + + verify(participantProvider).saveParticipant(any()); + verify(participantDeregisterAckPublisher).send(participantDeregisterMessage.getMessageId()); + } + + @Test + void testHandleParticipantRegister() throws PfModelException, CoderException { + var participant = new Participant(); + participant.setName(participantId.getName()); + participant.setVersion(participantId.getVersion()); + participant.setParticipantType(participantType); + + var participantRegisterMessage = new ParticipantRegister(); + participantRegisterMessage.setMessageId(UUID.randomUUID()); + participantRegisterMessage.setParticipantId(participantId); + participantRegisterMessage.setParticipantType(participantType); + var participantProvider = mock(ParticipantProvider.class); + var participantRegisterAckPublisher = mock(ParticipantRegisterAckPublisher.class); + var handler = createSupervisionHandler(mock(AutomationCompositionProvider.class), participantProvider, + mock(MonitoringProvider.class), participantRegisterAckPublisher, + mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionUpdatePublisher.class), + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE); + + handler.handleParticipantMessage(participantRegisterMessage); + + verify(participantProvider).saveParticipant(any()); + verify(participantRegisterAckPublisher).send(participantRegisterMessage.getMessageId(), participantId, + participantType); + } + + @Test + void testParticipantUpdateAck() throws PfModelException, CoderException { + var participant = new Participant(); + participant.setName(participantId.getName()); + participant.setVersion(participantId.getVersion()); + participant.setParticipantType(participantType); + + var participantProvider = mock(ParticipantProvider.class); + when(participantProvider.findParticipant(participantId.getName(), participantId.getVersion())) + .thenReturn(Optional.of(participant)); + + var participantUpdateAckMessage = new ParticipantUpdateAck(); + participantUpdateAckMessage.setParticipantId(participantId); + participantUpdateAckMessage.setParticipantType(participantType); + participantUpdateAckMessage.setState(ParticipantState.PASSIVE); + var handler = createSupervisionHandler(mock(AutomationCompositionProvider.class), participantProvider, + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionUpdatePublisher.class), + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE); + + handler.handleParticipantMessage(participantUpdateAckMessage); + + verify(participantProvider).saveParticipant(any()); + } + + @Test + void testHandleParticipantStatus() throws PfModelException, CoderException { + var participantStatusMessage = new ParticipantStatus(); + participantStatusMessage.setParticipantId(participantId); + participantStatusMessage.setParticipantType(participantType); + participantStatusMessage.setState(ParticipantState.PASSIVE); + participantStatusMessage.setHealthStatus(ParticipantHealthStatus.HEALTHY); + participantStatusMessage.setParticipantStatistics(new ParticipantStatistics()); + + var participantProvider = mock(ParticipantProvider.class); + var monitoringProvider = mock(MonitoringProvider.class); + var handler = createSupervisionHandler(mock(AutomationCompositionProvider.class), participantProvider, + monitoringProvider, mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionUpdatePublisher.class), + mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE); + handler.handleParticipantMessage(participantStatusMessage); + + verify(participantProvider).saveParticipant(any()); + verify(monitoringProvider).createParticipantStatistics(anyList()); + } + + @Test + void testHandleSendCommissionMessage() throws PfModelException, CoderException { + var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); + var handler = + createSupervisionHandler(mock(AutomationCompositionProvider.class), mock(ParticipantProvider.class), + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionUpdatePublisher.class), + participantUpdatePublisher, AutomationCompositionOrderedState.PASSIVE); + handler.handleSendCommissionMessage(participantId.getName(), participantId.getVersion()); + + verify(participantUpdatePublisher).sendComissioningBroadcast(participantId.getName(), + participantId.getVersion()); + } + + @Test + void testHandleSendDeCommissionMessage() throws PfModelException, CoderException { + var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); + var handler = + createSupervisionHandler(mock(AutomationCompositionProvider.class), mock(ParticipantProvider.class), + mock(MonitoringProvider.class), mock(ParticipantRegisterAckPublisher.class), + mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionUpdatePublisher.class), + participantUpdatePublisher, AutomationCompositionOrderedState.PASSIVE); + handler.handleSendDeCommissionMessage(); + + verify(participantUpdatePublisher).sendDecomisioning(); + } + + private SupervisionHandler createSupervisionHandler(AutomationCompositionProvider automationCompositionProvider, + ParticipantProvider participantProvider, MonitoringProvider monitoringProvider, + ParticipantRegisterAckPublisher participantRegisterAckPublisher, + ParticipantDeregisterAckPublisher participantDeregisterAckPublisher, + AutomationCompositionUpdatePublisher automationCompositionUpdatePublisher, + ParticipantUpdatePublisher participantUpdatePublisher, AutomationCompositionOrderedState orderedState) + throws PfModelException, CoderException { + var automationCompositionsCreate = + InstantiationUtils.getAutomationCompositionsFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); + + var automationComposition = automationCompositionsCreate.getAutomationCompositionList().get(0); + automationComposition.setOrderedState(orderedState); + + when(automationCompositionProvider.findAutomationComposition(identifier)) + .thenReturn(Optional.of(automationComposition)); + when(automationCompositionProvider.getAutomationComposition(identifier)).thenReturn(automationComposition); + + var serviceTemplateProvider = Mockito.mock(ServiceTemplateProvider.class); + when(serviceTemplateProvider.getServiceTemplateList(any(), any())) + .thenReturn(List.of(InstantiationUtils.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML))); + + var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); + + return new SupervisionHandler(automationCompositionProvider, participantProvider, monitoringProvider, + serviceTemplateProvider, automationCompositionUpdatePublisher, automationCompositionStateChangePublisher, + participantRegisterAckPublisher, participantDeregisterAckPublisher, participantUpdatePublisher); + + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java new file mode 100644 index 000000000..cd1a49b46 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java @@ -0,0 +1,214 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.supervision; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; +import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionUpdatePublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantStatusReqPublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantUpdatePublisher; +import org.onap.policy.clamp.acm.runtime.util.CommonTestData; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState; +import org.onap.policy.clamp.models.acm.concepts.Participant; +import org.onap.policy.clamp.models.acm.concepts.ParticipantHealthStatus; +import org.onap.policy.clamp.models.acm.concepts.ParticipantState; +import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ServiceTemplateProvider; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +class SupervisionScannerTest { + + private static final String TOSCA_SERVICE_TEMPLATE_YAML = + "src/test/resources/rest/servicetemplates/tosca-for-smoke-testing.yaml"; + private static final String AC_JSON = "src/test/resources/rest/acm/AutomationCompositionsSmoke.json"; + + private static ServiceTemplateProvider serviceTemplateProvider = mock(ServiceTemplateProvider.class); + + @BeforeAll + public static void setUpBeforeAll() throws Exception { + ToscaServiceTemplate serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + when(serviceTemplateProvider.getAllServiceTemplates()).thenReturn(List.of(serviceTemplate)); + } + + @Test + void testScannerOrderedStateEqualsToState() throws PfModelException, CoderException { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); + var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); + var participantProvider = mock(ParticipantProvider.class); + var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class); + var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); + var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + + var automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_JSON, "Crud").getAutomationCompositionList(); + when(automationCompositionProvider.getAutomationCompositions()).thenReturn(automationCompositions); + + var supervisionScanner = new SupervisionScanner(automationCompositionProvider, serviceTemplateProvider, + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + participantStatusReqPublisher, participantUpdatePublisher, acRuntimeParameterGroup); + supervisionScanner.run(false); + + verify(automationCompositionProvider, times(0)).saveAutomationComposition(any(AutomationComposition.class)); + } + + @Test + void testScannerOrderedStateDifferentToState() throws PfModelException, CoderException { + var automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_JSON, "Crud").getAutomationCompositionList(); + automationCompositions.get(0).setState(AutomationCompositionState.UNINITIALISED2PASSIVE); + automationCompositions.get(0).setOrderedState(AutomationCompositionOrderedState.UNINITIALISED); + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + when(automationCompositionProvider.getAutomationCompositions()).thenReturn(automationCompositions); + + var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); + var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); + var participantProvider = mock(ParticipantProvider.class); + var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class); + var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); + var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + + var supervisionScanner = new SupervisionScanner(automationCompositionProvider, serviceTemplateProvider, + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + participantStatusReqPublisher, participantUpdatePublisher, acRuntimeParameterGroup); + supervisionScanner.run(false); + + verify(automationCompositionProvider, times(1)).saveAutomationComposition(any(AutomationComposition.class)); + } + + @Test + void testScanner() throws PfModelException { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var automationComposition = new AutomationComposition(); + when(automationCompositionProvider.getAutomationCompositions()).thenReturn(List.of(automationComposition)); + + var participantProvider = mock(ParticipantProvider.class); + var participant = new Participant(); + participant.setName("Participant0"); + participant.setVersion("1.0.0"); + when(participantProvider.getParticipants(null, null)).thenReturn(List.of(participant)); + + var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); + var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class); + var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); + var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); + var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + + var supervisionScanner = new SupervisionScanner(automationCompositionProvider, serviceTemplateProvider, + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + participantStatusReqPublisher, participantUpdatePublisher, acRuntimeParameterGroup); + + supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier()); + supervisionScanner.run(true); + verify(automationCompositionProvider, times(0)).saveAutomationComposition(any(AutomationComposition.class)); + verify(participantStatusReqPublisher, times(0)).send(any(ToscaConceptIdentifier.class)); + } + + @Test + void testSendAutomationCompositionMsgUpdate() throws PfModelException, CoderException { + var automationCompositions = + InstantiationUtils.getAutomationCompositionsFromResource(AC_JSON, "Crud").getAutomationCompositionList(); + automationCompositions.get(0).setState(AutomationCompositionState.UNINITIALISED2PASSIVE); + automationCompositions.get(0).setOrderedState(AutomationCompositionOrderedState.PASSIVE); + for (var element : automationCompositions.get(0).getElements().values()) { + if ("org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement" + .equals(element.getDefinition().getName())) { + element.setOrderedState(AutomationCompositionOrderedState.PASSIVE); + element.setState(AutomationCompositionState.UNINITIALISED); + } else { + element.setOrderedState(AutomationCompositionOrderedState.PASSIVE); + element.setState(AutomationCompositionState.PASSIVE); + } + } + + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + when(automationCompositionProvider.getAutomationCompositions()).thenReturn(automationCompositions); + + var participantProvider = mock(ParticipantProvider.class); + var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); + var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class); + var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); + var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); + var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + + var supervisionScanner = new SupervisionScanner(automationCompositionProvider, serviceTemplateProvider, + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + participantStatusReqPublisher, participantUpdatePublisher, acRuntimeParameterGroup); + + supervisionScanner.run(false); + + verify(automationCompositionUpdatePublisher).send(any(AutomationComposition.class), anyInt()); + } + + @Test + void testScanParticipant() throws PfModelException { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var automationComposition = new AutomationComposition(); + when(automationCompositionProvider.getAutomationCompositions()).thenReturn(List.of(automationComposition)); + + var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanParticipant"); + acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().setMaxWaitMs(-1); + acRuntimeParameterGroup.getParticipantParameters().setMaxStatusWaitMs(-1); + + var participant = new Participant(); + participant.setName("Participant0"); + participant.setVersion("1.0.0"); + participant.setHealthStatus(ParticipantHealthStatus.HEALTHY); + participant.setParticipantState(ParticipantState.ACTIVE); + participant.setDefinition(new ToscaConceptIdentifier("unknown", "0.0.0")); + participant.setParticipantType(new ToscaConceptIdentifier("ParticipantType1", "1.0.0")); + var participantProvider = mock(ParticipantProvider.class); + when(participantProvider.getParticipants()).thenReturn(List.of(participant)); + + var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); + var participantStatusReqPublisher = mock(ParticipantStatusReqPublisher.class); + var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); + var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); + + var supervisionScanner = new SupervisionScanner(automationCompositionProvider, serviceTemplateProvider, + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + participantStatusReqPublisher, participantUpdatePublisher, acRuntimeParameterGroup); + + supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier()); + supervisionScanner.run(true); + verify(participantStatusReqPublisher).send(any(ToscaConceptIdentifier.class)); + verify(participantProvider).saveParticipant(any()); + + supervisionScanner.run(true); + verify(participantProvider, times(2)).saveParticipant(any()); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java new file mode 100644 index 000000000..6545fe395 --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java @@ -0,0 +1,225 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.supervision.comm; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.time.Instant; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.onap.policy.clamp.acm.runtime.monitoring.MonitoringProvider; +import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler; +import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantDeregister; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantDeregisterAck; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantRegisterAck; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantUpdateAck; +import org.onap.policy.clamp.models.acm.persistence.provider.AcElementStatisticsProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantStatisticsProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ServiceTemplateProvider; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class SupervisionMessagesTest extends CommonRestController { + + private static final String NOT_ACTIVE = "Not Active!"; + private static final Object lockit = new Object(); + private static final CommInfrastructure INFRA = CommInfrastructure.NOOP; + private static final String TOPIC = "my-topic"; + private static SupervisionHandler supervisionHandler; + + /** + * setup Db Provider Parameters. + * + * @throws PfModelException if an error occurs + */ + @BeforeAll + public static void setupDbProviderParameters() throws PfModelException { + var acProvider = mock(AutomationCompositionProvider.class); + var participantStatisticsProvider = mock(ParticipantStatisticsProvider.class); + var acElementStatisticsProvider = mock(AcElementStatisticsProvider.class); + var monitoringProvider = + new MonitoringProvider(participantStatisticsProvider, acElementStatisticsProvider, acProvider); + var participantProvider = mock(ParticipantProvider.class); + var serviceTemplateProvider = Mockito.mock(ServiceTemplateProvider.class); + var automationCompositionUpdatePublisher = Mockito.mock(AutomationCompositionUpdatePublisher.class); + var automationCompositionStateChangePublisher = Mockito.mock(AutomationCompositionStateChangePublisher.class); + var participantRegisterAckPublisher = Mockito.mock(ParticipantRegisterAckPublisher.class); + var participantDeregisterAckPublisher = Mockito.mock(ParticipantDeregisterAckPublisher.class); + var participantUpdatePublisher = Mockito.mock(ParticipantUpdatePublisher.class); + supervisionHandler = new SupervisionHandler(acProvider, participantProvider, monitoringProvider, + serviceTemplateProvider, automationCompositionUpdatePublisher, automationCompositionStateChangePublisher, + participantRegisterAckPublisher, participantDeregisterAckPublisher, participantUpdatePublisher); + } + + @Test + void testSendParticipantRegisterAck() throws Exception { + final ParticipantRegisterAck participantRegisterAckMsg = new ParticipantRegisterAck(); + participantRegisterAckMsg.setMessage("ParticipantRegisterAck message"); + participantRegisterAckMsg.setResponseTo(UUID.randomUUID()); + participantRegisterAckMsg.setResult(true); + + synchronized (lockit) { + ParticipantRegisterAckPublisher acRegisterAckPublisher = new ParticipantRegisterAckPublisher(); + acRegisterAckPublisher.active(List.of(Mockito.mock(TopicSink.class))); + assertThatCode(() -> acRegisterAckPublisher.send(participantRegisterAckMsg)).doesNotThrowAnyException(); + } + } + + @Test + void testReceiveParticipantDeregister() throws Exception { + final ParticipantDeregister participantDeregisterMsg = new ParticipantDeregister(); + participantDeregisterMsg.setParticipantId(getParticipantId()); + participantDeregisterMsg.setTimestamp(Instant.now()); + participantDeregisterMsg.setParticipantType(getParticipantType()); + + synchronized (lockit) { + ParticipantDeregisterListener participantDeregisterListener = + new ParticipantDeregisterListener(supervisionHandler); + assertThatCode( + () -> participantDeregisterListener.onTopicEvent(INFRA, TOPIC, null, participantDeregisterMsg)) + .doesNotThrowAnyException(); + } + } + + @Test + void testSendParticipantDeregisterAck() throws Exception { + final ParticipantDeregisterAck participantDeregisterAckMsg = new ParticipantDeregisterAck(); + participantDeregisterAckMsg.setMessage("ParticipantDeregisterAck message"); + participantDeregisterAckMsg.setResponseTo(UUID.randomUUID()); + participantDeregisterAckMsg.setResult(true); + + synchronized (lockit) { + ParticipantDeregisterAckPublisher acDeregisterAckPublisher = new ParticipantDeregisterAckPublisher(); + acDeregisterAckPublisher.active(Collections.singletonList(Mockito.mock(TopicSink.class))); + assertThatCode(() -> acDeregisterAckPublisher.send(participantDeregisterAckMsg)).doesNotThrowAnyException(); + } + } + + @Test + void testReceiveParticipantUpdateAckMessage() throws Exception { + final ParticipantUpdateAck participantUpdateAckMsg = new ParticipantUpdateAck(); + participantUpdateAckMsg.setMessage("ParticipantUpdateAck message"); + participantUpdateAckMsg.setResponseTo(UUID.randomUUID()); + participantUpdateAckMsg.setResult(true); + participantUpdateAckMsg.setParticipantId(getParticipantId()); + participantUpdateAckMsg.setParticipantType(getParticipantType()); + + synchronized (lockit) { + ParticipantUpdateAckListener participantUpdateAckListener = + new ParticipantUpdateAckListener(supervisionHandler); + assertThatCode(() -> participantUpdateAckListener.onTopicEvent(INFRA, TOPIC, null, participantUpdateAckMsg)) + .doesNotThrowAnyException(); + } + } + + @Test + void testSendAutomationCompositionStateChangePublisherNotActive() { + var publisher = new AutomationCompositionStateChangePublisher(); + assertThatThrownBy(() -> publisher.send(getAutomationComposition(), 0)).hasMessage(NOT_ACTIVE); + } + + @Test + void testSendAutomationCompositionStateChangePublisher() { + var publisher = new AutomationCompositionStateChangePublisher(); + var topicSink = mock(TopicSink.class); + publisher.active(List.of(topicSink)); + publisher.send(getAutomationComposition(), 0); + verify(topicSink).send(anyString()); + } + + @Test + void testParticipantUpdatePublisherDecomisioning() { + var publisher = new ParticipantUpdatePublisher(mock(ServiceTemplateProvider.class)); + var topicSink = mock(TopicSink.class); + publisher.active(List.of(topicSink)); + publisher.sendDecomisioning(); + verify(topicSink).send(anyString()); + } + + @Test + void testParticipantUpdatePublisherComissioning() { + var publisher = new ParticipantUpdatePublisher(mock(ServiceTemplateProvider.class)); + var topicSink = mock(TopicSink.class); + publisher.active(List.of(topicSink)); + publisher.sendComissioningBroadcast("NAME", "1.0.0"); + verify(topicSink, times(0)).send(anyString()); + } + + @Test + void testParticipantStatusReqPublisher() { + var publisher = new ParticipantStatusReqPublisher(); + var topicSink = mock(TopicSink.class); + publisher.active(List.of(topicSink)); + publisher.send(getParticipantId()); + verify(topicSink).send(anyString()); + } + + @Test + void testParticipantRegisterAckPublisher() { + var publisher = new ParticipantRegisterAckPublisher(); + var topicSink = mock(TopicSink.class); + publisher.active(List.of(topicSink)); + publisher.send(UUID.randomUUID(), getParticipantId(), getParticipantType()); + verify(topicSink).send(anyString()); + } + + @Test + void testParticipantDeregisterAckPublisher() { + var publisher = new ParticipantDeregisterAckPublisher(); + var topicSink = mock(TopicSink.class); + publisher.active(List.of(topicSink)); + publisher.send(UUID.randomUUID()); + verify(topicSink).send(anyString()); + } + + private AutomationComposition getAutomationComposition() { + var automationComposition = new AutomationComposition(); + automationComposition.setName("NAME"); + automationComposition.setVersion("0.0.1"); + automationComposition.setState(AutomationCompositionState.UNINITIALISED); + return automationComposition; + } + + private ToscaConceptIdentifier getParticipantId() { + return new ToscaConceptIdentifier("org.onap.PM_Policy", "1.0.0"); + } + + private ToscaConceptIdentifier getParticipantType() { + return new ToscaConceptIdentifier("org.onap.policy.acm.PolicyAutomationCompositionParticipant", "2.3.1"); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java new file mode 100644 index 000000000..33a00c21b --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java @@ -0,0 +1,125 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.util; + +import java.util.List; +import javax.ws.rs.core.Response.Status; +import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup; +import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; +import org.onap.policy.clamp.models.acm.concepts.Participant; +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.common.utils.resources.ResourceUtils; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.base.PfModelRuntimeException; +import org.onap.policy.models.provider.PolicyModelsProvider; +import org.onap.policy.models.provider.PolicyModelsProviderFactory; +import org.onap.policy.models.provider.PolicyModelsProviderParameters; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +/** + * Class to hold/create all parameters for test cases. + * + */ +public class CommonTestData { + private static final Coder CODER = new StandardCoder(); + + /** + * Gets the standard automation composition parameters. + * + * @param dbName the database name + * @return the standard automation composition parameters + * @throws AutomationCompositionRuntimeException on errors reading the automation composition parameters + */ + public static AcRuntimeParameterGroup geParameterGroup(final String dbName) { + try { + return CODER.convert(getParameterGroupAsString(dbName), AcRuntimeParameterGroup.class); + + } catch (CoderException e) { + throw new AutomationCompositionRuntimeException(Status.NOT_ACCEPTABLE, + "cannot read automation composition parameters", e); + } + } + + /** + * Gets the standard automation composition parameters, as a String. + * + * @param dbName the database name + * @return the standard automation composition parameters as string + */ + public static String getParameterGroupAsString(final String dbName) { + return ResourceUtils.getResourceAsString("src/test/resources/parameters/TestParameters.json") + .replace("${dbName}", "jdbc:h2:mem:" + dbName); + } + + /** + * Create a new PolicyModelsProvider. + * + * @param databaseProviderParameters the database Provider Parameters + * @return a new PolicyModelsProvider + */ + public static PolicyModelsProvider getPolicyModelsProvider( + PolicyModelsProviderParameters databaseProviderParameters) { + try { + return new PolicyModelsProviderFactory().createPolicyModelsProvider(databaseProviderParameters); + } catch (PfModelException e) { + throw new PfModelRuntimeException(e); + } + } + + /** + * Create a List of Participants. + * + * @return a List of Participants + */ + public static List<Participant> createParticipants() { + var participant1 = createParticipant( + new ToscaConceptIdentifier("org.onap.dcae.acm.DCAEMicroserviceAutomationCompositionParticipant", + "2.3.4"), + new ToscaConceptIdentifier("org.onap.dcae.acm.DCAEMicroserviceAutomationCompositionParticipant", + "2.3.4")); + var participant2 = createParticipant( + new ToscaConceptIdentifier("org.onap.policy.acm.PolicyAutomationCompositionParticipant", "2.3.1"), + new ToscaConceptIdentifier("org.onap.policy.acm.PolicyAutomationCompositionParticipant", "2.3.1")); + var participant3 = createParticipant( + new ToscaConceptIdentifier("org.onap.ccsdk.cds.acm.CdsAutomationCompositionParticipant", "2.2.1"), + new ToscaConceptIdentifier("org.onap.ccsdk.cds.acm.CdsAutomationCompositionParticipant", "2.2.1")); + return List.of(participant1, participant2, participant3); + } + + /** + * Create a new Participant. + * + * @param participantType the participant Type + * @param participantId the participant id + * @return a new Participant + */ + public static Participant createParticipant(ToscaConceptIdentifier participantType, + ToscaConceptIdentifier participantId) { + var participant = new Participant(); + participant.setDefinition(participantId); + participant.setParticipantType(participantType); + participant.setName(participantId.getName()); + participant.setVersion(participantId.getVersion()); + return participant; + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/rest/CommonRestController.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/rest/CommonRestController.java new file mode 100644 index 000000000..0fc0a6e9f --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/rest/CommonRestController.java @@ -0,0 +1,201 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.util.rest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.onap.policy.common.gson.GsonMessageBodyHandler; +import org.onap.policy.common.utils.network.NetworkUtil; + +/** + * Class to perform Rest unit tests. + * + */ +public class CommonRestController { + + public static final String SELF = NetworkUtil.getHostname(); + public static final String CONTEXT_PATH = "onap/automationcomposition"; + public static final String ENDPOINT_PREFIX = CONTEXT_PATH + "/v2/"; + public static final String ACTUATOR_ENDPOINT = CONTEXT_PATH + "/actuator/"; + + private static String httpPrefix; + + /** + * Verifies that an endpoint appears within the swagger response. + * + * @param endpoint the endpoint of interest + * @throws Exception if an error occurs + */ + protected void testSwagger(final String endpoint) throws Exception { + final Invocation.Builder invocationBuilder = sendRequest("api-docs"); + final String resp = invocationBuilder.get(String.class); + + assertThat(resp).contains(endpoint); + } + + /** + * Sends a request to an endpoint. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ENDPOINT_PREFIX + endpoint, true); + } + + /** + * Sends a request to an actuator endpoint. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendActRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, true); + } + + /** + * Sends a request to an Rest Api endpoint, without any authorization header. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendNoAuthRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ENDPOINT_PREFIX + endpoint, false); + } + + /** + * Sends a request to an actuator endpoint, without any authorization header. + * + * @param endpoint the target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendNoAuthActRequest(final String endpoint) throws Exception { + return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, false); + } + + /** + * Sends a request to a fully qualified endpoint. + * + * @param fullyQualifiedEndpoint the fully qualified target endpoint + * @param includeAuth if authorization header should be included + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendFqeRequest(final String fullyQualifiedEndpoint, boolean includeAuth) + throws Exception { + final Client client = ClientBuilder.newBuilder().build(); + + client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true"); + client.register(GsonMessageBodyHandler.class); + + if (includeAuth) { + client.register(HttpAuthenticationFeature.basic("runtimeUser", "zb!XztG34")); + } + + final WebTarget webTarget = client.target(fullyQualifiedEndpoint); + + return webTarget.request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN); + } + + /** + * Assert that POST call is Unauthorized. + * + * @param endPoint the endpoint + * @param entity the entity ofthe body + * @throws Exception if an error occurs + */ + protected void assertUnauthorizedPost(final String endPoint, final Entity<?> entity) throws Exception { + Response rawresp = sendNoAuthRequest(endPoint).post(entity); + assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + } + + /** + * Assert that PUT call is Unauthorized. + * + * @param endPoint the endpoint + * @param entity the entity ofthe body + * @throws Exception if an error occurs + */ + protected void assertUnauthorizedPut(final String endPoint, final Entity<?> entity) throws Exception { + Response rawresp = sendNoAuthRequest(endPoint).put(entity); + assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + } + + /** + * Assert that GET call is Unauthorized. + * + * @param endPoint the endpoint + * @throws Exception if an error occurs + */ + protected void assertUnauthorizedGet(final String endPoint) throws Exception { + Response rawresp = sendNoAuthRequest(endPoint).buildGet().invoke(); + assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + } + + /** + * Assert that GET call to actuator endpoint is Unauthorized. + * + * @param endPoint the endpoint + * @throws Exception if an error occurs + */ + protected void assertUnauthorizedActGet(final String endPoint) throws Exception { + Response rawresp = sendNoAuthActRequest(endPoint).buildGet().invoke(); + assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + } + + /** + * Assert that DELETE call is Unauthorized. + * + * @param endPoint the endpoint + * @throws Exception if an error occurs + */ + protected void assertUnauthorizedDelete(final String endPoint) throws Exception { + Response rawresp = sendNoAuthRequest(endPoint).delete(); + assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + } + + /** + * Set Up httpPrefix. + * + * @param port the port + */ + protected void setHttpPrefix(int port) { + httpPrefix = "http://" + SELF + ":" + port + "/"; + } + + protected String getHttpPrefix() { + return httpPrefix; + } +} |