@Test
public void testRequestAbortsOnlyWhenNoQueuedTaskAndSuccessFactorUnmet() throws Exception {

  ActionQueue aq = new ActionQueue();
  Clusters fsm = mock(Clusters.class);
  Cluster oneClusterMock = mock(Cluster.class);
  Service serviceObj = mock(Service.class);
  ServiceComponent scomp = mock(ServiceComponent.class);
  ServiceComponentHost sch = mock(ServiceComponentHost.class);
  UnitOfWork unitOfWork = mock(UnitOfWork.class);
  when(fsm.getCluster(anyString())).thenReturn(oneClusterMock);
  when(oneClusterMock.getService(anyString())).thenReturn(serviceObj);
  when(serviceObj.getServiceComponent(anyString())).thenReturn(scomp);
  when(scomp.getServiceComponentHost(anyString())).thenReturn(sch);
  when(serviceObj.getCluster()).thenReturn(oneClusterMock);
  String host1 = "host1";
  String host2 = "host2";
  Host host = mock(Host.class);
  HashMap<String, ServiceComponentHost> hosts =
          new HashMap<String, ServiceComponentHost>();
  hosts.put(host1, sch);
  hosts.put(host2, sch);
  when(scomp.getServiceComponentHosts()).thenReturn(hosts);
  when(fsm.getHost(anyString())).thenReturn(host);
  when(host.getState()).thenReturn(HostState.HEALTHY);
  when(host.getHostName()).thenReturn(host1);
  HostEntity hostEntity1 = new HostEntity();
  HostEntity hostEntity2 = new HostEntity();
  hostEntity1.setHostName(host1);
  hostEntity2.setHostName(host2);
  hostDAO.create(hostEntity1);
  hostDAO.create(hostEntity2);
  final List<Stage> stages = new ArrayList<Stage>();
  long now = System.currentTimeMillis();
  Stage stage = stageFactory.createNew(1, "/tmp", "cluster1", 1L,
      "testRequestFailureBasedOnSuccessFactor", CLUSTER_HOST_INFO, "", "");
  stage.setStageId(1);
  addHostRoleExecutionCommand(now, stage, Role.SQOOP, Service.Type.SQOOP,
      RoleCommand.INSTALL, host1, "cluster1");
  addHostRoleExecutionCommand(now, stage, Role.OOZIE_CLIENT, Service.Type.OOZIE,
      RoleCommand.INSTALL, host1, "cluster1");
  addHostRoleExecutionCommand(now, stage, Role.MAPREDUCE_CLIENT, Service.Type.MAPREDUCE,
      RoleCommand.INSTALL, host1, "cluster1");
  addHostRoleExecutionCommand(now, stage, Role.HBASE_CLIENT, Service.Type.HBASE,
      RoleCommand.INSTALL, host1, "cluster1");
  addHostRoleExecutionCommand(now, stage, Role.GANGLIA_MONITOR, Service.Type.GANGLIA,
      RoleCommand.INSTALL, host1, "cluster1");
  addHostRoleExecutionCommand(now, stage, Role.HBASE_CLIENT, Service.Type.HBASE,
      RoleCommand.INSTALL, host2, "cluster1");
  addHostRoleExecutionCommand(now, stage, Role.GANGLIA_MONITOR, Service.Type.GANGLIA,
      RoleCommand.INSTALL, host2, "cluster1");
  stages.add(stage);
  HostRoleStatus[] statusesAtIterOne = {HostRoleStatus.QUEUED, HostRoleStatus.QUEUED,
      HostRoleStatus.QUEUED, HostRoleStatus.QUEUED, HostRoleStatus.FAILED,
      HostRoleStatus.FAILED, HostRoleStatus.QUEUED, HostRoleStatus.QUEUED};
  for (int index = 0; index < stage.getOrderedHostRoleCommands().size(); index++) {
    stage.getOrderedHostRoleCommands().get(index).setTaskId(index + 1);
    stage.getOrderedHostRoleCommands().get(index).setStatus(statusesAtIterOne[index]);
  }
  stage.setLastAttemptTime(host1, Role.SQOOP.toString(), now);
  stage.setLastAttemptTime(host1, Role.MAPREDUCE_CLIENT.toString(), now);
  stage.setLastAttemptTime(host1, Role.OOZIE_CLIENT.toString(), now);
  stage.setLastAttemptTime(host1, Role.GANGLIA_MONITOR.toString(), now);
  stage.setLastAttemptTime(host1, Role.HBASE_CLIENT.toString(), now);
  stage.setLastAttemptTime(host2, Role.GANGLIA_MONITOR.toString(), now);
  stage.setLastAttemptTime(host2, Role.HBASE_CLIENT.toString(), now);
  ActionDBAccessor db = mock(ActionDBAccessor.class);
  HostRoleCommandDAO hostRoleCommandDAOMock = mock(HostRoleCommandDAO.class);
  Mockito.doNothing().when(hostRoleCommandDAOMock).publishTaskCreateEvent(anyListOf(HostRoleCommand.class));
  RequestEntity request = mock(RequestEntity.class);
  when(request.isExclusive()).thenReturn(false);
  when(db.getRequestEntity(anyLong())).thenReturn(request);
  when(db.getCommandsInProgressCount()).thenReturn(stages.size());
  when(db.getStagesInProgress()).thenReturn(stages);
  doAnswer(new Answer<Void>() {
    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
      String host = (String) invocation.getArguments()[0];
      Long requestId = (Long) invocation.getArguments()[1];
      Long stageId = (Long) invocation.getArguments()[2];
      String role = (String) invocation.getArguments()[3];
      CommandReport commandReport = (CommandReport) invocation.getArguments()[4];
      for (Stage stage : stages) {
        if (requestId.equals(stage.getRequestId()) && stageId.equals(stage.getStageId())) {
          HostRoleCommand command = stage.getHostRoleCommand(host, role);
          command.setStatus(HostRoleStatus.valueOf(commandReport.getStatus()));
        }
      }
      return null;
    }
  }).when(db).updateHostRoleState(anyString(), anyLong(), anyLong(), anyString(), any(CommandReport.class));
  when(db.getTask(anyLong())).thenAnswer(new Answer<Object>() {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
      Long taskId = (Long) invocation.getArguments()[0];
      for (Stage stage : stages) {
        for (HostRoleCommand command : stage.getOrderedHostRoleCommands()) {
          if (taskId.equals(command.getTaskId())) {
            return command;
          }
        }
      }
      return null;
    }
  });
  doAnswer(new Answer<Collection<HostRoleCommandEntity>>() {
    @Override
    public Collection<HostRoleCommandEntity> answer(InvocationOnMock invocation) throws Throwable {
      Long requestId = (Long) invocation.getArguments()[0];
      List<HostRoleCommandEntity> abortedCommands = Lists.newArrayList();
      for (Stage stage : stages) {
        if (requestId.equals(stage.getRequestId())) {
          for (HostRoleCommand command : stage.getOrderedHostRoleCommands()) {
            if (command.getStatus() == HostRoleStatus.QUEUED ||
                command.getStatus() == HostRoleStatus.IN_PROGRESS ||
                command.getStatus() == HostRoleStatus.PENDING) {
              command.setStatus(HostRoleStatus.ABORTED);
              HostRoleCommandEntity hostRoleCommandEntity = command.constructNewPersistenceEntity();
              hostRoleCommandEntity.setStage(stage.constructNewPersistenceEntity());
              abortedCommands.add(hostRoleCommandEntity);
            }
          }
        }
      }
      return abortedCommands;
    }
  }).when(db).abortOperation(anyLong());
  Properties properties = new Properties();
  Configuration conf = new Configuration(properties);
  ActionScheduler scheduler = new ActionScheduler(100, 10000, db, aq, fsm, 3,
      new HostsMap((String) null),
      unitOfWork, null, conf, entityManagerProviderMock,
      hostRoleCommandDAOMock, (HostRoleCommandFactory)null);
  scheduler.doWork();
  // Request is not aborted because all roles are in progress
  HostRoleStatus[] expectedStatusesAtIterOne = {HostRoleStatus.QUEUED, HostRoleStatus.QUEUED,
      HostRoleStatus.QUEUED, HostRoleStatus.QUEUED, HostRoleStatus.FAILED,
      HostRoleStatus.FAILED, HostRoleStatus.QUEUED, HostRoleStatus.QUEUED};
  for (int index = 0; index < stage.getOrderedHostRoleCommands().size(); index++) {
    log.info(stage.getOrderedHostRoleCommands().get(index).toString());
    Assert.assertEquals(expectedStatusesAtIterOne[index],
        stage.getOrderedHostRoleCommands().get(index).getStatus());
  }
  HostRoleStatus[] statusesAtIterTwo = {HostRoleStatus.QUEUED, HostRoleStatus.QUEUED,
      HostRoleStatus.QUEUED, HostRoleStatus.QUEUED, HostRoleStatus.FAILED,
      HostRoleStatus.FAILED, HostRoleStatus.QUEUED, HostRoleStatus.COMPLETED};
  for (int index = 0; index < stage.getOrderedHostRoleCommands().size(); index++) {
    stage.getOrderedHostRoleCommands().get(index).setStatus(statusesAtIterTwo[index]);
  }
  scheduler.doWork();
  // Request is not aborted because GANGLIA_MONITOR's success factor (0.5) is met
  HostRoleStatus[] expectedStatusesAtIterTwo = {HostRoleStatus.QUEUED, HostRoleStatus.QUEUED,
      HostRoleStatus.QUEUED, HostRoleStatus.QUEUED, HostRoleStatus.FAILED,
      HostRoleStatus.FAILED, HostRoleStatus.QUEUED, HostRoleStatus.COMPLETED};
  for (int index = 0; index < stage.getOrderedHostRoleCommands().size(); index++) {
    log.info(stage.getOrderedHostRoleCommands().get(index).toString());
    Assert.assertEquals(expectedStatusesAtIterTwo[index],
        stage.getOrderedHostRoleCommands().get(index).getStatus());
  }
  HostRoleStatus[] statusesAtIterThree = {HostRoleStatus.QUEUED, HostRoleStatus.QUEUED,
      HostRoleStatus.QUEUED, HostRoleStatus.QUEUED, HostRoleStatus.FAILED,
      HostRoleStatus.FAILED, HostRoleStatus.FAILED, HostRoleStatus.COMPLETED};
  for (int index = 0; index < stage.getOrderedHostRoleCommands().size(); index++) {
    stage.getOrderedHostRoleCommands().get(index).setStatus(statusesAtIterThree[index]);
  }
  // Fails becuse HostRoleCommand doesn't have a hostName
  scheduler.doWork();
  // Request is aborted because HBASE_CLIENT's success factor (1) is not met
  HostRoleStatus[] expectedStatusesAtIterThree = {HostRoleStatus.ABORTED, HostRoleStatus.ABORTED,
      HostRoleStatus.ABORTED, HostRoleStatus.ABORTED, HostRoleStatus.FAILED,
      HostRoleStatus.FAILED, HostRoleStatus.FAILED, HostRoleStatus.COMPLETED};
  for (int index = 0; index < stage.getOrderedHostRoleCommands().size(); index++) {
    log.info(stage.getOrderedHostRoleCommands().get(index).toString());
    Assert.assertEquals(expectedStatusesAtIterThree[index],
        stage.getOrderedHostRoleCommands().get(index).getStatus());
  }
}