X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-akka-raft%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fraft%2Fbehaviors%2FAbstractLeaderElectionScenarioTest.java;h=348b3d9acdd2e260de06edb222ddcf971ec609e9;hp=50f0c7b6af0b7d133e862430a9287777910fc8b1;hb=d3e310b940b60f6590f0e94a576aece95a055942;hpb=a54ec60368110d22794602343c934902f6833c65 diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeaderElectionScenarioTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeaderElectionScenarioTest.java index 50f0c7b6af..348b3d9acd 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeaderElectionScenarioTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeaderElectionScenarioTest.java @@ -25,8 +25,8 @@ import org.junit.After; import org.junit.Before; import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl; import org.opendaylight.controller.cluster.raft.MockRaftActorContext; -import org.opendaylight.controller.cluster.raft.RaftActorContext; import org.opendaylight.controller.cluster.raft.RaftState; +import org.opendaylight.controller.cluster.raft.TestActorFactory; import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat; import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply; import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor; @@ -62,10 +62,13 @@ public class AbstractLeaderElectionScenarioTest { try { if(behavior != null && !dropMessagesToBehavior.containsKey(message.getClass())) { - RaftActorBehavior oldBehavior = behavior; - behavior = behavior.handleMessage(getSender(), message); - if(behavior != oldBehavior && behaviorStateChangeLatch != null) { - behaviorStateChangeLatch.countDown(); + final RaftActorBehavior nextBehavior = behavior.handleMessage(getSender(), message); + if (nextBehavior != null) { + RaftActorBehavior oldBehavior = behavior; + behavior = nextBehavior; + if(behavior != oldBehavior && behaviorStateChangeLatch != null) { + behaviorStateChangeLatch.countDown(); + } } } } finally { @@ -132,14 +135,15 @@ public class AbstractLeaderElectionScenarioTest { } T getCapturedMessage(Class msgClass) throws Exception { - Object message = getFirstMatching(getSelf(), msgClass); + T message = getFirstMatching(getSelf(), msgClass); assertNotNull("Message of type " + msgClass + " not received", message); - return (T) message; + return message; } } protected final Logger testLog = LoggerFactory.getLogger(MockRaftActorContext.class); protected final ActorSystem system = ActorSystem.create("test"); + protected final TestActorFactory factory = new TestActorFactory(system); protected TestActorRef member1ActorRef; protected TestActorRef member2ActorRef; protected TestActorRef member3ActorRef; @@ -162,7 +166,18 @@ public class AbstractLeaderElectionScenarioTest { } @After - public void tearDown() { + public void tearDown() throws Exception { + + if (member1Actor.behavior != null) { + member1Actor.behavior.close(); + } + if (member2Actor.behavior != null) { + member2Actor.behavior.close(); + } + if (member3Actor.behavior != null) { + member3Actor.behavior.close(); + } + JavaTestKit.shutdownActorSystem(system); } @@ -186,27 +201,50 @@ public class AbstractLeaderElectionScenarioTest { assertEquals(name + " behavior state", expState, actor.behavior.state()); } - void initializeLeaderBehavior(MemberActor actor, RaftActorContext context, - int numActiveFollowers) throws Exception { + void initializeLeaderBehavior(MemberActor actor, MockRaftActorContext context, int numActiveFollowers) throws Exception { // Leader sends immediate heartbeats - we don't care about it so ignore it. + // Sometimes the initial AppendEntries messages go to dead letters, probably b/c the follower actors + // haven't been fully created/initialized by akka. So we try up to 3 times to create the Leader as + // a workaround. - actor.expectMessageClass(AppendEntriesReply.class, numActiveFollowers); - Leader leader = new Leader(context); - actor.waitForExpectedMessages(AppendEntriesReply.class); + Leader leader = null; + AssertionError lastAssertError = null; + for(int i = 1; i <= 3; i++) { + actor.expectMessageClass(AppendEntriesReply.class, numActiveFollowers); + + leader = new Leader(context); + try { + actor.waitForExpectedMessages(AppendEntriesReply.class); + lastAssertError = null; + break; + } catch (AssertionError e) { + lastAssertError = e; + } + } + + if(lastAssertError != null) { + throw lastAssertError; + } + + context.setCurrentBehavior(leader); + + // Delay assignment here so the AppendEntriesReply isn't forwarded to the behavior. actor.behavior = leader; actor.forwardCapturedMessagesToBehavior(AppendEntriesReply.class, ActorRef.noSender()); actor.clear(); + } TestActorRef newMemberActor(String name) throws Exception { - TestActorRef actor = TestActorRef.create(system, MemberActor.props(), name); + TestActorRef actor = factory.createTestActor(MemberActor.props(). + withDispatcher(Dispatchers.DefaultDispatcherId()), name); MessageCollectorActor.waitUntilReady(actor); return actor; } void sendHeartbeat(TestActorRef leaderActor) { Uninterruptibles.sleepUninterruptibly(HEARTBEAT_INTERVAL, TimeUnit.MILLISECONDS); - leaderActor.underlyingActor().behavior.handleMessage(leaderActor, new SendHeartBeat()); + leaderActor.underlyingActor().behavior.handleMessage(leaderActor, SendHeartBeat.INSTANCE); } }