Merge branch 'master' into 1063-docs-routing-he
Conflicts: akka-docs/java/routing.rst akka-docs/scala/routing.rst
This commit is contained in:
commit
26d49fecb9
57 changed files with 1633 additions and 877 deletions
154
akka-docs/scala/code/akka/docs/actor/TypedActorDocSpec.scala
Normal file
154
akka-docs/scala/code/akka/docs/actor/TypedActorDocSpec.scala
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
package akka.docs.actor
|
||||
|
||||
//#imports
|
||||
import akka.dispatch.{ Promise, Future, Await }
|
||||
import akka.util.duration._
|
||||
import akka.actor.{ ActorContext, TypedActor, Props }
|
||||
|
||||
//#imports
|
||||
|
||||
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
|
||||
import org.scalatest.matchers.MustMatchers
|
||||
import akka.testkit._
|
||||
|
||||
//#typed-actor-iface
|
||||
trait Squarer {
|
||||
//#typed-actor-iface-methods
|
||||
def squareDontCare(i: Int): Unit //fire-forget
|
||||
|
||||
def square(i: Int): Future[Int] //non-blocking send-request-reply
|
||||
|
||||
def squareNowPlease(i: Int): Option[Int] //blocking send-request-reply
|
||||
|
||||
def squareNow(i: Int): Int //blocking send-request-reply
|
||||
//#typed-actor-iface-methods
|
||||
}
|
||||
//#typed-actor-iface
|
||||
|
||||
//#typed-actor-impl
|
||||
class SquarerImpl(val name: String) extends Squarer {
|
||||
|
||||
def this() = this("default")
|
||||
//#typed-actor-impl-methods
|
||||
import TypedActor.dispatcher //So we can create Promises
|
||||
|
||||
def squareDontCare(i: Int): Unit = i * i //Nobody cares :(
|
||||
|
||||
def square(i: Int): Future[Int] = Promise successful i * i
|
||||
|
||||
def squareNowPlease(i: Int): Option[Int] = Some(i * i)
|
||||
|
||||
def squareNow(i: Int): Int = i * i
|
||||
//#typed-actor-impl-methods
|
||||
}
|
||||
//#typed-actor-impl
|
||||
|
||||
//#typed-actor-supercharge
|
||||
trait Foo {
|
||||
def doFoo(times: Int): Unit = println("doFoo(" + times + ")")
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
import TypedActor.dispatcher //So we have an implicit dispatcher for our Promise
|
||||
def doBar(str: String): Future[String] = Promise successful str.toUpperCase
|
||||
}
|
||||
|
||||
class FooBar extends Foo with Bar
|
||||
//#typed-actor-supercharge
|
||||
|
||||
class TypedActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
|
||||
|
||||
"get the TypedActor extension" in {
|
||||
val someReference: AnyRef = null
|
||||
|
||||
try {
|
||||
//#typed-actor-extension-tools
|
||||
|
||||
import akka.actor.TypedActor
|
||||
|
||||
//Returns the Typed Actor Extension
|
||||
val extension = TypedActor(system) //system is an instance of ActorSystem
|
||||
|
||||
//Returns whether the reference is a Typed Actor Proxy or not
|
||||
TypedActor(system).isTypedActor(someReference)
|
||||
|
||||
//Returns the backing Akka Actor behind an external Typed Actor Proxy
|
||||
TypedActor(system).getActorRefFor(someReference)
|
||||
|
||||
//Returns the current ActorContext,
|
||||
// method only valid within methods of a TypedActor implementation
|
||||
val c: ActorContext = TypedActor.context
|
||||
|
||||
//Returns the external proxy of the current Typed Actor,
|
||||
// method only valid within methods of a TypedActor implementation
|
||||
val s: Squarer = TypedActor.self[Squarer]
|
||||
|
||||
//Returns a contextual instance of the Typed Actor Extension
|
||||
//this means that if you create other Typed Actors with this,
|
||||
//they will become children to the current Typed Actor.
|
||||
TypedActor(TypedActor.context)
|
||||
|
||||
//#typed-actor-extension-tools
|
||||
} catch {
|
||||
case e: Exception ⇒ //dun care
|
||||
}
|
||||
}
|
||||
|
||||
"create a typed actor" in {
|
||||
//#typed-actor-create1
|
||||
val mySquarer: Squarer =
|
||||
TypedActor(system).typedActorOf[Squarer, SquarerImpl]()
|
||||
//#typed-actor-create1
|
||||
//#typed-actor-create2
|
||||
val otherSquarer: Squarer =
|
||||
TypedActor(system).typedActorOf(classOf[Squarer],
|
||||
new SquarerImpl("foo"),
|
||||
Props(),
|
||||
"name")
|
||||
//#typed-actor-create2
|
||||
|
||||
//#typed-actor-calls
|
||||
//#typed-actor-call-oneway
|
||||
mySquarer.squareDontCare(10)
|
||||
//#typed-actor-call-oneway
|
||||
|
||||
//#typed-actor-call-future
|
||||
val fSquare = mySquarer.square(10) //A Future[Int]
|
||||
//#typed-actor-call-future
|
||||
|
||||
//#typed-actor-call-option
|
||||
val oSquare = mySquarer.squareNowPlease(10) //Option[Int]
|
||||
//#typed-actor-call-option
|
||||
|
||||
//#typed-actor-call-strict
|
||||
val iSquare = mySquarer.squareNow(10) //Int
|
||||
//#typed-actor-call-strict
|
||||
//#typed-actor-calls
|
||||
|
||||
Await.result(fSquare, 3 seconds) must be === 100
|
||||
|
||||
oSquare must be === Some(100)
|
||||
|
||||
iSquare must be === 100
|
||||
|
||||
//#typed-actor-stop
|
||||
TypedActor(system).stop(mySquarer)
|
||||
//#typed-actor-stop
|
||||
|
||||
//#typed-actor-poisonpill
|
||||
TypedActor(system).poisonPill(otherSquarer)
|
||||
//#typed-actor-poisonpill
|
||||
}
|
||||
|
||||
"supercharge" in {
|
||||
//#typed-actor-supercharge-usage
|
||||
val awesomeFooBar = TypedActor(system).typedActorOf[Foo with Bar, FooBar]()
|
||||
|
||||
awesomeFooBar.doFoo(10)
|
||||
val f = awesomeFooBar.doBar("yes")
|
||||
|
||||
TypedActor(system).poisonPill(awesomeFooBar)
|
||||
//#typed-actor-supercharge-usage
|
||||
Await.result(f, 3 seconds) must be === "YES"
|
||||
}
|
||||
}
|
||||
44
akka-docs/scala/code/akka/docs/testkit/PlainWordSpec.scala
Normal file
44
akka-docs/scala/code/akka/docs/testkit/PlainWordSpec.scala
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package akka.docs.testkit
|
||||
|
||||
//#plain-spec
|
||||
import akka.actor.ActorSystem
|
||||
import akka.actor.Actor
|
||||
import akka.actor.Props
|
||||
import akka.testkit.TestKit
|
||||
import org.scalatest.WordSpec
|
||||
import org.scalatest.matchers.MustMatchers
|
||||
import org.scalatest.BeforeAndAfterAll
|
||||
import akka.testkit.ImplicitSender
|
||||
|
||||
object MySpec {
|
||||
class EchoActor extends Actor {
|
||||
def receive = {
|
||||
case x ⇒ sender ! x
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#implicit-sender
|
||||
class MySpec(_system: ActorSystem) extends TestKit(_system) with ImplicitSender
|
||||
with WordSpec with MustMatchers with BeforeAndAfterAll {
|
||||
//#implicit-sender
|
||||
|
||||
def this() = this(ActorSystem("MySpec"))
|
||||
|
||||
import MySpec._
|
||||
|
||||
override def afterAll {
|
||||
system.shutdown()
|
||||
}
|
||||
|
||||
"An Echo actor" must {
|
||||
|
||||
"send back messages unchanged" in {
|
||||
val echo = system.actorOf(Props[EchoActor])
|
||||
echo ! "hello world"
|
||||
expectMsg("hello world")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//#plain-spec
|
||||
238
akka-docs/scala/code/akka/docs/testkit/TestkitDocSpec.scala
Normal file
238
akka-docs/scala/code/akka/docs/testkit/TestkitDocSpec.scala
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
package akka.docs.testkit
|
||||
|
||||
//#imports-test-probe
|
||||
import akka.testkit.TestProbe
|
||||
import akka.actor.Actor
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.Props
|
||||
import akka.util.duration._
|
||||
|
||||
//#imports-test-probe
|
||||
|
||||
import akka.testkit.AkkaSpec
|
||||
import akka.actor.Actor
|
||||
import akka.testkit.DefaultTimeout
|
||||
import akka.testkit.ImplicitSender
|
||||
import akka.actor.ActorRef
|
||||
import akka.actor.Props
|
||||
|
||||
object TestkitDocSpec {
|
||||
case object Say42
|
||||
case object Unknown
|
||||
|
||||
class MyActor extends Actor {
|
||||
def receive = {
|
||||
case Say42 ⇒ sender ! 42
|
||||
case "some work" ⇒ sender ! "some result"
|
||||
}
|
||||
}
|
||||
|
||||
//#my-double-echo
|
||||
class MyDoubleEcho extends Actor {
|
||||
var dest1: ActorRef = _
|
||||
var dest2: ActorRef = _
|
||||
def receive = {
|
||||
case (d1: ActorRef, d2: ActorRef) ⇒
|
||||
dest1 = d1
|
||||
dest2 = d2
|
||||
case x ⇒
|
||||
dest1 ! x
|
||||
dest2 ! x
|
||||
}
|
||||
}
|
||||
|
||||
//#my-double-echo
|
||||
|
||||
import akka.testkit.TestProbe
|
||||
|
||||
//#test-probe-forward-actors
|
||||
class Source(target: ActorRef) extends Actor {
|
||||
def receive = {
|
||||
case "start" ⇒ target ! "work"
|
||||
}
|
||||
}
|
||||
|
||||
class Destination extends Actor {
|
||||
def receive = {
|
||||
case x ⇒ // Do something..
|
||||
}
|
||||
}
|
||||
|
||||
//#test-probe-forward-actors
|
||||
|
||||
class LoggingActor extends Actor {
|
||||
//#logging-receive
|
||||
import akka.event.LoggingReceive
|
||||
implicit def system = context.system
|
||||
def receive = LoggingReceive(this) {
|
||||
case msg ⇒ // Do something...
|
||||
}
|
||||
//#logging-receive
|
||||
}
|
||||
}
|
||||
|
||||
class TestkitDocSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
|
||||
import TestkitDocSpec._
|
||||
|
||||
"demonstrate usage of TestActorRef" in {
|
||||
//#test-actor-ref
|
||||
import akka.testkit.TestActorRef
|
||||
|
||||
val actorRef = TestActorRef[MyActor]
|
||||
val actor = actorRef.underlyingActor
|
||||
//#test-actor-ref
|
||||
}
|
||||
|
||||
"demonstrate usage of TestFSMRef" in {
|
||||
//#test-fsm-ref
|
||||
import akka.testkit.TestFSMRef
|
||||
import akka.actor.FSM
|
||||
import akka.util.duration._
|
||||
|
||||
val fsm = TestFSMRef(new Actor with FSM[Int, String] {
|
||||
startWith(1, "")
|
||||
when(1) {
|
||||
case Ev("go") ⇒ goto(2) using "go"
|
||||
}
|
||||
when(2) {
|
||||
case Ev("back") ⇒ goto(1) using "back"
|
||||
}
|
||||
})
|
||||
|
||||
assert(fsm.stateName == 1)
|
||||
assert(fsm.stateData == "")
|
||||
fsm ! "go" // being a TestActorRef, this runs also on the CallingThreadDispatcher
|
||||
assert(fsm.stateName == 2)
|
||||
assert(fsm.stateData == "go")
|
||||
|
||||
fsm.setState(stateName = 1)
|
||||
assert(fsm.stateName == 1)
|
||||
|
||||
assert(fsm.timerActive_?("test") == false)
|
||||
fsm.setTimer("test", 12, 10 millis, true)
|
||||
assert(fsm.timerActive_?("test") == true)
|
||||
fsm.cancelTimer("test")
|
||||
assert(fsm.timerActive_?("test") == false)
|
||||
//#test-fsm-ref
|
||||
}
|
||||
|
||||
"demonstrate testing of behavior" in {
|
||||
|
||||
//#test-behavior
|
||||
import akka.testkit.TestActorRef
|
||||
import akka.util.duration._
|
||||
import akka.dispatch.Await
|
||||
|
||||
val actorRef = TestActorRef(new MyActor)
|
||||
// hypothetical message stimulating a '42' answer
|
||||
val result = Await.result((actorRef ? Say42), 5 seconds).asInstanceOf[Int]
|
||||
result must be(42)
|
||||
//#test-behavior
|
||||
}
|
||||
|
||||
"demonstrate unhandled message" in {
|
||||
//#test-unhandled
|
||||
import akka.testkit.TestActorRef
|
||||
import akka.actor.UnhandledMessageException
|
||||
|
||||
val ref = TestActorRef[MyActor]
|
||||
intercept[UnhandledMessageException] { ref(Unknown) }
|
||||
//#test-unhandled
|
||||
}
|
||||
|
||||
"demonstrate expecting exceptions" in {
|
||||
//#test-expecting-exceptions
|
||||
import akka.testkit.TestActorRef
|
||||
|
||||
val actorRef = TestActorRef(new Actor {
|
||||
def receive = {
|
||||
case boom ⇒ throw new IllegalArgumentException("boom")
|
||||
}
|
||||
})
|
||||
intercept[IllegalArgumentException] { actorRef("hello") }
|
||||
//#test-expecting-exceptions
|
||||
}
|
||||
|
||||
"demonstrate within" in {
|
||||
type Worker = MyActor
|
||||
//#test-within
|
||||
import akka.actor.Props
|
||||
import akka.util.duration._
|
||||
|
||||
val worker = system.actorOf(Props[Worker])
|
||||
within(200 millis) {
|
||||
worker ! "some work"
|
||||
expectMsg("some result")
|
||||
expectNoMsg // will block for the rest of the 200ms
|
||||
Thread.sleep(300) // will NOT make this block fail
|
||||
}
|
||||
//#test-within
|
||||
}
|
||||
|
||||
"demonstrate dilated duration" in {
|
||||
//#duration-dilation
|
||||
import akka.util.duration._
|
||||
import akka.testkit._
|
||||
10.milliseconds.dilated
|
||||
//#duration-dilation
|
||||
}
|
||||
|
||||
"demonstrate usage of probe" in {
|
||||
//#test-probe
|
||||
val probe1 = TestProbe()
|
||||
val probe2 = TestProbe()
|
||||
val actor = system.actorOf(Props[MyDoubleEcho])
|
||||
actor ! (probe1.ref, probe2.ref)
|
||||
actor ! "hello"
|
||||
probe1.expectMsg(50 millis, "hello")
|
||||
probe2.expectMsg(50 millis, "hello")
|
||||
//#test-probe
|
||||
|
||||
//#test-special-probe
|
||||
case class Update(id: Int, value: String)
|
||||
|
||||
val probe = new TestProbe(system) {
|
||||
def expectUpdate(x: Int) = {
|
||||
expectMsgPF() {
|
||||
case Update(id, _) if id == x ⇒ true
|
||||
}
|
||||
sender ! "ACK"
|
||||
}
|
||||
}
|
||||
//#test-special-probe
|
||||
}
|
||||
|
||||
"demonstrate probe reply" in {
|
||||
import akka.testkit.TestProbe
|
||||
import akka.util.duration._
|
||||
//#test-probe-reply
|
||||
val probe = TestProbe()
|
||||
val future = probe.ref ? "hello"
|
||||
probe.expectMsg(0 millis, "hello") // TestActor runs on CallingThreadDispatcher
|
||||
probe.sender ! "world"
|
||||
assert(future.isCompleted && future.value == Some(Right("world")))
|
||||
//#test-probe-reply
|
||||
}
|
||||
|
||||
"demonstrate probe forward" in {
|
||||
import akka.testkit.TestProbe
|
||||
import akka.actor.Props
|
||||
//#test-probe-forward
|
||||
val probe = TestProbe()
|
||||
val source = system.actorOf(Props(new Source(probe.ref)))
|
||||
val dest = system.actorOf(Props[Destination])
|
||||
source ! "start"
|
||||
probe.expectMsg("work")
|
||||
probe.forward(dest)
|
||||
//#test-probe-forward
|
||||
}
|
||||
|
||||
"demonstrate " in {
|
||||
//#calling-thread-dispatcher
|
||||
import akka.testkit.CallingThreadDispatcher
|
||||
val dispatcher = new CallingThreadDispatcher(system.dispatcherFactory.prerequisites)
|
||||
val ref = system.actorOf(Props[MyActor].withDispatcher(dispatcher))
|
||||
//#calling-thread-dispatcher
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue