=per #18162 harden PersistentFSMActorSpec, less timing sensitive

This commit is contained in:
Konrad Malawski 2015-08-10 14:39:19 +02:00
parent 235df6ce09
commit 1bbf0731df
2 changed files with 10 additions and 14 deletions

View file

@ -33,13 +33,13 @@ object FSM {
* [[akka.actor.FSM.SubscribeTransitionCallBack]] before sending any * [[akka.actor.FSM.SubscribeTransitionCallBack]] before sending any
* [[akka.actor.FSM.Transition]] messages. * [[akka.actor.FSM.Transition]] messages.
*/ */
final case class CurrentState[S](fsmRef: ActorRef, state: S) final case class CurrentState[S](fsmRef: ActorRef, state: S, timeout: Option[FiniteDuration] = None)
/** /**
* Message type which is used to communicate transitions between states to * Message type which is used to communicate transitions between states to
* all subscribed listeners (use [[akka.actor.FSM.SubscribeTransitionCallBack]]). * all subscribed listeners (use [[akka.actor.FSM.SubscribeTransitionCallBack]]).
*/ */
final case class Transition[S](fsmRef: ActorRef, from: S, to: S) final case class Transition[S](fsmRef: ActorRef, from: S, to: S, timeout: Option[FiniteDuration] = None)
/** /**
* Send this to an [[akka.actor.FSM]] to request first the [[FSM.CurrentState]] * Send this to an [[akka.actor.FSM]] to request first the [[FSM.CurrentState]]
@ -622,17 +622,17 @@ trait FSM[S, D, E] extends Actor with Listeners with ActorLogging {
// TODO Use context.watch(actor) and receive Terminated(actor) to clean up list // TODO Use context.watch(actor) and receive Terminated(actor) to clean up list
listeners.add(actorRef) listeners.add(actorRef)
// send current state back as reference point // send current state back as reference point
actorRef ! CurrentState(self, currentState.stateName) actorRef ! CurrentState(self, currentState.stateName, currentState.timeout)
case Listen(actorRef) case Listen(actorRef)
// TODO Use context.watch(actor) and receive Terminated(actor) to clean up list // TODO Use context.watch(actor) and receive Terminated(actor) to clean up list
listeners.add(actorRef) listeners.add(actorRef)
// send current state back as reference point // send current state back as reference point
actorRef ! CurrentState(self, currentState.stateName) actorRef ! CurrentState(self, currentState.stateName, currentState.timeout)
case UnsubscribeTransitionCallBack(actorRef) case UnsubscribeTransitionCallBack(actorRef)
listeners.remove(actorRef) listeners.remove(actorRef)
case Deafen(actorRef) case Deafen(actorRef)
listeners.remove(actorRef) listeners.remove(actorRef)
case value { case value
if (timeoutFuture.isDefined) { if (timeoutFuture.isDefined) {
timeoutFuture.get.cancel() timeoutFuture.get.cancel()
timeoutFuture = None timeoutFuture = None
@ -640,7 +640,6 @@ trait FSM[S, D, E] extends Actor with Listeners with ActorLogging {
generation += 1 generation += 1
processMsg(value, sender()) processMsg(value, sender())
} }
}
private def processMsg(value: Any, source: AnyRef): Unit = { private def processMsg(value: Any, source: AnyRef): Unit = {
val event = Event(value, currentState.stateData) val event = Event(value, currentState.stateData)

View file

@ -195,7 +195,7 @@ abstract class PersistentFSMActorSpec(config: Config) extends PersistenceSpec(co
expectMsg(CurrentState(fsmRef, LookingAround)) expectMsg(CurrentState(fsmRef, LookingAround))
expectMsg(Transition(fsmRef, LookingAround, Shopping)) expectMsg(Transition(fsmRef, LookingAround, Shopping))
expectNoMsg(0.6 seconds) //randomly chosen delay, less than the timeout, before stopping the FSM expectNoMsg(0.6 seconds) // arbitrarily chosen delay, less than the timeout, before stopping the FSM
fsmRef ! PoisonPill fsmRef ! PoisonPill
expectTerminated(fsmRef) expectTerminated(fsmRef)
@ -203,13 +203,13 @@ abstract class PersistentFSMActorSpec(config: Config) extends PersistenceSpec(co
watch(recoveredFsmRef) watch(recoveredFsmRef)
recoveredFsmRef ! SubscribeTransitionCallBack(testActor) recoveredFsmRef ! SubscribeTransitionCallBack(testActor)
expectMsg(CurrentState(recoveredFsmRef, Shopping)) expectMsg(CurrentState(recoveredFsmRef, Shopping, Some(1 second)))
within(0.9 seconds, 1.9 seconds) { within(0.9 seconds, 1.9 seconds) {
expectMsg(Transition(recoveredFsmRef, Shopping, Inactive)) expectMsg(Transition(recoveredFsmRef, Shopping, Inactive))
} }
expectNoMsg(0.9 seconds) //randomly chosen delay, less than the timeout, before stopping the FSM expectNoMsg(0.6 seconds) // arbitrarily chosen delay, less than the timeout, before stopping the FSM
recoveredFsmRef ! PoisonPill recoveredFsmRef ! PoisonPill
expectTerminated(recoveredFsmRef) expectTerminated(recoveredFsmRef)
@ -217,12 +217,9 @@ abstract class PersistentFSMActorSpec(config: Config) extends PersistenceSpec(co
watch(recoveredFsmRef) watch(recoveredFsmRef)
recoveredFsmRef ! SubscribeTransitionCallBack(testActor) recoveredFsmRef ! SubscribeTransitionCallBack(testActor)
expectMsg(CurrentState(recoveredFsmRef, Inactive)) expectMsg(CurrentState(recoveredFsmRef, Inactive, Some(2 seconds)))
within(1.9 seconds, 2.9 seconds) {
expectTerminated(recoveredFsmRef) expectTerminated(recoveredFsmRef)
} }
}
"not trigger onTransition for stay()" taggedAs TimingTest in { "not trigger onTransition for stay()" taggedAs TimingTest in {
val persistenceId = name val persistenceId = name