1 package org.onap.vid.job.command;
3 import com.google.common.collect.ImmutableMap;
4 import org.jetbrains.annotations.NotNull;
5 import org.onap.vid.exceptions.GenericUncheckedException;
6 import org.onap.vid.job.Job;
7 import org.onap.vid.job.JobAdapter;
8 import org.onap.vid.job.NextCommand;
9 import org.onap.vid.job.impl.JobSharedData;
10 import org.onap.vid.model.Action;
11 import org.onap.vid.model.serviceInstantiation.BaseResource;
12 import org.onap.vid.mso.RestMsoImplementation;
13 import org.springframework.http.HttpMethod;
14 import org.testng.annotations.DataProvider;
15 import org.testng.annotations.Test;
17 import javax.ws.rs.ProcessingException;
18 import java.util.Collections;
19 import java.util.Optional;
20 import java.util.stream.Stream;
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.Mockito.*;
24 import static org.onap.vid.job.command.ResourceCommandKt.ACTION_PHASE;
25 import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE;
26 import static org.onap.vid.utils.Logging.getMethodCallerName;
27 import static org.testng.Assert.assertNull;
28 import static org.testng.Assert.assertTrue;
29 import static org.testng.AssertJUnit.assertEquals;
30 import static org.testng.AssertJUnit.assertFalse;
32 public class ResourceCommandTest {
34 public static class MockCommand extends ResourceCommand {
36 public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus) {
37 super(mock(RestMsoImplementation.class, RETURNS_MOCKS), mock(InProgressStatusService.class), mock(MsoResultHandlerService.class, RETURNS_MOCKS), mock(WatchChildrenJobsBL.class));
39 this.mockedJobStatus = mockedJobStatus;
40 this.mockState = mockState;
41 this.mockPhase = mockPhase;
42 if (mockState==InternalState.INITIAL) {
43 init(mock(JobSharedData.class), Collections.emptyMap());
46 init(mock(JobSharedData.class), ImmutableMap.of(INTERNAL_STATE, mockState.name(), ACTION_PHASE, mockPhase.name()));
48 when(this.getWatchChildrenJobsBL().cumulateJobStatus(any(), any())).thenReturn(mockedJobStatus);
51 private final Job.JobStatus mockedJobStatus;
52 private final InternalState mockState;
53 private final Action mockPhase;
58 public Job.JobStatus createChildren() {
59 if (mockState == InternalState.CREATING_CHILDREN || (mockState == InternalState.INITIAL && mockPhase== Action.Delete))
60 return mockedJobStatus;
61 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
64 protected Job.JobStatus mockedStatusOrThrow(InternalState expectedState) {
65 if (mockState == expectedState)
66 return mockedJobStatus;
67 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
70 protected MsoRestCallPlan mockedPlanOrThrow(InternalState expectedState) {
71 if (mockState == expectedState)
72 return new MsoRestCallPlan(HttpMethod.POST, "path", Optional.empty(), Optional.empty(), "nothing");
73 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
78 public MsoRestCallPlan planCreateMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId) {
79 return mockedPlanOrThrow(InternalState.CREATE_MYSELF);
84 public MsoRestCallPlan planDeleteMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId) {
85 return mockedPlanOrThrow(InternalState.DELETE_MYSELF);
89 public static class MockCommandTestingStateMachine extends MockCommand {
91 private final JobSharedData sharedData;
93 public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf) {
94 this(mockState, mockPhase, mockedJobStatus, mockedNeedToDeleteMySelf, false);
97 public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf, boolean isService) {
98 super(mockState, mockPhase, mockedJobStatus);
99 this.mockedNeedToDeleteMySelf = mockedNeedToDeleteMySelf;
100 this.isService = isService;
101 this.sharedData = mock(JobSharedData.class, RETURNS_MOCKS);
104 protected final boolean mockedNeedToDeleteMySelf;
105 private final boolean isService;
109 public Job.JobStatus inProgress() {
110 return mockedStatusOrThrow(InternalState.IN_PROGRESS);
115 public Job.JobStatus watchChildren() {
116 return mockedStatusOrThrow(InternalState.WATCHING);
120 public boolean isNeedToDeleteMyself() {
121 return mockedNeedToDeleteMySelf;
125 protected boolean isServiceCommand() {
130 public JobSharedData getSharedData() {
136 public static Object[][] nextStateDeletePhaseProvider() {
137 return new Object[][]{
138 {InternalState.CREATING_CHILDREN, Job.JobStatus.COMPLETED, InternalState.WATCHING},
139 {InternalState.WATCHING, Job.JobStatus.COMPLETED, InternalState.DELETE_MYSELF},
140 {InternalState.WATCHING, Job.JobStatus.IN_PROGRESS, InternalState.WATCHING},
141 {InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.WATCHING},
142 {InternalState.DELETE_MYSELF, Job.JobStatus.COMPLETED, InternalState.IN_PROGRESS},
143 {InternalState.IN_PROGRESS, Job.JobStatus.COMPLETED, InternalState.TERMINAL},
144 {InternalState.IN_PROGRESS, Job.JobStatus.IN_PROGRESS, InternalState.IN_PROGRESS},
145 {InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.IN_PROGRESS},
149 @Test(dataProvider = "nextStateDeletePhaseProvider")
150 public void whenCalcNextStateDeletePhase_expectedStateIsReturned(
151 InternalState internalState, Job.JobStatus jobStatus, InternalState expectedState) {
153 //there is no meaning to the constructor inputs here
154 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Action.Delete, Job.JobStatus.FAILED, true);
155 assertEquals(expectedState, underTest.calcNextStateDeletePhase(jobStatus, internalState));
159 public void whenNoNeedToDeleteMyself_internalStateMovesFromWatchingToTerminal() {
160 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Action.Delete, Job.JobStatus.COMPLETED, false);
161 assertEquals(InternalState.TERMINAL, underTest.calcNextStateDeletePhase(Job.JobStatus.COMPLETED, InternalState.WATCHING));
165 public static Object[][] testShallStopJobDataProvider() {
166 return new Object[][]{
167 {Job.JobStatus.IN_PROGRESS, Action.None, false, false},
168 {Job.JobStatus.COMPLETED_WITH_NO_ACTION, Action.None, false, false},
169 {Job.JobStatus.COMPLETED, Action.None, false, false},
170 {Job.JobStatus.FAILED, Action.None, false, true},
171 {Job.JobStatus.COMPLETED_WITH_ERRORS, Action.None, false, true},
172 {Job.JobStatus.COMPLETED_WITH_ERRORS, Action.None, true, false},
173 {Job.JobStatus.FAILED, Action.None, true, false},
174 {Job.JobStatus.FAILED, Action.Delete, true, true},
175 {Job.JobStatus.FAILED, Action.Create, true, true},
180 @Test(dataProvider = "testShallStopJobDataProvider")
181 public void testShallStopJob(Job.JobStatus jobStatus, Action action, boolean isService, boolean expectedResult) {
182 //in this test, there is no meaning to constructor parameters besides isService
183 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Action.Delete, Job.JobStatus.COMPLETED, false, isService);
185 BaseResource mockedRequest = mock(BaseResource.class);
186 when(underTest.getSharedData().getRequest()).thenReturn(mockedRequest);
187 when(mockedRequest.getAction()).thenReturn(action);
189 assertEquals(expectedResult, underTest.shallStopJob(jobStatus));
193 public static Object[][] testCallDataProvider() {
194 return new Object[][]{
195 {"initial state with successful creating children" ,InternalState.INITIAL, Job.JobStatus.COMPLETED, InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS},
196 {"initial state with failed creating children", InternalState.INITIAL, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED},
197 {"watching state with children still in progress" ,InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS},
198 {"watching state with children that completed with errors" ,InternalState.WATCHING, Job.JobStatus.COMPLETED_WITH_ERRORS, null, Job.JobStatus.COMPLETED_WITH_ERRORS},
199 {"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},
200 {"watching state with children that has completed" ,InternalState.WATCHING, Job.JobStatus.COMPLETED, InternalState.DELETE_MYSELF, Job.JobStatus.RESOURCE_IN_PROGRESS},
201 {"mso call state that failed" ,InternalState.DELETE_MYSELF, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED},
202 //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},
203 {"mso call state that success" ,InternalState.DELETE_MYSELF, Job.JobStatus.COMPLETED, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS},
204 {"in progress return in progress" ,InternalState.IN_PROGRESS, Job.JobStatus.IN_PROGRESS, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS},
205 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.PAUSE, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS},
206 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.STOPPED, null, Job.JobStatus.STOPPED},
207 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED},
208 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.COMPLETED, null, Job.JobStatus.COMPLETED},
213 @Test(dataProvider = "testCallDataProvider")
214 public void whenCallCommandWithDeletePhase_nextJobStatusAndInternalStateAreAsExpected(
215 String description, InternalState internalState, Job.JobStatus currentStateResult,
216 InternalState expectedNextState, Job.JobStatus expectedNextStatus) {
218 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(internalState, Action.Delete, currentStateResult, true);
219 NextCommand nextCommand = underTest.call();
220 assertEquals(expectedNextStatus, nextCommand.getStatus());
222 //expectedNextState == null means nextCommand has no real command
223 if (expectedNextState!=null) {
224 assertEquals(expectedNextState, (nextCommand.getCommand().getData().get(INTERNAL_STATE)));
225 assertFalse(nextCommand.getStatus().isFinal());
228 assertNull(nextCommand.getCommand());
229 assertTrue(nextCommand.getStatus().isFinal());
233 @Test(expectedExceptions = IllegalStateException.class)
234 public void whenCommandInUnMappedState_exceptionIsThrown() {
235 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Action.Delete, Job.JobStatus.COMPLETED, true);
240 public static Object[][] InProgressDataProvider() {
241 return Stream.of(Job.JobStatus.values())
242 .map(status -> new Object[] { status })
243 .toArray(Object[][]::new);
246 @Test(dataProvider = "InProgressDataProvider")
247 public void whenGetResultFromMso_InProgressReturnThem(Job.JobStatus mockedJobStatus) {
248 Job.JobStatus expectedJobStatus = (mockedJobStatus== Job.JobStatus.PAUSE) ? Job.JobStatus.IN_PROGRESS : mockedJobStatus;
249 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Action.Delete, mockedJobStatus);
250 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenReturn(mockedJobStatus);
251 assertEquals(expectedJobStatus, underTest.inProgress());
255 public static Object[][] InProgressExceptionsDataProvider() {
256 return new Object[][]{
257 {new ProcessingException(""), Job.JobStatus.IN_PROGRESS},
258 {new InProgressStatusService.BadResponseFromMso(null), Job.JobStatus.IN_PROGRESS},
259 {new GenericUncheckedException(""),Job.JobStatus.STOPPED }
263 @Test(dataProvider = "InProgressExceptionsDataProvider")
264 public void whenInProgressStatusServiceThrowException_InProgressReturnStatus(Exception exception, Job.JobStatus expectedJobStatus) {
265 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Action.Delete, expectedJobStatus);
266 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenThrow(exception);
267 assertEquals(expectedJobStatus, underTest.inProgress());
271 public static Object[][] testIsNeedToDeleteMySelfDataProvider() {
272 return Stream.of(Action.values())
273 .map(status -> new Object[] { status })
274 .toArray(Object[][]::new);
277 @Test(dataProvider = "testIsNeedToDeleteMySelfDataProvider")
278 public void testIsNeedToDeleteMySelf(Action action) {
279 boolean expectedResult = (action== Action.Delete);
280 MockCommand underTest = new MockCommand(InternalState.DELETE_MYSELF, Action.Delete, Job.JobStatus.IN_PROGRESS);
281 BaseResource mockedBaseResource = mock(BaseResource.class);
282 when(underTest.getSharedData().getRequest()).thenReturn(mockedBaseResource);
283 when(mockedBaseResource.getAction()).thenReturn(action);
284 assertEquals(expectedResult, underTest.isNeedToDeleteMyself());
288 public static Object[][] testWatchingDataProvider() {
289 return new Object[][]{
290 {"all children final, no failed child ", Job.JobStatus.COMPLETED, Job.JobStatus.COMPLETED},
291 {"all children final, there is failed child ", Job.JobStatus.COMPLETED_WITH_ERRORS, Job.JobStatus.COMPLETED_WITH_ERRORS},
292 {"not all children final", Job.JobStatus.IN_PROGRESS, Job.JobStatus.IN_PROGRESS},
296 @Test(dataProvider = "testWatchingDataProvider")
297 public void testWatching(String desc, Job.JobStatus childrenJobsStatus, Job.JobStatus expectedJobStatus) {
298 MockCommand underTest = new MockCommand(InternalState.WATCHING, Action.Delete, Job.JobStatus.IN_PROGRESS);
299 when(underTest.getWatchChildrenJobsBL().retrieveChildrenJobsStatus(any())).thenReturn(childrenJobsStatus);
300 assertEquals(expectedJobStatus, underTest.watchChildren());