@Test
  public void testRunning() {
    StageStateMachine stateMachine = createStageStateMachine();
    assertTrue(stateMachine.transitionToRunning());
    assertState(stateMachine, StageState.RUNNING);

    assertFalse(stateMachine.transitionToScheduling());
    assertState(stateMachine, StageState.RUNNING);

    assertFalse(stateMachine.transitionToScheduled());
    assertState(stateMachine, StageState.RUNNING);

    assertFalse(stateMachine.transitionToRunning());
    assertState(stateMachine, StageState.RUNNING);

    assertTrue(stateMachine.transitionToFinished());
    assertState(stateMachine, StageState.FINISHED);

    stateMachine = createStageStateMachine();
    stateMachine.transitionToRunning();
    assertTrue(stateMachine.transitionToFailed(FAILED_CAUSE));
    assertState(stateMachine, StageState.FAILED);

    stateMachine = createStageStateMachine();
    stateMachine.transitionToRunning();
    assertTrue(stateMachine.transitionToAborted());
    assertState(stateMachine, StageState.ABORTED);

    stateMachine = createStageStateMachine();
    stateMachine.transitionToRunning();
    assertTrue(stateMachine.transitionToCanceled());
    assertState(stateMachine, StageState.CANCELED);
  }
  private static void assertFinalState(StageStateMachine stateMachine, StageState expectedState) {
    assertTrue(expectedState.isDone());

    assertState(stateMachine, expectedState);

    assertFalse(stateMachine.transitionToScheduling());
    assertState(stateMachine, expectedState);

    assertFalse(stateMachine.transitionToScheduled());
    assertState(stateMachine, expectedState);

    assertFalse(stateMachine.transitionToRunning());
    assertState(stateMachine, expectedState);

    assertFalse(stateMachine.transitionToFinished());
    assertState(stateMachine, expectedState);

    assertFalse(stateMachine.transitionToFailed(FAILED_CAUSE));
    assertState(stateMachine, expectedState);

    assertFalse(stateMachine.transitionToAborted());
    assertState(stateMachine, expectedState);

    // attempt to fail with another exception, which will fail
    assertFalse(stateMachine.transitionToFailed(new IOException("failure after finish")));
    assertState(stateMachine, expectedState);
  }
  @Test
  public void testBasicStateChanges() {
    StageStateMachine stateMachine = createStageStateMachine();
    assertState(stateMachine, StageState.PLANNED);

    assertTrue(stateMachine.transitionToScheduling());
    assertState(stateMachine, StageState.SCHEDULING);

    assertTrue(stateMachine.transitionToScheduled());
    assertState(stateMachine, StageState.SCHEDULED);

    assertTrue(stateMachine.transitionToRunning());
    assertState(stateMachine, StageState.RUNNING);

    assertTrue(stateMachine.transitionToFinished());
    assertState(stateMachine, StageState.FINISHED);
  }