@Test
  public void shouldCancelTimedOutCommand() {
    scheduler.submit(c[0]);
    scheduler.submit(c[1]);
    scheduler.submit(d[1]);

    assertThat(list).isEmpty();

    scheduler.execute(0);

    assertThat(list)
        .isEqualTo(
            listOf(
                "C0 init", "C0 exe", "C0 fin", "C1 init", "C1 exe", "C1 fin", "D1 init", "D1 exe"));
    list.clear();

    scheduler.execute(1);
    assertThat(list).isEqualTo(listOf("D1 exe"));
    list.clear();

    scheduler.execute(2);
    assertThat(list).isEqualTo(listOf("D1 exe"));
    list.clear();

    scheduler.execute(1000);
    assertThat(list).isEqualTo(listOf("D1 fin"));
    list.clear();
  }
  @Test
  public void shoudKillCommandGroupThatUsesRequirementOfAnother() {
    Requirable required =
        new Requirable() {
          @Override
          public String toString() {
            return "R0";
          }
        };
    CommandWithRequirement r0 = new CommandWithRequirement(required, 0, list, true);
    CommandWithRequirement r1 = new CommandWithRequirement(required, 1, list, true);
    CommandWithRequirement r2 = new CommandWithRequirement(required, 2, list, true);
    RequiredGroup g = new RequiredGroup(r0, r1, r2);

    CommandWithRequirement r3 = new CommandWithRequirement(required, 3, list, false);
    scheduler.submit(g);

    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("R0 init", "R0 exe", "R0 end"));
    list.clear();

    scheduler.submit(r3);
    scheduler.execute(1);
    assertThat(list).isEqualTo(listOf("R1 inter", "R3 init", "R3 exe", "R3 end"));
    list.clear();

    scheduler.execute(2);
    assertThat(list).isEmpty();
  }
  @Test
  public void shoudKillCommandThatUsesRequirementOfAnother() {
    Requirable required = new Requirable() {};
    CommandWithRequirement r0 = new CommandWithRequirement(required, 0, list, true);
    CommandWithRequirement r1 = new CommandWithRequirement(required, 1, list, false);
    CommandWithRequirement r2 = new CommandWithRequirement(required, 2, list, true);

    scheduler.submit(r0);
    scheduler.submit(r1);
    scheduler.submit(r2);

    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("R0 inter", "R1 init", "R1 exe", "R1 end"));
    list.clear();
  }
  @Test
  public void shouldExecuteComposedNamedCommandGroups() {
    scheduler.submit(new OuterCommandGroup());

    assertThat(list).isEmpty();

    // First step should come from the OuterCommandGroup
    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("C0 init", "C0 exe", "C0 fin"));
    list.clear();

    // Second step should come from NestedCommandGroup
    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("C1 init", "C1 exe", "C1 fin"));
    list.clear();

    // Third step should come from NestedCommandGroup
    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("C2 init", "C2 exe", "C2 fin"));
    list.clear();

    // Fourth step should resume the OuterCommandGroup sequence
    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("C3 init", "C3 exe", "C3 fin"));
    list.clear();

    // Fifth step is empty, nothing executed
    scheduler.execute(0);
    assertThat(list).isEmpty();
  }
 @Test
 public void shouldExecuteCommandsTogether() {
   Command c = new SimulCommandGroup();
   scheduler.submit(c);
   scheduler.execute(0);
   // After one step, all three should have run
   assertThat(list)
       .isEqualTo(
           listOf(
               "C0 init", "C0 exe", "C0 fin", "C1 init", "C1 exe", "C1 fin", "C2 init", "C2 exe",
               "C2 fin"));
 }
  @Test
  public void shouldExecuteTwoCommandsTogetherAndOneAfter() {
    Command c = new TwoOneGroup();
    scheduler.submit(c);
    // After one step, first two should have run
    scheduler.execute(0);
    assertThat(list)
        .isEqualTo(listOf("C0 init", "C0 exe", "C0 fin", "C1 init", "C1 exe", "C1 fin"));
    list.clear();

    // After two steps, all three should have run
    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("C2 init", "C2 exe", "C2 fin"));
  }
  @Test
  public void shouldModelDiagramFromBoard() {
    scheduler.submit(new DiagramFromBoard());
    // Nothing has executed yet
    assertThat(list).isEmpty();

    // First step should execute 0
    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("C0 init", "C0 exe", "C0 fin"));
    list.clear();

    // Second step is a branch, nothing was executed, fork was primed
    scheduler.execute(0);
    assertThat(list).isEmpty();

    // Third step should execute 1 and 2 (parallelized) and 3 (just forked)
    scheduler.execute(0);
    assertThat(list)
        .isEqualTo(
            listOf(
                "C1 init", "C1 exe", "C1 fin", "C2 init", "C2 exe", "C2 fin", "C3 init", "C3 exe",
                "C3 fin"));
    list.clear();

    // Fourth step should execute 5 (main) and 4 (on fork)
    scheduler.execute(0);
    assertThat(list)
        .isEqualTo(listOf("C5 init", "C5 exe", "C5 fin", "C4 init", "C4 exe", "C4 fin"));
    list.clear();

    // Fifth step is a branch, nothing was executed fork is dead, another fork was primed
    scheduler.execute(0);
    assertThat(list).isEmpty();

    // Sixth step should execute 6 (main) and 7 (just forked)
    scheduler.execute(0);
    assertThat(list)
        .isEqualTo(listOf("C6 init", "C6 exe", "C6 fin", "C7 init", "C7 exe", "C7 fin"));
    list.clear();

    // Seventh step scheduler is empty, nothing executes
    scheduler.execute(0);
    assertThat(list).isEmpty();
  }
  @Test
  public void shouldModelOtherDiagramFromBoard() {
    scheduler.submit(new OtherDiagramFromBoard());

    // Nothing has executed yet
    assertThat(list).isEmpty();

    // First step should execute 0
    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("C0 init", "C0 exe", "C0 fin"));
    list.clear();

    // Second step is a branch, nothing executes, fork is primed
    scheduler.execute(0);
    assertThat(list).isEmpty();

    // Third step should execute 3 (main) and 1 and 2 (just forked parallelized)
    scheduler.execute(0);
    assertThat(list)
        .isEqualTo(
            listOf(
                "C3 init", "C3 exe", "C3 fin", "C1 init", "C1 exe", "C1 fin", "C2 init", "C2 exe",
                "C2 fin"));
    list.clear();

    // Fourth step should execute 4 and 5 (parallelized) fork is dead
    scheduler.execute(0);
    assertThat(list)
        .isEqualTo(listOf("C4 init", "C4 exe", "C4 fin", "C5 init", "C5 exe", "C5 fin"));
    list.clear();

    // Fifth step should execute 6
    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("C6 init", "C6 exe", "C6 fin"));
    list.clear();

    // Sixth step scheduler is empty, nothing executed
    scheduler.execute(0);
    assertThat(list).isEmpty();
  }
  @Test
  public void shouldExecuteCommandsInOrder() {
    Command c = new SeqCommandGroup();
    scheduler.submit(c);
    assertThat(list).isEmpty();
    // First step, C0 should have been added, run, and finished
    scheduler.execute(0);
    assertThat(list).isEqualTo(listOf("C0 init", "C0 exe", "C0 fin"));

    // Second step, C1 should have been added, run, and finished
    scheduler.execute(0);
    assertThat(list)
        .isEqualTo(listOf("C0 init", "C0 exe", "C0 fin", "C1 init", "C1 exe", "C1 fin"));

    // Third step, C2 should have been added, run, and finished
    scheduler.execute(0);
    assertThat(list)
        .isEqualTo(
            listOf(
                "C0 init", "C0 exe", "C0 fin", "C1 init", "C1 exe", "C1 fin", "C2 init", "C2 exe",
                "C2 fin"));
  }