use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class AbstractLeaderElectionScenarioTest method newRaftActorContext.
MockRaftActorContext newRaftActorContext(final String id, final ActorRef actor, final Map<String, String> peerAddresses) {
MockRaftActorContext context = new MockRaftActorContext(id, system, actor);
context.setPeerAddresses(peerAddresses);
context.getTermInformation().updateAndPersist(1, "");
return context;
}
use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class AbstractLeaderTest method testLeaderSchedulesHeartbeatsEvenWhenNoFollowersRespondToInitialAppendEntries.
/**
* When we removed scheduling of heartbeat in the AbstractLeader constructor we ended up with a situation where
* if no follower responded to an initial AppendEntries heartbeats would not be sent to it. This test verifies
* that regardless of whether followers respond or not we schedule heartbeats.
*/
@Test
public void testLeaderSchedulesHeartbeatsEvenWhenNoFollowersRespondToInitialAppendEntries() throws Exception {
logStart("testLeaderSchedulesHeartbeatsEvenWhenNoFollowersRespondToInitialAppendEntries");
String leaderActorId = actorFactory.generateActorId("leader");
String follower1ActorId = actorFactory.generateActorId("follower");
String follower2ActorId = actorFactory.generateActorId("follower");
TestActorRef<ForwardMessageToBehaviorActor> leaderActor = actorFactory.createTestActor(ForwardMessageToBehaviorActor.props(), leaderActorId);
final ActorRef follower1Actor = actorFactory.createActor(MessageCollectorActor.props(), follower1ActorId);
final ActorRef follower2Actor = actorFactory.createActor(MessageCollectorActor.props(), follower2ActorId);
MockRaftActorContext leaderActorContext = new MockRaftActorContext(leaderActorId, getSystem(), leaderActor);
DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
configParams.setHeartBeatInterval(new FiniteDuration(200, TimeUnit.MILLISECONDS));
configParams.setIsolatedLeaderCheckInterval(new FiniteDuration(10, TimeUnit.SECONDS));
leaderActorContext.setConfigParams(configParams);
leaderActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(1, 5, 1).build());
Map<String, String> peerAddresses = new HashMap<>();
peerAddresses.put(follower1ActorId, follower1Actor.path().toString());
peerAddresses.put(follower2ActorId, follower2Actor.path().toString());
leaderActorContext.setPeerAddresses(peerAddresses);
RaftActorBehavior leader = createBehavior(leaderActorContext);
leaderActor.underlyingActor().setBehavior(leader);
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
List<SendHeartBeat> allMessages = MessageCollectorActor.getAllMatching(leaderActor, SendHeartBeat.class);
// Need more than 1 heartbeat to be delivered because we waited for 1 second with heartbeat interval 200ms
assertTrue(String.format("%s messages is less than expected", allMessages.size()), allMessages.size() > 1);
}
use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class AbstractRaftActorBehaviorTest method testHandleAppendEntriesAddSameEntryToLog.
@Test
public void testHandleAppendEntriesAddSameEntryToLog() {
MockRaftActorContext context = createActorContext();
context.getTermInformation().update(2, "test");
// Prepare the receivers log
MockRaftActorContext.MockPayload payload = new MockRaftActorContext.MockPayload("zero");
setLastLogEntry(context, 2, 0, payload);
List<ReplicatedLogEntry> entries = new ArrayList<>();
entries.add(new SimpleReplicatedLogEntry(0, 2, payload));
final AppendEntries appendEntries = new AppendEntries(2, "leader-1", -1, -1, entries, 2, -1, (short) 0);
behavior = createBehavior(context);
assertFalse("This test should be overridden when testing Candidate", behavior instanceof Candidate);
RaftState expected = behavior.state();
// Check that the behavior does not handle unknwon message
assertNull(behavior.handleMessage(behaviorActor, "unknown"));
RaftActorBehavior raftBehavior = behavior.handleMessage(behaviorActor, appendEntries);
assertEquals("Raft state", expected, raftBehavior.state());
assertEquals("ReplicatedLog size", 1, context.getReplicatedLog().size());
handleAppendEntriesAddSameEntryToLogReply(behaviorActor);
}
use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class AbstractRaftActorBehaviorTest method testPerformSnapshot.
@Test
public void testPerformSnapshot() {
MockRaftActorContext context = new MockRaftActorContext("test", getSystem(), behaviorActor);
AbstractRaftActorBehavior abstractBehavior = (AbstractRaftActorBehavior) createBehavior(context);
if (abstractBehavior instanceof Candidate) {
return;
}
context.getTermInformation().update(1, "test");
// log has 1 entry with replicatedToAllIndex = 0, does not do anything, returns the
context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 1, 1).build());
context.setLastApplied(0);
abstractBehavior.performSnapshotWithoutCapture(0);
assertEquals(-1, abstractBehavior.getReplicatedToAllIndex());
assertEquals(1, context.getReplicatedLog().size());
// 2 entries, lastApplied still 0, no purging.
context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 2, 1).build());
context.setLastApplied(0);
abstractBehavior.performSnapshotWithoutCapture(0);
assertEquals(-1, abstractBehavior.getReplicatedToAllIndex());
assertEquals(2, context.getReplicatedLog().size());
// 2 entries, lastApplied still 0, no purging.
context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 2, 1).build());
context.setLastApplied(1);
abstractBehavior.performSnapshotWithoutCapture(0);
assertEquals(0, abstractBehavior.getReplicatedToAllIndex());
assertEquals(1, context.getReplicatedLog().size());
// 5 entries, lastApplied =2 and replicatedIndex = 3, but since we want to keep the lastapplied, indices 0 and
// 1 will only get purged
context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 5, 1).build());
context.setLastApplied(2);
abstractBehavior.performSnapshotWithoutCapture(3);
assertEquals(1, abstractBehavior.getReplicatedToAllIndex());
assertEquals(3, context.getReplicatedLog().size());
// scenario where Last applied > Replicated to all index (becoz of a slow follower)
context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 3, 1).build());
context.setLastApplied(2);
abstractBehavior.performSnapshotWithoutCapture(1);
assertEquals(1, abstractBehavior.getReplicatedToAllIndex());
assertEquals(1, context.getReplicatedLog().size());
}
use of org.opendaylight.controller.cluster.raft.MockRaftActorContext in project controller by opendaylight.
the class AbstractRaftActorBehaviorTest method testHandleAppendEntriesSenderTermLessThanReceiverTerm.
/**
* This test verifies that when an AppendEntries is received with a term that
* is less that the currentTerm of the RaftActor then the RaftActor does not
* change it's state and it responds back with a failure.
*/
@Test
public void testHandleAppendEntriesSenderTermLessThanReceiverTerm() {
MockRaftActorContext context = createActorContext();
short payloadVersion = 5;
context.setPayloadVersion(payloadVersion);
// First set the receivers term to a high number (1000)
context.getTermInformation().update(1000, "test");
AppendEntries appendEntries = new AppendEntries(100, "leader-1", 0, 0, Collections.emptyList(), 101, -1, (short) 4);
behavior = createBehavior(context);
RaftState expected = behavior.state();
RaftActorBehavior raftBehavior = behavior.handleMessage(behaviorActor, appendEntries);
assertEquals("Raft state", expected, raftBehavior.state());
// Also expect an AppendEntriesReply to be sent where success is false
AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(behaviorActor, AppendEntriesReply.class);
assertEquals("isSuccess", false, reply.isSuccess());
assertEquals("getPayloadVersion", payloadVersion, reply.getPayloadVersion());
}
Aggregations