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,
289 convertToMap(networks),
290 convertToMap(vnfGroups),
292 null, false, 1, false,false,null, null, null, null, null, null, null, null);
295 public static ServiceInstantiation createServiceWith2InstancesInEachLevel(Action action) {
296 return createService(
298 createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action),
299 createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action)),
301 createNetwork(action),
302 createNetwork(action)),
304 createGroup(ImmutableList.of(createMember(action), createMember(action)), action),
305 createGroup(ImmutableList.of(createMember(action), createMember(action)), action))
309 static InstanceGroup createGroup(List<InstanceGroupMember> groupMembers, Action action) {
310 return new InstanceGroup(mock(ModelInfo.class), null, action.name(), false, null, convertToMap(groupMembers), null, null, null,
314 static InstanceGroupMember createMember(Action action) {
315 return new InstanceGroupMember(null, action.toString(), null, null, null, null, null);
318 static Vnf createVnf(List<VfModule> vfModules, Action action) {
319 Map<String, Map<String, VfModule>> vfModulesMap = new HashMap<>();
320 vfModulesMap.put("abc",convertToMap(vfModules));
322 return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, vfModulesMap, null, null, null,
326 static Vnf createVnf(Action action) {
327 return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null,null, null, null, null,
331 static VfModule createVfModule(Action action) {
332 return new VfModule(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null,
333 false, false, null, null, null, null, null, null, null, null, null);
336 static Network createNetwork(Action action) {
337 return new Network(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, null, null, null,
343 public static Object[][] testIsDescendantHasActionDataProvider() {
344 return new Object[][]{
345 {"empty service", Create, false, createService(emptyList(), emptyList(), emptyList())},
346 {"instance group with None", Create, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), None)))},
347 {"instance group with Create", Create, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), Create)))},
348 {"instance group None + member Delete", Delete, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Delete)), None)))},
349 {"instance group None + member Create", Delete, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create)), None)))},
350 {"instance group None + member Create + member Delete", Delete, true,
351 createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create), createMember(Delete)), None)))},
352 {"vnf Create", Delete, false, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())},
353 {"vnf Create", Create, true, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())},
354 {"vnf Create null VfModules internal map", Create, false, createService(ImmutableList.of(createVnf(null, Delete)), emptyList(),emptyList())},
355 {"vnf Delete with null VfModules", Create, false, createService(ImmutableList.of(createVnf(Delete)), emptyList(),emptyList())},
356 {"vnf None + VfModule Create", Create, true, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(Create)), None)), emptyList(),emptyList())},
357 {"vnf None + VfModule None", Create, false, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(None)), None)), emptyList(),emptyList())},
358 {"network Create", Create, true, createService(emptyList(), ImmutableList.of(createNetwork(Create)), emptyList())},
359 {"network Delete", Create, false, createService(emptyList(), ImmutableList.of(createNetwork(Delete)), emptyList())},
363 @Test(dataProvider = "testIsDescendantHasActionDataProvider")
364 public void testIsDescendantHasAction(String desc, Action action, boolean expectedResult, BaseResource request) {
365 //in this test, there is no meaning to constructor parameters
366 MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, COMPLETED);
367 assertEquals(expectedResult, underTest.isDescendantHasAction(request, action));
371 public static Object[][] testCallDataProvider() {
372 return new Object[][]{
373 {"initial state with successful creating children" ,InternalState.INITIAL, COMPLETED, InternalState.WATCHING, RESOURCE_IN_PROGRESS},
374 {"initial state with failed creating children", InternalState.INITIAL, FAILED, null, FAILED},
375 {"watching state with children still in progress" ,InternalState.WATCHING, RESOURCE_IN_PROGRESS, InternalState.WATCHING, RESOURCE_IN_PROGRESS},
376 {"watching state with children that completed with errors" ,InternalState.WATCHING, COMPLETED_WITH_ERRORS, null, COMPLETED_WITH_ERRORS},
377 {"watching state with children that completed with no action" ,InternalState.WATCHING, COMPLETED_WITH_NO_ACTION, InternalState.DELETE_MYSELF, RESOURCE_IN_PROGRESS},
378 {"watching state with children that has completed" ,InternalState.WATCHING, COMPLETED, InternalState.DELETE_MYSELF, RESOURCE_IN_PROGRESS},
379 {"mso call state that failed" ,InternalState.DELETE_MYSELF, FAILED, null, FAILED},
380 //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},
381 {"mso call state that success" ,InternalState.DELETE_MYSELF, COMPLETED, InternalState.IN_PROGRESS, RESOURCE_IN_PROGRESS},
382 {"in progress return in progress" ,InternalState.IN_PROGRESS, IN_PROGRESS, InternalState.IN_PROGRESS, RESOURCE_IN_PROGRESS},
383 {"in progress return in pause" ,InternalState.IN_PROGRESS, PAUSE, InternalState.IN_PROGRESS, RESOURCE_IN_PROGRESS},
384 {"in progress return in pause" ,InternalState.IN_PROGRESS, STOPPED, null, STOPPED},
385 {"in progress return in pause" ,InternalState.IN_PROGRESS, FAILED, null, FAILED},
386 {"in progress return in pause" ,InternalState.IN_PROGRESS, COMPLETED, null, COMPLETED},
391 @Test(dataProvider = "testCallDataProvider")
392 public void whenCallCommandWithDeletePhase_nextJobStatusAndInternalStateAreAsExpected(
393 String description, InternalState internalState, Job.JobStatus currentStateResult,
394 InternalState expectedNextState, Job.JobStatus expectedNextStatus) {
396 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(internalState, Delete, currentStateResult, true);
397 NextCommand nextCommand = underTest.call();
398 assertEquals(expectedNextStatus, nextCommand.getStatus());
400 //expectedNextState == null means nextCommand has no real command
401 if (expectedNextState!=null) {
402 assertEquals(expectedNextState, (nextCommand.getCommand().getData().get(INTERNAL_STATE)));
403 assertFalse(nextCommand.getStatus().isFinal());
406 assertNull(nextCommand.getCommand());
407 assertTrue(nextCommand.getStatus().isFinal());
412 public static Object[][] InProgressDataProvider() {
413 return Stream.of(Job.JobStatus.values())
414 .map(status -> new Object[] { status })
415 .toArray(Object[][]::new);
418 @Test(dataProvider = "InProgressDataProvider")
419 public void whenGetResultFromMso_InProgressReturnThem(Job.JobStatus mockedJobStatus) {
420 Job.JobStatus expectedJobStatus = (mockedJobStatus== PAUSE) ? IN_PROGRESS : mockedJobStatus;
421 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, mockedJobStatus);
422 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenReturn(mockedJobStatus);
424 // we need to mock the request for pause after completion only when the status is completed
425 if(mockedJobStatus == COMPLETED){
426 BaseResource mockedBaseResource = mock(BaseResource.class);
427 when(underTest.getSharedData().getRequest()).thenReturn(mockedBaseResource);
429 assertEquals(expectedJobStatus, underTest.inProgress());
433 public static Object[][] InProgressExceptionsDataProvider() {
434 return new Object[][]{
435 {new ProcessingException(""), IN_PROGRESS},
436 {new InProgressStatusService.BadResponseFromMso(null), IN_PROGRESS},
437 {new GenericUncheckedException(""), STOPPED }
441 @Test(dataProvider = "InProgressExceptionsDataProvider")
442 public void whenInProgressStatusServiceThrowException_InProgressReturnStatus(Exception exception, Job.JobStatus expectedJobStatus) {
443 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, expectedJobStatus);
444 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenThrow(exception);
445 assertEquals(expectedJobStatus, underTest.inProgress());
449 public static Object[][] testIsNeedToDeleteMySelfDataProvider() {
450 return Stream.of(values())
451 .map(status -> new Object[] { status })
452 .toArray(Object[][]::new);
455 @Test(dataProvider = "testIsNeedToDeleteMySelfDataProvider")
456 public void testIsNeedToDeleteMySelf(Action action) {
457 boolean expectedResult = (action== Delete);
458 MockCommand underTest = new MockCommand(InternalState.DELETE_MYSELF, Delete, IN_PROGRESS);
459 BaseResource mockedBaseResource = mock(BaseResource.class);
460 when(underTest.getSharedData().getRequest()).thenReturn(mockedBaseResource);
461 when(mockedBaseResource.getAction()).thenReturn(action);
462 assertEquals(expectedResult, underTest.isNeedToDeleteMyself());
466 public static Object[][] testWatchingDataProvider() {
467 return new Object[][]{
468 {"all children final, no failed child ", COMPLETED, COMPLETED},
469 {"all children final, there is failed child ", COMPLETED_WITH_ERRORS, COMPLETED_WITH_ERRORS},
470 {"not all children final", IN_PROGRESS, IN_PROGRESS},
474 @Test(dataProvider = "testWatchingDataProvider")
475 public void testWatching(String desc, Job.JobStatus childrenJobsStatus, Job.JobStatus expectedJobStatus) {
476 MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, IN_PROGRESS);
477 when(underTest.getWatchChildrenJobsBL().retrieveChildrenJobsStatus(any())).thenReturn(childrenJobsStatus);
478 assertEquals(expectedJobStatus, underTest.watchChildren());
482 public static Object[][] testCalcInitialStateDataProvider() {
483 return new Object[][]{
484 {Delete, true, Delete, InternalState.CREATING_CHILDREN},
485 {Delete, false, Delete, InternalState.DELETE_MYSELF},
486 {Delete, false, Create, InternalState.TERMINAL},
487 {Delete, true, Create, InternalState.CREATING_CHILDREN},
488 {Create, true, Create, InternalState.CREATE_MYSELF},
489 {Create, false, Create, InternalState.CREATE_MYSELF},
490 {Create, false, Delete, InternalState.TERMINAL},
491 {Create, true, Delete, InternalState.CREATING_CHILDREN},
492 {Create, true, Resume, InternalState.RESUME_MYSELF},
493 {Delete, false, Resume, InternalState.TERMINAL},
497 @Test(dataProvider = "testCalcInitialStateDataProvider")
498 public void testCalcInitialState(Action phase, boolean isDescendantHasAction, Action action, InternalState expectedState) {
499 ResourceCommand underTest = mock(ResourceCommand.class);
500 when(underTest.calcInitialState(any(), any())).thenCallRealMethod();
501 when(underTest.isDescendantHasAction(eq(phase))).thenReturn(isDescendantHasAction);
502 when(underTest.getActionType()).thenReturn(action);
503 when(underTest.isNeedToDeleteMyself()).thenCallRealMethod();
504 when(underTest.isNeedToCreateMyself()).thenCallRealMethod();
505 when(underTest.isNeedToResumeMySelf()).thenCallRealMethod();
507 Map<String, String> commandData = ImmutableMap.of(INTERNAL_STATE, InternalState.INITIAL.name());
508 assertEquals(expectedState, underTest.calcInitialState(commandData, phase));
512 //throw exception when call to create children
513 //create children is just example, it could be any other method that called by ResourceCommand.invokeCommand
514 public static class MockCommandThrowExceptionOnCreateChildren extends MockCommandTestingStateMachine {
516 private final RuntimeException exceptionToThrow;
518 public MockCommandThrowExceptionOnCreateChildren(RuntimeException exceptionToThrow) {
519 super(InternalState.CREATING_CHILDREN, Delete, COMPLETED, true);
520 this.exceptionToThrow = exceptionToThrow;
521 doAnswer(returnsFirstArg()).when(this.getWatchChildrenJobsBL()).cumulateJobStatus(any(), any());
526 public Job.JobStatus createChildren() {
527 throw exceptionToThrow;
532 public static Object[][] exceptionAndStateProvider() {
533 return new Object[][]{
534 {new TryAgainException(new Exception()), RESOURCE_IN_PROGRESS},
535 {new AbortingException(new Exception()), FAILED},
539 @Test(dataProvider = "exceptionAndStateProvider")
540 public void whenKnownExceptionThrownInCommandInvocation_thenStateIsAsExpected(RuntimeException exception, Job.JobStatus expectedNextStatus) {
541 MockCommandTestingStateMachine underTest = new MockCommandThrowExceptionOnCreateChildren(exception);
542 NextCommand nextCommand = underTest.call();
543 assertEquals(expectedNextStatus, nextCommand.getStatus());
547 public static Object[][] resourcePosition() {
548 return new Object[][]{
549 {1, 2, 3, ImmutableList.of(1,2,3)},
550 {null, 1, 100, ImmutableList.of(101,1,100)},
551 {null, null, null, ImmutableList.of(1,2,3)},
552 {1,2,2, ImmutableList.of(1,2,2)}
556 @Test(dataProvider = "resourcePosition")
557 public void sortChildren_sortAccordingToPosition(Integer firstPosition, Integer secondPosition, Integer thirdPosition, List<Integer> expectedPositions){
558 BaseResource mockedRequest1 = mock(BaseResource.class);
559 when(mockedRequest1.getPosition()).thenReturn(firstPosition);
560 BaseResource mockedRequest2 = mock(BaseResource.class);
561 when(mockedRequest2.getPosition()).thenReturn(secondPosition);
562 BaseResource mockedRequest3 = mock(BaseResource.class);
563 when(mockedRequest3.getPosition()).thenReturn(thirdPosition);
565 MockCommand underTest = new MockCommand(InternalState.CREATING_CHILDREN, Create, IN_PROGRESS);
566 List<Pair<BaseResource, Integer>> sortedList = underTest.setPositionWhereIsMissing(ImmutableList.of(mockedRequest1, mockedRequest2, mockedRequest3));
568 assertEquals(sortedList.get(0).getSecond(),expectedPositions.get(0));
569 assertEquals(sortedList.get(1).getSecond(),expectedPositions.get(1));
570 assertEquals(sortedList.get(2).getSecond(),expectedPositions.get(2));