2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.vid.job.command;
23 import static java.util.Collections.emptyList;
24 import static org.mockito.AdditionalAnswers.returnsFirstArg;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.Mockito.RETURNS_MOCKS;
27 import static org.mockito.Mockito.doAnswer;
28 import static org.mockito.Mockito.eq;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.when;
31 import static org.onap.vid.job.Job.JobStatus.COMPLETED;
32 import static org.onap.vid.job.Job.JobStatus.COMPLETED_WITH_ERRORS;
33 import static org.onap.vid.job.Job.JobStatus.COMPLETED_WITH_NO_ACTION;
34 import static org.onap.vid.job.Job.JobStatus.FAILED;
35 import static org.onap.vid.job.Job.JobStatus.IN_PROGRESS;
36 import static org.onap.vid.job.Job.JobStatus.PAUSE;
37 import static org.onap.vid.job.Job.JobStatus.RESOURCE_IN_PROGRESS;
38 import static org.onap.vid.job.Job.JobStatus.STOPPED;
39 import static org.onap.vid.job.command.ResourceCommandKt.ACTION_PHASE;
40 import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE;
41 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createGroup;
42 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createMember;
43 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createNetwork;
44 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createService;
45 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createVfModule;
46 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createVnf;
47 import static org.onap.vid.model.Action.Create;
48 import static org.onap.vid.model.Action.Delete;
49 import static org.onap.vid.model.Action.None;
50 import static org.onap.vid.model.Action.Resume;
51 import static org.onap.vid.model.Action.values;
52 import static org.onap.vid.utils.Logging.getMethodCallerName;
53 import static org.testng.Assert.assertNull;
54 import static org.testng.Assert.assertTrue;
55 import static org.testng.AssertJUnit.assertEquals;
56 import static org.testng.AssertJUnit.assertFalse;
58 import com.google.common.collect.ImmutableList;
59 import com.google.common.collect.ImmutableMap;
60 import java.util.Collections;
61 import java.util.HashMap;
62 import java.util.List;
64 import java.util.Optional;
65 import java.util.UUID;
66 import java.util.stream.Collectors;
67 import java.util.stream.Stream;
68 import javax.ws.rs.ProcessingException;
70 import org.jetbrains.annotations.NotNull;
71 import org.onap.vid.exceptions.AbortingException;
72 import org.onap.vid.exceptions.GenericUncheckedException;
73 import org.onap.vid.exceptions.TryAgainException;
74 import org.onap.vid.job.Job;
75 import org.onap.vid.job.JobAdapter;
76 import org.onap.vid.job.JobsBrokerService;
77 import org.onap.vid.job.NextCommand;
78 import org.onap.vid.job.impl.JobSharedData;
79 import org.onap.vid.model.Action;
80 import org.onap.vid.model.serviceInstantiation.BaseResource;
81 import org.onap.vid.model.serviceInstantiation.InstanceGroup;
82 import org.onap.vid.model.serviceInstantiation.InstanceGroupMember;
83 import org.onap.vid.model.serviceInstantiation.Network;
84 import org.onap.vid.model.serviceInstantiation.ServiceInstantiation;
85 import org.onap.vid.model.serviceInstantiation.VfModule;
86 import org.onap.vid.model.serviceInstantiation.Vnf;
87 import org.onap.vid.mso.RestMsoImplementation;
88 import org.onap.vid.mso.model.ModelInfo;
89 import org.springframework.http.HttpMethod;
90 import org.testng.annotations.DataProvider;
91 import org.testng.annotations.Test;
92 import org.togglz.core.manager.FeatureManager;
94 public class ResourceCommandTest {
96 public static class MockCommand extends ResourceCommand {
98 public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus) {
99 this(mockState, mockPhase, mockedJobStatus, false);
102 public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean lateInit) {
104 mock(RestMsoImplementation.class, RETURNS_MOCKS),
105 mock(InProgressStatusService.class),
106 mock(MsoResultHandlerService.class, RETURNS_MOCKS),
107 mock(WatchChildrenJobsBL.class),
108 mock(JobsBrokerService.class, RETURNS_MOCKS),
109 mock(JobAdapter.class, RETURNS_MOCKS),
110 mock(FeatureManager.class));
111 this.mockedJobStatus = mockedJobStatus;
112 this.mockState = mockState;
113 this.mockPhase = mockPhase;
117 when(this.getWatchChildrenJobsBL().cumulateJobStatus(any(), any())).thenReturn(mockedJobStatus);
120 protected void init() {
121 if (mockState == InternalState.INITIAL) {
122 init(mock(JobSharedData.class), Collections.emptyMap());
124 init(mock(JobSharedData.class), ImmutableMap.of(INTERNAL_STATE, mockState.name(), ACTION_PHASE, mockPhase.name()));
128 private final Job.JobStatus mockedJobStatus;
129 private final InternalState mockState;
130 private final Action mockPhase;
135 public Job.JobStatus createChildren() {
136 if (mockState == InternalState.CREATING_CHILDREN || (mockState == InternalState.INITIAL && mockPhase== Delete))
137 return mockedJobStatus;
138 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
141 protected Job.JobStatus mockedStatusOrThrow(InternalState expectedState) {
142 if (mockState == expectedState)
143 return mockedJobStatus;
144 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
147 protected MsoRestCallPlan mockedPlanOrThrow(InternalState expectedState) {
148 if (mockState == expectedState)
149 return new MsoRestCallPlan(HttpMethod.POST, "path", Optional.empty(), Optional.empty(), "nothing");
150 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
155 public MsoRestCallPlan planCreateMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId, String testApi) {
156 return mockedPlanOrThrow(InternalState.CREATE_MYSELF);
161 public MsoRestCallPlan planDeleteMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId) {
162 return mockedPlanOrThrow(InternalState.DELETE_MYSELF);
166 public static class MockCommandTestingStateMachine extends MockCommand {
168 private final JobSharedData sharedData;
169 private final boolean isDescendantHasAction;
171 public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf) {
172 this(mockState, mockPhase, mockedJobStatus, mockedNeedToDeleteMySelf, false, true);
175 public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf, boolean isService, boolean isDescendantHasAction) {
176 super(mockState, mockPhase, mockedJobStatus, true);
177 this.mockedNeedToDeleteMySelf = mockedNeedToDeleteMySelf;
178 this.isService = isService;
179 this.sharedData = mock(JobSharedData.class, RETURNS_MOCKS);
180 this.isDescendantHasAction = isDescendantHasAction;
184 protected final boolean mockedNeedToDeleteMySelf;
185 private final boolean isService;
189 public Job.JobStatus inProgress() {
190 return mockedStatusOrThrow(InternalState.IN_PROGRESS);
195 public Job.JobStatus watchChildren() {
196 return mockedStatusOrThrow(InternalState.WATCHING);
200 public boolean isNeedToDeleteMyself() {
201 return mockedNeedToDeleteMySelf;
205 protected boolean isServiceCommand() {
210 public JobSharedData getSharedData() {
215 protected boolean isDescendantHasAction(@NotNull Action phase) {
216 return isDescendantHasAction;
221 public static Object[][] nextStateDeletePhaseProvider() {
222 return new Object[][]{
223 {InternalState.CREATING_CHILDREN, COMPLETED, InternalState.WATCHING},
224 {InternalState.WATCHING, COMPLETED, InternalState.DELETE_MYSELF},
225 {InternalState.WATCHING, IN_PROGRESS, InternalState.WATCHING},
226 {InternalState.WATCHING, RESOURCE_IN_PROGRESS, InternalState.WATCHING},
227 {InternalState.DELETE_MYSELF, COMPLETED, InternalState.IN_PROGRESS},
228 {InternalState.IN_PROGRESS, COMPLETED, InternalState.TERMINAL},
229 {InternalState.IN_PROGRESS, IN_PROGRESS, InternalState.IN_PROGRESS},
230 {InternalState.IN_PROGRESS, RESOURCE_IN_PROGRESS, InternalState.IN_PROGRESS},
234 @Test(dataProvider = "nextStateDeletePhaseProvider")
235 public void whenCalcNextStateDeletePhase_expectedStateIsReturned(
236 InternalState internalState, Job.JobStatus jobStatus, InternalState expectedState) {
238 //there is no meaning to the constructor inputs here
239 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Delete, FAILED, true);
240 assertEquals(expectedState, underTest.calcNextStateDeletePhase(jobStatus, internalState));
244 public void whenNoNeedToDeleteMyself_internalStateMovesFromWatchingToTerminal() {
245 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Delete, COMPLETED, false);
246 assertEquals(InternalState.TERMINAL, underTest.calcNextStateDeletePhase(COMPLETED, InternalState.WATCHING));
250 public static Object[][] testShallStopJobDataProvider() {
251 return new Object[][]{
252 {IN_PROGRESS, None, false, false},
253 {COMPLETED_WITH_NO_ACTION, None, false, false},
254 {COMPLETED, None, false, false},
255 {FAILED, None, false, true},
256 {COMPLETED_WITH_ERRORS, None, false, true},
257 {COMPLETED_WITH_ERRORS, None, true, false},
258 {FAILED, None, true, false},
259 {FAILED, Delete, true, true},
260 {FAILED, Create, true, true},
265 @Test(dataProvider = "testShallStopJobDataProvider")
266 public void testShallStopJob(Job.JobStatus jobStatus, Action action, boolean isService, boolean expectedResult) {
267 //in this test, there is no meaning to constructor parameters besides isService
268 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Delete, COMPLETED, false, isService, true);
270 BaseResource mockedRequest = mock(BaseResource.class);
271 when(underTest.getSharedData().getRequest()).thenReturn(mockedRequest);
272 when(mockedRequest.getAction()).thenReturn(action);
274 assertEquals(expectedResult, underTest.shallStopJob(jobStatus));
277 public static class FakeResourceCreator {
279 public static<T> Map<String, T> convertToMap(List<T> list) {
283 return list.stream().collect(Collectors.toMap(x-> UUID.randomUUID().toString(), x->x));
286 static ServiceInstantiation createService(List<Vnf> vnfs, List<Network> networks, List<InstanceGroup> vnfGroups) {
287 return new ServiceInstantiation(mock(ModelInfo.class), null, null, null, null, null, null, null, null, null, null, null, null, null, null,
290 convertToMap(networks),
291 convertToMap(vnfGroups),
293 null, false, 1, false,false,null, null, null, null, null, null, null, null);
296 public static ServiceInstantiation createServiceWith2InstancesInEachLevel(Action action) {
297 return createService(
299 createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action),
300 createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action)),
302 createNetwork(action),
303 createNetwork(action)),
305 createGroup(ImmutableList.of(createMember(action), createMember(action)), action),
306 createGroup(ImmutableList.of(createMember(action), createMember(action)), action))
310 static InstanceGroup createGroup(List<InstanceGroupMember> groupMembers, Action action) {
311 return new InstanceGroup(mock(ModelInfo.class), null, action.name(), false, null, convertToMap(groupMembers), null, null, null,
315 static InstanceGroupMember createMember(Action action) {
316 return new InstanceGroupMember(null, action.toString(), null, null, null, null, null);
319 static Vnf createVnf(List<VfModule> vfModules, Action action) {
320 Map<String, Map<String, VfModule>> vfModulesMap = new HashMap<>();
321 vfModulesMap.put("abc",convertToMap(vfModules));
323 return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, vfModulesMap, null, null, null,
327 static Vnf createVnf(Action action) {
328 return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null,null, null, null, null,
332 static VfModule createVfModule(Action action) {
333 return new VfModule(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null,
334 false, false, null, null, null, null, null, null, null, null, null);
337 static Network createNetwork(Action action) {
338 return new Network(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, null, null, null,
344 public static Object[][] testIsDescendantHasActionDataProvider() {
345 return new Object[][]{
346 {"empty service", Create, false, createService(emptyList(), emptyList(), emptyList())},
347 {"instance group with None", Create, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), None)))},
348 {"instance group with Create", Create, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), Create)))},
349 {"instance group None + member Delete", Delete, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Delete)), None)))},
350 {"instance group None + member Create", Delete, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create)), None)))},
351 {"instance group None + member Create + member Delete", Delete, true,
352 createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create), createMember(Delete)), None)))},
353 {"vnf Create", Delete, false, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())},
354 {"vnf Create", Create, true, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())},
355 {"vnf Create null VfModules internal map", Create, false, createService(ImmutableList.of(createVnf(null, Delete)), emptyList(),emptyList())},
356 {"vnf Delete with null VfModules", Create, false, createService(ImmutableList.of(createVnf(Delete)), emptyList(),emptyList())},
357 {"vnf None + VfModule Create", Create, true, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(Create)), None)), emptyList(),emptyList())},
358 {"vnf None + VfModule None", Create, false, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(None)), None)), emptyList(),emptyList())},
359 {"network Create", Create, true, createService(emptyList(), ImmutableList.of(createNetwork(Create)), emptyList())},
360 {"network Delete", Create, false, createService(emptyList(), ImmutableList.of(createNetwork(Delete)), emptyList())},
364 @Test(dataProvider = "testIsDescendantHasActionDataProvider")
365 public void testIsDescendantHasAction(String desc, Action action, boolean expectedResult, BaseResource request) {
366 //in this test, there is no meaning to constructor parameters
367 MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, COMPLETED);
368 assertEquals(expectedResult, underTest.isDescendantHasAction(request, action));
372 public static Object[][] testCallDataProvider() {
373 return new Object[][]{
374 {"initial state with successful creating children" ,InternalState.INITIAL, COMPLETED, InternalState.WATCHING, RESOURCE_IN_PROGRESS},
375 {"initial state with failed creating children", InternalState.INITIAL, FAILED, null, FAILED},
376 {"watching state with children still in progress" ,InternalState.WATCHING, RESOURCE_IN_PROGRESS, InternalState.WATCHING, RESOURCE_IN_PROGRESS},
377 {"watching state with children that completed with errors" ,InternalState.WATCHING, COMPLETED_WITH_ERRORS, null, COMPLETED_WITH_ERRORS},
378 {"watching state with children that completed with no action" ,InternalState.WATCHING, COMPLETED_WITH_NO_ACTION, InternalState.DELETE_MYSELF, RESOURCE_IN_PROGRESS},
379 {"watching state with children that has completed" ,InternalState.WATCHING, COMPLETED, InternalState.DELETE_MYSELF, RESOURCE_IN_PROGRESS},
380 {"mso call state that failed" ,InternalState.DELETE_MYSELF, FAILED, null, FAILED},
381 //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},
382 {"mso call state that success" ,InternalState.DELETE_MYSELF, COMPLETED, InternalState.IN_PROGRESS, RESOURCE_IN_PROGRESS},
383 {"in progress return in progress" ,InternalState.IN_PROGRESS, IN_PROGRESS, InternalState.IN_PROGRESS, RESOURCE_IN_PROGRESS},
384 {"in progress return in pause" ,InternalState.IN_PROGRESS, PAUSE, InternalState.IN_PROGRESS, RESOURCE_IN_PROGRESS},
385 {"in progress return in pause" ,InternalState.IN_PROGRESS, STOPPED, null, STOPPED},
386 {"in progress return in pause" ,InternalState.IN_PROGRESS, FAILED, null, FAILED},
387 {"in progress return in pause" ,InternalState.IN_PROGRESS, COMPLETED, null, COMPLETED},
392 @Test(dataProvider = "testCallDataProvider")
393 public void whenCallCommandWithDeletePhase_nextJobStatusAndInternalStateAreAsExpected(
394 String description, InternalState internalState, Job.JobStatus currentStateResult,
395 InternalState expectedNextState, Job.JobStatus expectedNextStatus) {
397 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(internalState, Delete, currentStateResult, true);
398 NextCommand nextCommand = underTest.call();
399 assertEquals(expectedNextStatus, nextCommand.getStatus());
401 //expectedNextState == null means nextCommand has no real command
402 if (expectedNextState!=null) {
403 assertEquals(expectedNextState, (nextCommand.getCommand().getData().get(INTERNAL_STATE)));
404 assertFalse(nextCommand.getStatus().isFinal());
407 assertNull(nextCommand.getCommand());
408 assertTrue(nextCommand.getStatus().isFinal());
413 public static Object[][] InProgressDataProvider() {
414 return Stream.of(Job.JobStatus.values())
415 .map(status -> new Object[] { status })
416 .toArray(Object[][]::new);
419 @Test(dataProvider = "InProgressDataProvider")
420 public void whenGetResultFromMso_InProgressReturnThem(Job.JobStatus mockedJobStatus) {
421 Job.JobStatus expectedJobStatus = (mockedJobStatus== PAUSE) ? IN_PROGRESS : mockedJobStatus;
422 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, mockedJobStatus);
423 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenReturn(mockedJobStatus);
425 // we need to mock the request for pause after completion only when the status is completed
426 if(mockedJobStatus == COMPLETED){
427 BaseResource mockedBaseResource = mock(BaseResource.class);
428 when(underTest.getSharedData().getRequest()).thenReturn(mockedBaseResource);
430 assertEquals(expectedJobStatus, underTest.inProgress());
434 public static Object[][] InProgressExceptionsDataProvider() {
435 return new Object[][]{
436 {new ProcessingException(""), IN_PROGRESS},
437 {new InProgressStatusService.BadResponseFromMso(null), IN_PROGRESS},
438 {new GenericUncheckedException(""), STOPPED }
442 @Test(dataProvider = "InProgressExceptionsDataProvider")
443 public void whenInProgressStatusServiceThrowException_InProgressReturnStatus(Exception exception, Job.JobStatus expectedJobStatus) {
444 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, expectedJobStatus);
445 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenThrow(exception);
446 assertEquals(expectedJobStatus, underTest.inProgress());
450 public static Object[][] testIsNeedToDeleteMySelfDataProvider() {
451 return Stream.of(values())
452 .map(status -> new Object[] { status })
453 .toArray(Object[][]::new);
456 @Test(dataProvider = "testIsNeedToDeleteMySelfDataProvider")
457 public void testIsNeedToDeleteMySelf(Action action) {
458 boolean expectedResult = (action== Delete);
459 MockCommand underTest = new MockCommand(InternalState.DELETE_MYSELF, Delete, IN_PROGRESS);
460 BaseResource mockedBaseResource = mock(BaseResource.class);
461 when(underTest.getSharedData().getRequest()).thenReturn(mockedBaseResource);
462 when(mockedBaseResource.getAction()).thenReturn(action);
463 assertEquals(expectedResult, underTest.isNeedToDeleteMyself());
467 public static Object[][] testWatchingDataProvider() {
468 return new Object[][]{
469 {"all children final, no failed child ", COMPLETED, COMPLETED},
470 {"all children final, there is failed child ", COMPLETED_WITH_ERRORS, COMPLETED_WITH_ERRORS},
471 {"not all children final", IN_PROGRESS, IN_PROGRESS},
475 @Test(dataProvider = "testWatchingDataProvider")
476 public void testWatching(String desc, Job.JobStatus childrenJobsStatus, Job.JobStatus expectedJobStatus) {
477 MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, IN_PROGRESS);
478 when(underTest.getWatchChildrenJobsBL().retrieveChildrenJobsStatus(any())).thenReturn(childrenJobsStatus);
479 assertEquals(expectedJobStatus, underTest.watchChildren());
483 public static Object[][] testCalcInitialStateDataProvider() {
484 return new Object[][]{
485 {Delete, true, Delete, InternalState.CREATING_CHILDREN},
486 {Delete, false, Delete, InternalState.DELETE_MYSELF},
487 {Delete, false, Create, InternalState.TERMINAL},
488 {Delete, true, Create, InternalState.CREATING_CHILDREN},
489 {Create, true, Create, InternalState.CREATE_MYSELF},
490 {Create, false, Create, InternalState.CREATE_MYSELF},
491 {Create, false, Delete, InternalState.TERMINAL},
492 {Create, true, Delete, InternalState.CREATING_CHILDREN},
493 {Create, true, Resume, InternalState.RESUME_MYSELF},
494 {Delete, false, Resume, InternalState.TERMINAL},
498 @Test(dataProvider = "testCalcInitialStateDataProvider")
499 public void testCalcInitialState(Action phase, boolean isDescendantHasAction, Action action, InternalState expectedState) {
500 ResourceCommand underTest = mock(ResourceCommand.class);
501 when(underTest.calcInitialState(any(), any())).thenCallRealMethod();
502 when(underTest.isDescendantHasAction(eq(phase))).thenReturn(isDescendantHasAction);
503 when(underTest.getActionType()).thenReturn(action);
504 when(underTest.isNeedToDeleteMyself()).thenCallRealMethod();
505 when(underTest.isNeedToCreateMyself()).thenCallRealMethod();
506 when(underTest.isNeedToResumeMySelf()).thenCallRealMethod();
508 Map<String, String> commandData = ImmutableMap.of(INTERNAL_STATE, InternalState.INITIAL.name());
509 assertEquals(expectedState, underTest.calcInitialState(commandData, phase));
513 //throw exception when call to create children
514 //create children is just example, it could be any other method that called by ResourceCommand.invokeCommand
515 public static class MockCommandThrowExceptionOnCreateChildren extends MockCommandTestingStateMachine {
517 private final RuntimeException exceptionToThrow;
519 public MockCommandThrowExceptionOnCreateChildren(RuntimeException exceptionToThrow) {
520 super(InternalState.CREATING_CHILDREN, Delete, COMPLETED, true);
521 this.exceptionToThrow = exceptionToThrow;
522 doAnswer(returnsFirstArg()).when(this.getWatchChildrenJobsBL()).cumulateJobStatus(any(), any());
527 public Job.JobStatus createChildren() {
528 throw exceptionToThrow;
533 public static Object[][] exceptionAndStateProvider() {
534 return new Object[][]{
535 {new TryAgainException(new Exception()), RESOURCE_IN_PROGRESS},
536 {new AbortingException(new Exception()), FAILED},
540 @Test(dataProvider = "exceptionAndStateProvider")
541 public void whenKnownExceptionThrownInCommandInvocation_thenStateIsAsExpected(RuntimeException exception, Job.JobStatus expectedNextStatus) {
542 MockCommandTestingStateMachine underTest = new MockCommandThrowExceptionOnCreateChildren(exception);
543 NextCommand nextCommand = underTest.call();
544 assertEquals(expectedNextStatus, nextCommand.getStatus());
548 public static Object[][] resourcePosition() {
549 return new Object[][]{
550 {1, 2, 3, ImmutableList.of(1,2,3)},
551 {null, 1, 100, ImmutableList.of(101,1,100)},
552 {null, null, null, ImmutableList.of(1,2,3)},
553 {1,2,2, ImmutableList.of(1,2,2)}
557 @Test(dataProvider = "resourcePosition")
558 public void sortChildren_sortAccordingToPosition(Integer firstPosition, Integer secondPosition, Integer thirdPosition, List<Integer> expectedPositions){
559 BaseResource mockedRequest1 = mock(BaseResource.class);
560 when(mockedRequest1.getPosition()).thenReturn(firstPosition);
561 BaseResource mockedRequest2 = mock(BaseResource.class);
562 when(mockedRequest2.getPosition()).thenReturn(secondPosition);
563 BaseResource mockedRequest3 = mock(BaseResource.class);
564 when(mockedRequest3.getPosition()).thenReturn(thirdPosition);
566 MockCommand underTest = new MockCommand(InternalState.CREATING_CHILDREN, Create, IN_PROGRESS);
567 List<Pair<BaseResource, Integer>> sortedList = underTest.setPositionWhereIsMissing(ImmutableList.of(mockedRequest1, mockedRequest2, mockedRequest3));
569 assertEquals(sortedList.get(0).getSecond(),expectedPositions.get(0));
570 assertEquals(sortedList.get(1).getSecond(),expectedPositions.get(1));
571 assertEquals(sortedList.get(2).getSecond(),expectedPositions.get(2));