use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class FollowerTest method testHandleAppendEntriesWithNewerCommitIndex.
/**
* This test verifies that when an AppendEntries RPC is received by a RaftActor
* with a commitIndex that is greater than what has been applied to the
* state machine of the RaftActor, the RaftActor applies the state and
* sets it current applied state to the commitIndex of the sender.
*/
@Test
public void testHandleAppendEntriesWithNewerCommitIndex() {
logStart("testHandleAppendEntriesWithNewerCommitIndex");
MockRaftActorContext context = createActorContext();
context.setLastApplied(100);
setLastLogEntry(context, 1, 100, new MockRaftActorContext.MockPayload(""));
context.getReplicatedLog().setSnapshotIndex(99);
List<ReplicatedLogEntry> entries = Arrays.<ReplicatedLogEntry>asList(newReplicatedLogEntry(2, 101, "foo"));
// The new commitIndex is 101
AppendEntries appendEntries = new AppendEntries(2, "leader-1", 100, 1, entries, 101, 100, (short) 0);
follower = createBehavior(context);
follower.handleMessage(leaderActor, appendEntries);
assertEquals("getLastApplied", 101L, context.getLastApplied());
}
use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class FollowerTest method testHandleInstallSnapshot.
/**
* This test verifies that when InstallSnapshot is received by
* the follower its applied correctly.
*/
@Test
public void testHandleInstallSnapshot() {
logStart("testHandleInstallSnapshot");
MockRaftActorContext context = createActorContext();
context.getTermInformation().update(1, "leader");
follower = createBehavior(context);
ByteString bsSnapshot = createSnapshot();
int offset = 0;
int snapshotLength = bsSnapshot.size();
int chunkSize = 50;
int totalChunks = snapshotLength / chunkSize + (snapshotLength % chunkSize > 0 ? 1 : 0);
int lastIncludedIndex = 1;
int chunkIndex = 1;
InstallSnapshot lastInstallSnapshot = null;
for (int i = 0; i < totalChunks; i++) {
byte[] chunkData = getNextChunk(bsSnapshot, offset, chunkSize);
lastInstallSnapshot = new InstallSnapshot(1, "leader", lastIncludedIndex, 1, chunkData, chunkIndex, totalChunks);
follower.handleMessage(leaderActor, lastInstallSnapshot);
offset = offset + 50;
lastIncludedIndex++;
chunkIndex++;
}
ApplySnapshot applySnapshot = MessageCollectorActor.expectFirstMatching(followerActor, ApplySnapshot.class);
Snapshot snapshot = applySnapshot.getSnapshot();
assertNotNull(lastInstallSnapshot);
assertEquals("getLastIndex", lastInstallSnapshot.getLastIncludedIndex(), snapshot.getLastIndex());
assertEquals("getLastIncludedTerm", lastInstallSnapshot.getLastIncludedTerm(), snapshot.getLastAppliedTerm());
assertEquals("getLastAppliedIndex", lastInstallSnapshot.getLastIncludedIndex(), snapshot.getLastAppliedIndex());
assertEquals("getLastTerm", lastInstallSnapshot.getLastIncludedTerm(), snapshot.getLastTerm());
assertEquals("getState type", ByteState.class, snapshot.getState().getClass());
Assert.assertArrayEquals("getState", bsSnapshot.toByteArray(), ((ByteState) snapshot.getState()).getBytes());
assertEquals("getElectionTerm", 1, snapshot.getElectionTerm());
assertEquals("getElectionVotedFor", "leader", snapshot.getElectionVotedFor());
applySnapshot.getCallback().onSuccess();
List<InstallSnapshotReply> replies = MessageCollectorActor.getAllMatching(leaderActor, InstallSnapshotReply.class);
assertEquals("InstallSnapshotReply count", totalChunks, replies.size());
chunkIndex = 1;
for (InstallSnapshotReply reply : replies) {
assertEquals("getChunkIndex", chunkIndex++, reply.getChunkIndex());
assertEquals("getTerm", 1, reply.getTerm());
assertEquals("isSuccess", true, reply.isSuccess());
assertEquals("getFollowerId", context.getId(), reply.getFollowerId());
}
assertNull("Expected null SnapshotTracker", follower.getSnapshotTracker());
}
use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class IsolatedLeaderTest method testHandleMessageWithThreeMembers.
@Test
public void testHandleMessageWithThreeMembers() throws Exception {
String followerAddress1 = "akka://test/user/$a";
String followerAddress2 = "akka://test/user/$b";
MockRaftActorContext leaderActorContext = createActorContext();
Map<String, String> peerAddresses = new HashMap<>();
peerAddresses.put("follower-1", followerAddress1);
peerAddresses.put("follower-2", followerAddress2);
leaderActorContext.setPeerAddresses(peerAddresses);
isolatedLeader = new IsolatedLeader(leaderActorContext);
leaderActorContext.setCurrentBehavior(isolatedLeader);
assertEquals("Raft state", RaftState.IsolatedLeader, isolatedLeader.state());
// in a 3 node cluster, even if 1 follower is returns a reply, the isolatedLeader is not isolated
RaftActorBehavior newBehavior = isolatedLeader.handleMessage(senderActor, new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() - 1, true, isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1, (short) 0));
assertEquals("Raft state", RaftState.Leader, newBehavior.state());
isolatedLeader.close();
isolatedLeader = (AbstractLeader) newBehavior;
newBehavior = isolatedLeader.handleMessage(senderActor, new AppendEntriesReply("follower-2", isolatedLeader.lastTerm() - 1, true, isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1, (short) 0));
assertEquals("Raft state", RaftState.Leader, newBehavior.state());
}
use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class LeaderTest method testHandleAppendEntriesReplyFailureWithFollowersLogTermDifferent.
@Test
public void testHandleAppendEntriesReplyFailureWithFollowersLogTermDifferent() {
logStart("testHandleAppendEntriesReplyFailureWithFollowersLogTermDifferent");
MockRaftActorContext leaderActorContext = createActorContextWithFollower();
((DefaultConfigParamsImpl) leaderActorContext.getConfigParams()).setHeartBeatInterval(new FiniteDuration(1000, TimeUnit.SECONDS));
leaderActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 2, 2).build());
long leaderCommitIndex = 1;
leaderActorContext.setCommitIndex(leaderCommitIndex);
leaderActorContext.setLastApplied(leaderCommitIndex);
final ReplicatedLogEntry leadersFirstLogEntry = leaderActorContext.getReplicatedLog().get(0);
final ReplicatedLogEntry leadersSecondLogEntry = leaderActorContext.getReplicatedLog().get(1);
MockRaftActorContext followerActorContext = createFollowerActorContextWithLeader();
followerActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 1, 1).build());
followerActorContext.setCommitIndex(-1);
followerActorContext.setLastApplied(-1);
Follower follower = new Follower(followerActorContext);
followerActor.underlyingActor().setBehavior(follower);
followerActorContext.setCurrentBehavior(follower);
leader = new Leader(leaderActorContext);
AppendEntries appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
final AppendEntriesReply appendEntriesReply = MessageCollectorActor.expectFirstMatching(leaderActor, AppendEntriesReply.class);
MessageCollectorActor.clearMessages(followerActor);
MessageCollectorActor.clearMessages(leaderActor);
// Verify initial AppendEntries sent with the leader's current commit index.
assertEquals("getLeaderCommit", -1, appendEntries.getLeaderCommit());
assertEquals("Log entries size", 0, appendEntries.getEntries().size());
assertEquals("getPrevLogIndex", 0, appendEntries.getPrevLogIndex());
leaderActor.underlyingActor().setBehavior(leader);
leaderActorContext.setCurrentBehavior(leader);
leader.handleMessage(followerActor, appendEntriesReply);
MessageCollectorActor.expectMatching(leaderActor, AppendEntriesReply.class, 1);
appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
assertEquals("getLeaderCommit", leaderCommitIndex, appendEntries.getLeaderCommit());
assertEquals("getPrevLogIndex", -1, appendEntries.getPrevLogIndex());
assertEquals("Log entries size", 2, appendEntries.getEntries().size());
assertEquals("First entry index", 0, appendEntries.getEntries().get(0).getIndex());
assertEquals("First entry term", 2, appendEntries.getEntries().get(0).getTerm());
assertEquals("First entry data", leadersFirstLogEntry.getData(), appendEntries.getEntries().get(0).getData());
assertEquals("Second entry index", 1, appendEntries.getEntries().get(1).getIndex());
assertEquals("Second entry term", 2, appendEntries.getEntries().get(1).getTerm());
assertEquals("Second entry data", leadersSecondLogEntry.getData(), appendEntries.getEntries().get(1).getData());
FollowerLogInformation followerInfo = leader.getFollower(FOLLOWER_ID);
assertEquals("getNextIndex", 2, followerInfo.getNextIndex());
List<ApplyState> applyStateList = MessageCollectorActor.expectMatching(followerActor, ApplyState.class, 2);
ApplyState applyState = applyStateList.get(0);
assertEquals("Follower's first ApplyState index", 0, applyState.getReplicatedLogEntry().getIndex());
assertEquals("Follower's first ApplyState term", 2, applyState.getReplicatedLogEntry().getTerm());
assertEquals("Follower's first ApplyState data", leadersFirstLogEntry.getData(), applyState.getReplicatedLogEntry().getData());
applyState = applyStateList.get(1);
assertEquals("Follower's second ApplyState index", 1, applyState.getReplicatedLogEntry().getIndex());
assertEquals("Follower's second ApplyState term", 2, applyState.getReplicatedLogEntry().getTerm());
assertEquals("Follower's second ApplyState data", leadersSecondLogEntry.getData(), applyState.getReplicatedLogEntry().getData());
assertEquals("Follower's commit index", 1, followerActorContext.getCommitIndex());
assertEquals("Follower's lastIndex", 1, followerActorContext.getReplicatedLog().lastIndex());
assertEquals("Follower's lastTerm", 2, followerActorContext.getReplicatedLog().lastTerm());
}
use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class LeaderTest method testHandleReplicateMessageCommitIndexIncrementedBeforeConsensus.
@Test
public void testHandleReplicateMessageCommitIndexIncrementedBeforeConsensus() throws Exception {
logStart("testHandleReplicateMessageCommitIndexIncrementedBeforeConsensus");
MockRaftActorContext actorContext = createActorContextWithFollower();
actorContext.setRaftPolicy(createRaftPolicy(true, true));
long term = 1;
actorContext.getTermInformation().update(term, "");
leader = new Leader(actorContext);
// Leader will send an immediate heartbeat - ignore it.
MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
// The follower would normally reply - simulate that explicitly here.
long lastIndex = actorContext.getReplicatedLog().lastIndex();
leader.handleMessage(followerActor, new AppendEntriesReply(FOLLOWER_ID, term, true, lastIndex, term, (short) 0));
assertEquals("isFollowerActive", true, leader.getFollower(FOLLOWER_ID).isFollowerActive());
followerActor.underlyingActor().clear();
RaftActorBehavior raftBehavior = sendReplicate(actorContext, lastIndex + 1);
// State should not change
assertTrue(raftBehavior instanceof Leader);
AppendEntries appendEntries = MessageCollectorActor.expectFirstMatching(followerActor, AppendEntries.class);
assertEquals("getPrevLogIndex", lastIndex, appendEntries.getPrevLogIndex());
assertEquals("getPrevLogTerm", term, appendEntries.getPrevLogTerm());
assertEquals("Entries size", 1, appendEntries.getEntries().size());
assertEquals("Entry getIndex", lastIndex + 1, appendEntries.getEntries().get(0).getIndex());
assertEquals("Entry getTerm", term, appendEntries.getEntries().get(0).getTerm());
assertEquals("Entry payload", "foo", appendEntries.getEntries().get(0).getData().toString());
assertEquals("Commit Index", lastIndex + 1, actorContext.getCommitIndex());
}
Aggregations