Fix BehaviorTestKit.signal false alarm in thread check #29779

This commit is contained in:
Alexander Aumann 2020-10-31 23:21:41 +01:00
parent dab8f3b642
commit 3ba5e89433
2 changed files with 87 additions and 67 deletions

View file

@ -145,9 +145,13 @@ private[akka] final class BehaviorTestKitImpl[T](_path: ActorPath, _initialBehav
override def signal(signal: Signal): Unit = {
try {
context.setCurrentActorThread()
currentUncanonical = Behavior.interpretSignal(current, context, signal)
current = Behavior.canonicalize(currentUncanonical, current, context)
} catch handleException
finally {
context.clearCurrentActorThread()
}
}
override def hasEffects(): Boolean = !context.effectQueue.isEmpty

View file

@ -16,7 +16,7 @@ import akka.actor.testkit.typed.{ CapturedLogEvent, Effect }
import akka.actor.testkit.typed.Effect._
import akka.actor.testkit.typed.scaladsl.BehaviorTestKitSpec.{ Child, Parent }
import akka.actor.testkit.typed.scaladsl.BehaviorTestKitSpec.Parent._
import akka.actor.typed.{ ActorRef, Behavior, Props }
import akka.actor.typed.{ ActorRef, Behavior, Props, Terminated }
import akka.actor.typed.receptionist.{ Receptionist, ServiceKey }
import akka.actor.typed.scaladsl.Behaviors
@ -43,75 +43,81 @@ object BehaviorTestKitSpec {
case class Log(what: String) extends Command
case class RegisterWithReceptionist(name: String) extends Command
val init: Behavior[Command] = Behaviors.receive[Command] { (context, message) =>
message match {
case SpawnChild =>
context.spawn(Child.initial, "child")
Behaviors.same
case SpawnChildren(numberOfChildren) if numberOfChildren > 0 =>
0.until(numberOfChildren).foreach { i =>
context.spawn(Child.initial, s"child$i")
}
Behaviors.same
case SpawnChildrenWithProps(numberOfChildren, props) if numberOfChildren > 0 =>
0.until(numberOfChildren).foreach { i =>
context.spawn(Child.initial, s"child$i", props)
}
Behaviors.same
case SpawnAnonymous(numberOfChildren) if numberOfChildren > 0 =>
0.until(numberOfChildren).foreach { _ =>
context.spawnAnonymous(Child.initial)
}
Behaviors.same
case SpawnAnonymousWithProps(numberOfChildren, props) if numberOfChildren > 0 =>
0.until(numberOfChildren).foreach { _ =>
context.spawnAnonymous(Child.initial, props)
}
Behaviors.same
case StopChild(child) =>
context.stop(child)
Behaviors.same
case SpawnAdapter =>
context.spawnMessageAdapter { (r: Reproduce) =>
SpawnAnonymous(r.times)
}
Behaviors.same
case SpawnAdapterWithName(name) =>
context.spawnMessageAdapter({ (r: Reproduce) =>
SpawnAnonymous(r.times)
}, name)
Behaviors.same
case SpawnAndWatchUnwatch(name) =>
val c = context.spawn(Child.initial, name)
context.watch(c)
context.unwatch(c)
Behaviors.same
case m @ SpawnAndWatchWith(name) =>
val c = context.spawn(Child.initial, name)
context.watchWith(c, m)
Behaviors.same
case SpawnSession(replyTo, sessionHandler) =>
val session = context.spawnAnonymous[String](Behaviors.receiveMessage { message =>
sessionHandler ! message
val init: Behavior[Command] = Behaviors
.receive[Command] { (context, message) =>
message match {
case SpawnChild =>
context.spawn(Child.initial, "child")
Behaviors.same
})
replyTo ! session
Behaviors.same
case KillSession(session, replyTo) =>
context.stop(session)
replyTo ! Done
Behaviors.same
case CreateMessageAdapter(messageClass, f) =>
context.messageAdapter(f)(ClassTag(messageClass))
Behaviors.same
case Log(what) =>
context.log.info(what)
Behaviors.same
case RegisterWithReceptionist(name: String) =>
context.system.receptionist ! Receptionist.Register(ServiceKey[Command](name), context.self)
case SpawnChildren(numberOfChildren) if numberOfChildren > 0 =>
0.until(numberOfChildren).foreach { i =>
context.spawn(Child.initial, s"child$i")
}
Behaviors.same
case SpawnChildrenWithProps(numberOfChildren, props) if numberOfChildren > 0 =>
0.until(numberOfChildren).foreach { i =>
context.spawn(Child.initial, s"child$i", props)
}
Behaviors.same
case SpawnAnonymous(numberOfChildren) if numberOfChildren > 0 =>
0.until(numberOfChildren).foreach { _ =>
context.spawnAnonymous(Child.initial)
}
Behaviors.same
case SpawnAnonymousWithProps(numberOfChildren, props) if numberOfChildren > 0 =>
0.until(numberOfChildren).foreach { _ =>
context.spawnAnonymous(Child.initial, props)
}
Behaviors.same
case StopChild(child) =>
context.stop(child)
Behaviors.same
case SpawnAdapter =>
context.spawnMessageAdapter { (r: Reproduce) =>
SpawnAnonymous(r.times)
}
Behaviors.same
case SpawnAdapterWithName(name) =>
context.spawnMessageAdapter({ (r: Reproduce) =>
SpawnAnonymous(r.times)
}, name)
Behaviors.same
case SpawnAndWatchUnwatch(name) =>
val c = context.spawn(Child.initial, name)
context.watch(c)
context.unwatch(c)
Behaviors.same
case m @ SpawnAndWatchWith(name) =>
val c = context.spawn(Child.initial, name)
context.watchWith(c, m)
Behaviors.same
case SpawnSession(replyTo, sessionHandler) =>
val session = context.spawnAnonymous[String](Behaviors.receiveMessage { message =>
sessionHandler ! message
Behaviors.same
})
replyTo ! session
Behaviors.same
case KillSession(session, replyTo) =>
context.stop(session)
replyTo ! Done
Behaviors.same
case CreateMessageAdapter(messageClass, f) =>
context.messageAdapter(f)(ClassTag(messageClass))
Behaviors.same
case Log(what) =>
context.log.info(what)
Behaviors.same
case RegisterWithReceptionist(name: String) =>
context.system.receptionist ! Receptionist.Register(ServiceKey[Command](name), context.self)
Behaviors.same
}
}
.receiveSignal {
case (context, Terminated(_)) =>
context.log.debug("Terminated")
Behaviors.same
}
}
}
object Child {
@ -277,6 +283,16 @@ class BehaviorTestKitSpec extends AnyWordSpec with Matchers with LogCapturing {
}
}
"BehaviorTestKit's signal" must {
"not throw thread validation errors when context log is accessed" in {
val other = TestInbox[String]()
val testkit = BehaviorTestKit[Parent.Command](Parent.init)
noException should be thrownBy {
testkit.signal(Terminated(other.ref))
}
}
}
"BehaviorTestKits watch" must {
"record effects for watching and unwatching" in {
val testkit = BehaviorTestKit(Parent.init)