@Test
  public void testPreviousStageToFailForSecondStage() throws Exception {
    Stage previousStage = createMock(Stage.class);
    Stage nextStage = createMock(Stage.class);
    ActionDBAccessor actionDBAccessor = createMock(ActionDBAccessor.class);

    expect(previousStage.isSkippable()).andReturn(false);

    expect(nextStage.getStageId()).andReturn(1L);
    expect(nextStage.getRequestId()).andReturn(1L);
    expect(actionDBAccessor.getStage("1-0")).andReturn(previousStage);

    Map<String, HostRoleCommand> roleCommandMap = new HashMap<>();
    HostRoleCommand hostRoleCommand = createMock(HostRoleCommand.class);
    expect(hostRoleCommand.getRole()).andReturn(Role.DATANODE).anyTimes();
    expect(hostRoleCommand.getStatus()).andReturn(HostRoleStatus.FAILED);

    roleCommandMap.put(Role.DATANODE.toString(), hostRoleCommand);

    Map<String, Map<String, HostRoleCommand>> hostRoleCommands = new HashMap<>();
    hostRoleCommands.put("host", roleCommandMap);

    expect(previousStage.getHostRoleCommands()).andReturn(hostRoleCommands).anyTimes();
    expect(previousStage.getSuccessFactor(Role.DATANODE)).andReturn(0.5F);

    ActionScheduler scheduler = new ActionScheduler(100, 50, actionDBAccessor, null, 3,
        new HostsMap((String) null), null, null, null, entityManagerProviderMock, null, null, null);

    replay(previousStage, nextStage, actionDBAccessor, hostRoleCommand);

    Method method = scheduler.getClass().getDeclaredMethod("hasPreviousStageFailed", Stage.class);
    method.setAccessible(true);
    Object result = method.invoke(scheduler, nextStage);

    assertTrue((Boolean) result);
    EasyMock.verify(previousStage, nextStage, actionDBAccessor, hostRoleCommand);
  }
Tests that command failures in skippable stages do not cause the request to
be aborted.
ambari-server/src/test/java/org/apache/ambari/server/actionmanager/TestActionScheduler.java