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 com.google.common.collect.ImmutableList;
24 import com.google.common.collect.ImmutableMap;
25 import org.jetbrains.annotations.NotNull;
26 import org.onap.vid.exceptions.AbortingException;
27 import org.onap.vid.exceptions.GenericUncheckedException;
28 import org.onap.vid.exceptions.TryAgainException;
29 import org.onap.vid.job.Job;
30 import org.onap.vid.job.JobAdapter;
31 import org.onap.vid.job.JobsBrokerService;
32 import org.onap.vid.job.NextCommand;
33 import org.onap.vid.job.impl.JobSharedData;
34 import org.onap.vid.model.Action;
35 import org.onap.vid.model.serviceInstantiation.*;
36 import org.onap.vid.mso.RestMsoImplementation;
37 import org.onap.vid.mso.model.ModelInfo;
38 import org.springframework.http.HttpMethod;
39 import org.testng.annotations.DataProvider;
40 import org.testng.annotations.Test;
42 import javax.ws.rs.ProcessingException;
44 import java.util.stream.Collectors;
45 import java.util.stream.Stream;
47 import static java.util.Collections.emptyList;
48 import static org.mockito.AdditionalAnswers.returnsFirstArg;
49 import static org.mockito.ArgumentMatchers.any;
50 import static org.mockito.Mockito.*;
51 import static org.onap.vid.job.command.ResourceCommandKt.ACTION_PHASE;
52 import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE;
53 import static org.onap.vid.job.command.ResourceCommandTest.FakeResourceCreator.*;
54 import static org.onap.vid.model.Action.*;
55 import static org.onap.vid.utils.Logging.getMethodCallerName;
56 import static org.testng.Assert.assertNull;
57 import static org.testng.Assert.assertTrue;
58 import static org.testng.AssertJUnit.assertEquals;
59 import static org.testng.AssertJUnit.assertFalse;
61 public class ResourceCommandTest {
63 public static class MockCommand extends ResourceCommand {
65 public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus) {
66 this(mockState, mockPhase, mockedJobStatus, false);
69 public MockCommand(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean lateInit) {
71 mock(RestMsoImplementation.class, RETURNS_MOCKS),
72 mock(InProgressStatusService.class),
73 mock(MsoResultHandlerService.class, RETURNS_MOCKS),
74 mock(WatchChildrenJobsBL.class),
75 mock(JobsBrokerService.class, RETURNS_MOCKS),
76 mock(JobAdapter.class, RETURNS_MOCKS));
77 this.mockedJobStatus = mockedJobStatus;
78 this.mockState = mockState;
79 this.mockPhase = mockPhase;
83 when(this.getWatchChildrenJobsBL().cumulateJobStatus(any(), any())).thenReturn(mockedJobStatus);
86 protected void init() {
87 if (mockState == InternalState.INITIAL) {
88 init(mock(JobSharedData.class), Collections.emptyMap());
90 init(mock(JobSharedData.class), ImmutableMap.of(INTERNAL_STATE, mockState.name(), ACTION_PHASE, mockPhase.name()));
94 private final Job.JobStatus mockedJobStatus;
95 private final InternalState mockState;
96 private final Action mockPhase;
101 public Job.JobStatus createChildren() {
102 if (mockState == InternalState.CREATING_CHILDREN || (mockState == InternalState.INITIAL && mockPhase== Delete))
103 return mockedJobStatus;
104 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
107 protected Job.JobStatus mockedStatusOrThrow(InternalState expectedState) {
108 if (mockState == expectedState)
109 return mockedJobStatus;
110 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
113 protected MsoRestCallPlan mockedPlanOrThrow(InternalState expectedState) {
114 if (mockState == expectedState)
115 return new MsoRestCallPlan(HttpMethod.POST, "path", Optional.empty(), Optional.empty(), "nothing");
116 throw (new RuntimeException("Not expected to call "+getMethodCallerName()));
121 public MsoRestCallPlan planCreateMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId, String testApi) {
122 return mockedPlanOrThrow(InternalState.CREATE_MYSELF);
127 public MsoRestCallPlan planDeleteMyselfRestCall(@NotNull CommandParentData commandParentData, @NotNull JobAdapter.AsyncJobRequest request, @NotNull String userId) {
128 return mockedPlanOrThrow(InternalState.DELETE_MYSELF);
132 public static class MockCommandTestingStateMachine extends MockCommand {
134 private final JobSharedData sharedData;
135 private final boolean isDescendantHasAction;
137 public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf) {
138 this(mockState, mockPhase, mockedJobStatus, mockedNeedToDeleteMySelf, false, true);
141 public MockCommandTestingStateMachine(InternalState mockState, Action mockPhase, Job.JobStatus mockedJobStatus, boolean mockedNeedToDeleteMySelf, boolean isService, boolean isDescendantHasAction) {
142 super(mockState, mockPhase, mockedJobStatus, true);
143 this.mockedNeedToDeleteMySelf = mockedNeedToDeleteMySelf;
144 this.isService = isService;
145 this.sharedData = mock(JobSharedData.class, RETURNS_MOCKS);
146 this.isDescendantHasAction = isDescendantHasAction;
150 protected final boolean mockedNeedToDeleteMySelf;
151 private final boolean isService;
155 public Job.JobStatus inProgress() {
156 return mockedStatusOrThrow(InternalState.IN_PROGRESS);
161 public Job.JobStatus watchChildren() {
162 return mockedStatusOrThrow(InternalState.WATCHING);
166 public boolean isNeedToDeleteMyself() {
167 return mockedNeedToDeleteMySelf;
171 protected boolean isServiceCommand() {
176 public JobSharedData getSharedData() {
181 protected boolean isDescendantHasAction(@NotNull Action phase) {
182 return isDescendantHasAction;
187 public static Object[][] nextStateDeletePhaseProvider() {
188 return new Object[][]{
189 {InternalState.CREATING_CHILDREN, Job.JobStatus.COMPLETED, InternalState.WATCHING},
190 {InternalState.WATCHING, Job.JobStatus.COMPLETED, InternalState.DELETE_MYSELF},
191 {InternalState.WATCHING, Job.JobStatus.IN_PROGRESS, InternalState.WATCHING},
192 {InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.WATCHING},
193 {InternalState.DELETE_MYSELF, Job.JobStatus.COMPLETED, InternalState.IN_PROGRESS},
194 {InternalState.IN_PROGRESS, Job.JobStatus.COMPLETED, InternalState.TERMINAL},
195 {InternalState.IN_PROGRESS, Job.JobStatus.IN_PROGRESS, InternalState.IN_PROGRESS},
196 {InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.IN_PROGRESS},
200 @Test(dataProvider = "nextStateDeletePhaseProvider")
201 public void whenCalcNextStateDeletePhase_expectedStateIsReturned(
202 InternalState internalState, Job.JobStatus jobStatus, InternalState expectedState) {
204 //there is no meaning to the constructor inputs here
205 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.TERMINAL, Delete, Job.JobStatus.FAILED, true);
206 assertEquals(expectedState, underTest.calcNextStateDeletePhase(jobStatus, internalState));
210 public void whenNoNeedToDeleteMyself_internalStateMovesFromWatchingToTerminal() {
211 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Delete, Job.JobStatus.COMPLETED, false);
212 assertEquals(InternalState.TERMINAL, underTest.calcNextStateDeletePhase(Job.JobStatus.COMPLETED, InternalState.WATCHING));
216 public static Object[][] testShallStopJobDataProvider() {
217 return new Object[][]{
218 {Job.JobStatus.IN_PROGRESS, None, false, false},
219 {Job.JobStatus.COMPLETED_WITH_NO_ACTION, None, false, false},
220 {Job.JobStatus.COMPLETED, None, false, false},
221 {Job.JobStatus.FAILED, None, false, true},
222 {Job.JobStatus.COMPLETED_WITH_ERRORS, None, false, true},
223 {Job.JobStatus.COMPLETED_WITH_ERRORS, None, true, false},
224 {Job.JobStatus.FAILED, None, true, false},
225 {Job.JobStatus.FAILED, Delete, true, true},
226 {Job.JobStatus.FAILED, Create, true, true},
231 @Test(dataProvider = "testShallStopJobDataProvider")
232 public void testShallStopJob(Job.JobStatus jobStatus, Action action, boolean isService, boolean expectedResult) {
233 //in this test, there is no meaning to constructor parameters besides isService
234 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(InternalState.WATCHING, Delete, Job.JobStatus.COMPLETED, false, isService, true);
236 BaseResource mockedRequest = mock(BaseResource.class);
237 when(underTest.getSharedData().getRequest()).thenReturn(mockedRequest);
238 when(mockedRequest.getAction()).thenReturn(action);
240 assertEquals(expectedResult, underTest.shallStopJob(jobStatus));
243 public static class FakeResourceCreator {
245 public static<T> Map<String, T> convertToMap(List<T> list) {
249 return list.stream().collect(Collectors.toMap(x-> UUID.randomUUID().toString(), x->x));
252 static ServiceInstantiation createService(List<Vnf> vnfs, List<Network> networks, List<InstanceGroup> vnfGroups) {
253 return new ServiceInstantiation(mock(ModelInfo.class), null, null, null, null, null, null, null, null, null, null, null, null, null, null,
255 convertToMap(networks),
256 convertToMap(vnfGroups),
258 null, false, 1, false,false,null, null, null, null, null, null, null);
261 public static ServiceInstantiation createServiceWith2InstancesInEachLevel(Action action) {
262 return createService(
264 createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action),
265 createVnf(ImmutableList.of(createVfModule(action), createVfModule(action)), action)),
267 createNetwork(action),
268 createNetwork(action)),
270 createGroup(ImmutableList.of(createMember(action), createMember(action)), action),
271 createGroup(ImmutableList.of(createMember(action), createMember(action)), action))
275 static InstanceGroup createGroup(List<InstanceGroupMember> groupMembers, Action action) {
276 return new InstanceGroup(mock(ModelInfo.class), null, action.name(), false, null, convertToMap(groupMembers), null, null, null);
279 static InstanceGroupMember createMember(Action action) {
280 return new InstanceGroupMember(null, action.toString(), null, null, null);
283 static Vnf createVnf(List<VfModule> vfModules, Action action) {
284 Map<String, Map<String, VfModule>> vfModulesMap = new HashMap<>();
285 vfModulesMap.put("abc",convertToMap(vfModules));
287 return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, vfModulesMap, null, null, null);
290 static Vnf createVnf(Action action) {
291 return new Vnf(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null,null, null, null, null);
294 static VfModule createVfModule(Action action) {
295 return new VfModule(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, false, false, null, null, null, null);
298 static Network createNetwork(Action action) {
299 return new Network(mock(ModelInfo.class), null, null, action.toString(), null, null, null, null, null, null, false, null, null, null, null);
304 public static Object[][] testIsDescendantHasActionDataProvider() {
305 return new Object[][]{
306 {"empty service", Create, false, createService(emptyList(), emptyList(), emptyList())},
307 {"instance group with None", Create, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), None)))},
308 {"instance group with Create", Create, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(emptyList(), Create)))},
309 {"instance group None + member Delete", Delete, true, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Delete)), None)))},
310 {"instance group None + member Create", Delete, false, createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create)), None)))},
311 {"instance group None + member Create + member Delete", Delete, true,
312 createService(emptyList(), emptyList(), ImmutableList.of(createGroup(ImmutableList.of(createMember(Create), createMember(Delete)), None)))},
313 {"vnf Create", Delete, false, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())},
314 {"vnf Create", Create, true, createService(ImmutableList.of(createVnf(emptyList(), Create)), emptyList(),emptyList())},
315 {"vnf Create null VfModules internal map", Create, false, createService(ImmutableList.of(createVnf(null, Delete)), emptyList(),emptyList())},
316 {"vnf Delete with null VfModules", Create, false, createService(ImmutableList.of(createVnf(Delete)), emptyList(),emptyList())},
317 {"vnf None + VfModule Create", Create, true, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(Create)), None)), emptyList(),emptyList())},
318 {"vnf None + VfModule None", Create, false, createService(ImmutableList.of(createVnf(ImmutableList.of(createVfModule(None)), None)), emptyList(),emptyList())},
319 {"network Create", Create, true, createService(emptyList(), ImmutableList.of(createNetwork(Create)), emptyList())},
320 {"network Delete", Create, false, createService(emptyList(), ImmutableList.of(createNetwork(Delete)), emptyList())},
324 @Test(dataProvider = "testIsDescendantHasActionDataProvider")
325 public void testIsDescendantHasAction(String desc, Action action, boolean expectedResult, BaseResource request) {
326 //in this test, there is no meaning to constructor parameters
327 MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, Job.JobStatus.COMPLETED);
328 assertEquals(expectedResult, underTest.isDescendantHasAction(request, action));
332 public static Object[][] testCallDataProvider() {
333 return new Object[][]{
334 {"initial state with successful creating children" ,InternalState.INITIAL, Job.JobStatus.COMPLETED, InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS},
335 {"initial state with failed creating children", InternalState.INITIAL, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED},
336 {"watching state with children still in progress" ,InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS, InternalState.WATCHING, Job.JobStatus.RESOURCE_IN_PROGRESS},
337 {"watching state with children that completed with errors" ,InternalState.WATCHING, Job.JobStatus.COMPLETED_WITH_ERRORS, null, Job.JobStatus.COMPLETED_WITH_ERRORS},
338 {"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},
339 {"watching state with children that has completed" ,InternalState.WATCHING, Job.JobStatus.COMPLETED, InternalState.DELETE_MYSELF, Job.JobStatus.RESOURCE_IN_PROGRESS},
340 {"mso call state that failed" ,InternalState.DELETE_MYSELF, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED},
341 //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},
342 {"mso call state that success" ,InternalState.DELETE_MYSELF, Job.JobStatus.COMPLETED, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS},
343 {"in progress return in progress" ,InternalState.IN_PROGRESS, Job.JobStatus.IN_PROGRESS, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS},
344 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.PAUSE, InternalState.IN_PROGRESS, Job.JobStatus.RESOURCE_IN_PROGRESS},
345 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.STOPPED, null, Job.JobStatus.STOPPED},
346 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.FAILED, null, Job.JobStatus.FAILED},
347 {"in progress return in pause" ,InternalState.IN_PROGRESS, Job.JobStatus.COMPLETED, null, Job.JobStatus.COMPLETED},
352 @Test(dataProvider = "testCallDataProvider")
353 public void whenCallCommandWithDeletePhase_nextJobStatusAndInternalStateAreAsExpected(
354 String description, InternalState internalState, Job.JobStatus currentStateResult,
355 InternalState expectedNextState, Job.JobStatus expectedNextStatus) {
357 MockCommandTestingStateMachine underTest = new MockCommandTestingStateMachine(internalState, Delete, currentStateResult, true);
358 NextCommand nextCommand = underTest.call();
359 assertEquals(expectedNextStatus, nextCommand.getStatus());
361 //expectedNextState == null means nextCommand has no real command
362 if (expectedNextState!=null) {
363 assertEquals(expectedNextState, (nextCommand.getCommand().getData().get(INTERNAL_STATE)));
364 assertFalse(nextCommand.getStatus().isFinal());
367 assertNull(nextCommand.getCommand());
368 assertTrue(nextCommand.getStatus().isFinal());
373 public static Object[][] InProgressDataProvider() {
374 return Stream.of(Job.JobStatus.values())
375 .map(status -> new Object[] { status })
376 .toArray(Object[][]::new);
379 @Test(dataProvider = "InProgressDataProvider")
380 public void whenGetResultFromMso_InProgressReturnThem(Job.JobStatus mockedJobStatus) {
381 Job.JobStatus expectedJobStatus = (mockedJobStatus== Job.JobStatus.PAUSE) ? Job.JobStatus.IN_PROGRESS : mockedJobStatus;
382 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, mockedJobStatus);
383 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenReturn(mockedJobStatus);
384 assertEquals(expectedJobStatus, underTest.inProgress());
388 public static Object[][] InProgressExceptionsDataProvider() {
389 return new Object[][]{
390 {new ProcessingException(""), Job.JobStatus.IN_PROGRESS},
391 {new InProgressStatusService.BadResponseFromMso(null), Job.JobStatus.IN_PROGRESS},
392 {new GenericUncheckedException(""),Job.JobStatus.STOPPED }
396 @Test(dataProvider = "InProgressExceptionsDataProvider")
397 public void whenInProgressStatusServiceThrowException_InProgressReturnStatus(Exception exception, Job.JobStatus expectedJobStatus) {
398 MockCommand underTest = new MockCommand(InternalState.IN_PROGRESS, Delete, expectedJobStatus);
399 when(underTest.getInProgressStatusService().call(any(), any(), any())).thenThrow(exception);
400 assertEquals(expectedJobStatus, underTest.inProgress());
404 public static Object[][] testIsNeedToDeleteMySelfDataProvider() {
405 return Stream.of(values())
406 .map(status -> new Object[] { status })
407 .toArray(Object[][]::new);
410 @Test(dataProvider = "testIsNeedToDeleteMySelfDataProvider")
411 public void testIsNeedToDeleteMySelf(Action action) {
412 boolean expectedResult = (action== Delete);
413 MockCommand underTest = new MockCommand(InternalState.DELETE_MYSELF, Delete, Job.JobStatus.IN_PROGRESS);
414 BaseResource mockedBaseResource = mock(BaseResource.class);
415 when(underTest.getSharedData().getRequest()).thenReturn(mockedBaseResource);
416 when(mockedBaseResource.getAction()).thenReturn(action);
417 assertEquals(expectedResult, underTest.isNeedToDeleteMyself());
421 public static Object[][] testWatchingDataProvider() {
422 return new Object[][]{
423 {"all children final, no failed child ", Job.JobStatus.COMPLETED, Job.JobStatus.COMPLETED},
424 {"all children final, there is failed child ", Job.JobStatus.COMPLETED_WITH_ERRORS, Job.JobStatus.COMPLETED_WITH_ERRORS},
425 {"not all children final", Job.JobStatus.IN_PROGRESS, Job.JobStatus.IN_PROGRESS},
429 @Test(dataProvider = "testWatchingDataProvider")
430 public void testWatching(String desc, Job.JobStatus childrenJobsStatus, Job.JobStatus expectedJobStatus) {
431 MockCommand underTest = new MockCommand(InternalState.WATCHING, Delete, Job.JobStatus.IN_PROGRESS);
432 when(underTest.getWatchChildrenJobsBL().retrieveChildrenJobsStatus(any())).thenReturn(childrenJobsStatus);
433 assertEquals(expectedJobStatus, underTest.watchChildren());
437 public static Object[][] testCalcInitialStateDataProvider() {
438 return new Object[][]{
439 {Delete, true, Delete, InternalState.CREATING_CHILDREN},
440 {Delete, false, Delete, InternalState.DELETE_MYSELF},
441 {Delete, false, Create, InternalState.TERMINAL},
442 {Delete, true, Create, InternalState.CREATING_CHILDREN},
443 {Create, true, Create, InternalState.CREATE_MYSELF},
444 {Create, false, Create, InternalState.CREATE_MYSELF},
445 {Create, false, Delete, InternalState.TERMINAL},
446 {Create, true, Delete, InternalState.CREATING_CHILDREN},
447 {Create, true, Resume, InternalState.RESUME_MYSELF},
448 {Delete, false, Resume, InternalState.TERMINAL},
452 @Test(dataProvider = "testCalcInitialStateDataProvider")
453 public void testCalcInitialState(Action phase, boolean isDescendantHasAction, Action action, InternalState expectedState) {
454 ResourceCommand underTest = mock(ResourceCommand.class);
455 when(underTest.calcInitialState(any(), any())).thenCallRealMethod();
456 when(underTest.isDescendantHasAction(eq(phase))).thenReturn(isDescendantHasAction);
457 when(underTest.getActionType()).thenReturn(action);
458 when(underTest.isNeedToDeleteMyself()).thenCallRealMethod();
459 when(underTest.isNeedToCreateMyself()).thenCallRealMethod();
460 when(underTest.isNeedToResumeMySelf()).thenCallRealMethod();
462 Map<String, String> commandData = ImmutableMap.of(INTERNAL_STATE, InternalState.INITIAL.name());
463 assertEquals(expectedState, underTest.calcInitialState(commandData, phase));
467 //throw exception when call to create children
468 //create children is just example, it could be any other method that called by ResourceCommand.invokeCommand
469 public static class MockCommandThrowExceptionOnCreateChildren extends MockCommandTestingStateMachine {
471 private final RuntimeException exceptionToThrow;
473 public MockCommandThrowExceptionOnCreateChildren(RuntimeException exceptionToThrow) {
474 super(InternalState.CREATING_CHILDREN, Delete, Job.JobStatus.COMPLETED, true);
475 this.exceptionToThrow = exceptionToThrow;
476 doAnswer(returnsFirstArg()).when(this.getWatchChildrenJobsBL()).cumulateJobStatus(any(), any());
481 public Job.JobStatus createChildren() {
482 throw exceptionToThrow;
487 public static Object[][] exceptionAndStateProvider() {
488 return new Object[][]{
489 {new TryAgainException(new Exception()), Job.JobStatus.RESOURCE_IN_PROGRESS},
490 {new AbortingException(new Exception()), Job.JobStatus.FAILED},
494 @Test(dataProvider = "exceptionAndStateProvider")
495 public void whenKnownExceptionThrownInCommandInvocation_thenStateIsAsExpected(RuntimeException exception, Job.JobStatus expectedNextStatus) {
496 MockCommandTestingStateMachine underTest = new MockCommandThrowExceptionOnCreateChildren(exception);
497 NextCommand nextCommand = underTest.call();
498 assertEquals(expectedNextStatus, nextCommand.getStatus());