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:
Christopher Batey 2017-12-18 15:37:30 +00:00
parent c394ee7aaa
commit 97180eb6ed
34 changed files with 1390 additions and 1360 deletions

View file

@ -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()
);

View file

@ -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;

View file

@ -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
}

View file

@ -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._

View file

@ -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
}

View file

@ -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)
}
}

View file

@ -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
}
}
}

View file

@ -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
}
}

View file

@ -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)
}
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}
}

View file

@ -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
}

View file

@ -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"
}
}

View file

@ -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
}
}

View file

@ -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] {

View file

@ -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

View file

@ -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
}
}
}

View file

@ -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
}
}
}

View file

@ -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

View file

@ -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

View file

@ -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]]

View file

@ -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)
*/

View file

@ -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")
}
}
}

View file

@ -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()
}
}
}

View file

@ -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"))
}
}
}

View file

@ -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
}

View file

@ -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

View file

@ -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])

View file

@ -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")
}
}
}

View file

@ -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)
}
}
}

View file

@ -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)
}
}

View file

@ -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
}

View file

@ -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
}