diff options
author | Sonsino, Ofir (os0695) <os0695@intl.att.com> | 2018-07-10 14:20:54 +0300 |
---|---|---|
committer | Sonsino, Ofir (os0695) <os0695@intl.att.com> | 2018-07-10 14:20:54 +0300 |
commit | c72d565bb58226b20625b2bce5f0019046bee649 (patch) | |
tree | 8658e49595705b02e47ddc14afa20d6bb7123547 /vid-app-common/src/test/java/org/onap/vid/services | |
parent | ef8a6b47847012fd59ea20da21d8d3d7c4a301ed (diff) |
Merge 1806 code of vid-common
Change-Id: I75d52abed4a24dfe3827d79edc4a2938726aa87a
Issue-ID: VID-208
Signed-off-by: Sonsino, Ofir (os0695) <os0695@intl.att.com>
Diffstat (limited to 'vid-app-common/src/test/java/org/onap/vid/services')
8 files changed, 2315 insertions, 161 deletions
diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AaiResponseTranslatorTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AaiResponseTranslatorTest.java new file mode 100644 index 00000000..04890e33 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/services/AaiResponseTranslatorTest.java @@ -0,0 +1,132 @@ +package org.onap.vid.services; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.ObjectMapper; +import org.onap.vid.aai.AaiResponseTranslator; +import org.onap.vid.aai.AaiResponseTranslator.PortMirroringConfigData; +import org.onap.vid.aai.AaiResponseTranslator.PortMirroringConfigDataError; +import org.onap.vid.aai.AaiResponseTranslator.PortMirroringConfigDataOk; +import org.testng.annotations.Test; + +import java.io.IOException; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; + +@Test +public class AaiResponseTranslatorTest { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void extractPortMirroringConfigData_givenValidAaiResponse_yieldCloudRegionId() throws IOException { + + final JsonNode aaiPayload = objectMapper.readTree("" + + "{" + + " \"results\": [{" + + " \"id\": \"2979590232\"," + + " \"node-type\": \"cloud-region\"," + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/SDNO-S-BcloudReg-E1802\"," + + " \"properties\": {" + + " \"cloud-owner\": \"att-aic\"," + + " \"cloud-region-id\": \"THE-EXPECTED-REGION-ID\"," + + " \"sriov-automation\": false," + + " \"resource-version\": \"1513631040564\"" + + " }" + + " }," + + " {" + + " \"id\": \"2979598424\"," + + " \"node-type\": \"generic-vnf\"," + + " \"url\": \"/aai/v12/network/generic-vnfs/generic-vnf/SOURCE-gVnf-E1802\"," + + " \"properties\": {" + + " \"vnf-id\": \"SOURCE-gVnf-E1802\"," + + " \"vnf-name\": \"SOURCE-vnf-SDNO\"," + + " \"vnf-type\": \"S-1-SDNO\"," + + " \"service-id\": \"a9a77d5a-123e-4-SDNO\"," + + " \"orchestration-status\": \"active\"," + + " \"in-maint\": true," + + " \"is-closed-loop-disabled\": false," + + " \"resource-version\": \"1513631043149\"" + + " }" + + " }" + + " ]" + + "}"); + + PortMirroringConfigData portMirroringConfigData = + new AaiResponseTranslator().extractPortMirroringConfigData(aaiPayload); + + assertThat(portMirroringConfigData, is(instanceOf(PortMirroringConfigDataOk.class))); + assertThat(((PortMirroringConfigDataOk) portMirroringConfigData).getCloudRegionId(), is("THE-EXPECTED-REGION-ID")); + + } + + @Test + public void extractPortMirroringConfigData_givenKindOfValidAaiResponse_yieldCloudRegionId() throws IOException { + // some completley different response, but with + // the results[cloud-region]->properties->cloud-region-id + + final JsonNode aaiPayload = objectMapper.readTree("" + + "{ " + + " \"results\": [{ " + + " \"node-type\": \"generic-vnf\", " + + " \"url\": \"configuration entries) so that git\" " + + " }, " + + " {}, " + + " { " + + " \"node-type\": \"cloud-region\", " + + " \"but it will not switch\": \"tip commits are reachable\", " + + " \"named\": [{ " + + " \"resource-version\": \"1513631040564\" " + + " }], " + + " \"properties\": { " + + " \"cloud-region-id\": \"THE-EXPECTED-REGION-ID\", " + + " \"oldbranch> will be renamed\": false " + + " } " + + " }, " + + " { " + + " \"node-type\": [\"generic-vnf\", \"can be overridden by using\"] " + + " } " + + " ] " + + "}"); + + PortMirroringConfigData portMirroringConfigData = + new AaiResponseTranslator().extractPortMirroringConfigData(aaiPayload); + + assertThat(portMirroringConfigData, is(instanceOf(PortMirroringConfigDataOk.class))); + assertThat(((PortMirroringConfigDataOk) portMirroringConfigData).getCloudRegionId(), is("THE-EXPECTED-REGION-ID")); + + } + + public void extractPortMirroringConfigData_givenAaiResponseWithoutRegionIdName_yieldException() throws IOException { + + final JsonNode aaiPayload = objectMapper.readTree("" + + "{" + + " \"results\": [{" + + " \"node-type\": \"cloud-region\"," + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/SDNO-S-BcloudReg-E1802\"," + + " \"properties\": {" + + " \"resource-version\": \"1513631040564\"" + + " }" + + " }" + + " ]" + + "}"); + + PortMirroringConfigData portMirroringConfigData = + new AaiResponseTranslator().extractPortMirroringConfigData(aaiPayload); + + assertThat(portMirroringConfigData, is(instanceOf(PortMirroringConfigDataError.class))); + assertThat(((PortMirroringConfigDataError) portMirroringConfigData).getErrorDescription(), + containsString("The node-type 'cloud-region' does not contain the property 'cloud-region-id'")); + assertThat(((PortMirroringConfigDataError) portMirroringConfigData).getRawAaiResponse(), + containsString(aaiPayload.toString()) + ); + + } + + /* + More tests: + [x] cloud-region-id field is missing -- descriptive exception is thrown, including the problematic payload itself + [ ] cloud-region-id field is empty -- descriptive exception etc. + [ ] node-type=="cloud-region" entry is empty -- descriptive exception etc. + */ +} diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java new file mode 100644 index 00000000..c3d01283 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBaseTest.java @@ -0,0 +1,193 @@ +package org.onap.vid.services; + +import com.google.common.collect.ImmutableMap; +import jersey.repackaged.com.google.common.collect.ImmutableList; +import org.onap.vid.aai.AaiClientInterface; +import org.onap.vid.aai.AaiResponse; +import org.onap.vid.aai.model.AaiNodeQueryResponse; +import org.onap.vid.aai.model.ResourceType; +import org.onap.vid.domain.mso.ModelInfo; +import org.onap.vid.domain.mso.RequestStatus; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.model.serviceInstantiation.VfModule; +import org.onap.vid.model.serviceInstantiation.Vnf; +import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.onap.vid.services.AsyncInstantiationBusinessLogicTest; +import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; +import org.togglz.core.manager.FeatureManager; + +import javax.inject.Inject; +import java.util.*; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.when; + +public class AsyncInstantiationBaseTest extends AbstractTestNGSpringContextTests { + + public static final String OWNING_ENTITY_ID = "038d99af-0427-42c2-9d15-971b99b9b489"; + public static final String PACKET_CORE = "PACKET CORE"; + public static final String PROJECT_NAME = "{some project name}"; + public static final String SUBSCRIBER_ID = "{some subscriber id}"; + public static final String SUBSCRIBER_NAME = "{some subscriber name}"; + public static final String PRODUCT_FAMILY_ID = "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb"; + public static final String INSTANCE_NAME = "vPE_Service"; + public static final String SUBSCRIPTION_SERVICE_TYPE = "VMX"; + public static final String LCP_CLOUD_REGION_ID = "mdt1"; + public static final String A6CA3EE0394ADE9403F075DB23167E = "88a6ca3ee0394ade9403f075db23167e"; + public static final String TENANT_NAME = "USP-SIP-IC-24335-T-01"; + public static final String AIC_ZONE_ID = "NFT1"; + public static final String AIC_ZONE_NAME = "NFTJSSSS-NFT1"; + + protected HashMap<String, String> instanceParamsMapWithoutParams; + protected HashMap<String, String> vfModuleInstanceParamsMapWithParamsToRemove; + protected HashMap<String, String> vnfInstanceParamsMapWithParamsToRemove; + + @Inject + protected FeatureManager featureManager; + + @Inject + protected AaiClientInterface aaiClient; + + public ServiceInstantiation generateMockServiceInstantiationPayload(boolean isPause, Map<String, Vnf> vnfs, int bulkSize, boolean isUserProvidedNaming, String projectName, boolean rollbackOnFailure) { + ModelInfo modelInfo = createModelInfo(); + + List<Map<String,String>> instanceParams = createInstanceParams(); + + return new ServiceInstantiation ( + modelInfo, + AsyncInstantiationBusinessLogicTest.OWNING_ENTITY_ID, + AsyncInstantiationBusinessLogicTest.PACKET_CORE, + projectName, + AsyncInstantiationBusinessLogicTest.SUBSCRIBER_ID, + AsyncInstantiationBusinessLogicTest.SUBSCRIBER_NAME, + AsyncInstantiationBusinessLogicTest.PRODUCT_FAMILY_ID, + isUserProvidedNaming ? AsyncInstantiationBusinessLogicTest.INSTANCE_NAME : "" , + isUserProvidedNaming, + AsyncInstantiationBusinessLogicTest.SUBSCRIPTION_SERVICE_TYPE, + AsyncInstantiationBusinessLogicTest.LCP_CLOUD_REGION_ID, + AsyncInstantiationBusinessLogicTest.A6CA3EE0394ADE9403F075DB23167E, + AsyncInstantiationBusinessLogicTest.TENANT_NAME, + AsyncInstantiationBusinessLogicTest.AIC_ZONE_ID, + AsyncInstantiationBusinessLogicTest.AIC_ZONE_NAME, + vnfs, + instanceParams, + isPause, + bulkSize, + rollbackOnFailure + ); + } + + private List<Map<String,String>> createInstanceParams() { + List<Map<String, String>> instanceParams = new ArrayList<>(); + HashMap<String, String> map = new HashMap<>(); + map.put("instanceParams_test1" , "some text"); + map.put("instanceParams_test2" , "another text"); + instanceParams.add(map); + return instanceParams; + } + + private VfModule createVfModule(String modelName, String modelVersionId, String modelCustomizationId, + List<Map<String, String>> instanceParams, String instanceName, String volumeGroupInstanceName) { + ModelInfo vfModuleInfo = new ModelInfo(); + vfModuleInfo.setModelType("vfModule"); + vfModuleInfo.setModelName(modelName); + vfModuleInfo.setModelVersionId(modelVersionId); + vfModuleInfo.setModelCustomizationId(modelCustomizationId); + return new VfModule(vfModuleInfo , instanceName, volumeGroupInstanceName, instanceParams); + } + + private ModelInfo createVnfModelInfo() { + ModelInfo vnfModelInfo = new ModelInfo(); + vnfModelInfo.setModelType("vnf"); + vnfModelInfo.setModelName("2016-73_MOW-AVPN-vPE-BV-L"); + vnfModelInfo.setModelVersionId("7f40c192-f63c-463e-ba94-286933b895f8"); + vnfModelInfo.setModelCustomizationName("2016-73_MOW-AVPN-vPE-BV-L 0"); + vnfModelInfo.setModelCustomizationId("ab153b6e-c364-44c0-bef6-1f2982117f04"); + return vnfModelInfo; + } + + private ModelInfo createModelInfo() { + ModelInfo modelInfo = new ModelInfo(); + modelInfo.setModelType("service"); + modelInfo.setModelVersionId("3c40d244-808e-42ca-b09a-256d83d19d0a"); + modelInfo.setModelVersion("10.0"); + modelInfo.setModelInvariantId("5d48acb5-097d-4982-aeb2-f4a3bd87d31b"); + modelInfo.setModelName("MOW AVPN vMX BV vPE 1 Service"); + return modelInfo; + } + + protected Map<String, Vnf> createVnfList(HashMap<String, String> vfModuleInstanceParamsMap, List vnfInstanceParams, boolean isUserProvidedNaming) { + Map<String, Vnf> vnfs = new HashMap<>(); + ModelInfo vnfModelInfo = createVnfModelInfo(); + + Map<String, Map<String, VfModule>> vfModules = new HashMap<>(); + + List<Map<String, String>> instanceParams1 =ImmutableList.of((ImmutableMap.of("vmx_int_net_len", "24"))); + VfModule vfModule1 = createVfModule("201673MowAvpnVpeBvL..AVPN_base_vPE_BV..module-0", "4c75f813-fa91-45a4-89d0-790ff5f1ae79", "a25e8e8c-58b8-4eec-810c-97dcc1f5cb7f", instanceParams1, "vmxnjr001_AVPN_base_vPE_BV_base", null); + List<Map<String, String>> instanceParams2 = ImmutableList.of(vfModuleInstanceParamsMap); + VfModule vfModule2 = createVfModule("201673MowAvpnVpeBvL..AVPN_vRE_BV..module-1", "56e2b103-637c-4d1a-adc8-3a7f4a6c3240", "72d9d1cd-f46d-447a-abdb-451d6fb05fa8", instanceParams2, "vmxnjr001_AVPN_base_vRE_BV_expansion", "myVgName"); + + String vfModuleModelName = vfModule1.getModelInfo().getModelName(); + vfModules.put(vfModuleModelName, new LinkedHashMap<>()); + + vfModules.get(vfModuleModelName).put(vfModule1.getInstanceName(),vfModule1); + vfModules.get(vfModuleModelName).put(vfModule2.getInstanceName(), vfModule2); + + Vnf vnf = new Vnf(vnfModelInfo, "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", "vmxnjr001", isUserProvidedNaming, + "platformName", "mdt1", "88a6ca3ee0394ade9403f075db23167e", vnfInstanceParams,"lineOfBusinessName" ,vfModules); + + vnfs.put(vnf.getInstanceName(), vnf); + return vnfs; + } + + protected void createInstanceParamsMaps() { + instanceParamsMapWithoutParams = new HashMap<>(); + instanceParamsMapWithoutParams.put("availability_zone_0" , "mtpocdv-kvm-az01"); + instanceParamsMapWithoutParams.put("vre_a_volume_size_0" , "100"); + + vfModuleInstanceParamsMapWithParamsToRemove = new HashMap<>(); + vfModuleInstanceParamsMapWithParamsToRemove.put(AsyncInstantiationBusinessLogic.PARAMS_TO_IGNORE.get(0), "should be removed"); + vfModuleInstanceParamsMapWithParamsToRemove.put("availability_zone_0" , "mtpocdv-kvm-az01"); + vfModuleInstanceParamsMapWithParamsToRemove.put("vre_a_volume_size_0" , "100"); + + vnfInstanceParamsMapWithParamsToRemove = new HashMap<>(); + vnfInstanceParamsMapWithParamsToRemove.put(AsyncInstantiationBusinessLogic.PARAMS_TO_IGNORE.get(1), "should be removed"); + } + + protected AsyncRequestStatus asyncRequestStatusResponse(String msoStatus) { + AsyncRequestStatus asyncRequestStatus = new AsyncRequestStatus(new AsyncRequestStatus.Request(new RequestStatus())); + asyncRequestStatus.request.requestStatus.setRequestState(msoStatus); + asyncRequestStatus.request.requestId = UUID.randomUUID().toString(); + return asyncRequestStatus; + } + + protected RestObject<AsyncRequestStatus> asyncRequestStatusResponseAsRestObject(String msoStatus) { + return asyncRequestStatusResponseAsRestObject(msoStatus, 200); + } + + protected RestObject<AsyncRequestStatus> asyncRequestStatusResponseAsRestObject(String msoStatus, int httpStatusCode) { + RestObject<AsyncRequestStatus> restObject = new RestObject<>(); + restObject.set(asyncRequestStatusResponse(msoStatus)); + restObject.setStatusCode(httpStatusCode); + return restObject; + } + + protected void mockAaiClientAnyNameFree() { + when(aaiClient.searchNodeTypeByName(any(), any())).thenReturn(aaiNodeQueryResponseNameFree()); + } + + protected AaiResponse<AaiNodeQueryResponse> aaiNodeQueryResponseNameFree() { + return new AaiResponse<>(new AaiNodeQueryResponse(null),"", 200); + } + + protected AaiResponse<AaiNodeQueryResponse> aaiNodeQueryBadResponse() { + return new AaiResponse<>(null,"", 404); + } + + protected AaiResponse<AaiNodeQueryResponse> aaiNodeQueryResponseNameUsed(ResourceType type) { + AaiNodeQueryResponse mockAaiNodeQuery = new AaiNodeQueryResponse(ImmutableList.of(new AaiNodeQueryResponse.ResultData(type, "/some/mocked/link"))); + return new AaiResponse<>(mockAaiNodeQuery,"", 200); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java new file mode 100644 index 00000000..7feb3704 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/services/AsyncInstantiationBusinessLogicTest.java @@ -0,0 +1,882 @@ +package org.onap.vid.services; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import jersey.repackaged.com.google.common.collect.ImmutableList; +import net.javacrumbs.jsonunit.JsonAssert; +import org.apache.commons.io.IOUtils; +import org.hibernate.SessionFactory; +import org.json.JSONException; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.onap.vid.aai.exceptions.InvalidAAIResponseException; +import org.onap.vid.aai.model.ResourceType; +import org.onap.vid.changeManagement.RequestDetailsWrapper; +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.exceptions.MaxRetriesException; +import org.onap.vid.exceptions.OperationNotAllowedException; +import org.onap.vid.job.Job; +import org.onap.vid.job.Job.JobStatus; +import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobsBrokerService; +import org.onap.vid.job.impl.JobDaoImpl; +import org.onap.vid.model.JobAuditStatus; +import org.onap.vid.model.JobAuditStatus.SourceStatus; +import org.onap.vid.model.NameCounter; +import org.onap.vid.model.ServiceInfo; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.model.serviceInstantiation.Vnf; +import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; +import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.utils.DaoUtils; +import org.onap.vid.config.DataSourceConfig; +import org.onap.vid.config.MockedAaiClientAndFeatureManagerConfig; +import org.onap.vid.mso.MsoOperationalEnvironmentTest; +import org.onap.vid.services.AsyncInstantiationBaseTest; +import org.onap.portalsdk.core.FusionObject; +import org.onap.portalsdk.core.service.DataAccessService; +import org.onap.portalsdk.core.util.SystemProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.testng.Assert; +import org.testng.annotations.*; + +import javax.inject.Inject; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.*; +import java.util.Optional; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.*; +import static org.hamcrest.core.Every.everyItem; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.onap.vid.job.Job.JobStatus.*; +import static org.testng.Assert.*; + +@ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, MockedAaiClientAndFeatureManagerConfig.class}) +public class AsyncInstantiationBusinessLogicTest extends AsyncInstantiationBaseTest { +/* +TO BE FIXED + @Inject + private DataAccessService dataAccessService; + + @Mock + private JobAdapter jobAdapter; + + @Mock + private JobsBrokerService jobsBrokerService; + + + + @Autowired + private SessionFactory sessionFactory; + + private AsyncInstantiationBusinessLogic asyncInstantiationBL; + + private int serviceCount = 0; + + private static final String UPDATE_SERVICE_INFO_EXCEPTION_MESSAGE = + "Failed to retrieve job with uuid .* from ServiceInfo table. Instances found: .*"; + + private static final String DELETE_SERVICE_INFO_STATUS_EXCEPTION_MESSAGE = + "Service status does not allow deletion from the queue"; + + @BeforeClass + void initServicesInfoService() { + MockitoAnnotations.initMocks(this); + asyncInstantiationBL = new AsyncInstantiationBusinessLogicImpl(dataAccessService, jobAdapter, jobsBrokerService, sessionFactory, aaiClient); + createInstanceParamsMaps(); + } + + @BeforeMethod + void defineMocks() { + mockAaiClientAnyNameFree(); + } + + @BeforeMethod + void resetServiceCount() { + serviceCount = 0; + } + + @AfterMethod + void clearDb() { + dataAccessService.deleteDomainObjects(JobDaoImpl.class, "1=1", getPropsMap()); + dataAccessService.deleteDomainObjects(ServiceInfo.class, "1=1", getPropsMap()); + dataAccessService.deleteDomainObjects(JobAuditStatus.class, "1=1", getPropsMap()); + dataAccessService.deleteDomainObjects(NameCounter.class, "1=1", getPropsMap()); + } + + + private void createNewTestServicesInfoForFilter(String userId) { + LocalDateTime createdDate, modifiedDate; + LocalDateTime NOW = LocalDateTime.now(); + UUID uuid; + + // Old job + uuid = UUID.randomUUID(); + addNewJob(uuid); + createdDate = NOW.minusYears(1); + addNewServiceInfo(uuid, userId, "Old", createdDate, createdDate, COMPLETED, false); + + uuid = UUID.randomUUID(); + addNewJob(uuid); + createdDate = NOW.minusDays(20); + modifiedDate = NOW.minusDays(19); + addNewServiceInfo(uuid, userId, "Hidden", createdDate, modifiedDate, PAUSE, true); + + createNewTestServicesInfo(String.valueOf(userId)); + } + + private void createNewTestServicesInfo(String userId) { + + LocalDateTime createdDate, modifiedDate; + LocalDateTime NOW = LocalDateTime.now(); + UUID uuid; + + uuid = UUID.randomUUID(); + addNewJob(uuid); + + createdDate = NOW.minusDays(40); + addNewServiceInfo(uuid, userId, "service instance 5", createdDate, createdDate, COMPLETED, false); + addNewServiceInfo(uuid, userId, "service instance 6", createdDate, createdDate, STOPPED, false); + + uuid = UUID.randomUUID(); + addNewJob(uuid); + + createdDate = NOW.minusDays(20); + modifiedDate = NOW.minusDays(10); + addNewServiceInfo(uuid, userId, "service instance 4", createdDate, modifiedDate, STOPPED, false); + addNewServiceInfo(uuid, userId, "service instance 2", createdDate, modifiedDate, COMPLETED, false); + addNewServiceInfo(uuid, userId, "service instance 3", createdDate, modifiedDate, PAUSE, false); + + modifiedDate = NOW.minusDays(19); + addNewServiceInfo(uuid, userId, "service instance 1", createdDate, modifiedDate, FAILED, false); + + + // Job to a different user + uuid = UUID.randomUUID(); + addNewJob(uuid); + + createdDate = NOW.minusMonths(2); + addNewServiceInfo(uuid, "2221", "service instance 7", createdDate, createdDate, COMPLETED, false); + + } + + private UUID createServicesInfoWithDefaultValues(Job.JobStatus status) { + + LocalDateTime NOW = LocalDateTime.now(); + UUID uuid; + + uuid = UUID.randomUUID(); + addNewJob(uuid, status); + + addNewServiceInfo(uuid, null, "service instance 1", NOW, NOW, status, false); + + return uuid; + + } + + private List<ServiceInfo> getFullList() { + List<ServiceInfo> expectedOrderServiceInfo = dataAccessService.getList(ServiceInfo.class, getPropsMap()); + assertThat("Failed to retrieve all predefined services", expectedOrderServiceInfo.size(), equalTo(serviceCount)); + expectedOrderServiceInfo.sort(new ServiceInfoComparator()); + return expectedOrderServiceInfo; + } + + private static Date toDate(LocalDateTime localDateTime) { + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + } + + private LocalDateTime fromDate(Date date) { + return Instant.ofEpochMilli(date.getTime()) + .atZone(ZoneId.systemDefault()) + .toLocalDateTime(); + } + + private void addNewServiceInfo(UUID uuid, String userId, String serviceName, LocalDateTime createDate, LocalDateTime statusModifiedDate, Job.JobStatus status, boolean isHidden) { + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.setJobId(uuid); + serviceInfo.setUserId(userId); + serviceInfo.setServiceInstanceName(serviceName); + serviceInfo.setStatusModifiedDate(toDate(statusModifiedDate)); + serviceInfo.setJobStatus(status); + serviceInfo.setPause(false); + serviceInfo.setOwningEntityId("1234"); + serviceInfo.setCreatedBulkDate(toDate(createDate)); + + serviceInfo.setHidden(isHidden); + dataAccessService.saveDomainObject(serviceInfo, getPropsMap()); + setCreateDateToServiceInfo(uuid, createDate); + serviceCount++; + + } + + private void setCreateDateToServiceInfo(UUID jobUuid, LocalDateTime createDate) { + List<ServiceInfo> serviceInfoList = dataAccessService.getList(ServiceInfo.class, getPropsMap()); + DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> { + serviceInfoList.stream() + .filter(serviceInfo -> jobUuid.equals(serviceInfo.getJobId())) + .forEach(serviceInfo -> { + serviceInfo.setCreated(toDate(createDate)); + session.saveOrUpdate(serviceInfo); + }); + return 1; + }); + } + + private void addNewJob(UUID uuid) { + addNewJob(uuid, null); + } + + private void addNewJob(UUID uuid, Job.JobStatus status) { + JobDaoImpl jobDao = new JobDaoImpl(); + jobDao.setUuid(uuid); + jobDao.setStatus(status); + dataAccessService.saveDomainObject(jobDao, getPropsMap()); + } + + @Test + public void testServiceInfoAreOrderedAsExpected() { + int userId = 2222; + createNewTestServicesInfo(String.valueOf(userId)); + List<ServiceInfo> expectedOrderServiceInfo = getFullList(); + List<ServiceInfo> serviceInfoListResult = asyncInstantiationBL.getAllServicesInfo(); + assertThat("Services aren't ordered as expected", serviceInfoListResult, equalTo(expectedOrderServiceInfo)); + } + + @Test + public void testServiceInfoAreFilteredAsExpected() { + int userId = 2222; + createNewTestServicesInfoForFilter(String.valueOf(userId)); + List<ServiceInfo> expectedOrderServiceInfo = getFullList(); + + List<ServiceInfo> expectedFilterByUser = expectedOrderServiceInfo.stream().filter(x -> + !x.getServiceInstanceName().equals("Old") && !x.getServiceInstanceName().equals("Hidden") + + ).collect(Collectors.toList()); + + + List<ServiceInfo> serviceInfoFilteredByUser = asyncInstantiationBL.getAllServicesInfo(); + assertThat("Services aren't ordered filtered as expected", serviceInfoFilteredByUser, equalTo(expectedFilterByUser)); + } + + @Test(dataProvider = "pauseAndInstanceParams", enabled = false) //Test is irrelevant with unique names feature + public void createServiceInstantiationMsoRequest(Boolean isPause, HashMap<String, String> vfModuleInstanceParamsMap, List vnfInstanceParams) throws Exception { + ServiceInstantiation serviceInstantiationPayload = generateMockServiceInstantiationPayload(isPause, createVnfList(vfModuleInstanceParamsMap, vnfInstanceParams, true)); + final URL resource = this.getClass().getResource("/payload_jsons/bulk_service_request.json"); + RequestDetailsWrapper<ServiceInstantiationRequestDetails> result = + asyncInstantiationBL.generateServiceInstantiationRequest(null, serviceInstantiationPayload, "az2016"); + String expected = IOUtils.toString(resource, "UTF-8"); + MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); + } + + @Test(dataProvider = "pauseAndInstanceParams") + public void createServiceInstantiationMsoRequestUniqueName(Boolean isPause, HashMap<String, String> vfModuleInstanceParamsMap, List vnfInstanceParams) throws Exception { + Mockito.reset(aaiClient); + mockAaiClientAnyNameFree(); + ServiceInstantiation serviceInstantiationPayload = generateMockServiceInstantiationPayload(isPause, createVnfList(vfModuleInstanceParamsMap, vnfInstanceParams, true)); + final URL resource = this.getClass().getResource("/payload_jsons/bulk_service_request_unique_names.json"); + List<UUID> uuids = new ArrayList<>(); + for (int i = 0; i < 2; i++) { + UUID currentUuid = createJobAndServiceInfo(); + uuids.add(currentUuid); + RequestDetailsWrapper<ServiceInstantiationRequestDetails> result = + asyncInstantiationBL.generateServiceInstantiationRequest(currentUuid, serviceInstantiationPayload, "az2016"); + String unique = String.format("00%s", i + 1); + String expected = IOUtils.toString(resource, "UTF-8") + .replace("{SERVICE_UNIQENESS}", unique) + .replace("{VNF_UNIQENESS}", unique) + .replace("{VF_MODULE_UNIQENESS}", unique) + .replace("{VF_MODULE_2_UNIQENESS}", unique) + .replace("{VG_UNIQUENESS}", unique); + MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); + Optional<ServiceInfo> optionalServiceInfo = getJobById(currentUuid); + assertThat(optionalServiceInfo.get().getServiceInstanceName(), equalTo("vPE_Service_" + unique)); + verifySearchNodeTypeByName(unique, "vPE_Service_", ResourceType.SERVICE_INSTANCE); + verifySearchNodeTypeByName(unique, "vmxnjr001_", ResourceType.GENERIC_VNF); + verifySearchNodeTypeByName(unique, "vmxnjr001_AVPN_base_vPE_BV_base_", ResourceType.VF_MODULE); + verifySearchNodeTypeByName(unique, "vmxnjr001_AVPN_base_vRE_BV_expansion_", ResourceType.VF_MODULE); + verifySearchNodeTypeByName(unique, "myVgName_", ResourceType.VOLUME_GROUP); + } + } + + protected void verifySearchNodeTypeByName(String unique, String resourceName, ResourceType serviceInstance) { + verify(aaiClient, times(1)).searchNodeTypeByName(resourceName + unique, serviceInstance); + } + + private HashMap<String, Object> getPropsMap() { + HashMap<String, Object> props = new HashMap<>(); + props.put(FusionObject.Parameters.PARAM_USERID, 0); + return props; + } + + @Test(enabled = false) //probably not needed with name uniqueness feature + public void pushBulkJob_bulkWithSize3_instancesNamesAreExactlyAsExpected() { + int bulkSize = 3; + + final ServiceInstantiation request = generateMockServiceInstantiationPayload( + false, + createVnfList(instanceParamsMapWithoutParams, Collections.EMPTY_LIST, true), + bulkSize, true,PROJECT_NAME, true + ); + + // in "createJob()" we will probe the service, with the generated names + final Job job = mock(Job.class); + when(job.getStatus()).thenReturn(PENDING); + when(jobAdapter.createJob(any(), any(), any(), any(), any())).thenReturn(job); + + + final List<UUID> uuids = asyncInstantiationBL.pushBulkJob(request, "myUserId"); + + + ArgumentCaptor<ServiceInstantiation> serviceInstantiationCaptor = new ArgumentCaptor<ServiceInstantiation>(); + verify(jobAdapter, times(bulkSize)).createJob(any(), serviceInstantiationCaptor.capture(), any(), any(), any()); + + assertThat(serviceInstantiationCaptor.getAllValues().stream().map(v -> v.getInstanceName()).collect(Collectors.toList()), + containsInAnyOrder("vPE_Service_001", "vPE_Service_002", "vPE_Service_003")); + + assertThat(uuids, hasSize(bulkSize)); + } + + @Test + public void generateMockServiceInstantiationPayload_serializeBackAndForth_sourceShouldBeTheSame() throws IOException { + ServiceInstantiation serviceInstantiationPayload = generateMockServiceInstantiationPayload( + false, + createVnfList(instanceParamsMapWithoutParams, ImmutableList.of(vnfInstanceParamsMapWithParamsToRemove, vnfInstanceParamsMapWithParamsToRemove), true), + 2, false,PROJECT_NAME, false); + ObjectMapper mapper = new ObjectMapper(); + final String asString = mapper.writeValueAsString(serviceInstantiationPayload); + + final ServiceInstantiation asObject = mapper.readValue(asString, ServiceInstantiation.class); + final String asString2 = mapper.writeValueAsString(asObject); + + JsonAssert.assertJsonEquals(asString, asString2); + } + + public static class ServiceInfoComparator implements Comparator<ServiceInfo> { + + @Override + public int compare(ServiceInfo o1, ServiceInfo o2) { + int compare; + + compare = o1.getCreatedBulkDate().compareTo(o2.getCreatedBulkDate()); + if (compare != 0) { + return -compare; + } + + // check jobStatus priority + int o1Priority = getPriority(o1); + int o2Priority = getPriority(o2); + compare = o1Priority - o2Priority; + if (compare != 0) { + return compare; + } + + // check statusModifiedDate + return o1.getStatusModifiedDate().compareTo(o2.getStatusModifiedDate()); + } + + private int getPriority(ServiceInfo o) throws JSONException { + Job.JobStatus status = o.getJobStatus(); + switch (status) { + case COMPLETED: + case FAILED: + return 1; + case IN_PROGRESS: + return 2; + case PAUSE: + return 3; + case STOPPED: + case PENDING: + return 4; + default: + return 5; + } + } + } + + @DataProvider + public Object[][] pauseAndInstanceParams() { + return new Object[][]{ + {Boolean.TRUE, instanceParamsMapWithoutParams, Collections.EMPTY_LIST}, + {Boolean.FALSE, instanceParamsMapWithoutParams, Collections.EMPTY_LIST}, + {Boolean.TRUE, vfModuleInstanceParamsMapWithParamsToRemove, Collections.singletonList(vnfInstanceParamsMapWithParamsToRemove)} + }; + } + + private ServiceInstantiation generateMockServiceInstantiationPayload(boolean isPause, Map<String, Vnf> vnfs) { + return generateMockServiceInstantiationPayload(isPause, vnfs, 1, true, PROJECT_NAME, false); + } + + @Test + public void testUpdateServiceInfo_WithExistingServiceInfo_ServiceInfoIsUpdated() { + UUID uuid = createJobAndServiceInfo(); + final String STEPH_CURRY = "Steph Curry"; + asyncInstantiationBL.updateServiceInfo(uuid, x -> { + x.setServiceInstanceName(STEPH_CURRY); + x.setJobStatus(Job.JobStatus.IN_PROGRESS); + }); + Optional<ServiceInfo> optionalServiceInfo = getJobById(uuid); + assertThat(optionalServiceInfo.get().getServiceInstanceName(), equalTo(STEPH_CURRY)); + assertThat(optionalServiceInfo.get().getJobStatus(), equalTo(Job.JobStatus.IN_PROGRESS)); + } + + private Optional<ServiceInfo> getJobById(UUID jobId) { + List<ServiceInfo> serviceInfoList = dataAccessService.getList(ServiceInfo.class, null); + return serviceInfoList.stream().filter(x -> jobId.equals(x.getJobId())).findFirst(); + } + + private UUID createJobAndServiceInfo() { + UUID uuid = UUID.randomUUID(); + addNewJob(uuid); + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.setServiceInstanceName("Lebron James"); + serviceInfo.setJobId(uuid); + serviceInfo.setJobStatus(Job.JobStatus.PENDING); + dataAccessService.saveDomainObject(serviceInfo, getPropsMap()); + return uuid; + } + + @Test(expectedExceptions = GenericUncheckedException.class, expectedExceptionsMessageRegExp = UPDATE_SERVICE_INFO_EXCEPTION_MESSAGE) + public void testUpdateServiceInfo_WithNonExisting_ThrowException() { + asyncInstantiationBL.updateServiceInfo(UUID.randomUUID(), x -> x.setServiceInstanceName("not matter")); + } + + @Test(expectedExceptions = GenericUncheckedException.class, expectedExceptionsMessageRegExp = UPDATE_SERVICE_INFO_EXCEPTION_MESSAGE) + public void testUpdateServiceInfo_WithDoubleServiceWithSameJobUuid_ThrowException() { + UUID uuid = createJobAndServiceInfo(); + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.setJobId(uuid); + dataAccessService.saveDomainObject(serviceInfo, getPropsMap()); + asyncInstantiationBL.updateServiceInfo(UUID.randomUUID(), x -> x.setServiceInstanceName("not matter")); + } + + + + @Test + public void testRequestPath_WithPauseFlagTrue_RequestPathIsAsExpected() { + ServiceInstantiation serviceInstantiationPauseFlagTrue = generateMockServiceInstantiationPayload(true, createVnfList(instanceParamsMapWithoutParams, Collections.EMPTY_LIST, true)); + String path = asyncInstantiationBL.getServiceInstantiationPath(serviceInstantiationPauseFlagTrue); + Assert.assertEquals(path, SystemProperties.getProperty("mso.restapi.serviceInstanceAssign")); + } + + @Test + public void testRequestPath_WithPauseFlagFalse_RequestPathIsAsExpected() { + ServiceInstantiation serviceInstantiationPauseFlagFalse = generateMockServiceInstantiationPayload(false, createVnfList(instanceParamsMapWithoutParams, Collections.EMPTY_LIST, true)); + String path = asyncInstantiationBL.getServiceInstantiationPath(serviceInstantiationPauseFlagFalse); + Assert.assertEquals(path, SystemProperties.getProperty("mso.restapi.serviceInstanceCreate")); + } + + @Test + public void createServiceInfo_WithUserProvidedNamingFalse_ServiceInfoIsAsExpected() throws IOException { + createServiceInfo_WithUserProvidedNamingFalse_ServiceInfoIsAsExpected(true); + } + + @Test + public void createServiceInfo_WithUserProvidedNamingFalseAndNoVfmodules_ServiceInfoIsAsExpected() throws IOException { + createServiceInfo_WithUserProvidedNamingFalse_ServiceInfoIsAsExpected(false); + } + + private void createServiceInfo_WithUserProvidedNamingFalse_ServiceInfoIsAsExpected(boolean withVfmodules) throws IOException { + ServiceInstantiation serviceInstantiationPayload = generateMockServiceInstantiationPayload(true, + createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, Collections.EMPTY_LIST, false), + 1, + false,PROJECT_NAME, true); + URL resource; + if (withVfmodules) { + resource = this.getClass().getResource("/payload_jsons/bulk_service_request_ecomp_naming.json"); + } else { + // remove the vf modules + serviceInstantiationPayload.getVnfs().values().forEach(vnf -> vnf.getVfModules().clear()); + resource = this.getClass().getResource("/payload_jsons/bulk_service_request_no_vfmodule_ecomp_naming.json"); + } + + RequestDetailsWrapper<ServiceInstantiationRequestDetails> result = + asyncInstantiationBL.generateServiceInstantiationRequest(null, serviceInstantiationPayload, "az2016"); + + String expected = IOUtils.toString(resource, "UTF-8"); + MsoOperationalEnvironmentTest.assertThatExpectationIsLikeObject(expected, result); + } + + @Test + public void checkIfNullProjectNameSentToMso(){ + ServiceInstantiation serviceInstantiationPayload = generateMockServiceInstantiationPayload(true, + createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, Collections.EMPTY_LIST, false), + 1, + false,null,false); + RequestDetailsWrapper<ServiceInstantiationRequestDetails> result = + asyncInstantiationBL.generateServiceInstantiationRequest(null, serviceInstantiationPayload, "az2016"); + JsonNode jsonNode = new ObjectMapper().valueToTree(result.requestDetails); + Assert.assertTrue(jsonNode.get("project").isNull()); + serviceInstantiationPayload = generateMockServiceInstantiationPayload(true, + createVnfList(vfModuleInstanceParamsMapWithParamsToRemove, Collections.EMPTY_LIST, false), + 1, + false,"not null",false); + result = asyncInstantiationBL.generateServiceInstantiationRequest(null, serviceInstantiationPayload, "az2016"); + jsonNode = new ObjectMapper().valueToTree(result.requestDetails); + Assert.assertTrue(jsonNode.get("project").get("projectName").asText().equalsIgnoreCase("not null")); + + + + } + + @Test + public void pushBulkJob_verifyCreatedDateBehavior_createdDateIsTheSameForAllServicesInSameBulk() { + LocalDateTime startTestDate = LocalDateTime.now().withNano(0); + final ServiceInstantiation request = generateMockServiceInstantiationPayload( + false, + createVnfList(instanceParamsMapWithoutParams, Collections.EMPTY_LIST, true), + 100, true,PROJECT_NAME, true + ); + + // in "createJob()" we will probe the service, with the generated names + final Job job = mock(Job.class); + when(job.getStatus()).thenReturn(PENDING); + when(jobAdapter.createJob(any(), any(), any(), any(), any())).thenReturn(job); + + asyncInstantiationBL.pushBulkJob(request, "myUserId"); + List<ServiceInfo> serviceInfoList = dataAccessService.getList(ServiceInfo.class, getPropsMap()); + + List<Date> creationDates = new ArrayList<>(); + for (ServiceInfo serviceInfo : serviceInfoList) { + creationDates.add(serviceInfo.getCreatedBulkDate()); + } + LocalDateTime endTestDate = LocalDateTime.now(); + + //creation date of all services is the same + Assert.assertTrue(creationDates.stream().distinct().count() <= 1); + LocalDateTime creationDate = fromDate(creationDates.get(0)); + assertFalse(creationDate.isBefore(startTestDate)); + assertFalse(creationDate.isAfter(endTestDate)); + } + + @DataProvider + public static Object[][] msoToJobStatusDataProvider() { + return new Object[][]{ + {"IN_PROGRESS", JobStatus.IN_PROGRESS}, + {"INPROGRESS", JobStatus.IN_PROGRESS}, + {"IN ProGREsS", JobStatus.IN_PROGRESS}, + {"JAMES_HARDEN", JobStatus.IN_PROGRESS}, + {"FAILED", JobStatus.FAILED}, + {"COMpleTE", JobStatus.COMPLETED}, + {"PENDING", JobStatus.IN_PROGRESS}, + {"Paused", JobStatus.PAUSE}, + {"Pause", JobStatus.PAUSE}, + {"PENDING_MANUAL_TASK", JobStatus.PAUSE}, + {"UNLOCKED", JobStatus.IN_PROGRESS} + }; + } + + @Test(dataProvider = "msoToJobStatusDataProvider") + void whenGetStatusFromMso_calcRightJobStatus(String msoStatus, Job.JobStatus expectedJobStatus) { + AsyncRequestStatus asyncRequestStatus = asyncRequestStatusResponse(msoStatus); + assertThat(asyncInstantiationBL.calcStatus(asyncRequestStatus), equalTo(expectedJobStatus)); + } + + private void createNewAuditStatus(JobAuditStatus auditStatus) + { + Date createdDate= auditStatus.getCreated(); + dataAccessService.saveDomainObject(auditStatus, getPropsMap()); + setDateToStatus(auditStatus.getSource(), auditStatus.getJobStatus(), createdDate); + } + + + + private static final String MSO_ARBITRARY_STATUS = "completed mso status"; + + @DataProvider + public static Object[][] auditStatuses(Method test) { + return new Object[][]{ + { + SourceStatus.VID, + new String[]{ JobStatus.PENDING.toString(), JobStatus.IN_PROGRESS.toString()} + }, + { SourceStatus.MSO, + new String[]{ JobStatus.IN_PROGRESS.toString(), MSO_ARBITRARY_STATUS } + } + }; + + } + + private void setDateToStatus(SourceStatus source, String status, Date date) { + List<JobAuditStatus> jobAuditStatusList = dataAccessService.getList(JobAuditStatus.class, getPropsMap()); + DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> { + jobAuditStatusList.stream() + .filter(auditStatus -> source.equals(auditStatus.getSource()) && status.equals(auditStatus.getJobStatus())) + .forEach(auditStatus -> { + auditStatus.setCreated(date); + session.saveOrUpdate(auditStatus); + }); + return 1; + }); + } + + + @Test(dataProvider = "auditStatuses") + public void givenSomeAuditStatuses_getStatusesOfSpecificSourceAndJobId_getSortedResultsMatchingToParameters(SourceStatus expectedSource, String [] expectedSortedStatuses){ + UUID jobUuid = UUID.randomUUID(); + List<JobAuditStatus> auditStatusList = com.google.common.collect.ImmutableList.of( + new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.VID, toDate(LocalDateTime.now().minusHours(2))), + new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, UUID.randomUUID(),"",toDate(LocalDateTime.now().minusHours(30))), + new JobAuditStatus(jobUuid, MSO_ARBITRARY_STATUS, SourceStatus.MSO, UUID.randomUUID(),"",toDate(LocalDateTime.now().minusHours(3))), + new JobAuditStatus(jobUuid, PENDING.toString(), SourceStatus.VID, toDate(LocalDateTime.now().minusHours(3))), + new JobAuditStatus(UUID.randomUUID(), PENDING.toString(), SourceStatus.VID, toDate(LocalDateTime.now().minusHours(3)))); + auditStatusList.forEach((auditStatus) -> createNewAuditStatus(auditStatus)); + List<JobAuditStatus> statuses = asyncInstantiationBL.getAuditStatuses(jobUuid, expectedSource); + List<String> statusesList = statuses.stream().map(status -> status.getJobStatus()).collect(Collectors.toList()); + Assert.assertTrue(statuses.stream().allMatch(status -> (status.getSource().equals(expectedSource)&& status.getJobId().equals(jobUuid))),"Only statuses of " + expectedSource + " for " + jobUuid + " should be returned. Returned statuses: " + String.join(",", statusesList )); + assertThat(statusesList, contains(expectedSortedStatuses)); + } + + + + @Test + public void addSomeVidStatuses_getThem_verifyGetInsertedWithoutDuplicates(){ + ImmutableList<JobStatus> statusesToBeInserted = ImmutableList.of(PENDING, IN_PROGRESS, IN_PROGRESS, COMPLETED); + UUID jobUuid = UUID.randomUUID(); + statusesToBeInserted.forEach(status-> + { + asyncInstantiationBL.auditVidStatus(jobUuid, status); + }); + List<String> statusesFromDB = asyncInstantiationBL.getAuditStatuses(jobUuid, SourceStatus.VID).stream().map(auditStatus -> auditStatus.getJobStatus()).collect(Collectors.toList()); + List<String> statusesWithoutDuplicates = statusesToBeInserted.stream().distinct().map(x -> x.toString()).collect(Collectors.toList()); + assertThat(statusesFromDB, is(statusesWithoutDuplicates)); + } + + @DataProvider + public static Object[][] msoAuditStatuses(Method test) { + UUID jobUuid = UUID.randomUUID(); + UUID requestId = UUID.randomUUID(); + return new Object[][]{ + { + jobUuid, + ImmutableList.of( + new JobAuditStatus(jobUuid, PENDING.toString(), SourceStatus.MSO, null, null), + new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, null), + new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, null), + new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, null), + new JobAuditStatus(jobUuid, COMPLETED.toString(), SourceStatus.MSO, requestId, null)), + ImmutableList.of(PENDING.toString(), IN_PROGRESS.toString(), COMPLETED.toString()), + "All distinct statuses should be without duplicates" + }, + { + jobUuid, + ImmutableList.of( + new JobAuditStatus(jobUuid, PENDING.toString(), SourceStatus.MSO, null, null), + new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, null), + new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, "aa"), + new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, requestId, "aa"), + new JobAuditStatus(jobUuid, IN_PROGRESS.toString(), SourceStatus.MSO, UUID.randomUUID(), "aa"), + new JobAuditStatus(jobUuid, COMPLETED.toString(), SourceStatus.MSO, requestId, null)), + ImmutableList.of(PENDING.toString(), IN_PROGRESS.toString(), IN_PROGRESS.toString(),IN_PROGRESS.toString(), COMPLETED.toString()), + "Statuses should be without duplicates only with same requestId and additionalInfo" + + } + }; + } + + @Test(dataProvider = "msoAuditStatuses") + public void addSomeMsoStatuses_getThem_verifyGetInsertedWithoutDuplicates(UUID jobUuid, ImmutableList<JobAuditStatus> msoStatuses, ImmutableList<String> expectedStatuses, String assertionReason) { + msoStatuses.forEach(status -> { + asyncInstantiationBL.auditMsoStatus(status.getJobId(), status.getJobStatus(), status.getRequestId() != null ? status.getRequestId().toString() : null, status.getAdditionalInfo()); + }); + List<String> statusesFromDB = asyncInstantiationBL.getAuditStatuses(jobUuid, SourceStatus.MSO).stream().map(auditStatus -> auditStatus.getJobStatus()).collect(Collectors.toList()); + assertThat( assertionReason, statusesFromDB, is(expectedStatuses)); + } + + @Test + public void addSameStatusOfVidAndMso_verifyThatBothWereAdded(){ + UUID jobUuid = UUID.randomUUID(); + JobStatus sameStatus = IN_PROGRESS; + asyncInstantiationBL.auditMsoStatus(jobUuid, sameStatus.toString(),null,null); + asyncInstantiationBL.auditVidStatus(jobUuid, sameStatus); + List<JobAuditStatus> list = dataAccessService.getList( + JobAuditStatus.class, + String.format(" where JOB_ID = '%s'", jobUuid), + null, null); + Assert.assertEquals(list.size(),2); + assertThat(list,everyItem(hasProperty("jobStatus", is(sameStatus.toString())))); + } + + @Test + public void verifyAsyncRequestStatus_canBeReadFromSample() throws IOException { + String body = "{" + + " \"request\": {" + + " \"requestId\": \"c0011670-0e1a-4b74-945d-8bf5aede1d9c\"," + + " \"startTime\": \"Mon, 11 Dec 2017 07:27:49 GMT\"," + + " \"requestScope\": \"service\"," + + " \"requestType\": \"createInstance\"," + + " \"instanceReferences\": {" + + " \"serviceInstanceId\": \"f8791436-8d55-4fde-b4d5-72dd2cf13cfb\"," + + " \"serviceInstanceName\": \"asdfasdf234234asdf\"," + + " \"requestorId\": \"il883e\"" + + " }," + + " \"requestStatus\": {" + + " \"requestState\": \"COMPLETE\"," + + " \"statusMessage\": \"Service Instance was created successfully.\"," + + " \"percentProgress\": 100," + + " \"finishTime\": \"Mon, 11 Dec 2017 07:27:53 GMT\"" + + " }" + + " }" + + "}"; + ObjectMapper objectMapper = new ObjectMapper(); + AsyncRequestStatus asyncRequestStatus = objectMapper.readValue(body, AsyncRequestStatus.class); + assertThat(asyncRequestStatus.request.requestStatus.getRequestState(), equalTo("COMPLETE")); + + } + + @Test + public void deleteJobInfo_pending_deleted() { + doNothing().when(jobsBrokerService).delete(any()); + UUID uuid = createServicesInfoWithDefaultValues(PENDING); + asyncInstantiationBL.deleteJob(uuid); + assertNotNull(asyncInstantiationBL.getServiceInfoByJobId(uuid).getDeletedAt(), "service info wasn't deleted"); + } + + @Test(expectedExceptions = IllegalStateException.class, expectedExceptionsMessageRegExp = DELETE_SERVICE_INFO_STATUS_EXCEPTION_MESSAGE) + public void deleteJobInfo_notAllowdStatus_shouldSendError() { + UUID uuid = createServicesInfoWithDefaultValues(COMPLETED); + doThrow(new IllegalStateException(DELETE_SERVICE_INFO_STATUS_EXCEPTION_MESSAGE)).when(jobsBrokerService).delete(any()); + try { + asyncInstantiationBL.deleteJob(uuid); + } catch (Exception e) { + assertNull(asyncInstantiationBL.getServiceInfoByJobId(uuid).getDeletedAt(), "service info shouldn't deleted"); + throw e; + } + } + + @DataProvider + public Object[][] jobStatusesFinal() { + return Arrays.stream(Job.JobStatus.values()) + .filter(t -> ImmutableList.of(COMPLETED, FAILED, STOPPED).contains(t)) + .map(v -> new Object[]{v}).collect(Collectors.toList()).toArray(new Object[][]{}); + } + + @Test(dataProvider = "jobStatusesFinal") + public void whenHideService_theServiceNotReturnedInServiceList(JobStatus jobStatus) { + UUID uuidToHide = createServicesInfoWithDefaultValues(jobStatus); + UUID uuidToShown = createServicesInfoWithDefaultValues(jobStatus); + List<UUID> serviceInfoList = listServicesUUID(); + assertThat(serviceInfoList, hasItems(uuidToHide, uuidToShown)); + + asyncInstantiationBL.hideServiceInfo(uuidToHide); + serviceInfoList = listServicesUUID(); + assertThat(serviceInfoList, hasItem(uuidToShown)); + assertThat(serviceInfoList, not(hasItem(uuidToHide))); + + } + + protected List<UUID> listServicesUUID() { + return asyncInstantiationBL.getAllServicesInfo().stream().map(ServiceInfo::getJobId).collect(Collectors.toList()); + } + + @DataProvider + public Object[][] jobStatusesNotFinal() { + return Arrays.stream(Job.JobStatus.values()) + .filter(t -> ImmutableList.of(PENDING, IN_PROGRESS, PAUSE).contains(t)) + .map(v -> new Object[]{v}).collect(Collectors.toList()).toArray(new Object[][]{}); + } + + @Test( dataProvider = "jobStatusesNotFinal", + expectedExceptions = OperationNotAllowedException.class, + expectedExceptionsMessageRegExp = "jobId.*Service status does not allow hide service, status = .*") + public void hideServiceInfo_notAllowedStatus_shouldSendError(JobStatus jobStatus) { + UUID uuid = createServicesInfoWithDefaultValues(jobStatus); + try { + asyncInstantiationBL.hideServiceInfo(uuid); + } catch (Exception e) { + assertFalse(asyncInstantiationBL.getServiceInfoByJobId(uuid).isHidden(), "service info shouldn't be hidden"); + throw e; + } + } + + @Test + public void whenUseGetCounterInMultiThreads_EachThreadGetDifferentCounter() throws InterruptedException { + int SIZE = 200; + ExecutorService executor = Executors.newFixedThreadPool(SIZE); + List<Callable<Integer>> tasks = IntStream.rangeClosed(1, SIZE) + .mapToObj(x-> ((Callable<Integer>)() -> asyncInstantiationBL.getCounterForName("a"))) + .collect(Collectors.toList()); + Set<Integer> expectedResults = IntStream.rangeClosed(1, SIZE).boxed().collect(Collectors.toSet()); + executor.invokeAll(tasks) + .forEach(future -> { + try { + assertTrue( expectedResults.remove(future.get()), "got unexpected counter"); + } + catch (Exception e) { + throw new RuntimeException(e); + } + }); + + assertThat(expectedResults.size(), is(0)); + } + + @Test + public void whenUseGetCounterForSameName_numbersReturnedByOrder() { + + String name = UUID.randomUUID().toString(); + int SIZE=10; + for (int i=1; i<=SIZE; i++) { + assertThat(asyncInstantiationBL.getCounterForName(name), is(i)); + } + } + + @Test + public void whenNamedInUsedInAai_getNextNumber() { + String name = someCommonStepsAndGetName(); + ResourceType type = ResourceType.GENERIC_VNF; + when(aaiClient.searchNodeTypeByName(name+"_001", type)).thenReturn(aaiNodeQueryResponseNameUsed(type)); + when(aaiClient.searchNodeTypeByName(name+"_002", type)).thenReturn(aaiNodeQueryResponseNameFree()); + assertThat(asyncInstantiationBL.getUniqueName(name, type), equalTo(name+"_002")); + } + + private String someCommonStepsAndGetName() { + mockAaiClientAaiStatusOK(); + return UUID.randomUUID().toString(); + } + + private void mockAaiClientAaiStatusOK() { + when(aaiClient.searchNodeTypeByName(eq(AsyncInstantiationBusinessLogicImpl.NAME_FOR_CHECK_AAI_STATUS), any())).thenReturn(aaiNodeQueryResponseNameFree()); + } + + @Test(expectedExceptions=InvalidAAIResponseException.class) + public void whenAaiBadResponseCode_throwInvalidAAIResponseException() { + String name = someCommonStepsAndGetName(); + ResourceType type = ResourceType.SERVICE_INSTANCE; + when(aaiClient.searchNodeTypeByName(name+"_001", type)).thenReturn(aaiNodeQueryBadResponse()); + asyncInstantiationBL.getUniqueName(name, type); + } + + @Test(expectedExceptions=MaxRetriesException.class) + public void whenAaiAlwaysReturnNameUsed_throwInvalidAAIResponseException() { + String name = someCommonStepsAndGetName(); + ResourceType type = ResourceType.VF_MODULE; + when(aaiClient.searchNodeTypeByName(any(), eq(type))).thenReturn(aaiNodeQueryResponseNameUsed(type)); + asyncInstantiationBL.setMaxRetriesGettingFreeNameFromAai(10); + asyncInstantiationBL.getUniqueName(name, type); + } + + @Test + public void testFormattingOfNameAndCounter() { + AsyncInstantiationBusinessLogicImpl bl = (AsyncInstantiationBusinessLogicImpl) asyncInstantiationBL; + assertThat(bl.formatNameAndCounter("x", 3), equalTo("x_003")); + assertThat(bl.formatNameAndCounter("x", 99), equalTo("x_099")); + assertThat(bl.formatNameAndCounter("x", 100), equalTo("x_100")); + assertThat(bl.formatNameAndCounter("x", 1234), equalTo("x_1234")); + }*/ +} diff --git a/vid-app-common/src/test/java/org/onap/vid/services/ChangeManagementServiceImplTest.java b/vid-app-common/src/test/java/org/onap/vid/services/ChangeManagementServiceImplTest.java index 7819b4c9..157f59c7 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/ChangeManagementServiceImplTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/ChangeManagementServiceImplTest.java @@ -1,193 +1,116 @@ package org.onap.vid.services; -import static org.junit.Assert.*; -import java.util.*; - -import org.json.simple.JSONArray; -import org.junit.Assert; -import org.junit.Test; -import org.onap.portalsdk.core.service.DataAccessService; -import org.onap.portalsdk.core.service.DataAccessServiceImpl; +import org.mockito.*; import org.onap.vid.changeManagement.ChangeManagementRequest; -import org.onap.vid.changeManagement.GetVnfWorkflowRelationRequest; import org.onap.vid.changeManagement.RequestDetails; -import org.onap.vid.changeManagement.VnfWorkflowRelationAllResponse; -import org.onap.vid.changeManagement.VnfWorkflowRelationRequest; -import org.onap.vid.changeManagement.VnfWorkflowRelationResponse; import org.onap.vid.mso.MsoBusinessLogic; -import org.onap.vid.mso.MsoBusinessLogicImpl; -import org.onap.vid.mso.rest.MsoRestClientNew; -import org.onap.vid.mso.rest.Request; +import org.onap.vid.mso.MsoResponseWrapperInterface; +import org.onap.vid.scheduler.SchedulerRestInterfaceIfc; +import org.onap.portalsdk.core.service.DataAccessService; import org.springframework.http.ResponseEntity; -import org.springframework.web.multipart.MultipartFile; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.mockito.Mockito.verify; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +@Test public class ChangeManagementServiceImplTest { - private ChangeManagementServiceImpl createTestSubject() { - return new ChangeManagementServiceImpl(new DataAccessServiceImpl(), - new MsoBusinessLogicImpl(new MsoRestClientNew())); - } + @Mock + DataAccessService dataAccessServiceMock; - @Test - public void testGetMSOChangeManagements() throws Exception { - ChangeManagementServiceImpl testSubject; - Collection<Request> result; + @Mock + MsoBusinessLogic msoBusinessLogicMock; + + @Mock + SchedulerRestInterfaceIfc schedulerRestInterface; - // default test - testSubject = createTestSubject(); - result = testSubject.getMSOChangeManagements(); + @BeforeMethod + public void initMocks(){ + MockitoAnnotations.initMocks(this); } @Test - public void testDoChangeManagement() throws Exception { - ChangeManagementServiceImpl testSubject; - ChangeManagementRequest request = null; - String vnfName = ""; - ResponseEntity<String> result; - - // test 1 - testSubject = createTestSubject(); - request = null; - result = testSubject.doChangeManagement(request, vnfName); - Assert.assertEquals(null, result); + public void doChangeManagement_requestIsNull_returnsNull() throws Exception { + ChangeManagementServiceImpl changeManagementService = new ChangeManagementServiceImpl(dataAccessServiceMock, msoBusinessLogicMock, schedulerRestInterface); + ResponseEntity<String> result = changeManagementService.doChangeManagement(null,"anyString"); + assertNull(result); } @Test - public void testGetSchedulerChangeManagements() throws Exception { - ChangeManagementServiceImpl testSubject; - JSONArray result; + public void doChangeManagement_currentRequestDetailsIsNull_returnsNull() throws Exception { + ChangeManagementServiceImpl changeManagementService = new ChangeManagementServiceImpl(dataAccessServiceMock, msoBusinessLogicMock, schedulerRestInterface); - // default test - testSubject = createTestSubject(); - result = testSubject.getSchedulerChangeManagements(); - } + ChangeManagementServiceImpl changeManagementServiceSpied = Mockito.spy(changeManagementService); + Mockito.doReturn(null).when(changeManagementServiceSpied).findRequestByVnfName(Matchers.anyList(),Mockito.anyString()); - @Test - public void testDeleteSchedule() throws Exception { - ChangeManagementServiceImpl testSubject; - String scheduleId = ""; + ResponseEntity<String> result = changeManagementServiceSpied.doChangeManagement(null,"anyString"); - // default test - testSubject = createTestSubject(); - testSubject.deleteSchedule(scheduleId); + assertNull(result); } - @Test - public void testAddVnfWorkflowRelation() throws Exception { - ChangeManagementServiceImpl testSubject; - VnfWorkflowRelationRequest vnfWorkflowRelationRequest = null; - VnfWorkflowRelationResponse result; - - // default test - try { - testSubject = createTestSubject(); - result = testSubject.addVnfWorkflowRelation(vnfWorkflowRelationRequest); - } catch ( - - Exception e) { - } - } @Test - public void testDeleteVnfWorkflowRelation() throws Exception { - ChangeManagementServiceImpl testSubject; - VnfWorkflowRelationRequest vnfWorkflowRelationRequest = null; - VnfWorkflowRelationResponse result; - - // default test - try { - testSubject = createTestSubject(); - result = testSubject.deleteVnfWorkflowRelation(vnfWorkflowRelationRequest); - } catch ( - - Exception e) { - } + public void doChangeManagement_requestTypeIsUpdate_MsoUpdateVnfIsCalled() throws Exception { + Mockito.doReturn(Mockito.mock(MsoResponseWrapperInterface.class)).when(msoBusinessLogicMock).updateVnf(Mockito.any(),Mockito.anyString(),Mockito.anyString()); + RequestDetails requestDetails = callChangeManagement(ChangeManagementRequest.UPDATE); + + ArgumentCaptor<RequestDetails> argumentCaptor = ArgumentCaptor.forClass(RequestDetails.class); + verify(msoBusinessLogicMock).updateVnf(argumentCaptor.capture(),Mockito.anyString(),Mockito.anyString()); + assertEquals(argumentCaptor.getValue().getVnfInstanceId(),requestDetails.getVnfInstanceId()); } @Test - public void testGetAllVnfWorkflowRelations() throws Exception { - ChangeManagementServiceImpl testSubject; - VnfWorkflowRelationAllResponse result; - - // default test - try { - testSubject = createTestSubject(); - result = testSubject.getAllVnfWorkflowRelations(); - } catch ( - - Exception e) { - } + public void doChangeManagement_requestTypeIsReplace_MsoUpdateVnfIsCalled() throws Exception { + Mockito.doReturn(Mockito.mock(MsoResponseWrapperInterface.class)).when(msoBusinessLogicMock).replaceVnf(Mockito.any(),Mockito.anyString(),Mockito.anyString()); + RequestDetails requestDetails = callChangeManagement(ChangeManagementRequest.REPLACE); + + + ArgumentCaptor<RequestDetails> argumentCaptor = ArgumentCaptor.forClass(RequestDetails.class); + + verify(msoBusinessLogicMock).replaceVnf(argumentCaptor.capture(),Mockito.anyString(),Mockito.anyString()); + assertEquals(argumentCaptor.getValue().getVnfInstanceId(),requestDetails.getVnfInstanceId()); } @Test - public void testGetWorkflowsForVnf() throws Exception { - ChangeManagementServiceImpl testSubject; - GetVnfWorkflowRelationRequest getVnfWorkflowRelationRequest = null; - List<String> result; - - // default test - try { - testSubject = createTestSubject(); - result = testSubject.getWorkflowsForVnf(getVnfWorkflowRelationRequest); - } catch ( - - Exception e) { - } + public void doChangeManagement_requestTypeIsInPlaceSoftwareUpdate_MsoUpdateVnfIsCalled() throws Exception { + Mockito.doReturn(Mockito.mock(MsoResponseWrapperInterface.class)).when(msoBusinessLogicMock).updateVnfSoftware(Mockito.any(),Mockito.anyString(),Mockito.anyString()); + RequestDetails requestDetails = callChangeManagement(ChangeManagementRequest.VNF_IN_PLACE_SOFTWARE_UPDATE); + + + ArgumentCaptor<RequestDetails> argumentCaptor = ArgumentCaptor.forClass(RequestDetails.class); + + verify(msoBusinessLogicMock).updateVnfSoftware(argumentCaptor.capture(),Mockito.anyString(),Mockito.anyString()); + assertEquals(argumentCaptor.getValue().getVnfInstanceId(),requestDetails.getVnfInstanceId()); } @Test - public void testUploadConfigUpdateFile() throws Exception { - ChangeManagementServiceImpl testSubject; - MultipartFile file = null; - String result; - - // default test - try { - testSubject = createTestSubject(); - result = testSubject.uploadConfigUpdateFile(file); - } catch ( - - Exception e) { - } + public void doChangeManagement_requestTypeIsConfigUpdate_MsoUpdateVnfIsCalled() throws Exception { + Mockito.doReturn(Mockito.mock(MsoResponseWrapperInterface.class)).when(msoBusinessLogicMock).updateVnfConfig(Mockito.any(),Mockito.anyString(),Mockito.anyString()); + RequestDetails requestDetails = callChangeManagement(ChangeManagementRequest.CONFIG_UPDATE); + + + ArgumentCaptor<RequestDetails> argumentCaptor = ArgumentCaptor.forClass(RequestDetails.class); + + verify(msoBusinessLogicMock).updateVnfConfig(argumentCaptor.capture(),Mockito.anyString(),Mockito.anyString()); + assertEquals(argumentCaptor.getValue().getVnfInstanceId(),requestDetails.getVnfInstanceId()); } - /* - * TODO: fix private ChangeManagementServiceImpl createTestSubject() { - * return new ChangeManagementServiceImpl(); } - */ - - /* - * @Test public void testGetMSOChangeManagements() throws Exception { - * ChangeManagementServiceImpl testSubject; Collection<Request> result; - * - * // default test testSubject = createTestSubject(); result = - * testSubject.getMSOChangeManagements(); } - * - * - * @Test public void testFindRequestByVnfName() throws Exception { - * ChangeManagementServiceImpl testSubject;List<RequestDetails> requests = - * null; String vnfName = ""; RequestDetails result; - * - * // test 1 testSubject=createTestSubject();requests = null; - * result=Deencapsulation.invoke(testSubject, "findRequestByVnfName", new - * Object[]{List<RequestDetails>.class, vnfName}); Assert.assertEquals(null, - * result); } - */ - /* - * - * @Test public void testDoChangeManagement() throws Exception { - * ChangeManagementServiceImpl testSubject; ChangeManagementRequest request - * = null; String vnfName = ""; ResponseEntity<String> result; - * - * // test 1 testSubject = createTestSubject(); request = null; result = - * testSubject.doChangeManagement(request, vnfName); - * Assert.assertEquals(null, result); } - * - * - * @Test public void testGetSchedulerChangeManagements() throws Exception { - * ChangeManagementServiceImpl testSubject; JSONArray result; - * - * // default test testSubject = createTestSubject(); result = - * testSubject.getSchedulerChangeManagements(); } - */ -}
\ No newline at end of file + private RequestDetails callChangeManagement(String requestType) throws Exception { + ChangeManagementServiceImpl changeManagementService = new ChangeManagementServiceImpl(dataAccessServiceMock, msoBusinessLogicMock, schedulerRestInterface); + ChangeManagementServiceImpl changeManagementServiceSpied = Mockito.spy(changeManagementService); + ChangeManagementRequest updateRequest = new ChangeManagementRequest(); + + updateRequest.setRequestType(requestType); + RequestDetails requestDetails = new RequestDetails(); + requestDetails.setVnfInstanceId("vnfFakeId"); + Mockito.doReturn("fakeId").when(changeManagementServiceSpied).extractServiceInstanceId(Mockito.anyObject(),Mockito.anyString()); + Mockito.doReturn(requestDetails).when(changeManagementServiceSpied).findRequestByVnfName(Matchers.anyList(),Mockito.anyString()); + + changeManagementServiceSpied.doChangeManagement(updateRequest,"anyVnfName"); + + return requestDetails; + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/services/ChangeManagementServiceUnitTest.java b/vid-app-common/src/test/java/org/onap/vid/services/ChangeManagementServiceUnitTest.java index 26274e80..5a21d8ca 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/ChangeManagementServiceUnitTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/ChangeManagementServiceUnitTest.java @@ -3,18 +3,21 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.io.IOUtils; import org.mockito.ArgumentCaptor; -import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.changeManagement.ChangeManagementRequest; import org.onap.vid.controllers.MsoConfig; import org.onap.vid.controllers.WebConfig; import org.onap.vid.model.RequestReferencesContainer; +import org.onap.vid.mso.MsoBusinessLogic; import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.MsoRestClientNew; import org.onap.vid.mso.rest.RequestDetails; import org.onap.vid.properties.AsdcClientConfiguration; +import org.onap.vid.scheduler.SchedulerRestInterfaceIfc; import org.onap.vid.services.ChangeManagementService; import org.onap.vid.services.ChangeManagementServiceImpl; import org.onap.vid.testUtils.RegExMatcher; +import org.onap.portalsdk.core.service.DataAccessService; +import org.onap.portalsdk.core.util.SystemProperties; import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.context.annotation.Bean; @@ -100,8 +103,8 @@ public class ChangeManagementServiceUnitTest extends AbstractTestNGSpringContext } @Bean - public ChangeManagementService getChangeManagementService() { - return new ChangeManagementServiceImpl(null, getMsoBusinessLogic()); + public ChangeManagementService getChangeManagementService(DataAccessService dataAccessService, MsoBusinessLogic msoInterface, SchedulerRestInterfaceIfc schedulerRestInterface) { + return new ChangeManagementServiceImpl(dataAccessService, msoInterface, schedulerRestInterface); } } } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java b/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java new file mode 100644 index 00000000..ff4b34f5 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java @@ -0,0 +1,616 @@ +package org.onap.vid.services; + +// +//import com.google.common.collect.ImmutableList; +//import com.google.common.collect.ImmutableMap; +//import org.apache.commons.lang.RandomStringUtils; +//import org.apache.commons.lang3.RandomUtils; +//import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +//import org.apache.commons.lang3.builder.ToStringStyle; +//import org.hibernate.SessionFactory; +//import org.onap.vid.exceptions.GenericUncheckedException; +//import org.onap.vid.exceptions.OperationNotAllowedException; +//import org.onap.vid.job.Job; +//import org.onap.vid.job.JobAdapter; +//import org.onap.vid.job.JobType; +//import org.onap.vid.job.JobsBrokerService; +//import org.onap.vid.job.impl.JobDaoImpl; +//import org.onap.vid.job.impl.JobsBrokerServiceInDatabaseImpl; +//import org.onap.vid.utils.DaoUtils; +//import org.onap.vid.config.DataSourceConfig; +//import org.onap.vid.config.JobAdapterConfig; +//import org.onap.portalsdk.core.domain.support.DomainVo; +//import org.onap.portalsdk.core.service.DataAccessService; +//import org.onap.portalsdk.core.util.SystemProperties; +//import org.springframework.test.context.ContextConfiguration; +//import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; +//import org.testng.Assert; +//import org.testng.annotations.AfterMethod; +//import org.testng.annotations.BeforeMethod; +//import org.testng.annotations.DataProvider; +//import org.testng.annotations.Test; +// +//import javax.inject.Inject; +//import java.lang.reflect.Method; +//import java.time.LocalDateTime; +//import java.time.ZoneId; +//import java.util.*; +//import java.util.concurrent.*; +//import java.util.stream.Collectors; +//import java.util.stream.IntStream; +//import java.util.stream.Stream; +// +//import static java.util.concurrent.TimeUnit.MILLISECONDS; +//import static org.hamcrest.CoreMatchers.equalTo; +//import static org.hamcrest.CoreMatchers.is; +//import static org.hamcrest.MatcherAssert.assertThat; +//import static org.hamcrest.Matchers.both; +//import static org.hamcrest.Matchers.containsInAnyOrder; +//import static org.onap.vid.job.Job.JobStatus.*; +//import static org.onap.vid.utils.Streams.not; +//import static org.testng.Assert.assertNotNull; +//import static org.testng.AssertJUnit.assertEquals; +// +//@ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, JobAdapterConfig.class}) +//public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { +// +// private static final int JOBS_COUNT = 127; +// private static final boolean DELETED = true; +// private final ExecutorService executor = Executors.newFixedThreadPool(90); +// +// private final Set<Long> threadsIds = new ConcurrentSkipListSet<>(); +// +// private final long FEW = 500; +// +// private final String JOBS_SHOULD_MATCH = "the jobs that added and those that pulled must be the same"; +// private final String JOBS_PEEKED_SHOULD_MATCH = "the jobs that added and those that peeked must be the same"; +// private static final String DELETE_SERVICE_INFO_STATUS_EXCEPTION_MESSAGE = "Service status does not allow deletion from the queue"; +// private static final String DELETE_SERVICE_NOT_EXIST_EXCEPTION_MESSAGE = "Service does not exist"; +// private JobsBrokerService broker; +// +// @Inject +// JobAdapter jobAdapter; +// @Inject +// private DataAccessService dataAccessService; +// @Inject +// private SessionFactory sessionFactory; +// +// /* +// - pulling jobs is limited to inserted ones +// - putting back allows getting the job again +// - multi threads safety +// - any added job should be visible with view +// +// - edges: +// - pulling with empty repo should return empty optional +// - pulling more than expected should return empty optional +// - putting one, over-pulling from a different thread +// - take before inserting, then insert while waiting +// +// */ +// +// private class NoJobException extends RuntimeException { +// } +// +// private Future<Job> newJobAsync(JobsBrokerService b) { +// return newJobAsync(b, createMockJob("user id")); +// } +// +// private Future<Job> newJobAsync(JobsBrokerService b, Job.JobStatus status) { +// return newJobAsync(b, createMockJob("user id", status)); +// } +// +// private Job createMockJob(String userId) { +// return jobAdapter.createJob( +// JobType.NoOp, +// new JobAdapter.AsyncJobRequest() { +// public int nothing = 42; +// }, +// UUID.randomUUID(), +// userId, +// RandomUtils.nextInt()); +// } +// +// private Job createMockJob(String userId, Job.JobStatus jobStatus) { +// Job job = createMockJob(userId); +// job.setStatus(jobStatus); +// return job; +// } +// +// private Future<Job> newJobAsync(JobsBrokerService b, Job job) { +// final Future<Job> jobFuture = executor.submit(() -> { +// accountThreadId(); +// +// b.add(job); +// +// return job; +// }); +// return jobFuture; +// } +// +// private void pushBackJobAsync(JobsBrokerService b, Job job) { +// executor.submit(() -> { +// accountThreadId(); +// b.pushBack(job); +// return job; +// }); +// } +// +// private Future<Optional<Job>> pullJobAsync(JobsBrokerService broker) { +// final Future<Optional<Job>> job = executor.submit(() -> { +// accountThreadId(); +// // Pull only pending jobs, as H2 database does not support our SQL for in-progress jobs +// return broker.pull(Job.JobStatus.PENDING, UUID.randomUUID().toString()); +// }); +// return job; +// } +// +// private Job waitForFutureOptionalJob(Future<Optional<Job>> retrievedOptionalJobFuture) { +// try { +// return retrievedOptionalJobFuture.get(FEW, MILLISECONDS).orElseThrow(NoJobException::new); +// } catch (TimeoutException | InterruptedException | ExecutionException e) { +// throw new RuntimeException(e); +// } +// } +// +// private Job waitForFutureJob(Future<Job> retrievedJobFuture) { +// try { +// return retrievedJobFuture.get(FEW, MILLISECONDS); +// } catch (TimeoutException | InterruptedException | ExecutionException e) { +// throw new RuntimeException(e); +// } +// } +// +// private List<Job> putAndGetALotOfJobs(JobsBrokerService broker) { +// final List<Job> originalJobs = putALotOfJobs(broker); +// final List<Job> retrievedJobs = getAlotOfJobs(broker); +// +// assertThat(JOBS_SHOULD_MATCH, retrievedJobs, containsInAnyOrder(originalJobs.toArray())); +// +// return retrievedJobs; +// } +// +// private List<Job> putALotOfJobs(JobsBrokerService broker) { +// int n = JOBS_COUNT; +// return IntStream.range(0, n) +// .mapToObj(i -> newJobAsync(broker)) +// .map(this::waitForFutureJob) +// .collect(Collectors.toList()); +// } +// +// private List<Job> getAlotOfJobs(JobsBrokerService broker) { +// int n = JOBS_COUNT; +// return IntStream.range(0, n) +// .mapToObj(i -> pullJobAsync(broker)) +// .map(this::waitForFutureOptionalJob) +// .collect(Collectors.toList()); +// } +// +// private void pushBackJobs(List<Job> jobs, JobsBrokerService broker) { +// jobs.forEach(job -> pushBackJobAsync(broker, job)); +// } +// +// private void accountThreadId() { +// threadsIds.add(Thread.currentThread().getId()); +// } +// +// @AfterMethod +// public void threadsCounter() { +// System.out.println("participating threads count: " + threadsIds.size()); +// threadsIds.clear(); +// } +// +// @BeforeMethod +// public void initializeBroker() { +// broker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, 200, 0); +// ((JobsBrokerServiceInDatabaseImpl) broker).deleteAll(); +// } +// +// @Test +// public void givenSingleJob_getIt_verifySameJob() { +// final Job originalJob = waitForFutureJob(newJobAsync(broker)); +// +// final Job retrievedJob = waitForFutureOptionalJob(pullJobAsync(broker)); +// assertThat(JOBS_SHOULD_MATCH, retrievedJob, is(originalJob)); +// } +// +// @Test +// public void givenManyJobs_getJobsAndPushThemBack_alwaysSeeAllOfThemWithPeek() throws InterruptedException { +// final List<Job> originalJobs = putALotOfJobs(broker); +// +// MILLISECONDS.sleep(FEW); +// assertThat(JOBS_PEEKED_SHOULD_MATCH, broker.peek(), containsInAnyOrder(originalJobs.toArray())); +// +// final Job retrievedJob = waitForFutureOptionalJob(pullJobAsync(broker)); +// +// MILLISECONDS.sleep(FEW); +// assertThat(JOBS_PEEKED_SHOULD_MATCH, broker.peek(), containsInAnyOrder(originalJobs.toArray())); +// +// pushBackJobAsync(broker, retrievedJob); +// +// MILLISECONDS.sleep(FEW); +// assertThat(JOBS_PEEKED_SHOULD_MATCH, broker.peek(), containsInAnyOrder(originalJobs.toArray())); +// } +// +// @Test +// public void givenManyJobs_getThemAll_verifySameJobs() { +// putAndGetALotOfJobs(broker); +// } +// +// @Test +// public void givenManyJobs_getThemAllThenPushBackandGet_verifySameJobs() { +// final List<Job> retrievedJobs1 = putAndGetALotOfJobs(broker); +// +// pushBackJobs(retrievedJobs1, broker); +// final List<Job> retrievedJobs2 = getAlotOfJobs(broker); +// +// assertThat(JOBS_SHOULD_MATCH, retrievedJobs2, containsInAnyOrder(retrievedJobs1.toArray())); +// } +// +// private static Date toDate(LocalDateTime localDateTime) { +// return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); +// } +// +// private void setModifiedDateToJob(UUID jobUuid, Date date) { +// DomainVo job = dataAccessService.getDomainObject(JobDaoImpl.class, jobUuid, DaoUtils.getPropsMap()); +// job.setModified(date); +// DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> { +// session.saveOrUpdate(job); +// return 1; +// }); +// } +// +// +// public static JobDaoImpl createNewJob(Integer indexInBulk, UUID templateId, String userId, Job.JobStatus status, String takenBy, LocalDateTime date) { +// return createNewJob(indexInBulk, templateId, userId, status, takenBy, date, false); +// } +// +// public static JobDaoImpl createNewJob(Integer indexInBulk, UUID templateId, String userId, Job.JobStatus status, String takenBy, LocalDateTime date, boolean deleted){ +// JobDaoImpl job = new JobDaoImpl(); +// job.setTypeAndData(JobType.NoOp, ImmutableMap.of("x", RandomStringUtils.randomAlphanumeric(15))); +// job.setIndexInBulk(indexInBulk); +// job.setTemplateId(templateId); +// job.setType(JobType.NoOp); +// job.setStatus(status); +// job.setTakenBy(takenBy); +// job.setCreated(toDate(date)); +// job.setModified(toDate(date)); +// job.setUserId(userId); +// if (deleted) { +// job.setDeletedAt(new Date()); +// } +// return job; +// } +// +// @DataProvider +// public static Object[][] jobs(Method test) { +// LocalDateTime oldestDate = LocalDateTime.now().minusHours(30); +// UUID sameTemplate = UUID.randomUUID(); +// return new Object[][]{ +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userId", PENDING, null, oldestDate), +// createNewJob(22, UUID.randomUUID(), "userId", PENDING, null, oldestDate), +// createNewJob(11, UUID.randomUUID(), "userId", PENDING, null, LocalDateTime.now().minusHours(2)), +// createNewJob(44, UUID.randomUUID(), "userId", PENDING, null, LocalDateTime.now().minusHours(5))), +// 4, +// 0, +// PENDING, +// "Broker should pull the first pending job by oldest date then by job index" +// }, +// { ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userId", COMPLETED,null, oldestDate), +// createNewJob(11, UUID.randomUUID(), "userId", PENDING,null, oldestDate, DELETED),createNewJob(12, UUID.randomUUID(), "userId", FAILED,null, oldestDate), +// createNewJob(13, UUID.randomUUID(), "userId", IN_PROGRESS,null, oldestDate), +// createNewJob(14, UUID.randomUUID(), "userId", STOPPED,null, oldestDate), +// createNewJob(22, UUID.randomUUID(), "userId", PENDING,null, oldestDate), +// createNewJob(33, UUID.randomUUID(), "userId", PENDING,null, LocalDateTime.now().minusHours(2))), +// 6, +// 5, +// PENDING, +// "Broker should pull the only pending - first pending job by oldest job - ignore deleted,completed, failed, in-progress and stopped statuses" +// }, +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userId", IN_PROGRESS, UUID.randomUUID().toString(), oldestDate), +// createNewJob(22, UUID.randomUUID(), "userId", IN_PROGRESS, UUID.randomUUID().toString(), oldestDate), +// createNewJob(33, UUID.randomUUID(), "userId", PENDING, null, LocalDateTime.now().minusHours(2))), +// 2, +// -1, +// PENDING, +// "Broker should not pull any job when it exceeded mso limit with count (in-progress) statuses" +// }, +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userId", IN_PROGRESS, UUID.randomUUID().toString(), oldestDate), +// createNewJob(22, UUID.randomUUID(), "userId", PENDING, UUID.randomUUID().toString(), oldestDate), +// createNewJob(33, UUID.randomUUID(), "userId", PENDING, null, LocalDateTime.now().minusHours(2))), +// 2, +// -1, +// PENDING, +// "Broker should not pull any job when it exceeded mso limit with count(in-progress or pending && taken) statuses" +// }, +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userId", IN_PROGRESS, UUID.randomUUID().toString(), oldestDate), +// createNewJob(22, UUID.randomUUID(), "userId", PENDING, UUID.randomUUID().toString(), oldestDate), +// createNewJob(33, UUID.randomUUID(), "userId", PENDING, null, LocalDateTime.now().minusHours(2))), +// 3, +// 2, +// PENDING, +// "Broker should pull first job when it doesn't exceeded mso limit with count(in-progress or pending && taken) statuses" +// }, +// {ImmutableList.of( +// createNewJob(11, sameTemplate, "userId", PENDING, UUID.randomUUID().toString(), oldestDate), +// createNewJob(22, sameTemplate, "userId", PENDING, null, oldestDate), +// createNewJob(33, sameTemplate, "userId", PENDING, null, LocalDateTime.now().minusHours(2))), +// 3, +// -1, +// PENDING, +// "Broker should not pull any job when there is another job from this template that was taken" +// }, +// {ImmutableList.of( +// createNewJob(11, sameTemplate, "userId", IN_PROGRESS, null, oldestDate), +// createNewJob(22, sameTemplate, "userId", PENDING, null, oldestDate), +// createNewJob(33, sameTemplate, "userId", PENDING, null, LocalDateTime.now().minusHours(2))), +// 3, +// -1, +// PENDING, +// "Broker should not pull any job when there is another job from this template that in progress" +// }, +// {ImmutableList.of( +// createNewJob(11, sameTemplate, "userId", FAILED, null, oldestDate), +// createNewJob(22, sameTemplate, "userId", STOPPED, null, oldestDate), +// createNewJob(33, sameTemplate, "userId", PENDING, null, LocalDateTime.now().minusHours(2))), +// 3, +// -1, +// PENDING, +// "Broker should not pull any job when there is another job from this template that was failed" +// }, +// {ImmutableList.of( +// createNewJob(11, sameTemplate, "userId", FAILED, null, oldestDate, DELETED), +// createNewJob(22, sameTemplate, "userId", STOPPED,null, oldestDate), +// createNewJob(33, sameTemplate, "userId", PENDING,null, LocalDateTime.now().minusHours(2))), +// 3, +// 2, +// PENDING, +// "Broker should pull pending job when there is another job from this template that was deleted, although failed" +// }, +// { ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userA", IN_PROGRESS, null, oldestDate), +// createNewJob(22, UUID.randomUUID(), "userA", PENDING, null, oldestDate), +// createNewJob(33, UUID.randomUUID(), "userB", PENDING, null, LocalDateTime.now().minusHours(2))), +// 3, +// 2, +// PENDING, +// "Broker should prioritize jobs of user that has no in-progress jobs" +// }, +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userA", PENDING, UUID.randomUUID().toString(), oldestDate), +// createNewJob(22, UUID.randomUUID(), "userA", PENDING, null, oldestDate), +// createNewJob(33, UUID.randomUUID(), "userB", PENDING, null, LocalDateTime.now().minusHours(2))), +// 3, +// 2, +// PENDING, +// "Broker should prioritize jobs of user that has no taken jobs" +// }, +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userA", IN_PROGRESS, UUID.randomUUID().toString(), oldestDate), +// createNewJob(22, UUID.randomUUID(), "userA", PENDING, null, LocalDateTime.now().minusHours(2)), +// createNewJob(31, UUID.randomUUID(), "userB", IN_PROGRESS, null, LocalDateTime.now().minusHours(2)), +// createNewJob(32, UUID.randomUUID(), "userB", IN_PROGRESS, null, LocalDateTime.now().minusHours(2)), +// createNewJob(33, UUID.randomUUID(), "userB", PENDING, null, oldestDate)), +// 5, +// 4, +// PENDING, +// "Broker should take oldest job when there is one in-progress job to each user" +// }, +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), UUID.randomUUID().toString(), IN_PROGRESS, null, oldestDate), +// createNewJob(22, UUID.randomUUID(), UUID.randomUUID().toString(), IN_PROGRESS, null, oldestDate), +// createNewJob(33, UUID.randomUUID(), UUID.randomUUID().toString(), PENDING, null, LocalDateTime.now().minusHours(2))), +// 2, +// -1, +// PENDING, +// "Broker should not pull any job when it exceeded mso limit with count(in-progress or pending && taken) statuses" +// }, +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userId", IN_PROGRESS, UUID.randomUUID().toString(), oldestDate), +// createNewJob(22, UUID.randomUUID(), "userId", IN_PROGRESS, null, oldestDate), +// createNewJob(11, UUID.randomUUID(), "userId", IN_PROGRESS, null, LocalDateTime.now().minusHours(2)), +// createNewJob(44, UUID.randomUUID(), "userId", IN_PROGRESS, null, LocalDateTime.now().minusHours(5))), +// 20, +// 1, +// IN_PROGRESS, +// "Broker with in progress topic should pull the first in progress and not taken job by oldest date" +// }, +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userId", COMPLETED, null, oldestDate), +// createNewJob(12, UUID.randomUUID(), "userId", FAILED, null, oldestDate), +// createNewJob(13, UUID.randomUUID(), "userId", PENDING,null, oldestDate), +// createNewJob(14, UUID.randomUUID(), "userId", STOPPED,null, oldestDate), +// createNewJob(11, UUID.randomUUID(), "userId", IN_PROGRESS,null, oldestDate, DELETED),createNewJob(22, UUID.randomUUID(), "userId", IN_PROGRESS,null, oldestDate), +// createNewJob(33, UUID.randomUUID(), "userId", IN_PROGRESS,null, LocalDateTime.now().minusHours(2))), +// 20, +// 5, +// IN_PROGRESS, +// "Broker with in progress topic should pull only in-progress jobs - first in-progress job by oldest date - ignore deleted,completed, failed, pending and stopped statuses" +// }, +// {ImmutableList.of( +// createNewJob(11, UUID.randomUUID(), "userId", IN_PROGRESS, null, LocalDateTime.now()), +// createNewJob(22, UUID.randomUUID(), "userId", IN_PROGRESS, null, LocalDateTime.now().minusSeconds(1)), +// createNewJob(33, UUID.randomUUID(), "userId", IN_PROGRESS, null, LocalDateTime.now().minusSeconds(2))), +// 20, +// -1, +// IN_PROGRESS, +// "Broker with in progress topic should not pull any job if its modified date is smaller than now-interval (20 seconds)" +// } +// +// }; +// } +// +// +// @Test(dataProvider = "jobs") +// public void givenSomeJobs_pullNextJob_returnNextOrNothingAsExpected(List<JobDaoImpl> jobs, int msoLimit, int expectedIndexSelected, Job.JobStatus topic, String assertionReason) { +// JobsBrokerServiceInDatabaseImpl broker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, msoLimit, 20); +// for (JobDaoImpl job : jobs) { +// Date modifiedDate = job.getModified(); +// broker.add(job); +// setModifiedDateToJob(job.getUuid(), modifiedDate); +// } +// Optional<Job> nextJob = broker.pull(topic, UUID.randomUUID().toString()); +// boolean shouldAnyBeSelected = expectedIndexSelected >= 0; +// Assert.assertEquals(nextJob.isPresent(), shouldAnyBeSelected, assertionReason); +// if (shouldAnyBeSelected) { +// Assert.assertEquals(jobs.get(expectedIndexSelected), nextJob.get(), assertionReason); +// } +// } +// +// @DataProvider +// public Object[][] topics() { +// return Arrays.stream(Job.JobStatus.values()) +// .filter(not(t -> ImmutableList.of(PENDING, IN_PROGRESS).contains(t))) +// .map(v -> new Object[]{v}).collect(Collectors.toList()).toArray(new Object[][]{}); +// } +// +// @Test(dataProvider = "topics", expectedExceptions = GenericUncheckedException.class, expectedExceptionsMessageRegExp = "Unsupported topic.*") +// public void pullUnexpectedTopic_exceptionIsThrown(Job.JobStatus topic) { +// broker.pull(topic, UUID.randomUUID().toString()); +// } +// +// @Test(expectedExceptions = NoJobException.class) +// public void givenNonPendingJobs_getJobAsPendingTopic_verifyNothingRetrieved() { +// Stream.of(Job.JobStatus.values()) +// .filter(not(s -> s.equals(PENDING))) +// .map(s -> createMockJob("some user id", s)) +// .map(job -> newJobAsync(broker, job)) +// .map(this::waitForFutureJob) +// .collect(Collectors.toList()); +// +// waitForFutureOptionalJob(pullJobAsync(broker)); +// } +// +// @Test +// public void givenPendingAndNonPendingJobs_getJobAsPendingTopic_verifyAJobRetrieved() { +// newJobAsync(broker); // this negated the expected result of the call below +// givenNonPendingJobs_getJobAsPendingTopic_verifyNothingRetrieved(); +// } +// +// @Test(expectedExceptions = NoJobException.class) +// public void givenManyJobs_pullThemAllAndAskOneMore_verifyFinallyNothingRetrieved() { +// putAndGetALotOfJobs(broker); +// waitForFutureOptionalJob(pullJobAsync(broker)); +// } +// +// @Test(expectedExceptions = NoJobException.class) +// public void givenNoJob_requestJob_verifyNothingRetrieved() throws InterruptedException, ExecutionException, TimeoutException { +// final Future<Optional<Job>> futureOptionalJob = pullJobAsync(broker); +// assertThat("job should not be waiting yet", futureOptionalJob.get(FEW, MILLISECONDS).isPresent(), is(false)); +// waitForFutureOptionalJob(futureOptionalJob); +// } +// +// @Test(expectedExceptions = IllegalStateException.class) +// public void givenSinglePulledJob_pushBackDifferentJob_verifyPushingRejected() { +// waitForFutureJob(newJobAsync(broker)); +// waitForFutureJob(newJobAsync(broker)); +// waitForFutureOptionalJob(pullJobAsync(broker)); +// +// Job myJob = createMockJob("user id"); +// myJob.setUuid(UUID.randomUUID()); +// +// broker.pushBack(myJob); //Should fail +// } +// +// @Test +// public void givenSingleJob_pushBackModifiedJob_verifyPulledIsVeryVeryTheSame() { +// final ImmutableMap<String, Object> randomDataForMostRecentJobType = +// ImmutableMap.of("42", 42, "complex", ImmutableList.of("a", "b", "c")); +// +// waitForFutureJob(newJobAsync(broker)); +// final Job job = waitForFutureOptionalJob(pullJobAsync(broker)); +// +// job.setStatus(Job.JobStatus.PENDING); +// job.setTypeAndData(JobType.NoOp, ImmutableMap.of("good", "morning")); +// job.setTypeAndData(JobType.HttpCall, ImmutableMap.of()); +// job.setTypeAndData(JobType.ServiceInstantiation, randomDataForMostRecentJobType); +// +// broker.pushBack(job); +// final Job retrievedJob = waitForFutureOptionalJob(pullJobAsync(broker)); +// +// assertThat(JOBS_SHOULD_MATCH, retrievedJob, is(job)); +// assertThat(JOBS_SHOULD_MATCH, retrievedJob.getData(), both(equalTo(job.getData())).and(equalTo(randomDataForMostRecentJobType))); +// assertThat(JOBS_SHOULD_MATCH, jobDataReflected(retrievedJob), is(jobDataReflected(job))); +// } +// +// private static String jobDataReflected(Job job) { +// return new ReflectionToStringBuilder(job, ToStringStyle.SHORT_PREFIX_STYLE) +// .setExcludeFieldNames("created", "modified", "takenBy") +// .toString(); +// } +// +// @Test(expectedExceptions = IllegalStateException.class) +// public void givenSingleJob_pushBackTwice_verifyPushingRejected() { +// waitForFutureJob(newJobAsync(broker)); +// final Job job = waitForFutureOptionalJob(pullJobAsync(broker)); +// +// broker.pushBack(job); +// broker.pushBack(job); //Should fail +// } +// +// @Test +// public void addJob_PeekItById_verifySameJobWasPeeked() { +// String userId = UUID.randomUUID().toString(); +// Job myJob = createMockJob(userId); +// UUID uuid = broker.add(myJob); +// Job peekedJob = broker.peek(uuid); +// assertEquals("added testId is not the same as peeked TestsId", +// userId, +// peekedJob.getData().get("userId")); +// } +// +// @Test(dataProvider = "jobStatusesForSuccessDelete", expectedExceptions = NoJobException.class) +// public void givenOneJob_deleteIt_canPeekOnItButCantPull(Job.JobStatus status) { +// final Job job = waitForFutureJob(newJobAsync(broker, status)); +// broker.delete(job.getUuid()); +// assertNotNull(((JobDaoImpl) broker.peek(job.getUuid())).getDeletedAt(), "job should be deleted"); +// waitForFutureOptionalJob(pullJobAsync(broker)); +// } +// +// @DataProvider +// public static Object[][] jobStatusesForSuccessDelete() { +// return new Object[][]{ +// {PENDING}, +// {STOPPED} +// }; +// } +// +// @Test( +// dataProvider = "jobStatusesForFailedDelete", +// expectedExceptions = OperationNotAllowedException.class, +// expectedExceptionsMessageRegExp=DELETE_SERVICE_INFO_STATUS_EXCEPTION_MESSAGE +// ) +// public void deleteJob_notAllowedStatus_exceptionIsThrown(Job.JobStatus status, boolean taken) { +// final Job job = waitForFutureJob(newJobAsync(broker, createMockJob("some user id", status))); +// +// if (taken) { +// waitForFutureOptionalJob(pullJobAsync(broker)); +// } +// +// +// broker.delete(job.getUuid()); +// } +// +// @DataProvider +// public static Object[][] jobStatusesForFailedDelete() { +// return new Object[][]{ +// {PENDING, true}, +// {IN_PROGRESS, false}, +// {COMPLETED, false}, +// {PAUSE, false}, +// {FAILED, false}, +// }; +// } +// +// @Test(expectedExceptions = OperationNotAllowedException.class, expectedExceptionsMessageRegExp = DELETE_SERVICE_NOT_EXIST_EXCEPTION_MESSAGE) +// public void deleteJob_notExist_exceptionIsThrown() { +// waitForFutureJob(newJobAsync(broker, createMockJob("some user id", PENDING))); +// broker.delete(new UUID(111, 111)); +// } +// +//} diff --git a/vid-app-common/src/test/java/org/onap/vid/services/PortDetailsTranslatorTest.java b/vid-app-common/src/test/java/org/onap/vid/services/PortDetailsTranslatorTest.java new file mode 100644 index 00000000..cb9eb93d --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/services/PortDetailsTranslatorTest.java @@ -0,0 +1,283 @@ +package org.onap.vid.services; + +import com.google.common.collect.ImmutableList; +import org.codehaus.jackson.map.ObjectMapper; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.vid.aai.model.AaiGetPortMirroringSourcePorts; +import org.onap.vid.aai.model.PortDetailsTranslator; +import org.onap.vid.aai.model.RelatedTo; +import org.onap.vid.aai.model.SimpleResult; +import org.onap.vid.properties.Features; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.togglz.core.manager.FeatureManager; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.mockito.Mockito.when; + +public class PortDetailsTranslatorTest { + + private static final ObjectMapper om = new ObjectMapper(); + + @InjectMocks + private PortDetailsTranslator portDetailsTranslator = new PortDetailsTranslator(); + + @Mock + private FeatureManager featureManager; + + @BeforeMethod + public void initMocks() throws Exception { + MockitoAnnotations.initMocks(this); + when(featureManager.isActive(Features.FLAG_ADVANCED_PORTS_FILTER)).thenReturn(true); + } + + @Test + public void extractPortDetailsFromProperties_givenValidAaiResponse() throws IOException { + + final String aaiResponse = "{\n" + + " \"results\": [\n" + + " {\n" + + " \"id\": \"4876980240\",\n" + + " \"node-type\": \"l-interface\",\n" + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\",\n" + + " \"properties\": {\n" + + " \"interface-name\": \"zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\",\n" + + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\",\n" + + " \"interface-id\": \"6de7bf87-6faa-4984-9492-18d1188b3d4a\",\n" + + " \"macaddr\": \"02:6d:e7:bf:87:6f\",\n" + + " \"network-name\": \"APP-C-24595-D-T001-vprobe_int_pktmirror_net_1\",\n" + + " \"is-port-mirrored\": false,\n" + + " \"resource-version\": \"1519383879190\",\n" + + " \"in-maint\": false,\n" + + " \"is-ip-unnumbered\": false\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + AaiGetPortMirroringSourcePorts aaiGetPortMirroringSourcePorts = om.readValue(aaiResponse, AaiGetPortMirroringSourcePorts.class); + + + PortDetailsTranslator.PortDetails portDetails = PortDetailsTranslator.extractPortDetailsFromProperties(aaiGetPortMirroringSourcePorts.getResults().get(0).getProperties(), aaiResponse); + + assertThat(portDetails, is(instanceOf(PortDetailsTranslator.PortDetailsOk.class))); + + PortDetailsTranslator.PortDetailsOk portDetailsOk = (PortDetailsTranslator.PortDetailsOk) portDetails; + assertThat(portDetailsOk.getInterfaceName(), is("zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib")); + assertThat(portDetailsOk.getInterfaceId(), is("6de7bf87-6faa-4984-9492-18d1188b3d4a")); + assertThat(portDetailsOk.getIsPortMirrored(), is(false)); + } + + @Test + public void extractPortDetailsFromProperties_givenAaiResponseWithInstanceNameNull_yieldException() throws IOException { + final String aaiResponse = "{\n" + + " \"results\": [\n" + + " {\n" + + " \"id\": \"4876980240\",\n" + + " \"node-type\": \"l-interface\",\n" + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\",\n" + + " \"properties\": {\n" + + " \"interface-name\": null,\n" + + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\",\n" + + " \"interface-id\": \"6de7bf87-6faa-4984-9492-18d1188b3d4a\",\n" + + " \"macaddr\": \"02:6d:e7:bf:87:6f\",\n" + + " \"network-name\": \"APP-C-24595-D-T001-vprobe_int_pktmirror_net_1\",\n" + + " \"is-port-mirrored\": false,\n" + + " \"resource-version\": \"1519383879190\",\n" + + " \"in-maint\": false,\n" + + " \"is-ip-unnumbered\": false\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + AaiGetPortMirroringSourcePorts aaiGetPortMirroringSourcePorts = om.readValue(aaiResponse, AaiGetPortMirroringSourcePorts.class); + PortDetailsTranslator.PortDetails portDetails = PortDetailsTranslator.extractPortDetailsFromProperties(aaiGetPortMirroringSourcePorts.getResults().get(0).getProperties(),aaiResponse); + + assertThat(portDetails, is(instanceOf(PortDetailsTranslator.PortDetailsError.class))); + + PortDetailsTranslator.PortDetailsError portDetailsError = (PortDetailsTranslator.PortDetailsError) portDetails; + assertThat(portDetailsError.getErrorDescription(), is("Value of 'interface-name' is missing.")); + assertThat(portDetailsError.getRawAaiResponse(), is(aaiResponse)); + } + + @Test + public void extractPortDetailsFromProperties_givenAaiResponseWithInstanceIdNull_yieldException() throws IOException { + final String aaiResponse = "{\n" + + " \"results\": [\n" + + " {\n" + + " \"id\": \"4876980240\",\n" + + " \"node-type\": \"l-interface\",\n" + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\",\n" + + " \"properties\": {\n" + + " \"interface-name\": \"zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\",\n" + + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\",\n" + + " \"interface-id\": null,\n" + + " \"macaddr\": \"02:6d:e7:bf:87:6f\",\n" + + " \"network-name\": \"APP-C-24595-D-T001-vprobe_int_pktmirror_net_1\",\n" + + " \"is-port-mirrored\": false,\n" + + " \"resource-version\": \"1519383879190\",\n" + + " \"in-maint\": false,\n" + + " \"is-ip-unnumbered\": false\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + AaiGetPortMirroringSourcePorts aaiGetPortMirroringSourcePorts = om.readValue(aaiResponse, AaiGetPortMirroringSourcePorts.class); + PortDetailsTranslator.PortDetails portDetails = PortDetailsTranslator.extractPortDetailsFromProperties(aaiGetPortMirroringSourcePorts.getResults().get(0).getProperties(),aaiResponse); + + assertThat(portDetails, is(instanceOf(PortDetailsTranslator.PortDetailsError.class))); + + PortDetailsTranslator.PortDetailsError portDetailsError = (PortDetailsTranslator.PortDetailsError) portDetails; + assertThat(portDetailsError.getErrorDescription(), is("Value of 'interface-id' is missing.")); + assertThat(portDetailsError.getRawAaiResponse(), is(aaiResponse)); + } + + @Test + public void extractPortDetailsFromProperties_givenAaiResponseWithEmptyInstanceId_yieldException() throws IOException { + final String aaiResponse = "{\n" + + " \"results\": [\n" + + " {\n" + + " \"id\": \"4876980240\",\n" + + " \"node-type\": \"l-interface\",\n" + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\",\n" + + " \"properties\": {\n" + + " \"interface-name\": \"\",\n" + + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\",\n" + + " \"interface-id\": \"6de7bf87-6faa-4984-9492-18d1188b3d4a\",\n" + + " \"macaddr\": \"02:6d:e7:bf:87:6f\",\n" + + " \"network-name\": \"APP-C-24595-D-T001-vprobe_int_pktmirror_net_1\",\n" + + " \"is-port-mirrored\": false,\n" + + " \"resource-version\": \"1519383879190\",\n" + + " \"in-maint\": false,\n" + + " \"is-ip-unnumbered\": false\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + AaiGetPortMirroringSourcePorts aaiGetPortMirroringSourcePorts = om.readValue(aaiResponse, AaiGetPortMirroringSourcePorts.class); + PortDetailsTranslator.PortDetails portDetails = PortDetailsTranslator.extractPortDetailsFromProperties(aaiGetPortMirroringSourcePorts.getResults().get(0).getProperties(),aaiResponse); + + assertThat(portDetails, is(instanceOf(PortDetailsTranslator.PortDetailsError.class))); + + PortDetailsTranslator.PortDetailsError portDetailsError = (PortDetailsTranslator.PortDetailsError) portDetails; + assertThat(portDetailsError.getErrorDescription(), is("Value of 'interface-name' is empty.")); + assertThat(portDetailsError.getRawAaiResponse(), is(aaiResponse)); + } + + @Test + public void extractPortDetailsFromProperties_givenAaiResponseWithIsPortMirroredNull_yieldException() throws IOException { + final String aaiResponse = "{\n" + + " \"results\": [\n" + + " {\n" + + " \"id\": \"4876980240\",\n" + + " \"node-type\": \"l-interface\",\n" + + " \"url\": \"/aai/v12/cloud-infrastructure/cloud-regions/cloud-region/att-aic/rdm5b/tenants/tenant/460f35aeb53542dc9f77105066483e83/vservers/vserver/15e46e2f-4b98-4e06-9644-f0e6e35cc79a/l-interfaces/l-interface/zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\",\n" + + " \"properties\": {\n" + + " \"interface-name\": \"zrdm5bfprbVLBA005-vlbagent_aff_int_pktmirror_1_port-dr5jhyxva5ib\",\n" + + " \"selflink\": \"https://network-aic.rdm5b.cci.att.com:9696/v2.0/ports/6de7bf87-6faa-4984-9492-18d1188b3d4a\",\n" + + " \"interface-id\": \"6de7bf87-6faa-4984-9492-18d1188b3d4a\",\n" + + " \"macaddr\": \"02:6d:e7:bf:87:6f\",\n" + + " \"network-name\": \"APP-C-24595-D-T001-vprobe_int_pktmirror_net_1\",\n" + + " \"is-port-mirrored\": null,\n" + + " \"resource-version\": \"1519383879190\",\n" + + " \"in-maint\": false,\n" + + " \"is-ip-unnumbered\": false\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + AaiGetPortMirroringSourcePorts aaiGetPortMirroringSourcePorts = om.readValue(aaiResponse, AaiGetPortMirroringSourcePorts.class); + PortDetailsTranslator.PortDetails portDetails = PortDetailsTranslator.extractPortDetailsFromProperties(aaiGetPortMirroringSourcePorts.getResults().get(0).getProperties(),aaiResponse); + + assertThat(portDetails, is(instanceOf(PortDetailsTranslator.PortDetailsError.class))); + + PortDetailsTranslator.PortDetailsError portDetailsError = (PortDetailsTranslator.PortDetailsError) portDetails; + assertThat(portDetailsError.getErrorDescription(), is("Value of 'is-port-mirrored' is missing.")); + assertThat(portDetailsError.getRawAaiResponse(), is(aaiResponse)); + } + + @Test + public void getFilteredPortList_givenEmptyList_ReturnEmptyList() { + + final ImmutableList<SimpleResult> input = ImmutableList.of(); + + List<SimpleResult> result = portDetailsTranslator.getFilteredPortList(input); + assertThat("List size if different than expected", result, is(empty())); + } + + @DataProvider + public static Object[][] trueAndFalse() { + return new Object[][]{ + { Boolean.TRUE }, { Boolean.FALSE } + }; + } + + @Test(dataProvider = "trueAndFalse") + public void getFilteredPortList_givenFeatureFlagIsOff_returnAllLInterfaces(Boolean advancedPortsFilterFlag) throws IOException { + when(featureManager.isActive(Features.FLAG_ADVANCED_PORTS_FILTER)).thenReturn(advancedPortsFilterFlag); + + final String relationshipLabelSource = "org.onap.relationships.inventory.Source"; + final String nodeTypeLInterface = "l-interface"; + + SimpleResult lInterfaceWithSource = + buildSimpleResult(nodeTypeLInterface, relationshipLabelSource); + SimpleResult lInterfaceWithTwoSources = + buildSimpleResult(nodeTypeLInterface, relationshipLabelSource, relationshipLabelSource); + SimpleResult lInterfaceWithSourceAndMore = + buildSimpleResult(nodeTypeLInterface, relationshipLabelSource, "not a source"); + SimpleResult lInterfaceWithoutSource = + buildSimpleResult(nodeTypeLInterface, "not a source"); + SimpleResult lInterfaceWithoutRelations = + buildSimpleResult(nodeTypeLInterface); + SimpleResult fooTypeWithSource = + buildSimpleResult("not an l-interface", relationshipLabelSource); + SimpleResult fooTypeWithoutSource = + buildSimpleResult("not an l-interface", "not a source"); + + final ImmutableList<SimpleResult> input = ImmutableList.of( + fooTypeWithSource, fooTypeWithoutSource, + lInterfaceWithTwoSources, lInterfaceWithSourceAndMore, + lInterfaceWithoutSource, lInterfaceWithSource, + lInterfaceWithoutRelations); + + List<SimpleResult> result = portDetailsTranslator.getFilteredPortList(input); + + if (advancedPortsFilterFlag) { + assertThat("List should contain all l-interfaces with a related source", result, containsInAnyOrder( + lInterfaceWithSource, lInterfaceWithSourceAndMore, + lInterfaceWithTwoSources)); + } else { + assertThat("List should contain all l-interfaces", result, containsInAnyOrder( + lInterfaceWithSource, lInterfaceWithoutSource, + lInterfaceWithoutRelations, lInterfaceWithSourceAndMore, + lInterfaceWithTwoSources)); + } + } + + private SimpleResult buildSimpleResult(String nodeType, String... relationshipLabels) { + SimpleResult simpleResult = new SimpleResult(); + simpleResult.setNodeType(nodeType); + simpleResult.setRelatedTo(Stream.of(relationshipLabels).map(label -> + new RelatedTo("my foo id", label, "logical-link", "foo url")) + .collect(Collectors.toList()) + ); + return simpleResult; + } + +} diff --git a/vid-app-common/src/test/java/org/onap/vid/services/VidServiceImplTest.java b/vid-app-common/src/test/java/org/onap/vid/services/VidServiceImplTest.java new file mode 100644 index 00000000..7dbd622a --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/services/VidServiceImplTest.java @@ -0,0 +1,122 @@ +package org.onap.vid.services; + +import com.google.common.collect.ImmutableMap; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; +import org.onap.vid.asdc.AsdcCatalogException; +import org.onap.vid.asdc.AsdcClient; +import org.onap.vid.asdc.beans.Service; +import org.onap.vid.asdc.parser.ToscaParserImpl2; +import org.onap.vid.model.ServiceModel; +import org.onap.vid.properties.Features; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.togglz.core.manager.FeatureManager; + +import java.util.Map; +import java.util.UUID; + +import static java.util.stream.Collectors.toMap; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.*; + +public class VidServiceImplTest { + + @Mock(answer = Answers.RETURNS_MOCKS) + AsdcClient asdcClientMock; + + @Mock(answer = Answers.RETURNS_MOCKS) + ToscaParserImpl2 toscaParserMock; + + @Mock + FeatureManager featureManager; + + private final UUID uuid1 = UUID.randomUUID(); + private final UUID uuid2 = UUID.randomUUID(); + private final UUID uuid3 = UUID.randomUUID(); + private final Map<UUID, Service> pseudoServiceByUuid = ImmutableMap.of( + uuid1, mock(Service.class), + uuid2, mock(Service.class), + uuid3, mock(Service.class) + ); + + private final Map<Service, ServiceModel> pseudoModelByService = + pseudoServiceByUuid.values().stream() + .collect(toMap(service -> service, service -> mock(ServiceModel.class))); + private VidServiceImpl vidService; + + private ServiceModel expectedServiceModelForUuid(UUID uuid) { + final ServiceModel serviceModel = pseudoModelByService.get(pseudoServiceByUuid.get(uuid)); + assertThat(serviceModel, is(not(nullValue()))); + return serviceModel; + } + + @BeforeMethod + public void initMocks() throws AsdcCatalogException, SdcToscaParserException, IllegalAccessException { + MockitoAnnotations.initMocks(this); + + vidService = new VidServiceImpl(asdcClientMock, featureManager); + FieldUtils.writeField(vidService, "toscaParser", toscaParserMock, true); + + when(featureManager.isActive(Features.FLAG_SERVICE_MODEL_CACHE)).thenReturn(true); + + when(asdcClientMock.getService(any())).thenAnswer(invocation -> pseudoServiceByUuid.get(invocation.getArguments()[0])); + when(toscaParserMock.makeServiceModel(any(), any())).thenAnswer(invocation -> pseudoModelByService.get(invocation.getArguments()[1])); + } + + @Test + public void whenGetServiceMultipleTimes_asdcIsCalledOnlyOnce() throws AsdcCatalogException { + vidService.getService(uuid1.toString()); + vidService.getService(uuid1.toString()); + vidService.getService(uuid1.toString()); + + verify(asdcClientMock, times(1)).getService(uuid1); + } + + @Test + public void whenGetServiceTwiceWithResetBetween_asdcIsCalledTwice() throws AsdcCatalogException { + vidService.getService(uuid1.toString()); + vidService.invalidateServiceCache(); + vidService.getService(uuid1.toString()); + + verify(asdcClientMock, times(2)).getService(uuid1); + } + + @Test + public void cache_saves_service_model_correctly() throws AsdcCatalogException { + ServiceModel service1 = vidService.getService(uuid1.toString()); + ServiceModel service2 = vidService.getService(uuid1.toString()); + ServiceModel service3 = vidService.getService(uuid1.toString()); + + assertThat(service1, sameInstance(expectedServiceModelForUuid(uuid1))); + assertThat(service1, sameInstance(service2)); + assertThat(service1, sameInstance(service3)); + } + + @Test + public void cache_provide_correct_serviceModel() throws AsdcCatalogException { + ServiceModel service2 = vidService.getService(uuid2.toString()); + assertThat(service2, sameInstance(expectedServiceModelForUuid(uuid2))); + + ServiceModel service3 = vidService.getService(uuid3.toString()); + assertThat(service3, sameInstance(expectedServiceModelForUuid(uuid3))); + + UUID nonExisting = UUID.randomUUID(); + ServiceModel service4 = vidService.getService(nonExisting.toString()); + assertThat(service4, is(nullValue())); + } + + @Test(expectedExceptions = AsdcCatalogException.class, expectedExceptionsMessageRegExp = "someMessage") + public void whenAsdcClientThrowAsdcCatalogException_thenGetServiceAlsoThrowIt() throws AsdcCatalogException { + when(asdcClientMock.getServiceToscaModel(any())).thenThrow(new AsdcCatalogException("someMessage")); + vidService.getService(uuid1.toString()); + } + +} + |