From 6ad41e3ccd398a2721f41ad61c80b7bb03f7d127 Mon Sep 17 00:00:00 2001 From: Ittay Stern Date: Mon, 31 Dec 2018 17:21:27 +0200 Subject: Merge from ECOMP's repository Main Features -------------- - Async-Instantiation jobs mechanism major update; still WIP (package `org.onap.vid.job`) - New features in View/Edit: Activate fabric configuration; show related networks; soft delete - Support AAI service-tree traversal (`AAIServiceTree`) - In-memory cache for SDC models and certain A&AI queries (`CacheProviderWithLoadingCache`) - Upgrade TOSCA Parser and add parsing options; fix malformed TOSCA models - Resolve Cloud-Owner values for MSO - Pass X-ONAP headers to MSO Infrastructure -------------- - Remove codehaus' jackson mapper; use soley fasterxml 2.9.7 - Surefire invokes both TestNG and JUnit tests - Support Kotlin source files - AaiController2 which handles errors in a "Spring manner" - Inline generated-sources and remove jsonschema2pojo Quality -------- - Cumulative bug fixes (A&AI API, UI timeouts, and many more) - Many Sonar issues cleaned-up - Some unused classes removed - Minor changes in vid-automation project, allowing some API verification to run Hard Merges ------------ - HTTP Clients (MSO, A&AI, WebConfig, OutgoingRequestHeadersTest) - Moved `package org.onap.vid.controllers` to `controller`, without plural -- just to keep semantic sync with ECOMP. Reference commit in ECOMP: 3d1141625 Issue-ID: VID-378 Change-Id: I9c8d1e74caa41815891d441fc0760bb5f29c5788 Signed-off-by: Ittay Stern --- .../org/onap/vid/job/command/CommandUtilsTest.java | 88 ++ .../job/command/InProgressStatusCommandTest.java | 143 ---- .../job/command/InProgressStatusServiceTest.java | 83 ++ .../vid/job/command/InstanceGroupCommandTest.java | 85 ++ .../vid/job/command/JobCommandFactoryTest.java | 36 +- .../onap/vid/job/command/ResourceCommandTest.java | 303 +++++++ .../ResourceInProgressStatusCommandTest.java | 40 + .../ServiceInProgressStatusCommandTest.java | 208 +++++ .../command/ServiceInstantiationCommandTest.java | 157 ---- .../vid/job/command/WatchChildrenJobsBLTest.java | 98 +++ .../onap/vid/job/command/WatchingCommandTest.java | 77 ++ .../impl/AsyncInstantiationIntegrationTest.java | 925 +++++++++++++++++++++ .../org/onap/vid/job/impl/JobAdapterImplTest.java | 110 --- .../java/org/onap/vid/job/impl/JobAdapterTest.java | 100 +++ .../vid/job/impl/JobSchedulerInitializerTest.java | 121 --- .../java/org/onap/vid/job/impl/JobWorkerTest.java | 9 +- 16 files changed, 2047 insertions(+), 536 deletions(-) create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/CommandUtilsTest.java delete mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusCommandTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusServiceTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/InstanceGroupCommandTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/ResourceInProgressStatusCommandTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInProgressStatusCommandTest.java delete mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInstantiationCommandTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/command/WatchingCommandTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/impl/AsyncInstantiationIntegrationTest.java delete mode 100644 vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterImplTest.java create mode 100644 vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterTest.java delete mode 100644 vid-app-common/src/test/java/org/onap/vid/job/impl/JobSchedulerInitializerTest.java (limited to 'vid-app-common/src/test/java/org/onap/vid/job') diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/CommandUtilsTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/CommandUtilsTest.java new file mode 100644 index 000000000..61a54f250 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/CommandUtilsTest.java @@ -0,0 +1,88 @@ +package org.onap.vid.job.command; + +import com.google.common.collect.ImmutableMap; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.vid.asdc.AsdcCatalogException; +import org.onap.vid.model.GroupProperties; +import org.onap.vid.model.ServiceModel; +import org.onap.vid.model.VfModule; +import org.onap.vid.services.VidService; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.*; + +public class CommandUtilsTest { + + @InjectMocks + CommandUtils commandUtils; + + @Mock + VidService vidService; + + @BeforeClass + public void initMocks() { + MockitoAnnotations.initMocks(this); + } + + @AfterMethod + public void resetVidService() { + reset(vidService); + } + + @DataProvider + public static Object[][] trueAndFalse() { + return new Object[][]{ {true}, {false} }; + } + + @Test(dataProvider="trueAndFalse") + void testIsVfModelIsBaseModule(boolean isBase) throws AsdcCatalogException { + final String serviceModelUuid = UUID.randomUUID().toString(); + final String vfModuleUuid = UUID.randomUUID().toString(); + + ServiceModel mockedServiceModel = mock(ServiceModel.class); + VfModule mockedVfModule = mock(VfModule.class); + GroupProperties mockedGroupProperties = mock(GroupProperties.class); + Map vfModulesMap = ImmutableMap.of(randomAlphanumeric(10), mockedVfModule); + + when(vidService.getService(serviceModelUuid)).thenReturn(mockedServiceModel); + when(mockedServiceModel.getVfModules()).thenReturn(vfModulesMap); + when(mockedVfModule.getUuid()).thenReturn(vfModuleUuid); + when(mockedVfModule.getProperties()).thenReturn(mockedGroupProperties); + when(mockedGroupProperties.getBaseModule()).thenReturn(isBase); + + assertThat(commandUtils.isVfModuleBaseModule(serviceModelUuid, vfModuleUuid), equalTo(isBase)); + } + + @Test(expectedExceptions = AsdcCatalogException.class) + void whenCantFindModelInSdc_thenExceptionIsThrown() throws AsdcCatalogException { + String serviceModelUuid = UUID.randomUUID().toString(); + when(vidService.getService(serviceModelUuid)).thenReturn(null); + commandUtils.isVfModuleBaseModule(serviceModelUuid, "abc"); + } + + @Test(expectedExceptions = AsdcCatalogException.class) + void whenCantFindVfModuleInModel_thenExceptionIsThrown() throws AsdcCatalogException { + + String serviceModelUuid = UUID.randomUUID().toString(); + + ServiceModel mockedServiceModel = mock(ServiceModel.class); + Map emptyMap = Collections.emptyMap(); + + when(vidService.getService(serviceModelUuid)).thenReturn(mockedServiceModel); + when(mockedServiceModel.getVfModules()).thenReturn(emptyMap); + + commandUtils.isVfModuleBaseModule(serviceModelUuid, "abc"); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusCommandTest.java deleted file mode 100644 index bc623928c..000000000 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusCommandTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2018 Nokia Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.vid.job.command; - - -import io.joshworks.restclient.http.HttpResponse; -import org.mockito.Mock; -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.onap.vid.mso.MsoInterface; -import org.onap.vid.mso.rest.AsyncRequestStatus; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.onap.vid.services.AuditService; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import javax.ws.rs.ProcessingException; -import java.util.UUID; - - -import static org.assertj.core.api.Java6Assertions.assertThat; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -public class InProgressStatusCommandTest { - - @Mock - private AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic; - - @Mock - private MsoInterface msoInterface; - - @Mock - private AuditService auditService; - - @Mock - private HttpResponse msoResponse; - - @Mock - private AsyncRequestStatus asyncRequestStatus; - - @Mock - private AsyncRequestStatus.Request request; - - private UUID uuid = UUID.randomUUID(); - - private InProgressStatusCommand inProgressStatusCommand; - - @BeforeMethod - public void setUp() { - initMocks(this); - - inProgressStatusCommand = new InProgressStatusCommand(asyncInstantiationBusinessLogic, msoInterface, auditService, uuid, "sampleRequestId"); - - when(asyncInstantiationBusinessLogic.getOrchestrationRequestsPath()).thenReturn("http://localhost:8080/samplePath"); - when(msoInterface.get("http://localhost:8080/samplePath/sampleRequestId", AsyncRequestStatus.class)).thenReturn(msoResponse); - when(msoResponse.getBody()).thenReturn(asyncRequestStatus); - } - - - @Test - public void whenSOReturnsErrorShouldSetProperFailureStateAndReturnRetryCommand() { - when(msoResponse.getStatus()).thenReturn(500); - - NextCommand call = inProgressStatusCommand.call(); - - assertThat(call.getStatus()).isEqualTo(Job.JobStatus.IN_PROGRESS); - assertThat(call.getCommand()).isEqualTo(inProgressStatusCommand); - - verify(auditService).setFailedAuditStatusFromMso(uuid, "sampleRequestId", 500, asyncRequestStatus.toString()); - } - - @Test - public void shouldProperlyHandleFailedInstantiation() { - when(msoResponse.getStatus()).thenReturn(200); - when(asyncInstantiationBusinessLogic.calcStatus(asyncRequestStatus)).thenReturn(Job.JobStatus.FAILED); - asyncRequestStatus.request = request; - - NextCommand call = inProgressStatusCommand.call(); - - assertThat(call.getCommand()).isEqualTo(inProgressStatusCommand); - assertThat(call.getStatus()).isEqualTo(Job.JobStatus.FAILED); - - verify(asyncInstantiationBusinessLogic).handleFailedInstantiation(uuid); - verify(asyncInstantiationBusinessLogic).auditMsoStatus(uuid, request); - } - - @Test - public void shouldRetryCommandWithPausedState() { - when(msoResponse.getStatus()).thenReturn(200); - when(asyncInstantiationBusinessLogic.calcStatus(asyncRequestStatus)).thenReturn(Job.JobStatus.PAUSE); - asyncRequestStatus.request = request; - - NextCommand call = inProgressStatusCommand.call(); - - assertThat(call.getCommand()).isEqualTo(inProgressStatusCommand); - assertThat(call.getStatus()).isEqualTo(Job.JobStatus.IN_PROGRESS); - - verify(asyncInstantiationBusinessLogic).auditMsoStatus(uuid, request); - verify(asyncInstantiationBusinessLogic).updateServiceInfoAndAuditStatus(uuid, Job.JobStatus.PAUSE); - } - - @Test - public void shouldRetryCommandExitedWithProcessingException() { - when(msoResponse.getStatus()).thenReturn(200); - when(asyncInstantiationBusinessLogic.calcStatus(asyncRequestStatus)).thenThrow(new ProcessingException("")); - - NextCommand call = inProgressStatusCommand.call(); - - assertThat(call.getCommand()).isEqualTo(inProgressStatusCommand); - assertThat(call.getStatus()).isEqualTo(Job.JobStatus.IN_PROGRESS); - } - - @Test - public void shouldSetStoppedStatusWhenRuntimeExceptionOccurs() { - when(msoResponse.getStatus()).thenReturn(200); - when(asyncInstantiationBusinessLogic.calcStatus(asyncRequestStatus)).thenThrow(new RuntimeException()); - - NextCommand call = inProgressStatusCommand.call(); - - assertThat(call.getCommand()).isEqualTo(inProgressStatusCommand); - assertThat(call.getStatus()).isEqualTo(Job.JobStatus.STOPPED); - } -} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusServiceTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusServiceTest.java new file mode 100644 index 000000000..2e8139716 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/InProgressStatusServiceTest.java @@ -0,0 +1,83 @@ +package org.onap.vid.job.command; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.vid.job.Job; +import org.onap.vid.job.impl.JobSharedData; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.mso.RestMsoImplementation; +import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.services.AsyncInstantiationBaseTest; +import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.UUID; +import java.util.stream.Stream; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; +import static org.testng.AssertJUnit.assertEquals; + +public class InProgressStatusServiceTest { + + @Mock + private RestMsoImplementation restMso; + + @Mock + private AsyncInstantiationBusinessLogic asyncInstantiationBL; + + @InjectMocks + private InProgressStatusService inProgressStatusService; + + @BeforeClass + public void initMocks() { + MockitoAnnotations.initMocks(this); + } + + @DataProvider + public static Object[][] jobStatuses() { + return Stream.of(Job.JobStatus.values()) + .map(student -> new Object[] { student }) + .toArray(Object[][]::new); + } + + @Test(dataProvider = "jobStatuses") + public void whenGetFromMsoRequestStatus_returnItToCaller(Job.JobStatus expectedJobStatus) { + + UUID jobUuid = UUID.randomUUID(); + String userId = "mockedUserID"; + String requestId = UUID.randomUUID().toString(); + ServiceInstantiation serviceInstantiation = mock(ServiceInstantiation.class); + + when(asyncInstantiationBL.getOrchestrationRequestsPath()).thenReturn(""); + + RestObject msoResponse = mock(RestObject.class); + AsyncRequestStatus requestStatus = AsyncInstantiationBaseTest.asyncRequestStatusResponse(""); + + when(msoResponse.getStatusCode()).thenReturn(200); + when(msoResponse.get()).thenReturn(requestStatus); + when(restMso.GetForObject(contains(requestId), eq(AsyncRequestStatus.class))).thenReturn(msoResponse); + + when(asyncInstantiationBL.calcStatus(any())).thenReturn(expectedJobStatus); + + ExpiryChecker expiryChecker = mock(ExpiryChecker.class); + when(expiryChecker.isExpired(any())).thenReturn(false); + + JobSharedData sharedData = new JobSharedData(jobUuid, userId, serviceInstantiation); + Job.JobStatus actualJobStatus = inProgressStatusService.call(expiryChecker, sharedData, requestId); + assertEquals(expectedJobStatus, actualJobStatus); + + verify(asyncInstantiationBL).auditMsoStatus(eq(jobUuid), same(requestStatus.request)); + + //verify we don't update service info during this case, which shall stay in_progress + verify(asyncInstantiationBL, never()).updateServiceInfo(any(), any()); + + + } + +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/InstanceGroupCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/InstanceGroupCommandTest.java new file mode 100644 index 000000000..4cd00174a --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/InstanceGroupCommandTest.java @@ -0,0 +1,85 @@ +package org.onap.vid.job.command; + +import com.google.common.collect.ImmutableMap; +import org.apache.commons.beanutils.BeanUtils; +import org.mockito.Answers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.vid.job.impl.JobSharedData; +import org.onap.vid.model.RequestReferencesContainer; +import org.onap.vid.model.serviceInstantiation.InstanceGroup; +import org.onap.vid.mso.RestMsoImplementation; +import org.onap.vid.mso.model.ModelInfo; +import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.springframework.http.HttpMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.Optional; +import java.util.Set; + +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +public class InstanceGroupCommandTest { + + @Mock(answer = Answers.RETURNS_MOCKS) + RestMsoImplementation restMso; + + @Mock InstanceGroup instanceGroupRequest; + + @Mock(answer = Answers.RETURNS_MOCKS) + MsoResultHandlerService msoResultHandlerService; + + @Mock WatchChildrenJobsBL watchChildrenJobsBL; + + @Mock(answer = Answers.RETURNS_MOCKS) + AsyncInstantiationBusinessLogic asyncInstantiationBL; + + @Mock InProgressStatusService inProgressStatusService; + + @InjectMocks + private InstanceGroupCommand command; + + @BeforeMethod + public void initMocks() { + command = null; + MockitoAnnotations.initMocks(this); + } + + @Test + public void createMyself_callsMso() { + final ModelInfo serviceModelInfo = setRandomStrings(new ModelInfo()); + final String serviceInstanceId = "service-instance-id"; + final String userId = "ff3223"; + + command.init(new JobSharedData( + null, userId, instanceGroupRequest + ), ImmutableMap.of( + "resourceModelInfos", ImmutableMap.of("SERVICE_MODEL_INFO", serviceModelInfo), + "resourceInstancesIds", ImmutableMap.of("SERVICE_INSTANCE_ID", serviceInstanceId) + )); + + command.createMyself(); + + verify(asyncInstantiationBL).generateInstanceGroupInstantiationRequest( + same(instanceGroupRequest), eq(serviceModelInfo), eq(serviceInstanceId), eq(userId)); + verify(restMso, only()).restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty())); + + } + + private ModelInfo setRandomStrings(ModelInfo object) { + try { + Set fields = BeanUtils.describe(object).keySet(); + BeanUtils.populate(object, + fields.stream().collect(toMap(identity(), s -> randomAlphanumeric(4)))); + return object; + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/JobCommandFactoryTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/JobCommandFactoryTest.java index b51553be7..2138b77cd 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/JobCommandFactoryTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/JobCommandFactoryTest.java @@ -1,17 +1,22 @@ package org.onap.vid.job.command; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.ImmutableMap; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.vid.job.Job; +import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobCommand; import org.onap.vid.job.JobType; +import org.onap.vid.job.impl.JobSharedData; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Arrays; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; @@ -48,19 +53,48 @@ public class JobCommandFactoryTest { } + public static class MockedRequest implements JobAdapter.AsyncJobRequest { + + final public int x; + final public String y; + + @JsonCreator + public MockedRequest(@JsonProperty("x")int x, @JsonProperty("y")String y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MockedRequest)) return false; + MockedRequest that = (MockedRequest) o; + return x == that.x && + Objects.equals(y, that.y); + } + + @Override + public int hashCode() { + + return Objects.hash(x, y); + } + } + @Test(dataProvider = "jobTypes") public void givenJob_createCommandCallsTheInitAndReturnsTheInstance(JobType jobType) { final UUID uuid = UUID.randomUUID(); final Map data = ImmutableMap.of("foo", "bar"); + final JobSharedData sharedData = new JobSharedData(uuid, "userid", new MockedRequest(1,"a")); when(job.getType()).thenReturn(jobType); when(job.getUuid()).thenReturn(uuid); when(job.getData()).thenReturn(data); + when(job.getSharedData()).thenReturn(sharedData); final JobCommand command = jobCommandFactory.toCommand(job); - verify(mockCommand).init(uuid, data); + verify(mockCommand).init(sharedData, data); assertThat(command, equalTo(mockCommand)); } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java new file mode 100644 index 000000000..29be48edc --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceCommandTest.java @@ -0,0 +1,303 @@ +package org.onap.vid.job.command; + +import com.google.common.collect.ImmutableMap; +import org.jetbrains.annotations.NotNull; +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.job.Job; +import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.NextCommand; +import org.onap.vid.job.impl.JobSharedData; +import org.onap.vid.model.Action; +import org.onap.vid.model.serviceInstantiation.BaseResource; +import org.onap.vid.mso.RestMsoImplementation; +import org.springframework.http.HttpMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import javax.ws.rs.ProcessingException; +import java.util.Collections; +import java.util.Optional; +import java.util.stream.Stream; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.onap.vid.job.command.ResourceCommandKt.ACTION_PHASE; +import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE; +import static org.onap.vid.utils.Logging.getMethodCallerName; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; + +public class ResourceCommandTest { + + public static class MockCommand extends ResourceCommand { + + public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus) { + super(mock(RestMsoImplementation.class, RETURNS_MOCKS), mock(InProgressStatusService.class), mock(MsoResultHandlerService.class, RETURNS_MOCKS), mock(WatchChildrenJobsBL.class)); + + this.mockedJobStatus = mockedJobStatus; + this.mockState = mockState; + this.mockPhase = mockPhase; + if (mockState==InternalState.INITIAL) { + init(mock(JobSharedData.class), Collections.emptyMap()); + } + else { + init(mock(JobSharedData.class), ImmutableMap.of(INTERNAL_STATE, mockState.name(), ACTION_PHASE, mockPhase.name())); + } + when(this.getWatchChildrenJobsBL().cumulateJobStatus(any(), any())).thenReturn(mockedJobStatus); + } + + private final Job.JobStatus mockedJobStatus; + private final InternalState mockState; + private final Action mockPhase; + + + @NotNull + @Override + public Job.JobStatus createChildren() { + if (mockState == InternalState.CREATING_CHILDREN || (mockState == InternalState.INITIAL && mockPhase== Action.Delete)) + return mockedJobStatus; + throw (new RuntimeException("Not expected to call "+getMethodCallerName())); + } + + protected Job.JobStatus mockedStatusOrThrow(InternalState expectedState) { + if (mockState == expectedState) + return mockedJobStatus; + throw (new RuntimeException("Not expected to call "+getMethodCallerName())); + } + + protected MsoRestCallPlan mockedPlanOrThrow(InternalState expectedState) { + if (mockState == expectedState) + return new MsoRestCallPlan(HttpMethod.POST, "path", Optional.empty(), Optional.empty(), "nothing"); + throw (new RuntimeException("Not expected to call "+getMethodCallerName())); + } + + @NotNull + @Override + public MsoRestCallPlan planCreateMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId) { + return mockedPlanOrThrow(InternalState.CREATE_MYSELF); + } + + @NotNull + @Override + public MsoRestCallPlan planDeleteMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId) { + return mockedPlanOrThrow(InternalState.DELETE_MYSELF); + } + } + + public static class MockCommandTestingStateMachine extends MockCommand { + + private final JobSharedData sharedData; + + public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf) { + this(mockState, mockPhase, mockedJobStatus, mockedNeedToDeleteMySelf, false); + } + + public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf, boolean isService) { + super(mockState, mockPhase, mockedJobStatus); + this.mockedNeedToDeleteMySelf = mockedNeedToDeleteMySelf; + this.isService = isService; + this.sharedData = mock(JobSharedData.class, RETURNS_MOCKS); + } + + protected final boolean mockedNeedToDeleteMySelf; + private final boolean isService; + + @NotNull + @Override + public Job.JobStatus inProgress() { + return mockedStatusOrThrow(InternalState.IN_PROGRESS); + } + + @NotNull + @Override + public Job.JobStatus watchChildren() { + return mockedStatusOrThrow(InternalState.WATCHING); + } + + @Override + public boolean isNeedToDeleteMyself() { + return mockedNeedToDeleteMySelf; + } + + @Override + protected boolean isServiceCommand() { + return isService; + } + + @Override + public JobSharedData getSharedData() { + return sharedData; + } + } + + @DataProvider + public static Object[][] nextStateDeletePhaseProvider() { + return new Object[][]{ + {InternalState.CREATING_CHILDREN, Job.JobStatus.COMPLETED, InternalState.WATCHING}, + {InternalState.WATCHING, Job.JobStatus.COMPLETED, InternalState.DELETE_MYSELF}, + {InternalState.WATCHING, Job.JobStatus.IN_PROGRESS, InternalState.WATCHING}, + {InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.WATCHING}, + {InternalState.DELETE_MYSELF, Job.JobStatus.COMPLETED, InternalState.IN_PROGRESS}, + {InternalState.IN_PROGRESS, Job.JobStatus.COMPLETED, InternalState.TERMINAL}, + {InternalState.IN_PROGRESS, Job.JobStatus.IN_PROGRESS, InternalState.IN_PROGRESS}, + {InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.IN_PROGRESS}, + }; + } + + @Test(dataProvider = "nextStateDeletePhaseProvider") + public void whenCalcNextStateDeletePhase_expectedStateIsReturned( + InternalState internalState, Job.JobStatus jobStatus, InternalState expectedState) { + + //there is no meaning to the constructor inputs here + MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Action.Delete, Job.JobStatus.FAILED, true); + assertEquals(expectedState, underTest.calcNextStateDeletePhase(jobStatus, internalState)); + } + + @Test + public void whenNoNeedToDeleteMyself_internalStateMovesFromWatchingToTerminal() { + MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Action.Delete, Job.JobStatus.COMPLETED, false); + assertEquals(InternalState.TERMINAL, underTest.calcNextStateDeletePhase(Job.JobStatus.COMPLETED, InternalState.WATCHING)); + } + + @DataProvider + public static Object[][] testShallStopJobDataProvider() { + return new Object[][]{ + {Job.JobStatus.IN_PROGRESS, Action.None, false, false}, + {Job.JobStatus.COMPLETED_WITH_NO_ACTION, Action.None, false, false}, + {Job.JobStatus.COMPLETED, Action.None, false, false}, + {Job.JobStatus.FAILED, Action.None, false, true}, + {Job.JobStatus.COMPLETED_WITH_ERRORS, Action.None, false, true}, + {Job.JobStatus.COMPLETED_WITH_ERRORS, Action.None, true, false}, + {Job.JobStatus.FAILED, Action.None, true, false}, + {Job.JobStatus.FAILED, Action.Delete, true, true}, + {Job.JobStatus.FAILED, Action.Create, true, true}, + }; + } + + + @Test(dataProvider = "testShallStopJobDataProvider") + public void testShallStopJob(Job.JobStatus jobStatus, Action action, boolean isService, boolean expectedResult) { + //in this test, there is no meaning to constructor parameters besides isService + MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Action.Delete, Job.JobStatus.COMPLETED, false, isService); + + BaseResource mockedRequest = mock(BaseResource.class); + when(underTest.getSharedData().getRequest()).thenReturn(mockedRequest); + when(mockedRequest.getAction()).thenReturn(action); + + assertEquals(expectedResult, underTest.shallStopJob(jobStatus)); + } + + @DataProvider + public static Object[][] testCallDataProvider() { + return new Object[][]{ + {"initial state with successful creating children" ,InternalState.INITIAL, Job.JobStatus.COMPLETED, InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS}, + {"initial state with failed creating children", InternalState.INITIAL, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED}, + {"watching state with children still in progress" ,InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS}, + {"watching state with children that completed with errors" ,InternalState.WATCHING, Job.JobStatus.COMPLETED_WITH_ERRORS, null, Job.JobStatus.COMPLETED_WITH_ERRORS}, + {"watching state with children that completed with no action" ,InternalState.WATCHING, Job.JobStatus.COMPLETED_WITH_NO_ACTION, InternalState.DELETE_MYSELF, Job.JobStatus.RESOURCE_IN_PROGRESS}, + {"watching state with children that has completed" ,InternalState.WATCHING, Job.JobStatus.COMPLETED, InternalState.DELETE_MYSELF, Job.JobStatus.RESOURCE_IN_PROGRESS}, + {"mso call state that failed" ,InternalState.DELETE_MYSELF, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED}, + //TODO handle AAI get unique name state {"mso call state that still in progress" ,InternalState.DELETE_MYSELF, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED, false}, + {"mso call state that success" ,InternalState.DELETE_MYSELF, Job.JobStatus.COMPLETED, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS}, + {"in progress return in progress" ,InternalState.IN_PROGRESS, Job.JobStatus.IN_PROGRESS, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS}, + {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.PAUSE, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS}, + {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.STOPPED, null, Job.JobStatus.STOPPED}, + {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED}, + {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.COMPLETED, null, Job.JobStatus.COMPLETED}, + + }; + } + + @Test(dataProvider = "testCallDataProvider") + public void whenCallCommandWithDeletePhase_nextJobStatusAndInternalStateAreAsExpected( + String description, InternalState internalState, Job.JobStatus currentStateResult, + InternalState expectedNextState, Job.JobStatus expectedNextStatus) { + + MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(internalState, Action.Delete, currentStateResult, true); + NextCommand nextCommand = underTest.call(); + assertEquals(expectedNextStatus, nextCommand.getStatus()); + + //expectedNextState == null means nextCommand has no real command + if (expectedNextState!=null) { + assertEquals(expectedNextState, (nextCommand.getCommand().getData().get(INTERNAL_STATE))); + assertFalse(nextCommand.getStatus().isFinal()); + } + else { + assertNull(nextCommand.getCommand()); + assertTrue(nextCommand.getStatus().isFinal()); + } + } + + @Test(expectedExceptions = IllegalStateException.class) + public void whenCommandInUnMappedState_exceptionIsThrown() { + MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Action.Delete, Job.JobStatus.COMPLETED, true); + underTest.call(); + } + + @DataProvider + public static Object[][] InProgressDataProvider() { + return Stream.of(Job.JobStatus.values()) + .map(status -> new Object[] { status }) + .toArray(Object[][]::new); + } + + @Test(dataProvider = "InProgressDataProvider") + public void whenGetResultFromMso_InProgressReturnThem(Job.JobStatus mockedJobStatus) { + Job.JobStatus expectedJobStatus = (mockedJobStatus== Job.JobStatus.PAUSE) ? Job.JobStatus.IN_PROGRESS : mockedJobStatus; + MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Action.Delete, mockedJobStatus); + when(underTest.getInProgressStatusService().call(any(), any(), any())).thenReturn(mockedJobStatus); + assertEquals(expectedJobStatus, underTest.inProgress()); + } + + @DataProvider + public static Object[][] InProgressExceptionsDataProvider() { + return new Object[][]{ + {new ProcessingException(""), Job.JobStatus.IN_PROGRESS}, + {new InProgressStatusService.BadResponseFromMso(null), Job.JobStatus.IN_PROGRESS}, + {new GenericUncheckedException(""),Job.JobStatus.STOPPED } + }; + } + + @Test(dataProvider = "InProgressExceptionsDataProvider") + public void whenInProgressStatusServiceThrowException_InProgressReturnStatus(Exception exception, Job.JobStatus expectedJobStatus) { + MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Action.Delete, expectedJobStatus); + when(underTest.getInProgressStatusService().call(any(), any(), any())).thenThrow(exception); + assertEquals(expectedJobStatus, underTest.inProgress()); + } + + @DataProvider + public static Object[][] testIsNeedToDeleteMySelfDataProvider() { + return Stream.of(Action.values()) + .map(status -> new Object[] { status }) + .toArray(Object[][]::new); + } + + @Test(dataProvider = "testIsNeedToDeleteMySelfDataProvider") + public void testIsNeedToDeleteMySelf(Action action) { + boolean expectedResult = (action== Action.Delete); + MockCommand underTest = new MockCommand(InternalState.DELETE_MYSELF, Action.Delete, Job.JobStatus.IN_PROGRESS); + BaseResource mockedBaseResource = mock(BaseResource.class); + when(underTest.getSharedData().getRequest()).thenReturn(mockedBaseResource); + when(mockedBaseResource.getAction()).thenReturn(action); + assertEquals(expectedResult, underTest.isNeedToDeleteMyself()); + } + + @DataProvider + public static Object[][] testWatchingDataProvider() { + return new Object[][]{ + {"all children final, no failed child ", Job.JobStatus.COMPLETED, Job.JobStatus.COMPLETED}, + {"all children final, there is failed child ", Job.JobStatus.COMPLETED_WITH_ERRORS, Job.JobStatus.COMPLETED_WITH_ERRORS}, + {"not all children final", Job.JobStatus.IN_PROGRESS, Job.JobStatus.IN_PROGRESS}, + }; + } + + @Test(dataProvider = "testWatchingDataProvider") + public void testWatching(String desc, Job.JobStatus childrenJobsStatus, Job.JobStatus expectedJobStatus) { + MockCommand underTest = new MockCommand(InternalState.WATCHING, Action.Delete, Job.JobStatus.IN_PROGRESS); + when(underTest.getWatchChildrenJobsBL().retrieveChildrenJobsStatus(any())).thenReturn(childrenJobsStatus); + assertEquals(expectedJobStatus, underTest.watchChildren()); + } + +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceInProgressStatusCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceInProgressStatusCommandTest.java new file mode 100644 index 000000000..9ec49a2e5 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/ResourceInProgressStatusCommandTest.java @@ -0,0 +1,40 @@ +package org.onap.vid.job.command; + +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; +import org.onap.vid.job.Job; +import org.onap.vid.job.NextCommand; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + + +public class ResourceInProgressStatusCommandTest { + + @InjectMocks + private ResourceInProgressStatusCommand commandUnderTest = new ResourceInProgressStatusCommand(); + + @BeforeMethod + public void initMocks() { + MockitoAnnotations.initMocks(this); + } + + @DataProvider + public static Object[][] givenStatusToExpectedStatus() { + return new Object[][]{ + {Job.JobStatus.IN_PROGRESS, Job.JobStatus.IN_PROGRESS}, + {Job.JobStatus.FAILED, Job.JobStatus.FAILED}, + {Job.JobStatus.COMPLETED, Job.JobStatus.COMPLETED} + }; + } + + @Test(dataProvider = "givenStatusToExpectedStatus") + public void whenGetStatusFromMso_returnExpectedNextCommand(Job.JobStatus jobStatus, Job.JobStatus expectedNextStatus) { + NextCommand nextCommand = commandUnderTest.processJobStatus(jobStatus); + assertThat(nextCommand.getStatus(), is(expectedNextStatus)); + assertThat(nextCommand.getCommand(), is(commandUnderTest)); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInProgressStatusCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInProgressStatusCommandTest.java new file mode 100644 index 000000000..bfda6cf34 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInProgressStatusCommandTest.java @@ -0,0 +1,208 @@ +package org.onap.vid.job.command; + +import com.google.common.collect.ImmutableMap; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.job.*; +import org.onap.vid.job.impl.JobSharedData; +import org.onap.vid.model.serviceInstantiation.Network; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.model.serviceInstantiation.Vnf; +import org.onap.vid.mso.model.ModelInfo; +import org.onap.vid.properties.Features; +import org.onap.vid.properties.VidProperties; +import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.springframework.core.env.Environment; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.togglz.core.manager.FeatureManager; + +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.core.Is.is; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.*; +import static org.onap.vid.job.Job.JobStatus.*; + +public class ServiceInProgressStatusCommandTest { + + + @Mock + private AsyncInstantiationBusinessLogic asyncInstantiationBL; + + @Mock + private JobsBrokerService jobsBrokerService; + + @Mock + private JobAdapter jobAdapter; + + @Mock + private FeatureManager featureManager; + + @Mock + private JobSharedData sharedData; + + @Mock + private Environment environment; + + @Mock + private ServiceInstantiation request; + + @Mock + private InProgressStatusService inProgressStatusService; + + @InjectMocks + private ServiceInProgressStatusCommand command = new ServiceInProgressStatusCommand(); + + @DataProvider + public static Object[][] isNeedToCreateChildJobsDataProvider() { + return new Object[][]{ + {new TreeMap() , true, true, false}, + {null , true, true, false}, + {ImmutableMap.of("a",mock(Vnf.class)), false, true, false}, + {ImmutableMap.of("a",mock(Vnf.class)), true, false, false}, + {ImmutableMap.of("a",mock(Vnf.class)), true, true, true}, + }; + } + + @DataProvider + public static Object[][] processJobStatusData() { + return new Object[][]{ + /* {MSO jobStatus, jobStartTime, isNeedToCreateChildJobs(), property vid.job.max.hoursInProgress, expected nextCommand.getStatus() } */ + {IN_PROGRESS, false, IN_PROGRESS}, + {FAILED, false, FAILED}, + {PAUSE, false, IN_PROGRESS}, + {COMPLETED, false, COMPLETED}, + {COMPLETED, true, IN_PROGRESS}, + {RESOURCE_IN_PROGRESS, false, RESOURCE_IN_PROGRESS}, + {PENDING, false, PENDING}, + {STOPPED, false, STOPPED}, + {COMPLETED_WITH_ERRORS, false, COMPLETED_WITH_ERRORS}, + {CREATING, false, CREATING} + }; + } + + @DataProvider + public static Object[][] isExpiredJobStatusData() { + return new Object[][]{ + {ZonedDateTime.now(), "24", false}, + {getTimeNowMinus(2), "1", true}, + {getTimeNowMinus(24), "24", true}, + {getTimeNowMinus(2), "0", false}, + {getTimeNowMinus(2), "-1", false}, + {getTimeNowMinus(2), "", false}, + {getTimeNowMinus(2), "a", false} + }; + } + + private static ZonedDateTime getTimeNowMinus(int hoursAgo) { + return ZonedDateTime.ofInstant(Instant.now().minus(hoursAgo, ChronoUnit.HOURS), ZoneOffset.UTC); + } + + @BeforeMethod + public void initMocks() { + MockitoAnnotations.initMocks(this); + } + + @Test(dataProvider = "isNeedToCreateChildJobsDataProvider" ) + public void testIsNeedToCreateChildJobs(Map serviceVnfs, boolean isALaCarte, + boolean isFeatureEnabled, boolean expected) { + MockitoAnnotations.initMocks(this); + ServiceInstantiation serviceInstantiation = mock(ServiceInstantiation.class); + when(serviceInstantiation.getVnfs()).thenReturn(serviceVnfs); + when(serviceInstantiation.isALaCarte()).thenReturn(isALaCarte); + when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(isFeatureEnabled); + assertThat(command.isNeedToCreateChildJobs(serviceInstantiation), is(expected)); + } + + @Test + public void whenGetFromMsoCompletedAndALaCarte_generateNewJobsForVnfs() { + UUID uuid = UUID.randomUUID(); + String userId = "mockedUserID"; + Vnf vnf1 = mock(Vnf.class); + Vnf vnf2 = mock(Vnf.class); + Network network1 = mock(Network.class); + ServiceInstantiation serviceInstantiation = mock(ServiceInstantiation.class); + when(serviceInstantiation.getVnfs()).thenReturn(ImmutableMap.of("a", vnf1, "b", vnf2)); + when(serviceInstantiation.getNetworks()).thenReturn(ImmutableMap.of("c", network1)); + when(serviceInstantiation.isALaCarte()).thenReturn(true); + when(serviceInstantiation.getModelInfo()).thenReturn(new ModelInfo()); + + when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true); + + UUID uuid1 = UUID.fromString("12345678-1234-1234-1234-123456789012"); + UUID uuid2 = UUID.fromString("12345678-1234-1234-1234-123456789013"); + UUID uuid3 = UUID.fromString("12345678-1234-1234-1234-123456789014"); + when(jobsBrokerService.add(any())).thenReturn(uuid1).thenReturn(uuid2).thenReturn(uuid3); + + JobSharedData sharedData = new JobSharedData(uuid, userId, serviceInstantiation); + command.init(sharedData, "", ""); + when(inProgressStatusService.call(any(), eq(sharedData), any())).thenReturn(Job.JobStatus.COMPLETED); + NextCommand nextCommand = command.call(); + + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(JobAdapter.AsyncJobRequest.class); + verify(jobAdapter, times(2)).createChildJob(eq(JobType.VnfInstantiation), eq(Job.JobStatus.CREATING), argumentCaptor.capture(), eq(sharedData), any()); + verify(jobAdapter, times(1)).createChildJob(eq(JobType.NetworkInstantiation), eq(Job.JobStatus.CREATING), argumentCaptor.capture(), eq(sharedData), any()); + assertThat(argumentCaptor.getAllValues(), containsInAnyOrder(vnf1, vnf2, network1)); + + verify(jobsBrokerService, times(3)).add(any()); + + //verify we don't update service info during this case, which shall stay in_progress + verify(asyncInstantiationBL, never()).updateServiceInfo(any(), any()); + + assertThat(nextCommand.getStatus(), is(Job.JobStatus.IN_PROGRESS)); + assertThat(nextCommand.getCommand().getType(), is(new WatchingCommand().getType())); + assertThat(nextCommand.getCommand().getData().get("childrenJobs"), is(Arrays.asList(uuid1.toString(), uuid2.toString(), uuid3.toString()))); + assertThat(nextCommand.getCommand().getData().get("isService"), is(true)); + } + + @Test(dataProvider = "processJobStatusData") + public void processJobStatusTest(Job.JobStatus jobStatus, boolean isNeedToCreateChildJobs, Job.JobStatus expectedStatus) { + + when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true); + // All mocks under are used for isNeedToCreateChildJobs=true case + when(sharedData.getRequest()).thenReturn(request); + when(request.isALaCarte()).thenReturn(true); + Map vnfs = mock(Map.class); + ModelInfo modelInfo = mock(ModelInfo.class); + + // if vnfs.isEmpty -> isNeedToCreateChildJobs will return false + when(vnfs.isEmpty()).thenReturn(!isNeedToCreateChildJobs); + + when(request.getVnfs()).thenReturn(vnfs); + when(request.getModelInfo()).thenReturn(modelInfo); + command.instanceId = "MockInstId"; + + NextCommand nextCommand = command.processJobStatus(jobStatus); + Assert.assertEquals(nextCommand.getStatus(), expectedStatus); + if (isNeedToCreateChildJobs) { + Assert.assertEquals(nextCommand.getCommand().getClass(), WatchingCommand.class); + } else { + Assert.assertEquals(nextCommand.getCommand(), command); + } + } + + @Test(dataProvider = "isExpiredJobStatusData") + public void isExpiredJobStatusTest(ZonedDateTime jobStartTime, String configValue, boolean expectedResult) { + SystemProperties systemProperties = new SystemProperties(); + systemProperties.setEnvironment(environment); + when(environment.getRequiredProperty(VidProperties.VID_JOB_MAX_HOURS_IN_PROGRESS)).thenReturn(configValue); + when(environment.containsProperty(VidProperties.VID_JOB_MAX_HOURS_IN_PROGRESS)).thenReturn(true); + Assert.assertEquals(command.getExpiryChecker().isExpired(jobStartTime), expectedResult); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInstantiationCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInstantiationCommandTest.java deleted file mode 100644 index e7ab4f098..000000000 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/ServiceInstantiationCommandTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2018 Nokia Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.vid.job.command; - - -import io.joshworks.restclient.http.HttpResponse; -import org.mockito.Mock; -import org.onap.vid.aai.AaiResponse; -import org.onap.vid.aai.exceptions.InvalidAAIResponseException; -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.domain.mso.RequestReferences; -import org.onap.vid.exceptions.MaxRetriesException; -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.onap.vid.model.RequestReferencesContainer; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.mso.MsoInterface; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.onap.vid.services.AuditService; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.UUID; - -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -public class ServiceInstantiationCommandTest { - @Mock - private AsyncInstantiationBusinessLogic asyncInstantiationBusinessLogic; - - @Mock - private MsoInterface msoInterface; - - @Mock - private AuditService auditService; - - @Mock - private ServiceInstantiation serviceInstantiation; - - @Mock - private HttpResponse msoResponse; - - @Mock - private RequestDetailsWrapper requestDetailsWrapper; - - @Mock - private AaiResponse aaiResponse; - - @Mock - private RequestReferencesContainer requestReferencesContainer; - - - private UUID uuid = UUID.randomUUID(); - - - private ServiceInstantiationCommand serviceInstantiationCommand; - - @BeforeMethod - public void setUp() { - initMocks(this); - serviceInstantiationCommand = new ServiceInstantiationCommand(asyncInstantiationBusinessLogic, auditService, msoInterface, uuid, serviceInstantiation, "sampleUserId"); - } - - - @Test - public void shouldProperlyHandleMaxRetriesException() { - when(asyncInstantiationBusinessLogic.generateServiceInstantiationRequest(uuid, serviceInstantiation, "sampleUserId")).thenThrow(new MaxRetriesException("", 2)); - - NextCommand call = serviceInstantiationCommand.call(); - - assertThat(call.getCommand(), is(nullValue())); - assertThat(call.getStatus(), is(equalTo(Job.JobStatus.FAILED))); - - verify(asyncInstantiationBusinessLogic).handleFailedInstantiation(uuid); - } - - @Test - public void shouldProperlyHandleInvalidAAIResponseException() { - doThrow(new InvalidAAIResponseException(aaiResponse)).when(asyncInstantiationBusinessLogic).generateServiceInstantiationRequest(uuid, serviceInstantiation, "sampleUserId"); - - NextCommand call = serviceInstantiationCommand.call(); - - assertThat(call.getCommand(), is(serviceInstantiationCommand)); - assertThat(call.getStatus(), is(equalTo(Job.JobStatus.IN_PROGRESS))); - } - - - @Test - public void shouldProperlyHandleInvalidSOResponse() { - when(asyncInstantiationBusinessLogic.generateServiceInstantiationRequest(uuid, serviceInstantiation, "sampleUserId")).thenReturn(requestDetailsWrapper); - when(asyncInstantiationBusinessLogic.getServiceInstantiationPath(serviceInstantiation)).thenReturn("samplePath"); - when(msoInterface.post("samplePath", requestDetailsWrapper, RequestReferencesContainer.class)).thenReturn(msoResponse); - when(msoResponse.getStatus()).thenReturn(500); - when(msoResponse.getBody()).thenReturn(requestReferencesContainer); - - NextCommand call = serviceInstantiationCommand.call(); - - assertThat(call.getCommand(), is(nullValue())); - assertThat(call.getStatus(), is(equalTo(Job.JobStatus.FAILED))); - - verify(auditService).setFailedAuditStatusFromMso(uuid, null, 500, requestReferencesContainer.toString()); - } - - - @Test - public void shouldProperlyUpdateServiceStatusAndReturnInProgressCommand() { - RequestReferences requestReferences = createRequestReferences(); - - when(asyncInstantiationBusinessLogic.generateServiceInstantiationRequest(uuid, serviceInstantiation, "sampleUserId")).thenReturn(requestDetailsWrapper); - when(asyncInstantiationBusinessLogic.getServiceInstantiationPath(serviceInstantiation)).thenReturn("samplePath"); - when(msoInterface.post("samplePath", requestDetailsWrapper, RequestReferencesContainer.class)).thenReturn(msoResponse); - when(msoResponse.getStatus()).thenReturn(200); - when(msoResponse.getBody()).thenReturn(requestReferencesContainer); - when(requestReferencesContainer.getRequestReferences()).thenReturn(requestReferences); - - - NextCommand call = serviceInstantiationCommand.call(); - - assertThat(call.getCommand(), instanceOf(InProgressStatusCommand.class)); - assertThat(call.getStatus(), is(equalTo(Job.JobStatus.IN_PROGRESS))); - - } - - private RequestReferences createRequestReferences() { - RequestReferences requestReferences = new RequestReferences(); - requestReferences.setInstanceId("sampleInstanceId"); - requestReferences.setRequestId("sampleRequestId"); - return requestReferences; - } -} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java new file mode 100644 index 000000000..98524c7db --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java @@ -0,0 +1,98 @@ +package org.onap.vid.job.command; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.portalsdk.core.service.DataAccessService; +import org.onap.vid.job.Job.JobStatus; +import org.onap.vid.job.impl.JobDaoImpl; +import org.onap.vid.utils.DaoUtils; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.when; +import static org.testng.AssertJUnit.assertEquals; + +public class WatchChildrenJobsBLTest { + @Mock + private DataAccessService dataAccessService; + + @InjectMocks + private WatchChildrenJobsBL watchChildrenJobsBL; + + @BeforeClass + public void initMocks() { + MockitoAnnotations.initMocks(this); + } + + public static Object[][] dataProviderForChildrenStatusOnly() { + return new Object[][]{ + {Arrays.asList(JobStatus.STOPPED, JobStatus.COMPLETED_WITH_NO_ACTION, JobStatus.COMPLETED), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(JobStatus.COMPLETED, JobStatus.FAILED, JobStatus.COMPLETED_WITH_NO_ACTION), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(null, JobStatus.COMPLETED), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(null, JobStatus.IN_PROGRESS), JobStatus.IN_PROGRESS}, + {Arrays.asList(null, JobStatus.FAILED), JobStatus.FAILED}, + {new ArrayList<>(), JobStatus.COMPLETED_WITH_NO_ACTION} + }; + } + + @DataProvider + public static Object[][] childrenStatusDataProvider() { + + List result = new ArrayList<>(); + result.addAll(Arrays.asList(dataProviderForChildrenStatusOnly())); + result.addAll(Arrays.asList(inputsStatusAndExpectedOutputDataProvider())); + return result.toArray(new Object[result.size()][]); + } + + @DataProvider + public static Object[][] inputsStatusAndExpectedOutputDataProvider() { + return new Object[][]{ + {Arrays.asList(JobStatus.COMPLETED, JobStatus.COMPLETED), JobStatus.COMPLETED}, + {Arrays.asList(JobStatus.COMPLETED, JobStatus.COMPLETED_WITH_NO_ACTION), JobStatus.COMPLETED}, + {Arrays.asList(JobStatus.FAILED, JobStatus.COMPLETED_WITH_NO_ACTION), JobStatus.FAILED}, + {Arrays.asList(JobStatus.FAILED, JobStatus.COMPLETED), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(JobStatus.RESOURCE_IN_PROGRESS, JobStatus.FAILED), JobStatus.IN_PROGRESS}, + {Arrays.asList(JobStatus.PAUSE, JobStatus.FAILED), JobStatus.IN_PROGRESS}, + {Arrays.asList(JobStatus.PENDING, JobStatus.FAILED), JobStatus.IN_PROGRESS}, + {Arrays.asList(JobStatus.IN_PROGRESS, JobStatus.COMPLETED), JobStatus.IN_PROGRESS}, + {Arrays.asList(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS), JobStatus.IN_PROGRESS}, + {Arrays.asList(JobStatus.COMPLETED, JobStatus.COMPLETED_WITH_ERRORS), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED_WITH_ERRORS), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED_WITH_NO_ACTION), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(JobStatus.COMPLETED_WITH_NO_ACTION, JobStatus.COMPLETED_WITH_NO_ACTION), JobStatus.COMPLETED_WITH_NO_ACTION}, + + + }; + } + + @Test(dataProvider = "childrenStatusDataProvider") + public void whenRetrieveListOfChildrenWithStatues_thenAccumulatedChildrenStatusAsExpected(List childJobs, JobStatus expectedChildrenJobsStatus) { + //init sql result mock + List mockChildren = childJobs.stream().map(st -> { + JobDaoImpl job = new JobDaoImpl(); + job.setUuid(UUID.randomUUID()); + job.setStatus(st); + return job; + }).collect(Collectors.toList()); + when(dataAccessService.getList(eq(JobDaoImpl.class), anyString(), any(), eq(DaoUtils.getPropsMap()))) + .thenReturn(mockChildren); + + List uuids = mockChildren.stream().map(job -> job.getUuid().toString()).collect(Collectors.toList()); + assertEquals(expectedChildrenJobsStatus, watchChildrenJobsBL.retrieveChildrenJobsStatus(uuids)); + } + + @Test(dataProvider = "inputsStatusAndExpectedOutputDataProvider") + public void whenCumulate2JobStatus_thenResultAsExpected(List jobs, JobStatus expectedChildrenJobsStatus) { + assertEquals(expectedChildrenJobsStatus, watchChildrenJobsBL.cumulateJobStatus(jobs.get(0), jobs.get(1))); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/WatchingCommandTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/WatchingCommandTest.java new file mode 100644 index 000000000..f47a18d5f --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/WatchingCommandTest.java @@ -0,0 +1,77 @@ +package org.onap.vid.job.command; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.portalsdk.core.service.DataAccessService; +import org.onap.vid.job.Job; +import org.onap.vid.job.NextCommand; +import org.onap.vid.job.impl.JobSharedData; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.UUID; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.*; + +public class WatchingCommandTest { + + @Mock + private AsyncInstantiationBusinessLogic asyncInstantiationBL; + + @Mock + private DataAccessService dataAccessService; + + @Mock + private WatchChildrenJobsBL watchChildrenJobsBL; + + @InjectMocks + private WatchingCommand watchingCommand = new WatchingCommand(); + + + + @BeforeClass + public void initMocks() { + MockitoAnnotations.initMocks(this); + } + + @DataProvider + public static Object[][] testWatchingDataProvider() { + return new Object[][]{ + {"all children final, no failed child, is service", Job.JobStatus.COMPLETED, true, Job.JobStatus.COMPLETED}, + {"all children final, there is failed child, is service", Job.JobStatus.COMPLETED_WITH_ERRORS, true, Job.JobStatus.COMPLETED_WITH_ERRORS}, + {"not all children final, is service", Job.JobStatus.IN_PROGRESS, true, Job.JobStatus.IN_PROGRESS}, + {"all children final, no failed child, not service", Job.JobStatus.COMPLETED, false, Job.JobStatus.COMPLETED}, + {"all children final, there is failed child, not service", Job.JobStatus.COMPLETED_WITH_ERRORS, false, Job.JobStatus.COMPLETED_WITH_ERRORS}, + {"not all children final, not service", Job.JobStatus.IN_PROGRESS, false, Job.JobStatus.RESOURCE_IN_PROGRESS}, + }; + } + + + + @Test(dataProvider = "testWatchingDataProvider") + public void whenGetChildrenStatus_thenJobStatusAsExpected(String desc, Job.JobStatus childrenComulativeStatus, boolean isService, Job.JobStatus expectedCommandStatus) { + UUID jobUUID = UUID.randomUUID(); + JobSharedData sharedData = new JobSharedData(jobUUID, "mockedUserID", mock(ServiceInstantiation.class)); + List uuids = mock(List.class); + watchingCommand.init(sharedData, uuids, isService); + when(watchChildrenJobsBL.retrieveChildrenJobsStatus(eq(uuids))).thenReturn(childrenComulativeStatus); + when(watchChildrenJobsBL.cumulateJobStatus(eq(childrenComulativeStatus),eq(Job.JobStatus.COMPLETED))).thenReturn(childrenComulativeStatus); + + //execute command and verify + NextCommand nextCommand = watchingCommand.call(); + assertThat(nextCommand.getStatus(), is(expectedCommandStatus)); + if (!expectedCommandStatus.equals(Job.JobStatus.IN_PROGRESS) && isService) { + verify(asyncInstantiationBL).updateServiceInfoAndAuditStatus(jobUUID, expectedCommandStatus); + } else { + verify(asyncInstantiationBL, never()).updateServiceInfoAndAuditStatus(jobUUID, expectedCommandStatus); + } + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/impl/AsyncInstantiationIntegrationTest.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/AsyncInstantiationIntegrationTest.java new file mode 100644 index 000000000..f7f83bdfe --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/impl/AsyncInstantiationIntegrationTest.java @@ -0,0 +1,925 @@ +package org.onap.vid.job.impl; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import org.apache.commons.lang3.StringUtils; +import org.mockito.Mockito; +import org.onap.portalsdk.core.service.DataAccessService; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.asdc.AsdcCatalogException; +import org.onap.vid.config.DataSourceConfig; +import org.onap.vid.config.JobCommandsConfigWithMockedMso; +import org.onap.vid.config.MockedAaiClientAndFeatureManagerConfig; +import org.onap.vid.job.Job; +import org.onap.vid.job.Job.JobStatus; +import org.onap.vid.job.JobType; +import org.onap.vid.job.JobsBrokerService; +import org.onap.vid.job.command.CommandUtils; +import org.onap.vid.job.command.InternalState; +import org.onap.vid.model.Action; +import org.onap.vid.model.NameCounter; +import org.onap.vid.model.RequestReferencesContainer; +import org.onap.vid.model.ServiceInfo; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.mso.RestMsoImplementation; +import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.model.RequestReferences; +import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.properties.Features; +import org.onap.vid.services.AsyncInstantiationBaseTest; +import org.onap.vid.services.AsyncInstantiationBusinessLogic; +import org.onap.vid.utils.DaoUtils; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.togglz.core.manager.FeatureManager; + +import javax.inject.Inject; +import javax.ws.rs.ProcessingException; +import java.lang.reflect.Method; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.*; +import static net.javacrumbs.jsonunit.JsonMatchers.jsonPartEquals; +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.core.Every.everyItem; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.endsWith; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; +import static org.onap.vid.job.Job.JobStatus.*; +import static org.onap.vid.model.JobAuditStatus.SourceStatus.MSO; +import static org.onap.vid.model.JobAuditStatus.SourceStatus.VID; +import static org.testng.AssertJUnit.*; + +//it's more like integration test than UT +//But it's very hard to test in API test so I use UT +@ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, MockedAaiClientAndFeatureManagerConfig.class, JobCommandsConfigWithMockedMso.class}) +public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTest { + + private static final String FAILED_STR = "FAILED"; + private static final String COMPLETE_STR = "COMPLETE"; + private static final String IN_PROGRESS_STR = "IN_PROGRESS"; + private static final String REQUESTED = "REQUESTED"; + private static final String PENDING_MANUAL_TASK = "PENDING_MANUAL_TASK"; + public static final String RAW_DATA_FROM_MSO = "RAW DATA FROM MSO"; + private static String USER_ID = "123"; + public static String REQUEST_ID = UUID.randomUUID().toString(); + public static String SERVICE_INSTANCE_ID = UUID.randomUUID().toString(); + + @Inject + private JobsBrokerService jobsBrokerService; + + @Inject + private JobWorker jobWorker; + + @Inject + private FeatureManager featureManager; + + @Inject + private AsyncInstantiationBusinessLogic asyncInstantiationBL; + + @Inject + private RestMsoImplementation restMso; + + @Inject + private DataAccessService dataAccessService; + + @Inject + private CommandUtils commandUtils; + + @BeforeClass + void initServicesInfoService() { + createInstanceParamsMaps(); + } + + @BeforeMethod + void clearDb() { + dataAccessService.deleteDomainObjects(ServiceInfo.class, "1=1", DaoUtils.getPropsMap()); + dataAccessService.deleteDomainObjects(JobDaoImpl.class, "1=1", DaoUtils.getPropsMap()); + dataAccessService.deleteDomainObjects(NameCounter.class, "1=1", DaoUtils.getPropsMap()); + } + + @BeforeMethod + void defineMocks() { + mockAaiClientAnyNameFree(); + } + + //@Test + public void whenPushNewBulk_thenAllServicesAreInPending() { + + pushMacroBulk(); + List serviceInfoList = asyncInstantiationBL.getAllServicesInfo(); + assertThat( serviceInfoList, everyItem(hasProperty("jobStatus", is(PENDING)))); + } + + private List pushMacroBulk() { + ServiceInstantiation serviceInstantiation = generateMockMacroServiceInstantiationPayload(false, + createVnfList(instanceParamsMapWithoutParams, Collections.EMPTY_LIST, true), + 3, true,PROJECT_NAME, true); + return asyncInstantiationBL.pushBulkJob(serviceInstantiation, USER_ID); + } + + private UUID pushALaCarteWithVnf() { + ServiceInstantiation serviceInstantiation = generateALaCarteWithVnfsServiceInstantiationPayload(); + List uuids = asyncInstantiationBL.pushBulkJob(serviceInstantiation, USER_ID); + assertThat(uuids, hasSize(1)); + return uuids.get(0); + } + + private UUID pushALaCarteUpdateWithGroups() { + ServiceInstantiation serviceInstantiation = generateALaCarteUpdateWith1ExistingGroup2NewGroupsPayload(); + List uuids = asyncInstantiationBL.pushBulkJob(serviceInstantiation, USER_ID); + assertThat(uuids, hasSize(1)); + return uuids.get(0); + } + + public static RestObject createResponse(int statusCode) { + return createResponse(statusCode, SERVICE_INSTANCE_ID, REQUEST_ID); + } + + public static RestObject createResponse(int statusCode, String instanceId, String requestId) { + RequestReferences requestReferences = new RequestReferences(); + requestReferences.setRequestId(requestId); + requestReferences.setInstanceId(instanceId); + RestObject restObject = new RestObject<>(); + restObject.set(new RequestReferencesContainer(requestReferences)); + restObject.setStatusCode(statusCode); + restObject.setRaw(RAW_DATA_FROM_MSO); + return restObject; + } + + ImmutableList statusesToStrings(JobStatus... jobStatuses) { + return Stream.of(jobStatuses).map( + Enum::toString).collect(ImmutableList.toImmutableList()); + } + + /* + Make sure service state is in progress once request has sent to MSO + Make sure service state is in progress once request has sent to MSO and MSO status is in_progress + Make sure service state is Failed once we got from MSO failure state, and that job's are not collected any more. + Make sure service state is Completed successfully once we got from MSO complete, and that next job is peeked. + Once a service in the bulk is failed, other services moved to Stopped, and no other jobs from the bulk are peeked. + */ + //@Test + public void testStatusesOfMacroServiceInBulkDuringBulkLifeCycle() { + when(restMso.PostForObject(any(), any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(200)); + ImmutableList> expectedStatusesForVid = ImmutableList.of( + statusesToStrings(PENDING, IN_PROGRESS, COMPLETED), + statusesToStrings(PENDING, IN_PROGRESS, FAILED), + statusesToStrings(PENDING, STOPPED) + ); + + ImmutableList> expectedStatusesForMso = ImmutableList.of( + ImmutableList.of(REQUESTED, IN_PROGRESS_STR, "not a state", FAILED_STR ,COMPLETE_STR), + ImmutableList.of(REQUESTED, FAILED_STR), + ImmutableList.of() + ); + + List uuids = pushMacroBulk(); + pullPendingJobAndAssertJobStatus(JobStatus.IN_PROGRESS, PENDING); + + //assert that when get ProcessingException from restMso, status remain the same + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenThrow(new ProcessingException("fake message")); + Job job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); + UUID firstHandledJobUUID = job.getUuid(); + listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + + //assert that when get IN_PROGRESS status from restMso, status remain IN_PROGRESS + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR)); + job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); + listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + + //assert that when get unrecognized status from restMso, status remain IN_PROGRESS + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject("not a state")); + job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); + listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + + //assert that when get non 200 status code during IN_PROGRESS, status remain IN_PROGRESS + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR, 404)); + job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); + listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + + //when get job COMPLETE from MSO, service status become COMPLETED + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED); + List serviceInfoList = listServicesAndAssertStatus(COMPLETED, PENDING, job); + + + //for use later in the test + Map expectedJobStatusMap = serviceInfoList.stream().collect( + Collectors.toMap(ServiceInfo::getJobId, x-> PENDING)); + expectedJobStatusMap.put(job.getUuid(), COMPLETED); + + //when handling another PENDING job, statuses are : COMPLETED, IN_PROGRESS, PENDING + job = pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS); + assertThat(job.getUuid(), not(equalTo(firstHandledJobUUID))); //assert different job was handled now + expectedJobStatusMap.put(job.getUuid(), JobStatus.IN_PROGRESS); + listServicesAndAssertStatus(expectedJobStatusMap); + + //when get FAILED status from MSO statuses are : COMPLETED, FAILED, STOPPED + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(FAILED_STR)); + job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.FAILED); + expectedJobStatusMap.put(job.getUuid(), JobStatus.FAILED); + expectedJobStatusMap = expectedJobStatusMap.entrySet().stream().collect(Collectors.toMap( + e -> e.getKey(), e -> e.getValue() == PENDING ? JobStatus.STOPPED : e.getValue() + )); + + listServicesAndAssertStatus(expectedJobStatusMap); + IntStream.range(0, uuids.size()).forEach(i -> { + UUID uuid = uuids.get(i); + List msoStatuses = asyncInstantiationBL.getAuditStatuses(uuid, MSO).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); + List vidStatuses = asyncInstantiationBL.getAuditStatuses(uuid, VID).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); + assertThat(msoStatuses, is(expectedStatusesForMso.get(i))); + assertThat(vidStatuses, is(expectedStatusesForVid.get(i))); + }); + // + assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent()); + assertFalse(jobsBrokerService.pull(JobStatus.IN_PROGRESS, randomUuid()).isPresent()); + } + + + @DataProvider + public static Object[][] AlaCarteStatuses(Method test) { + return new Object[][]{ + {COMPLETE_STR, JobStatus.COMPLETED, JobStatus.COMPLETED}, + {FAILED_STR, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED}, + }; + } + + /* + Make sure service state is in progress once request has sent to MSO + Make sure service state is watching until state changes to complemented + Make sure service state is watching until vnf state changes to completed + Make sure service state is Completed successfully once we got from MSO complete for the vnf job. + status Creating + */ + //@Test(dataProvider = "AlaCarteStatuses") + public void testStatusesOfServiceDuringALaCarteLifeCycleIgnoringVfModules(String msoVnfStatus, JobStatus expectedServiceStatus, JobStatus expectedVnfStatus) { + /* + [v] + push alacarte with 1 vnf + [v] verify STATUS pending + [v] + pull+execute (should post to MSO) + [v] verify STATUS in progress + [v] + pull+execute (should GET completed from MSO) + [v] verify STATUS in progress; TYPE watching + [v] verify job#2 *new* VNF job STATUS creating + [v] + pull+execute job#2 (should post to MSO) + [v] verify job#2 STATUS resource in progress + [v] verify job#1 STATUS in progress + [v] + pull+execute job#2 (should GET completed from MSO) + [v] verify job#2 STATUS completed + [v] + pull+execute job#1 + [v] verify job#1 STATUS completed + + * not looking on audit (yet) + */ + when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true); + when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(false); + final String SERVICE_REQUEST_ID = UUID.randomUUID().toString(); + final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString(); + final String VNF_REQUEST_ID = UUID.randomUUID().toString(); + + + //push alacarte with 1 vnf, verify STATUS pending + UUID uuid = pushALaCarteWithVnf(); + singleServicesAndAssertStatus(JobStatus.PENDING, uuid); + + //mock mso to answer 200 of create service instance request, verify STATUS in progress + when(restMso.PostForObject(any(), endsWith("serviceInstances"), eq(RequestReferencesContainer.class))).thenReturn( + createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID)); + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.PENDING, JobStatus.IN_PROGRESS, JobType.InProgressStatus); + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + + //mock mso to answer COMPLETE for service instance create, job status shall remain IN_PROGRESS and type shall be Watching + reset(restMso); + when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, JobType.Watching); + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + + //mock mso to answer 200 of create vnf instance request, pull+execute vnf job, STATUS resource in progress + reset(restMso); + when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), eq(RequestReferencesContainer.class))).thenReturn( + createResponse(200, UUID.randomUUID().toString(), VNF_REQUEST_ID)); + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.VnfInProgressStatus); + + //verify service job STATUS in progress + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, JobType.Watching); + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + + //mock mso to answer msoVnfStatus (COMPLETE/FAILED) for vnf creation status, + //job status shall be final (COMPLETE/COMPLETE_WITH_ERRORS) + reset(restMso); + when(restMso.GetForObject(endsWith(VNF_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn( + asyncRequestStatusResponseAsRestObject(msoVnfStatus)); + pullJobProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, expectedVnfStatus, false); + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, expectedServiceStatus, true); + singleServicesAndAssertStatus(expectedServiceStatus, uuid); + + } + + /* + this test is almost duplication of testStatusesOfServiceDuringALaCarteLifeCycleIgnoringVfModules. + + IgnoringVfModules test check the scenario while FLAG_ASYNC_ALACARTE_VFMODULE is off + WithVfModules test check the scenario while FLAG_ASYNC_ALACARTE_VFMODULE is on + + We shall consider later to remove testStatusesOfServiceDuringALaCarteLifeCycleIgnoringVfModules + And union these tests to single one. + */ + + //@Test + public void testALaCarteLifeCycle1Vnf2VfModules() { + + + String msoVnfStatus = COMPLETE_STR; + JobStatus expectedServiceStatus = IN_PROGRESS; + JobStatus expectedVnfStatus = RESOURCE_IN_PROGRESS; + when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true); + when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true); + final String SERVICE_REQUEST_ID = UUID.randomUUID().toString(); + final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString(); + final String VNF_REQUEST_ID = UUID.randomUUID().toString(); + final String VNF_INSTANCE_ID = UUID.randomUUID().toString(); + final String VG_REQUEST_ID = UUID.randomUUID().toString(); + final String VG_INSTANCE_ID = UUID.randomUUID().toString(); + final String VF_MODULE_REQUEST_ID = UUID.randomUUID().toString(); + final String VF_MODULE_REQUEST_ID2 = UUID.randomUUID().toString(); + + + //push alacarte with 1 vnf, verify STATUS pending + UUID uuid = pushALaCarteWithVnf(); + singleServicesAndAssertStatus(JobStatus.PENDING, uuid); + + /*---------- service -----------*/ + + //mock mso to answer 200 of create service instance request, verify STATUS in progress + when(restMso.PostForObject(any(), endsWith("serviceInstances"), eq(RequestReferencesContainer.class))).thenReturn( + createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID)); + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.PENDING, JobStatus.IN_PROGRESS, JobType.InProgressStatus); + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + + //mock mso to answer COMPLETE for service instance create, job status shall remain IN_PROGRESS and type shall be Watching + reset(restMso); + when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, JobType.Watching); + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + + /*---------- vnf -----------*/ + + //mock mso to answer 200 of create vnf instance request, pull+execute vnf job, STATUS resource in progress + reset(restMso); + when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), eq(RequestReferencesContainer.class))).thenReturn( + createResponse(200, VNF_INSTANCE_ID, VNF_REQUEST_ID)); + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.VnfInProgressStatus); + + //verify service job STATUS in progress + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, JobType.Watching); + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + + //mock mso to answer msoVnfStatus (COMPLETE/FAILED) for vnf creation status, + //job status shall be final (COMPLETE/COMPLETE_WITH_ERRORS) + reset(restMso); + when(restMso.GetForObject(endsWith(VNF_REQUEST_ID), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + + try { + reset(commandUtils); + when(commandUtils.isVfModuleBaseModule(SERVICE_MODEL_VERSION_ID, VF_MODULE_0_MODEL_VERSION_ID)).thenReturn(true); + when(commandUtils.isVfModuleBaseModule(SERVICE_MODEL_VERSION_ID, VF_MODULE_1_MODEL_VERSION_ID)).thenReturn(false); + } catch (AsdcCatalogException e) { + + } + + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.RESOURCE_IN_PROGRESS, JobStatus.RESOURCE_IN_PROGRESS, JobType.WatchingBaseModule); + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, true); + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + + /*---------- vf Module without volume group name (base) -----------*/ + + //vg name not exist, so vf module created immediately + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); + + //verify vnf/volumeGroup job STATUS still watching with resource in progress + pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); + + //mock mso to answer 200 of create vfModule instance request, pull+execute volumeGroup job, STATUS resource in progress + reset(restMso); + when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), eq(RequestReferencesContainer.class))).thenReturn( + createResponse(200, UUID.randomUUID().toString(), VF_MODULE_REQUEST_ID)); + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus); + + //mock mso to answer for vf module orchestration request + reset(restMso); + when(restMso.GetForObject(endsWith(VF_MODULE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn( + asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus, JobStatus.COMPLETED, JobType.ResourceInProgressStatus); + + //verify volume group become completed + pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching, JobStatus.COMPLETED, JobType.Watching); + + //vnf become watching after volume group completed, and new volume group created + pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.WatchingBaseModule, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); + + /*---------- volume group & vf module (non base) -----------*/ + + /*---------- volume group -----------*/ + + //mock mso to answer 200 of create volumeGroup instance request, pull+execute volumeGroup job, STATUS resource in progress + reset(restMso); + when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/volumeGroups"), eq(RequestReferencesContainer.class))).thenReturn( + createResponse(200, VG_INSTANCE_ID, VG_REQUEST_ID)); + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.VolumeGroupInProgressStatus); + + //verify vnf job STATUS still watching with resource in progress + pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); + + //mock mso to answer for volume group orchestration request + reset(restMso); + when(restMso.GetForObject(endsWith(VG_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn( + asyncRequestStatusResponseAsRestObject(msoVnfStatus)); + pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.VolumeGroupInProgressStatus, JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching); + + /*---------- vfModule -----------*/ + + //mock mso to answer 200 of create vfModule instance request, pull+execute volumeGroup job, STATUS resource in progress + reset(restMso); + when(restMso.PostForObject(any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), eq(RequestReferencesContainer.class))).thenReturn( + createResponse(200, UUID.randomUUID().toString(), VF_MODULE_REQUEST_ID2)); + pullJobProcessAndPushBackWithTypeAssertion(JobStatus.CREATING, JobStatus.RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus); + + //mock mso to answer for vf module orchestration request + reset(restMso); + when(restMso.GetForObject(endsWith(VF_MODULE_REQUEST_ID2), eq(AsyncRequestStatus.class))).thenReturn( + asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus.RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus, JobStatus.COMPLETED, JobType.ResourceInProgressStatus); + + //execute twice - 1 for parent volume group, 1 for parent vnf + pullAllJobProcessAndPushBackByType(JobStatus.RESOURCE_IN_PROGRESS, JobType.Watching , JobStatus.COMPLETED); + + singleServicesAndAssertStatus(JobStatus.IN_PROGRESS, uuid); + pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.COMPLETED, true); + singleServicesAndAssertStatus(JobStatus.COMPLETED, uuid); + } + + //@Test + public void testBadAaiResponseForSearchNamesAndBackToNormal() { + when(aaiClient.isNodeTypeExistsByName(any(), any())).thenThrow(aaiNodeQueryBadResponseException()); + pushMacroBulk(); //JOB shall become IN_PROGRESS but service info is still pending + Job job = pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS, true); + listServicesAndAssertStatus(PENDING, PENDING, job); + + //JOB shall remain in IN_PROGRESS + job = pullJobProcessAndPushBack( JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, true); + //make sure the job command is still ServiceInstantiation + assertThat(job.getType(), is(JobType.MacroServiceInstantiation)); + listServicesAndAssertStatus(PENDING, PENDING, job); + + //simulate AAI back to normal, AAI return name is free, and MSO return good response + Mockito.reset(aaiClient); // must forget the "thenThrow" + when(aaiClient.isNodeTypeExistsByName(any(), any())).thenReturn(false); + when(restMso.PostForObject(any(),any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(200)); + job = pullJobProcessAndPushBack( JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS, true); + listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + + //when get job COMPLETE from MSO, service status become COMPLETED + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED); + listServicesAndAssertStatus(COMPLETED, PENDING, job); + } + + //@Test + public void testAaiResponseNameUsedTillMaxRetries() { + when(aaiClient.isNodeTypeExistsByName(any(), any())).thenReturn(true); + asyncInstantiationBL.setMaxRetriesGettingFreeNameFromAai(10); + pushMacroBulk(); + //JOB shall become IN_PROGRESS but service info is still pending + Job job = pullJobProcessAndPushBack(PENDING, JobStatus.FAILED, true); + listServicesAndAssertStatus(JobStatus.FAILED, JobStatus.STOPPED, job); + } + + private Job pullJobProcessAndPushBack(JobStatus topic, JobStatus expectedNextJobStatus) { + return pullJobProcessAndPushBack(topic, expectedNextJobStatus, true); + } + + //return the pulled job (and not the pushed job) + private Job pullJobProcessAndPushBack(JobStatus topic, JobStatus expectedNextJobStatus, boolean pullingAssertion) { + Optional job = pullJob(topic, pullingAssertion); + + Job nextJob = jobWorker.executeJobAndGetNext(job.get()); + + try { + assertThat("next job not ok: " + nextJob.getData(), nextJob.getStatus(), is(expectedNextJobStatus)); + + if (pullingAssertion) { + //assert another pulling on same topic return no result (before push back) + assertFalse(jobsBrokerService.pull(topic, randomUuid()).isPresent()); + } + + } finally { + jobsBrokerService.pushBack(nextJob); // push back to let retries - even if any assertion failure + } + assertThat(jobsBrokerService.peek(job.get().getUuid()).getStatus(), is(expectedNextJobStatus)); + return job.get(); + } + + private Job pullJobProcessAndPushBackWithTypeAssertion(JobStatus topic, JobStatus expectedNextJobStatus, + JobType expectedNextJobType) { + Job job = pullJobProcessAndPushBack(topic, expectedNextJobStatus, false); + assertThat("job not ok: " + job.getData(), job.getType(), is(expectedNextJobType)); + return job; + } + + private Job pullJobProcessAndPushBackWithTypeAssertion(JobStatus topic, JobStatus expectedNextJobStatus, + JobType expectedNextJobType, int retries) { + return retryWithAssertionsLimit(retries, () -> { + return pullJobProcessAndPushBackWithTypeAssertion(topic, expectedNextJobStatus, expectedNextJobType); + }); + } + + private Job pullJobProcessAndPushBackWithTypeAssertion(JobStatus topic, JobStatus expectedNextJobStatus, + JobType expectedNextJobType, Action actionPhase, InternalState internalState, int retries) { + return retryWithAssertionsLimit(retries, () -> { + Job job = pullJobProcessAndPushBackWithTypeAssertion(topic, expectedNextJobStatus, expectedNextJobType); + assertThat("job not ok: " + job.getData(), job.getData(), is(jsonPartEquals("actionPhase", actionPhase.name()))); + if (internalState != null) { + assertThat("job not ok: " + job.getData(), job.getData(), is(jsonPartEquals("internalState", internalState.name()))); + } + return job; + }); + } + + private Job retryWithAssertionsLimit(int retries, Supplier supplier) { + java.util.Stack history = new Stack<>(); + + do { + try { + return supplier.get(); + } catch (AssertionError assertionError) { + history.push(assertionError); + } + } while (history.size() < retries); + + // No success: + throw new AssertionError("No luck while all of these assertion errors: " + history.stream() + .map(Throwable::getMessage) + .map(s -> s.replace('\n', ' ')) + .map(s -> s.replaceAll("\\s{2,}"," ")) + .distinct() + .collect(joining("\n ", "\n ", "")), history.peek()); + } + + private Job pullMultipleJobsFindExpectedProcessAndPushBack(JobStatus topic, JobType expectedCurrentJobType, JobStatus expectedNextJobStatus, + JobType expectedNextJobType) { + List pulledJobs = new ArrayList<>(); + Job lastJob = null; + while (lastJob == null || lastJob.getType() != expectedCurrentJobType) { + lastJob = pullJob(topic, false).get(); + if (lastJob.getType() != expectedCurrentJobType) { + pulledJobs.add(lastJob); + } + } + + Job nextJob = jobWorker.executeJobAndGetNext(lastJob); + assertThat(nextJob.getStatus(), is(expectedNextJobStatus)); + assertThat(nextJob.getType(), is(expectedNextJobType)); + + jobsBrokerService.pushBack(nextJob); + assertThat(jobsBrokerService.peek(nextJob.getUuid()).getStatus(), is(expectedNextJobStatus)); + + pulledJobs.forEach(job -> + jobsBrokerService.pushBack(job) + ); + + return nextJob; + } + + private void pullAllJobProcessAndPushBackByType(JobStatus topic, JobType commandType, JobStatus expectedFinalStatus) { + Map jobStatusMap = new HashMap<>(); + Optional job = pullJob(topic, false); + for (int i=0; i<1000 && job.isPresent() && job.get().getType() == commandType; i++) { + Job nextJob = jobWorker.executeJobAndGetNext(job.get()); + jobStatusMap.put(nextJob.getUuid(), nextJob.getStatus()); + jobsBrokerService.pushBack(nextJob); + job = jobsBrokerService.pull(topic, UUID.randomUUID().toString()); + } + assertThat(jobStatusMap.values(), everyItem(is(expectedFinalStatus))); + + } + + private Optional pullJob(JobStatus topic, boolean pullingAssertion) { + if (pullingAssertion) { + //assert pulling on inverse topic return no result + assertFalse(jobsBrokerService.pull(inverseTopic(topic), randomUuid()).isPresent()); + } + + Optional job = jobsBrokerService.pull(topic, randomUuid()); + assertTrue("no job fetched", job.isPresent()); + + if (pullingAssertion) { + //assert another pulling on same topic return no result + assertFalse(jobsBrokerService.pull(topic, randomUuid()).isPresent()); + } + + return job; + } + + private JobStatus inverseTopic(JobStatus topic) { + return topic==JobStatus.IN_PROGRESS ? PENDING : JobStatus.IN_PROGRESS; + } + + + //@Test + public void whenPushNewBulk_andGetNoResponseFromMsoOnCreation_thenServiceMoveToFailedAndOtherToStopped() { + when(restMso.PostForObject(any(), any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(500)); + pushBulkPullPendingJobAndAssertJobStatus(JobStatus.FAILED, JobStatus.STOPPED); + } + + //@Test + public void whenMsoStatusIsPendingManualTask_ThenJobStatusIsPaused() { + when(restMso.PostForObject(any(), any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(200)); + + Job firstJob = pushBulkPullPendingJobAndAssertJobStatus(JobStatus.IN_PROGRESS, PENDING); + + //assert that when get ProcessingException from restMso, status remain the same + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(PENDING_MANUAL_TASK)); + Job job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); + listServicesAndAssertStatus(PAUSE, PENDING, job); + + //The paused job is pulled and remain in pause state. Other jobs from bulk remain pending + job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); + listServicesAndAssertStatus(PAUSE, PENDING, job); + + //the job get IN_PROGRESS response (simulate activate operation) and status changed to IN_PROGRESS + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR)); + job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS); + listServicesAndAssertStatus(JobStatus.IN_PROGRESS, PENDING, job); + + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + job = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED); + listServicesAndAssertStatus(COMPLETED, PENDING, job); + + //Pulling PENDING job return another job + assertThat(jobsBrokerService.pull(PENDING, randomUuid()).get().getUuid(), not(equalTo(job.getUuid()))); + + + ImmutableList expectedStatusesForMso = ImmutableList.of(REQUESTED, PENDING_MANUAL_TASK, IN_PROGRESS_STR, COMPLETE_STR); + List msoStatuses = asyncInstantiationBL.getAuditStatuses(firstJob.getUuid(), MSO).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); + assertThat(msoStatuses, is(expectedStatusesForMso)); + + ImmutableList expectedStatusesForVid = statusesToStrings(PENDING, IN_PROGRESS, PAUSE, IN_PROGRESS, COMPLETED); + List vidStatuses = asyncInstantiationBL.getAuditStatuses(firstJob.getUuid(), VID).stream().map(x -> x.getJobStatus()).collect(Collectors.toList()); + assertThat(vidStatuses, is(expectedStatusesForVid)); + } + + private Job pushBulkPullPendingJobAndAssertJobStatus(JobStatus pulledJobStatus, JobStatus otherJobsStatus) { + pushMacroBulk(); + return pullPendingJobAndAssertJobStatus(pulledJobStatus, otherJobsStatus); + } + + private Job pullPendingJobAndAssertJobStatus(JobStatus pulledJobStatus, JobStatus otherJobsStatus) { + Job job = pullJobProcessAndPushBack(PENDING, pulledJobStatus, false); + listServicesAndAssertStatus(pulledJobStatus, otherJobsStatus, job); + return job; + } + + //@Test + public void test2BulksLifeCyclesAreIndependent() { + pushMacroBulk(); + when(restMso.PostForObject(any(), any(), eq(RequestReferencesContainer.class))).thenReturn(createResponse(200)); + //push 2nd job, then when pulling first job the job become in_progress, other jobs (from 2 bulks) remain pending + Job firstJob = pushBulkPullPendingJobAndAssertJobStatus(JobStatus.IN_PROGRESS, PENDING); + + //assert we can pull another job from pending from other template id + Job secondJob = pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS, false); + assertThat(firstJob.getTemplateId(), not(equalTo(secondJob.getTemplateId()))); + + //assert no more PENDING jobs to pull + assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent()); + + //when get FAILED status from MSO statuses for failed bulk are: FAILED, STOPPED, for other bulk: IN_PROGRESS, 2 pending + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(FAILED_STR)); + Job failedJob = pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.FAILED, false); + Map> servicesByTemplateId = + asyncInstantiationBL.getAllServicesInfo() + .stream().collect(groupingBy(ServiceInfo::getTemplateId)); + assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob); + Job successJob = failedJob.getUuid().equals(firstJob.getUuid()) ? secondJob : firstJob; + assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), JobStatus.IN_PROGRESS, PENDING, successJob); + + //yet no more PENDING jobs to pull + assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent()); + + //assert that job from non failed bulk can progress. + //When completed, failed bulk statuses: FAILED, STOPPED. Succeeded bulk statuses are : COMPLETED, 2 pending + when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED, false); + servicesByTemplateId = + asyncInstantiationBL.getAllServicesInfo() + .stream().collect(groupingBy(ServiceInfo::getTemplateId)); + assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob); + assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), COMPLETED, PENDING, successJob); + + //advance other jobs of succeeded bulk till al of them reach to COMPLETED + pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS, false); + pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED, false); + pullJobProcessAndPushBack(PENDING, JobStatus.IN_PROGRESS, false); + pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED, false); + servicesByTemplateId = + asyncInstantiationBL.getAllServicesInfo() + .stream().collect(groupingBy(ServiceInfo::getTemplateId)); + assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob); + assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), COMPLETED, COMPLETED, successJob); + + //assert no more PENDING jobs nor IN_PROGRESS jobs to pull + assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent()); + assertFalse(jobsBrokerService.pull(JobStatus.IN_PROGRESS, randomUuid()).isPresent()); + } + + public void deploy2NewGroupsToServiceWith1ExistingGroup() { + + /* + new feature: skip service (existing impl) and skip group (new impl) + service+group aren't touched, 2 groups ARE created + + [v] success if all GROUPs success + + Next test variation should: + [ ] error if all GROUPs error + [ ] completed with error if 1 GROUP error + + + [v] + service with 3 groups - 1 action=none, 2 action=create; service's action=none + [v] verify STATUS pending + [v] + pull+execute (should NOT post to MSO) + [v] verify STATUS in progress; TYPE watching + ... + [v] verify job#2 *new* GROUP job STATUS completed with no action TYPE group INTERNAL STATE terminal PHASE delete + [v] verify job#3 *new* GROUP job STATUS completed with no action TYPE group INTERNAL STATE terminal PHASE delete + [v] verify job#4 *new* GROUP job STATUS completed with no action TYPE group INTERNAL STATE terminal PHASE delete + + [v] + pull+execute job#1 (should NOT post to MSO) + [v] verify STATUS in progress; TYPE watching + [v] verify job#5 *new* GROUP job STATUS creating TYPE group INTERNAL STATE initial PHASE create + [v] verify job#6 *new* GROUP job STATUS creating TYPE group INTERNAL STATE initial PHASE create + [v] verify job#7 *new* GROUP job STATUS creating TYPE group INTERNAL STATE initial PHASE create + + [v] + pull+execute job#5 (should NOT post to MSO) + [v] verify job#5 STATUS completed with no action TYPE group INTERNAL STATE terminal PHASE create + [v] + pull+execute job#1 + [v] verify job#1 STATUS in progress; TYPE watching + + [v] + pull+execute job#6 (should post to MSO) + [v] verify job#6 STATUS resource in progress + [v] + pull+execute job#1 + [v] verify job#1 STATUS in progress; TYPE watching + [v] + pull+execute job#6 (should get from MSO) + [v] verify job#6 STATUS completed + [v] + pull+execute job#1 + [v] verify job#1 STATUS in progress; TYPE watching + + [v] + pull+execute job#7 (should post to MSO) + [v] verify job#7 STATUS resource in progress + [v] + pull+execute job#1 + [v] verify job#1 STATUS in progress; TYPE watching + [v] + pull+execute job#7 (should get from MSO) + [v] verify job#7 STATUS completed + [v] + pull+execute job#1 + [v] verify job#1 STATUS completed + + */ + + final String GROUP1_REQUEST_ID = UUID.randomUUID().toString(); + final String GROUP1_INSTANCE_ID = UUID.randomUUID().toString(); + final String GROUP2_REQUEST_ID = UUID.randomUUID().toString(); + final String GROUP2_INSTANCE_ID = UUID.randomUUID().toString(); + + // Utility method + final BiConsumer verify_Job1InProgress = (phase, nextJobStatus) -> { + pullJobProcessAndPushBackWithTypeAssertion(IN_PROGRESS, nextJobStatus, JobType.ALaCarteService, phase, InternalState.WATCHING, 2); + }; + + //service with 3 groups - 1 action=none, 2 action=create; service's action=none + UUID uuid = pushALaCarteUpdateWithGroups(); + singleServicesAndAssertStatus(PENDING, uuid); + + // take from pending, put in-progress -> 3 delete-child were born + pullJobProcessAndPushBackWithTypeAssertion(PENDING, IN_PROGRESS, JobType.ALaCarteService, Action.Delete, InternalState.WATCHING, 1); + verifyQueueSizes(ImmutableMap.of( + IN_PROGRESS, 1, CREATING, 3 + )); + + Stream.of(1, 2, 3).forEach(i -> { + // take each child creating, put in-progress + verify_Job1InProgress.accept(Action.Delete, IN_PROGRESS); + pullJobProcessAndPushBackWithTypeAssertion(CREATING, RESOURCE_IN_PROGRESS, JobType.InstanceGroup, Action.Delete, null, 1); + + // execute each in-progress -> job is completed + verify_Job1InProgress.accept(Action.Delete, IN_PROGRESS); + pullJobProcessAndPushBackWithTypeAssertion(RESOURCE_IN_PROGRESS, COMPLETED/*_WITH_NO_ACTION*/, JobType.InstanceGroup,1); + }); + verifyQueueSizes(ImmutableMap.of( + IN_PROGRESS, 1, COMPLETED, 3 + )); + + // take job #1 from phase delete to phase create -> 3 create-child were born + verify_Job1InProgress.accept(Action.Create, IN_PROGRESS); + verifyQueueSizes(ImmutableMap.of( + IN_PROGRESS, 1, CREATING, 3, COMPLETED, 3 + )); + + // prepare MSO mock + when(restMso.PostForObject(any(), endsWith("instanceGroups"), eq(RequestReferencesContainer.class))) + .thenReturn(createResponse(200, GROUP1_INSTANCE_ID, GROUP1_REQUEST_ID)) + .thenReturn(createResponse(200, GROUP2_INSTANCE_ID, GROUP2_REQUEST_ID)) + .thenReturn(null); + when(restMso.GetForObject(argThat(uri -> StringUtils.endsWithAny(uri, GROUP1_REQUEST_ID, GROUP2_REQUEST_ID)), eq(AsyncRequestStatus.class))). + thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR)); + + // take first "none" child from creating to completed + // note there's no concrete mechanism that makes the first child be + // the "action=None" case, but that's what happens, and following line + // relies on that fact. + pullJobProcessAndPushBackWithTypeAssertion(CREATING, COMPLETED_WITH_NO_ACTION, JobType.InstanceGroupInstantiation, 1); + + // take each of next two children from creating to in-progress, then to completed + // verify job #1 is watching, and MSO is getting requests + Stream.of(1, 2).forEach(i -> { + verify_Job1InProgress.accept(Action.Create, IN_PROGRESS); + pullJobProcessAndPushBackWithTypeAssertion(CREATING, RESOURCE_IN_PROGRESS, JobType.ResourceInProgressStatus); + verify(restMso, times(i)).PostForObject(any(), any(), any()); + + verify_Job1InProgress.accept(Action.Create, IN_PROGRESS); + pullJobProcessAndPushBackWithTypeAssertion(RESOURCE_IN_PROGRESS, COMPLETED, JobType.ResourceInProgressStatus); + verify(restMso, times(i)).GetForObject(any(), any()); + }); + + // job #1 is done as all children are done + verify_Job1InProgress.accept(Action.Create, COMPLETED); + verifyQueueSizes(ImmutableMap.of(COMPLETED, 7)); + } + + private void verifyQueueSizes(ImmutableMap expected) { + final Collection peek = jobsBrokerService.peek(); + final Map jobTypes = peek.stream().collect(groupingBy(Job::getStatus, counting())); + assertThat(jobTypes, is(expected)); + } + + private List listServicesAndAssertStatus(JobStatus pulledJobStatus, JobStatus otherJobsStatus, Job job) { + List serviceInfoList = asyncInstantiationBL.getAllServicesInfo(); + assertServicesStatus(serviceInfoList, pulledJobStatus, otherJobsStatus, job); + + return serviceInfoList; + } + + private ServiceInfo singleServicesAndAssertStatus(JobStatus expectedStatus, UUID jobUUID) { + List serviceInfoList = asyncInstantiationBL.getAllServicesInfo(); + assertEquals(1, serviceInfoList.size()); + ServiceInfo serviceInfo = serviceInfoList.get(0); + assertThat(serviceInfo.getJobStatus(), is(expectedStatus)); + assertThat(serviceInfo.getJobId(), is(jobUUID)); + return serviceInfo; + } + + private void assertServicesStatus(List serviceInfoList, JobStatus pulledJobStatus, JobStatus otherJobsStatus, Job job) { + serviceInfoList.forEach(si->{ + if (si.getJobId().equals(job.getUuid())) { + assertThat(si.getJobStatus(), is(pulledJobStatus)); + } + else { + assertThat(si.getJobStatus(), is(otherJobsStatus)); + } + }); + } + + private void listServicesAndAssertStatus(Map expectedJobStatusMap) { + Map actualStatuses = asyncInstantiationBL.getAllServicesInfo() + .stream().collect(Collectors.toMap(ServiceInfo::getJobId, ServiceInfo::getJobStatus)); + assertThat(actualStatuses.entrySet(), equalTo(expectedJobStatusMap.entrySet())); + } + + private String randomUuid() { + return UUID.randomUUID().toString(); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterImplTest.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterImplTest.java deleted file mode 100644 index dc2eafc9b..000000000 --- a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterImplTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2018 Nokia Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.vid.job.impl; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import org.mockito.Mock; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.JobType; -import org.onap.vid.model.JobBulk; -import org.onap.vid.model.JobModel; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.List; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -public class JobAdapterImplTest { - - - private static final int SAMPLE_INDEX = 10; - private static final String SAMPLE_USER_ID = "sampleUserId"; - - @Mock - private Job job; - - @Mock - private JobAdapter.AsyncJobRequest asyncJobRequest; - - private UUID sampleUuid=UUID.randomUUID(); - - private JobAdapterImpl jobAdapter = new JobAdapterImpl(); - - @BeforeMethod - public void setUp() { - initMocks(this); - - when(job.getUuid()).thenReturn(sampleUuid); - when(job.getStatus()).thenReturn(Job.JobStatus.IN_PROGRESS); - when(job.getTemplateId()).thenReturn(sampleUuid); - } - - @Test - public void shouldConvertJobToJobModel() { - - - JobModel convertedJob = jobAdapter.toModel(job); - - assertThat(convertedJob.getUuid()).isEqualByComparingTo(sampleUuid); - assertThat(convertedJob.getStatus()).isEqualByComparingTo(Job.JobStatus.IN_PROGRESS); - assertThat(convertedJob.getTemplateId()).isEqualByComparingTo(sampleUuid); - } - - - @Test - public void shouldProperlyCreateJob() { - UUID uuid = UUID.randomUUID(); - - Job createdJob = jobAdapter.createJob(JobType.ServiceInstantiation, asyncJobRequest, uuid, SAMPLE_USER_ID, SAMPLE_INDEX); - - assertThat(createdJob.getStatus()).isEqualByComparingTo(Job.JobStatus.PENDING); - assertThat(createdJob.getTemplateId()).isEqualByComparingTo(uuid); - assertThat(createdJob.getType()).isEqualByComparingTo(JobType.ServiceInstantiation); - assertThat(createdJob.getData()).isEqualTo(ImmutableMap.of("request", asyncJobRequest, "userId", SAMPLE_USER_ID)); - } - - @Test - public void shouldProperlyCreateBulkOfJobs(){ - List bulkOfJobs = jobAdapter.createBulkOfJobs(ImmutableMap.of("count", 5, "type", JobType.InProgressStatus.name())); - - - assertThat(bulkOfJobs).hasSize(5); - - Stream jobStream = bulkOfJobs.stream().filter(x -> JobType.InProgressStatus.equals(x.getType()) && Job.JobStatus.PENDING.equals(x.getStatus())); - - assertThat(jobStream).hasSize(5); - } - - - @Test - public void shouldConvertListToBulkJob(){ - JobBulk jobBulk = jobAdapter.toModelBulk(ImmutableList.of(job, job)); - - assertThat(jobBulk.getJobs()).hasSize(2); - } -} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterTest.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterTest.java new file mode 100644 index 000000000..95228476b --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobAdapterTest.java @@ -0,0 +1,100 @@ +package org.onap.vid.job.impl; + +import com.google.common.collect.ImmutableMap; +import org.apache.commons.lang3.RandomUtils; +import org.onap.vid.job.Job; +import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; +import org.onap.vid.job.command.JobCommandFactoryTest; +import org.testng.annotations.Test; + +import java.util.UUID; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; +import static org.testng.AssertJUnit.assertNotNull; + +public class JobAdapterTest { + + @Test + public void testCreateServiceInstantiationJob() { + JobAdapter jobAdapter = new JobAdapterImpl(); + + JobType jobType = JobType.NoOp; + JobAdapter.AsyncJobRequest request = new JobCommandFactoryTest.MockedRequest(42,"nothing"); + UUID templateId = UUID.randomUUID(); + String userId = "ou012t"; + String optimisticUniqueServiceInstanceName = "optimisticUniqueServiceInstanceName"; + int indexInBulk = RandomUtils.nextInt(); + Job job = jobAdapter.createServiceInstantiationJob( + jobType, + request, + templateId, + userId, + optimisticUniqueServiceInstanceName, + indexInBulk + ); + + assertEquals(job.getType(), jobType); + assertEquals(job.getSharedData().getRequest(), request); + assertEquals(job.getSharedData().getRequestType(), request.getClass()); + assertEquals(job.getSharedData().getUserId(), userId); + assertEquals(job.getSharedData().getJobUuid(), job.getUuid()); + assertEquals(job.getSharedData().getRootJobId(), job.getUuid()); + assertNotNull(job.getUuid()); + assertEquals(job.getTemplateId(), templateId); + assertEquals(job.getData().get("optimisticUniqueServiceInstanceName"), optimisticUniqueServiceInstanceName); + assertEquals((int)job.getIndexInBulk(), indexInBulk ); + assertEquals(job.getStatus(), Job.JobStatus.PENDING); + } + + @Test + public void testCreateChildJob() { + + JobAdapter jobAdapter = new JobAdapterImpl(); + + UUID templateId = UUID.randomUUID(); + String userId = "ou012t"; + String optimisticUniqueServiceInstanceName = "optimisticUniqueServiceInstanceName"; + int indexInBulk = RandomUtils.nextInt(); + Job grandJob = jobAdapter.createServiceInstantiationJob( + JobType.HttpCall, + new JobCommandFactoryTest.MockedRequest(99, "anything"), + templateId, + userId, + optimisticUniqueServiceInstanceName, + indexInBulk + ); + + Job.JobStatus jobStatus = Job.JobStatus.PAUSE; + JobType jobType = JobType.NoOp; + JobAdapter.AsyncJobRequest request = new JobCommandFactoryTest.MockedRequest(42,"nothing"); + Job parentJob = jobAdapter.createChildJob(jobType, jobStatus, request, grandJob.getSharedData(), ImmutableMap.of()); + + assertEquals(parentJob.getType(), jobType); + assertEquals(parentJob.getSharedData().getRequest(), request); + assertEquals(parentJob.getSharedData().getRequestType(), request.getClass()); + assertEquals(parentJob.getSharedData().getUserId(), userId); + assertEquals(parentJob.getSharedData().getJobUuid(), parentJob.getUuid()); + assertNotNull(parentJob.getUuid()); + assertNotEquals(parentJob.getUuid(), grandJob.getUuid()); + assertEquals(parentJob.getStatus(), jobStatus); + assertEquals(parentJob.getSharedData().getRootJobId(), grandJob.getUuid()); + + Job.JobStatus jobStatus2 = Job.JobStatus.IN_PROGRESS; + JobType jobType2 = JobType.AggregateState; + JobAdapter.AsyncJobRequest request2 = new JobCommandFactoryTest.MockedRequest(66,"abc"); + Job job = jobAdapter.createChildJob(jobType2, jobStatus2, request2, parentJob.getSharedData(), ImmutableMap.of()); + + assertEquals(job.getType(), jobType2); + assertEquals(job.getSharedData().getRequest(), request2); + assertEquals(job.getSharedData().getRequestType(), request2.getClass()); + assertEquals(job.getSharedData().getUserId(), userId); + assertEquals(job.getSharedData().getJobUuid(), job.getUuid()); + assertNotNull(job.getUuid()); + assertNotEquals(job.getUuid(), parentJob.getUuid()); + assertEquals(job.getStatus(), jobStatus2); + assertEquals(job.getSharedData().getRootJobId(), grandJob.getUuid()); + + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobSchedulerInitializerTest.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobSchedulerInitializerTest.java deleted file mode 100644 index 93afd1709..000000000 --- a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobSchedulerInitializerTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2018 Nokia Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.vid.job.impl; - - -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.onap.vid.job.JobsBrokerService; -import org.onap.vid.job.command.JobCommandFactory; -import org.onap.vid.properties.Features; -import org.quartz.JobDetail; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.quartz.Trigger; -import org.springframework.scheduling.quartz.SchedulerFactoryBean; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; -import org.togglz.core.manager.FeatureManager; - -import java.util.List; -import java.util.stream.Collectors; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.initMocks; - -public class JobSchedulerInitializerTest { - - @Mock - private JobsBrokerService brokerService; - - @Mock - private SchedulerFactoryBean schedulerFactoryBean; - - @Mock - private FeatureManager featureManager; - - @Mock - private JobCommandFactory commandFactory; - - @Mock - private Scheduler scheduler; - - @InjectMocks - private JobSchedulerInitializer jobSchedulerInitializer; - - @BeforeMethod - public void setUp() { - initMocks(this); - } - - - @Test - public void shouldNotInitializeSchedulerWhenAsyncJobsAreDisabled() { - when(featureManager.isActive(Features.FLAG_ASYNC_JOBS)).thenReturn(false); - - jobSchedulerInitializer.init(); - - verifyZeroInteractions(schedulerFactoryBean); - } - - - @Test - public void shouldInitializeSchedulerWhenAsyncJobsAreEnabled() throws SchedulerException { - ArgumentCaptor jobDetailArgumentCaptor = ArgumentCaptor.forClass(JobDetail.class); - ArgumentCaptor triggerArgumentCaptor = ArgumentCaptor.forClass(Trigger.class); - when(featureManager.isActive(Features.FLAG_ASYNC_JOBS)).thenReturn(true); - when(schedulerFactoryBean.getScheduler()).thenReturn(scheduler); - - jobSchedulerInitializer.init(); - - verify(scheduler, times(2)).scheduleJob(jobDetailArgumentCaptor.capture(), triggerArgumentCaptor.capture()); - - List topics = extractTopics(jobDetailArgumentCaptor); - - List descriptions = extractDescription(triggerArgumentCaptor); - - assertThat(topics, containsInAnyOrder(org.onap.vid.job.Job.JobStatus.IN_PROGRESS, org.onap.vid.job.Job.JobStatus.PENDING)); - assertThat(descriptions, containsInAnyOrder("Trigger to run async worker for PENDING", "Trigger to run async worker for IN_PROGRESS")); - } - - private List extractTopics(ArgumentCaptor jobDetailArgumentCaptor) { - return jobDetailArgumentCaptor - .getAllValues() - .stream() - .map(JobDetail::getJobDataMap) - .map(x -> x.get("topic")) - .collect(Collectors.toList()); - } - - private List extractDescription(ArgumentCaptor triggerArgumentCaptor) { - return triggerArgumentCaptor - .getAllValues() - .stream() - .map(Trigger::getDescription) - .collect(Collectors.toList()); - } -} \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobWorkerTest.java b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobWorkerTest.java index e58b6ba03..3ff324d61 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/impl/JobWorkerTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/impl/JobWorkerTest.java @@ -19,7 +19,7 @@ import java.util.UUID; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -47,12 +47,13 @@ public class JobWorkerTest { public final String foobar = "aux"; }; - originalType = JobType.ServiceInstantiation; - jobUnderTest = new JobAdapterImpl().createJob( + originalType = JobType.MacroServiceInstantiation; + jobUnderTest = new JobAdapterImpl().createServiceInstantiationJob( originalType, originalData, UUID.randomUUID(), "my user id", + "optimisticUniqueServiceInstanceName", RandomUtils.nextInt() ); } @@ -62,7 +63,7 @@ public class JobWorkerTest { assertNextJobAfterExecuteJob(null, new String[]{"status"}, allOf( hasProperty("status", is(Job.JobStatus.STOPPED)), - hasProperty("data", hasEntry("request", originalData)), + hasProperty("sharedData", hasProperty("request", is(originalData))), hasProperty("type", is(originalType))) ); } -- cgit 1.2.3-korg