@VisibleForTesting
  static void computeAndSetAggregatedInstanceStatus(
      WorkflowInstance currentInstance, WorkflowInstanceAggregatedInfo aggregated) {
    if (!currentInstance.getStatus().isTerminal()
        || currentInstance.isFreshRun()
        || !currentInstance.getStatus().equals(WorkflowInstance.Status.SUCCEEDED)) {
      aggregated.setWorkflowInstanceStatus(currentInstance.getStatus());
      return;
    }

    boolean succeeded = true;
    for (StepAggregatedView stepAggregated : aggregated.getStepAggregatedViews().values()) {
      WorkflowInstance.Status workflowStatus =
          STEP_INSTANCE_STATUS_TO_WORKFLOW_INSTANCE_STATUS.get(stepAggregated.getStatus());
      switch (workflowStatus) {
        case FAILED:
          // if any step is failed overall status is failed
          aggregated.setWorkflowInstanceStatus(WorkflowInstance.Status.FAILED);
          return;
        case TIMED_OUT:
          // if any are timed out, we want to keep going to search for failed steps
          aggregated.setWorkflowInstanceStatus(WorkflowInstance.Status.TIMED_OUT);
          break;
        case STOPPED:
          // prioritize timed out status before stopped
          if (aggregated.getWorkflowInstanceStatus() != WorkflowInstance.Status.TIMED_OUT) {
            aggregated.setWorkflowInstanceStatus(WorkflowInstance.Status.STOPPED);
          }
          break;
        case SUCCEEDED:
          break;
        case CREATED:
          // there are steps in NOT_CREATED STATUS and the workflow instance cannot be SUCCEEDED.
          succeeded = false;
          break;
        default:
          // should never reach here with IN_PROGRESS status;
          throw new MaestroInternalError(
              "State %s is not expected during aggregated status computation for"
                  + " workflow_id = %s ; workflow_instance_id = %s ; workflow_run_id = %s",
              workflowStatus,
              currentInstance.getWorkflowId(),
              currentInstance.getWorkflowInstanceId(),
              currentInstance.getWorkflowRunId());
      }
    }
    if (aggregated.getWorkflowInstanceStatus() == null) {
      if (succeeded) {
        aggregated.setWorkflowInstanceStatus(WorkflowInstance.Status.SUCCEEDED);
      } else {
        aggregated.setWorkflowInstanceStatus(
            currentInstance.getAggregatedInfo().getWorkflowInstanceStatus());
      }
    }
  }
@Test
  public void testStatusAggregation() {
    WorkflowInstance run2 =
        getGenericWorkflowInstance(
            2,
            WorkflowInstance.Status.SUCCEEDED,
            RunPolicy.START_CUSTOMIZED_RUN,
            RestartPolicy.RESTART_FROM_INCOMPLETE);

    WorkflowInstance run3 =
        getGenericWorkflowInstance(
            3,
            WorkflowInstance.Status.IN_PROGRESS,
            RunPolicy.START_CUSTOMIZED_RUN,
            RestartPolicy.RESTART_FROM_INCOMPLETE);

    WorkflowInstance run4 =
        getGenericWorkflowInstance(
            4,
            WorkflowInstance.Status.STOPPED,
            RunPolicy.START_CUSTOMIZED_RUN,
            RestartPolicy.RESTART_FROM_INCOMPLETE);

    WorkflowInstance run5 =
        getGenericWorkflowInstance(
            5,
            WorkflowInstance.Status.FAILED,
            RunPolicy.START_CUSTOMIZED_RUN,
            RestartPolicy.RESTART_FROM_INCOMPLETE);

    WorkflowInstanceAggregatedInfo aggregated = new WorkflowInstanceAggregatedInfo();
    aggregated
        .getStepAggregatedViews()
        .put("step1", generateStepAggregated(StepInstance.Status.SUCCEEDED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step2", generateStepAggregated(StepInstance.Status.SUCCEEDED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step3", generateStepAggregated(StepInstance.Status.SUCCEEDED, 11L, 12L));
    AggregatedViewHelper.computeAndSetAggregatedInstanceStatus(run2, aggregated);
    assertEquals(WorkflowInstance.Status.SUCCEEDED, aggregated.getWorkflowInstanceStatus());

    aggregated = new WorkflowInstanceAggregatedInfo();
    aggregated
        .getStepAggregatedViews()
        .put("step1", generateStepAggregated(StepInstance.Status.SUCCEEDED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step2", generateStepAggregated(StepInstance.Status.FATALLY_FAILED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step3", generateStepAggregated(StepInstance.Status.SUCCEEDED, 11L, 12L));
    AggregatedViewHelper.computeAndSetAggregatedInstanceStatus(run5, aggregated);
    assertEquals(WorkflowInstance.Status.FAILED, aggregated.getWorkflowInstanceStatus());

    aggregated = new WorkflowInstanceAggregatedInfo();
    aggregated
        .getStepAggregatedViews()
        .put("step1", generateStepAggregated(StepInstance.Status.NOT_CREATED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step2", generateStepAggregated(StepInstance.Status.NOT_CREATED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step3", generateStepAggregated(StepInstance.Status.NOT_CREATED, 11L, 12L));
    AggregatedViewHelper.computeAndSetAggregatedInstanceStatus(run3, aggregated);
    assertEquals(WorkflowInstance.Status.IN_PROGRESS, aggregated.getWorkflowInstanceStatus());

    aggregated = new WorkflowInstanceAggregatedInfo();
    aggregated
        .getStepAggregatedViews()
        .put("step1", generateStepAggregated(StepInstance.Status.SUCCEEDED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step2", generateStepAggregated(StepInstance.Status.NOT_CREATED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step3", generateStepAggregated(StepInstance.Status.NOT_CREATED, 11L, 12L));
    AggregatedViewHelper.computeAndSetAggregatedInstanceStatus(run3, aggregated);
    assertEquals(WorkflowInstance.Status.IN_PROGRESS, aggregated.getWorkflowInstanceStatus());

    aggregated = new WorkflowInstanceAggregatedInfo();
    aggregated
        .getStepAggregatedViews()
        .put("step1", generateStepAggregated(StepInstance.Status.INTERNALLY_FAILED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step2", generateStepAggregated(StepInstance.Status.NOT_CREATED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step3", generateStepAggregated(StepInstance.Status.NOT_CREATED, 11L, 12L));
    AggregatedViewHelper.computeAndSetAggregatedInstanceStatus(run5, aggregated);
    assertEquals(WorkflowInstance.Status.FAILED, aggregated.getWorkflowInstanceStatus());

    aggregated = new WorkflowInstanceAggregatedInfo();
    aggregated
        .getStepAggregatedViews()
        .put("step1", generateStepAggregated(StepInstance.Status.INTERNALLY_FAILED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step2", generateStepAggregated(StepInstance.Status.STOPPED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step3", generateStepAggregated(StepInstance.Status.STOPPED, 11L, 12L));
    AggregatedViewHelper.computeAndSetAggregatedInstanceStatus(run5, aggregated);
    assertEquals(WorkflowInstance.Status.FAILED, aggregated.getWorkflowInstanceStatus());

    aggregated = new WorkflowInstanceAggregatedInfo();
    aggregated
        .getStepAggregatedViews()
        .put("step1", generateStepAggregated(StepInstance.Status.SUCCEEDED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step2", generateStepAggregated(StepInstance.Status.STARTING, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step3", generateStepAggregated(StepInstance.Status.STOPPED, 11L, 12L));
    AggregatedViewHelper.computeAndSetAggregatedInstanceStatus(run3, aggregated);
    assertEquals(WorkflowInstance.Status.IN_PROGRESS, aggregated.getWorkflowInstanceStatus());

    aggregated = new WorkflowInstanceAggregatedInfo();
    aggregated
        .getStepAggregatedViews()
        .put("step1", generateStepAggregated(StepInstance.Status.STOPPED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step2", generateStepAggregated(StepInstance.Status.NOT_CREATED, 11L, 12L));
    aggregated
        .getStepAggregatedViews()
        .put("step3", generateStepAggregated(StepInstance.Status.NOT_CREATED, 11L, 12L));
    AggregatedViewHelper.computeAndSetAggregatedInstanceStatus(run4, aggregated);
    assertEquals(WorkflowInstance.Status.STOPPED, aggregated.getWorkflowInstanceStatus());
  }