Typed test kit improvements #23360
* Call right overloaded super method in spawn and spawnAnonymous (avoiding infinite recursion) * Add Effects for each type of Spawning
This commit is contained in:
parent
cc11ed40b5
commit
3b01e08904
2 changed files with 156 additions and 8 deletions
|
|
@ -5,7 +5,7 @@ package akka.typed.testkit
|
|||
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
|
||||
import akka.typed.{ ActorContext, ActorRef, ActorSystem, Behavior, EmptyProps, PostStop, Props, Signal }
|
||||
import akka.typed.{ ActorContext, ActorRef, ActorSystem, Behavior, PostStop, Props, Signal }
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.immutable
|
||||
|
|
@ -20,7 +20,12 @@ import scala.concurrent.duration.{ Duration, FiniteDuration }
|
|||
abstract class Effect
|
||||
|
||||
object Effect {
|
||||
@SerialVersionUID(1L) final case class Spawned(childName: String) extends Effect
|
||||
|
||||
abstract class SpawnedEffect extends Effect
|
||||
|
||||
@SerialVersionUID(1L) final case class Spawned(childName: String, props: Props) extends SpawnedEffect
|
||||
@SerialVersionUID(1L) final case class SpawnedAnonymous(props: Props) extends SpawnedEffect
|
||||
@SerialVersionUID(1L) final case object SpawnedAdapter extends SpawnedEffect
|
||||
@SerialVersionUID(1L) final case class Stopped(childName: String) extends Effect
|
||||
@SerialVersionUID(1L) final case class Watched[T](other: ActorRef[T]) extends Effect
|
||||
@SerialVersionUID(1L) final case class Unwatched[T](other: ActorRef[T]) extends Effect
|
||||
|
|
@ -78,18 +83,23 @@ class EffectfulActorContext[T](_name: String, _initialBehavior: Behavior[T], _ma
|
|||
}
|
||||
|
||||
override def spawnAnonymous[U](behavior: Behavior[U], props: Props = Props.empty): ActorRef[U] = {
|
||||
val ref = super.spawnAnonymous(behavior)
|
||||
effectQueue.offer(Spawned(ref.path.name))
|
||||
val ref = super.spawnAnonymous(behavior, props)
|
||||
effectQueue.offer(SpawnedAnonymous(props))
|
||||
ref
|
||||
}
|
||||
override def spawnAdapter[U](f: U ⇒ T, name: String = ""): ActorRef[U] = {
|
||||
|
||||
override def spawnAdapter[U](f: U ⇒ T): ActorRef[U] = {
|
||||
spawnAdapter(f, "")
|
||||
}
|
||||
|
||||
override def spawnAdapter[U](f: U ⇒ T, name: String): ActorRef[U] = {
|
||||
val ref = super.spawnAdapter(f, name)
|
||||
effectQueue.offer(Spawned(ref.path.name))
|
||||
effectQueue.offer(SpawnedAdapter)
|
||||
ref
|
||||
}
|
||||
override def spawn[U](behavior: Behavior[U], name: String, props: Props = Props.empty): ActorRef[U] = {
|
||||
effectQueue.offer(Spawned(name))
|
||||
super.spawn(behavior, name)
|
||||
effectQueue.offer(Spawned(name, props))
|
||||
super.spawn(behavior, name, props)
|
||||
}
|
||||
override def stop[U](child: ActorRef[U]): Boolean = {
|
||||
effectQueue.offer(Stopped(child.path.name))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* Copyright (C) 2014-2017 Lightbend Inc. <http://www.lightbend.com>
|
||||
*/
|
||||
|
||||
package akka.typed.testkit
|
||||
|
||||
import akka.typed.scaladsl.Actor
|
||||
import akka.typed.testkit.Effect.{ Spawned, SpawnedAdapter, SpawnedAnonymous }
|
||||
import akka.typed.testkit.EffectfulActorContextSpec.Father
|
||||
import akka.typed.testkit.EffectfulActorContextSpec.Father._
|
||||
import akka.typed.{ ActorSystem, Behavior, Props }
|
||||
import org.scalatest.{ FlatSpec, Matchers }
|
||||
|
||||
object EffectfulActorContextSpec {
|
||||
object Father {
|
||||
|
||||
case class Reproduce(times: Int)
|
||||
|
||||
sealed trait Command
|
||||
|
||||
case class SpawnChildren(numberOfChildren: Int) extends Command
|
||||
case class SpawnChildrenWithProps(numberOfChildren: Int, props: Props) extends Command
|
||||
case class SpawnAnonymous(numberOfChildren: Int) extends Command
|
||||
case class SpawnAnonymousWithProps(numberOfChildren: Int, props: Props) extends Command
|
||||
case object SpawnAdapter extends Command
|
||||
case class SpawnAdapterWithName(name: String) extends Command
|
||||
|
||||
def behavior: Behavior[Command] = init()
|
||||
|
||||
def init(): Behavior[Command] = Actor.immutable[Command] { (ctx, msg) ⇒
|
||||
msg match {
|
||||
case SpawnChildren(numberOfChildren) if numberOfChildren > 0 ⇒
|
||||
0.until(numberOfChildren).foreach { i ⇒
|
||||
ctx.spawn(Child.initial, s"child$i")
|
||||
}
|
||||
Actor.same
|
||||
case SpawnChildrenWithProps(numberOfChildren, props) if numberOfChildren > 0 ⇒
|
||||
0.until(numberOfChildren).foreach { i ⇒
|
||||
ctx.spawn(Child.initial, s"child$i", props)
|
||||
}
|
||||
Actor.same
|
||||
case SpawnAnonymous(numberOfChildren) if numberOfChildren > 0 ⇒
|
||||
0.until(numberOfChildren).foreach { _ ⇒
|
||||
ctx.spawnAnonymous(Child.initial)
|
||||
}
|
||||
Actor.same
|
||||
case SpawnAnonymousWithProps(numberOfChildren, props) if numberOfChildren > 0 ⇒
|
||||
0.until(numberOfChildren).foreach { _ ⇒
|
||||
ctx.spawnAnonymous(Child.initial, props)
|
||||
}
|
||||
Actor.same
|
||||
case SpawnAdapter ⇒
|
||||
ctx.spawnAdapter {
|
||||
r: Reproduce ⇒ SpawnAnonymous(r.times)
|
||||
}
|
||||
Actor.same
|
||||
case SpawnAdapterWithName(name) ⇒
|
||||
ctx.spawnAdapter({
|
||||
r: Reproduce ⇒ SpawnAnonymous(r.times)
|
||||
}, name)
|
||||
Actor.same
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Child {
|
||||
|
||||
sealed trait Action
|
||||
|
||||
def initial: Behavior[Action] = Actor.immutable[Action] { (_, msg) ⇒
|
||||
msg match {
|
||||
case _ ⇒
|
||||
Actor.empty
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class EffectfulActorContextSpec extends FlatSpec with Matchers {
|
||||
|
||||
private val props = Props.empty.withMailboxCapacity(10)
|
||||
|
||||
"EffectfulActorContext's spawn" should "create children when no props specified" in {
|
||||
val system = ActorSystem.create(Father.init(), "father-system")
|
||||
val ctx = new EffectfulActorContext[Father.Command]("father-test", Father.init(), 100, system)
|
||||
|
||||
ctx.run(SpawnChildren(2))
|
||||
val effects = ctx.getAllEffects()
|
||||
effects should contain only (Spawned("child0", Props.empty), Spawned("child1", Props.empty))
|
||||
}
|
||||
|
||||
it should "create children when props specified and record effects" in {
|
||||
val system = ActorSystem.create(Father.init(), "father-system")
|
||||
val ctx = new EffectfulActorContext[Father.Command]("father-test", Father.init(), 100, system)
|
||||
|
||||
ctx.run(SpawnChildrenWithProps(2, props))
|
||||
val effects = ctx.getAllEffects()
|
||||
effects should contain only (Spawned("child0", props), Spawned("child1", props))
|
||||
}
|
||||
|
||||
"EffectfulActorContext's spawnAnonymous" should "create children when no props specified and record effects" in {
|
||||
val system = ActorSystem.create(Father.init(), "father-system")
|
||||
val ctx = new EffectfulActorContext[Father.Command]("father-test", Father.init(), 100, system)
|
||||
|
||||
ctx.run(SpawnAnonymous(2))
|
||||
val effects = ctx.getAllEffects()
|
||||
effects shouldBe Seq(SpawnedAnonymous(Props.empty), SpawnedAnonymous(Props.empty))
|
||||
}
|
||||
|
||||
it should "create children when props specified and record effects" in {
|
||||
val system = ActorSystem.create(Father.init(), "father-system")
|
||||
val ctx = new EffectfulActorContext[Father.Command]("father-test", Father.init(), 100, system)
|
||||
|
||||
ctx.run(SpawnAnonymousWithProps(2, props))
|
||||
val effects = ctx.getAllEffects()
|
||||
effects shouldBe Seq(SpawnedAnonymous(props), SpawnedAnonymous(props))
|
||||
}
|
||||
|
||||
"EffectfulActorContext's spawnAdapter" should "create adapters without name and record effects" in {
|
||||
val system = ActorSystem.create(Father.init(), "father-system")
|
||||
val ctx = new EffectfulActorContext[Father.Command]("father-test", Father.init(), 100, system)
|
||||
|
||||
ctx.run(SpawnAdapter)
|
||||
val effects = ctx.getAllEffects()
|
||||
effects shouldBe Seq(SpawnedAdapter)
|
||||
}
|
||||
|
||||
it should "create adapters with name and record effects" in {
|
||||
val system = ActorSystem.create(Father.init(), "father-system")
|
||||
val ctx = new EffectfulActorContext[Father.Command]("father-test", Father.init(), 100, system)
|
||||
|
||||
ctx.run(SpawnAdapterWithName("adapter"))
|
||||
val effects = ctx.getAllEffects()
|
||||
effects shouldBe Seq(SpawnedAdapter)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue