Disallow nested mixed widen usages, #25604

This commit is contained in:
Johan Andrén 2018-09-21 15:24:01 +02:00 committed by Patrik Nordwall
parent 63e00634d4
commit 8c058678ca
2 changed files with 50 additions and 8 deletions

View file

@ -6,12 +6,22 @@ package akka.actor.typed
import java.util.concurrent.atomic.AtomicInteger
import akka.actor.ActorInitializationException
import akka.actor.testkit.typed.scaladsl.ScalaTestWithActorTestKit
import akka.actor.testkit.typed.scaladsl.TestProbe
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.adapter._
import akka.testkit.EventFilter
import org.scalatest.WordSpecLike
class WidenSpec extends ScalaTestWithActorTestKit with WordSpecLike {
import scala.concurrent.duration._
class WidenSpec extends ScalaTestWithActorTestKit(
"""
akka.loggers = [akka.testkit.TestEventListener]
""") with WordSpecLike {
implicit val untypedSystem = system.toUntyped
def intToString(probe: ActorRef[String]): Behavior[Int] = {
Behaviors.receiveMessage[String] { msg
@ -36,11 +46,14 @@ class WidenSpec extends ScalaTestWithActorTestKit with WordSpecLike {
val probe = TestProbe[String]()
val ref = spawn(intToString(probe.ref))
ref ! 42
ref ! 13
ref ! 43
probe.expectMessage("42")
probe.expectMessage("43")
// TestEventListener logs unhandled as warnings, silence that
EventFilter.warning(occurrences = 1).intercept {
ref ! 42
ref ! 13
ref ! 43
probe.expectMessage("42")
probe.expectMessage("43")
}
}
"not build up when the same widen is used many times (initially)" in {
@ -105,6 +118,30 @@ class WidenSpec extends ScalaTestWithActorTestKit with WordSpecLike {
transformCount.get should ===(2)
}
"not allow mixing different widens in the same behavior stack" in {
val probe = TestProbe[String]()
def widen(behavior: Behavior[String]): Behavior[String] =
behavior.widen[String] {
case s s.toLowerCase
}
EventFilter[ActorInitializationException](occurrences = 1).intercept {
val ref = spawn(
widen(
widen(
Behaviors.receiveMessage[String] { msg
Behaviors.same
}
)
)
)
probe.expectTerminated(ref, 3.seconds)
}
}
}
}

View file

@ -138,9 +138,14 @@ private[akka] final case class WidenedInterceptor[O, I](matcher: PartialFunction
import BehaviorInterceptor._
override def isSame(other: BehaviorInterceptor[Any, Any]): Boolean = other match {
// can only be elimintated if it is the same partial function
// If they use the same pf instance we can allow it, to have one way to workaround defining
// "recursive" narrowed behaviors.
case WidenedInterceptor(`matcher`) true
case _ false
case WidenedInterceptor(otherMatcher)
// there is no safe way to allow this
throw new IllegalStateException("Widen can only be used one time in the same behavior stack. " +
s"One defined in ${LineNumbers(matcher)}, and another in ${LineNumbers(otherMatcher)}")
case _ false
}
def aroundReceive(ctx: ActorContext[O], msg: O, target: ReceiveTarget[I]): Behavior[I] = {