Avoid infinite recursion in AbstractFSM with Java on Scala 2.12 #12887
This commit is contained in:
parent
f528e67422
commit
f2adb0a3fd
2 changed files with 65 additions and 6 deletions
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
|
||||
*/
|
||||
package akka.actor;
|
||||
|
||||
import akka.testkit.AkkaJUnitActorSystemResource;
|
||||
import akka.testkit.AkkaSpec;
|
||||
import akka.testkit.TestProbe;
|
||||
import akka.testkit.javadsl.TestKit;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.scalatest.junit.JUnitSuite;
|
||||
|
||||
public class AbstractFSMActorTest extends JUnitSuite {
|
||||
|
||||
public static class MyFSM extends AbstractFSM<String, String> {
|
||||
|
||||
private final ActorRef probe;
|
||||
|
||||
MyFSM(ActorRef probe) {
|
||||
this.probe = probe;
|
||||
onTransition(this::logTransition);
|
||||
startWith("start", "data");
|
||||
when("start", matchEventEquals("next", (newState, data) ->
|
||||
goTo(newState)
|
||||
));
|
||||
when("next", AbstractFSM.NullFunction());
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void logTransition(final String s1, final String s2) {
|
||||
probe.tell(String.format("Transitioning from %1$s to %2$s.", s1, s2), getSelf());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ClassRule
|
||||
public static AkkaJUnitActorSystemResource actorSystemResource = new AkkaJUnitActorSystemResource("AbstractFSMActorTest",
|
||||
AkkaSpec.testConf());
|
||||
|
||||
private final ActorSystem system = actorSystemResource.getSystem();
|
||||
|
||||
@Test
|
||||
public void canCreateFSM() {
|
||||
// Coverage for #22887 (failed with Scala 2.12 before fix)
|
||||
TestProbe probe = new TestProbe(system);
|
||||
|
||||
ActorRef ref = system.actorOf(Props.create(MyFSM.class, probe.ref()));
|
||||
probe.expectMsg("Transitioning from start to start.");
|
||||
|
||||
ref.tell("next", ActorRef.noSender());
|
||||
|
||||
probe.expectMsg("Transitioning from start to next.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ abstract class AbstractFSM[S, D] extends FSM[S, D] {
|
|||
stateName: S,
|
||||
stateTimeout: FiniteDuration,
|
||||
stateFunctionBuilder: FSMStateFunctionBuilder[S, D]): Unit =
|
||||
when(stateName, stateTimeout)(stateFunctionBuilder.build())
|
||||
super.when(stateName, stateTimeout)(stateFunctionBuilder.build())
|
||||
|
||||
/**
|
||||
* Set initial state. Call this method from the constructor before the [[#initialize]] method.
|
||||
|
|
@ -119,7 +119,7 @@ abstract class AbstractFSM[S, D] extends FSM[S, D] {
|
|||
* @param timeout state timeout for the initial state, overriding the default timeout for that state
|
||||
*/
|
||||
final def startWith(stateName: S, stateData: D, timeout: FiniteDuration): Unit =
|
||||
startWith(stateName, stateData, Option(timeout))
|
||||
super.startWith(stateName, stateData, Option(timeout))
|
||||
|
||||
/**
|
||||
* Add a handler which is called upon each state transition, i.e. not when
|
||||
|
|
@ -129,7 +129,7 @@ abstract class AbstractFSM[S, D] extends FSM[S, D] {
|
|||
* called, not only the first one matching.</b>
|
||||
*/
|
||||
final def onTransition(transitionHandlerBuilder: FSMTransitionHandlerBuilder[S]): Unit =
|
||||
onTransition(transitionHandlerBuilder.build().asInstanceOf[TransitionHandler])
|
||||
super.onTransition(transitionHandlerBuilder.build().asInstanceOf[TransitionHandler])
|
||||
|
||||
/**
|
||||
* Add a handler which is called upon each state transition, i.e. not when
|
||||
|
|
@ -139,7 +139,7 @@ abstract class AbstractFSM[S, D] extends FSM[S, D] {
|
|||
* called, not only the first one matching.</b>
|
||||
*/
|
||||
final def onTransition(transitionHandler: UnitApply2[S, S]): Unit =
|
||||
onTransition(transitionHandler(_: S, _: S))
|
||||
super.onTransition(transitionHandler(_: S, _: S))
|
||||
|
||||
/**
|
||||
* Set handler which is called upon reception of unhandled messages. Calling
|
||||
|
|
@ -148,14 +148,14 @@ abstract class AbstractFSM[S, D] extends FSM[S, D] {
|
|||
* The current state may be queried using ``stateName``.
|
||||
*/
|
||||
final def whenUnhandled(stateFunctionBuilder: FSMStateFunctionBuilder[S, D]): Unit =
|
||||
whenUnhandled(stateFunctionBuilder.build())
|
||||
super.whenUnhandled(stateFunctionBuilder.build())
|
||||
|
||||
/**
|
||||
* Set handler which is called upon termination of this FSM actor. Calling
|
||||
* this method again will overwrite the previous contents.
|
||||
*/
|
||||
final def onTermination(stopBuilder: FSMStopBuilder[S, D]): Unit =
|
||||
onTermination(stopBuilder.build().asInstanceOf[PartialFunction[StopEvent, Unit]])
|
||||
super.onTermination(stopBuilder.build().asInstanceOf[PartialFunction[StopEvent, Unit]])
|
||||
|
||||
/**
|
||||
* Create an [[akka.japi.pf.FSMStateFunctionBuilder]] with the first case statement set.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue