use of akka.testkit.TestActorRef in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testAddServerWithNoConsensusReached.
@Test
public void testAddServerWithNoConsensusReached() {
LOG.info("testAddServerWithNoConsensusReached starting");
setupNewFollower();
RaftActorContext initialActorContext = new MockRaftActorContext();
TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.<String, String>of(), initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
final RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
final ActorRef leaderCollectorActor = newLeaderCollectorActor(leaderRaftActor);
// Drop UnInitializedFollowerSnapshotReply initially
leaderRaftActor.setDropMessageOfType(UnInitializedFollowerSnapshotReply.class);
MockNewFollowerRaftActor newFollowerRaftActorInstance = newFollowerRaftActor.underlyingActor();
newFollowerCollectorActor = newCollectorActor(newFollowerRaftActorInstance, NEW_SERVER_ID);
// Drop AppendEntries to the new follower so consensus isn't reached
newFollowerRaftActorInstance.setDropMessageOfType(AppendEntries.class);
leaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), true), testKit.getRef());
// Capture the UnInitializedFollowerSnapshotReply
Object snapshotReply = expectFirstMatching(leaderCollectorActor, UnInitializedFollowerSnapshotReply.class);
// Send the UnInitializedFollowerSnapshotReply to resume the first request
leaderRaftActor.setDropMessageOfType(null);
leaderActor.tell(snapshotReply, leaderActor);
expectFirstMatching(newFollowerCollectorActor, AppendEntries.class);
// Send a second AddServer
leaderActor.tell(new AddServer(NEW_SERVER_ID2, "", false), testKit.getRef());
// The first AddServer should succeed with OK even though consensus wasn't reached
AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.OK, addServerReply.getStatus());
assertEquals("getLeaderHint", LEADER_ID, addServerReply.getLeaderHint().get());
// Verify ServerConfigurationPayload entry in leader's log
verifyServerConfigurationPayloadEntry(leaderActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(NEW_SERVER_ID));
// The second AddServer should fail since consensus wasn't reached for the first
addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.PRIOR_REQUEST_CONSENSUS_TIMEOUT, addServerReply.getStatus());
// Re-send the second AddServer - should also fail
leaderActor.tell(new AddServer(NEW_SERVER_ID2, "", false), testKit.getRef());
addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.PRIOR_REQUEST_CONSENSUS_TIMEOUT, addServerReply.getStatus());
LOG.info("testAddServerWithNoConsensusReached ending");
}
use of akka.testkit.TestActorRef in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testChangeToVotingWithNoLeaderAndElectionTimeout.
@Test
public void testChangeToVotingWithNoLeaderAndElectionTimeout() {
LOG.info("testChangeToVotingWithNoLeaderAndElectionTimeout starting");
final String node1ID = "node1";
final String node2ID = "node2";
final PeerAddressResolver peerAddressResolver = peerId -> peerId.equals(node1ID) ? actorFactory.createTestActorPath(node1ID) : peerId.equals(node2ID) ? actorFactory.createTestActorPath(node2ID) : null;
ServerConfigurationPayload persistedServerConfig = new ServerConfigurationPayload(Arrays.asList(new ServerInfo(node1ID, false), new ServerInfo(node2ID, true)));
SimpleReplicatedLogEntry persistedServerConfigEntry = new SimpleReplicatedLogEntry(0, 1, persistedServerConfig);
InMemoryJournal.addEntry(node1ID, 1, new UpdateElectionTerm(1, "node1"));
InMemoryJournal.addEntry(node1ID, 2, persistedServerConfigEntry);
InMemoryJournal.addEntry(node2ID, 1, new UpdateElectionTerm(1, "node1"));
InMemoryJournal.addEntry(node2ID, 2, persistedServerConfigEntry);
DefaultConfigParamsImpl configParams1 = new DefaultConfigParamsImpl();
configParams1.setHeartBeatInterval(new FiniteDuration(100, TimeUnit.MILLISECONDS));
configParams1.setElectionTimeoutFactor(1);
configParams1.setPeerAddressResolver(peerAddressResolver);
ActorRef node1Collector = actorFactory.createActor(MessageCollectorActor.props(), actorFactory.generateActorId("collector"));
TestActorRef<CollectingMockRaftActor> node1RaftActorRef = actorFactory.createTestActor(CollectingMockRaftActor.props(node1ID, ImmutableMap.<String, String>of(), configParams1, PERSISTENT, node1Collector).withDispatcher(Dispatchers.DefaultDispatcherId()), node1ID);
final CollectingMockRaftActor node1RaftActor = node1RaftActorRef.underlyingActor();
DefaultConfigParamsImpl configParams2 = new DefaultConfigParamsImpl();
configParams2.setElectionTimeoutFactor(1000000);
configParams2.setPeerAddressResolver(peerAddressResolver);
ActorRef node2Collector = actorFactory.createActor(MessageCollectorActor.props(), actorFactory.generateActorId("collector"));
TestActorRef<CollectingMockRaftActor> node2RaftActorRef = actorFactory.createTestActor(CollectingMockRaftActor.props(node2ID, ImmutableMap.<String, String>of(), configParams2, PERSISTENT, node2Collector).withDispatcher(Dispatchers.DefaultDispatcherId()), node2ID);
CollectingMockRaftActor node2RaftActor = node2RaftActorRef.underlyingActor();
// Send a ChangeServersVotingStatus message to node1 to change mode1 to voting. This should cause
// node1 to try to elect itself as leader in order to apply the new server config. But we'll drop
// RequestVote messages in node2 which should cause node1 to time out and revert back to the previous
// server config and fail with NO_LEADER. Note that node1 shouldn't forward the request to node2 b/c
// node2 was previously voting.
node2RaftActor.setDropMessageOfType(RequestVote.class);
ChangeServersVotingStatus changeServers = new ChangeServersVotingStatus(ImmutableMap.of(node1ID, true));
node1RaftActorRef.tell(changeServers, testKit.getRef());
ServerChangeReply reply = testKit.expectMsgClass(testKit.duration("5 seconds"), ServerChangeReply.class);
assertEquals("getStatus", ServerChangeStatus.NO_LEADER, reply.getStatus());
assertEquals("Server config", Sets.newHashSet(nonVotingServer(node1ID), votingServer(node2ID)), Sets.newHashSet(node1RaftActor.getRaftActorContext().getPeerServerInfo(true).getServerConfig()));
assertEquals("getRaftState", RaftState.Follower, node1RaftActor.getRaftState());
LOG.info("testChangeToVotingWithNoLeaderAndElectionTimeout ending");
}
use of akka.testkit.TestActorRef in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testRemoveServerForwardToLeader.
@Test
public void testRemoveServerForwardToLeader() {
LOG.info("testRemoveServerForwardToLeader starting");
DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
configParams.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS));
ActorRef leaderActor = actorFactory.createTestActor(MessageCollectorActor.props(), actorFactory.generateActorId(LEADER_ID));
TestActorRef<MockRaftActor> followerRaftActor = actorFactory.createTestActor(MockRaftActor.builder().id(FOLLOWER_ID).peerAddresses(ImmutableMap.of(LEADER_ID, leaderActor.path().toString())).config(configParams).persistent(Optional.of(false)).props().withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(FOLLOWER_ID));
followerRaftActor.underlyingActor().waitForInitializeBehaviorComplete();
followerRaftActor.tell(new AppendEntries(1, LEADER_ID, 0, 1, Collections.<ReplicatedLogEntry>emptyList(), -1, -1, (short) 0), leaderActor);
followerRaftActor.tell(new RemoveServer(FOLLOWER_ID), testKit.getRef());
expectFirstMatching(leaderActor, RemoveServer.class);
LOG.info("testRemoveServerForwardToLeader ending");
}
use of akka.testkit.TestActorRef in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testAddServerWithNoExistingFollower.
@Test
public void testAddServerWithNoExistingFollower() throws Exception {
LOG.info("testAddServerWithNoExistingFollower starting");
setupNewFollower();
RaftActorContext initialActorContext = new MockRaftActorContext();
initialActorContext.setCommitIndex(1);
initialActorContext.setLastApplied(1);
initialActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 2, 1).build());
TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.<String, String>of(), initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
final RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
final ActorRef leaderCollectorActor = newLeaderCollectorActor(leaderRaftActor);
leaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), true), testKit.getRef());
// Leader should install snapshot - capture and verify ApplySnapshot contents
ApplySnapshot applySnapshot = expectFirstMatching(newFollowerCollectorActor, ApplySnapshot.class);
List<Object> snapshotState = MockRaftActor.fromState(applySnapshot.getSnapshot().getState());
assertEquals("Snapshot state", snapshotState, leaderRaftActor.getState());
AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.OK, addServerReply.getStatus());
assertEquals("getLeaderHint", LEADER_ID, addServerReply.getLeaderHint().get());
// Verify ServerConfigurationPayload entry in leader's log
expectFirstMatching(leaderCollectorActor, ApplyState.class);
assertEquals("Leader journal last index", 2, leaderActorContext.getReplicatedLog().lastIndex());
assertEquals("Leader commit index", 2, leaderActorContext.getCommitIndex());
assertEquals("Leader last applied index", 2, leaderActorContext.getLastApplied());
verifyServerConfigurationPayloadEntry(leaderActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(NEW_SERVER_ID));
// Verify ServerConfigurationPayload entry in the new follower
expectFirstMatching(newFollowerCollectorActor, ApplyState.class);
assertEquals("New follower journal last index", 2, newFollowerActorContext.getReplicatedLog().lastIndex());
verifyServerConfigurationPayloadEntry(newFollowerActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(NEW_SERVER_ID));
// Verify new server config was applied in the new follower
assertEquals("New follower peers", Sets.newHashSet(LEADER_ID), newFollowerActorContext.getPeerIds());
LOG.info("testAddServerWithNoExistingFollower ending");
}
use of akka.testkit.TestActorRef in project controller by opendaylight.
the class RaftActorServerConfigurationSupportTest method testAddServerWithOperationInProgress.
@Test
public void testAddServerWithOperationInProgress() throws Exception {
LOG.info("testAddServerWithOperationInProgress starting");
setupNewFollower();
RaftActorContext initialActorContext = new MockRaftActorContext();
TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(ImmutableMap.<String, String>of(), initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()), actorFactory.generateActorId(LEADER_ID));
MockLeaderRaftActor leaderRaftActor = leaderActor.underlyingActor();
final RaftActorContext leaderActorContext = leaderRaftActor.getRaftActorContext();
final ActorRef leaderCollectorActor = newLeaderCollectorActor(leaderRaftActor);
RaftActorContext follower2ActorContext = newFollowerContext(NEW_SERVER_ID2, followerActor);
Follower newFollower2 = new Follower(follower2ActorContext);
followerActor.underlyingActor().setBehavior(newFollower2);
MockNewFollowerRaftActor newFollowerRaftActorInstance = newFollowerRaftActor.underlyingActor();
newFollowerRaftActorInstance.setDropMessageOfType(InstallSnapshot.class);
leaderActor.tell(new AddServer(NEW_SERVER_ID, newFollowerRaftActor.path().toString(), true), testKit.getRef());
// Wait for leader's install snapshot and capture it
InstallSnapshot installSnapshot = expectFirstMatching(newFollowerCollectorActor, InstallSnapshot.class);
// Send a second AddServer - should get queued
TestKit testKit2 = new TestKit(getSystem());
leaderActor.tell(new AddServer(NEW_SERVER_ID2, followerActor.path().toString(), false), testKit2.getRef());
// Continue the first AddServer
newFollowerRaftActorInstance.setDropMessageOfType(null);
newFollowerRaftActor.tell(installSnapshot, leaderActor);
// Verify both complete successfully
AddServerReply addServerReply = testKit.expectMsgClass(testKit.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.OK, addServerReply.getStatus());
addServerReply = testKit2.expectMsgClass(testKit2.duration("5 seconds"), AddServerReply.class);
assertEquals("getStatus", ServerChangeStatus.OK, addServerReply.getStatus());
// Verify ServerConfigurationPayload entries in leader's log
expectMatching(leaderCollectorActor, ApplyState.class, 2);
assertEquals("Leader journal last index", 1, leaderActorContext.getReplicatedLog().lastIndex());
assertEquals("Leader commit index", 1, leaderActorContext.getCommitIndex());
assertEquals("Leader last applied index", 1, leaderActorContext.getLastApplied());
verifyServerConfigurationPayloadEntry(leaderActorContext.getReplicatedLog(), votingServer(LEADER_ID), votingServer(NEW_SERVER_ID), nonVotingServer(NEW_SERVER_ID2));
// Verify ServerConfigurationPayload entry in the new follower
expectMatching(newFollowerCollectorActor, ApplyState.class, 2);
assertEquals("New follower peers", Sets.newHashSet(LEADER_ID, NEW_SERVER_ID2), newFollowerActorContext.getPeerIds());
LOG.info("testAddServerWithOperationInProgress ending");
}
Aggregations