2011-06-04 17:34:37 +02:00
|
|
|
/**
|
2011-07-14 16:03:08 +02:00
|
|
|
* Copyright (C) 2009-2011 Typesafe Inc. <http://www.typesafe.com>
|
2011-06-04 17:34:37 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package akka.testkit
|
|
|
|
|
|
|
|
|
|
import akka.actor._
|
2011-06-05 10:45:27 +02:00
|
|
|
import akka.util._
|
|
|
|
|
import com.eaio.uuid.UUID
|
2011-11-10 20:08:00 +01:00
|
|
|
import akka.actor.ActorSystem
|
2011-06-04 17:34:37 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This is a specialised form of the TestActorRef with support for querying and
|
|
|
|
|
* setting the state of a FSM. Use a LoggingFSM with this class if you also
|
|
|
|
|
* need to inspect event traces.
|
|
|
|
|
*
|
|
|
|
|
* <pre><code>
|
|
|
|
|
* val fsm = TestFSMRef(new Actor with LoggingFSM[Int, Null] {
|
|
|
|
|
* override def logDepth = 12
|
|
|
|
|
* startWith(1, null)
|
|
|
|
|
* when(1) {
|
|
|
|
|
* case Ev("hello") => goto(2)
|
|
|
|
|
* }
|
|
|
|
|
* when(2) {
|
|
|
|
|
* case Ev("world") => goto(1)
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* assert (fsm.stateName == 1)
|
|
|
|
|
* fsm ! "hallo"
|
|
|
|
|
* assert (fsm.stateName == 2)
|
|
|
|
|
* assert (fsm.underlyingActor.getLog == IndexedSeq(FSMLogEntry(1, null, "hallo")))
|
|
|
|
|
* </code></pre>
|
|
|
|
|
*
|
|
|
|
|
* @author Roland Kuhn
|
|
|
|
|
* @since 1.2
|
|
|
|
|
*/
|
2011-11-10 20:08:00 +01:00
|
|
|
class TestFSMRef[S, D, T <: Actor](app: ActorSystem, props: Props, supervisor: ActorRef, name: String)(implicit ev: T <:< FSM[S, D])
|
2011-11-08 14:30:33 +01:00
|
|
|
extends TestActorRef(app, props, supervisor, name) {
|
2011-06-04 17:34:37 +02:00
|
|
|
|
2011-08-26 17:25:18 +02:00
|
|
|
private def fsm: T = underlyingActor
|
2011-06-04 17:34:37 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get current state name of this FSM.
|
|
|
|
|
*/
|
|
|
|
|
def stateName: S = fsm.stateName
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get current state data of this FSM.
|
|
|
|
|
*/
|
|
|
|
|
def stateData: D = fsm.stateData
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Change FSM state; any value left out defaults to the current FSM state
|
|
|
|
|
* (timeout defaults to None). This method is directly equivalent to a
|
|
|
|
|
* corresponding transition initiated from within the FSM, including timeout
|
|
|
|
|
* and stop handling.
|
|
|
|
|
*/
|
2011-06-05 10:45:27 +02:00
|
|
|
def setState(stateName: S = fsm.stateName, stateData: D = fsm.stateData, timeout: Option[Duration] = None, stopReason: Option[FSM.Reason] = None) {
|
|
|
|
|
fsm.applyState(FSM.State(stateName, stateData, timeout, stopReason))
|
2011-06-04 17:34:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Proxy for FSM.setTimer.
|
|
|
|
|
*/
|
|
|
|
|
def setTimer(name: String, msg: Any, timeout: Duration, repeat: Boolean) {
|
|
|
|
|
fsm.setTimer(name, msg, timeout, repeat)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Proxy for FSM.cancelTimer.
|
|
|
|
|
*/
|
|
|
|
|
def cancelTimer(name: String) { fsm.cancelTimer(name) }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Proxy for FSM.timerActive_?.
|
|
|
|
|
*/
|
|
|
|
|
def timerActive_?(name: String) = fsm.timerActive_?(name)
|
|
|
|
|
|
2011-06-05 10:45:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object TestFSMRef {
|
|
|
|
|
|
2011-11-10 20:08:00 +01:00
|
|
|
def apply[S, D, T <: Actor](factory: ⇒ T)(implicit ev: T <:< FSM[S, D], app: ActorSystem): TestFSMRef[S, D, T] =
|
2011-11-13 20:38:14 +01:00
|
|
|
new TestFSMRef(app, Props(creator = () ⇒ factory), app.guardian, TestActorRef.randomName)
|
2011-06-05 10:45:27 +02:00
|
|
|
|
2011-11-10 20:08:00 +01:00
|
|
|
def apply[S, D, T <: Actor](factory: ⇒ T, name: String)(implicit ev: T <:< FSM[S, D], app: ActorSystem): TestFSMRef[S, D, T] =
|
2011-11-08 14:30:33 +01:00
|
|
|
new TestFSMRef(app, Props(creator = () ⇒ factory), app.guardian, name)
|
2011-06-04 17:34:37 +02:00
|
|
|
}
|