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.command.ResourceCommandKt.ACTION_PHASE;
32 import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE;
33 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createGroup;
34 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createMember;
35 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createNetwork;
36 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createService;
37 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createVfModule;
38 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.createVnf;
39 import static org.onap.vid.model.Action.Create;
40 import static org.onap.vid.model.Action.Delete;
41 import static org.onap.vid.model.Action.None;
42 import static org.onap.vid.model.Action.Resume;
43 import static org.onap.vid.model.Action.values;
44 import static org.onap.vid.utils.Logging.getMethodCallerName;
45 import static org.testng.Assert.assertNull;
46 import static org.testng.Assert.assertTrue;
47 import static org.testng.AssertJUnit.assertEquals;
48 import static org.testng.AssertJUnit.assertFalse;
50 import com.google.common.collect.ImmutableList;
51 import com.google.common.collect.ImmutableMap;
52 import java.util.Collections;
53 import java.util.HashMap;
54 import java.util.List;
56 import java.util.Optional;
57 import java.util.UUID;
58 import java.util.stream.Collectors;
59 import java.util.stream.Stream;
60 import javax.ws.rs.ProcessingException;
62 import org.jetbrains.annotations.NotNull;
63 import org.onap.vid.exceptions.AbortingException;
64 import org.onap.vid.exceptions.GenericUncheckedException;
65 import org.onap.vid.exceptions.TryAgainException;
66 import org.onap.vid.job.Job;
67 import org.onap.vid.job.JobAdapter;
68 import org.onap.vid.job.JobsBrokerService;
69 import org.onap.vid.job.NextCommand;
70 import org.onap.vid.job.impl.JobSharedData;
71 import org.onap.vid.model.Action;
72 import org.onap.vid.model.serviceInstantiation.BaseResource;
73 import org.onap.vid.model.serviceInstantiation.InstanceGroup;
74 import org.onap.vid.model.serviceInstantiation.InstanceGroupMember;
75 import org.onap.vid.model.serviceInstantiation.Network;
76 import org.onap.vid.model.serviceInstantiation.ServiceInstantiation;
77 import org.onap.vid.model.serviceInstantiation.VfModule;
78 import org.onap.vid.model.serviceInstantiation.Vnf;
79 import org.onap.vid.mso.RestMsoImplementation;
80 import org.onap.vid.mso.model.ModelInfo;
81 import org.springframework.http.HttpMethod;
82 import org.testng.annotations.DataProvider;
83 import org.testng.annotations.Test;
84 import org.togglz.core.manager.FeatureManager;
86 public class ResourceCommandTest {
88 public static class MockCommand extends ResourceCommand {
90 public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus) {
91 this(mockState, mockPhase, mockedJobStatus, false);
94 public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean lateInit) {
96 mock(RestMsoImplementation.class, RETURNS_MOCKS),
97 mock(InProgressStatusService.class),
98 mock(MsoResultHandlerService.class, RETURNS_MOCKS),
99 mock(WatchChildrenJobsBL.class),
100 mock(JobsBrokerService.class, RETURNS_MOCKS),
101 mock(JobAdapter.class, RETURNS_MOCKS),
102 mock(FeatureManager.class));
103 this.mockedJobStatus = mockedJobStatus;
104 this.mockState = mockState;
105 this.mockPhase = mockPhase;
109 when(this.getWatchChildrenJobsBL().cumulateJobStatus(any(), any())).thenReturn(mockedJobStatus);
112 protected void init() {
113 if (mockState == InternalState.INITIAL) {
114 init(mock(JobSharedData.class), Collections.emptyMap());
116 init(mock(JobSharedData.class), ImmutableMap.of(INTERNAL_STATE, mockState.name(), ACTION_PHASE, mockPhase.name()));
120 private final Job.JobStatus mockedJobStatus;
121 private final InternalState mockState;
122 private final Action mockPhase;
127 public Job.JobStatus createChildren() {
128 if (mockState == InternalState.CREATING_CHILDREN || (mockState == InternalState.INITIAL && mockPhase== Delete))
129 return mockedJobStatus;
130 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
133 protected Job.JobStatus mockedStatusOrThrow(InternalState expectedState) {
134 if (mockState == expectedState)
135 return mockedJobStatus;
136 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
139 protected MsoRestCallPlan mockedPlanOrThrow(InternalState expectedState) {
140 if (mockState == expectedState)
141 return new MsoRestCallPlan(HttpMethod.POST, "path", Optional.empty(), Optional.empty(), "nothing");
142 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
147 public MsoRestCallPlan planCreateMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId, String testApi) {
148 return mockedPlanOrThrow(InternalState.CREATE_MYSELF);
153 public MsoRestCallPlan planDeleteMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId) {
154 return mockedPlanOrThrow(InternalState.DELETE_MYSELF);
158 public static class MockCommandTestingStateMachine extends MockCommand {
160 private final JobSharedData sharedData;
161 private final boolean isDescendantHasAction;
163 public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf) {
164 this(mockState, mockPhase, mockedJobStatus, mockedNeedToDeleteMySelf, false, true);
167 public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf, boolean isService, boolean isDescendantHasAction) {
168 super(mockState, mockPhase, mockedJobStatus, true);
169 this.mockedNeedToDeleteMySelf = mockedNeedToDeleteMySelf;
170 this.isService = isService;
171 this.sharedData = mock(JobSharedData.class, RETURNS_MOCKS);
172 this.isDescendantHasAction = isDescendantHasAction;
176 protected final boolean mockedNeedToDeleteMySelf;
177 private final boolean isService;
181 public Job.JobStatus inProgress() {
182 return mockedStatusOrThrow(InternalState.IN_PROGRESS);
187 public Job.JobStatus watchChildren() {
188 return mockedStatusOrThrow(InternalState.WATCHING);
192 public boolean isNeedToDeleteMyself() {
193 return mockedNeedToDeleteMySelf;
197 protected boolean isServiceCommand() {
202 public JobSharedData getSharedData() {
207 protected boolean isDescendantHasAction(@NotNull Action phase) {
208 return isDescendantHasAction;
213 public static Object[][] nextStateDeletePhaseProvider() {
214 return new Object[][]{
215 {InternalState.CREATING_CHILDREN, Job.JobStatus.COMPLETED, InternalState.WATCHING},
216 {InternalState.WATCHING, Job.JobStatus.COMPLETED, InternalState.DELETE_MYSELF},
217 {InternalState.WATCHING, Job.JobStatus.IN_PROGRESS, InternalState.WATCHING},
218 {InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.WATCHING},
219 {InternalState.DELETE_MYSELF, Job.JobStatus.COMPLETED, InternalState.IN_PROGRESS},
220 {InternalState.IN_PROGRESS, Job.JobStatus.COMPLETED, InternalState.TERMINAL},
221 {InternalState.IN_PROGRESS, Job.JobStatus.IN_PROGRESS, InternalState.IN_PROGRESS},
222 {InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.IN_PROGRESS},
226 @Test(dataProvider = "nextStateDeletePhaseProvider")
227 public void whenCalcNextStateDeletePhase_expectedStateIsReturned(
228 InternalState internalState, Job.JobStatus jobStatus, InternalState expectedState) {
230 //there is no meaning to the constructor inputs here
231 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Delete, Job.JobStatus.FAILED, true);
232 assertEquals(expectedState, underTest.calcNextStateDeletePhase(jobStatus, internalState));
236 public void whenNoNeedToDeleteMyself_internalStateMovesFromWatchingToTerminal() {
237 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Delete, Job.JobStatus.COMPLETED, false);
238 assertEquals(InternalState.TERMINAL, underTest.calcNextStateDeletePhase(Job.JobStatus.COMPLETED, InternalState.WATCHING));
242 public static Object[][] testShallStopJobDataProvider() {
243 return new Object[][]{
244 {Job.JobStatus.IN_PROGRESS, None, false, false},
245 {Job.JobStatus.COMPLETED_WITH_NO_ACTION, None, false, false},
246 {Job.JobStatus.COMPLETED, None, false, false},
247 {Job.JobStatus.FAILED, None, false, true},
248 {Job.JobStatus.COMPLETED_WITH_ERRORS, None, false, true},
249 {Job.JobStatus.COMPLETED_WITH_ERRORS, None, true, false},
250 {Job.JobStatus.FAILED, None, true, false},
251 {Job.JobStatus.FAILED, Delete, true, true},
252 {Job.JobStatus.FAILED, Create, true, true},
257 @Test(dataProvider = "testShallStopJobDataProvider")
258 public void testShallStopJob(Job.JobStatus jobStatus, Action action, boolean isService, boolean expectedResult) {
259 //in this test, there is no meaning to constructor parameters besides isService
260 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Delete, Job.JobStatus.COMPLETED, false, isService, true);
262 BaseResource mockedRequest = mock(BaseResource.class);
263 when(underTest.getSharedData().getRequest()).thenReturn(mockedRequest);
264 when(mockedRequest.getAction()).thenReturn(action);
266 assertEquals(expectedResult, underTest.shallStopJob(jobStatus));
269 public static class FakeResourceCreator {
271 public static<T> Map<String, T> convertToMap(List<T> list) {
275 return list.stream().collect(Collectors.toMap(x-> UUID.randomUUID().toString(), x->x));
278 static ServiceInstantiation createService(List<Vnf> vnfs, List<Network> networks, List<InstanceGroup> vnfGroups) {
279 return new ServiceInstantiation(mock(ModelInfo.class), null, null, null, null, null, null, null, null, null, null, null, null, null, null,
281 convertToMap(networks),
282 convertToMap(vnfGroups),
284 null, false, 1, false,false,null, null, null, null, null, null, null, null);
287 public static ServiceInstantiation createServiceWith2InstancesInEachLevel(Action action) {
288 return createService(
290 createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action),
291 createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action)),
293 createNetwork(action),
294 createNetwork(action)),
296 createGroup(ImmutableList.of(createMember(action), createMember(action)), action),
297 createGroup(ImmutableList.of(createMember(action), createMember(action)), action))
301 static InstanceGroup createGroup(List<InstanceGroupMember> groupMembers, Action action) {
302 return new InstanceGroup(mock(ModelInfo.class), null, action.name(), false, null, convertToMap(groupMembers), null, null, null,
306 static InstanceGroupMember createMember(Action action) {
307 return new InstanceGroupMember(null, action.toString(), null, null, null, null, null);
310 static Vnf createVnf(List<VfModule> vfModules, Action action) {
311 Map<String, Map<String, VfModule>> vfModulesMap = new HashMap<>();
312 vfModulesMap.put("abc",convertToMap(vfModules));
314 return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, vfModulesMap, null, null, null,
318 static Vnf createVnf(Action action) {
319 return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null,null, null, null, null,
323 static VfModule createVfModule(Action action) {
324 return new VfModule(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null,
325 false, false, null, null, null, null, null, null, null, null, null);
328 static Network createNetwork(Action action) {
329 return new Network(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, null, null, null,
335 public static Object[][] testIsDescendantHasActionDataProvider() {
336 return new Object[][]{
337 {"empty service", Create, false, createService(emptyList(), emptyList(), emptyList())},
338 {"instance group with None", Create, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), None)))},
339 {"instance group with Create", Create, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), Create)))},
340 {"instance group None + member Delete", Delete, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Delete)), None)))},
341 {"instance group None + member Create", Delete, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create)), None)))},
342 {"instance group None + member Create + member Delete", Delete, true,
343 createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create), createMember(Delete)), None)))},
344 {"vnf Create", Delete, false, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())},
345 {"vnf Create", Create, true, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())},
346 {"vnf Create null VfModules internal map", Create, false, createService(ImmutableList.of(createVnf(null, Delete)), emptyList(),emptyList())},
347 {"vnf Delete with null VfModules", Create, false, createService(ImmutableList.of(createVnf(Delete)), emptyList(),emptyList())},
348 {"vnf None + VfModule Create", Create, true, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(Create)), None)), emptyList(),emptyList())},
349 {"vnf None + VfModule None", Create, false, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(None)), None)), emptyList(),emptyList())},
350 {"network Create", Create, true, createService(emptyList(), ImmutableList.of(createNetwork(Create)), emptyList())},
351 {"network Delete", Create, false, createService(emptyList(), ImmutableList.of(createNetwork(Delete)), emptyList())},
355 @Test(dataProvider = "testIsDescendantHasActionDataProvider")
356 public void testIsDescendantHasAction(String desc, Action action, boolean expectedResult, BaseResource request) {
357 //in this test, there is no meaning to constructor parameters
358 MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, Job.JobStatus.COMPLETED);
359 assertEquals(expectedResult, underTest.isDescendantHasAction(request, action));
363 public static Object[][] testCallDataProvider() {
364 return new Object[][]{
365 {"initial state with successful creating children" ,InternalState.INITIAL, Job.JobStatus.COMPLETED, InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS},
366 {"initial state with failed creating children", InternalState.INITIAL, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED},
367 {"watching state with children still in progress" ,InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS},
368 {"watching state with children that completed with errors" ,InternalState.WATCHING, Job.JobStatus.COMPLETED_WITH_ERRORS, null, Job.JobStatus.COMPLETED_WITH_ERRORS},
369 {"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},
370 {"watching state with children that has completed" ,InternalState.WATCHING, Job.JobStatus.COMPLETED, InternalState.DELETE_MYSELF, Job.JobStatus.RESOURCE_IN_PROGRESS},
371 {"mso call state that failed" ,InternalState.DELETE_MYSELF, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED},
372 //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},
373 {"mso call state that success" ,InternalState.DELETE_MYSELF, Job.JobStatus.COMPLETED, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS},
374 {"in progress return in progress" ,InternalState.IN_PROGRESS, Job.JobStatus.IN_PROGRESS, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS},
375 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.PAUSE, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS},
376 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.STOPPED, null, Job.JobStatus.STOPPED},
377 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED},
378 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.COMPLETED, null, Job.JobStatus.COMPLETED},
383 @Test(dataProvider = "testCallDataProvider")
384 public void whenCallCommandWithDeletePhase_nextJobStatusAndInternalStateAreAsExpected(
385 String description, InternalState internalState, Job.JobStatus currentStateResult,
386 InternalState expectedNextState, Job.JobStatus expectedNextStatus) {
388 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(internalState, Delete, currentStateResult, true);
389 NextCommand nextCommand = underTest.call();
390 assertEquals(expectedNextStatus, nextCommand.getStatus());
392 //expectedNextState == null means nextCommand has no real command
393 if (expectedNextState!=null) {
394 assertEquals(expectedNextState, (nextCommand.getCommand().getData().get(INTERNAL_STATE)));
395 assertFalse(nextCommand.getStatus().isFinal());
398 assertNull(nextCommand.getCommand());
399 assertTrue(nextCommand.getStatus().isFinal());
404 public static Object[][] InProgressDataProvider() {
405 return Stream.of(Job.JobStatus.values())
406 .map(status -> new Object[] { status })
407 .toArray(Object[][]::new);
410 @Test(dataProvider = "InProgressDataProvider")
411 public void whenGetResultFromMso_InProgressReturnThem(Job.JobStatus mockedJobStatus) {
412 Job.JobStatus expectedJobStatus = (mockedJobStatus== Job.JobStatus.PAUSE) ? Job.JobStatus.IN_PROGRESS : mockedJobStatus;
413 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, mockedJobStatus);
414 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenReturn(mockedJobStatus);
415 assertEquals(expectedJobStatus, underTest.inProgress());
419 public static Object[][] InProgressExceptionsDataProvider() {
420 return new Object[][]{
421 {new ProcessingException(""), Job.JobStatus.IN_PROGRESS},
422 {new InProgressStatusService.BadResponseFromMso(null), Job.JobStatus.IN_PROGRESS},
423 {new GenericUncheckedException(""),Job.JobStatus.STOPPED }
427 @Test(dataProvider = "InProgressExceptionsDataProvider")
428 public void whenInProgressStatusServiceThrowException_InProgressReturnStatus(Exception exception, Job.JobStatus expectedJobStatus) {
429 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, expectedJobStatus);
430 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenThrow(exception);
431 assertEquals(expectedJobStatus, underTest.inProgress());
435 public static Object[][] testIsNeedToDeleteMySelfDataProvider() {
436 return Stream.of(values())
437 .map(status -> new Object[] { status })
438 .toArray(Object[][]::new);
441 @Test(dataProvider = "testIsNeedToDeleteMySelfDataProvider")
442 public void testIsNeedToDeleteMySelf(Action action) {
443 boolean expectedResult = (action== Delete);
444 MockCommand underTest = new MockCommand(InternalState.DELETE_MYSELF, Delete, Job.JobStatus.IN_PROGRESS);
445 BaseResource mockedBaseResource = mock(BaseResource.class);
446 when(underTest.getSharedData().getRequest()).thenReturn(mockedBaseResource);
447 when(mockedBaseResource.getAction()).thenReturn(action);
448 assertEquals(expectedResult, underTest.isNeedToDeleteMyself());
452 public static Object[][] testWatchingDataProvider() {
453 return new Object[][]{
454 {"all children final, no failed child ", Job.JobStatus.COMPLETED, Job.JobStatus.COMPLETED},
455 {"all children final, there is failed child ", Job.JobStatus.COMPLETED_WITH_ERRORS, Job.JobStatus.COMPLETED_WITH_ERRORS},
456 {"not all children final", Job.JobStatus.IN_PROGRESS, Job.JobStatus.IN_PROGRESS},
460 @Test(dataProvider = "testWatchingDataProvider")
461 public void testWatching(String desc, Job.JobStatus childrenJobsStatus, Job.JobStatus expectedJobStatus) {
462 MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, Job.JobStatus.IN_PROGRESS);
463 when(underTest.getWatchChildrenJobsBL().retrieveChildrenJobsStatus(any())).thenReturn(childrenJobsStatus);
464 assertEquals(expectedJobStatus, underTest.watchChildren());
468 public static Object[][] testCalcInitialStateDataProvider() {
469 return new Object[][]{
470 {Delete, true, Delete, InternalState.CREATING_CHILDREN},
471 {Delete, false, Delete, InternalState.DELETE_MYSELF},
472 {Delete, false, Create, InternalState.TERMINAL},
473 {Delete, true, Create, InternalState.CREATING_CHILDREN},
474 {Create, true, Create, InternalState.CREATE_MYSELF},
475 {Create, false, Create, InternalState.CREATE_MYSELF},
476 {Create, false, Delete, InternalState.TERMINAL},
477 {Create, true, Delete, InternalState.CREATING_CHILDREN},
478 {Create, true, Resume, InternalState.RESUME_MYSELF},
479 {Delete, false, Resume, InternalState.TERMINAL},
483 @Test(dataProvider = "testCalcInitialStateDataProvider")
484 public void testCalcInitialState(Action phase, boolean isDescendantHasAction, Action action, InternalState expectedState) {
485 ResourceCommand underTest = mock(ResourceCommand.class);
486 when(underTest.calcInitialState(any(), any())).thenCallRealMethod();
487 when(underTest.isDescendantHasAction(eq(phase))).thenReturn(isDescendantHasAction);
488 when(underTest.getActionType()).thenReturn(action);
489 when(underTest.isNeedToDeleteMyself()).thenCallRealMethod();
490 when(underTest.isNeedToCreateMyself()).thenCallRealMethod();
491 when(underTest.isNeedToResumeMySelf()).thenCallRealMethod();
493 Map<String, String> commandData = ImmutableMap.of(INTERNAL_STATE, InternalState.INITIAL.name());
494 assertEquals(expectedState, underTest.calcInitialState(commandData, phase));
498 //throw exception when call to create children
499 //create children is just example, it could be any other method that called by ResourceCommand.invokeCommand
500 public static class MockCommandThrowExceptionOnCreateChildren extends MockCommandTestingStateMachine {
502 private final RuntimeException exceptionToThrow;
504 public MockCommandThrowExceptionOnCreateChildren(RuntimeException exceptionToThrow) {
505 super(InternalState.CREATING_CHILDREN, Delete, Job.JobStatus.COMPLETED, true);
506 this.exceptionToThrow = exceptionToThrow;
507 doAnswer(returnsFirstArg()).when(this.getWatchChildrenJobsBL()).cumulateJobStatus(any(), any());
512 public Job.JobStatus createChildren() {
513 throw exceptionToThrow;
518 public static Object[][] exceptionAndStateProvider() {
519 return new Object[][]{
520 {new TryAgainException(new Exception()), Job.JobStatus.RESOURCE_IN_PROGRESS},
521 {new AbortingException(new Exception()), Job.JobStatus.FAILED},
525 @Test(dataProvider = "exceptionAndStateProvider")
526 public void whenKnownExceptionThrownInCommandInvocation_thenStateIsAsExpected(RuntimeException exception, Job.JobStatus expectedNextStatus) {
527 MockCommandTestingStateMachine underTest = new MockCommandThrowExceptionOnCreateChildren(exception);
528 NextCommand nextCommand = underTest.call();
529 assertEquals(expectedNextStatus, nextCommand.getStatus());
533 public static Object[][] resourcePosition() {
534 return new Object[][]{
535 {1, 2, 3, ImmutableList.of(1,2,3)},
536 {null, 1, 100, ImmutableList.of(101,1,100)},
537 {null, null, null, ImmutableList.of(1,2,3)},
538 {1,2,2, ImmutableList.of(1,2,2)}
542 @Test(dataProvider = "resourcePosition")
543 public void sortChildren_sortAccordingToPosition(Integer firstPosition, Integer secondPosition, Integer thirdPosition, List<Integer> expectedPositions){
544 BaseResource mockedRequest1 = mock(BaseResource.class);
545 when(mockedRequest1.getPosition()).thenReturn(firstPosition);
546 BaseResource mockedRequest2 = mock(BaseResource.class);
547 when(mockedRequest2.getPosition()).thenReturn(secondPosition);
548 BaseResource mockedRequest3 = mock(BaseResource.class);
549 when(mockedRequest3.getPosition()).thenReturn(thirdPosition);
551 MockCommand underTest = new MockCommand(InternalState.CREATING_CHILDREN, Create, Job.JobStatus.IN_PROGRESS);
552 List<Pair<BaseResource, Integer>> sortedList = underTest.setPositionWhereIsMissing(ImmutableList.of(mockedRequest1, mockedRequest2, mockedRequest3));
554 assertEquals(sortedList.get(0).getSecond(),expectedPositions.get(0));
555 assertEquals(sortedList.get(1).getSecond(),expectedPositions.get(1));
556 assertEquals(sortedList.get(2).getSecond(),expectedPositions.get(2));