Use Wordspec for all tests
It was discussed and team agreed we'd rather have consistent tests even if the compilation is slightly slower.
This commit is contained in:
parent
c394ee7aaa
commit
97180eb6ed
34 changed files with 1390 additions and 1360 deletions
|
|
@ -13,7 +13,7 @@ import java.util.Optional;
|
|||
import static junit.framework.TestCase.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
class ExtensionsTest extends JUnitSuite {
|
||||
public class ExtensionsTest extends JUnitSuite {
|
||||
|
||||
public static class MyExtImpl implements Extension {
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ class ExtensionsTest extends JUnitSuite {
|
|||
Behavior.empty(),
|
||||
"loadJavaExtensionsFromConfig",
|
||||
Optional.empty(),
|
||||
Optional.of(ConfigFactory.parseString("akka.typed.extensions += \"akka.typed.ExtensionsTest$MyExtension\"").resolve()),
|
||||
Optional.of(ConfigFactory.parseString("akka.typed.extensions += \"akka.actor.typed.ExtensionsTest$MyExtension\"").resolve()),
|
||||
Optional.empty(),
|
||||
Optional.empty()
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Copyright (C) 2017 Lightbend Inc. <http://www.lightbend.com>
|
||||
*/
|
||||
package jdocs.akka.actor.typed;
|
||||
package jdocs.akka.typed;
|
||||
|
||||
//#imports
|
||||
import akka.actor.typed.ActorRef;
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ object ActorContextSpec {
|
|||
|
||||
}
|
||||
|
||||
class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
||||
abstract class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
||||
"""|akka {
|
||||
| loglevel = WARNING
|
||||
| actor.debug {
|
||||
|
|
@ -268,11 +268,11 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
| }
|
||||
| typed.loggers = ["akka.typed.testkit.TestEventListener"]
|
||||
|}""".stripMargin)) {
|
||||
|
||||
import ActorContextSpec._
|
||||
|
||||
val expectTimeout = 3.seconds
|
||||
|
||||
trait Tests {
|
||||
/**
|
||||
* The name for the set of tests to be instantiated, used for keeping the test case actors’ names unique.
|
||||
*/
|
||||
|
|
@ -283,8 +283,6 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
*/
|
||||
def behavior(ctx: scaladsl.ActorContext[Event], ignorePostStop: Boolean): Behavior[Command]
|
||||
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
|
||||
private def mySuite: String = suite + "Adapted"
|
||||
|
||||
def setup(name: String, wrapper: Option[Behavior[Command] ⇒ Behavior[Command]] = None, ignorePostStop: Boolean = true)(
|
||||
|
|
@ -336,7 +334,9 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
|
||||
protected def stop(ref: ActorRef[Command]) = ref ! Stop
|
||||
|
||||
def `00 must canonicalize behaviors`(): Unit = sync(setup("ctx00") { (ctx, startWith) ⇒
|
||||
"An ActorContext" must {
|
||||
"canonicalize behaviors" in {
|
||||
sync(setup("ctx00") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith.keep { subj ⇒
|
||||
subj ! Ping(self)
|
||||
|
|
@ -353,8 +353,9 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msg should ===(Pong1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `01 must correctly wire the lifecycle hooks`(): Unit =
|
||||
"correctly wire the lifecycle hooks" in {
|
||||
sync(setup("ctx01", Some(b ⇒ Actor.supervise(b).onFailure[Throwable](SupervisorStrategy.restart)), ignorePostStop = false) { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
val ex = new Exception("KABOOM1")
|
||||
|
|
@ -371,8 +372,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msg should ===(GotSignal(PostStop))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `02 must signal PostStop after voluntary termination`(): Unit = sync(setup("ctx02", ignorePostStop = false) { (ctx, startWith) ⇒
|
||||
"signal PostStop after voluntary termination" in {
|
||||
sync(setup("ctx02", ignorePostStop = false) { (ctx, startWith) ⇒
|
||||
startWith.keep { subj ⇒
|
||||
stop(subj)
|
||||
}.expectMessage(expectTimeout) {
|
||||
|
|
@ -380,8 +383,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msg should ===(GotSignal(PostStop))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `03 must restart and stop a child actor`(): Unit = sync(setup("ctx03") { (ctx, startWith) ⇒
|
||||
"restart and stop a child actor" in {
|
||||
sync(setup("ctx03") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
val ex = new Exception("KABOOM2")
|
||||
startWith.mkChild(None, ctx.spawnAdapter(ChildEvent), self) {
|
||||
|
|
@ -410,8 +415,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
t.ref should ===(subj)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `04 must stop a child actor`(): Unit = sync(setup("ctx04") { (ctx, startWith) ⇒
|
||||
"stop a child actor" in {
|
||||
sync(setup("ctx04") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith.mkChild(Some("A"), ctx.spawnAdapter(ChildEvent), self, inert = true) {
|
||||
case (subj, child) ⇒
|
||||
|
|
@ -424,21 +431,25 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
t.ref should ===(child)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `05 must reset behavior upon Restart`(): Unit = sync(setup("ctx05", Some(Actor.supervise(_).onFailure(SupervisorStrategy.restart))) { (ctx, startWith) ⇒
|
||||
"reset behavior upon Restart" in {
|
||||
sync(setup("ctx05", Some(Actor.supervise(_).onFailure(SupervisorStrategy.restart))) { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
val ex = new Exception("KABOOM05")
|
||||
startWith
|
||||
.stimulate(_ ! BecomeInert(self), _ ⇒ BecameInert)
|
||||
.stimulate(_ ! Ping(self), _ ⇒ Pong2) { subj ⇒
|
||||
val log = muteExpectedException[Exception]("KABOOM05")
|
||||
muteExpectedException[Exception]("KABOOM05")
|
||||
subj ! Throw(ex)
|
||||
subj
|
||||
}
|
||||
.stimulate(_ ! Ping(self), _ ⇒ Pong1)
|
||||
})
|
||||
}
|
||||
|
||||
def `06 must not reset behavior upon Resume`(): Unit = sync(setup(
|
||||
"not reset behavior upon Resume" in {
|
||||
sync(setup(
|
||||
"ctx06",
|
||||
Some(b ⇒ Actor.supervise(b).onFailure(SupervisorStrategy.resume))) { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
|
|
@ -450,8 +461,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
subj ! Throw(ex)
|
||||
}.stimulate(_ ! Ping(self), _ ⇒ Pong2)
|
||||
})
|
||||
}
|
||||
|
||||
def `07 must stop upon Stop`(): Unit = sync(setup("ctx07", ignorePostStop = false) { (ctx, startWith) ⇒
|
||||
"stop upon Stop" in {
|
||||
sync(setup("ctx07", ignorePostStop = false) { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
val ex = new Exception("KABOOM07")
|
||||
startWith
|
||||
|
|
@ -463,8 +476,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msgs.toSet should ===(Set(Left(Terminated(subj)(null)), Right(GotSignal(PostStop))))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `08 must not stop non-child actor`(): Unit = sync(setup("ctx08") { (ctx, startWith) ⇒
|
||||
"not stop non-child actor" in {
|
||||
sync(setup("ctx08") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith.mkChild(Some("A"), ctx.spawnAdapter(ChildEvent), self) {
|
||||
case (subj, child) ⇒
|
||||
|
|
@ -475,8 +490,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msg should ===(NotKilled)
|
||||
}.stimulate(_ ! Ping(self), _ ⇒ Pong1)
|
||||
})
|
||||
}
|
||||
|
||||
def `10 must watch a child actor before its termination`(): Unit = sync(setup("ctx10") { (ctx, startWith) ⇒
|
||||
"watch a child actor before its termination" in {
|
||||
sync(setup("ctx10") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith.mkChild(None, ctx.spawnAdapter(ChildEvent), self) {
|
||||
case (subj, child) ⇒
|
||||
|
|
@ -489,8 +506,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msg should ===(GotSignal(Terminated(child)(null)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `11 must watch a child actor after its termination`(): Unit = sync(setup("ctx11") { (ctx, startWith) ⇒
|
||||
"watch a child actor after its termination" in {
|
||||
sync(setup("ctx11") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith.mkChild(None, ctx.spawnAdapter(ChildEvent), self).keep {
|
||||
case (subj, child) ⇒
|
||||
|
|
@ -505,8 +524,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msg should ===(GotSignal(Terminated(child)(null)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `12 must unwatch a child actor before its termination`(): Unit = sync(setup("ctx12") { (ctx, startWith) ⇒
|
||||
"unwatch a child actor before its termination" in {
|
||||
sync(setup("ctx12") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith.mkChild(None, ctx.spawnAdapter(ChildEvent), self).keep {
|
||||
case (subj, child) ⇒
|
||||
|
|
@ -525,8 +546,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
t should ===(Terminated(child)(null))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `13 must terminate upon not handling Terminated`(): Unit = sync(setup("ctx13", ignorePostStop = false) { (ctx, startWith) ⇒
|
||||
"terminate upon not handling Terminated" in {
|
||||
sync(setup("ctx13", ignorePostStop = false) { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith.mkChild(None, ctx.spawnAdapter(ChildEvent), self).keep {
|
||||
case (subj, child) ⇒
|
||||
|
|
@ -548,8 +571,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msg should ===(GotSignal(PostStop))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `20 must return the right context info`(): Unit = sync(setup("ctx20") { (ctx, startWith) ⇒
|
||||
"return the right context info" in {
|
||||
sync(setup("ctx20") { (ctx, startWith) ⇒
|
||||
startWith.keep(_ ! GetInfo(ctx.self))
|
||||
.expectMessage(expectTimeout) {
|
||||
case (msg: Info, subj) ⇒
|
||||
|
|
@ -559,8 +584,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
fail(s"$other was not an Info(...)")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `21 must return right info about children`(): Unit = sync(setup("ctx21") { (ctx, startWith) ⇒
|
||||
"return right info about children" in {
|
||||
sync(setup("ctx21") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith
|
||||
.mkChild(Some("B"), ctx.spawnAdapter(ChildEvent), self)
|
||||
|
|
@ -568,8 +595,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
.stimulate(_._1 ! GetChild("B", self), x ⇒ Child(Some(x._2)))
|
||||
.stimulate(_._1 ! GetChildren(self), x ⇒ Children(Set(x._2)))
|
||||
})
|
||||
}
|
||||
|
||||
def `30 must set small receive timeout`(): Unit = sync(setup("ctx30") { (ctx, startWith) ⇒
|
||||
"set small receive timeout" in {
|
||||
sync(setup("ctx30") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith
|
||||
.stimulate(_ ! SetTimeout(1.nano, self), _ ⇒ TimeoutSet)
|
||||
|
|
@ -577,23 +606,30 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msg should ===(GotReceiveTimeout)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `31 must set large receive timeout`(): Unit = sync(setup("ctx31") { (ctx, startWith) ⇒
|
||||
"set large receive timeout" in {
|
||||
sync(setup("ctx31") { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith
|
||||
.stimulate(_ ! SetTimeout(1.minute, self), _ ⇒ TimeoutSet)
|
||||
.stimulate(_ ⇒ ctx.schedule(1.second, self, Pong2), _ ⇒ Pong2)
|
||||
.stimulate(_ ! Ping(self), _ ⇒ Pong1)
|
||||
})
|
||||
|
||||
def `32 must schedule a message`(): Unit = sync(setup("ctx32") { (ctx, startWith) ⇒
|
||||
})
|
||||
}
|
||||
|
||||
"schedule a message" in {
|
||||
sync(setup("ctx32") { (ctx, startWith) ⇒
|
||||
startWith(_ ! Schedule(1.nano, ctx.self, Pong2, ctx.self))
|
||||
.expectMultipleMessages(expectTimeout, 2) { (msgs, _) ⇒
|
||||
msgs should ===(Scheduled :: Pong2 :: Nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `40 must create a working adapter`(): Unit = sync(setup("ctx40", ignorePostStop = false) { (ctx, startWith) ⇒
|
||||
"create a working adapter" in {
|
||||
sync(setup("ctx40", ignorePostStop = false) { (ctx, startWith) ⇒
|
||||
startWith.keep { subj ⇒
|
||||
subj ! GetAdapter(ctx.self)
|
||||
}.expectMessage(expectTimeout) { (msg, subj) ⇒
|
||||
|
|
@ -610,8 +646,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
msgs.toSet should ===(Set(Left(Terminated(adapter)(null)), Right(GotSignal(PostStop))))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `41 must create a named adapter`(): Unit = sync(setup("ctx41") { (ctx, startWith) ⇒
|
||||
"create a named adapter" in {
|
||||
sync(setup("ctx41") { (ctx, startWith) ⇒
|
||||
startWith.keep { subj ⇒
|
||||
subj ! GetAdapter(ctx.self, "named")
|
||||
}.expectMessage(expectTimeout) { (msg, subj) ⇒
|
||||
|
|
@ -619,7 +657,10 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
adapter.path.name should include("named")
|
||||
}
|
||||
})
|
||||
def `42 must not allow null messages`(): Unit = sync(setup("ctx42") { (ctx, startWith) ⇒
|
||||
}
|
||||
|
||||
"not allow null messages" in {
|
||||
sync(setup("ctx42") { (ctx, startWith) ⇒
|
||||
startWith.keep { subj ⇒
|
||||
intercept[InvalidMessageException] {
|
||||
subj ! null
|
||||
|
|
@ -627,40 +668,41 @@ class ActorContextSpec extends TypedSpec(ConfigFactory.parseString(
|
|||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Normal extends Tests {
|
||||
import ActorContextSpec._
|
||||
|
||||
class NormalActorContextSpec extends ActorContextSpec {
|
||||
override def suite = "normal"
|
||||
override def behavior(ctx: scaladsl.ActorContext[Event], ignorePostStop: Boolean): Behavior[Command] =
|
||||
subject(ctx.self, ignorePostStop)
|
||||
}
|
||||
object `An ActorContext (adapted)` extends Normal with AdaptedSystem
|
||||
|
||||
trait Widened extends Tests {
|
||||
class WidenedActorContextSpec extends ActorContextSpec {
|
||||
|
||||
import Actor._
|
||||
|
||||
override def suite = "widened"
|
||||
override def behavior(ctx: scaladsl.ActorContext[Event], ignorePostStop: Boolean): Behavior[Command] =
|
||||
subject(ctx.self, ignorePostStop).widen { case x ⇒ x }
|
||||
}
|
||||
object `An ActorContext with widened Behavior (adapted)` extends Widened with AdaptedSystem
|
||||
|
||||
trait Deferred extends Tests {
|
||||
class DeferredActorContextSpec extends ActorContextSpec {
|
||||
override def suite = "deferred"
|
||||
override def behavior(ctx: scaladsl.ActorContext[Event], ignorePostStop: Boolean): Behavior[Command] =
|
||||
Actor.deferred(_ ⇒ subject(ctx.self, ignorePostStop))
|
||||
}
|
||||
object `An ActorContext with deferred Behavior (adapted)` extends Deferred with AdaptedSystem
|
||||
|
||||
trait NestedDeferred extends Tests {
|
||||
override def suite = "deferred"
|
||||
class NestedDeferredActorContextSpec extends ActorContextSpec {
|
||||
override def suite = "nexted-deferred"
|
||||
override def behavior(ctx: scaladsl.ActorContext[Event], ignorePostStop: Boolean): Behavior[Command] =
|
||||
Actor.deferred(_ ⇒ Actor.deferred(_ ⇒ subject(ctx.self, ignorePostStop)))
|
||||
}
|
||||
object `An ActorContext with nested deferred Behavior (adapted)` extends NestedDeferred with AdaptedSystem
|
||||
|
||||
trait Tap extends Tests {
|
||||
class TapActorContextSpec extends ActorContextSpec {
|
||||
override def suite = "tap"
|
||||
override def behavior(ctx: scaladsl.ActorContext[Event], ignorePostStop: Boolean): Behavior[Command] =
|
||||
Actor.tap((_, _) ⇒ (), (_, _) ⇒ (), subject(ctx.self, ignorePostStop))
|
||||
}
|
||||
object `An ActorContext with Tap (old-adapted)` extends Tap with AdaptedSystem
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,20 +12,14 @@ import akka.actor.typed.scaladsl.Actor._
|
|||
import akka.actor.typed.scaladsl.AskPattern._
|
||||
|
||||
object AskSpec {
|
||||
|
||||
sealed trait Msg
|
||||
final case class Foo(s: String)(val replyTo: ActorRef[String]) extends Msg
|
||||
final case class Stop(replyTo: ActorRef[Unit]) extends Msg
|
||||
}
|
||||
|
||||
class AskSpec extends TypedSpec with ScalaFutures {
|
||||
|
||||
import AskSpec._
|
||||
|
||||
trait Common {
|
||||
|
||||
def system: ActorSystem[TypedSpec.Command]
|
||||
|
||||
implicit def executor: ExecutionContext =
|
||||
system.executionContext
|
||||
|
||||
|
|
@ -34,34 +28,30 @@ class AskSpec extends TypedSpec with ScalaFutures {
|
|||
foo.replyTo ! "foo"
|
||||
same
|
||||
case (_, Stop(r)) ⇒
|
||||
r ! (())
|
||||
r ! ()
|
||||
stopped
|
||||
}
|
||||
|
||||
def `must fail the future if the actor is already terminated`(): Unit = {
|
||||
"Ask pattern" must {
|
||||
"must fail the future if the actor is already terminated" in {
|
||||
val fut = for {
|
||||
ref ← system ? TypedSpec.Create(behavior, "test1")
|
||||
_ ← ref ? Stop
|
||||
answer ← ref.?(Foo("bar"))(Timeout(1.second), implicitly)
|
||||
} yield answer
|
||||
(fut.recover { case _: AskTimeoutException ⇒ "" }).futureValue should ===("")
|
||||
fut.recover { case _: AskTimeoutException ⇒ "" }.futureValue should ===("")
|
||||
}
|
||||
|
||||
def `must succeed when the actor is alive`(): Unit = {
|
||||
"must succeed when the actor is alive" in {
|
||||
val fut = for {
|
||||
ref ← system ? TypedSpec.Create(behavior, "test2")
|
||||
answer ← ref ? Foo("bar")
|
||||
} yield answer
|
||||
fut.futureValue should ===("foo")
|
||||
}
|
||||
}
|
||||
|
||||
object `Ask pattern (adapted)` extends Common with AdaptedSystem {
|
||||
|
||||
import AskSpec._
|
||||
|
||||
/** See issue #19947 (MatchError with adapted ActorRef) */
|
||||
def `must fail the future if the actor doesn't exist`(): Unit = {
|
||||
"must fail the future if the actor doesn't exist" in {
|
||||
val noSuchActor: ActorRef[Msg] = system match {
|
||||
case adaptedSys: akka.actor.typed.internal.adapter.ActorSystemAdapter[_] ⇒
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ import java.util.function.{ Function ⇒ F1 }
|
|||
import akka.Done
|
||||
import akka.typed.testkit.{ EffectfulActorContext, Inbox }
|
||||
|
||||
class BehaviorSpec extends TypedSpec {
|
||||
|
||||
object BehaviorSpec {
|
||||
sealed trait Command {
|
||||
def expectedResponse(ctx: ActorContext[Command]): Seq[Event] = Nil
|
||||
}
|
||||
|
|
@ -50,11 +49,19 @@ class BehaviorSpec extends TypedSpec {
|
|||
case object Pong extends Event
|
||||
case object Swapped extends Event
|
||||
|
||||
sealed trait State extends Event { def next: State }
|
||||
val StateA: State = new State { override def toString = "StateA"; override def next = StateB }
|
||||
val StateB: State = new State { override def toString = "StateB"; override def next = StateA }
|
||||
sealed trait State extends Event {
|
||||
def next: State
|
||||
}
|
||||
val StateA: State = new State {
|
||||
override def toString = "StateA"
|
||||
override def next = StateB
|
||||
}
|
||||
val StateB: State = new State {
|
||||
override def toString = "StateB"
|
||||
override def next = StateA
|
||||
}
|
||||
|
||||
trait Common {
|
||||
trait Common extends TypedSpec {
|
||||
type Aux >: Null <: AnyRef
|
||||
def system: ActorSystem[TypedSpec.Command]
|
||||
def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux)
|
||||
|
|
@ -130,131 +137,7 @@ class BehaviorSpec extends TypedSpec {
|
|||
}
|
||||
}
|
||||
|
||||
trait Lifecycle extends Common {
|
||||
def `must react to PreStart`(): Unit = {
|
||||
mkCtx(requirePreStart = true)
|
||||
}
|
||||
|
||||
def `must react to PostStop`(): Unit = {
|
||||
mkCtx().check(PostStop)
|
||||
}
|
||||
|
||||
def `must react to PostStop after a message`(): Unit = {
|
||||
mkCtx().check(GetSelf).check(PostStop)
|
||||
}
|
||||
|
||||
def `must react to PreRestart`(): Unit = {
|
||||
mkCtx().check(PreRestart)
|
||||
}
|
||||
|
||||
def `must react to PreRestart after a message`(): Unit = {
|
||||
mkCtx().check(GetSelf).check(PreRestart)
|
||||
}
|
||||
|
||||
def `must react to Terminated`(): Unit = {
|
||||
mkCtx().check(Terminated(Inbox("x").ref)(null))
|
||||
}
|
||||
|
||||
def `must react to Terminated after a message`(): Unit = {
|
||||
mkCtx().check(GetSelf).check(Terminated(Inbox("x").ref)(null))
|
||||
}
|
||||
|
||||
def `must react to a message after Terminated`(): Unit = {
|
||||
mkCtx().check(Terminated(Inbox("x").ref)(null)).check(GetSelf)
|
||||
}
|
||||
}
|
||||
|
||||
trait Messages extends Common {
|
||||
def `must react to two messages`(): Unit = {
|
||||
mkCtx().check(Ping).check(Ping)
|
||||
}
|
||||
|
||||
def `must react to a message after missing one`(): Unit = {
|
||||
mkCtx().check(Miss).check(Ping)
|
||||
}
|
||||
|
||||
def `must react to a message after ignoring one`(): Unit = {
|
||||
mkCtx().check(Ignore).check(Ping)
|
||||
}
|
||||
}
|
||||
|
||||
trait Unhandled extends Common {
|
||||
def `must return Unhandled`(): Unit = {
|
||||
val Setup(ctx, inbox, aux) = mkCtx()
|
||||
Behavior.interpretMessage(ctx.currentBehavior, ctx, Miss) should be(Behavior.UnhandledBehavior)
|
||||
inbox.receiveAll() should ===(Missed :: Nil)
|
||||
checkAux(Miss, aux)
|
||||
}
|
||||
}
|
||||
|
||||
trait Stoppable extends Common {
|
||||
def `must stop`(): Unit = {
|
||||
val Setup(ctx, inbox, aux) = mkCtx()
|
||||
ctx.run(Stop)
|
||||
ctx.currentBehavior should be(Behavior.StoppedBehavior)
|
||||
checkAux(Stop, aux)
|
||||
}
|
||||
}
|
||||
|
||||
trait Become extends Common with Unhandled {
|
||||
private implicit val inbox = Inbox[State]("state")
|
||||
|
||||
def `must be in state A`(): Unit = {
|
||||
mkCtx().check(GetState()(StateA))
|
||||
}
|
||||
|
||||
def `must switch to state B`(): Unit = {
|
||||
mkCtx().check(Swap).check(GetState()(StateB))
|
||||
}
|
||||
|
||||
def `must switch back to state A`(): Unit = {
|
||||
mkCtx().check(Swap).check(Swap).check(GetState()(StateA))
|
||||
}
|
||||
}
|
||||
|
||||
trait BecomeWithLifecycle extends Become with Lifecycle {
|
||||
def `must react to PostStop after swap`(): Unit = {
|
||||
mkCtx().check(Swap).check(PostStop)
|
||||
}
|
||||
|
||||
def `must react to PostStop after a message after swap`(): Unit = {
|
||||
mkCtx().check(Swap).check(GetSelf).check(PostStop)
|
||||
}
|
||||
|
||||
def `must react to PreRestart after swap`(): Unit = {
|
||||
mkCtx().check(Swap).check(PreRestart)
|
||||
}
|
||||
|
||||
def `must react to PreRestart after a message after swap`(): Unit = {
|
||||
mkCtx().check(Swap).check(GetSelf).check(PreRestart)
|
||||
}
|
||||
|
||||
def `must react to Terminated after swap`(): Unit = {
|
||||
mkCtx().check(Swap).check(Terminated(Inbox("x").ref)(null))
|
||||
}
|
||||
|
||||
def `must react to Terminated after a message after swap`(): Unit = {
|
||||
mkCtx().check(Swap).check(GetSelf).check(Terminated(Inbox("x").ref)(null))
|
||||
}
|
||||
|
||||
def `must react to a message after Terminated after swap`(): Unit = {
|
||||
mkCtx().check(Swap).check(Terminated(Inbox("x").ref)(null)).check(GetSelf)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This targets behavior wrappers to ensure that the wrapper does not
|
||||
* hold on to the changed behavior. Wrappers must be immutable.
|
||||
*/
|
||||
trait Reuse extends Common {
|
||||
def `must be reusable`(): Unit = {
|
||||
val i = init()
|
||||
i.mkCtx().check(GetState()(StateA)).check(Swap).check(GetState()(StateB))
|
||||
i.mkCtx().check(GetState()(StateA)).check(Swap).check(GetState()(StateB))
|
||||
}
|
||||
}
|
||||
|
||||
private def mkFull(monitor: ActorRef[Event], state: State = StateA): Behavior[Command] = {
|
||||
def mkFull(monitor: ActorRef[Event], state: State = StateA): Behavior[Command] = {
|
||||
SActor.immutable[Command] {
|
||||
case (ctx, GetSelf) ⇒
|
||||
monitor ! Self(ctx.self)
|
||||
|
|
@ -282,13 +165,185 @@ class BehaviorSpec extends TypedSpec {
|
|||
SActor.same
|
||||
}
|
||||
}
|
||||
/*
|
||||
* function converters for Java, to ease the pain on Scala 2.11
|
||||
*/
|
||||
def fs(f: (JActorContext[Command], Signal) ⇒ Behavior[Command]) =
|
||||
new F2[JActorContext[Command], Signal, Behavior[Command]] {
|
||||
override def apply(ctx: JActorContext[Command], sig: Signal) = f(ctx, sig)
|
||||
}
|
||||
def fc(f: (JActorContext[Command], Command) ⇒ Behavior[Command]) =
|
||||
new F2[JActorContext[Command], Command, Behavior[Command]] {
|
||||
override def apply(ctx: JActorContext[Command], command: Command) = f(ctx, command)
|
||||
}
|
||||
def ps(f: (JActorContext[Command], Signal) ⇒ Unit) =
|
||||
new P2[JActorContext[Command], Signal] {
|
||||
override def apply(ctx: JActorContext[Command], sig: Signal) = f(ctx, sig)
|
||||
}
|
||||
def pc(f: (JActorContext[Command], Command) ⇒ Unit) =
|
||||
new P2[JActorContext[Command], Command] {
|
||||
override def apply(ctx: JActorContext[Command], command: Command) = f(ctx, command)
|
||||
}
|
||||
def pf(f: PFBuilder[Command, Command] ⇒ PFBuilder[Command, Command]) =
|
||||
new F1[PFBuilder[Command, Command], PFBuilder[Command, Command]] {
|
||||
override def apply(in: PFBuilder[Command, Command]) = f(in)
|
||||
}
|
||||
def fi(f: Command ⇒ Command) =
|
||||
new FI.Apply[Command, Command] {
|
||||
override def apply(in: Command) = f(in)
|
||||
}
|
||||
def df(f: JActorContext[Command] ⇒ Behavior[Command]) =
|
||||
new F1e[JActorContext[Command], Behavior[Command]] {
|
||||
override def apply(in: JActorContext[Command]) = f(in)
|
||||
}
|
||||
|
||||
trait FullBehavior extends Messages with BecomeWithLifecycle with Stoppable {
|
||||
trait Lifecycle extends Common {
|
||||
"Lifecycle" must {
|
||||
"must react to PreStart" in {
|
||||
mkCtx(requirePreStart = true)
|
||||
}
|
||||
|
||||
"must react to PostStop" in {
|
||||
mkCtx().check(PostStop)
|
||||
}
|
||||
|
||||
"must react to PostStop after a message" in {
|
||||
mkCtx().check(GetSelf).check(PostStop)
|
||||
}
|
||||
|
||||
"must react to PreRestart" in {
|
||||
mkCtx().check(PreRestart)
|
||||
}
|
||||
|
||||
"must react to PreRestart after a message" in {
|
||||
mkCtx().check(GetSelf).check(PreRestart)
|
||||
}
|
||||
|
||||
"must react to Terminated" in {
|
||||
mkCtx().check(Terminated(Inbox("x").ref)(null))
|
||||
}
|
||||
|
||||
"must react to Terminated after a message" in {
|
||||
mkCtx().check(GetSelf).check(Terminated(Inbox("x").ref)(null))
|
||||
}
|
||||
|
||||
"must react to a message after Terminated" in {
|
||||
mkCtx().check(Terminated(Inbox("x").ref)(null)).check(GetSelf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Messages extends Common {
|
||||
"Messages" must {
|
||||
"react to two messages" in {
|
||||
mkCtx().check(Ping).check(Ping)
|
||||
}
|
||||
|
||||
"react to a message after missing one" in {
|
||||
mkCtx().check(Miss).check(Ping)
|
||||
}
|
||||
|
||||
"must react to a message after ignoring one" in {
|
||||
mkCtx().check(Ignore).check(Ping)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Unhandled extends Common {
|
||||
"Unahndled" must {
|
||||
"must return Unhandled" in {
|
||||
val Setup(ctx, inbox, aux) = mkCtx()
|
||||
Behavior.interpretMessage(ctx.currentBehavior, ctx, Miss) should be(Behavior.UnhandledBehavior)
|
||||
inbox.receiveAll() should ===(Missed :: Nil)
|
||||
checkAux(Miss, aux)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Stoppable extends Common {
|
||||
"Stopping" must {
|
||||
"must stop" in {
|
||||
val Setup(ctx, inbox, aux) = mkCtx()
|
||||
ctx.run(Stop)
|
||||
ctx.currentBehavior should be(Behavior.StoppedBehavior)
|
||||
checkAux(Stop, aux)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Become extends Common with Unhandled {
|
||||
private implicit val inbox = Inbox[State]("state")
|
||||
|
||||
"Becoming" must {
|
||||
"must be in state A" in {
|
||||
mkCtx().check(GetState()(StateA))
|
||||
}
|
||||
|
||||
"must switch to state B" in {
|
||||
mkCtx().check(Swap).check(GetState()(StateB))
|
||||
}
|
||||
|
||||
"must switch back to state A" in {
|
||||
mkCtx().check(Swap).check(Swap).check(GetState()(StateA))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait BecomeWithLifecycle extends Become with Lifecycle {
|
||||
"Become with lifecycle" must {
|
||||
"react to PostStop after swap" in {
|
||||
mkCtx().check(Swap).check(PostStop)
|
||||
}
|
||||
|
||||
"react to PostStop after a message after swap" in {
|
||||
mkCtx().check(Swap).check(GetSelf).check(PostStop)
|
||||
}
|
||||
|
||||
"react to PreRestart after swap" in {
|
||||
mkCtx().check(Swap).check(PreRestart)
|
||||
}
|
||||
|
||||
"react to PreRestart after a message after swap" in {
|
||||
mkCtx().check(Swap).check(GetSelf).check(PreRestart)
|
||||
}
|
||||
|
||||
"react to Terminated after swap" in {
|
||||
mkCtx().check(Swap).check(Terminated(Inbox("x").ref)(null))
|
||||
}
|
||||
|
||||
"react to Terminated after a message after swap" in {
|
||||
mkCtx().check(Swap).check(GetSelf).check(Terminated(Inbox("x").ref)(null))
|
||||
}
|
||||
|
||||
"react to a message after Terminated after swap" in {
|
||||
mkCtx().check(Swap).check(Terminated(Inbox("x").ref)(null)).check(GetSelf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This targets behavior wrappers to ensure that the wrapper does not
|
||||
* hold on to the changed behavior. Wrappers must be immutable.
|
||||
*/
|
||||
trait Reuse extends Common {
|
||||
"Reuse" must {
|
||||
"must be reusable" in {
|
||||
val i = init()
|
||||
i.mkCtx().check(GetState()(StateA)).check(Swap).check(GetState()(StateB))
|
||||
i.mkCtx().check(GetState()(StateA)).check(Swap).check(GetState()(StateB))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
import BehaviorSpec._
|
||||
|
||||
class FullBehaviorSpec extends TypedSpec with Messages with BecomeWithLifecycle with Stoppable {
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = mkFull(monitor) → null
|
||||
}
|
||||
object `A Full Behavior (adapted)` extends FullBehavior with AdaptedSystem
|
||||
|
||||
trait ImmutableBehavior extends Messages with BecomeWithLifecycle with Stoppable {
|
||||
class ImmutableBehaviorSpec extends TypedSpec with Messages with BecomeWithLifecycle with Stoppable {
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor, StateA) → null
|
||||
private def behv(monitor: ActorRef[Event], state: State): Behavior[Command] = {
|
||||
SActor.immutable[Command] {
|
||||
|
|
@ -319,10 +374,11 @@ class BehaviorSpec extends TypedSpec {
|
|||
}
|
||||
}
|
||||
}
|
||||
object `A immutable Behavior (adapted)` extends ImmutableBehavior with AdaptedSystem
|
||||
|
||||
trait ImmutableWithSignalScalaBehavior extends Messages with BecomeWithLifecycle with Stoppable {
|
||||
class ImmutableWithSignalScalaBehaviorSpec extends TypedSpec with Messages with BecomeWithLifecycle with Stoppable {
|
||||
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor) → null
|
||||
|
||||
def behv(monitor: ActorRef[Event], state: State = StateA): Behavior[Command] =
|
||||
SActor.immutable[Command] {
|
||||
(ctx, msg) ⇒
|
||||
|
|
@ -354,10 +410,11 @@ class BehaviorSpec extends TypedSpec {
|
|||
SActor.same
|
||||
}
|
||||
}
|
||||
object `A ImmutableWithSignal Behavior (scala,adapted)` extends ImmutableWithSignalScalaBehavior with AdaptedSystem
|
||||
|
||||
trait ImmutableScalaBehavior extends Messages with Become with Stoppable {
|
||||
class ImmutableScalaBehaviorSpec extends TypedSpec with Messages with Become with Stoppable {
|
||||
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor, StateA) → null
|
||||
|
||||
def behv(monitor: ActorRef[Event], state: State): Behavior[Command] =
|
||||
SActor.immutable[Command] { (ctx, msg) ⇒
|
||||
msg match {
|
||||
|
|
@ -384,10 +441,11 @@ class BehaviorSpec extends TypedSpec {
|
|||
}
|
||||
}
|
||||
}
|
||||
object `A immutable Behavior (scala,adapted)` extends ImmutableScalaBehavior with AdaptedSystem
|
||||
|
||||
trait MutableScalaBehavior extends Messages with Become with Stoppable {
|
||||
class MutableScalaBehaviorSpec extends TypedSpec with Messages with Become with Stoppable {
|
||||
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor) → null
|
||||
|
||||
def behv(monitor: ActorRef[Event]): Behavior[Command] =
|
||||
SActor.mutable[Command] { ctx ⇒
|
||||
new SActor.MutableBehavior[Command] {
|
||||
|
|
@ -421,9 +479,9 @@ class BehaviorSpec extends TypedSpec {
|
|||
}
|
||||
}
|
||||
}
|
||||
object `A mutable Behavior (scala,adapted)` extends MutableScalaBehavior with AdaptedSystem
|
||||
|
||||
trait WidenedScalaBehavior extends ImmutableWithSignalScalaBehavior with Reuse with Siphon {
|
||||
class WidenedScalaBehaviorSpec extends ImmutableWithSignalScalaBehaviorSpec with Reuse with Siphon {
|
||||
|
||||
import SActor.BehaviorDecorators
|
||||
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = {
|
||||
|
|
@ -431,9 +489,8 @@ class BehaviorSpec extends TypedSpec {
|
|||
super.behavior(monitor)._1.widen[Command] { case c ⇒ inbox.ref ! c; c } → inbox
|
||||
}
|
||||
}
|
||||
object `A widened Behavior (scala,adapted)` extends WidenedScalaBehavior with AdaptedSystem
|
||||
|
||||
trait DeferredScalaBehavior extends ImmutableWithSignalScalaBehavior {
|
||||
class DeferredScalaBehaviorSpec extends ImmutableWithSignalScalaBehaviorSpec {
|
||||
override type Aux = Inbox[Done]
|
||||
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = {
|
||||
|
|
@ -447,56 +504,21 @@ class BehaviorSpec extends TypedSpec {
|
|||
override def checkAux(signal: Signal, aux: Aux): Unit =
|
||||
aux.receiveAll() should ===(Done :: Nil)
|
||||
}
|
||||
object `A deferred Behavior (scala,adapted)` extends DeferredScalaBehavior with AdaptedSystem
|
||||
|
||||
trait TapScalaBehavior extends ImmutableWithSignalScalaBehavior with Reuse with SignalSiphon {
|
||||
class TapScalaBehaviorSpec extends ImmutableWithSignalScalaBehaviorSpec with Reuse with SignalSiphon {
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = {
|
||||
val inbox = Inbox[Either[Signal, Command]]("tapListener")
|
||||
(SActor.tap((_, msg) ⇒ inbox.ref ! Right(msg), (_, sig) ⇒ inbox.ref ! Left(sig), super.behavior(monitor)._1), inbox)
|
||||
}
|
||||
}
|
||||
object `A tap Behavior (scala,adapted)` extends TapScalaBehavior with AdaptedSystem
|
||||
|
||||
trait RestarterScalaBehavior extends ImmutableWithSignalScalaBehavior with Reuse {
|
||||
class RestarterScalaBehaviorSpec extends ImmutableWithSignalScalaBehaviorSpec with Reuse {
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = {
|
||||
SActor.supervise(super.behavior(monitor)._1).onFailure(SupervisorStrategy.restart) → null
|
||||
}
|
||||
}
|
||||
object `A restarter Behavior (scala,adapted)` extends RestarterScalaBehavior with AdaptedSystem
|
||||
|
||||
/*
|
||||
* function converters for Java, to ease the pain on Scala 2.11
|
||||
*/
|
||||
def fs(f: (JActorContext[Command], Signal) ⇒ Behavior[Command]) =
|
||||
new F2[JActorContext[Command], Signal, Behavior[Command]] {
|
||||
override def apply(ctx: JActorContext[Command], sig: Signal) = f(ctx, sig)
|
||||
}
|
||||
def fc(f: (JActorContext[Command], Command) ⇒ Behavior[Command]) =
|
||||
new F2[JActorContext[Command], Command, Behavior[Command]] {
|
||||
override def apply(ctx: JActorContext[Command], command: Command) = f(ctx, command)
|
||||
}
|
||||
def ps(f: (JActorContext[Command], Signal) ⇒ Unit) =
|
||||
new P2[JActorContext[Command], Signal] {
|
||||
override def apply(ctx: JActorContext[Command], sig: Signal) = f(ctx, sig)
|
||||
}
|
||||
def pc(f: (JActorContext[Command], Command) ⇒ Unit) =
|
||||
new P2[JActorContext[Command], Command] {
|
||||
override def apply(ctx: JActorContext[Command], command: Command) = f(ctx, command)
|
||||
}
|
||||
def pf(f: PFBuilder[Command, Command] ⇒ PFBuilder[Command, Command]) =
|
||||
new F1[PFBuilder[Command, Command], PFBuilder[Command, Command]] {
|
||||
override def apply(in: PFBuilder[Command, Command]) = f(in)
|
||||
}
|
||||
def fi(f: Command ⇒ Command) =
|
||||
new FI.Apply[Command, Command] {
|
||||
override def apply(in: Command) = f(in)
|
||||
}
|
||||
def df(f: JActorContext[Command] ⇒ Behavior[Command]) =
|
||||
new F1e[JActorContext[Command], Behavior[Command]] {
|
||||
override def apply(in: JActorContext[Command]) = f(in)
|
||||
}
|
||||
|
||||
trait ImmutableWithSignalJavaBehavior extends Messages with BecomeWithLifecycle with Stoppable {
|
||||
class ImmutableWithSignalJavaBehaviorSpec extends TypedSpec with Messages with BecomeWithLifecycle with Stoppable {
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor) → null
|
||||
def behv(monitor: ActorRef[Event], state: State = StateA): Behavior[Command] =
|
||||
JActor.immutable(
|
||||
|
|
@ -527,9 +549,8 @@ class BehaviorSpec extends TypedSpec {
|
|||
SActor.same
|
||||
}))
|
||||
}
|
||||
object `A ImmutableWithSignal Behavior (java,adapted)` extends ImmutableWithSignalJavaBehavior with AdaptedSystem
|
||||
|
||||
trait ImmutableJavaBehavior extends Messages with Become with Stoppable {
|
||||
class ImmutableJavaBehaviorSpec extends TypedSpec with Messages with Become with Stoppable {
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = behv(monitor, StateA) → null
|
||||
def behv(monitor: ActorRef[Event], state: State): Behavior[Command] =
|
||||
JActor.immutable {
|
||||
|
|
@ -558,17 +579,18 @@ class BehaviorSpec extends TypedSpec {
|
|||
})
|
||||
}
|
||||
}
|
||||
object `A immutable Behavior (java,adapted)` extends ImmutableJavaBehavior with AdaptedSystem
|
||||
|
||||
trait WidenedJavaBehavior extends ImmutableWithSignalJavaBehavior with Reuse with Siphon {
|
||||
class WidenedJavaBehaviorSpec extends ImmutableWithSignalJavaBehaviorSpec with Reuse with Siphon {
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = {
|
||||
val inbox = Inbox[Command]("widenedListener")
|
||||
JActor.widened(super.behavior(monitor)._1, pf(_.`match`(classOf[Command], fi(x ⇒ { inbox.ref ! x; x })))) → inbox
|
||||
JActor.widened(super.behavior(monitor)._1, pf(_.`match`(classOf[Command], fi(x ⇒ {
|
||||
inbox.ref ! x
|
||||
x
|
||||
})))) → inbox
|
||||
}
|
||||
}
|
||||
object `A widened Behavior (java,adapted)` extends WidenedJavaBehavior with AdaptedSystem
|
||||
|
||||
trait DeferredJavaBehavior extends ImmutableWithSignalJavaBehavior {
|
||||
class DeferredJavaBehaviorSpec extends ImmutableWithSignalJavaBehaviorSpec {
|
||||
override type Aux = Inbox[Done]
|
||||
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = {
|
||||
|
|
@ -582,9 +604,8 @@ class BehaviorSpec extends TypedSpec {
|
|||
override def checkAux(signal: Signal, aux: Aux): Unit =
|
||||
aux.receiveAll() should ===(Done :: Nil)
|
||||
}
|
||||
object `A deferred Behavior (java,adapted)` extends DeferredJavaBehavior with AdaptedSystem
|
||||
|
||||
trait TapJavaBehavior extends ImmutableWithSignalJavaBehavior with Reuse with SignalSiphon {
|
||||
class TapJavaBehaviorSpec extends ImmutableWithSignalJavaBehaviorSpec with Reuse with SignalSiphon {
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = {
|
||||
val inbox = Inbox[Either[Signal, Command]]("tapListener")
|
||||
(JActor.tap(
|
||||
|
|
@ -593,14 +614,10 @@ class BehaviorSpec extends TypedSpec {
|
|||
super.behavior(monitor)._1), inbox)
|
||||
}
|
||||
}
|
||||
object `A tap Behavior (java,adapted)` extends TapJavaBehavior with AdaptedSystem
|
||||
|
||||
trait RestarterJavaBehavior extends ImmutableWithSignalJavaBehavior with Reuse {
|
||||
class RestarterJavaBehaviorSpec extends ImmutableWithSignalJavaBehaviorSpec with Reuse {
|
||||
override def behavior(monitor: ActorRef[Event]): (Behavior[Command], Aux) = {
|
||||
JActor.supervise(super.behavior(monitor)._1)
|
||||
.onFailure(classOf[Exception], SupervisorStrategy.restart) → null
|
||||
}
|
||||
}
|
||||
object `A restarter Behavior (java,adapted)` extends RestarterJavaBehavior with AdaptedSystem
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@ import akka.actor.typed.scaladsl.AskPattern._
|
|||
import akka.typed.testkit.{ EffectfulActorContext, Inbox, TestKitSettings }
|
||||
import akka.typed.testkit.scaladsl._
|
||||
|
||||
@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner])
|
||||
class DeferredSpec extends TypedSpec {
|
||||
|
||||
object DeferredSpec {
|
||||
sealed trait Command
|
||||
case object Ping extends Command
|
||||
|
||||
|
|
@ -28,44 +26,15 @@ class DeferredSpec extends TypedSpec {
|
|||
monitor ! Pong
|
||||
Actor.same
|
||||
})
|
||||
|
||||
trait StubbedTests {
|
||||
def system: ActorSystem[TypedSpec.Command]
|
||||
|
||||
def mkCtx(behv: Behavior[Command]): EffectfulActorContext[Command] =
|
||||
new EffectfulActorContext("ctx", behv, 1000, system)
|
||||
|
||||
def `must create underlying deferred behavior immediately`(): Unit = {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv = Actor.deferred[Command] { _ ⇒
|
||||
inbox.ref ! Started
|
||||
target(inbox.ref)
|
||||
}
|
||||
val ctx = mkCtx(behv)
|
||||
// it's supposed to be created immediately (not waiting for first message)
|
||||
inbox.receiveMsg() should ===(Started)
|
||||
}
|
||||
|
||||
def `must stop when exception from factory`(): Unit = {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val exc = new RuntimeException("simulated exc from factory") with NoStackTrace
|
||||
val behv = Actor.deferred[Command] { _ ⇒
|
||||
inbox.ref ! Started
|
||||
throw exc
|
||||
}
|
||||
intercept[RuntimeException] {
|
||||
mkCtx(behv)
|
||||
} should ===(exc)
|
||||
inbox.receiveMsg() should ===(Started)
|
||||
}
|
||||
class DeferredSpec extends TypedSpec with StartSupport {
|
||||
|
||||
}
|
||||
|
||||
trait RealTests extends StartSupport {
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
import DeferredSpec._
|
||||
implicit val testSettings = TestKitSettings(system)
|
||||
|
||||
def `must create underlying`(): Unit = {
|
||||
"Deferred behaviour" must {
|
||||
"must create underlying" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.deferred[Command] { _ ⇒
|
||||
probe.ref ! Started
|
||||
|
|
@ -77,7 +46,7 @@ class DeferredSpec extends TypedSpec {
|
|||
probe.expectMsg(Started)
|
||||
}
|
||||
|
||||
def `must stop when exception from factory`(): Unit = {
|
||||
"must stop when exception from factory" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.deferred[Command] { ctx ⇒
|
||||
val child = ctx.spawnAnonymous(Actor.deferred[Command] { _ ⇒
|
||||
|
|
@ -96,7 +65,7 @@ class DeferredSpec extends TypedSpec {
|
|||
probe.expectMsg(Pong)
|
||||
}
|
||||
|
||||
def `must stop when deferred result it Stopped`(): Unit = {
|
||||
"must stop when deferred result it Stopped" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.deferred[Command] { ctx ⇒
|
||||
val child = ctx.spawnAnonymous(Actor.deferred[Command](_ ⇒ Actor.stopped))
|
||||
|
|
@ -111,7 +80,7 @@ class DeferredSpec extends TypedSpec {
|
|||
probe.expectMsg(Pong)
|
||||
}
|
||||
|
||||
def `must create underlying when nested`(): Unit = {
|
||||
"must create underlying when nested" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.deferred[Command] { _ ⇒
|
||||
Actor.deferred[Command] { _ ⇒
|
||||
|
|
@ -123,7 +92,7 @@ class DeferredSpec extends TypedSpec {
|
|||
probe.expectMsg(Started)
|
||||
}
|
||||
|
||||
def `must undefer underlying when wrapped by widen`(): Unit = {
|
||||
"must undefer underlying when wrapped by widen" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.deferred[Command] { _ ⇒
|
||||
probe.ref ! Started
|
||||
|
|
@ -139,7 +108,7 @@ class DeferredSpec extends TypedSpec {
|
|||
probe.expectMsg(Pong)
|
||||
}
|
||||
|
||||
def `must undefer underlying when wrapped by monitor`(): Unit = {
|
||||
"must undefer underlying when wrapped by monitor" in {
|
||||
// monitor is implemented with tap, so this is testing both
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val monitorProbe = TestProbe[Command]("monitor")
|
||||
|
|
@ -155,10 +124,40 @@ class DeferredSpec extends TypedSpec {
|
|||
monitorProbe.expectMsg(Ping)
|
||||
probe.expectMsg(Pong)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object `A DeferredBehavior (stubbed, adapted)` extends StubbedTests with AdaptedSystem
|
||||
object `A DeferredBehavior (real, adapted)` extends RealTests with AdaptedSystem
|
||||
class DeferredStubbedSpec extends TypedSpec {
|
||||
|
||||
import DeferredSpec._
|
||||
|
||||
def mkCtx(behv: Behavior[Command]): EffectfulActorContext[Command] =
|
||||
new EffectfulActorContext("ctx", behv, 1000, system)
|
||||
|
||||
"must create underlying deferred behavior immediately" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv = Actor.deferred[Command] { _ ⇒
|
||||
inbox.ref ! Started
|
||||
target(inbox.ref)
|
||||
}
|
||||
val ctx = mkCtx(behv)
|
||||
// it's supposed to be created immediately (not waiting for first message)
|
||||
inbox.receiveMsg() should ===(Started)
|
||||
}
|
||||
|
||||
"must stop when exception from factory" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val exc = new RuntimeException("simulated exc from factory") with NoStackTrace
|
||||
val behv = Actor.deferred[Command] { _ ⇒
|
||||
inbox.ref ! Started
|
||||
throw exc
|
||||
}
|
||||
intercept[RuntimeException] {
|
||||
mkCtx(behv)
|
||||
} should ===(exc)
|
||||
inbox.receiveMsg() should ===(Started)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,8 @@ object InstanceCountingExtension extends ExtensionId[DummyExtension1] {
|
|||
|
||||
class ExtensionsSpec extends TypedSpecSetup {
|
||||
|
||||
object `The extensions subsystem` {
|
||||
|
||||
def `01 should return the same instance for the same id`(): Unit =
|
||||
"The extensions subsystem" must {
|
||||
"return the same instance for the same id" in
|
||||
withEmptyActorSystem("ExtensionsSpec01") { system ⇒
|
||||
val instance1 = system.registerExtension(DummyExtension1)
|
||||
val instance2 = system.registerExtension(DummyExtension1)
|
||||
|
|
@ -61,7 +60,7 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
instance4 should be theSameInstanceAs instance3
|
||||
}
|
||||
|
||||
def `02 should return the same instance for the same id concurrently`(): Unit =
|
||||
"return the same instance for the same id concurrently" in
|
||||
withEmptyActorSystem("ExtensionsSpec02") { system ⇒
|
||||
// not exactly water tight but better than nothing
|
||||
import system.executionContext
|
||||
|
|
@ -79,7 +78,7 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
}
|
||||
}
|
||||
|
||||
def `03 should load extensions from the configuration`(): Unit =
|
||||
"load extensions from the configuration" in
|
||||
withEmptyActorSystem("ExtensionsSpec03", Some(ConfigFactory.parseString(
|
||||
"""
|
||||
akka.typed.extensions = ["akka.actor.typed.DummyExtension1$", "akka.actor.typed.SlowExtension$"]
|
||||
|
|
@ -92,7 +91,7 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
system.extension(SlowExtension) shouldBe a[SlowExtension]
|
||||
}
|
||||
|
||||
def `04 handle extensions that fail to initialize`(): Unit = {
|
||||
"handle extensions that fail to initialize" in {
|
||||
def create(): Unit = {
|
||||
ActorSystem[Any](Behavior.EmptyBehavior, "ExtensionsSpec04", config = Some(ConfigFactory.parseString(
|
||||
"""
|
||||
|
|
@ -109,7 +108,7 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
}
|
||||
}
|
||||
|
||||
def `05 support multiple instances of the same type of extension (with different ids)`(): Unit =
|
||||
"support multiple instances of the same type of extension (with different ids)" in
|
||||
withEmptyActorSystem("ExtensionsSpec06") { system ⇒
|
||||
val id1 = new MultiExtensionId(1)
|
||||
val id2 = new MultiExtensionId(2)
|
||||
|
|
@ -119,7 +118,7 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
system.registerExtension(id1).n should ===(1)
|
||||
}
|
||||
|
||||
def `06 allow for auto-loading of library-extensions`(): Unit =
|
||||
"allow for auto-loading of library-extensions" in
|
||||
withEmptyActorSystem("ExtensionsSpec06") { system ⇒
|
||||
val listedExtensions = system.settings.config.getStringList("akka.typed.library-extensions")
|
||||
listedExtensions.size should be > 0
|
||||
|
|
@ -127,7 +126,7 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
InstanceCountingExtension.createCount.get() should be > 0
|
||||
}
|
||||
|
||||
def `07 fail the system if a library-extension cannot be loaded`(): Unit =
|
||||
"fail the system if a library-extension cannot be loaded" in
|
||||
intercept[RuntimeException] {
|
||||
withEmptyActorSystem(
|
||||
"ExtensionsSpec07",
|
||||
|
|
@ -135,7 +134,7 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
) { _ ⇒ () }
|
||||
}
|
||||
|
||||
def `08 fail the system if a library-extension cannot be loaded`(): Unit =
|
||||
"fail the system if a library-extension is missing" in
|
||||
intercept[RuntimeException] {
|
||||
withEmptyActorSystem(
|
||||
"ExtensionsSpec08",
|
||||
|
|
@ -143,7 +142,7 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
) { _ ⇒ () }
|
||||
}
|
||||
|
||||
def `09 load an extension implemented in Java`(): Unit =
|
||||
"load an extension implemented in Java" in
|
||||
withEmptyActorSystem("ExtensionsSpec09") { system ⇒
|
||||
// no way to make apply work cleanly with extensions implemented in Java
|
||||
val instance1 = ExtensionsTest.MyExtension.get(system)
|
||||
|
|
@ -152,7 +151,7 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
instance1 should be theSameInstanceAs instance2
|
||||
}
|
||||
|
||||
def `10 not create an extension multiple times when using the ActorSystemAdapter`(): Unit = {
|
||||
"not create an extension multiple times when using the ActorSystemAdapter" in {
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
val untypedSystem = akka.actor.ActorSystem()
|
||||
try {
|
||||
|
|
@ -168,11 +167,10 @@ class ExtensionsSpec extends TypedSpecSetup {
|
|||
untypedSystem.terminate().futureValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def withEmptyActorSystem[T](name: String, config: Option[Config] = None)(f: ActorSystem[_] ⇒ T): T = {
|
||||
val system = ActorSystem[Any](Behavior.EmptyBehavior, name, config = config)
|
||||
try f(system) finally system.terminate().futureValue
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,15 +11,14 @@ import akka.util.Timeout
|
|||
|
||||
@RunWith(classOf[org.scalatest.junit.JUnitRunner])
|
||||
class PerformanceSpec extends TypedSpec(
|
||||
ConfigFactory.parseString("""
|
||||
ConfigFactory.parseString(
|
||||
"""
|
||||
# increase this if you do real benchmarking
|
||||
akka.actor.typed.PerformanceSpec.iterations=100000
|
||||
""")) {
|
||||
|
||||
override def setTimeout = Timeout(20.seconds)
|
||||
|
||||
object `A immutable behavior` {
|
||||
|
||||
case class Ping(x: Int, pong: ActorRef[Pong], report: ActorRef[Pong])
|
||||
case class Pong(x: Int, ping: ActorRef[Ping], report: ActorRef[Pong])
|
||||
|
||||
|
|
@ -64,20 +63,42 @@ class PerformanceSpec extends TypedSpec(
|
|||
|
||||
val iterations = system.settings.config.getInt("akka.actor.typed.PerformanceSpec.iterations")
|
||||
|
||||
trait CommonTests {
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
|
||||
def `01 when warming up`(): Unit = sync(runTest("01")(behavior(1, 1, iterations, "dispatcher-1")))
|
||||
def `02 when using a single message on a single thread`(): Unit = sync(runTest("02")(behavior(1, 1, iterations, "dispatcher-1")))
|
||||
def `03 when using a 10 messages on a single thread`(): Unit = sync(runTest("03")(behavior(1, 10, iterations, "dispatcher-1")))
|
||||
def `04 when using a single message on two threads`(): Unit = sync(runTest("04")(behavior(1, 1, iterations, "dispatcher-2")))
|
||||
def `05 when using a 10 messages on two threads`(): Unit = sync(runTest("05")(behavior(1, 10, iterations, "dispatcher-2")))
|
||||
def `06 when using 4 pairs with a single message`(): Unit = sync(runTest("06")(behavior(4, 1, iterations, "dispatcher-8")))
|
||||
def `07 when using 4 pairs with 10 messages`(): Unit = sync(runTest("07")(behavior(4, 10, iterations, "dispatcher-8")))
|
||||
def `08 when using 8 pairs with a single message`(): Unit = sync(runTest("08")(behavior(8, 1, iterations, "dispatcher-8")))
|
||||
def `09 when using 8 pairs with 10 messages`(): Unit = sync(runTest("09")(behavior(8, 10, iterations, "dispatcher-8")))
|
||||
"An immutable behaviour" must {
|
||||
"when warming up" in {
|
||||
sync(runTest("01")(behavior(1, 1, iterations, "dispatcher-1")))
|
||||
}
|
||||
|
||||
"when using a single message on a single thread" in {
|
||||
sync(runTest("02")(behavior(1, 1, iterations, "dispatcher-1")))
|
||||
}
|
||||
|
||||
"when using a 10 messages on a single thread" in {
|
||||
sync(runTest("03")(behavior(1, 10, iterations, "dispatcher-1")))
|
||||
}
|
||||
|
||||
"when using a single message on two threads" in {
|
||||
sync(runTest("04")(behavior(1, 1, iterations, "dispatcher-2")))
|
||||
}
|
||||
|
||||
"when using a 10 messages on two threads" in {
|
||||
sync(runTest("05")(behavior(1, 10, iterations, "dispatcher-2")))
|
||||
}
|
||||
|
||||
"when using 4 pairs with a single message" in {
|
||||
sync(runTest("06")(behavior(4, 1, iterations, "dispatcher-8")))
|
||||
}
|
||||
|
||||
"when using 4 pairs with 10 messages" in {
|
||||
sync(runTest("07")(behavior(4, 10, iterations, "dispatcher-8")))
|
||||
}
|
||||
|
||||
"when using 8 pairs with a single message" in {
|
||||
sync(runTest("08")(behavior(8, 1, iterations, "dispatcher-8")))
|
||||
}
|
||||
|
||||
"when using 8 pairs with 10 messages" in {
|
||||
sync(runTest("09")(behavior(8, 10, iterations, "dispatcher-8")))
|
||||
}
|
||||
|
||||
object `must be fast with ActorSystemAdapter` extends CommonTests with AdaptedSystem
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ class PropsSpec extends TypedSpecSetup {
|
|||
|
||||
val dispatcherFirst = DispatcherDefault(DispatcherFromConfig("pool"))
|
||||
|
||||
object `A Props` {
|
||||
"A Props" must {
|
||||
|
||||
def `must get first dispatcher`(): Unit = {
|
||||
"get first dispatcher" in {
|
||||
dispatcherFirst.firstOrElse[DispatcherSelector](null) should ===(dispatcherFirst)
|
||||
}
|
||||
|
||||
def `must yield all configs of some type`(): Unit = {
|
||||
"yield all configs of some type" in {
|
||||
dispatcherFirst.allOf[DispatcherSelector] should ===(DispatcherSelector.default() :: DispatcherSelector.fromConfig("pool") :: Nil)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ import akka.typed.testkit.{ EffectfulActorContext, Inbox, TestKitSettings }
|
|||
import scala.util.control.NoStackTrace
|
||||
import akka.typed.testkit.scaladsl._
|
||||
|
||||
@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner])
|
||||
class RestarterSpec extends TypedSpec {
|
||||
object RestarterSpec {
|
||||
|
||||
sealed trait Command
|
||||
case object Ping extends Command
|
||||
|
|
@ -63,14 +62,17 @@ class RestarterSpec extends TypedSpec {
|
|||
same
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait StubbedTests {
|
||||
def system: ActorSystem[TypedSpec.Command]
|
||||
class RestarterSpec extends TypedSpec {
|
||||
|
||||
import RestarterSpec._
|
||||
|
||||
def mkCtx(behv: Behavior[Command]): EffectfulActorContext[Command] =
|
||||
new EffectfulActorContext("ctx", behv, 1000, system)
|
||||
|
||||
def `must receive message`(): Unit = {
|
||||
"A restarter" must {
|
||||
"receive message" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv = supervise(target(inbox.ref)).onFailure[Throwable](SupervisorStrategy.restart)
|
||||
val ctx = mkCtx(behv)
|
||||
|
|
@ -78,7 +80,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(Pong)
|
||||
}
|
||||
|
||||
def `must stop when no supervise`(): Unit = {
|
||||
"stop when no supervise" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv = target(inbox.ref)
|
||||
val ctx = mkCtx(behv)
|
||||
|
|
@ -88,7 +90,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(GotSignal(PostStop))
|
||||
}
|
||||
|
||||
def `must stop when unhandled exception`(): Unit = {
|
||||
"stop when unhandled exception" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv = supervise(target(inbox.ref)).onFailure[Exc1](SupervisorStrategy.restart)
|
||||
val ctx = mkCtx(behv)
|
||||
|
|
@ -98,7 +100,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(GotSignal(PostStop))
|
||||
}
|
||||
|
||||
def `must restart when handled exception`(): Unit = {
|
||||
"restart when handled exception" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv = supervise(target(inbox.ref)).onFailure[Exc1](SupervisorStrategy.restart)
|
||||
val ctx = mkCtx(behv)
|
||||
|
|
@ -112,7 +114,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(State(0, Map.empty))
|
||||
}
|
||||
|
||||
def `must resume when handled exception`(): Unit = {
|
||||
"resume when handled exception" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv = supervise(target(inbox.ref)).onFailure[Exc1](SupervisorStrategy.resume)
|
||||
val ctx = mkCtx(behv)
|
||||
|
|
@ -125,7 +127,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(State(1, Map.empty))
|
||||
}
|
||||
|
||||
def `must support nesting to handle different exceptions`(): Unit = {
|
||||
"support nesting to handle different exceptions" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv =
|
||||
supervise(
|
||||
|
|
@ -156,7 +158,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(GotSignal(PostStop))
|
||||
}
|
||||
|
||||
def `must not catch fatal error`(): Unit = {
|
||||
"not catch fatal error" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv = supervise(target(inbox.ref)).onFailure[Throwable](SupervisorStrategy.restart)
|
||||
val ctx = mkCtx(behv)
|
||||
|
|
@ -166,7 +168,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveAll() should ===(Nil)
|
||||
}
|
||||
|
||||
def `must stop after restart retries limit`(): Unit = {
|
||||
"stop after restart retries limit" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val strategy = SupervisorStrategy.restartWithLimit(maxNrOfRetries = 2, withinTimeRange = 1.minute)
|
||||
val behv = supervise(target(inbox.ref)).onFailure[Exc1](strategy)
|
||||
|
|
@ -181,7 +183,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(GotSignal(PostStop))
|
||||
}
|
||||
|
||||
def `must reset retry limit after withinTimeRange`(): Unit = {
|
||||
"reset retry limit after withinTimeRange" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val withinTimeRange = 2.seconds
|
||||
val strategy = SupervisorStrategy.restartWithLimit(maxNrOfRetries = 2, withinTimeRange)
|
||||
|
|
@ -203,7 +205,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(GotSignal(PostStop))
|
||||
}
|
||||
|
||||
def `must stop at first exception when restart retries limit is 0`(): Unit = {
|
||||
"stop at first exception when restart retries limit is 0" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val strategy = SupervisorStrategy.restartWithLimit(maxNrOfRetries = 0, withinTimeRange = 1.minute)
|
||||
val behv = supervise(target(inbox.ref)).onFailure[Exc1](strategy)
|
||||
|
|
@ -214,7 +216,7 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(GotSignal(PostStop))
|
||||
}
|
||||
|
||||
def `must create underlying deferred behavior immediately`(): Unit = {
|
||||
"create underlying deferred behavior immediately" in {
|
||||
val inbox = Inbox[Event]("evt")
|
||||
val behv = supervise(deferred[Command] { _ ⇒
|
||||
inbox.ref ! Started
|
||||
|
|
@ -225,13 +227,16 @@ class RestarterSpec extends TypedSpec {
|
|||
inbox.receiveMsg() should ===(Started)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RestarterStubbedSpec extends TypedSpec with StartSupport {
|
||||
|
||||
import RestarterSpec._
|
||||
|
||||
trait RealTests extends StartSupport {
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
implicit val testSettings = TestKitSettings(system)
|
||||
|
||||
def `must receive message`(): Unit = {
|
||||
"A restart (subbed)" must {
|
||||
"receive message" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = supervise(target(probe.ref)).onFailure[Throwable](SupervisorStrategy.restart)
|
||||
val ref = start(behv)
|
||||
|
|
@ -239,7 +244,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsg(Pong)
|
||||
}
|
||||
|
||||
def `must stop when no supervise`(): Unit = {
|
||||
"stop when no supervise" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = target(probe.ref)
|
||||
val ref = start(behv)
|
||||
|
|
@ -248,7 +253,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsg(GotSignal(PostStop))
|
||||
}
|
||||
|
||||
def `must stop when unhandled exception`(): Unit = {
|
||||
"stop when unhandled exception" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = supervise(target(probe.ref)).onFailure[Exc1](SupervisorStrategy.restart)
|
||||
val ref = start(behv)
|
||||
|
|
@ -256,7 +261,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsg(GotSignal(PostStop))
|
||||
}
|
||||
|
||||
def `must restart when handled exception`(): Unit = {
|
||||
"restart when handled exception" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = supervise(target(probe.ref)).onFailure[Exc1](SupervisorStrategy.restart)
|
||||
val ref = start(behv)
|
||||
|
|
@ -270,7 +275,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsg(State(0, Map.empty))
|
||||
}
|
||||
|
||||
def `must NOT stop children when restarting`(): Unit = {
|
||||
"NOT stop children when restarting" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = supervise(target(probe.ref)).onFailure[Exc1](SupervisorStrategy.restart)
|
||||
val ref = start(behv)
|
||||
|
|
@ -289,7 +294,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsgType[State].children.keySet should contain(childName)
|
||||
}
|
||||
|
||||
def `must resume when handled exception`(): Unit = {
|
||||
"resume when handled exception" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = supervise(target(probe.ref)).onFailure[Exc1](SupervisorStrategy.resume)
|
||||
val ref = start(behv)
|
||||
|
|
@ -302,7 +307,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsg(State(1, Map.empty))
|
||||
}
|
||||
|
||||
def `must support nesting to handle different exceptions`(): Unit = {
|
||||
"support nesting to handle different exceptions" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = supervise(
|
||||
supervise(target(probe.ref)).onFailure[Exc2](SupervisorStrategy.resume)
|
||||
|
|
@ -328,7 +333,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsg(GotSignal(PostStop))
|
||||
}
|
||||
|
||||
def `must restart after exponential backoff`(): Unit = {
|
||||
"restart after exponential backoff" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val startedProbe = TestProbe[Event]("started")
|
||||
val minBackoff = 1.seconds
|
||||
|
|
@ -365,7 +370,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsg(State(0, Map.empty))
|
||||
}
|
||||
|
||||
def `must reset exponential backoff count after reset timeout`(): Unit = {
|
||||
"reset exponential backoff count after reset timeout" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val minBackoff = 1.seconds
|
||||
val strategy = SupervisorStrategy.restartWithBackoff(minBackoff, 10.seconds, 0.0)
|
||||
|
|
@ -395,7 +400,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsg(State(0, Map.empty))
|
||||
}
|
||||
|
||||
def `must create underlying deferred behavior immediately`(): Unit = {
|
||||
"create underlying deferred behavior immediately" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = supervise(deferred[Command] { _ ⇒
|
||||
probe.ref ! Started
|
||||
|
|
@ -407,7 +412,7 @@ class RestarterSpec extends TypedSpec {
|
|||
probe.expectMsg(Started)
|
||||
}
|
||||
|
||||
def `must stop when exception from MutableBehavior constructor`(): Unit = {
|
||||
"stop when exception from MutableBehavior constructor" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = supervise(mutable[Command](_ ⇒ new FailingConstructor(probe.ref))).onFailure[Exception](SupervisorStrategy.restart)
|
||||
val ref = start(behv)
|
||||
|
|
@ -415,10 +420,5 @@ class RestarterSpec extends TypedSpec {
|
|||
ref ! Ping
|
||||
probe.expectNoMsg(100.millis)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object `A restarter (stubbed, adapted)` extends StubbedTests with AdaptedSystem
|
||||
object `A restarter (real, adapted)` extends RealTests with AdaptedSystem
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ import akka.actor.typed.scaladsl.TimerScheduler
|
|||
import akka.typed.testkit.TestKitSettings
|
||||
import akka.typed.testkit.scaladsl._
|
||||
|
||||
@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner])
|
||||
class TimerSpec extends TypedSpec("""
|
||||
class TimerSpec extends TypedSpec(
|
||||
"""
|
||||
#akka.loglevel = DEBUG
|
||||
""") {
|
||||
""") with StartSupport {
|
||||
|
||||
sealed trait Command
|
||||
case class Tick(n: Int) extends Command
|
||||
|
|
@ -36,8 +36,6 @@ class TimerSpec extends TypedSpec("""
|
|||
|
||||
class Exc extends RuntimeException("simulated exc") with NoStackTrace
|
||||
|
||||
trait RealTests extends StartSupport {
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
implicit val testSettings = TestKitSettings(system)
|
||||
|
||||
val interval = 1.second
|
||||
|
|
@ -81,7 +79,8 @@ class TimerSpec extends TypedSpec("""
|
|||
}
|
||||
}
|
||||
|
||||
def `01 must schedule non-repeated ticks`(): Unit = {
|
||||
"A timer" must {
|
||||
"schedule non-repeated ticks" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.withTimers[Command] { timer ⇒
|
||||
timer.startSingleTimer("T", Tick(1), 10.millis)
|
||||
|
|
@ -96,7 +95,7 @@ class TimerSpec extends TypedSpec("""
|
|||
probe.expectMsg(GotPostStop(false))
|
||||
}
|
||||
|
||||
def `02 must schedule repeated ticks`(): Unit = {
|
||||
"schedule repeated ticks" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.withTimers[Command] { timer ⇒
|
||||
timer.startPeriodicTimer("T", Tick(1), interval)
|
||||
|
|
@ -114,7 +113,7 @@ class TimerSpec extends TypedSpec("""
|
|||
probe.expectMsg(GotPostStop(false))
|
||||
}
|
||||
|
||||
def `03 must replace timer`(): Unit = {
|
||||
"replace timer" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.withTimers[Command] { timer ⇒
|
||||
timer.startPeriodicTimer("T", Tick(1), interval)
|
||||
|
|
@ -134,7 +133,7 @@ class TimerSpec extends TypedSpec("""
|
|||
probe.expectMsg(GotPostStop(false))
|
||||
}
|
||||
|
||||
def `04 must cancel timer`(): Unit = {
|
||||
"cancel timer" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.withTimers[Command] { timer ⇒
|
||||
timer.startPeriodicTimer("T", Tick(1), interval)
|
||||
|
|
@ -150,7 +149,7 @@ class TimerSpec extends TypedSpec("""
|
|||
probe.expectMsg(GotPostStop(false))
|
||||
}
|
||||
|
||||
def `05 must discard timers from old incarnation after restart, alt 1`(): Unit = {
|
||||
"discard timers from old incarnation after restart, alt 1" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val startCounter = new AtomicInteger(0)
|
||||
val behv = Actor.supervise(Actor.withTimers[Command] { timer ⇒
|
||||
|
|
@ -174,7 +173,7 @@ class TimerSpec extends TypedSpec("""
|
|||
probe.expectMsg(GotPostStop(false))
|
||||
}
|
||||
|
||||
def `06 must discard timers from old incarnation after restart, alt 2`(): Unit = {
|
||||
"discard timers from old incarnation after restart, alt 2" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.supervise(Actor.withTimers[Command] { timer ⇒
|
||||
timer.startPeriodicTimer("T", Tick(1), interval)
|
||||
|
|
@ -200,7 +199,7 @@ class TimerSpec extends TypedSpec("""
|
|||
probe.expectMsg(GotPostStop(false))
|
||||
}
|
||||
|
||||
def `07 must cancel timers when stopped from exception`(): Unit = {
|
||||
"cancel timers when stopped from exception" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.withTimers[Command] { timer ⇒
|
||||
timer.startPeriodicTimer("T", Tick(1), interval)
|
||||
|
|
@ -211,7 +210,7 @@ class TimerSpec extends TypedSpec("""
|
|||
probe.expectMsg(GotPostStop(false))
|
||||
}
|
||||
|
||||
def `08 must cancel timers when stopped voluntarily`(): Unit = {
|
||||
"cancel timers when stopped voluntarily" in {
|
||||
val probe = TestProbe[Event]("evt")
|
||||
val behv = Actor.withTimers[Command] { timer ⇒
|
||||
timer.startPeriodicTimer("T", Tick(1), interval)
|
||||
|
|
@ -222,6 +221,4 @@ class TimerSpec extends TypedSpec("""
|
|||
probe.expectMsg(GotPostStop(false))
|
||||
}
|
||||
}
|
||||
|
||||
object `A Restarter (real, adapted)` extends RealTests with AdaptedSystem
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@
|
|||
*/
|
||||
package akka.actor.typed
|
||||
|
||||
import org.scalatest.refspec.RefSpec
|
||||
import org.scalatest.Matchers
|
||||
import org.scalatest.BeforeAndAfterAll
|
||||
import org.scalatest.{ BeforeAndAfterAll, Matchers, WordSpec }
|
||||
import akka.testkit.AkkaSpec
|
||||
|
||||
import scala.concurrent.Await
|
||||
|
|
@ -36,14 +34,29 @@ import org.scalatest.time.Span
|
|||
/**
|
||||
* Helper class for writing tests for typed Actors with ScalaTest.
|
||||
*/
|
||||
@RunWith(classOf[org.scalatest.junit.JUnitRunner])
|
||||
class TypedSpecSetup extends RefSpec with Matchers with BeforeAndAfterAll with ScalaFutures with TypeCheckedTripleEquals {
|
||||
class TypedSpecSetup extends WordSpec with Matchers with BeforeAndAfterAll with ScalaFutures with TypeCheckedTripleEquals {
|
||||
|
||||
// TODO hook this up with config like in akka-testkit/AkkaSpec?
|
||||
implicit val akkaPatience = PatienceConfig(3.seconds, Span(100, org.scalatest.time.Millis))
|
||||
|
||||
}
|
||||
|
||||
trait StartSupport {
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
private implicit def timeout: Timeout = Timeout(1.minute)
|
||||
private implicit def scheduler = system.scheduler
|
||||
|
||||
private val nameCounter = Iterator.from(0)
|
||||
|
||||
def nextName(prefix: String = "a"): String = s"$prefix-${nameCounter.next()}"
|
||||
|
||||
def start[T](behv: Behavior[T]): ActorRef[T] = {
|
||||
import akka.actor.typed.scaladsl.AskPattern._
|
||||
import akka.typed.testkit.scaladsl._
|
||||
implicit val testSettings = TestKitSettings(system)
|
||||
Await.result(system ? TypedSpec.Create(behv, nextName()), 3.seconds.dilated)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Helper class for writing tests against both ActorSystemImpl and ActorSystemAdapter.
|
||||
*/
|
||||
|
|
@ -59,25 +72,11 @@ abstract class TypedSpec(val config: Config) extends TypedSpecSetup {
|
|||
// extension point
|
||||
def setTimeout: Timeout = Timeout(1.minute)
|
||||
|
||||
lazy val system: ActorSystem[TypedSpec.Command] = {
|
||||
implicit lazy val system: ActorSystem[TypedSpec.Command] = {
|
||||
val sys = ActorSystem(guardian(), AkkaSpec.getCallerName(classOf[TypedSpec]), config = Some(config withFallback AkkaSpec.testConf))
|
||||
sys
|
||||
}
|
||||
|
||||
trait StartSupport {
|
||||
def system: ActorSystem[TypedSpec.Command]
|
||||
|
||||
private val nameCounter = Iterator.from(0)
|
||||
def nextName(prefix: String = "a"): String = s"$prefix-${nameCounter.next()}"
|
||||
|
||||
def start[T](behv: Behavior[T]): ActorRef[T] = {
|
||||
import akka.actor.typed.scaladsl.AskPattern._
|
||||
import akka.typed.testkit.scaladsl._
|
||||
implicit val testSettings = TestKitSettings(system)
|
||||
Await.result(system ? TypedSpec.Create(behv, nextName()), 3.seconds.dilated)
|
||||
}
|
||||
}
|
||||
|
||||
trait AdaptedSystem {
|
||||
def system: ActorSystem[TypedSpec.Command] = TypedSpec.this.system
|
||||
}
|
||||
|
|
@ -219,12 +218,8 @@ object TypedSpec {
|
|||
|
||||
class TypedSpecSpec extends TypedSpec {
|
||||
|
||||
object `A TypedSpec` {
|
||||
|
||||
trait CommonTests {
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
|
||||
def `must report failures`(): Unit = {
|
||||
"A TypedSpec" must {
|
||||
"must report failures" in {
|
||||
a[TypedSpec.SimulatedException] must be thrownBy {
|
||||
sync(runTest("failure")(StepWise[String]((ctx, startWith) ⇒
|
||||
startWith {
|
||||
|
|
@ -233,7 +228,4 @@ class TypedSpecSpec extends TypedSpec {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
object `when using the adapted implementation` extends CommonTests with AdaptedSystem
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,15 +7,12 @@ import scala.concurrent._
|
|||
import scala.concurrent.duration._
|
||||
import akka.actor.typed.scaladsl.Actor._
|
||||
import akka.actor.typed.scaladsl.AskPattern._
|
||||
import akka.testkit._
|
||||
|
||||
@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner])
|
||||
class WatchSpec extends TypedSpec {
|
||||
|
||||
trait Tests {
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
"Actor monitoring" must {
|
||||
|
||||
def `get notified of actor termination`(): Unit = {
|
||||
"get notified of actor termination" in {
|
||||
case object Stop
|
||||
case class StartWatching(watchee: ActorRef[Stop.type])
|
||||
|
||||
|
|
@ -37,7 +34,7 @@ class WatchSpec extends TypedSpec {
|
|||
Await.result(receivedTerminationSignal.future, 3.seconds /*.dilated*/ )
|
||||
}
|
||||
|
||||
def `get notified of actor termination with a custom message`(): Unit = {
|
||||
"get notified of actor termination with a custom message" in {
|
||||
case object Stop
|
||||
|
||||
sealed trait Message
|
||||
|
|
@ -65,6 +62,4 @@ class WatchSpec extends TypedSpec {
|
|||
Await.result(receivedTerminationSignal.future, 3.seconds /*.dilated*/ )
|
||||
}
|
||||
}
|
||||
|
||||
object `Actor monitoring (adapted)` extends Tests with AdaptedSystem
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,10 @@
|
|||
package akka.actor.typed
|
||||
package internal
|
||||
|
||||
import akka.Done
|
||||
import akka.actor.InvalidMessageException
|
||||
import akka.actor.typed.scaladsl.Actor
|
||||
import akka.actor.typed.scaladsl.Actor._
|
||||
import akka.typed.testkit.Inbox
|
||||
import akka.util.Timeout
|
||||
import org.junit.runner.RunWith
|
||||
import org.scalactic.ConversionCheckedTripleEquals
|
||||
import org.scalatest._
|
||||
import org.scalatest.concurrent.{ Eventually, ScalaFutures }
|
||||
|
|
@ -19,17 +16,14 @@ import scala.concurrent.duration._
|
|||
import scala.concurrent.{ Future, Promise }
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
@RunWith(classOf[org.scalatest.junit.JUnitRunner])
|
||||
class ActorSystemSpec extends Spec with Matchers with BeforeAndAfterAll with ScalaFutures with Eventually with ConversionCheckedTripleEquals {
|
||||
class ActorSystemSpec extends WordSpec with Matchers with BeforeAndAfterAll with ScalaFutures with Eventually with ConversionCheckedTripleEquals {
|
||||
|
||||
override implicit val patienceConfig = PatienceConfig(1.second)
|
||||
def system[T](behavior: Behavior[T], name: String) = ActorSystem(behavior, name)
|
||||
def suite = "adapter"
|
||||
|
||||
case class Probe(msg: String, replyTo: ActorRef[String])
|
||||
|
||||
trait CommonTests {
|
||||
def system[T](behavior: Behavior[T], name: String): ActorSystem[T]
|
||||
def suite: String
|
||||
|
||||
def withSystem[T](name: String, behavior: Behavior[T], doTerminate: Boolean = true)(block: ActorSystem[T] ⇒ Unit): Terminated = {
|
||||
val sys = system(behavior, s"$suite-$name")
|
||||
try {
|
||||
|
|
@ -42,11 +36,14 @@ class ActorSystemSpec extends Spec with Matchers with BeforeAndAfterAll with Sca
|
|||
}
|
||||
}
|
||||
|
||||
def `must start the guardian actor and terminate when it terminates`(): Unit = {
|
||||
"An ActorSystem" must {
|
||||
"must start the guardian actor and terminate when it terminates" in {
|
||||
val t = withSystem("a", immutable[Probe] { case (_, p) ⇒ p.replyTo ! p.msg; stopped }, doTerminate = false) { sys ⇒
|
||||
val inbox = Inbox[String]("a")
|
||||
sys ! Probe("hello", inbox.ref)
|
||||
eventually { inbox.hasMessages should ===(true) }
|
||||
eventually {
|
||||
inbox.hasMessages should ===(true)
|
||||
}
|
||||
inbox.receiveAll() should ===("hello" :: Nil)
|
||||
}
|
||||
val p = t.ref.path
|
||||
|
|
@ -54,7 +51,7 @@ class ActorSystemSpec extends Spec with Matchers with BeforeAndAfterAll with Sca
|
|||
p.address.system should ===(suite + "-a")
|
||||
}
|
||||
|
||||
def `must terminate the guardian actor`(): Unit = {
|
||||
"must terminate the guardian actor" in {
|
||||
val inbox = Inbox[String]("terminate")
|
||||
val sys = system(
|
||||
immutable[Probe] {
|
||||
|
|
@ -69,21 +66,25 @@ class ActorSystemSpec extends Spec with Matchers with BeforeAndAfterAll with Sca
|
|||
inbox.receiveAll() should ===("done" :: Nil)
|
||||
}
|
||||
|
||||
def `must log to the event stream`(): Unit = pending
|
||||
"must log to the event stream" in {
|
||||
pending
|
||||
}
|
||||
|
||||
def `must have a name`(): Unit =
|
||||
"must have a name" in {
|
||||
withSystem("name", Actor.empty[String]) { sys ⇒
|
||||
sys.name should ===(suite + "-name")
|
||||
}
|
||||
}
|
||||
|
||||
def `must report its uptime`(): Unit =
|
||||
"must report its uptime" in {
|
||||
withSystem("uptime", Actor.empty[String]) { sys ⇒
|
||||
sys.uptime should be < 1L
|
||||
Thread.sleep(1000)
|
||||
sys.uptime should be >= 1L
|
||||
}
|
||||
}
|
||||
|
||||
def `must have a working thread factory`(): Unit =
|
||||
"must have a working thread factory" in {
|
||||
withSystem("thread", Actor.empty[String]) { sys ⇒
|
||||
val p = Promise[Int]
|
||||
sys.threadFactory.newThread(new Runnable {
|
||||
|
|
@ -91,14 +92,16 @@ class ActorSystemSpec extends Spec with Matchers with BeforeAndAfterAll with Sca
|
|||
}).start()
|
||||
p.future.futureValue should ===(42)
|
||||
}
|
||||
}
|
||||
|
||||
def `must be able to run Futures`(): Unit =
|
||||
"must be able to run Futures" in {
|
||||
withSystem("futures", Actor.empty[String]) { sys ⇒
|
||||
val f = Future(42)(sys.executionContext)
|
||||
f.futureValue should ===(42)
|
||||
}
|
||||
}
|
||||
|
||||
def `must not allow null messages`(): Unit = {
|
||||
"must not allow null messages" in {
|
||||
withSystem("null-messages", Actor.empty[String]) { sys ⇒
|
||||
intercept[InvalidMessageException] {
|
||||
sys ! null
|
||||
|
|
@ -106,9 +109,4 @@ class ActorSystemSpec extends Spec with Matchers with BeforeAndAfterAll with Sca
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
object `An ActorSystemAdapter` extends CommonTests {
|
||||
def system[T](behavior: Behavior[T], name: String) = ActorSystem(behavior, name)
|
||||
def suite = "adapter"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import org.scalatest.concurrent.Eventually
|
|||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class LocalReceptionistSpec extends TypedSpec with Eventually {
|
||||
class LocalReceptionistSpec extends TypedSpec with Eventually with StartSupport {
|
||||
|
||||
trait ServiceA
|
||||
val ServiceKeyA = Receptionist.ServiceKey[ServiceA]("service-a")
|
||||
|
|
@ -35,15 +35,15 @@ class LocalReceptionistSpec extends TypedSpec with Eventually {
|
|||
|
||||
import akka.actor.typed.internal.receptionist.ReceptionistImpl.{ localOnlyBehavior ⇒ behavior }
|
||||
|
||||
trait CommonTests extends StartSupport {
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
implicit val testSettings = TestKitSettings(system)
|
||||
|
||||
abstract class TestSetup {
|
||||
val receptionist = start(behavior)
|
||||
}
|
||||
|
||||
def `must register a service`(): Unit = {
|
||||
"A local receptionist" must {
|
||||
|
||||
"must register a service" in {
|
||||
val ctx = new EffectfulActorContext("register", behavior, 1000, system)
|
||||
val a = Inbox[ServiceA]("a")
|
||||
val r = Inbox[Registered[_]]("r")
|
||||
|
|
@ -57,7 +57,7 @@ class LocalReceptionistSpec extends TypedSpec with Eventually {
|
|||
assertEmpty(a, r, q)
|
||||
}
|
||||
|
||||
def `must register two services`(): Unit = {
|
||||
"must register two services" in {
|
||||
val ctx = new EffectfulActorContext("registertwo", behavior, 1000, system)
|
||||
val a = Inbox[ServiceA]("a")
|
||||
val r = Inbox[Registered[_]]("r")
|
||||
|
|
@ -74,7 +74,7 @@ class LocalReceptionistSpec extends TypedSpec with Eventually {
|
|||
assertEmpty(a, b, r, q)
|
||||
}
|
||||
|
||||
def `must register two services with the same key`(): Unit = {
|
||||
"must register two services with the same key" in {
|
||||
val ctx = new EffectfulActorContext("registertwosame", behavior, 1000, system)
|
||||
val a1 = Inbox[ServiceA]("a1")
|
||||
val r = Inbox[Registered[_]]("r")
|
||||
|
|
@ -91,7 +91,8 @@ class LocalReceptionistSpec extends TypedSpec with Eventually {
|
|||
assertEmpty(a1, a2, r, q)
|
||||
}
|
||||
|
||||
def `must unregister services when they terminate`(): Unit = new TestSetup {
|
||||
"must unregister services when they terminate" in {
|
||||
new TestSetup {
|
||||
val regProbe = TestProbe[Any]("regProbe")
|
||||
|
||||
val serviceA = start(stoppableBehavior.narrow[ServiceA])
|
||||
|
|
@ -122,8 +123,10 @@ class LocalReceptionistSpec extends TypedSpec with Eventually {
|
|||
regProbe.expectMsg(Listing(ServiceKeyB, Set(serviceB)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def `must support subscribing to service changes`(): Unit = new TestSetup {
|
||||
"must support subscribing to service changes" in {
|
||||
new TestSetup {
|
||||
val regProbe = TestProbe[Registered[_]]("regProbe")
|
||||
|
||||
val aSubscriber = TestProbe[Listing[ServiceA]]("aUser")
|
||||
|
|
@ -148,8 +151,10 @@ class LocalReceptionistSpec extends TypedSpec with Eventually {
|
|||
serviceA2 ! Stop
|
||||
aSubscriber.expectMsg(Listing(ServiceKeyA, Set.empty[ActorRef[ServiceA]]))
|
||||
}
|
||||
}
|
||||
|
||||
def `must work with ask`(): Unit = sync(runTest("Receptionist") {
|
||||
"must work with ask" in {
|
||||
sync(runTest("Receptionist") {
|
||||
StepWise[Registered[ServiceA]] { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith.withKeepTraces(true) {
|
||||
|
|
@ -169,8 +174,10 @@ class LocalReceptionistSpec extends TypedSpec with Eventually {
|
|||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def `must be present in the system`(): Unit = sync(runTest("systemReceptionist") {
|
||||
"must be present in the system" in {
|
||||
sync(runTest("systemReceptionist") {
|
||||
StepWise[Listing[ServiceA]] { (ctx, startWith) ⇒
|
||||
val self = ctx.self
|
||||
startWith.withKeepTraces(true) {
|
||||
|
|
@ -180,8 +187,6 @@ class LocalReceptionistSpec extends TypedSpec with Eventually {
|
|||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
object `A Receptionist (adapted)` extends CommonTests with AdaptedSystem
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,24 +6,15 @@ package scaladsl
|
|||
|
||||
import akka.typed.testkit.{ EffectfulActorContext, TestKitSettings }
|
||||
import akka.typed.testkit.scaladsl.TestProbe
|
||||
import org.junit.runner.RunWith
|
||||
import org.scalatest.junit.JUnitRunner
|
||||
import scala.concurrent.duration.DurationInt
|
||||
|
||||
@RunWith(classOf[JUnitRunner])
|
||||
final class ImmutablePartialSpec extends TypedSpec {
|
||||
|
||||
final object `An Actor.immutablePartial behavior (adapted)`
|
||||
extends Tests
|
||||
with AdaptedSystem
|
||||
|
||||
trait Tests extends StartSupport {
|
||||
class ImmutablePartialSpec extends TypedSpec with StartSupport {
|
||||
|
||||
private implicit val testSettings = TestKitSettings(system)
|
||||
|
||||
override implicit def system: ActorSystem[TypedSpec.Command]
|
||||
"An immutable partial" must {
|
||||
|
||||
def `must correctly install the message handler`(): Unit = {
|
||||
"correctly install the message handler" in {
|
||||
val probe = TestProbe[Command]("probe")
|
||||
val behavior =
|
||||
Actor.immutablePartial[Command] {
|
||||
|
|
@ -7,21 +7,13 @@ package scaladsl
|
|||
import akka.Done
|
||||
import akka.typed.testkit.TestKitSettings
|
||||
import akka.typed.testkit.scaladsl.TestProbe
|
||||
import org.junit.runner.RunWith
|
||||
import org.scalatest.junit.JUnitRunner
|
||||
|
||||
@RunWith(classOf[JUnitRunner])
|
||||
final class OnSignalSpec extends TypedSpec {
|
||||
|
||||
final object `An Actor.onSignal behavior (adapted)` extends Tests with AdaptedSystem
|
||||
|
||||
trait Tests extends StartSupport {
|
||||
final class OnSignalSpec extends TypedSpec with StartSupport {
|
||||
|
||||
private implicit val testSettings = TestKitSettings(system)
|
||||
|
||||
override implicit def system: ActorSystem[TypedSpec.Command]
|
||||
|
||||
def `must correctly install the signal handler`(): Unit = {
|
||||
"An Actor.OnSignal behavior" must {
|
||||
"must correctly install the signal handler" in {
|
||||
val probe = TestProbe[Done]("probe")
|
||||
val behavior =
|
||||
Actor.deferred[Nothing] { context ⇒
|
||||
|
|
|
|||
|
|
@ -74,9 +74,11 @@ object IntroSpec {
|
|||
}
|
||||
|
||||
class IntroSpec extends TypedSpec {
|
||||
|
||||
import IntroSpec._
|
||||
|
||||
def `must say hello`(): Unit = {
|
||||
"Hello world" must {
|
||||
"must say hello" in {
|
||||
// TODO Implicits.global is not something we would like to encourage in docs
|
||||
//#hello-world
|
||||
import HelloWorld._
|
||||
|
|
@ -89,12 +91,15 @@ class IntroSpec extends TypedSpec {
|
|||
|
||||
for {
|
||||
greeting ← future.recover { case ex ⇒ ex.getMessage }
|
||||
done ← { println(s"result: $greeting"); system.terminate() }
|
||||
done ← {
|
||||
println(s"result: $greeting")
|
||||
system.terminate()
|
||||
}
|
||||
} println("system terminated")
|
||||
//#hello-world
|
||||
}
|
||||
|
||||
def `must chat`(): Unit = {
|
||||
"must chat" in {
|
||||
//#chatroom-gabbler
|
||||
import ChatRoom._
|
||||
|
||||
|
|
@ -139,5 +144,6 @@ class IntroSpec extends TypedSpec {
|
|||
Await.result(system.whenTerminated, 3.seconds)
|
||||
//#chatroom-main
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
package docs.akka.typed
|
||||
|
||||
//#imports
|
||||
import akka.NotUsed
|
||||
import akka.actor.typed._
|
||||
import akka.actor.typed.scaladsl.Actor
|
||||
import akka.actor.typed.scaladsl.ActorContext
|
||||
|
|
@ -67,9 +66,11 @@ object MutableIntroSpec {
|
|||
}
|
||||
|
||||
class MutableIntroSpec extends TypedSpec {
|
||||
|
||||
import MutableIntroSpec._
|
||||
|
||||
def `must chat`(): Unit = {
|
||||
"A chat room" must {
|
||||
"chat" in {
|
||||
//#chatroom-gabbler
|
||||
import ChatRoom._
|
||||
|
||||
|
|
@ -112,5 +113,5 @@ class MutableIntroSpec extends TypedSpec {
|
|||
Await.result(system.whenTerminated, 1.second)
|
||||
//#chatroom-main
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ akka.typed {
|
|||
library-extensions = ${?akka.typed.library-extensions} []
|
||||
}
|
||||
|
||||
# TODO: move these out somewhere else when doing #23632
|
||||
akka.actor {
|
||||
serialization-bindings {
|
||||
"akka.actor.typed.ActorRef" = typed-misc
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
*/
|
||||
package akka.actor.typed
|
||||
|
||||
import akka.annotation.InternalApi
|
||||
import akka.{ actor ⇒ a }
|
||||
|
||||
import scala.annotation.unchecked.uncheckedVariance
|
||||
|
|
@ -61,10 +62,11 @@ object ActorRef {
|
|||
// FIXME factory methods for below for Java (trait + object)
|
||||
|
||||
/**
|
||||
* Create an ActorRef from a Future, buffering up to the given number of
|
||||
* messages in while the Future is not fulfilled.
|
||||
* INTERNAL API
|
||||
*
|
||||
* FIXME, this isn't really used since we removed the native actor system
|
||||
*/
|
||||
private[akka] def apply[T](f: Future[ActorRef[T]], bufferSize: Int = 1000): ActorRef[T] =
|
||||
@InternalApi private[akka] def apply[T](f: Future[ActorRef[T]], bufferSize: Int = 1000): ActorRef[T] =
|
||||
f.value match {
|
||||
// an AdaptedActorSystem will always create refs eagerly, so it will take this path
|
||||
case Some(Success(ref)) ⇒ ref
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ abstract class ActorSystem[-T] extends ActorRef[T] with Extensions {
|
|||
* invocation when asking the guardian.
|
||||
*
|
||||
* The returned Future of [[ActorRef]] may be converted into an [[ActorRef]]
|
||||
* to which messages can immediately be sent by using the [[ActorRef.apply[T](s*]]
|
||||
* to which messages can immediately be sent by using the [[ActorRef$.apply[T](s*]]
|
||||
* method.
|
||||
*/
|
||||
def systemActorOf[U](behavior: Behavior[U], name: String, props: Props = Props.empty)(implicit timeout: Timeout): Future[ActorRef[U]]
|
||||
|
|
|
|||
|
|
@ -23,9 +23,11 @@ trait ExtensionsImpl extends Extensions { self: ActorSystem[_] ⇒
|
|||
private val extensions = new ConcurrentHashMap[ExtensionId[_], AnyRef]
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Hook for ActorSystem to load extensions on startup
|
||||
*/
|
||||
final def loadExtensions(): Unit = {
|
||||
@InternalApi private[akka] def loadExtensions(): Unit = {
|
||||
/**
|
||||
* @param throwOnLoadFail Throw exception when an extension fails to load (needed for backwards compatibility)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -72,11 +72,11 @@ class ClusterShardingPersistenceSpec extends TypedSpec(ClusterShardingPersistenc
|
|||
implicit val untypedSystem = system.toUntyped
|
||||
private val untypedCluster = akka.cluster.Cluster(untypedSystem)
|
||||
|
||||
object `Typed cluster sharding with persistent actor` {
|
||||
"Typed cluster sharding with persistent actor" must {
|
||||
|
||||
untypedCluster.join(untypedCluster.selfAddress)
|
||||
|
||||
def `01 start persistent actor`(): Unit = {
|
||||
"start persistent actor" in {
|
||||
ClusterSharding(system).spawn(persistentActor, Props.empty, typeKey,
|
||||
ClusterShardingSettings(system), maxNumberOfShards = 100, handOffStopMessage = StopPlz)
|
||||
|
||||
|
|
@ -90,5 +90,4 @@ class ClusterShardingPersistenceSpec extends TypedSpec(ClusterShardingPersistenc
|
|||
p.expectMsg("a|b|c")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,9 @@ object ClusterShardingSpec {
|
|||
final case class WhoAreYou(replyTo: ActorRef[String]) extends TestProtocol
|
||||
final case class StopPlz() extends TestProtocol
|
||||
|
||||
sealed trait IdTestProtocol extends java.io.Serializable { def id: String }
|
||||
sealed trait IdTestProtocol extends java.io.Serializable {
|
||||
def id: String
|
||||
}
|
||||
final case class IdReplyPlz(id: String, toMe: ActorRef[String]) extends IdTestProtocol
|
||||
final case class IdWhoAreYou(id: String, replyTo: ActorRef[String]) extends IdTestProtocol
|
||||
final case class IdStopPlz(id: String) extends IdTestProtocol
|
||||
|
|
@ -118,6 +120,7 @@ object ClusterShardingSpec {
|
|||
}
|
||||
|
||||
class ClusterShardingSpec extends TypedSpec(ClusterShardingSpec.config) with ScalaFutures with Eventually {
|
||||
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
import ClusterShardingSpec._
|
||||
|
||||
|
|
@ -164,9 +167,9 @@ class ClusterShardingSpec extends TypedSpec(ClusterShardingSpec.config) with Sca
|
|||
Actor.same
|
||||
}
|
||||
|
||||
object `Typed cluster sharding` {
|
||||
"Typed cluster sharding" must {
|
||||
|
||||
def `01 must join cluster`(): Unit = {
|
||||
"join cluster" in {
|
||||
Cluster(system).manager ! Join(Cluster(system).selfMember.address)
|
||||
Cluster(system2).manager ! Join(Cluster(system).selfMember.address)
|
||||
|
||||
|
|
@ -181,7 +184,7 @@ class ClusterShardingSpec extends TypedSpec(ClusterShardingSpec.config) with Sca
|
|||
|
||||
}
|
||||
|
||||
def `02 must send messsages via cluster sharding, using envelopes`(): Unit = {
|
||||
"send messsages via cluster sharding, using envelopes" in {
|
||||
val ref = sharding.spawn(
|
||||
behavior,
|
||||
Props.empty,
|
||||
|
|
@ -204,7 +207,8 @@ class ClusterShardingSpec extends TypedSpec(ClusterShardingSpec.config) with Sca
|
|||
ref ! ShardingEnvelope(s"test$n", StopPlz())
|
||||
}
|
||||
}
|
||||
def `03 must send messsages via cluster sharding, without envelopes`(): Unit = {
|
||||
|
||||
"send messsages via cluster sharding, without envelopes" in {
|
||||
val ref = sharding.spawn(
|
||||
behaviorWithId,
|
||||
Props.empty,
|
||||
|
|
@ -228,7 +232,7 @@ class ClusterShardingSpec extends TypedSpec(ClusterShardingSpec.config) with Sca
|
|||
}
|
||||
}
|
||||
|
||||
// def `04 fail if starting sharding for already used typeName, but with wrong type`(): Unit = {
|
||||
// "04 fail if starting sharding for already used typeName, but with wrong type" in {
|
||||
// val ex = intercept[Exception] {
|
||||
// sharding.spawn(
|
||||
// Actor.empty[String],
|
||||
|
|
@ -243,7 +247,7 @@ class ClusterShardingSpec extends TypedSpec(ClusterShardingSpec.config) with Sca
|
|||
// ex.getMessage should include("already started")
|
||||
// }
|
||||
|
||||
def `11 EntityRef - tell`(): Unit = {
|
||||
"EntityRef - tell" in {
|
||||
val charlieRef = sharding.entityRefFor(typeKey, "charlie")
|
||||
|
||||
val p = TestProbe[String]()
|
||||
|
|
@ -257,7 +261,7 @@ class ClusterShardingSpec extends TypedSpec(ClusterShardingSpec.config) with Sca
|
|||
charlieRef ! StopPlz()
|
||||
}
|
||||
|
||||
def `12 EntityRef - ask`(): Unit = {
|
||||
"EntityRef - ask" in {
|
||||
val bobRef = sharding.entityRefFor(typeKey, "bob")
|
||||
val charlieRef = sharding.entityRefFor(typeKey, "charlie")
|
||||
|
||||
|
|
@ -271,7 +275,5 @@ class ClusterShardingSpec extends TypedSpec(ClusterShardingSpec.config) with Sca
|
|||
|
||||
bobRef ! StopPlz()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import akka.actor.typed.scaladsl.AskPattern._
|
|||
|
||||
class ShardingSerializerSpec extends TypedSpec {
|
||||
|
||||
object `The typed ShardingSerializer` {
|
||||
"The typed ShardingSerializer" must {
|
||||
|
||||
val serialization = SerializationExtension(ActorSystemAdapter.toUntyped(system))
|
||||
|
||||
|
|
@ -27,13 +27,12 @@ class ShardingSerializerSpec extends TypedSpec {
|
|||
}
|
||||
}
|
||||
|
||||
def `must serialize and deserialize ShardingEnvelope`(): Unit = {
|
||||
"must serialize and deserialize ShardingEnvelope" in {
|
||||
checkSerialization(ShardingEnvelope("abc", 42))
|
||||
}
|
||||
|
||||
def `must serialize and deserialize StartEntity`(): Unit = {
|
||||
"must serialize and deserialize StartEntity" in {
|
||||
checkSerialization(StartEntity("abc"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
package akka.cluster.ddata.typed.scaladsl
|
||||
|
||||
import akka.actor.Scheduler
|
||||
import akka.actor.typed.{ ActorRef, ActorSystem, Behavior, TypedSpec }
|
||||
import akka.actor.typed.{ ActorRef, ActorSystem, Behavior, StartSupport, TypedSpec }
|
||||
import akka.actor.typed.scaladsl.Actor
|
||||
import akka.actor.typed.scaladsl.AskPattern._
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
|
|
@ -22,7 +22,8 @@ import scala.concurrent.duration._
|
|||
|
||||
object ReplicatorSpec {
|
||||
|
||||
val config = ConfigFactory.parseString("""
|
||||
val config = ConfigFactory.parseString(
|
||||
"""
|
||||
akka.actor.provider = "cluster"
|
||||
akka.remote.netty.tcp.port = 0
|
||||
akka.remote.artery.canonical.port = 0
|
||||
|
|
@ -113,16 +114,17 @@ object ReplicatorSpec {
|
|||
|
||||
}
|
||||
|
||||
class ReplicatorSpec extends TypedSpec(ReplicatorSpec.config) with Eventually {
|
||||
class ReplicatorSpec extends TypedSpec(ReplicatorSpec.config) with Eventually with StartSupport {
|
||||
|
||||
import ReplicatorSpec._
|
||||
|
||||
trait RealTests extends StartSupport {
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
implicit val testSettings = TestKitSettings(system)
|
||||
val settings = ReplicatorSettings(system)
|
||||
implicit val cluster = Cluster(system.toUntyped)
|
||||
|
||||
def `have API for Update and Get`(): Unit = {
|
||||
"Replicator" must {
|
||||
|
||||
"have API for Update and Get" in {
|
||||
val replicator = start(Replicator.behavior(settings))
|
||||
val c = start(client(replicator))
|
||||
|
||||
|
|
@ -132,7 +134,7 @@ class ReplicatorSpec extends TypedSpec(ReplicatorSpec.config) with Eventually {
|
|||
probe.expectMsg(1)
|
||||
}
|
||||
|
||||
def `have API for Subscribe`(): Unit = {
|
||||
"have API for Subscribe" in {
|
||||
val replicator = start(Replicator.behavior(settings))
|
||||
val c = start(client(replicator))
|
||||
|
||||
|
|
@ -150,7 +152,7 @@ class ReplicatorSpec extends TypedSpec(ReplicatorSpec.config) with Eventually {
|
|||
}
|
||||
}
|
||||
|
||||
def `have an extension`(): Unit = {
|
||||
"have an extension" in {
|
||||
val replicator = DistributedData(system).replicator
|
||||
val c = start(client(replicator))
|
||||
|
||||
|
|
@ -159,8 +161,6 @@ class ReplicatorSpec extends TypedSpec(ReplicatorSpec.config) with Eventually {
|
|||
c ! GetValue(probe.ref)
|
||||
probe.expectMsg(1)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
object `A ReplicatorBehavior (real, adapted)` extends RealTests with AdaptedSystem
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@ class ClusterApiSpec extends TypedSpec(ClusterApiSpec.config) with ScalaFutures
|
|||
val clusterNode1 = Cluster(system)
|
||||
val untypedSystem1 = system.toUntyped
|
||||
|
||||
object `A typed cluster` {
|
||||
"A typed Cluster" must {
|
||||
|
||||
def `01 must join a cluster and observe events from both sides`() = {
|
||||
"join a cluster and observe events from both sides" in {
|
||||
|
||||
val system2 = akka.actor.ActorSystem(system.name, system.settings.config)
|
||||
val adaptedSystem2 = system2.toTyped
|
||||
|
|
|
|||
|
|
@ -101,9 +101,9 @@ class ClusterSingletonApiSpec extends TypedSpec(ClusterSingletonApiSpec.config)
|
|||
val adaptedSystem2 = system2.toTyped
|
||||
val clusterNode2 = Cluster(adaptedSystem2)
|
||||
|
||||
object `A typed cluster singleton` {
|
||||
"A typed cluster singleton" must {
|
||||
|
||||
def `01 must be accessible from two nodes in a cluster`() = {
|
||||
"be accessible from two nodes in a cluster" in {
|
||||
val node1UpProbe = TestProbe[SelfUp]()(system, implicitly[TestKitSettings])
|
||||
clusterNode1.subscriptions ! Subscribe(node1UpProbe.ref, classOf[SelfUp])
|
||||
|
||||
|
|
|
|||
|
|
@ -65,11 +65,11 @@ class ClusterSingletonPersistenceSpec extends TypedSpec(ClusterSingletonPersiste
|
|||
implicit val untypedSystem = system.toUntyped
|
||||
private val untypedCluster = akka.cluster.Cluster(untypedSystem)
|
||||
|
||||
object `Typed cluster singleton with persistent actor` {
|
||||
"A typed cluster singleton with persistent actor" must {
|
||||
|
||||
untypedCluster.join(untypedCluster.selfAddress)
|
||||
|
||||
def `01 start persistent actor`(): Unit = {
|
||||
"start persistent actor" in {
|
||||
val ref = ClusterSingleton(system).spawn(
|
||||
behavior = persistentActor,
|
||||
singletonName = "singleton",
|
||||
|
|
@ -86,5 +86,4 @@ class ClusterSingletonPersistenceSpec extends TypedSpec(ClusterSingletonPersiste
|
|||
p.expectMsg("a|b|c")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,10 +26,9 @@ object MiscMessageSerializerSpec {
|
|||
|
||||
class MiscMessageSerializerSpec extends TypedSpec(MiscMessageSerializerSpec.config) {
|
||||
|
||||
object `The typed MiscMessageSerializer` {
|
||||
|
||||
val serialization = SerializationExtension(system.toUntyped)
|
||||
|
||||
"MiscMessageSerializer" must {
|
||||
def checkSerialization(obj: AnyRef): Unit = {
|
||||
serialization.findSerializerFor(obj) match {
|
||||
case serializer: MiscMessageSerializer ⇒
|
||||
|
|
@ -41,10 +40,9 @@ class MiscMessageSerializerSpec extends TypedSpec(MiscMessageSerializerSpec.conf
|
|||
}
|
||||
}
|
||||
|
||||
def `must serialize and deserialize typed actor refs `(): Unit = {
|
||||
"must serialize and deserialize typed actor refs" in {
|
||||
val ref = (system ? Create(Actor.empty[Unit], "some-actor")).futureValue
|
||||
checkSerialization(ref)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,8 @@ import akka.actor.ExtendedActorSystem
|
|||
import akka.cluster.Cluster
|
||||
import akka.cluster.typed.ActorRefResolver
|
||||
import akka.serialization.SerializerWithStringManifest
|
||||
import akka.actor.typed.ActorRef
|
||||
import akka.actor.typed.ActorSystem
|
||||
import akka.actor.typed.{ ActorRef, ActorSystem, StartSupport, TypedSpec }
|
||||
import akka.actor.typed.internal.adapter.ActorSystemAdapter
|
||||
import akka.actor.typed.TypedSpec
|
||||
import akka.actor.typed.TypedSpec.Command
|
||||
import akka.cluster.typed.ActorRefResolver
|
||||
import akka.actor.typed.internal.adapter.ActorRefAdapter
|
||||
|
|
@ -96,29 +94,30 @@ object ClusterReceptionistSpec {
|
|||
val PingKey = Receptionist.ServiceKey[PingProtocol]("pingy")
|
||||
}
|
||||
|
||||
class ClusterReceptionistSpec extends TypedSpec(ClusterReceptionistSpec.config) {
|
||||
class ClusterReceptionistSpec extends TypedSpec(ClusterReceptionistSpec.config) with StartSupport {
|
||||
|
||||
import ClusterReceptionistSpec._
|
||||
|
||||
val adaptedSystem = system
|
||||
implicit val testSettings = TestKitSettings(adaptedSystem)
|
||||
val untypedSystem1 = ActorSystemAdapter.toUntyped(adaptedSystem)
|
||||
implicit val testSettings = TestKitSettings(system)
|
||||
val untypedSystem1 = ActorSystemAdapter.toUntyped(system)
|
||||
val clusterNode1 = Cluster(untypedSystem1)
|
||||
|
||||
val system2 = akka.actor.ActorSystem(
|
||||
adaptedSystem.name,
|
||||
adaptedSystem.settings.config)
|
||||
system.name,
|
||||
system.settings.config)
|
||||
val adaptedSystem2 = system2.toTyped
|
||||
val clusterNode2 = Cluster(system2)
|
||||
|
||||
clusterNode1.join(clusterNode1.selfAddress)
|
||||
clusterNode2.join(clusterNode1.selfAddress)
|
||||
|
||||
object `The ClusterReceptionist` extends StartSupport {
|
||||
def system: ActorSystem[Command] = adaptedSystem
|
||||
import Receptionist._
|
||||
|
||||
def `must eventually replicate registrations to the other side`() = new TestSetup {
|
||||
val regProbe = TestProbe[Any]()(adaptedSystem, testSettings)
|
||||
"The cluster receptionist" must {
|
||||
|
||||
"must eventually replicate registrations to the other side" in {
|
||||
new TestSetup {
|
||||
val regProbe = TestProbe[Any]()(system, testSettings)
|
||||
val regProbe2 = TestProbe[Any]()(adaptedSystem2, testSettings)
|
||||
|
||||
adaptedSystem2.receptionist ! Subscribe(PingKey, regProbe2.ref)
|
||||
|
|
@ -137,13 +136,14 @@ class ClusterReceptionistSpec extends TypedSpec(ClusterReceptionistSpec.config)
|
|||
regProbe2.expectMsg(Listing(PingKey, Set.empty[ActorRef[PingProtocol]]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait TestSetup {
|
||||
}
|
||||
|
||||
override def afterAll(): Unit = {
|
||||
super.afterAll()
|
||||
Await.result(adaptedSystem.terminate(), 3.seconds)
|
||||
Await.result(system.terminate(), 3.seconds)
|
||||
Await.result(system2.terminate(), 3.seconds)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,7 @@
|
|||
package akka.persistence.typed.scaladsl
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import akka.actor.typed.ActorRef
|
||||
import akka.actor.typed.ActorSystem
|
||||
import akka.actor.typed.Behavior
|
||||
import akka.actor.typed.TypedSpec
|
||||
import akka.actor.typed.{ ActorRef, ActorSystem, Behavior, StartSupport, SupervisorStrategy, Terminated, TypedSpec }
|
||||
import akka.actor.typed.scaladsl.Actor
|
||||
import akka.actor.typed.scaladsl.AskPattern._
|
||||
import akka.actor.typed.scaladsl.adapter._
|
||||
|
|
@ -17,8 +14,6 @@ import com.typesafe.config.ConfigFactory
|
|||
import org.scalatest.concurrent.Eventually
|
||||
import akka.util.Timeout
|
||||
import akka.persistence.typed.scaladsl.PersistentActor._
|
||||
import akka.actor.typed.SupervisorStrategy
|
||||
import akka.actor.typed.Terminated
|
||||
|
||||
object PersistentActorSpec {
|
||||
|
||||
|
|
@ -113,14 +108,14 @@ object PersistentActorSpec {
|
|||
|
||||
}
|
||||
|
||||
class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eventually {
|
||||
class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eventually with StartSupport {
|
||||
import PersistentActorSpec._
|
||||
|
||||
trait RealTests extends StartSupport {
|
||||
implicit def system: ActorSystem[TypedSpec.Command]
|
||||
implicit val testSettings = TestKitSettings(system)
|
||||
|
||||
def `persist an event`(): Unit = {
|
||||
"A typed persistent actor" must {
|
||||
|
||||
"persist an event" in {
|
||||
val c = start(counter("c1"))
|
||||
|
||||
val probe = TestProbe[State]
|
||||
|
|
@ -129,7 +124,7 @@ class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eve
|
|||
probe.expectMsg(State(1, Vector(0)))
|
||||
}
|
||||
|
||||
def `replay stored events`(): Unit = {
|
||||
"replay stored events" in {
|
||||
val c = start(counter("c2"))
|
||||
|
||||
val probe = TestProbe[State]
|
||||
|
|
@ -147,7 +142,7 @@ class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eve
|
|||
probe.expectMsg(State(4, Vector(0, 1, 2, 3)))
|
||||
}
|
||||
|
||||
def `handle Terminated signal`(): Unit = {
|
||||
"handle Terminated signal" in {
|
||||
val c = start(counter("c3"))
|
||||
|
||||
val probe = TestProbe[State]
|
||||
|
|
@ -159,7 +154,7 @@ class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eve
|
|||
}
|
||||
}
|
||||
|
||||
def `handle receive timeout`(): Unit = {
|
||||
"handle receive timeout" in {
|
||||
val c = start(counter("c4"))
|
||||
|
||||
val probe = TestProbe[State]
|
||||
|
|
@ -177,7 +172,7 @@ class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eve
|
|||
* Verify that all side-effects callbacks are called (in order) and only once.
|
||||
* The [[IncrementTwiceAndThenLog]] command will emit two Increment events
|
||||
*/
|
||||
def `chainable side effects with events`(): Unit = {
|
||||
"chainable side effects with events" in {
|
||||
val loggingProbe = TestProbe[String]
|
||||
val c = start(counter("c5", loggingProbe.ref))
|
||||
|
||||
|
|
@ -192,7 +187,7 @@ class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eve
|
|||
}
|
||||
|
||||
/** Proves that side-effects are called when emitting an empty list of events */
|
||||
def `chainable side effects without events`(): Unit = {
|
||||
"chainable side effects without events" in {
|
||||
val loggingProbe = TestProbe[String]
|
||||
val c = start(counter("c6", loggingProbe.ref))
|
||||
|
||||
|
|
@ -204,7 +199,7 @@ class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eve
|
|||
}
|
||||
|
||||
/** Proves that side-effects are called when explicitly calling Effect.none */
|
||||
def `chainable side effects when doing nothing (Effect.none)`(): Unit = {
|
||||
"chainable side effects when doing nothing (Effect.none)" in {
|
||||
val loggingProbe = TestProbe[String]
|
||||
val c = start(counter("c7", loggingProbe.ref))
|
||||
|
||||
|
|
@ -215,7 +210,7 @@ class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eve
|
|||
loggingProbe.expectMsg(firstLogging)
|
||||
}
|
||||
|
||||
def `work when wrapped in other behavior`(): Unit = {
|
||||
"work when wrapped in other behavior" in {
|
||||
// FIXME This is a major problem with current implementation. Since the
|
||||
// behavior is running as an untyped PersistentActor it's not possible to
|
||||
// wrap it in Actor.deferred or Actor.supervise
|
||||
|
|
@ -224,8 +219,6 @@ class PersistentActorSpec extends TypedSpec(PersistentActorSpec.config) with Eve
|
|||
.onFailure(SupervisorStrategy.restartWithBackoff(1.second, 10.seconds, 0.1))
|
||||
val c = start(behavior)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object `A PersistentActor (real, adapted)` extends RealTests with AdaptedSystem
|
||||
}
|
||||
|
|
|
|||
|
|
@ -446,10 +446,3 @@ def akkaModule(name: String): Project =
|
|||
.settings(akka.Formatting.formatSettings)
|
||||
.enablePlugins(BootstrapGenjavadoc)
|
||||
|
||||
lazy val typedTests = taskKey[Unit]("Runs all the typed tests")
|
||||
typedTests := {
|
||||
(test in(actorTyped, Test)).value
|
||||
(test in(actorTypedTests, Test)).value
|
||||
(test in(clusterTyped, Test)).value
|
||||
(test in(clusterShardingTyped, Test)).value
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue