X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-akka-raft%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fraft%2FTestActorFactory.java;h=4ca018c5e2a29634f37a716fe889367a3b0f789d;hb=388dd012c7b36177808ff5c5ad692b16dd58c944;hp=b47df13fed8c97297abf66c68bc837a03988dfb9;hpb=bfd413d87f82ee3ffed67a141a980805950a0f06;p=controller.git diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/TestActorFactory.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/TestActorFactory.java index b47df13fed..4ca018c5e2 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/TestActorFactory.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/TestActorFactory.java @@ -23,10 +23,14 @@ import akka.actor.PoisonPill; import akka.actor.Props; import akka.testkit.JavaTestKit; import akka.testkit.TestActorRef; +import akka.util.Timeout; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import scala.concurrent.Await; +import scala.concurrent.Future; /** * TestActorFactory provides methods to create both normal and test actors and to kill them when the factory is closed @@ -58,8 +62,7 @@ public class TestActorFactory implements AutoCloseable { */ public ActorRef createActor(Props props){ ActorRef actorRef = system.actorOf(props); - createdActors.add(actorRef); - return actorRef; + return addActor(actorRef); } /** @@ -70,8 +73,7 @@ public class TestActorFactory implements AutoCloseable { */ public ActorRef createActor(Props props, String actorId){ ActorRef actorRef = system.actorOf(props, actorId); - createdActors.add(actorRef); - return actorRef; + return addActor(actorRef); } /** @@ -81,22 +83,49 @@ public class TestActorFactory implements AutoCloseable { * @param * @return */ + @SuppressWarnings("unchecked") public TestActorRef createTestActor(Props props, String actorId){ TestActorRef actorRef = TestActorRef.create(system, props, actorId); + return (TestActorRef) addActor(actorRef); + } + + private ActorRef addActor(T actorRef) { createdActors.add(actorRef); + verifyActorReady(actorRef); return actorRef; } + private void verifyActorReady(ActorRef actorRef) { + // Sometimes we see messages go to dead letters soon after creation - it seems the actor isn't quite + // in a state yet to receive messages or isn't actually created yet. This seems to happen with + // actorSelection so, to alleviate it, we use an actorSelection and call resolveOne with retries to + // ensure it's ready. + + int tries = 1; + while(true) { + try { + Timeout timeout = new Timeout(100, TimeUnit.MILLISECONDS); + Future future = system.actorSelection(actorRef.path()).resolveOne(timeout); + Await.ready(future, timeout.duration()); + break; + } catch (Exception e) { + if(tries++ > 20) { + throw new RuntimeException(e); + } + } + } + } + /** * Create a test actor with an auto-generated name * @param props * @param * @return */ + @SuppressWarnings("unchecked") public TestActorRef createTestActor(Props props){ TestActorRef actorRef = TestActorRef.create(system, props); - createdActors.add(actorRef); - return actorRef; + return (TestActorRef) addActor(actorRef); } /** @@ -108,15 +137,30 @@ public class TestActorFactory implements AutoCloseable { return prefix + actorCount++; } + public void killActor(ActorRef actor, JavaTestKit kit) { + killActor(actor, kit, true); + } + + public String createTestActorPath(String actorId){ + return "akka://test/user/" + actorId; + } + + private void killActor(ActorRef actor, JavaTestKit kit, boolean remove) { + LOG.info("Killing actor {}", actor); + kit.watch(actor); + actor.tell(PoisonPill.getInstance(), ActorRef.noSender()); + kit.expectTerminated(JavaTestKit.duration("5 seconds"), actor); + + if(remove) { + createdActors.remove(actor); + } + } + @Override public void close() { - new JavaTestKit(system) {{ - for(ActorRef actor : createdActors) { - watch(actor); - LOG.info("Killing actor {}", actor); - actor.tell(PoisonPill.getInstance(), ActorRef.noSender()); - expectTerminated(duration("5 seconds"), actor); - } - }}; + JavaTestKit kit = new JavaTestKit(system); + for(ActorRef actor : createdActors) { + killActor(actor, kit, false); + } } } \ No newline at end of file