@Test
public void shouldReturnSnapshotFollowedByLogEntriesInResponseToRepeatedGetNextCommittedCallsWithInitialIndexToSearchFromAsZero() throws Exception {

    // we have a snapshot that contains data to index 6 (inclusive)
    SnapshotsStore.ExtendedSnapshot storedSnapshot = new UnitTestSnapshot((long) 6, 2);
    // we have a log that contains entries from index 7 onwards
    LogEntry unappliedEntry0 = CLIENT(7, 2, new UnitTestCommand());
    LogEntry unappliedEntry1 = NOOP(8, 2);
    final LogEntry[] entries = new LogEntry[] {
            unappliedEntry0,
            unappliedEntry1, // <------ we've committed up to here
            NOOP(9, 3),
            CLIENT(10, 3, new UnitTestCommand()),
            CLIENT(11, 3, new UnitTestCommand()),
            CLIENT(12, 3, new UnitTestCommand())
    };
    clearLog(); // clear out the log completely - we don't even want the sentinel
    insertIntoLog(entries);
    // set the current term
    long currentTerm = 8;
    store.setCurrentTerm(currentTerm);
    // set the committed index
    long commitIndex = 8;
    store.setCommitIndex(commitIndex);
    // have the snapshot store return the snapshot
    when(snapshotsStore.getLatestSnapshot()).thenReturn(storedSnapshot);
    //
    // situation is as follows:
    //
    //                                +----------- COMMITTED
    //                                V
    //                         ------------------------------
    //      .... EMPTY ....   | 07 | 08 | 09 | 10 | 11 | 12 | (LOG)
    //                        ------------------------------
    //   ---------------------
    //  | LAST APPLIED = 6   | (SNAPSHOT)
    //  ---------------------
    //   ^
    //   +----------- INDEX TO SEARCH FROM = 0
    //
    Committed committed;
    // OK, now, let's start by saying that the last index we applied was '0' (IOW, we have no state and have to start from scratch)
    // we should get the snapshot back
    committed = algorithm.getNextCommitted(0);
    checkMatchingSnapshot(committed, storedSnapshot);
    // let's check that if we make a second call we should get back the first committed, unapplied entry (command)
    committed = algorithm.getNextCommitted(committed.getIndex()); // index = 6
    checkMatchingCommittedLogEntry(committed, unappliedEntry0);
    // let's check that if we make a third call we should get back the second committed, unapplied entry (noop)
    committed = algorithm.getNextCommitted(committed.getIndex()); // index = 7
    checkMatchingCommittedLogEntry(committed, unappliedEntry1);
    // if we make a fourth call we should get nothing
    committed = algorithm.getNextCommitted(committed.getIndex()); // index = 8
    assertThat(committed, nullValue());
    // algorithm should have exactly the same state at the end
    assertThatLogContains(entries);
    assertThatTermAndCommitIndexHaveValues(currentTerm, commitIndex);
}