format source with scalafmt
This commit is contained in:
parent
0f40491d42
commit
ce404e4f53
1669 changed files with 43208 additions and 35404 deletions
|
|
@ -17,8 +17,7 @@ import scala.compat.java8.OptionConverters._
|
||||||
/**
|
/**
|
||||||
* Representation of a Log Event issued by a [[akka.actor.typed.Behavior]]
|
* Representation of a Log Event issued by a [[akka.actor.typed.Behavior]]
|
||||||
*/
|
*/
|
||||||
final case class CapturedLogEvent(
|
final case class CapturedLogEvent(logLevel: LogLevel,
|
||||||
logLevel: LogLevel,
|
|
||||||
message: String,
|
message: String,
|
||||||
cause: Option[Throwable],
|
cause: Option[Throwable],
|
||||||
marker: Option[LogMarker],
|
marker: Option[LogMarker],
|
||||||
|
|
@ -27,7 +26,11 @@ final case class CapturedLogEvent(
|
||||||
/**
|
/**
|
||||||
* Constructor for Java API
|
* Constructor for Java API
|
||||||
*/
|
*/
|
||||||
def this(logLevel: LogLevel, message: String, errorCause: Optional[Throwable], marker: Optional[LogMarker], mdc: java.util.Map[String, Any]) {
|
def this(logLevel: LogLevel,
|
||||||
|
message: String,
|
||||||
|
errorCause: Optional[Throwable],
|
||||||
|
marker: Optional[LogMarker],
|
||||||
|
mdc: java.util.Map[String, Any]) {
|
||||||
this(logLevel, message, errorCause.asScala, marker.asScala, mdc.asScala.toMap)
|
this(logLevel, message, errorCause.asScala, marker.asScala, mdc.asScala.toMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,9 +79,7 @@ object CapturedLogEvent {
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
def apply(
|
def apply(logLevel: LogLevel, message: String): CapturedLogEvent = {
|
||||||
logLevel: LogLevel,
|
|
||||||
message: String): CapturedLogEvent = {
|
|
||||||
CapturedLogEvent(logLevel, message, None, None, Map.empty[String, Any])
|
CapturedLogEvent(logLevel, message, None, None, Map.empty[String, Any])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,8 +88,7 @@ object CapturedLogEvent {
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
@InternalApi
|
@InternalApi
|
||||||
private[akka] def apply(
|
private[akka] def apply(logLevel: LogLevel,
|
||||||
logLevel: LogLevel,
|
|
||||||
message: String,
|
message: String,
|
||||||
errorCause: OptionVal[Throwable],
|
errorCause: OptionVal[Throwable],
|
||||||
logMarker: OptionVal[LogMarker],
|
logMarker: OptionVal[LogMarker],
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,14 @@ import scala.concurrent.duration.FiniteDuration
|
||||||
abstract class Effect private[akka] ()
|
abstract class Effect private[akka] ()
|
||||||
|
|
||||||
object Effect {
|
object Effect {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned a named child with the given behavior (and optionally specific props)
|
* The behavior spawned a named child with the given behavior (and optionally specific props)
|
||||||
*/
|
*/
|
||||||
final class Spawned[T](val behavior: Behavior[T], val childName: String, val props: Props, val ref: ActorRef[T])
|
final class Spawned[T](val behavior: Behavior[T], val childName: String, val props: Props, val ref: ActorRef[T])
|
||||||
extends Effect with Product3[Behavior[T], String, Props] with Serializable {
|
extends Effect
|
||||||
|
with Product3[Behavior[T], String, Props]
|
||||||
|
with Serializable {
|
||||||
|
|
||||||
override def equals(other: Any) = other match {
|
override def equals(other: Any) = other match {
|
||||||
case o: Spawned[_] =>
|
case o: Spawned[_] =>
|
||||||
|
|
@ -49,7 +52,8 @@ object Effect {
|
||||||
}
|
}
|
||||||
|
|
||||||
object Spawned {
|
object Spawned {
|
||||||
def apply[T](behavior: Behavior[T], childName: String, props: Props = Props.empty): Spawned[T] = new Spawned(behavior, childName, props, null)
|
def apply[T](behavior: Behavior[T], childName: String, props: Props = Props.empty): Spawned[T] =
|
||||||
|
new Spawned(behavior, childName, props, null)
|
||||||
def unapply[T](s: Spawned[T]): Option[(Behavior[T], String, Props)] = Some((s.behavior, s.childName, s.props))
|
def unapply[T](s: Spawned[T]): Option[(Behavior[T], String, Props)] = Some((s.behavior, s.childName, s.props))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +61,9 @@ object Effect {
|
||||||
* The behavior spawned an anonymous child with the given behavior (and optionally specific props)
|
* The behavior spawned an anonymous child with the given behavior (and optionally specific props)
|
||||||
*/
|
*/
|
||||||
final class SpawnedAnonymous[T](val behavior: Behavior[T], val props: Props, val ref: ActorRef[T])
|
final class SpawnedAnonymous[T](val behavior: Behavior[T], val props: Props, val ref: ActorRef[T])
|
||||||
extends Effect with Product2[Behavior[T], Props] with Serializable {
|
extends Effect
|
||||||
|
with Product2[Behavior[T], Props]
|
||||||
|
with Serializable {
|
||||||
|
|
||||||
override def equals(other: Any) = other match {
|
override def equals(other: Any) = other match {
|
||||||
case o: SpawnedAnonymous[_] => this.behavior == o.behavior && this.props == o.props
|
case o: SpawnedAnonymous[_] => this.behavior == o.behavior && this.props == o.props
|
||||||
|
|
@ -73,7 +79,8 @@ object Effect {
|
||||||
}
|
}
|
||||||
|
|
||||||
object SpawnedAnonymous {
|
object SpawnedAnonymous {
|
||||||
def apply[T](behavior: Behavior[T], props: Props = Props.empty): SpawnedAnonymous[T] = new SpawnedAnonymous(behavior, props, null)
|
def apply[T](behavior: Behavior[T], props: Props = Props.empty): SpawnedAnonymous[T] =
|
||||||
|
new SpawnedAnonymous(behavior, props, null)
|
||||||
def unapply[T](s: SpawnedAnonymous[T]): Option[(Behavior[T], Props)] = Some((s.behavior, s.props))
|
def unapply[T](s: SpawnedAnonymous[T]): Option[(Behavior[T], Props)] = Some((s.behavior, s.props))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,7 +90,9 @@ object Effect {
|
||||||
*/
|
*/
|
||||||
@InternalApi
|
@InternalApi
|
||||||
private[akka] final class SpawnedAdapter[T](val name: String, val ref: ActorRef[T])
|
private[akka] final class SpawnedAdapter[T](val name: String, val ref: ActorRef[T])
|
||||||
extends Effect with Product1[String] with Serializable {
|
extends Effect
|
||||||
|
with Product1[String]
|
||||||
|
with Serializable {
|
||||||
|
|
||||||
override def equals(other: Any) = other match {
|
override def equals(other: Any) = other match {
|
||||||
case o: SpawnedAdapter[_] => this.name == o.name
|
case o: SpawnedAdapter[_] => this.name == o.name
|
||||||
|
|
@ -113,7 +122,9 @@ object Effect {
|
||||||
*/
|
*/
|
||||||
@InternalApi
|
@InternalApi
|
||||||
private[akka] final class SpawnedAnonymousAdapter[T](val ref: ActorRef[T])
|
private[akka] final class SpawnedAnonymousAdapter[T](val ref: ActorRef[T])
|
||||||
extends Effect with Product with Serializable {
|
extends Effect
|
||||||
|
with Product
|
||||||
|
with Serializable {
|
||||||
|
|
||||||
override def equals(other: Any): Boolean = other match {
|
override def equals(other: Any): Boolean = other match {
|
||||||
case _: SpawnedAnonymousAdapter[_] => true
|
case _: SpawnedAnonymousAdapter[_] => true
|
||||||
|
|
@ -142,6 +153,7 @@ object Effect {
|
||||||
* The behavior create a message adapter for the messages of type clazz
|
* The behavior create a message adapter for the messages of type clazz
|
||||||
*/
|
*/
|
||||||
final case class MessageAdapter[A, T](messageClass: Class[A], adapt: A => T) extends Effect {
|
final case class MessageAdapter[A, T](messageClass: Class[A], adapt: A => T) extends Effect {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JAVA API
|
* JAVA API
|
||||||
*/
|
*/
|
||||||
|
|
@ -167,6 +179,7 @@ object Effect {
|
||||||
* The behavior set a new receive timeout, with `message` as timeout notification
|
* The behavior set a new receive timeout, with `message` as timeout notification
|
||||||
*/
|
*/
|
||||||
final case class ReceiveTimeoutSet[T](d: FiniteDuration, message: T) extends Effect {
|
final case class ReceiveTimeoutSet[T](d: FiniteDuration, message: T) extends Effect {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Java API
|
* Java API
|
||||||
*/
|
*/
|
||||||
|
|
@ -195,4 +208,3 @@ object Effect {
|
||||||
*/
|
*/
|
||||||
sealed abstract class NoEffects extends Effect
|
sealed abstract class NoEffects extends Effect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,3 @@ import scala.util.control.NoStackTrace
|
||||||
* A predefined exception that can be used in tests. It doesn't include a stack trace.
|
* A predefined exception that can be used in tests. It doesn't include a stack trace.
|
||||||
*/
|
*/
|
||||||
final case class TestException(message: String) extends RuntimeException(message) with NoStackTrace
|
final case class TestException(message: String) extends RuntimeException(message) with NoStackTrace
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import akka.util.Timeout
|
||||||
import akka.actor.typed.ActorSystem
|
import akka.actor.typed.ActorSystem
|
||||||
|
|
||||||
object TestKitSettings {
|
object TestKitSettings {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads configuration settings from `akka.actor.testkit.typed` section.
|
* Reads configuration settings from `akka.actor.testkit.typed` section.
|
||||||
*/
|
*/
|
||||||
|
|
@ -43,15 +44,19 @@ final class TestKitSettings(val config: Config) {
|
||||||
|
|
||||||
import akka.util.Helpers._
|
import akka.util.Helpers._
|
||||||
|
|
||||||
val TestTimeFactor = config.getDouble("timefactor").
|
val TestTimeFactor = config
|
||||||
requiring(tf => !tf.isInfinite && tf > 0, "timefactor must be positive finite double")
|
.getDouble("timefactor")
|
||||||
|
.requiring(tf => !tf.isInfinite && tf > 0, "timefactor must be positive finite double")
|
||||||
|
|
||||||
/** dilated with `TestTimeFactor` */
|
/** dilated with `TestTimeFactor` */
|
||||||
val SingleExpectDefaultTimeout: FiniteDuration = dilated(config.getMillisDuration("single-expect-default"))
|
val SingleExpectDefaultTimeout: FiniteDuration = dilated(config.getMillisDuration("single-expect-default"))
|
||||||
|
|
||||||
/** dilated with `TestTimeFactor` */
|
/** dilated with `TestTimeFactor` */
|
||||||
val ExpectNoMessageDefaultTimeout: FiniteDuration = dilated(config.getMillisDuration("expect-no-message-default"))
|
val ExpectNoMessageDefaultTimeout: FiniteDuration = dilated(config.getMillisDuration("expect-no-message-default"))
|
||||||
|
|
||||||
/** dilated with `TestTimeFactor` */
|
/** dilated with `TestTimeFactor` */
|
||||||
val DefaultTimeout: Timeout = Timeout(dilated(config.getMillisDuration("default-timeout")))
|
val DefaultTimeout: Timeout = Timeout(dilated(config.getMillisDuration("default-timeout")))
|
||||||
|
|
||||||
/** dilated with `TestTimeFactor` */
|
/** dilated with `TestTimeFactor` */
|
||||||
val DefaultActorSystemShutdownTimeout: FiniteDuration = dilated(config.getMillisDuration("system-shutdown-default"))
|
val DefaultActorSystemShutdownTimeout: FiniteDuration = dilated(config.getMillisDuration("system-shutdown-default"))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,19 @@ package akka.actor.testkit.typed.internal
|
||||||
import java.util.concurrent.{ CompletionStage, ThreadFactory }
|
import java.util.concurrent.{ CompletionStage, ThreadFactory }
|
||||||
|
|
||||||
import akka.actor.typed.internal.ActorRefImpl
|
import akka.actor.typed.internal.ActorRefImpl
|
||||||
import akka.actor.typed.{ ActorRef, ActorSystem, Behavior, DispatcherSelector, Dispatchers, Extension, ExtensionId, Logger, Props, Settings, Terminated }
|
import akka.actor.typed.{
|
||||||
|
ActorRef,
|
||||||
|
ActorSystem,
|
||||||
|
Behavior,
|
||||||
|
DispatcherSelector,
|
||||||
|
Dispatchers,
|
||||||
|
Extension,
|
||||||
|
ExtensionId,
|
||||||
|
Logger,
|
||||||
|
Props,
|
||||||
|
Settings,
|
||||||
|
Terminated
|
||||||
|
}
|
||||||
import akka.annotation.InternalApi
|
import akka.annotation.InternalApi
|
||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
import akka.{ actor => untyped }
|
import akka.{ actor => untyped }
|
||||||
|
|
@ -22,13 +34,17 @@ import akka.actor.typed.internal.InternalRecipientRef
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
@InternalApi private[akka] final class ActorSystemStub(val name: String)
|
@InternalApi private[akka] final class ActorSystemStub(val name: String)
|
||||||
extends ActorSystem[Nothing] with ActorRef[Nothing] with ActorRefImpl[Nothing] with InternalRecipientRef[Nothing] {
|
extends ActorSystem[Nothing]
|
||||||
|
with ActorRef[Nothing]
|
||||||
|
with ActorRefImpl[Nothing]
|
||||||
|
with InternalRecipientRef[Nothing] {
|
||||||
|
|
||||||
override val path: untyped.ActorPath = untyped.RootActorPath(untyped.Address("akka", name)) / "user"
|
override val path: untyped.ActorPath = untyped.RootActorPath(untyped.Address("akka", name)) / "user"
|
||||||
|
|
||||||
override val settings: Settings = new Settings(getClass.getClassLoader, ConfigFactory.empty, name)
|
override val settings: Settings = new Settings(getClass.getClassLoader, ConfigFactory.empty, name)
|
||||||
|
|
||||||
override def tell(message: Nothing): Unit = throw new UnsupportedOperationException("must not send message to ActorSystemStub")
|
override def tell(message: Nothing): Unit =
|
||||||
|
throw new UnsupportedOperationException("must not send message to ActorSystemStub")
|
||||||
|
|
||||||
// impl ActorRefImpl
|
// impl ActorRefImpl
|
||||||
override def isLocal: Boolean = true
|
override def isLocal: Boolean = true
|
||||||
|
|
@ -72,7 +88,8 @@ import akka.actor.typed.internal.InternalRecipientRef
|
||||||
|
|
||||||
override def printTree: String = "no tree for ActorSystemStub"
|
override def printTree: String = "no tree for ActorSystemStub"
|
||||||
|
|
||||||
def systemActorOf[U](behavior: Behavior[U], name: String, props: Props)(implicit timeout: Timeout): Future[ActorRef[U]] = {
|
def systemActorOf[U](behavior: Behavior[U], name: String, props: Props)(
|
||||||
|
implicit timeout: Timeout): Future[ActorRef[U]] = {
|
||||||
Future.failed(new UnsupportedOperationException("ActorSystemStub cannot create system actors"))
|
Future.failed(new UnsupportedOperationException("ActorSystemStub cannot create system actors"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,8 @@ private[akka] final class BehaviorTestKitImpl[T](_path: ActorPath, _initialBehav
|
||||||
def expectEffectClass[E <: Effect](effectClass: Class[E]): E = {
|
def expectEffectClass[E <: Effect](effectClass: Class[E]): E = {
|
||||||
context.effectQueue.poll() match {
|
context.effectQueue.poll() match {
|
||||||
case null if effectClass.isAssignableFrom(NoEffects.getClass) => effectClass.cast(NoEffects)
|
case null if effectClass.isAssignableFrom(NoEffects.getClass) => effectClass.cast(NoEffects)
|
||||||
case null => throw new AssertionError(s"expected: effect type ${effectClass.getName} but no effects were recorded")
|
case null =>
|
||||||
|
throw new AssertionError(s"expected: effect type ${effectClass.getName} but no effects were recorded")
|
||||||
case effect if effectClass.isAssignableFrom(effect.getClass) => effect.asInstanceOf[E]
|
case effect if effectClass.isAssignableFrom(effect.getClass) => effect.asInstanceOf[E]
|
||||||
case other => throw new AssertionError(s"expected: effect class ${effectClass.getName} but found $other")
|
case other => throw new AssertionError(s"expected: effect class ${effectClass.getName} but found $other")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ import akka.actor.typed.internal.InternalRecipientRef
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
@InternalApi private[akka] final class DebugRef[T](override val path: untyped.ActorPath, override val isLocal: Boolean)
|
@InternalApi private[akka] final class DebugRef[T](override val path: untyped.ActorPath, override val isLocal: Boolean)
|
||||||
extends ActorRef[T] with ActorRefImpl[T] with InternalRecipientRef[T] {
|
extends ActorRef[T]
|
||||||
|
with ActorRefImpl[T]
|
||||||
|
with InternalRecipientRef[T] {
|
||||||
|
|
||||||
private val q = new ConcurrentLinkedQueue[Either[SystemMessage, T]]
|
private val q = new ConcurrentLinkedQueue[Either[SystemMessage, T]]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,4 +83,3 @@ import scala.compat.java8.FunctionConverters._
|
||||||
super.scheduleOnce(delay, target, message)
|
super.scheduleOnce(delay, target, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,10 @@ import akka.actor.ActorRefProvider
|
||||||
* This reference cannot watch other references.
|
* This reference cannot watch other references.
|
||||||
*/
|
*/
|
||||||
@InternalApi
|
@InternalApi
|
||||||
private[akka] final class FunctionRef[-T](
|
private[akka] final class FunctionRef[-T](override val path: ActorPath, send: (T, FunctionRef[T]) => Unit)
|
||||||
override val path: ActorPath,
|
extends ActorRef[T]
|
||||||
send: (T, FunctionRef[T]) => Unit)
|
with ActorRefImpl[T]
|
||||||
extends ActorRef[T] with ActorRefImpl[T] with InternalRecipientRef[T] {
|
with InternalRecipientRef[T] {
|
||||||
|
|
||||||
override def tell(message: T): Unit = {
|
override def tell(message: T): Unit = {
|
||||||
if (message == null) throw InvalidMessageException("[null] is not an allowed message")
|
if (message == null) throw InvalidMessageException("[null] is not an allowed message")
|
||||||
|
|
@ -69,9 +69,13 @@ private[akka] final class FunctionRef[-T](
|
||||||
override def isInfoEnabled(marker: LogMarker): Boolean = true
|
override def isInfoEnabled(marker: LogMarker): Boolean = true
|
||||||
override def isDebugEnabled(marker: LogMarker): Boolean = true
|
override def isDebugEnabled(marker: LogMarker): Boolean = true
|
||||||
|
|
||||||
override private[akka] def notifyError(message: String, cause: OptionVal[Throwable], marker: OptionVal[LogMarker]): Unit =
|
override private[akka] def notifyError(message: String,
|
||||||
|
cause: OptionVal[Throwable],
|
||||||
|
marker: OptionVal[LogMarker]): Unit =
|
||||||
logBuffer = CapturedLogEvent(Logging.ErrorLevel, message, cause, marker, mdc) :: logBuffer
|
logBuffer = CapturedLogEvent(Logging.ErrorLevel, message, cause, marker, mdc) :: logBuffer
|
||||||
override private[akka] def notifyWarning(message: String, cause: OptionVal[Throwable], marker: OptionVal[LogMarker]): Unit =
|
override private[akka] def notifyWarning(message: String,
|
||||||
|
cause: OptionVal[Throwable],
|
||||||
|
marker: OptionVal[LogMarker]): Unit =
|
||||||
logBuffer = CapturedLogEvent(Logging.WarningLevel, message, OptionVal.None, marker, mdc) :: logBuffer
|
logBuffer = CapturedLogEvent(Logging.WarningLevel, message, OptionVal.None, marker, mdc) :: logBuffer
|
||||||
|
|
||||||
override private[akka] def notifyInfo(message: String, marker: OptionVal[LogMarker]): Unit =
|
override private[akka] def notifyInfo(message: String, marker: OptionVal[LogMarker]): Unit =
|
||||||
|
|
@ -107,14 +111,18 @@ private[akka] final class FunctionRef[-T](
|
||||||
override def isInfoEnabled(marker: LogMarker): Boolean = actual.isInfoEnabled(marker)
|
override def isInfoEnabled(marker: LogMarker): Boolean = actual.isInfoEnabled(marker)
|
||||||
override def isDebugEnabled(marker: LogMarker): Boolean = actual.isDebugEnabled(marker)
|
override def isDebugEnabled(marker: LogMarker): Boolean = actual.isDebugEnabled(marker)
|
||||||
|
|
||||||
override private[akka] def notifyError(message: String, cause: OptionVal[Throwable], marker: OptionVal[LogMarker]): Unit = {
|
override private[akka] def notifyError(message: String,
|
||||||
|
cause: OptionVal[Throwable],
|
||||||
|
marker: OptionVal[LogMarker]): Unit = {
|
||||||
val original = actual.mdc
|
val original = actual.mdc
|
||||||
actual.mdc = mdc
|
actual.mdc = mdc
|
||||||
actual.notifyError(message, cause, marker)
|
actual.notifyError(message, cause, marker)
|
||||||
actual.mdc = original
|
actual.mdc = original
|
||||||
}
|
}
|
||||||
|
|
||||||
override private[akka] def notifyWarning(message: String, cause: OptionVal[Throwable], marker: OptionVal[LogMarker]): Unit = {
|
override private[akka] def notifyWarning(message: String,
|
||||||
|
cause: OptionVal[Throwable],
|
||||||
|
marker: OptionVal[LogMarker]): Unit = {
|
||||||
val original = actual.mdc
|
val original = actual.mdc
|
||||||
actual.mdc = mdc
|
actual.mdc = mdc
|
||||||
actual.notifyWarning(message, cause, marker)
|
actual.notifyWarning(message, cause, marker)
|
||||||
|
|
@ -147,11 +155,10 @@ private[akka] final class FunctionRef[-T](
|
||||||
* provides only stubs for the effects an Actor can perform and replaces
|
* provides only stubs for the effects an Actor can perform and replaces
|
||||||
* created child Actors by a synchronous Inbox (see `Inbox.sync`).
|
* created child Actors by a synchronous Inbox (see `Inbox.sync`).
|
||||||
*/
|
*/
|
||||||
@InternalApi private[akka] class StubbedActorContext[T](
|
@InternalApi private[akka] class StubbedActorContext[T](val path: ActorPath) extends ActorContextImpl[T] {
|
||||||
val path: ActorPath) extends ActorContextImpl[T] {
|
|
||||||
|
|
||||||
def this(name: String) = {
|
def this(name: String) = {
|
||||||
this(TestInbox.address / name withUid rnd().nextInt())
|
this((TestInbox.address / name).withUid(rnd().nextInt()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -162,24 +169,24 @@ private[akka] final class FunctionRef[-T](
|
||||||
override val self = selfInbox.ref
|
override val self = selfInbox.ref
|
||||||
override val system = new ActorSystemStub("StubbedActorContext")
|
override val system = new ActorSystemStub("StubbedActorContext")
|
||||||
private var _children = TreeMap.empty[String, BehaviorTestKitImpl[_]]
|
private var _children = TreeMap.empty[String, BehaviorTestKitImpl[_]]
|
||||||
private val childName = Iterator from 0 map (Helpers.base64(_))
|
private val childName = Iterator.from(0).map(Helpers.base64(_))
|
||||||
private val loggingAdapter = new StubbedLogger
|
private val loggingAdapter = new StubbedLogger
|
||||||
|
|
||||||
override def children: Iterable[ActorRef[Nothing]] = _children.values map (_.context.self)
|
override def children: Iterable[ActorRef[Nothing]] = _children.values.map(_.context.self)
|
||||||
def childrenNames: Iterable[String] = _children.keys
|
def childrenNames: Iterable[String] = _children.keys
|
||||||
|
|
||||||
override def child(name: String): Option[ActorRef[Nothing]] = _children get name map (_.context.self)
|
override def child(name: String): Option[ActorRef[Nothing]] = _children.get(name).map(_.context.self)
|
||||||
|
|
||||||
override def spawnAnonymous[U](behavior: Behavior[U], props: Props = Props.empty): ActorRef[U] = {
|
override def spawnAnonymous[U](behavior: Behavior[U], props: Props = Props.empty): ActorRef[U] = {
|
||||||
val btk = new BehaviorTestKitImpl[U](path / childName.next() withUid rnd().nextInt(), behavior)
|
val btk = new BehaviorTestKitImpl[U]((path / childName.next()).withUid(rnd().nextInt()), behavior)
|
||||||
_children += btk.context.self.path.name -> btk
|
_children += btk.context.self.path.name -> btk
|
||||||
btk.context.self
|
btk.context.self
|
||||||
}
|
}
|
||||||
override def spawn[U](behavior: Behavior[U], name: String, props: Props = Props.empty): ActorRef[U] =
|
override def spawn[U](behavior: Behavior[U], name: String, props: Props = Props.empty): ActorRef[U] =
|
||||||
_children get name match {
|
_children.get(name) match {
|
||||||
case Some(_) => throw untyped.InvalidActorNameException(s"actor name $name is already taken")
|
case Some(_) => throw untyped.InvalidActorNameException(s"actor name $name is already taken")
|
||||||
case None =>
|
case None =>
|
||||||
val btk = new BehaviorTestKitImpl[U](path / name withUid rnd().nextInt(), behavior)
|
val btk = new BehaviorTestKitImpl[U]((path / name).withUid(rnd().nextInt()), behavior)
|
||||||
_children += name -> btk
|
_children += name -> btk
|
||||||
btk.context.self
|
btk.context.self
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +196,8 @@ private[akka] final class FunctionRef[-T](
|
||||||
* Removal is asynchronous, explicit removeInbox is needed from outside afterwards.
|
* Removal is asynchronous, explicit removeInbox is needed from outside afterwards.
|
||||||
*/
|
*/
|
||||||
override def stop[U](child: ActorRef[U]): Unit = {
|
override def stop[U](child: ActorRef[U]): Unit = {
|
||||||
if (child.path.parent != self.path) throw new IllegalArgumentException(
|
if (child.path.parent != self.path)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
"Only direct children of an actor can be stopped through the actor context, " +
|
"Only direct children of an actor can be stopped through the actor context, " +
|
||||||
s"but [$child] is not a child of [$self]. Stopping other actors has to be expressed as " +
|
s"but [$child] is not a child of [$self]. Stopping other actors has to be expressed as " +
|
||||||
"an explicit stop message that the actor accepts.")
|
"an explicit stop message that the actor accepts.")
|
||||||
|
|
@ -203,7 +211,8 @@ private[akka] final class FunctionRef[-T](
|
||||||
override def setReceiveTimeout(d: FiniteDuration, message: T): Unit = ()
|
override def setReceiveTimeout(d: FiniteDuration, message: T): Unit = ()
|
||||||
override def cancelReceiveTimeout(): Unit = ()
|
override def cancelReceiveTimeout(): Unit = ()
|
||||||
|
|
||||||
override def scheduleOnce[U](delay: FiniteDuration, target: ActorRef[U], message: U): untyped.Cancellable = new untyped.Cancellable {
|
override def scheduleOnce[U](delay: FiniteDuration, target: ActorRef[U], message: U): untyped.Cancellable =
|
||||||
|
new untyped.Cancellable {
|
||||||
override def cancel() = false
|
override def cancel() = false
|
||||||
override def isCancelled = true
|
override def isCancelled = true
|
||||||
}
|
}
|
||||||
|
|
@ -217,13 +226,16 @@ private[akka] final class FunctionRef[-T](
|
||||||
@InternalApi private[akka] def internalSpawnMessageAdapter[U](f: U => T, name: String): ActorRef[U] = {
|
@InternalApi private[akka] def internalSpawnMessageAdapter[U](f: U => T, name: String): ActorRef[U] = {
|
||||||
|
|
||||||
val n = if (name != "") s"${childName.next()}-$name" else childName.next()
|
val n = if (name != "") s"${childName.next()}-$name" else childName.next()
|
||||||
val p = path / n withUid rnd().nextInt()
|
val p = (path / n).withUid(rnd().nextInt())
|
||||||
val i = new BehaviorTestKitImpl[U](p, Behavior.ignore)
|
val i = new BehaviorTestKitImpl[U](p, Behavior.ignore)
|
||||||
_children += p.name -> i
|
_children += p.name -> i
|
||||||
|
|
||||||
new FunctionRef[U](
|
new FunctionRef[U](p, (message, _) => {
|
||||||
p,
|
val m = f(message);
|
||||||
(message, _) => { val m = f(message); if (m != null) { selfInbox.ref ! m; i.selfInbox.ref ! message } })
|
if (m != null) {
|
||||||
|
selfInbox.ref ! m; i.selfInbox.ref ! message
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,10 @@ import scala.concurrent.duration.Duration
|
||||||
@InternalApi
|
@InternalApi
|
||||||
private[akka] object ActorTestKitGuardian {
|
private[akka] object ActorTestKitGuardian {
|
||||||
sealed trait TestKitCommand
|
sealed trait TestKitCommand
|
||||||
final case class SpawnActor[T](name: String, behavior: Behavior[T], replyTo: ActorRef[ActorRef[T]], props: Props) extends TestKitCommand
|
final case class SpawnActor[T](name: String, behavior: Behavior[T], replyTo: ActorRef[ActorRef[T]], props: Props)
|
||||||
final case class SpawnActorAnonymous[T](behavior: Behavior[T], replyTo: ActorRef[ActorRef[T]], props: Props) extends TestKitCommand
|
extends TestKitCommand
|
||||||
|
final case class SpawnActorAnonymous[T](behavior: Behavior[T], replyTo: ActorRef[ActorRef[T]], props: Props)
|
||||||
|
extends TestKitCommand
|
||||||
final case class StopActor[T](ref: ActorRef[T], replyTo: ActorRef[Ack.type]) extends TestKitCommand
|
final case class StopActor[T](ref: ActorRef[T], replyTo: ActorRef[Ack.type]) extends TestKitCommand
|
||||||
final case class ActorStopped[T](replyTo: ActorRef[Ack.type]) extends TestKitCommand
|
final case class ActorStopped[T](replyTo: ActorRef[Ack.type]) extends TestKitCommand
|
||||||
|
|
||||||
|
|
@ -94,12 +96,10 @@ private[akka] object TestKitUtils {
|
||||||
.replaceAll("[^a-zA-Z_0-9]", "_")
|
.replaceAll("[^a-zA-Z_0-9]", "_")
|
||||||
}
|
}
|
||||||
|
|
||||||
def shutdown(
|
def shutdown(system: ActorSystem[_], timeout: Duration, throwIfShutdownTimesOut: Boolean): Unit = {
|
||||||
system: ActorSystem[_],
|
|
||||||
timeout: Duration,
|
|
||||||
throwIfShutdownTimesOut: Boolean): Unit = {
|
|
||||||
system.terminate()
|
system.terminate()
|
||||||
try Await.ready(system.whenTerminated, timeout) catch {
|
try Await.ready(system.whenTerminated, timeout)
|
||||||
|
catch {
|
||||||
case _: TimeoutException =>
|
case _: TimeoutException =>
|
||||||
val message = "Failed to stop [%s] within [%s] \n%s".format(system.name, timeout, system.printTree)
|
val message = "Failed to stop [%s] within [%s] \n%s".format(system.name, timeout, system.printTree)
|
||||||
if (throwIfShutdownTimesOut) throw new RuntimeException(message)
|
if (throwIfShutdownTimesOut) throw new RuntimeException(message)
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ private[akka] object TestProbeImpl {
|
||||||
private case object Stop
|
private case object Stop
|
||||||
|
|
||||||
private def testActor[M](queue: BlockingDeque[M], terminations: BlockingDeque[Terminated]): Behavior[M] =
|
private def testActor[M](queue: BlockingDeque[M], terminations: BlockingDeque[Terminated]): Behavior[M] =
|
||||||
Behaviors.receive[M] { (context, msg) =>
|
Behaviors
|
||||||
|
.receive[M] { (context, msg) =>
|
||||||
msg match {
|
msg match {
|
||||||
case WatchActor(ref) =>
|
case WatchActor(ref) =>
|
||||||
context.watch(ref)
|
context.watch(ref)
|
||||||
|
|
@ -54,7 +55,8 @@ private[akka] object TestProbeImpl {
|
||||||
queue.offerLast(other)
|
queue.offerLast(other)
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
}
|
}
|
||||||
}.receiveSignal {
|
}
|
||||||
|
.receiveSignal {
|
||||||
case (_, t: Terminated) =>
|
case (_, t: Terminated) =>
|
||||||
terminations.offerLast(t)
|
terminations.offerLast(t)
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
|
|
@ -62,7 +64,9 @@ private[akka] object TestProbeImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
@InternalApi
|
@InternalApi
|
||||||
private[akka] final class TestProbeImpl[M](name: String, system: ActorSystem[_]) extends JavaTestProbe[M] with ScalaTestProbe[M] {
|
private[akka] final class TestProbeImpl[M](name: String, system: ActorSystem[_])
|
||||||
|
extends JavaTestProbe[M]
|
||||||
|
with ScalaTestProbe[M] {
|
||||||
|
|
||||||
import TestProbeImpl._
|
import TestProbeImpl._
|
||||||
protected implicit val settings: TestKitSettings = TestKitSettings(system)
|
protected implicit val settings: TestKitSettings = TestKitSettings(system)
|
||||||
|
|
@ -80,7 +84,8 @@ private[akka] final class TestProbeImpl[M](name: String, system: ActorSystem[_])
|
||||||
private val testActor: ActorRef[M] = {
|
private val testActor: ActorRef[M] = {
|
||||||
// FIXME arbitrary timeout?
|
// FIXME arbitrary timeout?
|
||||||
implicit val timeout: Timeout = Timeout(3.seconds)
|
implicit val timeout: Timeout = Timeout(3.seconds)
|
||||||
val futRef = system.systemActorOf(TestProbeImpl.testActor(queue, terminations), s"$name-${testActorId.incrementAndGet()}")
|
val futRef =
|
||||||
|
system.systemActorOf(TestProbeImpl.testActor(queue, terminations), s"$name-${testActorId.incrementAndGet()}")
|
||||||
Await.result(futRef, timeout.duration + 1.second)
|
Await.result(futRef, timeout.duration + 1.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,7 +134,8 @@ private[akka] final class TestProbeImpl[M](name: String, system: ActorSystem[_])
|
||||||
val prevEnd = end
|
val prevEnd = end
|
||||||
end = start + maxDiff
|
end = start + maxDiff
|
||||||
|
|
||||||
val ret = try f finally end = prevEnd
|
val ret = try f
|
||||||
|
finally end = prevEnd
|
||||||
|
|
||||||
val diff = now - start
|
val diff = now - start
|
||||||
assert(min <= diff, s"block took ${diff.pretty}, should at least have been $min")
|
assert(min <= diff, s"block took ${diff.pretty}, should at least have been $min")
|
||||||
|
|
@ -170,8 +176,7 @@ private[akka] final class TestProbeImpl[M](name: String, system: ActorSystem[_])
|
||||||
override def receiveMessage(max: FiniteDuration): M = receiveMessage_internal(max.dilated)
|
override def receiveMessage(max: FiniteDuration): M = receiveMessage_internal(max.dilated)
|
||||||
|
|
||||||
def receiveMessage_internal(max: FiniteDuration): M =
|
def receiveMessage_internal(max: FiniteDuration): M =
|
||||||
receiveOne_internal(max).
|
receiveOne_internal(max).getOrElse(assertFail(s"Timeout ($max) during receiveMessage while waiting for message."))
|
||||||
getOrElse(assertFail(s"Timeout ($max) during receiveMessage while waiting for message."))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receive one message from the internal queue of the TestActor. If the given
|
* Receive one message from the internal queue of the TestActor. If the given
|
||||||
|
|
@ -180,13 +185,11 @@ private[akka] final class TestProbeImpl[M](name: String, system: ActorSystem[_])
|
||||||
* This method does NOT automatically scale its Duration parameter!
|
* This method does NOT automatically scale its Duration parameter!
|
||||||
*/
|
*/
|
||||||
private def receiveOne_internal(max: FiniteDuration): Option[M] = {
|
private def receiveOne_internal(max: FiniteDuration): Option[M] = {
|
||||||
val message = Option(
|
val message = Option(if (max == Duration.Zero) {
|
||||||
if (max == Duration.Zero) {
|
|
||||||
queue.pollFirst
|
queue.pollFirst
|
||||||
} else {
|
} else {
|
||||||
queue.pollFirst(max.length, max.unit)
|
queue.pollFirst(max.length, max.unit)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
lastWasNoMessage = false
|
lastWasNoMessage = false
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
|
|
@ -224,7 +227,7 @@ private[akka] final class TestProbeImpl[M](name: String, system: ActorSystem[_])
|
||||||
val o = receiveOne_internal(max)
|
val o = receiveOne_internal(max)
|
||||||
val bt = BoxedType(c)
|
val bt = BoxedType(c)
|
||||||
o match {
|
o match {
|
||||||
case Some(m) if bt isInstance m => m.asInstanceOf[C]
|
case Some(m) if bt.isInstance(m) => m.asInstanceOf[C]
|
||||||
case Some(m) => assertFail(s"Expected $c, found ${m.getClass} ($m)")
|
case Some(m) => assertFail(s"Expected $c, found ${m.getClass} ($m)")
|
||||||
case None => assertFail(s"Timeout ($max) during expectMessageClass waiting for $c")
|
case None => assertFail(s"Timeout ($max) during expectMessageClass waiting for $c")
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +266,9 @@ private[akka] final class TestProbeImpl[M](name: String, system: ActorSystem[_])
|
||||||
override def fishForMessage(max: JDuration, fisher: java.util.function.Function[M, FishingOutcome]): JList[M] =
|
override def fishForMessage(max: JDuration, fisher: java.util.function.Function[M, FishingOutcome]): JList[M] =
|
||||||
fishForMessage(max, "", fisher)
|
fishForMessage(max, "", fisher)
|
||||||
|
|
||||||
override def fishForMessage(max: JDuration, hint: String, fisher: java.util.function.Function[M, FishingOutcome]): JList[M] =
|
override def fishForMessage(max: JDuration,
|
||||||
|
hint: String,
|
||||||
|
fisher: java.util.function.Function[M, FishingOutcome]): JList[M] =
|
||||||
fishForMessage_internal(max.asScala.dilated, hint, fisher.apply).asJava
|
fishForMessage_internal(max.asScala.dilated, hint, fisher.apply).asJava
|
||||||
|
|
||||||
private def fishForMessage_internal(max: FiniteDuration, hint: String, fisher: M => FishingOutcome): List[M] = {
|
private def fishForMessage_internal(max: FiniteDuration, hint: String, fisher: M => FishingOutcome): List[M] = {
|
||||||
|
|
@ -273,10 +278,12 @@ private[akka] final class TestProbeImpl[M](name: String, system: ActorSystem[_])
|
||||||
maybeMsg match {
|
maybeMsg match {
|
||||||
case Some(message) =>
|
case Some(message) =>
|
||||||
val outcome =
|
val outcome =
|
||||||
try fisher(message) catch {
|
try fisher(message)
|
||||||
case ex: MatchError => throw new AssertionError(
|
catch {
|
||||||
s"Unexpected message $message while fishing for messages, " +
|
case ex: MatchError =>
|
||||||
s"seen messages ${seen.reverse}, hint: $hint", ex)
|
throw new AssertionError(s"Unexpected message $message while fishing for messages, " +
|
||||||
|
s"seen messages ${seen.reverse}, hint: $hint",
|
||||||
|
ex)
|
||||||
}
|
}
|
||||||
outcome match {
|
outcome match {
|
||||||
case FishingOutcome.Complete => (message :: seen).reverse
|
case FishingOutcome.Complete => (message :: seen).reverse
|
||||||
|
|
|
||||||
|
|
@ -89,11 +89,7 @@ object ActorTestKit {
|
||||||
*/
|
*/
|
||||||
def shutdown(system: ActorSystem[_]): Unit = {
|
def shutdown(system: ActorSystem[_]): Unit = {
|
||||||
val settings = TestKitSettings.create(system)
|
val settings = TestKitSettings.create(system)
|
||||||
shutdown(
|
shutdown(system, settings.DefaultActorSystemShutdownTimeout.asJava, settings.ThrowOnShutdownTimeout)
|
||||||
system,
|
|
||||||
settings.DefaultActorSystemShutdownTimeout.asJava,
|
|
||||||
settings.ThrowOnShutdownTimeout
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -136,27 +132,32 @@ final class ActorTestKit private[akka] (delegate: akka.actor.testkit.typed.scala
|
||||||
* Spawn a new auto-named actor under the testkit user guardian and return the ActorRef for the spawned actor
|
* Spawn a new auto-named actor under the testkit user guardian and return the ActorRef for the spawned actor
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T]): ActorRef[T] = delegate.spawn(behavior)
|
def spawn[T](behavior: Behavior[T]): ActorRef[T] = delegate.spawn(behavior)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawn a new named actor under the testkit user guardian and return the ActorRef for the spawned actor,
|
* Spawn a new named actor under the testkit user guardian and return the ActorRef for the spawned actor,
|
||||||
* note that spawning actors with the same name in multiple test cases will cause failures.
|
* note that spawning actors with the same name in multiple test cases will cause failures.
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T], name: String): ActorRef[T] = delegate.spawn(behavior, name)
|
def spawn[T](behavior: Behavior[T], name: String): ActorRef[T] = delegate.spawn(behavior, name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawn a new auto-named actor under the testkit user guardian with the given props
|
* Spawn a new auto-named actor under the testkit user guardian with the given props
|
||||||
* and return the ActorRef for the spawned actor
|
* and return the ActorRef for the spawned actor
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T], props: Props): ActorRef[T] = delegate.spawn(behavior, props)
|
def spawn[T](behavior: Behavior[T], props: Props): ActorRef[T] = delegate.spawn(behavior, props)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spawn a new named actor under the testkit user guardian with the given props and return the ActorRef
|
* Spawn a new named actor under the testkit user guardian with the given props and return the ActorRef
|
||||||
* for the spawned actor, note that spawning actors with the same name in multiple test cases will cause failures.
|
* for the spawned actor, note that spawning actors with the same name in multiple test cases will cause failures.
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T], name: String, props: Props): ActorRef[T] = delegate.spawn(behavior, name, props)
|
def spawn[T](behavior: Behavior[T], name: String, props: Props): ActorRef[T] = delegate.spawn(behavior, name, props)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop the actor under test and wait until it terminates.
|
* Stop the actor under test and wait until it terminates.
|
||||||
* It can only be used for actors that were spawned by this `ActorTestKit`.
|
* It can only be used for actors that were spawned by this `ActorTestKit`.
|
||||||
* Other actors will not be stopped by this method.
|
* Other actors will not be stopped by this method.
|
||||||
*/
|
*/
|
||||||
def stop[T](ref: ActorRef[T]): Unit = delegate.stop(ref)
|
def stop[T](ref: ActorRef[T]): Unit = delegate.stop(ref)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop the actor under test and wait `max` until it terminates.
|
* Stop the actor under test and wait `max` until it terminates.
|
||||||
* It can only be used for actors that were spawned by this `ActorTestKit`.
|
* It can only be used for actors that were spawned by this `ActorTestKit`.
|
||||||
|
|
@ -169,6 +170,7 @@ final class ActorTestKit private[akka] (delegate: akka.actor.testkit.typed.scala
|
||||||
* @tparam M the type of messages the probe should accept
|
* @tparam M the type of messages the probe should accept
|
||||||
*/
|
*/
|
||||||
def createTestProbe[M](): TestProbe[M] = TestProbe.create(system)
|
def createTestProbe[M](): TestProbe[M] = TestProbe.create(system)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut for creating a new test probe for the testkit actor system
|
* Shortcut for creating a new test probe for the testkit actor system
|
||||||
* @tparam M the type of messages the probe should accept
|
* @tparam M the type of messages the probe should accept
|
||||||
|
|
@ -180,6 +182,7 @@ final class ActorTestKit private[akka] (delegate: akka.actor.testkit.typed.scala
|
||||||
* @tparam M the type of messages the probe should accept
|
* @tparam M the type of messages the probe should accept
|
||||||
*/
|
*/
|
||||||
def createTestProbe[M](name: String): TestProbe[M] = TestProbe.create(name, system)
|
def createTestProbe[M](name: String): TestProbe[M] = TestProbe.create(name, system)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut for creating a new named test probe for the testkit actor system
|
* Shortcut for creating a new named test probe for the testkit actor system
|
||||||
* @tparam M the type of messages the probe should accept
|
* @tparam M the type of messages the probe should accept
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@ object BehaviorTestKit {
|
||||||
*/
|
*/
|
||||||
def create[T](initialBehavior: Behavior[T], name: String): BehaviorTestKit[T] = {
|
def create[T](initialBehavior: Behavior[T], name: String): BehaviorTestKit[T] = {
|
||||||
val uid = ThreadLocalRandom.current().nextInt()
|
val uid = ThreadLocalRandom.current().nextInt()
|
||||||
new BehaviorTestKitImpl(address / name withUid (uid), initialBehavior)
|
new BehaviorTestKitImpl((address / name).withUid(uid), initialBehavior)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JAVA API
|
* JAVA API
|
||||||
*/
|
*/
|
||||||
|
|
@ -39,6 +40,7 @@ object BehaviorTestKit {
|
||||||
*/
|
*/
|
||||||
@DoNotInherit
|
@DoNotInherit
|
||||||
abstract class BehaviorTestKit[T] {
|
abstract class BehaviorTestKit[T] {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests the oldest [[Effect]] or [[akka.actor.testkit.typed.javadsl.Effects.noEffects]] if no effects
|
* Requests the oldest [[Effect]] or [[akka.actor.testkit.typed.javadsl.Effects.noEffects]] if no effects
|
||||||
* have taken place. The effect is consumed, subsequent calls won't
|
* have taken place. The effect is consumed, subsequent calls won't
|
||||||
|
|
|
||||||
|
|
@ -20,38 +20,52 @@ object Effects {
|
||||||
* The behavior spawned a named child with the given behavior with no specific props
|
* The behavior spawned a named child with the given behavior with no specific props
|
||||||
*/
|
*/
|
||||||
def spawned[T](behavior: Behavior[T], childName: String): Spawned[T] = Spawned(behavior, childName)
|
def spawned[T](behavior: Behavior[T], childName: String): Spawned[T] = Spawned(behavior, childName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned a named child with the given behavior with no specific props
|
* The behavior spawned a named child with the given behavior with no specific props
|
||||||
*/
|
*/
|
||||||
def spawned[T](behavior: Behavior[T], childName: String, ref: ActorRef[T]): Spawned[T] = new Spawned(behavior, childName, Props.empty, ref)
|
def spawned[T](behavior: Behavior[T], childName: String, ref: ActorRef[T]): Spawned[T] =
|
||||||
|
new Spawned(behavior, childName, Props.empty, ref)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned a named child with the given behavior and specific props
|
* The behavior spawned a named child with the given behavior and specific props
|
||||||
*/
|
*/
|
||||||
def spawned[T](behavior: Behavior[T], childName: String, props: Props): Spawned[T] = Spawned(behavior, childName, props)
|
def spawned[T](behavior: Behavior[T], childName: String, props: Props): Spawned[T] =
|
||||||
|
Spawned(behavior, childName, props)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned a named child with the given behavior and specific props
|
* The behavior spawned a named child with the given behavior and specific props
|
||||||
*/
|
*/
|
||||||
def spawned[T](behavior: Behavior[T], childName: String, props: Props, ref: ActorRef[T]): Spawned[T] = new Spawned(behavior, childName, props, ref)
|
def spawned[T](behavior: Behavior[T], childName: String, props: Props, ref: ActorRef[T]): Spawned[T] =
|
||||||
|
new Spawned(behavior, childName, props, ref)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned an anonymous child with the given behavior with no specific props
|
* The behavior spawned an anonymous child with the given behavior with no specific props
|
||||||
*/
|
*/
|
||||||
def spawnedAnonymous[T](behavior: Behavior[T]): SpawnedAnonymous[T] = SpawnedAnonymous(behavior)
|
def spawnedAnonymous[T](behavior: Behavior[T]): SpawnedAnonymous[T] = SpawnedAnonymous(behavior)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned an anonymous child with the given behavior with no specific props
|
* The behavior spawned an anonymous child with the given behavior with no specific props
|
||||||
*/
|
*/
|
||||||
def spawnedAnonymous[T](behavior: Behavior[T], ref: ActorRef[T]): SpawnedAnonymous[T] = new SpawnedAnonymous(behavior, Props.empty, ref)
|
def spawnedAnonymous[T](behavior: Behavior[T], ref: ActorRef[T]): SpawnedAnonymous[T] =
|
||||||
|
new SpawnedAnonymous(behavior, Props.empty, ref)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned an anonymous child with the given behavior with specific props
|
* The behavior spawned an anonymous child with the given behavior with specific props
|
||||||
*/
|
*/
|
||||||
def spawnedAnonymous[T](behavior: Behavior[T], props: Props): SpawnedAnonymous[T] = SpawnedAnonymous(behavior, props)
|
def spawnedAnonymous[T](behavior: Behavior[T], props: Props): SpawnedAnonymous[T] = SpawnedAnonymous(behavior, props)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned an anonymous child with the given behavior with specific props
|
* The behavior spawned an anonymous child with the given behavior with specific props
|
||||||
*/
|
*/
|
||||||
def spawnedAnonymous[T](behavior: Behavior[T], props: Props, ref: ActorRef[T]): SpawnedAnonymous[T] = new SpawnedAnonymous(behavior, props, ref)
|
def spawnedAnonymous[T](behavior: Behavior[T], props: Props, ref: ActorRef[T]): SpawnedAnonymous[T] =
|
||||||
|
new SpawnedAnonymous(behavior, props, ref)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior stopped `childName`
|
* The behavior stopped `childName`
|
||||||
*/
|
*/
|
||||||
def stopped(childName: String): Stopped = Stopped(childName)
|
def stopped(childName: String): Stopped = Stopped(childName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior started watching `other`, through `context.watch(other)`
|
* The behavior started watching `other`, through `context.watch(other)`
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,9 @@ object ManualTime {
|
||||||
def get[A](system: ActorSystem[A]): ManualTime =
|
def get[A](system: ActorSystem[A]): ManualTime =
|
||||||
system.scheduler match {
|
system.scheduler match {
|
||||||
case sc: akka.testkit.ExplicitlyTriggeredScheduler => new ManualTime(sc)
|
case sc: akka.testkit.ExplicitlyTriggeredScheduler => new ManualTime(sc)
|
||||||
case _ => throw new IllegalArgumentException("ActorSystem not configured with explicitly triggered scheduler, " +
|
case _ =>
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"ActorSystem not configured with explicitly triggered scheduler, " +
|
||||||
"make sure to include akka.actor.testkit.typed.javadsl.ManualTime.config() when setting up the test")
|
"make sure to include akka.actor.testkit.typed.javadsl.ManualTime.config() when setting up the test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ object TestInbox {
|
||||||
|
|
||||||
def create[T](name: String): TestInbox[T] = {
|
def create[T](name: String): TestInbox[T] = {
|
||||||
val uid = ThreadLocalRandom.current().nextInt()
|
val uid = ThreadLocalRandom.current().nextInt()
|
||||||
new TestInboxImpl(address / name withUid (uid))
|
new TestInboxImpl((address / name).withUid(uid))
|
||||||
}
|
}
|
||||||
def create[T](): TestInbox[T] = {
|
def create[T](): TestInbox[T] = {
|
||||||
val uid = ThreadLocalRandom.current().nextInt()
|
val uid = ThreadLocalRandom.current().nextInt()
|
||||||
new TestInboxImpl(address / "inbox" withUid (uid))
|
new TestInboxImpl((address / "inbox").withUid(uid))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,6 +39,7 @@ object TestInbox {
|
||||||
*/
|
*/
|
||||||
@DoNotInherit
|
@DoNotInherit
|
||||||
abstract class TestInbox[T] {
|
abstract class TestInbox[T] {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actor ref of the inbox
|
* The actor ref of the inbox
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ final class TestKitJunitResource(_kit: ActorTestKit) extends ExternalResource {
|
||||||
* Use a custom config for the actor system.
|
* Use a custom config for the actor system.
|
||||||
*/
|
*/
|
||||||
def this(customConfig: String) =
|
def this(customConfig: String) =
|
||||||
this(ActorTestKit.create(
|
this(
|
||||||
TestKitUtils.testNameFromCallStack(classOf[TestKitJunitResource]),
|
ActorTestKit.create(TestKitUtils.testNameFromCallStack(classOf[TestKitJunitResource]),
|
||||||
ConfigFactory.parseString(customConfig)))
|
ConfigFactory.parseString(customConfig)))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -67,14 +67,17 @@ final class TestKitJunitResource(_kit: ActorTestKit) extends ExternalResource {
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def system: ActorSystem[Void] = testKit.system
|
def system: ActorSystem[Void] = testKit.system
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def testKitSettings: TestKitSettings = testKit.testKitSettings
|
def testKitSettings: TestKitSettings = testKit.testKitSettings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def timeout: Timeout = testKit.timeout
|
def timeout: Timeout = testKit.timeout
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
|
|
@ -84,14 +87,17 @@ final class TestKitJunitResource(_kit: ActorTestKit) extends ExternalResource {
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T]): ActorRef[T] = testKit.spawn(behavior)
|
def spawn[T](behavior: Behavior[T]): ActorRef[T] = testKit.spawn(behavior)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T], name: String): ActorRef[T] = testKit.spawn(behavior, name)
|
def spawn[T](behavior: Behavior[T], name: String): ActorRef[T] = testKit.spawn(behavior, name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T], props: Props): ActorRef[T] = testKit.spawn(behavior, props)
|
def spawn[T](behavior: Behavior[T], props: Props): ActorRef[T] = testKit.spawn(behavior, props)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
|
|
@ -101,14 +107,17 @@ final class TestKitJunitResource(_kit: ActorTestKit) extends ExternalResource {
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def createTestProbe[M](): TestProbe[M] = testKit.createTestProbe[M]()
|
def createTestProbe[M](): TestProbe[M] = testKit.createTestProbe[M]()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def createTestProbe[M](clazz: Class[M]): TestProbe[M] = testKit.createTestProbe(clazz)
|
def createTestProbe[M](clazz: Class[M]): TestProbe[M] = testKit.createTestProbe(clazz)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def createTestProbe[M](name: String, clazz: Class[M]): TestProbe[M] = testKit.createTestProbe(name, clazz)
|
def createTestProbe[M](name: String, clazz: Class[M]): TestProbe[M] = testKit.createTestProbe(name, clazz)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import akka.annotation.DoNotInherit
|
||||||
import akka.util.unused
|
import akka.util.unused
|
||||||
|
|
||||||
object FishingOutcomes {
|
object FishingOutcomes {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consume this message and continue with the next
|
* Consume this message and continue with the next
|
||||||
*/
|
*/
|
||||||
|
|
@ -214,7 +215,9 @@ abstract class TestProbe[M] {
|
||||||
/**
|
/**
|
||||||
* Same as the other `fishForMessage` but includes the provided hint in all error messages
|
* Same as the other `fishForMessage` but includes the provided hint in all error messages
|
||||||
*/
|
*/
|
||||||
def fishForMessage(max: Duration, hint: String, fisher: java.util.function.Function[M, FishingOutcome]): java.util.List[M]
|
def fishForMessage(max: Duration,
|
||||||
|
hint: String,
|
||||||
|
fisher: java.util.function.Function[M, FishingOutcome]): java.util.List[M]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expect the given actor to be stopped or stop within the given timeout or
|
* Expect the given actor to be stopped or stop within the given timeout or
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,9 @@ object ActorTestKit {
|
||||||
* the testkit with [[ActorTestKit#shutdownTestKit]].
|
* the testkit with [[ActorTestKit#shutdownTestKit]].
|
||||||
*/
|
*/
|
||||||
def apply(): ActorTestKit =
|
def apply(): ActorTestKit =
|
||||||
new ActorTestKit(
|
new ActorTestKit(name = TestKitUtils.testNameFromCallStack(classOf[ActorTestKit]),
|
||||||
name = TestKitUtils.testNameFromCallStack(classOf[ActorTestKit]),
|
|
||||||
config = noConfigSet,
|
config = noConfigSet,
|
||||||
settings = None
|
settings = None)
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a named testkit.
|
* Create a named testkit.
|
||||||
|
|
@ -44,11 +42,7 @@ object ActorTestKit {
|
||||||
* the testkit with [[ActorTestKit#shutdownTestKit]].
|
* the testkit with [[ActorTestKit#shutdownTestKit]].
|
||||||
*/
|
*/
|
||||||
def apply(name: String): ActorTestKit =
|
def apply(name: String): ActorTestKit =
|
||||||
new ActorTestKit(
|
new ActorTestKit(name = TestKitUtils.scrubActorSystemName(name), config = noConfigSet, settings = None)
|
||||||
name = TestKitUtils.scrubActorSystemName(name),
|
|
||||||
config = noConfigSet,
|
|
||||||
settings = None
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a named testkit, and use a custom config for the actor system.
|
* Create a named testkit, and use a custom config for the actor system.
|
||||||
|
|
@ -59,11 +53,7 @@ object ActorTestKit {
|
||||||
* the testkit with [[ActorTestKit#shutdownTestKit]].
|
* the testkit with [[ActorTestKit#shutdownTestKit]].
|
||||||
*/
|
*/
|
||||||
def apply(name: String, customConfig: Config): ActorTestKit =
|
def apply(name: String, customConfig: Config): ActorTestKit =
|
||||||
new ActorTestKit(
|
new ActorTestKit(name = TestKitUtils.scrubActorSystemName(name), config = customConfig, settings = None)
|
||||||
name = TestKitUtils.scrubActorSystemName(name),
|
|
||||||
config = customConfig,
|
|
||||||
settings = None
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a named testkit, and use a custom config for the actor system,
|
* Create a named testkit, and use a custom config for the actor system,
|
||||||
|
|
@ -75,11 +65,7 @@ object ActorTestKit {
|
||||||
* the testkit with [[ActorTestKit#shutdownTestKit]].
|
* the testkit with [[ActorTestKit#shutdownTestKit]].
|
||||||
*/
|
*/
|
||||||
def apply(name: String, customConfig: Config, settings: TestKitSettings): ActorTestKit =
|
def apply(name: String, customConfig: Config, settings: TestKitSettings): ActorTestKit =
|
||||||
new ActorTestKit(
|
new ActorTestKit(name = TestKitUtils.scrubActorSystemName(name), config = customConfig, settings = Some(settings))
|
||||||
name = TestKitUtils.scrubActorSystemName(name),
|
|
||||||
config = customConfig,
|
|
||||||
settings = Some(settings)
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shutdown the given [[akka.actor.typed.ActorSystem]] and block until it shuts down,
|
* Shutdown the given [[akka.actor.typed.ActorSystem]] and block until it shuts down,
|
||||||
|
|
@ -87,21 +73,14 @@ object ActorTestKit {
|
||||||
*/
|
*/
|
||||||
def shutdown(system: ActorSystem[_]): Unit = {
|
def shutdown(system: ActorSystem[_]): Unit = {
|
||||||
val settings = TestKitSettings(system)
|
val settings = TestKitSettings(system)
|
||||||
TestKitUtils.shutdown(
|
TestKitUtils.shutdown(system, settings.DefaultActorSystemShutdownTimeout, settings.ThrowOnShutdownTimeout)
|
||||||
system,
|
|
||||||
settings.DefaultActorSystemShutdownTimeout,
|
|
||||||
settings.ThrowOnShutdownTimeout
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shutdown the given [[akka.actor.typed.ActorSystem]] and block until it shuts down
|
* Shutdown the given [[akka.actor.typed.ActorSystem]] and block until it shuts down
|
||||||
* or the `duration` hits. If the timeout hits `verifySystemShutdown` decides
|
* or the `duration` hits. If the timeout hits `verifySystemShutdown` decides
|
||||||
*/
|
*/
|
||||||
def shutdown(
|
def shutdown(system: ActorSystem[_], timeout: Duration, throwIfShutdownFails: Boolean = false): Unit =
|
||||||
system: ActorSystem[_],
|
|
||||||
timeout: Duration,
|
|
||||||
throwIfShutdownFails: Boolean = false): Unit =
|
|
||||||
TestKitUtils.shutdown(system, timeout, throwIfShutdownFails)
|
TestKitUtils.shutdown(system, timeout, throwIfShutdownFails)
|
||||||
|
|
||||||
// place holder for no custom config specified to avoid the boilerplate
|
// place holder for no custom config specified to avoid the boilerplate
|
||||||
|
|
@ -140,11 +119,9 @@ final class ActorTestKit private[akka] (val name: String, val config: Config, se
|
||||||
implicit val timeout: Timeout = testKitSettings.DefaultTimeout
|
implicit val timeout: Timeout = testKitSettings.DefaultTimeout
|
||||||
|
|
||||||
def shutdownTestKit(): Unit = {
|
def shutdownTestKit(): Unit = {
|
||||||
ActorTestKit.shutdown(
|
ActorTestKit.shutdown(system,
|
||||||
system,
|
|
||||||
testKitSettings.DefaultActorSystemShutdownTimeout,
|
testKitSettings.DefaultActorSystemShutdownTimeout,
|
||||||
testKitSettings.ThrowOnShutdownTimeout
|
testKitSettings.ThrowOnShutdownTimeout)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -180,8 +157,11 @@ final class ActorTestKit private[akka] (val name: String, val config: Config, se
|
||||||
* It can only be used for actors that were spawned by this `ActorTestKit`.
|
* It can only be used for actors that were spawned by this `ActorTestKit`.
|
||||||
* Other actors will not be stopped by this method.
|
* Other actors will not be stopped by this method.
|
||||||
*/
|
*/
|
||||||
def stop[T](ref: ActorRef[T], max: FiniteDuration = timeout.duration): Unit = try {
|
def stop[T](ref: ActorRef[T], max: FiniteDuration = timeout.duration): Unit =
|
||||||
Await.result(internalSystem.ask { x: ActorRef[ActorTestKitGuardian.Ack.type] => ActorTestKitGuardian.StopActor(ref, x) }, max)
|
try {
|
||||||
|
Await.result(internalSystem.ask { x: ActorRef[ActorTestKitGuardian.Ack.type] =>
|
||||||
|
ActorTestKitGuardian.StopActor(ref, x)
|
||||||
|
}, max)
|
||||||
} catch {
|
} catch {
|
||||||
case _: TimeoutException =>
|
case _: TimeoutException =>
|
||||||
assert(false, s"timeout ($max) during stop() waiting for actor [${ref.path}] to stop")
|
assert(false, s"timeout ($max) during stop() waiting for actor [${ref.path}] to stop")
|
||||||
|
|
|
||||||
|
|
@ -54,14 +54,17 @@ abstract class ActorTestKitBase(val testKit: ActorTestKit) {
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
implicit def system: ActorSystem[Nothing] = testKit.system
|
implicit def system: ActorSystem[Nothing] = testKit.system
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
implicit def testKitSettings: TestKitSettings = testKit.testKitSettings
|
implicit def testKitSettings: TestKitSettings = testKit.testKitSettings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
implicit def timeout: Timeout = testKit.timeout
|
implicit def timeout: Timeout = testKit.timeout
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
|
|
@ -71,14 +74,17 @@ abstract class ActorTestKitBase(val testKit: ActorTestKit) {
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T]): ActorRef[T] = testKit.spawn(behavior)
|
def spawn[T](behavior: Behavior[T]): ActorRef[T] = testKit.spawn(behavior)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T], name: String): ActorRef[T] = testKit.spawn(behavior, name)
|
def spawn[T](behavior: Behavior[T], name: String): ActorRef[T] = testKit.spawn(behavior, name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def spawn[T](behavior: Behavior[T], props: Props): ActorRef[T] = testKit.spawn(behavior, props)
|
def spawn[T](behavior: Behavior[T], props: Props): ActorRef[T] = testKit.spawn(behavior, props)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
|
|
@ -88,6 +94,7 @@ abstract class ActorTestKitBase(val testKit: ActorTestKit) {
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
def createTestProbe[M](): TestProbe[M] = testKit.createTestProbe[M]()
|
def createTestProbe[M](): TestProbe[M] = testKit.createTestProbe[M]()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See corresponding method on [[ActorTestKit]]
|
* See corresponding method on [[ActorTestKit]]
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ object BehaviorTestKit {
|
||||||
|
|
||||||
def apply[T](initialBehavior: Behavior[T], name: String): BehaviorTestKit[T] = {
|
def apply[T](initialBehavior: Behavior[T], name: String): BehaviorTestKit[T] = {
|
||||||
val uid = ThreadLocalRandom.current().nextInt()
|
val uid = ThreadLocalRandom.current().nextInt()
|
||||||
new BehaviorTestKitImpl(address / name withUid (uid), initialBehavior)
|
new BehaviorTestKitImpl((address / name).withUid(uid), initialBehavior)
|
||||||
}
|
}
|
||||||
def apply[T](initialBehavior: Behavior[T]): BehaviorTestKit[T] =
|
def apply[T](initialBehavior: Behavior[T]): BehaviorTestKit[T] =
|
||||||
apply(initialBehavior, "testkit")
|
apply(initialBehavior, "testkit")
|
||||||
|
|
|
||||||
|
|
@ -19,38 +19,52 @@ object Effects {
|
||||||
* The behavior spawned a named child with the given behavior with no specific props
|
* The behavior spawned a named child with the given behavior with no specific props
|
||||||
*/
|
*/
|
||||||
def spawned[T](behavior: Behavior[T], childName: String): Spawned[T] = Spawned(behavior, childName)
|
def spawned[T](behavior: Behavior[T], childName: String): Spawned[T] = Spawned(behavior, childName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned a named child with the given behavior with no specific props
|
* The behavior spawned a named child with the given behavior with no specific props
|
||||||
*/
|
*/
|
||||||
def spawned[T](behavior: Behavior[T], childName: String, ref: ActorRef[T]): Spawned[T] = new Spawned(behavior, childName, Props.empty, ref)
|
def spawned[T](behavior: Behavior[T], childName: String, ref: ActorRef[T]): Spawned[T] =
|
||||||
|
new Spawned(behavior, childName, Props.empty, ref)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned a named child with the given behavior and specific props
|
* The behavior spawned a named child with the given behavior and specific props
|
||||||
*/
|
*/
|
||||||
def spawned[T](behavior: Behavior[T], childName: String, props: Props): Spawned[T] = Spawned(behavior, childName, props)
|
def spawned[T](behavior: Behavior[T], childName: String, props: Props): Spawned[T] =
|
||||||
|
Spawned(behavior, childName, props)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned a named child with the given behavior and specific props
|
* The behavior spawned a named child with the given behavior and specific props
|
||||||
*/
|
*/
|
||||||
def spawned[T](behavior: Behavior[T], childName: String, props: Props, ref: ActorRef[T]): Spawned[T] = new Spawned(behavior, childName, props, ref)
|
def spawned[T](behavior: Behavior[T], childName: String, props: Props, ref: ActorRef[T]): Spawned[T] =
|
||||||
|
new Spawned(behavior, childName, props, ref)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned an anonymous child with the given behavior with no specific props
|
* The behavior spawned an anonymous child with the given behavior with no specific props
|
||||||
*/
|
*/
|
||||||
def spawnedAnonymous[T](behavior: Behavior[T]): SpawnedAnonymous[T] = SpawnedAnonymous(behavior)
|
def spawnedAnonymous[T](behavior: Behavior[T]): SpawnedAnonymous[T] = SpawnedAnonymous(behavior)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned an anonymous child with the given behavior with no specific props
|
* The behavior spawned an anonymous child with the given behavior with no specific props
|
||||||
*/
|
*/
|
||||||
def spawnedAnonymous[T](behavior: Behavior[T], ref: ActorRef[T]): SpawnedAnonymous[T] = new SpawnedAnonymous(behavior, Props.empty, ref)
|
def spawnedAnonymous[T](behavior: Behavior[T], ref: ActorRef[T]): SpawnedAnonymous[T] =
|
||||||
|
new SpawnedAnonymous(behavior, Props.empty, ref)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned an anonymous child with the given behavior with specific props
|
* The behavior spawned an anonymous child with the given behavior with specific props
|
||||||
*/
|
*/
|
||||||
def spawnedAnonymous[T](behavior: Behavior[T], props: Props): SpawnedAnonymous[T] = SpawnedAnonymous(behavior, props)
|
def spawnedAnonymous[T](behavior: Behavior[T], props: Props): SpawnedAnonymous[T] = SpawnedAnonymous(behavior, props)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior spawned an anonymous child with the given behavior with specific props
|
* The behavior spawned an anonymous child with the given behavior with specific props
|
||||||
*/
|
*/
|
||||||
def spawnedAnonymous[T](behavior: Behavior[T], props: Props, ref: ActorRef[T]): SpawnedAnonymous[T] = new SpawnedAnonymous(behavior, props, ref)
|
def spawnedAnonymous[T](behavior: Behavior[T], props: Props, ref: ActorRef[T]): SpawnedAnonymous[T] =
|
||||||
|
new SpawnedAnonymous(behavior, props, ref)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior stopped `childName`
|
* The behavior stopped `childName`
|
||||||
*/
|
*/
|
||||||
def stopped(childName: String): Stopped = Stopped(childName)
|
def stopped(childName: String): Stopped = Stopped(childName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The behavior started watching `other`, through `context.watch(other)`
|
* The behavior started watching `other`, through `context.watch(other)`
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,12 @@ import scala.concurrent.duration.{ Duration, FiniteDuration }
|
||||||
* scheduler control through [[ManualTime.apply()]]
|
* scheduler control through [[ManualTime.apply()]]
|
||||||
*/
|
*/
|
||||||
object ManualTime {
|
object ManualTime {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config needed to use the `ExplicitlyTriggeredScheduler`
|
* Config needed to use the `ExplicitlyTriggeredScheduler`
|
||||||
*/
|
*/
|
||||||
val config: Config = ConfigFactory.parseString("""akka.scheduler.implementation = "akka.testkit.ExplicitlyTriggeredScheduler"""")
|
val config: Config =
|
||||||
|
ConfigFactory.parseString("""akka.scheduler.implementation = "akka.testkit.ExplicitlyTriggeredScheduler"""")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access the manual scheduler, note that you need to setup the actor system/testkit with [[config()]] for this to
|
* Access the manual scheduler, note that you need to setup the actor system/testkit with [[config()]] for this to
|
||||||
|
|
@ -29,7 +31,9 @@ object ManualTime {
|
||||||
def apply()(implicit system: ActorSystem[_]): ManualTime =
|
def apply()(implicit system: ActorSystem[_]): ManualTime =
|
||||||
system.scheduler match {
|
system.scheduler match {
|
||||||
case sc: akka.testkit.ExplicitlyTriggeredScheduler => new ManualTime(sc)
|
case sc: akka.testkit.ExplicitlyTriggeredScheduler => new ManualTime(sc)
|
||||||
case _ => throw new IllegalArgumentException("ActorSystem not configured with explicitly triggered scheduler, " +
|
case _ =>
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"ActorSystem not configured with explicitly triggered scheduler, " +
|
||||||
"make sure to include akka.actor.testkit.typed.scaladsl.ManualTime.config() when setting up the test")
|
"make sure to include akka.actor.testkit.typed.scaladsl.ManualTime.config() when setting up the test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,13 @@ import org.scalatest.time.Span
|
||||||
* Note that ScalaTest is not provided as a transitive dependency of the testkit module but must be added explicitly
|
* Note that ScalaTest is not provided as a transitive dependency of the testkit module but must be added explicitly
|
||||||
* to your project to use this.
|
* to your project to use this.
|
||||||
*/
|
*/
|
||||||
abstract class ScalaTestWithActorTestKit(testKit: ActorTestKit) extends ActorTestKitBase(testKit)
|
abstract class ScalaTestWithActorTestKit(testKit: ActorTestKit)
|
||||||
with TestSuite with Matchers with BeforeAndAfterAll with ScalaFutures with Eventually {
|
extends ActorTestKitBase(testKit)
|
||||||
|
with TestSuite
|
||||||
|
with Matchers
|
||||||
|
with BeforeAndAfterAll
|
||||||
|
with ScalaFutures
|
||||||
|
with Eventually {
|
||||||
|
|
||||||
def this() = this(ActorTestKit(ActorTestKitBase.testNameFromCallStack()))
|
def this() = this(ActorTestKit(ActorTestKitBase.testNameFromCallStack()))
|
||||||
|
|
||||||
|
|
@ -57,4 +62,3 @@ abstract class ScalaTestWithActorTestKit(testKit: ActorTestKit) extends ActorTes
|
||||||
testKit.shutdownTestKit()
|
testKit.shutdownTestKit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import scala.collection.immutable
|
||||||
object TestInbox {
|
object TestInbox {
|
||||||
def apply[T](name: String = "inbox"): TestInbox[T] = {
|
def apply[T](name: String = "inbox"): TestInbox[T] = {
|
||||||
val uid = ThreadLocalRandom.current().nextInt()
|
val uid = ThreadLocalRandom.current().nextInt()
|
||||||
new TestInboxImpl(address / name withUid uid)
|
new TestInboxImpl((address / name).withUid(uid))
|
||||||
}
|
}
|
||||||
|
|
||||||
private[akka] val address = RootActorPath(Address("akka.actor.typed.inbox", "anonymous"))
|
private[akka] val address = RootActorPath(Address("akka.actor.typed.inbox", "anonymous"))
|
||||||
|
|
@ -36,6 +36,7 @@ object TestInbox {
|
||||||
*/
|
*/
|
||||||
@DoNotInherit
|
@DoNotInherit
|
||||||
trait TestInbox[T] {
|
trait TestInbox[T] {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actor ref of the inbox
|
* The actor ref of the inbox
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,22 @@ import akka.actor.typed.ActorSystem
|
||||||
import akka.annotation.DoNotInherit
|
import akka.annotation.DoNotInherit
|
||||||
|
|
||||||
object FishingOutcomes {
|
object FishingOutcomes {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Complete fishing and return all messages up until this
|
* Complete fishing and return all messages up until this
|
||||||
*/
|
*/
|
||||||
val complete: FishingOutcome = FishingOutcome.Complete
|
val complete: FishingOutcome = FishingOutcome.Complete
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consume this message, collect it into the result, and continue with the next message
|
* Consume this message, collect it into the result, and continue with the next message
|
||||||
*/
|
*/
|
||||||
val continue: FishingOutcome = FishingOutcome.Continue
|
val continue: FishingOutcome = FishingOutcome.Continue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consume this message, but do not collect it into the result, and continue with the next message
|
* Consume this message, but do not collect it into the result, and continue with the next message
|
||||||
*/
|
*/
|
||||||
val continueAndIgnore: FishingOutcome = FishingOutcome.ContinueAndIgnore
|
val continueAndIgnore: FishingOutcome = FishingOutcome.ContinueAndIgnore
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fail fishing with a custom error message
|
* Fail fishing with a custom error message
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,7 @@ class ActorTestKitSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
||||||
val testkit2 = ActorTestKit()
|
val testkit2 = ActorTestKit()
|
||||||
try {
|
try {
|
||||||
testkit2.system.name should ===("ActorTestKitSpec")
|
testkit2.system.name should ===("ActorTestKitSpec")
|
||||||
} finally
|
} finally testkit2.shutdownTestKit()
|
||||||
testkit2.shutdownTestKit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"use name from given class name" in {
|
"use name from given class name" in {
|
||||||
|
|
@ -34,8 +33,7 @@ class ActorTestKitSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
||||||
try {
|
try {
|
||||||
// removing package name and such
|
// removing package name and such
|
||||||
testkit2.system.name should ===("Vector")
|
testkit2.system.name should ===("Vector")
|
||||||
} finally
|
} finally testkit2.shutdownTestKit()
|
||||||
testkit2.shutdownTestKit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"spawn an actor" in {
|
"spawn an actor" in {
|
||||||
|
|
@ -81,16 +79,14 @@ class MyConcreteDerivateSpec extends MyBaseSpec {
|
||||||
val testkit2 = ActorTestKit()
|
val testkit2 = ActorTestKit()
|
||||||
try {
|
try {
|
||||||
testkit2.system.name should ===("MyConcreteDerivateSpec")
|
testkit2.system.name should ===("MyConcreteDerivateSpec")
|
||||||
} finally
|
} finally testkit2.shutdownTestKit()
|
||||||
testkit2.shutdownTestKit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"use name from given class name" in {
|
"use name from given class name" in {
|
||||||
val testkit2 = ActorTestKit(classOf[Vector[_]].getName)
|
val testkit2 = ActorTestKit(classOf[Vector[_]].getName)
|
||||||
try {
|
try {
|
||||||
testkit2.system.name should ===("Vector")
|
testkit2.system.name should ===("Vector")
|
||||||
} finally
|
} finally testkit2.shutdownTestKit()
|
||||||
testkit2.shutdownTestKit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,4 +103,3 @@ class CompositionSpec extends WordSpec with Matchers with BeforeAndAfterAll {
|
||||||
testKit.system.name should ===("CompositionSpec")
|
testKit.system.name should ===("CompositionSpec")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,13 +67,13 @@ object BehaviorTestKitSpec {
|
||||||
context.stop(child)
|
context.stop(child)
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case SpawnAdapter =>
|
case SpawnAdapter =>
|
||||||
context.spawnMessageAdapter {
|
context.spawnMessageAdapter { r: Reproduce =>
|
||||||
r: Reproduce => SpawnAnonymous(r.times)
|
SpawnAnonymous(r.times)
|
||||||
}
|
}
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case SpawnAdapterWithName(name) =>
|
case SpawnAdapterWithName(name) =>
|
||||||
context.spawnMessageAdapter({
|
context.spawnMessageAdapter({ r: Reproduce =>
|
||||||
r: Reproduce => SpawnAnonymous(r.times)
|
SpawnAnonymous(r.times)
|
||||||
}, name)
|
}, name)
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case SpawnAndWatchUnwatch(name) =>
|
case SpawnAndWatchUnwatch(name) =>
|
||||||
|
|
@ -253,7 +253,7 @@ class BehaviorTestKitSpec extends WordSpec with Matchers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"BehaviorTestkit's run" can {
|
"BehaviorTestkit's run".can {
|
||||||
"run behaviors with messages without canonicalization" in {
|
"run behaviors with messages without canonicalization" in {
|
||||||
val testkit = BehaviorTestKit[Father.Command](Father.init)
|
val testkit = BehaviorTestKit[Father.Command](Father.init)
|
||||||
testkit.run(SpawnAdapterWithName("adapter"))
|
testkit.run(SpawnAdapterWithName("adapter"))
|
||||||
|
|
@ -267,21 +267,16 @@ class BehaviorTestKitSpec extends WordSpec with Matchers {
|
||||||
val testkit = BehaviorTestKit(Father.init)
|
val testkit = BehaviorTestKit(Father.init)
|
||||||
testkit.run(SpawnAndWatchUnwatch("hello"))
|
testkit.run(SpawnAndWatchUnwatch("hello"))
|
||||||
val child = testkit.childInbox("hello").ref
|
val child = testkit.childInbox("hello").ref
|
||||||
testkit.retrieveAllEffects() should be(Seq(
|
testkit.retrieveAllEffects() should be(
|
||||||
Effects.spawned(Child.initial, "hello", Props.empty),
|
Seq(Effects.spawned(Child.initial, "hello", Props.empty), Effects.watched(child), Effects.unwatched(child)))
|
||||||
Effects.watched(child),
|
|
||||||
Effects.unwatched(child)
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"record effects for watchWith" in {
|
"record effects for watchWith" in {
|
||||||
val testkit = BehaviorTestKit(Father.init)
|
val testkit = BehaviorTestKit(Father.init)
|
||||||
testkit.run(SpawnAndWatchWith("hello"))
|
testkit.run(SpawnAndWatchWith("hello"))
|
||||||
val child = testkit.childInbox("hello").ref
|
val child = testkit.childInbox("hello").ref
|
||||||
testkit.retrieveAllEffects() should be(Seq(
|
testkit.retrieveAllEffects() should be(
|
||||||
Effects.spawned(Child.initial, "hello", Props.empty),
|
Seq(Effects.spawned(Child.initial, "hello", Props.empty), Effects.watched(child)))
|
||||||
Effects.watched(child)
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,8 @@ class TestProbeSpec extends ScalaTestWithActorTestKit with WordSpecLike {
|
||||||
Behaviors.withTimers { (timer) =>
|
Behaviors.withTimers { (timer) =>
|
||||||
timer.startSingleTimer("key", Stop, 300.millis)
|
timer.startSingleTimer("key", Stop, 300.millis)
|
||||||
|
|
||||||
Behaviors.receive((context, stop) =>
|
Behaviors.receive((context, stop) => Behaviors.stopped)
|
||||||
Behaviors.stopped
|
}))
|
||||||
)
|
|
||||||
}
|
|
||||||
))
|
|
||||||
ref ! Stop
|
ref ! Stop
|
||||||
// race, but not sure how to test in any other way
|
// race, but not sure how to test in any other way
|
||||||
probe.expectTerminated(ref, 500.millis)
|
probe.expectTerminated(ref, 500.millis)
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,10 @@ object ActorConfigurationVerificationSpec {
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
class ActorConfigurationVerificationSpec extends AkkaSpec(ActorConfigurationVerificationSpec.config) with DefaultTimeout with BeforeAndAfterEach {
|
class ActorConfigurationVerificationSpec
|
||||||
|
extends AkkaSpec(ActorConfigurationVerificationSpec.config)
|
||||||
|
with DefaultTimeout
|
||||||
|
with BeforeAndAfterEach {
|
||||||
import ActorConfigurationVerificationSpec._
|
import ActorConfigurationVerificationSpec._
|
||||||
|
|
||||||
override def atStartup: Unit = {
|
override def atStartup: Unit = {
|
||||||
|
|
@ -64,8 +67,10 @@ class ActorConfigurationVerificationSpec extends AkkaSpec(ActorConfigurationVeri
|
||||||
}
|
}
|
||||||
"fail verification with a ConfigurationException if also configured with a ScatterGatherFirstCompletedPool" in {
|
"fail verification with a ConfigurationException if also configured with a ScatterGatherFirstCompletedPool" in {
|
||||||
intercept[ConfigurationException] {
|
intercept[ConfigurationException] {
|
||||||
system.actorOf(ScatterGatherFirstCompletedPool(nrOfInstances = 2, within = 2 seconds).
|
system.actorOf(
|
||||||
withDispatcher("balancing-dispatcher").props(Props[TestActor]))
|
ScatterGatherFirstCompletedPool(nrOfInstances = 2, within = 2 seconds)
|
||||||
|
.withDispatcher("balancing-dispatcher")
|
||||||
|
.props(Props[TestActor]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"not fail verification with a ConfigurationException also not configured with a Router" in {
|
"not fail verification with a ConfigurationException also not configured with a Router" in {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ package akka.actor
|
||||||
|
|
||||||
import scala.language.postfixOps
|
import scala.language.postfixOps
|
||||||
|
|
||||||
import akka.testkit.{ PerformanceTest, ImplicitSender, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, ImplicitSender, PerformanceTest }
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import akka.testkit.metrics._
|
import akka.testkit.metrics._
|
||||||
import org.scalatest.BeforeAndAfterAll
|
import org.scalatest.BeforeAndAfterAll
|
||||||
|
|
@ -58,7 +58,6 @@ object ActorCreationPerfSpec {
|
||||||
case IsAlive =>
|
case IsAlive =>
|
||||||
sender() ! Alive
|
sender() ! Alive
|
||||||
case Create(number, propsCreator) =>
|
case Create(number, propsCreator) =>
|
||||||
|
|
||||||
for (i <- 1 to number) {
|
for (i <- 1 to number) {
|
||||||
val start = System.nanoTime()
|
val start = System.nanoTime()
|
||||||
context.actorOf(propsCreator.apply())
|
context.actorOf(propsCreator.apply())
|
||||||
|
|
@ -117,8 +116,11 @@ object ActorCreationPerfSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ActorCreationPerfSpec extends AkkaSpec(ActorCreationPerfSpec.config) with ImplicitSender
|
class ActorCreationPerfSpec
|
||||||
with MetricsKit with BeforeAndAfterAll {
|
extends AkkaSpec(ActorCreationPerfSpec.config)
|
||||||
|
with ImplicitSender
|
||||||
|
with MetricsKit
|
||||||
|
with BeforeAndAfterAll {
|
||||||
|
|
||||||
import ActorCreationPerfSpec._
|
import ActorCreationPerfSpec._
|
||||||
|
|
||||||
|
|
@ -175,7 +177,7 @@ class ActorCreationPerfSpec extends AkkaSpec(ActorCreationPerfSpec.config) with
|
||||||
watch(driver)
|
watch(driver)
|
||||||
expectTerminated(driver, 15.seconds)
|
expectTerminated(driver, 15.seconds)
|
||||||
|
|
||||||
after diff before
|
after.diff(before)
|
||||||
}
|
}
|
||||||
|
|
||||||
def registerTests(name: String, propsCreator: () => Props): Unit = {
|
def registerTests(name: String, propsCreator: () => Props): Unit = {
|
||||||
|
|
|
||||||
|
|
@ -49,19 +49,21 @@ class ActorDSLSpec extends AkkaSpec {
|
||||||
actor(new Act {})
|
actor(new Act {})
|
||||||
//#watch
|
//#watch
|
||||||
val i = inbox()
|
val i = inbox()
|
||||||
i watch target
|
i.watch(target)
|
||||||
//#watch
|
//#watch
|
||||||
target ! PoisonPill
|
target ! PoisonPill
|
||||||
i receive 1.second should ===(Terminated(target)(true, false))
|
i.receive(1.second) should ===(Terminated(target)(true, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
"support queueing multiple queries" in {
|
"support queueing multiple queries" in {
|
||||||
val i = inbox()
|
val i = inbox()
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
val res = Future.sequence(Seq(
|
val res =
|
||||||
Future { i.receive() } recover { case x => x },
|
Future.sequence(Seq(Future { i.receive() }.recover { case x => x }, Future {
|
||||||
Future { Thread.sleep(100); i.select() { case "world" => 1 } } recover { case x => x },
|
Thread.sleep(100); i.select() { case "world" => 1 }
|
||||||
Future { Thread.sleep(200); i.select() { case "hello" => 2 } } recover { case x => x }))
|
}.recover { case x => x }, Future { Thread.sleep(200); i.select() { case "hello" => 2 } }.recover {
|
||||||
|
case x => x
|
||||||
|
}))
|
||||||
Thread.sleep(1000)
|
Thread.sleep(1000)
|
||||||
res.isCompleted should ===(false)
|
res.isCompleted should ===(false)
|
||||||
i.receiver ! 42
|
i.receiver ! 42
|
||||||
|
|
@ -87,14 +89,14 @@ class ActorDSLSpec extends AkkaSpec {
|
||||||
try {
|
try {
|
||||||
for (_ <- 1 to 1000) i.receiver ! 0
|
for (_ <- 1 to 1000) i.receiver ! 0
|
||||||
expectNoMsg(1 second)
|
expectNoMsg(1 second)
|
||||||
EventFilter.warning(start = "dropping message", occurrences = 1) intercept {
|
EventFilter.warning(start = "dropping message", occurrences = 1).intercept {
|
||||||
i.receiver ! 42
|
i.receiver ! 42
|
||||||
}
|
}
|
||||||
expectMsgType[Warning]
|
expectMsgType[Warning]
|
||||||
i.receiver ! 42
|
i.receiver ! 42
|
||||||
expectNoMsg(1 second)
|
expectNoMsg(1 second)
|
||||||
val gotit = for (_ <- 1 to 1000) yield i.receive()
|
val gotit = for (_ <- 1 to 1000) yield i.receive()
|
||||||
gotit should ===((1 to 1000) map (_ => 0))
|
gotit should ===((1 to 1000).map(_ => 0))
|
||||||
intercept[TimeoutException] {
|
intercept[TimeoutException] {
|
||||||
i.receive(1 second)
|
i.receive(1 second)
|
||||||
}
|
}
|
||||||
|
|
@ -165,7 +167,7 @@ class ActorDSLSpec extends AkkaSpec {
|
||||||
})
|
})
|
||||||
//#simple-start-stop
|
//#simple-start-stop
|
||||||
|
|
||||||
system stop a
|
system.stop(a)
|
||||||
expectMsg("started")
|
expectMsg("started")
|
||||||
expectMsg("stopped")
|
expectMsg("stopped")
|
||||||
}
|
}
|
||||||
|
|
@ -177,11 +179,13 @@ class ActorDSLSpec extends AkkaSpec {
|
||||||
case "die" => throw new Exception
|
case "die" => throw new Exception
|
||||||
}
|
}
|
||||||
whenFailing { case m @ (cause, msg) => testActor ! m }
|
whenFailing { case m @ (cause, msg) => testActor ! m }
|
||||||
whenRestarted { cause => testActor ! cause }
|
whenRestarted { cause =>
|
||||||
|
testActor ! cause
|
||||||
|
}
|
||||||
})
|
})
|
||||||
//#failing-actor
|
//#failing-actor
|
||||||
|
|
||||||
EventFilter[Exception](occurrences = 1) intercept {
|
EventFilter[Exception](occurrences = 1).intercept {
|
||||||
a ! "die"
|
a ! "die"
|
||||||
}
|
}
|
||||||
expectMsgPF() { case (x: Exception, Some("die")) => }
|
expectMsgPF() { case (x: Exception, Some("die")) => }
|
||||||
|
|
@ -198,7 +202,8 @@ class ActorDSLSpec extends AkkaSpec {
|
||||||
})
|
})
|
||||||
//#supervise-with
|
//#supervise-with
|
||||||
val child = actor("child")(new Act {
|
val child = actor("child")(new Act {
|
||||||
whenFailing { (_, _) => }
|
whenFailing { (_, _) =>
|
||||||
|
}
|
||||||
become {
|
become {
|
||||||
case ref: ActorRef => whenStopping(ref ! "stopped")
|
case ref: ActorRef => whenStopping(ref ! "stopped")
|
||||||
case ex: Exception => throw ex
|
case ex: Exception => throw ex
|
||||||
|
|
@ -209,11 +214,11 @@ class ActorDSLSpec extends AkkaSpec {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
a ! testActor
|
a ! testActor
|
||||||
EventFilter.warning("hi", occurrences = 1) intercept {
|
EventFilter.warning("hi", occurrences = 1).intercept {
|
||||||
a ! new Exception("hi")
|
a ! new Exception("hi")
|
||||||
}
|
}
|
||||||
expectNoMsg(1 second)
|
expectNoMsg(1 second)
|
||||||
EventFilter[Exception]("hello", occurrences = 1) intercept {
|
EventFilter[Exception]("hello", occurrences = 1).intercept {
|
||||||
a ! new Exception("hello")
|
a ! new Exception("hello")
|
||||||
}
|
}
|
||||||
expectMsg("stopped")
|
expectMsg("stopped")
|
||||||
|
|
@ -242,7 +247,8 @@ class ActorDSLSpec extends AkkaSpec {
|
||||||
become {
|
become {
|
||||||
case 1 => stash()
|
case 1 => stash()
|
||||||
case 2 =>
|
case 2 =>
|
||||||
testActor ! 2; unstashAll(); becomeStacked {
|
testActor ! 2; unstashAll();
|
||||||
|
becomeStacked {
|
||||||
case 1 => testActor ! 1; unbecome()
|
case 1 => testActor ! 1; unbecome()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,11 @@ object ActorLifeCycleSpec {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ActorLifeCycleSpec extends AkkaSpec("akka.actor.serialize-messages=off") with BeforeAndAfterEach with ImplicitSender with DefaultTimeout {
|
class ActorLifeCycleSpec
|
||||||
|
extends AkkaSpec("akka.actor.serialize-messages=off")
|
||||||
|
with BeforeAndAfterEach
|
||||||
|
with ImplicitSender
|
||||||
|
with DefaultTimeout {
|
||||||
import ActorLifeCycleSpec._
|
import ActorLifeCycleSpec._
|
||||||
|
|
||||||
"An Actor" must {
|
"An Actor" must {
|
||||||
|
|
@ -37,7 +41,8 @@ class ActorLifeCycleSpec extends AkkaSpec("akka.actor.serialize-messages=off") w
|
||||||
"invoke preRestart, preStart, postRestart when using OneForOneStrategy" in {
|
"invoke preRestart, preStart, postRestart when using OneForOneStrategy" in {
|
||||||
filterException[ActorKilledException] {
|
filterException[ActorKilledException] {
|
||||||
val id = newUuid.toString
|
val id = newUuid.toString
|
||||||
val supervisor = system.actorOf(Props(classOf[Supervisor], OneForOneStrategy(maxNrOfRetries = 3)(List(classOf[Exception]))))
|
val supervisor =
|
||||||
|
system.actorOf(Props(classOf[Supervisor], OneForOneStrategy(maxNrOfRetries = 3)(List(classOf[Exception]))))
|
||||||
val gen = new AtomicInteger(0)
|
val gen = new AtomicInteger(0)
|
||||||
val restarterProps = Props(new LifeCycleTestActor(testActor, id, gen) {
|
val restarterProps = Props(new LifeCycleTestActor(testActor, id, gen) {
|
||||||
override def preRestart(reason: Throwable, message: Option[Any]): Unit = { report("preRestart") }
|
override def preRestart(reason: Throwable, message: Option[Any]): Unit = { report("preRestart") }
|
||||||
|
|
@ -71,7 +76,8 @@ class ActorLifeCycleSpec extends AkkaSpec("akka.actor.serialize-messages=off") w
|
||||||
"default for preRestart and postRestart is to call postStop and preStart respectively" in {
|
"default for preRestart and postRestart is to call postStop and preStart respectively" in {
|
||||||
filterException[ActorKilledException] {
|
filterException[ActorKilledException] {
|
||||||
val id = newUuid().toString
|
val id = newUuid().toString
|
||||||
val supervisor = system.actorOf(Props(classOf[Supervisor], OneForOneStrategy(maxNrOfRetries = 3)(List(classOf[Exception]))))
|
val supervisor =
|
||||||
|
system.actorOf(Props(classOf[Supervisor], OneForOneStrategy(maxNrOfRetries = 3)(List(classOf[Exception]))))
|
||||||
val gen = new AtomicInteger(0)
|
val gen = new AtomicInteger(0)
|
||||||
val restarterProps = Props(classOf[LifeCycleTestActor], testActor, id, gen)
|
val restarterProps = Props(classOf[LifeCycleTestActor], testActor, id, gen)
|
||||||
val restarter = Await.result((supervisor ? restarterProps).mapTo[ActorRef], timeout.duration)
|
val restarter = Await.result((supervisor ? restarterProps).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
@ -101,9 +107,8 @@ class ActorLifeCycleSpec extends AkkaSpec("akka.actor.serialize-messages=off") w
|
||||||
|
|
||||||
"not invoke preRestart and postRestart when never restarted using OneForOneStrategy" in {
|
"not invoke preRestart and postRestart when never restarted using OneForOneStrategy" in {
|
||||||
val id = newUuid().toString
|
val id = newUuid().toString
|
||||||
val supervisor = system.actorOf(Props(
|
val supervisor =
|
||||||
classOf[Supervisor],
|
system.actorOf(Props(classOf[Supervisor], OneForOneStrategy(maxNrOfRetries = 3)(List(classOf[Exception]))))
|
||||||
OneForOneStrategy(maxNrOfRetries = 3)(List(classOf[Exception]))))
|
|
||||||
val gen = new AtomicInteger(0)
|
val gen = new AtomicInteger(0)
|
||||||
val props = Props(classOf[LifeCycleTestActor], testActor, id, gen)
|
val props = Props(classOf[LifeCycleTestActor], testActor, id, gen)
|
||||||
val a = Await.result((supervisor ? props).mapTo[ActorRef], timeout.duration)
|
val a = Await.result((supervisor ? props).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
@ -121,7 +126,7 @@ class ActorLifeCycleSpec extends AkkaSpec("akka.actor.serialize-messages=off") w
|
||||||
def receive = Actor.emptyBehavior
|
def receive = Actor.emptyBehavior
|
||||||
override def postStop: Unit = { throw new Exception("hurrah") }
|
override def postStop: Unit = { throw new Exception("hurrah") }
|
||||||
}))
|
}))
|
||||||
EventFilter[Exception]("hurrah", occurrences = 1) intercept {
|
EventFilter[Exception]("hurrah", occurrences = 1).intercept {
|
||||||
a ! PoisonPill
|
a ! PoisonPill
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -143,7 +148,7 @@ class ActorLifeCycleSpec extends AkkaSpec("akka.actor.serialize-messages=off") w
|
||||||
expectMsg("ok")
|
expectMsg("ok")
|
||||||
a ! "hello"
|
a ! "hello"
|
||||||
expectMsg(43)
|
expectMsg(43)
|
||||||
EventFilter[RuntimeException]("buh", occurrences = 1) intercept {
|
EventFilter[RuntimeException]("buh", occurrences = 1).intercept {
|
||||||
a ! "fail"
|
a ! "fail"
|
||||||
}
|
}
|
||||||
a ! "hello"
|
a ! "hello"
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,11 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
|
||||||
system.actorFor(system / "c1") should ===(c1)
|
system.actorFor(system / "c1") should ===(c1)
|
||||||
system.actorFor(system / "c2") should ===(c2)
|
system.actorFor(system / "c2") should ===(c2)
|
||||||
system.actorFor(system / "c2" / "c21") should ===(c21)
|
system.actorFor(system / "c2" / "c21") should ===(c21)
|
||||||
system.actorFor(system child "c2" child "c21") should ===(c21) // test Java API
|
system.actorFor(system.child("c2").child("c21")) should ===(c21) // test Java API
|
||||||
system.actorFor(system / Seq("c2", "c21")) should ===(c21)
|
system.actorFor(system / Seq("c2", "c21")) should ===(c21)
|
||||||
|
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
system.actorFor(system descendant Seq("c2", "c21").asJava) // test Java API
|
system.actorFor(system.descendant(Seq("c2", "c21").asJava)) // test Java API
|
||||||
}
|
}
|
||||||
|
|
||||||
"find actors by looking up their string representation" in {
|
"find actors by looking up their string representation" in {
|
||||||
|
|
@ -201,7 +201,8 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
|
||||||
"find actors by looking up their root-anchored relative path" in {
|
"find actors by looking up their root-anchored relative path" in {
|
||||||
def check(looker: ActorRef, pathOf: ActorRef, result: ActorRef): Unit = {
|
def check(looker: ActorRef, pathOf: ActorRef, result: ActorRef): Unit = {
|
||||||
Await.result(looker ? LookupString(pathOf.path.toStringWithoutAddress), timeout.duration) should ===(result)
|
Await.result(looker ? LookupString(pathOf.path.toStringWithoutAddress), timeout.duration) should ===(result)
|
||||||
Await.result(looker ? LookupString(pathOf.path.elements.mkString("/", "/", "/")), timeout.duration) should ===(result)
|
Await.result(looker ? LookupString(pathOf.path.elements.mkString("/", "/", "/")), timeout.duration) should ===(
|
||||||
|
result)
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
looker <- all
|
looker <- all
|
||||||
|
|
@ -212,8 +213,8 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
|
||||||
"find actors by looking up their relative path" in {
|
"find actors by looking up their relative path" in {
|
||||||
def check(looker: ActorRef, result: ActorRef, elems: String*): Unit = {
|
def check(looker: ActorRef, result: ActorRef, elems: String*): Unit = {
|
||||||
Await.result(looker ? LookupElems(elems), timeout.duration) should ===(result)
|
Await.result(looker ? LookupElems(elems), timeout.duration) should ===(result)
|
||||||
Await.result(looker ? LookupString(elems mkString "/"), timeout.duration) should ===(result)
|
Await.result(looker ? LookupString(elems.mkString("/")), timeout.duration) should ===(result)
|
||||||
Await.result(looker ? LookupString(elems mkString ("", "/", "/")), timeout.duration) should ===(result)
|
Await.result(looker ? LookupString(elems.mkString("", "/", "/")), timeout.duration) should ===(result)
|
||||||
}
|
}
|
||||||
check(c1, user, "..")
|
check(c1, user, "..")
|
||||||
for {
|
for {
|
||||||
|
|
@ -232,7 +233,9 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
|
||||||
Await.result(looker ? LookupString(target.path.toString), timeout.duration) should ===(target)
|
Await.result(looker ? LookupString(target.path.toString), timeout.duration) should ===(target)
|
||||||
Await.result(looker ? LookupString(target.path.toString + "/"), timeout.duration) should ===(target)
|
Await.result(looker ? LookupString(target.path.toString + "/"), timeout.duration) should ===(target)
|
||||||
Await.result(looker ? LookupString(target.path.toStringWithoutAddress), timeout.duration) should ===(target)
|
Await.result(looker ? LookupString(target.path.toStringWithoutAddress), timeout.duration) should ===(target)
|
||||||
if (target != root) Await.result(looker ? LookupString(target.path.elements.mkString("/", "/", "/")), timeout.duration) should ===(target)
|
if (target != root)
|
||||||
|
Await.result(looker ? LookupString(target.path.elements.mkString("/", "/", "/")), timeout.duration) should ===(
|
||||||
|
target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (target <- Seq(root, syst, user, system.deadLetters)) check(target)
|
for (target <- Seq(root, syst, user, system.deadLetters)) check(target)
|
||||||
|
|
@ -248,17 +251,14 @@ class ActorLookupSpec extends AkkaSpec with DefaultTimeout {
|
||||||
}
|
}
|
||||||
def check(looker: ActorRef): Unit = {
|
def check(looker: ActorRef): Unit = {
|
||||||
val lookname = looker.path.elements.mkString("", "/", "/")
|
val lookname = looker.path.elements.mkString("", "/", "/")
|
||||||
for (
|
for ((l, r) <- Seq(LookupString("a/b/c") -> empty(lookname + "a/b/c"),
|
||||||
(l, r) <- Seq(
|
|
||||||
LookupString("a/b/c") -> empty(lookname + "a/b/c"),
|
|
||||||
LookupString("") -> system.deadLetters,
|
LookupString("") -> system.deadLetters,
|
||||||
LookupString("akka://all-systems/Nobody") -> system.deadLetters,
|
LookupString("akka://all-systems/Nobody") -> system.deadLetters,
|
||||||
LookupPath(system / "hallo") -> empty("user/hallo"),
|
LookupPath(system / "hallo") -> empty("user/hallo"),
|
||||||
LookupPath(looker.path child "hallo") -> empty(lookname + "hallo"), // test Java API
|
LookupPath(looker.path.child("hallo")) -> empty(lookname + "hallo"), // test Java API
|
||||||
LookupPath(looker.path descendant Seq("a", "b").asJava) -> empty(lookname + "a/b"), // test Java API
|
LookupPath(looker.path.descendant(Seq("a", "b").asJava)) -> empty(lookname + "a/b"), // test Java API
|
||||||
LookupElems(Seq()) -> system.deadLetters,
|
LookupElems(Seq()) -> system.deadLetters,
|
||||||
LookupElems(Seq("a")) -> empty(lookname + "a"))
|
LookupElems(Seq("a")) -> empty(lookname + "a"))) checkOne(looker, l, r)
|
||||||
) checkOne(looker, l, r)
|
|
||||||
}
|
}
|
||||||
for (looker <- all) check(looker)
|
for (looker <- all) check(looker)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,10 +174,12 @@ object ActorMailboxSpec {
|
||||||
|
|
||||||
class BoundedQueueReportingActor extends QueueReportingActor with RequiresMessageQueue[BoundedMessageQueueSemantics]
|
class BoundedQueueReportingActor extends QueueReportingActor with RequiresMessageQueue[BoundedMessageQueueSemantics]
|
||||||
|
|
||||||
class BoundedControlAwareQueueReportingActor extends QueueReportingActor
|
class BoundedControlAwareQueueReportingActor
|
||||||
|
extends QueueReportingActor
|
||||||
with RequiresMessageQueue[BoundedControlAwareMessageQueueSemantics]
|
with RequiresMessageQueue[BoundedControlAwareMessageQueueSemantics]
|
||||||
|
|
||||||
class UnboundedControlAwareQueueReportingActor extends QueueReportingActor
|
class UnboundedControlAwareQueueReportingActor
|
||||||
|
extends QueueReportingActor
|
||||||
with RequiresMessageQueue[UnboundedControlAwareMessageQueueSemantics]
|
with RequiresMessageQueue[UnboundedControlAwareMessageQueueSemantics]
|
||||||
|
|
||||||
class StashQueueReportingActor extends QueueReportingActor with Stash
|
class StashQueueReportingActor extends QueueReportingActor with Stash
|
||||||
|
|
@ -187,32 +189,28 @@ object ActorMailboxSpec {
|
||||||
val UnboundedMailboxTypes = Seq(classOf[UnboundedMessageQueueSemantics])
|
val UnboundedMailboxTypes = Seq(classOf[UnboundedMessageQueueSemantics])
|
||||||
val BoundedMailboxTypes = Seq(classOf[BoundedMessageQueueSemantics])
|
val BoundedMailboxTypes = Seq(classOf[BoundedMessageQueueSemantics])
|
||||||
|
|
||||||
val UnboundedDeqMailboxTypes = Seq(
|
val UnboundedDeqMailboxTypes = Seq(classOf[DequeBasedMessageQueueSemantics],
|
||||||
classOf[DequeBasedMessageQueueSemantics],
|
|
||||||
classOf[UnboundedMessageQueueSemantics],
|
classOf[UnboundedMessageQueueSemantics],
|
||||||
classOf[UnboundedDequeBasedMessageQueueSemantics])
|
classOf[UnboundedDequeBasedMessageQueueSemantics])
|
||||||
|
|
||||||
val BoundedDeqMailboxTypes = Seq(
|
val BoundedDeqMailboxTypes = Seq(classOf[DequeBasedMessageQueueSemantics],
|
||||||
classOf[DequeBasedMessageQueueSemantics],
|
|
||||||
classOf[BoundedMessageQueueSemantics],
|
classOf[BoundedMessageQueueSemantics],
|
||||||
classOf[BoundedDequeBasedMessageQueueSemantics])
|
classOf[BoundedDequeBasedMessageQueueSemantics])
|
||||||
|
|
||||||
val BoundedControlAwareMailboxTypes = Seq(
|
val BoundedControlAwareMailboxTypes = Seq(classOf[BoundedMessageQueueSemantics],
|
||||||
classOf[BoundedMessageQueueSemantics],
|
|
||||||
classOf[ControlAwareMessageQueueSemantics],
|
classOf[ControlAwareMessageQueueSemantics],
|
||||||
classOf[BoundedControlAwareMessageQueueSemantics])
|
classOf[BoundedControlAwareMessageQueueSemantics])
|
||||||
val UnboundedControlAwareMailboxTypes = Seq(
|
val UnboundedControlAwareMailboxTypes = Seq(classOf[UnboundedMessageQueueSemantics],
|
||||||
classOf[UnboundedMessageQueueSemantics],
|
|
||||||
classOf[ControlAwareMessageQueueSemantics],
|
classOf[ControlAwareMessageQueueSemantics],
|
||||||
classOf[UnboundedControlAwareMessageQueueSemantics])
|
classOf[UnboundedControlAwareMessageQueueSemantics])
|
||||||
|
|
||||||
trait MCBoundedMessageQueueSemantics extends MessageQueue with MultipleConsumerSemantics
|
trait MCBoundedMessageQueueSemantics extends MessageQueue with MultipleConsumerSemantics
|
||||||
final case class MCBoundedMailbox(val capacity: Int, val pushTimeOut: FiniteDuration)
|
final case class MCBoundedMailbox(val capacity: Int, val pushTimeOut: FiniteDuration)
|
||||||
extends MailboxType with ProducesMessageQueue[MCBoundedMessageQueueSemantics] {
|
extends MailboxType
|
||||||
|
with ProducesMessageQueue[MCBoundedMessageQueueSemantics] {
|
||||||
|
|
||||||
def this(settings: ActorSystem.Settings, config: Config) = this(
|
def this(settings: ActorSystem.Settings, config: Config) =
|
||||||
config.getInt("mailbox-capacity"),
|
this(config.getInt("mailbox-capacity"), config.getNanosDuration("mailbox-push-timeout-time"))
|
||||||
config.getNanosDuration("mailbox-push-timeout-time"))
|
|
||||||
|
|
||||||
final override def create(owner: Option[ActorRef], system: Option[ActorSystem]): MessageQueue =
|
final override def create(owner: Option[ActorRef], system: Option[ActorSystem]): MessageQueue =
|
||||||
new BoundedMailbox.MessageQueue(capacity, pushTimeOut)
|
new BoundedMailbox.MessageQueue(capacity, pushTimeOut)
|
||||||
|
|
@ -231,7 +229,7 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout
|
||||||
|
|
||||||
actor ! "ping"
|
actor ! "ping"
|
||||||
val q = expectMsgType[MessageQueue]
|
val q = expectMsgType[MessageQueue]
|
||||||
types foreach (t => assert(t isInstance q, s"Type [${q.getClass.getName}] is not assignable to [${t.getName}]"))
|
types.foreach(t => assert(t.isInstance(q), s"Type [${q.getClass.getName}] is not assignable to [${t.getName}]"))
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,30 +240,24 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
"get an unbounded deque message queue when it is only configured on the props" in {
|
"get an unbounded deque message queue when it is only configured on the props" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[QueueReportingActor].withMailbox("akka.actor.mailbox.unbounded-deque-based"),
|
||||||
Props[QueueReportingActor].withMailbox("akka.actor.mailbox.unbounded-deque-based"),
|
"default-override-from-props",
|
||||||
"default-override-from-props", UnboundedDeqMailboxTypes)
|
UnboundedDeqMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"get an bounded message queue when it's only configured with RequiresMailbox" in {
|
"get an bounded message queue when it's only configured with RequiresMailbox" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[BoundedQueueReportingActor], "default-override-from-trait", BoundedMailboxTypes)
|
||||||
Props[BoundedQueueReportingActor],
|
|
||||||
"default-override-from-trait", BoundedMailboxTypes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"get an unbounded deque message queue when it's only mixed with Stash" in {
|
"get an unbounded deque message queue when it's only mixed with Stash" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[StashQueueReportingActor], "default-override-from-stash", UnboundedDeqMailboxTypes)
|
||||||
Props[StashQueueReportingActor],
|
checkMailboxQueue(Props(new StashQueueReportingActor), "default-override-from-stash2", UnboundedDeqMailboxTypes)
|
||||||
"default-override-from-stash", UnboundedDeqMailboxTypes)
|
checkMailboxQueue(Props(classOf[StashQueueReportingActorWithParams], 17, "hello"),
|
||||||
checkMailboxQueue(
|
"default-override-from-stash3",
|
||||||
Props(new StashQueueReportingActor),
|
UnboundedDeqMailboxTypes)
|
||||||
"default-override-from-stash2", UnboundedDeqMailboxTypes)
|
checkMailboxQueue(Props(new StashQueueReportingActorWithParams(17, "hello")),
|
||||||
checkMailboxQueue(
|
"default-override-from-stash4",
|
||||||
Props(classOf[StashQueueReportingActorWithParams], 17, "hello"),
|
UnboundedDeqMailboxTypes)
|
||||||
"default-override-from-stash3", UnboundedDeqMailboxTypes)
|
|
||||||
checkMailboxQueue(
|
|
||||||
Props(new StashQueueReportingActorWithParams(17, "hello")),
|
|
||||||
"default-override-from-stash4", UnboundedDeqMailboxTypes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"get a bounded message queue when it's configured as mailbox" in {
|
"get a bounded message queue when it's configured as mailbox" in {
|
||||||
|
|
@ -281,23 +273,26 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
"get an unbounded control aware message queue when it's configured as mailbox" in {
|
"get an unbounded control aware message queue when it's configured as mailbox" in {
|
||||||
checkMailboxQueue(Props[QueueReportingActor], "default-unbounded-control-aware", UnboundedControlAwareMailboxTypes)
|
checkMailboxQueue(Props[QueueReportingActor],
|
||||||
|
"default-unbounded-control-aware",
|
||||||
|
UnboundedControlAwareMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"get an bounded control aware message queue when it's only configured with RequiresMailbox" in {
|
"get an bounded control aware message queue when it's only configured with RequiresMailbox" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[BoundedControlAwareQueueReportingActor],
|
||||||
Props[BoundedControlAwareQueueReportingActor],
|
"default-override-from-trait-bounded-control-aware",
|
||||||
"default-override-from-trait-bounded-control-aware", BoundedControlAwareMailboxTypes)
|
BoundedControlAwareMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"get an unbounded control aware message queue when it's only configured with RequiresMailbox" in {
|
"get an unbounded control aware message queue when it's only configured with RequiresMailbox" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[UnboundedControlAwareQueueReportingActor],
|
||||||
Props[UnboundedControlAwareQueueReportingActor],
|
"default-override-from-trait-unbounded-control-aware",
|
||||||
"default-override-from-trait-unbounded-control-aware", UnboundedControlAwareMailboxTypes)
|
UnboundedControlAwareMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail to create actor when an unbounded dequeu message queue is configured as mailbox overriding RequestMailbox" in {
|
"fail to create actor when an unbounded dequeu message queue is configured as mailbox overriding RequestMailbox" in {
|
||||||
intercept[ConfigurationException](system.actorOf(Props[BoundedQueueReportingActor], "default-unbounded-deque-override-trait"))
|
intercept[ConfigurationException](
|
||||||
|
system.actorOf(Props[BoundedQueueReportingActor], "default-unbounded-deque-override-trait"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"get an unbounded message queue when defined in dispatcher" in {
|
"get an unbounded message queue when defined in dispatcher" in {
|
||||||
|
|
@ -305,7 +300,8 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail to create actor when an unbounded message queue is defined in dispatcher overriding RequestMailbox" in {
|
"fail to create actor when an unbounded message queue is defined in dispatcher overriding RequestMailbox" in {
|
||||||
intercept[ConfigurationException](system.actorOf(Props[BoundedQueueReportingActor], "unbounded-default-override-trait"))
|
intercept[ConfigurationException](
|
||||||
|
system.actorOf(Props[BoundedQueueReportingActor], "unbounded-default-override-trait"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"get a bounded message queue when it's configured as mailbox overriding unbounded in dispatcher" in {
|
"get a bounded message queue when it's configured as mailbox overriding unbounded in dispatcher" in {
|
||||||
|
|
@ -317,7 +313,9 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
"get a bounded message queue with 0 push timeout when defined in dispatcher" in {
|
"get a bounded message queue with 0 push timeout when defined in dispatcher" in {
|
||||||
val q = checkMailboxQueue(Props[QueueReportingActor], "default-bounded-mailbox-with-zero-pushtimeout", BoundedMailboxTypes)
|
val q = checkMailboxQueue(Props[QueueReportingActor],
|
||||||
|
"default-bounded-mailbox-with-zero-pushtimeout",
|
||||||
|
BoundedMailboxTypes)
|
||||||
q.asInstanceOf[BoundedMessageQueueSemantics].pushTimeOut should ===(Duration.Zero)
|
q.asInstanceOf[BoundedMessageQueueSemantics].pushTimeOut should ===(Duration.Zero)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,21 +324,25 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
"get an unbounded message queue overriding configuration on the props" in {
|
"get an unbounded message queue overriding configuration on the props" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[QueueReportingActor].withMailbox("akka.actor.mailbox.unbounded-deque-based"),
|
||||||
Props[QueueReportingActor].withMailbox("akka.actor.mailbox.unbounded-deque-based"),
|
"bounded-unbounded-override-props",
|
||||||
"bounded-unbounded-override-props", UnboundedMailboxTypes)
|
UnboundedMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"get a bounded deque-based message queue if configured and required" in {
|
"get a bounded deque-based message queue if configured and required" in {
|
||||||
checkMailboxQueue(Props[StashQueueReportingActor], "bounded-deque-requirements-configured", BoundedDeqMailboxTypes)
|
checkMailboxQueue(Props[StashQueueReportingActor],
|
||||||
|
"bounded-deque-requirements-configured",
|
||||||
|
BoundedDeqMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail with a unbounded deque-based message queue if configured and required" in {
|
"fail with a unbounded deque-based message queue if configured and required" in {
|
||||||
intercept[ConfigurationException](system.actorOf(Props[StashQueueReportingActor], "bounded-deque-require-unbounded-configured"))
|
intercept[ConfigurationException](
|
||||||
|
system.actorOf(Props[StashQueueReportingActor], "bounded-deque-require-unbounded-configured"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail with a bounded deque-based message queue if not configured" in {
|
"fail with a bounded deque-based message queue if not configured" in {
|
||||||
intercept[ConfigurationException](system.actorOf(Props[StashQueueReportingActor], "bounded-deque-require-unbounded-unconfigured"))
|
intercept[ConfigurationException](
|
||||||
|
system.actorOf(Props[StashQueueReportingActor], "bounded-deque-require-unbounded-unconfigured"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"get a bounded deque-based message queue if configured and required with Props" in {
|
"get a bounded deque-based message queue if configured and required with Props" in {
|
||||||
|
|
@ -353,7 +355,8 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail with a unbounded deque-based message queue if configured and required with Props" in {
|
"fail with a unbounded deque-based message queue if configured and required with Props" in {
|
||||||
intercept[ConfigurationException](system.actorOf(
|
intercept[ConfigurationException](
|
||||||
|
system.actorOf(
|
||||||
Props[StashQueueReportingActor]
|
Props[StashQueueReportingActor]
|
||||||
.withDispatcher("requiring-bounded-dispatcher")
|
.withDispatcher("requiring-bounded-dispatcher")
|
||||||
.withMailbox("akka.actor.mailbox.unbounded-deque-based"),
|
.withMailbox("akka.actor.mailbox.unbounded-deque-based"),
|
||||||
|
|
@ -361,71 +364,62 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail with a bounded deque-based message queue if not configured with Props" in {
|
"fail with a bounded deque-based message queue if not configured with Props" in {
|
||||||
intercept[ConfigurationException](system.actorOf(
|
intercept[ConfigurationException](
|
||||||
Props[StashQueueReportingActor]
|
system.actorOf(Props[StashQueueReportingActor].withDispatcher("requiring-bounded-dispatcher"),
|
||||||
.withDispatcher("requiring-bounded-dispatcher"),
|
|
||||||
"bounded-deque-require-unbounded-unconfigured-props"))
|
"bounded-deque-require-unbounded-unconfigured-props"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"get a bounded deque-based message queue if configured and required with Props (dispatcher)" in {
|
"get a bounded deque-based message queue if configured and required with Props (dispatcher)" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[StashQueueReportingActor].withDispatcher("requiring-bounded-dispatcher"),
|
||||||
Props[StashQueueReportingActor]
|
|
||||||
.withDispatcher("requiring-bounded-dispatcher"),
|
|
||||||
"bounded-deque-requirements-configured-props-disp",
|
"bounded-deque-requirements-configured-props-disp",
|
||||||
BoundedDeqMailboxTypes)
|
BoundedDeqMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail with a unbounded deque-based message queue if configured and required with Props (dispatcher)" in {
|
"fail with a unbounded deque-based message queue if configured and required with Props (dispatcher)" in {
|
||||||
intercept[ConfigurationException](system.actorOf(
|
intercept[ConfigurationException](
|
||||||
Props[StashQueueReportingActor]
|
system.actorOf(Props[StashQueueReportingActor].withDispatcher("requiring-bounded-dispatcher"),
|
||||||
.withDispatcher("requiring-bounded-dispatcher"),
|
|
||||||
"bounded-deque-require-unbounded-configured-props-disp"))
|
"bounded-deque-require-unbounded-configured-props-disp"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail with a bounded deque-based message queue if not configured with Props (dispatcher)" in {
|
"fail with a bounded deque-based message queue if not configured with Props (dispatcher)" in {
|
||||||
intercept[ConfigurationException](system.actorOf(
|
intercept[ConfigurationException](
|
||||||
Props[StashQueueReportingActor]
|
system.actorOf(Props[StashQueueReportingActor].withDispatcher("requiring-bounded-dispatcher"),
|
||||||
.withDispatcher("requiring-bounded-dispatcher"),
|
|
||||||
"bounded-deque-require-unbounded-unconfigured-props-disp"))
|
"bounded-deque-require-unbounded-unconfigured-props-disp"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"get a bounded deque-based message queue if configured and required with Props (mailbox)" in {
|
"get a bounded deque-based message queue if configured and required with Props (mailbox)" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[StashQueueReportingActor].withMailbox("akka.actor.mailbox.bounded-deque-based"),
|
||||||
Props[StashQueueReportingActor]
|
|
||||||
.withMailbox("akka.actor.mailbox.bounded-deque-based"),
|
|
||||||
"bounded-deque-requirements-configured-props-mail",
|
"bounded-deque-requirements-configured-props-mail",
|
||||||
BoundedDeqMailboxTypes)
|
BoundedDeqMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail with a unbounded deque-based message queue if configured and required with Props (mailbox)" in {
|
"fail with a unbounded deque-based message queue if configured and required with Props (mailbox)" in {
|
||||||
intercept[ConfigurationException](system.actorOf(
|
intercept[ConfigurationException](
|
||||||
Props[StashQueueReportingActor]
|
system.actorOf(Props[StashQueueReportingActor].withMailbox("akka.actor.mailbox.unbounded-deque-based"),
|
||||||
.withMailbox("akka.actor.mailbox.unbounded-deque-based"),
|
|
||||||
"bounded-deque-require-unbounded-configured-props-mail"))
|
"bounded-deque-require-unbounded-configured-props-mail"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail with a bounded deque-based message queue if not configured with Props (mailbox)" in {
|
"fail with a bounded deque-based message queue if not configured with Props (mailbox)" in {
|
||||||
intercept[ConfigurationException](system.actorOf(
|
intercept[ConfigurationException](
|
||||||
Props[StashQueueReportingActor],
|
system.actorOf(Props[StashQueueReportingActor], "bounded-deque-require-unbounded-unconfigured-props-mail"))
|
||||||
"bounded-deque-require-unbounded-unconfigured-props-mail"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"get an unbounded message queue with a balancing dispatcher" in {
|
"get an unbounded message queue with a balancing dispatcher" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[QueueReportingActor].withDispatcher("balancing-dispatcher"),
|
||||||
Props[QueueReportingActor].withDispatcher("balancing-dispatcher"),
|
"unbounded-balancing",
|
||||||
"unbounded-balancing", UnboundedMailboxTypes)
|
UnboundedMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"get a bounded message queue with a balancing bounded dispatcher" in {
|
"get a bounded message queue with a balancing bounded dispatcher" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[QueueReportingActor].withDispatcher("balancing-bounded-dispatcher"),
|
||||||
Props[QueueReportingActor].withDispatcher("balancing-bounded-dispatcher"),
|
"bounded-balancing",
|
||||||
"bounded-balancing", BoundedMailboxTypes)
|
BoundedMailboxTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
"get a bounded message queue with a requiring balancing bounded dispatcher" in {
|
"get a bounded message queue with a requiring balancing bounded dispatcher" in {
|
||||||
checkMailboxQueue(
|
checkMailboxQueue(Props[QueueReportingActor].withDispatcher("requiring-balancing-bounded-dispatcher"),
|
||||||
Props[QueueReportingActor].withDispatcher("requiring-balancing-bounded-dispatcher"),
|
"requiring-bounded-balancing",
|
||||||
"requiring-bounded-balancing", BoundedMailboxTypes)
|
BoundedMailboxTypes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,8 @@ class ActorPathSpec extends WordSpec with Matchers {
|
||||||
}
|
}
|
||||||
|
|
||||||
"have correct path elements" in {
|
"have correct path elements" in {
|
||||||
(RootActorPath(Address("akka.tcp", "mysys")) / "user" / "foo" / "bar").elements.toSeq should ===(Seq("user", "foo", "bar"))
|
(RootActorPath(Address("akka.tcp", "mysys")) / "user" / "foo" / "bar").elements.toSeq should ===(
|
||||||
|
Seq("user", "foo", "bar"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"create correct toStringWithoutAddress" in {
|
"create correct toStringWithoutAddress" in {
|
||||||
|
|
@ -51,7 +52,8 @@ class ActorPathSpec extends WordSpec with Matchers {
|
||||||
}
|
}
|
||||||
|
|
||||||
"validate path elements" in {
|
"validate path elements" in {
|
||||||
intercept[InvalidActorNameException](ActorPath.validatePathElement("")).getMessage should include("must not be empty")
|
intercept[InvalidActorNameException](ActorPath.validatePathElement("")).getMessage should include(
|
||||||
|
"must not be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
"create correct toStringWithAddress" in {
|
"create correct toStringWithAddress" in {
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ object ActorRefSpec {
|
||||||
class OuterActor(val inner: ActorRef) extends Actor {
|
class OuterActor(val inner: ActorRef) extends Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
case "self" => sender() ! self
|
case "self" => sender() ! self
|
||||||
case x => inner forward x
|
case x => inner.forward(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ object ActorRefSpec {
|
||||||
|
|
||||||
def receive = {
|
def receive = {
|
||||||
case "self" => sender() ! self
|
case "self" => sender() ! self
|
||||||
case x => inner forward x
|
case x => inner.forward(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +112,8 @@ object ActorRefSpec {
|
||||||
class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
import akka.actor.ActorRefSpec._
|
import akka.actor.ActorRefSpec._
|
||||||
|
|
||||||
def promiseIntercept(f: => Actor)(to: Promise[Actor]): Actor = try {
|
def promiseIntercept(f: => Actor)(to: Promise[Actor]): Actor =
|
||||||
|
try {
|
||||||
val r = f
|
val r = f
|
||||||
to.success(r)
|
to.success(r)
|
||||||
r
|
r
|
||||||
|
|
@ -139,7 +140,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
|
|
||||||
def contextStackMustBeEmpty(): Unit = ActorCell.contextStack.get.headOption should ===(None)
|
def contextStackMustBeEmpty(): Unit = ActorCell.contextStack.get.headOption should ===(None)
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 1) intercept {
|
EventFilter[ActorInitializationException](occurrences = 1).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(result =>
|
||||||
actorOf(Props(new Actor {
|
actorOf(Props(new Actor {
|
||||||
|
|
@ -151,25 +152,25 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 1) intercept {
|
EventFilter[ActorInitializationException](occurrences = 1).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(
|
||||||
actorOf(Props(promiseIntercept(new FailingOuterActor(actorOf(Props(new InnerActor))))(result))))
|
result => actorOf(Props(promiseIntercept(new FailingOuterActor(actorOf(Props(new InnerActor))))(result))))
|
||||||
}
|
}
|
||||||
|
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 1) intercept {
|
EventFilter[ActorInitializationException](occurrences = 1).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(
|
||||||
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept(new FailingInnerActor)(result)))))))
|
result => actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept(new FailingInnerActor)(result)))))))
|
||||||
}
|
}
|
||||||
|
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 1) intercept {
|
EventFilter[ActorInitializationException](occurrences = 1).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(result =>
|
||||||
actorOf(Props(promiseIntercept(new FailingInheritingOuterActor(actorOf(Props(new InnerActor))))(result))))
|
actorOf(Props(promiseIntercept(new FailingInheritingOuterActor(actorOf(Props(new InnerActor))))(result))))
|
||||||
|
|
@ -178,34 +179,38 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 2) intercept {
|
EventFilter[ActorInitializationException](occurrences = 2).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(result =>
|
||||||
actorOf(Props(new FailingOuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
|
actorOf(
|
||||||
|
Props(new FailingOuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
|
||||||
}
|
}
|
||||||
|
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 2) intercept {
|
EventFilter[ActorInitializationException](occurrences = 2).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(
|
||||||
actorOf(Props(new FailingInheritingOuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
|
result =>
|
||||||
|
actorOf(Props(new FailingInheritingOuterActor(
|
||||||
|
actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
|
||||||
}
|
}
|
||||||
|
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 2) intercept {
|
EventFilter[ActorInitializationException](occurrences = 2).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(result =>
|
||||||
actorOf(Props(new FailingInheritingOuterActor(actorOf(Props(promiseIntercept(new FailingInnerActor)(result)))))))
|
actorOf(
|
||||||
|
Props(new FailingInheritingOuterActor(actorOf(Props(promiseIntercept(new FailingInnerActor)(result)))))))
|
||||||
}
|
}
|
||||||
|
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 1) intercept {
|
EventFilter[ActorInitializationException](occurrences = 1).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(result =>
|
||||||
actorOf(Props(new OuterActor(actorOf(Props(new InnerActor {
|
actorOf(Props(new OuterActor(actorOf(Props(new InnerActor {
|
||||||
|
|
@ -216,16 +221,17 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 2) intercept {
|
EventFilter[ActorInitializationException](occurrences = 2).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(result =>
|
||||||
actorOf(Props(new FailingOuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
|
actorOf(
|
||||||
|
Props(new FailingOuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
|
||||||
}
|
}
|
||||||
|
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 1) intercept {
|
EventFilter[ActorInitializationException](occurrences = 1).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(result =>
|
||||||
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
|
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept(new FailingInheritingInnerActor)(result)))))))
|
||||||
|
|
@ -234,19 +240,23 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 1) intercept {
|
EventFilter[ActorInitializationException](occurrences = 1).intercept {
|
||||||
intercept[akka.actor.ActorInitializationException] {
|
intercept[akka.actor.ActorInitializationException] {
|
||||||
wrap(result =>
|
wrap(
|
||||||
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept({ new InnerActor; new InnerActor })(result)))))))
|
result =>
|
||||||
|
actorOf(
|
||||||
|
Props(new OuterActor(actorOf(Props(promiseIntercept({ new InnerActor; new InnerActor })(result)))))))
|
||||||
}
|
}
|
||||||
|
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorInitializationException](occurrences = 1) intercept {
|
EventFilter[ActorInitializationException](occurrences = 1).intercept {
|
||||||
(intercept[java.lang.IllegalStateException] {
|
(intercept[java.lang.IllegalStateException] {
|
||||||
wrap(result =>
|
wrap(result =>
|
||||||
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept({ throw new IllegalStateException("Ur state be b0rked"); new InnerActor })(result)))))))
|
actorOf(Props(new OuterActor(actorOf(Props(promiseIntercept({
|
||||||
|
throw new IllegalStateException("Ur state be b0rked"); new InnerActor
|
||||||
|
})(result)))))))
|
||||||
}).getMessage should ===("Ur state be b0rked")
|
}).getMessage should ===("Ur state be b0rked")
|
||||||
|
|
||||||
contextStackMustBeEmpty()
|
contextStackMustBeEmpty()
|
||||||
|
|
@ -254,7 +264,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
}
|
}
|
||||||
|
|
||||||
"insert its path in a ActorInitializationException" in {
|
"insert its path in a ActorInitializationException" in {
|
||||||
EventFilter[ActorInitializationException](occurrences = 1, pattern = "/user/failingActor:") intercept {
|
EventFilter[ActorInitializationException](occurrences = 1, pattern = "/user/failingActor:").intercept {
|
||||||
intercept[java.lang.IllegalStateException] {
|
intercept[java.lang.IllegalStateException] {
|
||||||
wrap(result =>
|
wrap(result =>
|
||||||
system.actorOf(Props(promiseIntercept({
|
system.actorOf(Props(promiseIntercept({
|
||||||
|
|
@ -312,7 +322,8 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
|
|
||||||
(intercept[java.lang.IllegalStateException] {
|
(intercept[java.lang.IllegalStateException] {
|
||||||
in.readObject
|
in.readObject
|
||||||
}).getMessage should ===("Trying to deserialize a serialized ActorRef without an ActorSystem in scope." +
|
}).getMessage should ===(
|
||||||
|
"Trying to deserialize a serialized ActorRef without an ActorSystem in scope." +
|
||||||
" Use 'akka.serialization.JavaSerializer.currentSystem.withValue(system) { ... }'")
|
" Use 'akka.serialization.JavaSerializer.currentSystem.withValue(system) { ... }'")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -394,7 +405,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
val a = system.actorOf(NonPublicClass.createProps())
|
val a = system.actorOf(NonPublicClass.createProps())
|
||||||
a.tell("pigdog", testActor)
|
a.tell("pigdog", testActor)
|
||||||
expectMsg("pigdog")
|
expectMsg("pigdog")
|
||||||
system stop a
|
system.stop(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
"stop when sent a poison pill" in {
|
"stop when sent a poison pill" in {
|
||||||
|
|
@ -426,8 +437,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
override val supervisorStrategy =
|
override val supervisorStrategy =
|
||||||
OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 1 second)(List(classOf[Throwable]))
|
OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 1 second)(List(classOf[Throwable]))
|
||||||
|
|
||||||
val ref = context.actorOf(
|
val ref = context.actorOf(Props(new Actor {
|
||||||
Props(new Actor {
|
|
||||||
def receive = { case _ => }
|
def receive = { case _ => }
|
||||||
override def preRestart(reason: Throwable, msg: Option[Any]) = latch.countDown()
|
override def preRestart(reason: Throwable, msg: Option[Any]) = latch.countDown()
|
||||||
override def postRestart(reason: Throwable) = latch.countDown()
|
override def postRestart(reason: Throwable) = latch.countDown()
|
||||||
|
|
@ -444,8 +454,7 @@ class ActorRefSpec extends AkkaSpec with DefaultTimeout {
|
||||||
"be able to check for existence of children" in {
|
"be able to check for existence of children" in {
|
||||||
val parent = system.actorOf(Props(new Actor {
|
val parent = system.actorOf(Props(new Actor {
|
||||||
|
|
||||||
val child = context.actorOf(
|
val child = context.actorOf(Props(new Actor {
|
||||||
Props(new Actor {
|
|
||||||
def receive = { case _ => }
|
def receive = { case _ => }
|
||||||
}), "child")
|
}), "child")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,8 @@ class ActorSelectionSpec extends AkkaSpec with DefaultTimeout {
|
||||||
asked.correlationId should ===(selection)
|
asked.correlationId should ===(selection)
|
||||||
|
|
||||||
implicit val ec = system.dispatcher
|
implicit val ec = system.dispatcher
|
||||||
val resolved = Await.result(
|
val resolved =
|
||||||
selection.resolveOne(timeout.duration).mapTo[ActorRef] recover { case _ => null },
|
Await.result(selection.resolveOne(timeout.duration).mapTo[ActorRef].recover { case _ => null }, timeout.duration)
|
||||||
timeout.duration)
|
|
||||||
Option(resolved) should ===(result)
|
Option(resolved) should ===(result)
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|
@ -93,11 +92,11 @@ class ActorSelectionSpec extends AkkaSpec with DefaultTimeout {
|
||||||
identify(system / "c1") should ===(Some(c1))
|
identify(system / "c1") should ===(Some(c1))
|
||||||
identify(system / "c2") should ===(Some(c2))
|
identify(system / "c2") should ===(Some(c2))
|
||||||
identify(system / "c2" / "c21") should ===(Some(c21))
|
identify(system / "c2" / "c21") should ===(Some(c21))
|
||||||
identify(system child "c2" child "c21") should ===(Some(c21)) // test Java API
|
identify(system.child("c2").child("c21")) should ===(Some(c21)) // test Java API
|
||||||
identify(system / Seq("c2", "c21")) should ===(Some(c21))
|
identify(system / Seq("c2", "c21")) should ===(Some(c21))
|
||||||
|
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
identify(system descendant Seq("c2", "c21").asJava) // test Java API
|
identify(system.descendant(Seq("c2", "c21").asJava)) // test Java API
|
||||||
}
|
}
|
||||||
|
|
||||||
"select actors by their string path representation" in {
|
"select actors by their string path representation" in {
|
||||||
|
|
@ -218,8 +217,8 @@ class ActorSelectionSpec extends AkkaSpec with DefaultTimeout {
|
||||||
|
|
||||||
"select actors by their relative path" in {
|
"select actors by their relative path" in {
|
||||||
def check(looker: ActorRef, result: ActorRef, elems: String*): Unit = {
|
def check(looker: ActorRef, result: ActorRef, elems: String*): Unit = {
|
||||||
askNode(looker, SelectString(elems mkString "/")) should ===(Some(result))
|
askNode(looker, SelectString(elems.mkString("/"))) should ===(Some(result))
|
||||||
askNode(looker, SelectString(elems mkString ("", "/", "/"))) should ===(Some(result))
|
askNode(looker, SelectString(elems.mkString("", "/", "/"))) should ===(Some(result))
|
||||||
}
|
}
|
||||||
check(c1, user, "..")
|
check(c1, user, "..")
|
||||||
for {
|
for {
|
||||||
|
|
@ -253,13 +252,11 @@ class ActorSelectionSpec extends AkkaSpec with DefaultTimeout {
|
||||||
}
|
}
|
||||||
def check(looker: ActorRef): Unit = {
|
def check(looker: ActorRef): Unit = {
|
||||||
val lookname = looker.path.elements.mkString("", "/", "/")
|
val lookname = looker.path.elements.mkString("", "/", "/")
|
||||||
for (
|
for ((l, r) <- Seq(SelectString("a/b/c") -> None,
|
||||||
(l, r) <- Seq(
|
|
||||||
SelectString("a/b/c") -> None,
|
|
||||||
SelectString("akka://all-systems/Nobody") -> None,
|
SelectString("akka://all-systems/Nobody") -> None,
|
||||||
SelectPath(system / "hallo") -> None,
|
SelectPath(system / "hallo") -> None,
|
||||||
SelectPath(looker.path child "hallo") -> None, // test Java API
|
SelectPath(looker.path.child("hallo")) -> None, // test Java API
|
||||||
SelectPath(looker.path descendant Seq("a", "b").asJava) -> None) // test Java API
|
SelectPath(looker.path.descendant(Seq("a", "b").asJava)) -> None) // test Java API
|
||||||
) checkOne(looker, l, r)
|
) checkOne(looker, l, r)
|
||||||
}
|
}
|
||||||
for (looker <- all) check(looker)
|
for (looker <- all) check(looker)
|
||||||
|
|
@ -341,7 +338,8 @@ class ActorSelectionSpec extends AkkaSpec with DefaultTimeout {
|
||||||
|
|
||||||
"have a stringly serializable path" in {
|
"have a stringly serializable path" in {
|
||||||
system.actorSelection(system / "c2").toSerializationFormat should ===("akka://ActorSelectionSpec/user/c2")
|
system.actorSelection(system / "c2").toSerializationFormat should ===("akka://ActorSelectionSpec/user/c2")
|
||||||
system.actorSelection(system / "c2" / "c21").toSerializationFormat should ===("akka://ActorSelectionSpec/user/c2/c21")
|
system.actorSelection(system / "c2" / "c21").toSerializationFormat should ===(
|
||||||
|
"akka://ActorSelectionSpec/user/c2/c21")
|
||||||
ActorSelection(c2, "/").toSerializationFormat should ===("akka://ActorSelectionSpec/user/c2")
|
ActorSelection(c2, "/").toSerializationFormat should ===("akka://ActorSelectionSpec/user/c2")
|
||||||
ActorSelection(c2, "../*/hello").toSerializationFormat should ===("akka://ActorSelectionSpec/user/c2/../*/hello")
|
ActorSelection(c2, "../*/hello").toSerializationFormat should ===("akka://ActorSelectionSpec/user/c2/../*/hello")
|
||||||
ActorSelection(c2, "/../*/hello").toSerializationFormat should ===("akka://ActorSelectionSpec/user/c2/../*/hello")
|
ActorSelection(c2, "/../*/hello").toSerializationFormat should ===("akka://ActorSelectionSpec/user/c2/../*/hello")
|
||||||
|
|
@ -368,7 +366,8 @@ class ActorSelectionSpec extends AkkaSpec with DefaultTimeout {
|
||||||
|
|
||||||
val probe = TestProbe()
|
val probe = TestProbe()
|
||||||
system.actorSelection("/user/a/*").tell(Identify(1), probe.ref)
|
system.actorSelection("/user/a/*").tell(Identify(1), probe.ref)
|
||||||
probe.receiveN(2).map { case ActorIdentity(1, r) => r }.toSet should ===(Set[Option[ActorRef]](Some(b1), Some(b2)))
|
probe.receiveN(2).map { case ActorIdentity(1, r) => r }.toSet should ===(
|
||||||
|
Set[Option[ActorRef]](Some(b1), Some(b2)))
|
||||||
probe.expectNoMsg(200.millis)
|
probe.expectNoMsg(200.millis)
|
||||||
|
|
||||||
system.actorSelection("/user/a/b1/*").tell(Identify(2), probe.ref)
|
system.actorSelection("/user/a/b1/*").tell(Identify(2), probe.ref)
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ object ActorSystemSpec {
|
||||||
terminaters -= child
|
terminaters -= child
|
||||||
if (terminaters.isEmpty) {
|
if (terminaters.isEmpty) {
|
||||||
master ! "done"
|
master ! "done"
|
||||||
context stop self
|
context.stop(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ object ActorSystemSpec {
|
||||||
if (master ne null) {
|
if (master ne null) {
|
||||||
master ! "failed with " + cause + " while processing " + msg
|
master ! "failed with " + cause + " while processing " + msg
|
||||||
}
|
}
|
||||||
context stop self
|
context.stop(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,16 +73,18 @@ object ActorSystemSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SlowDispatcher(_config: Config, _prerequisites: DispatcherPrerequisites) extends MessageDispatcherConfigurator(_config, _prerequisites) {
|
class SlowDispatcher(_config: Config, _prerequisites: DispatcherPrerequisites)
|
||||||
private val instance = new Dispatcher(
|
extends MessageDispatcherConfigurator(_config, _prerequisites) {
|
||||||
this,
|
private val instance = new Dispatcher(this,
|
||||||
config.getString("id"),
|
config.getString("id"),
|
||||||
config.getInt("throughput"),
|
config.getInt("throughput"),
|
||||||
config.getNanosDuration("throughput-deadline-time"),
|
config.getNanosDuration("throughput-deadline-time"),
|
||||||
configureExecutor(),
|
configureExecutor(),
|
||||||
config.getMillisDuration("shutdown-timeout")) {
|
config.getMillisDuration("shutdown-timeout")) {
|
||||||
val doneIt = new Switch
|
val doneIt = new Switch
|
||||||
override protected[akka] def registerForExecution(mbox: Mailbox, hasMessageHint: Boolean, hasSystemMessageHint: Boolean): Boolean = {
|
override protected[akka] def registerForExecution(mbox: Mailbox,
|
||||||
|
hasMessageHint: Boolean,
|
||||||
|
hasSystemMessageHint: Boolean): Boolean = {
|
||||||
val ret = super.registerForExecution(mbox, hasMessageHint, hasSystemMessageHint)
|
val ret = super.registerForExecution(mbox, hasMessageHint, hasSystemMessageHint)
|
||||||
doneIt.switchOn {
|
doneIt.switchOn {
|
||||||
TestKit.awaitCond(mbox.actor.actor != null, 1.second)
|
TestKit.awaitCond(mbox.actor.actor != null, 1.second)
|
||||||
|
|
@ -127,21 +129,19 @@ class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSend
|
||||||
"An ActorSystem" must {
|
"An ActorSystem" must {
|
||||||
|
|
||||||
"use scala.concurrent.Future's InternalCallbackEC" in {
|
"use scala.concurrent.Future's InternalCallbackEC" in {
|
||||||
system.asInstanceOf[ActorSystemImpl].internalCallingThreadExecutionContext.getClass.getName should ===("scala.concurrent.Future$InternalCallbackExecutor$")
|
system.asInstanceOf[ActorSystemImpl].internalCallingThreadExecutionContext.getClass.getName should ===(
|
||||||
|
"scala.concurrent.Future$InternalCallbackExecutor$")
|
||||||
}
|
}
|
||||||
|
|
||||||
"reject invalid names" in {
|
"reject invalid names" in {
|
||||||
for (
|
for (n <- Seq("-hallowelt",
|
||||||
n <- Seq(
|
|
||||||
"-hallowelt",
|
|
||||||
"_hallowelt",
|
"_hallowelt",
|
||||||
"hallo*welt",
|
"hallo*welt",
|
||||||
"hallo@welt",
|
"hallo@welt",
|
||||||
"hallo#welt",
|
"hallo#welt",
|
||||||
"hallo$welt",
|
"hallo$welt",
|
||||||
"hallo%welt",
|
"hallo%welt",
|
||||||
"hallo/welt")
|
"hallo/welt")) intercept[IllegalArgumentException] {
|
||||||
) intercept[IllegalArgumentException] {
|
|
||||||
ActorSystem(n)
|
ActorSystem(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,15 +151,21 @@ class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSend
|
||||||
}
|
}
|
||||||
|
|
||||||
"log dead letters" in {
|
"log dead letters" in {
|
||||||
val sys = ActorSystem("LogDeadLetters", ConfigFactory.parseString("akka.loglevel=INFO").withFallback(AkkaSpec.testConf))
|
val sys =
|
||||||
|
ActorSystem("LogDeadLetters", ConfigFactory.parseString("akka.loglevel=INFO").withFallback(AkkaSpec.testConf))
|
||||||
try {
|
try {
|
||||||
val probe = TestProbe()(sys)
|
val probe = TestProbe()(sys)
|
||||||
val a = sys.actorOf(Props[ActorSystemSpec.Terminater])
|
val a = sys.actorOf(Props[ActorSystemSpec.Terminater])
|
||||||
probe.watch(a)
|
probe.watch(a)
|
||||||
a.tell("run", probe.ref)
|
a.tell("run", probe.ref)
|
||||||
probe.expectTerminated(a)
|
probe.expectTerminated(a)
|
||||||
EventFilter.info(pattern = """from Actor\[akka://LogDeadLetters/system/testProbe.*not delivered""", occurrences = 1).intercept {
|
EventFilter
|
||||||
EventFilter.warning(pattern = """received dead letter from Actor\[akka://LogDeadLetters/system/testProbe""", occurrences = 1).intercept {
|
.info(pattern = """from Actor\[akka://LogDeadLetters/system/testProbe.*not delivered""", occurrences = 1)
|
||||||
|
.intercept {
|
||||||
|
EventFilter
|
||||||
|
.warning(pattern = """received dead letter from Actor\[akka://LogDeadLetters/system/testProbe""",
|
||||||
|
occurrences = 1)
|
||||||
|
.intercept {
|
||||||
a.tell("boom", probe.ref)
|
a.tell("boom", probe.ref)
|
||||||
}(sys)
|
}(sys)
|
||||||
}(sys)
|
}(sys)
|
||||||
|
|
@ -168,15 +174,20 @@ class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSend
|
||||||
}
|
}
|
||||||
|
|
||||||
"log dead letters sent without sender reference" in {
|
"log dead letters sent without sender reference" in {
|
||||||
val sys = ActorSystem("LogDeadLetters", ConfigFactory.parseString("akka.loglevel=INFO").withFallback(AkkaSpec.testConf))
|
val sys =
|
||||||
|
ActorSystem("LogDeadLetters", ConfigFactory.parseString("akka.loglevel=INFO").withFallback(AkkaSpec.testConf))
|
||||||
try {
|
try {
|
||||||
val probe = TestProbe()(sys)
|
val probe = TestProbe()(sys)
|
||||||
val a = sys.actorOf(Props[ActorSystemSpec.Terminater])
|
val a = sys.actorOf(Props[ActorSystemSpec.Terminater])
|
||||||
probe.watch(a)
|
probe.watch(a)
|
||||||
a.tell("run", probe.ref)
|
a.tell("run", probe.ref)
|
||||||
probe.expectTerminated(a)
|
probe.expectTerminated(a)
|
||||||
EventFilter.info(pattern = "without sender.*not delivered", occurrences = 1).intercept {
|
EventFilter
|
||||||
EventFilter.warning(pattern = "received dead letter without sender", occurrences = 1).intercept {
|
.info(pattern = "without sender.*not delivered", occurrences = 1)
|
||||||
|
.intercept {
|
||||||
|
EventFilter
|
||||||
|
.warning(pattern = "received dead letter without sender", occurrences = 1)
|
||||||
|
.intercept {
|
||||||
a.tell("boom", ActorRef.noSender)
|
a.tell("boom", ActorRef.noSender)
|
||||||
}(sys)
|
}(sys)
|
||||||
}(sys)
|
}(sys)
|
||||||
|
|
@ -193,7 +204,7 @@ class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSend
|
||||||
for (i <- 1 to count) {
|
for (i <- 1 to count) {
|
||||||
system2.registerOnTermination {
|
system2.registerOnTermination {
|
||||||
Thread.sleep((i % 3).millis.dilated.toMillis)
|
Thread.sleep((i % 3).millis.dilated.toMillis)
|
||||||
result add i
|
result.add(i)
|
||||||
latch.countDown()
|
latch.countDown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +243,7 @@ class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSend
|
||||||
terminated.actor should ===(system.provider.rootGuardian)
|
terminated.actor should ===(system.provider.rootGuardian)
|
||||||
terminated.addressTerminated should ===(true)
|
terminated.addressTerminated should ===(true)
|
||||||
terminated.existenceConfirmed should ===(true)
|
terminated.existenceConfirmed should ===(true)
|
||||||
terminated should be theSameInstanceAs Await.result(f, 10 seconds)
|
(terminated should be).theSameInstanceAs(Await.result(f, 10 seconds))
|
||||||
}
|
}
|
||||||
|
|
||||||
"throw RejectedExecutionException when shutdown" in {
|
"throw RejectedExecutionException when shutdown" in {
|
||||||
|
|
@ -295,21 +306,24 @@ class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
created filter (ref => !ref.isTerminated && !ref.asInstanceOf[ActorRefWithCell].underlying.isInstanceOf[UnstartedCell]) should ===(Seq.empty[ActorRef])
|
created.filter(ref =>
|
||||||
|
!ref.isTerminated && !ref.asInstanceOf[ActorRefWithCell].underlying.isInstanceOf[UnstartedCell]) should ===(
|
||||||
|
Seq.empty[ActorRef])
|
||||||
}
|
}
|
||||||
|
|
||||||
"shut down when /user fails" in {
|
"shut down when /user fails" in {
|
||||||
implicit val system = ActorSystem("Stop", AkkaSpec.testConf)
|
implicit val system = ActorSystem("Stop", AkkaSpec.testConf)
|
||||||
EventFilter[ActorKilledException]() intercept {
|
EventFilter[ActorKilledException]().intercept {
|
||||||
system.actorSelection("/user") ! Kill
|
system.actorSelection("/user") ! Kill
|
||||||
Await.ready(system.whenTerminated, Duration.Inf)
|
Await.ready(system.whenTerminated, Duration.Inf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"allow configuration of guardian supervisor strategy" in {
|
"allow configuration of guardian supervisor strategy" in {
|
||||||
implicit val system = ActorSystem(
|
implicit val system =
|
||||||
"Stop",
|
ActorSystem("Stop",
|
||||||
ConfigFactory.parseString("akka.actor.guardian-supervisor-strategy=akka.actor.StoppingSupervisorStrategy")
|
ConfigFactory
|
||||||
|
.parseString("akka.actor.guardian-supervisor-strategy=akka.actor.StoppingSupervisorStrategy")
|
||||||
.withFallback(AkkaSpec.testConf))
|
.withFallback(AkkaSpec.testConf))
|
||||||
val a = system.actorOf(Props(new Actor {
|
val a = system.actorOf(Props(new Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
|
|
@ -318,7 +332,7 @@ class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSend
|
||||||
}))
|
}))
|
||||||
val probe = TestProbe()
|
val probe = TestProbe()
|
||||||
probe.watch(a)
|
probe.watch(a)
|
||||||
EventFilter[Exception]("hello", occurrences = 1) intercept {
|
EventFilter[Exception]("hello", occurrences = 1).intercept {
|
||||||
a ! "die"
|
a ! "die"
|
||||||
}
|
}
|
||||||
val t = probe.expectMsg(Terminated(a)(existenceConfirmed = true, addressTerminated = false))
|
val t = probe.expectMsg(Terminated(a)(existenceConfirmed = true, addressTerminated = false))
|
||||||
|
|
@ -328,16 +342,17 @@ class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSend
|
||||||
}
|
}
|
||||||
|
|
||||||
"shut down when /user escalates" in {
|
"shut down when /user escalates" in {
|
||||||
implicit val system = ActorSystem(
|
implicit val system =
|
||||||
"Stop",
|
ActorSystem("Stop",
|
||||||
ConfigFactory.parseString("akka.actor.guardian-supervisor-strategy=\"akka.actor.ActorSystemSpec$Strategy\"")
|
ConfigFactory
|
||||||
|
.parseString("akka.actor.guardian-supervisor-strategy=\"akka.actor.ActorSystemSpec$Strategy\"")
|
||||||
.withFallback(AkkaSpec.testConf))
|
.withFallback(AkkaSpec.testConf))
|
||||||
val a = system.actorOf(Props(new Actor {
|
val a = system.actorOf(Props(new Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
case "die" => throw new Exception("hello")
|
case "die" => throw new Exception("hello")
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
EventFilter[Exception]("hello") intercept {
|
EventFilter[Exception]("hello").intercept {
|
||||||
a ! "die"
|
a ! "die"
|
||||||
Await.ready(system.whenTerminated, Duration.Inf)
|
Await.ready(system.whenTerminated, Duration.Inf)
|
||||||
}
|
}
|
||||||
|
|
@ -388,8 +403,12 @@ class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSend
|
||||||
}
|
}
|
||||||
|
|
||||||
"not allow top-level actor creation with custom guardian" in {
|
"not allow top-level actor creation with custom guardian" in {
|
||||||
val sys = new ActorSystemImpl("custom", ConfigFactory.defaultReference(),
|
val sys = new ActorSystemImpl("custom",
|
||||||
getClass.getClassLoader, None, Some(Props.empty), ActorSystemSetup.empty)
|
ConfigFactory.defaultReference(),
|
||||||
|
getClass.getClassLoader,
|
||||||
|
None,
|
||||||
|
Some(Props.empty),
|
||||||
|
ActorSystemSetup.empty)
|
||||||
sys.start()
|
sys.start()
|
||||||
try {
|
try {
|
||||||
intercept[UnsupportedOperationException] {
|
intercept[UnsupportedOperationException] {
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,13 @@ object ActorWithBoundedStashSpec {
|
||||||
def receive = {
|
def receive = {
|
||||||
case msg: String if msg.startsWith("hello") =>
|
case msg: String if msg.startsWith("hello") =>
|
||||||
numStashed += 1
|
numStashed += 1
|
||||||
try { stash(); sender() ! "ok" } catch {
|
try {
|
||||||
|
stash(); sender() ! "ok"
|
||||||
|
} catch {
|
||||||
case _: StashOverflowException =>
|
case _: StashOverflowException =>
|
||||||
if (numStashed == 21) {
|
if (numStashed == 21) {
|
||||||
sender() ! "STASHOVERFLOW"
|
sender() ! "STASHOVERFLOW"
|
||||||
context stop self
|
context.stop(self)
|
||||||
} else {
|
} else {
|
||||||
sender() ! "Unexpected StashOverflowException: " + numStashed
|
sender() ! "Unexpected StashOverflowException: " + numStashed
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +84,11 @@ object ActorWithBoundedStashSpec {
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
class ActorWithBoundedStashSpec extends AkkaSpec(ActorWithBoundedStashSpec.testConf) with BeforeAndAfterEach with DefaultTimeout with ImplicitSender {
|
class ActorWithBoundedStashSpec
|
||||||
|
extends AkkaSpec(ActorWithBoundedStashSpec.testConf)
|
||||||
|
with BeforeAndAfterEach
|
||||||
|
with DefaultTimeout
|
||||||
|
with ImplicitSender {
|
||||||
import ActorWithBoundedStashSpec._
|
import ActorWithBoundedStashSpec._
|
||||||
|
|
||||||
override def atStartup: Unit = {
|
override def atStartup: Unit = {
|
||||||
|
|
|
||||||
|
|
@ -142,8 +142,9 @@ class ActorWithStashSpec extends AkkaSpec(ActorWithStashSpec.testConf) with Defa
|
||||||
}
|
}
|
||||||
|
|
||||||
"process stashed messages after restart" in {
|
"process stashed messages after restart" in {
|
||||||
val boss = system.actorOf(Props(new Supervisor(
|
val boss = system.actorOf(
|
||||||
OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 1 second)(List(classOf[Throwable])))))
|
Props(
|
||||||
|
new Supervisor(OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 1 second)(List(classOf[Throwable])))))
|
||||||
|
|
||||||
val restartLatch = new TestLatch
|
val restartLatch = new TestLatch
|
||||||
val hasMsgLatch = new TestLatch
|
val hasMsgLatch = new TestLatch
|
||||||
|
|
@ -196,7 +197,7 @@ class ActorWithStashSpec extends AkkaSpec(ActorWithStashSpec.testConf) with Defa
|
||||||
testActor ! "restarted"
|
testActor ! "restarted"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
EventFilter[RuntimeException]("dying", occurrences = 1) intercept {
|
EventFilter[RuntimeException]("dying", occurrences = 1).intercept {
|
||||||
a ! "die"
|
a ! "die"
|
||||||
}
|
}
|
||||||
expectMsg("restarted")
|
expectMsg("restarted")
|
||||||
|
|
|
||||||
|
|
@ -47,19 +47,22 @@ object Chameneos {
|
||||||
}
|
}
|
||||||
|
|
||||||
def complement(otherColour: Colour): Colour = colour match {
|
def complement(otherColour: Colour): Colour = colour match {
|
||||||
case RED => otherColour match {
|
case RED =>
|
||||||
|
otherColour match {
|
||||||
case RED => RED
|
case RED => RED
|
||||||
case YELLOW => BLUE
|
case YELLOW => BLUE
|
||||||
case BLUE => YELLOW
|
case BLUE => YELLOW
|
||||||
case FADED => FADED
|
case FADED => FADED
|
||||||
}
|
}
|
||||||
case YELLOW => otherColour match {
|
case YELLOW =>
|
||||||
|
otherColour match {
|
||||||
case RED => BLUE
|
case RED => BLUE
|
||||||
case YELLOW => YELLOW
|
case YELLOW => YELLOW
|
||||||
case BLUE => RED
|
case BLUE => RED
|
||||||
case FADED => FADED
|
case FADED => FADED
|
||||||
}
|
}
|
||||||
case BLUE => otherColour match {
|
case BLUE =>
|
||||||
|
otherColour match {
|
||||||
case RED => YELLOW
|
case RED => YELLOW
|
||||||
case YELLOW => RED
|
case YELLOW => RED
|
||||||
case BLUE => BLUE
|
case BLUE => BLUE
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ object ConsistencySpec {
|
||||||
var lastStep = -1L
|
var lastStep = -1L
|
||||||
def receive = {
|
def receive = {
|
||||||
case step: Long =>
|
case step: Long =>
|
||||||
|
|
||||||
if (lastStep != (step - 1))
|
if (lastStep != (step - 1))
|
||||||
sender() ! "Test failed: Last step %s, this step %s".format(lastStep, step)
|
sender() ! "Test failed: Last step %s, this step %s".format(lastStep, step)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ import scala.collection.JavaConverters._
|
||||||
import scala.concurrent.Promise
|
import scala.concurrent.Promise
|
||||||
import java.util.concurrent.TimeoutException
|
import java.util.concurrent.TimeoutException
|
||||||
|
|
||||||
class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
class CoordinatedShutdownSpec
|
||||||
"""
|
extends AkkaSpec(ConfigFactory.parseString("""
|
||||||
akka.loglevel=INFO
|
akka.loglevel=INFO
|
||||||
akka.loggers = ["akka.testkit.TestEventListener"]
|
akka.loggers = ["akka.testkit.TestEventListener"]
|
||||||
""")) {
|
""")) {
|
||||||
|
|
@ -38,7 +38,8 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
phases.get(phase) match {
|
phases.get(phase) match {
|
||||||
case Some(Phase(dependsOn, _, _, _)) =>
|
case Some(Phase(dependsOn, _, _, _)) =>
|
||||||
dependsOn.foreach { depPhase =>
|
dependsOn.foreach { depPhase =>
|
||||||
withClue(s"phase [$phase] depends on [$depPhase] but was ordered before it in topological sort result $result") {
|
withClue(
|
||||||
|
s"phase [$phase] depends on [$depPhase] but was ordered before it in topological sort result $result") {
|
||||||
i should be > result.indexOf(depPhase)
|
i should be > result.indexOf(depPhase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -55,38 +56,29 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
"sort phases in topological order" in {
|
"sort phases in topological order" in {
|
||||||
checkTopologicalSort(Map.empty) should ===(Nil)
|
checkTopologicalSort(Map.empty) should ===(Nil)
|
||||||
|
|
||||||
checkTopologicalSort(Map(
|
checkTopologicalSort(Map("a" -> emptyPhase)) should ===(List("a"))
|
||||||
"a" -> emptyPhase)) should ===(List("a"))
|
|
||||||
|
|
||||||
checkTopologicalSort(Map(
|
checkTopologicalSort(Map("b" -> phase("a"))) should ===(List("a", "b"))
|
||||||
"b" -> phase("a"))) should ===(List("a", "b"))
|
|
||||||
|
|
||||||
val result1 = checkTopologicalSort(Map(
|
val result1 = checkTopologicalSort(Map("c" -> phase("a"), "b" -> phase("a")))
|
||||||
"c" -> phase("a"), "b" -> phase("a")))
|
|
||||||
result1.head should ===("a")
|
result1.head should ===("a")
|
||||||
// b, c can be in any order
|
// b, c can be in any order
|
||||||
result1.toSet should ===(Set("a", "b", "c"))
|
result1.toSet should ===(Set("a", "b", "c"))
|
||||||
|
|
||||||
checkTopologicalSort(Map(
|
checkTopologicalSort(Map("b" -> phase("a"), "c" -> phase("b"))) should ===(List("a", "b", "c"))
|
||||||
"b" -> phase("a"), "c" -> phase("b"))) should ===(List("a", "b", "c"))
|
|
||||||
|
|
||||||
checkTopologicalSort(Map(
|
checkTopologicalSort(Map("b" -> phase("a"), "c" -> phase("a", "b"))) should ===(List("a", "b", "c"))
|
||||||
"b" -> phase("a"), "c" -> phase("a", "b"))) should ===(List("a", "b", "c"))
|
|
||||||
|
|
||||||
val result2 = checkTopologicalSort(Map(
|
val result2 = checkTopologicalSort(Map("c" -> phase("a", "b")))
|
||||||
"c" -> phase("a", "b")))
|
|
||||||
result2.last should ===("c")
|
result2.last should ===("c")
|
||||||
// a, b can be in any order
|
// a, b can be in any order
|
||||||
result2.toSet should ===(Set("a", "b", "c"))
|
result2.toSet should ===(Set("a", "b", "c"))
|
||||||
|
|
||||||
checkTopologicalSort(Map(
|
checkTopologicalSort(Map("b" -> phase("a"), "c" -> phase("b"), "d" -> phase("b", "c"), "e" -> phase("d"))) should ===(
|
||||||
"b" -> phase("a"), "c" -> phase("b"), "d" -> phase("b", "c"),
|
|
||||||
"e" -> phase("d"))) should ===(
|
|
||||||
List("a", "b", "c", "d", "e"))
|
List("a", "b", "c", "d", "e"))
|
||||||
|
|
||||||
val result3 = checkTopologicalSort(Map(
|
val result3 =
|
||||||
"a2" -> phase("a1"), "a3" -> phase("a2"),
|
checkTopologicalSort(Map("a2" -> phase("a1"), "a3" -> phase("a2"), "b2" -> phase("b1"), "b3" -> phase("b2")))
|
||||||
"b2" -> phase("b1"), "b3" -> phase("b2")))
|
|
||||||
val (a, b) = result3.partition(_.charAt(0) == 'a')
|
val (a, b) = result3.partition(_.charAt(0) == 'a')
|
||||||
a should ===(List("a1", "a2", "a3"))
|
a should ===(List("a1", "a2", "a3"))
|
||||||
b should ===(List("b1", "b2", "b3"))
|
b should ===(List("b1", "b2", "b3"))
|
||||||
|
|
@ -94,31 +86,28 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
|
|
||||||
"detect cycles in phases (non-DAG)" in {
|
"detect cycles in phases (non-DAG)" in {
|
||||||
intercept[IllegalArgumentException] {
|
intercept[IllegalArgumentException] {
|
||||||
CoordinatedShutdown.topologicalSort(Map(
|
CoordinatedShutdown.topologicalSort(Map("a" -> phase("a")))
|
||||||
"a" -> phase("a")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
intercept[IllegalArgumentException] {
|
intercept[IllegalArgumentException] {
|
||||||
CoordinatedShutdown.topologicalSort(Map(
|
CoordinatedShutdown.topologicalSort(Map("b" -> phase("a"), "a" -> phase("b")))
|
||||||
"b" -> phase("a"), "a" -> phase("b")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
intercept[IllegalArgumentException] {
|
intercept[IllegalArgumentException] {
|
||||||
CoordinatedShutdown.topologicalSort(Map(
|
CoordinatedShutdown.topologicalSort(Map("c" -> phase("a"), "c" -> phase("b"), "b" -> phase("c")))
|
||||||
"c" -> phase("a"), "c" -> phase("b"), "b" -> phase("c")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
intercept[IllegalArgumentException] {
|
intercept[IllegalArgumentException] {
|
||||||
CoordinatedShutdown.topologicalSort(Map(
|
CoordinatedShutdown.topologicalSort(
|
||||||
"d" -> phase("a"), "d" -> phase("c"), "c" -> phase("b"), "b" -> phase("d")))
|
Map("d" -> phase("a"), "d" -> phase("c"), "c" -> phase("b"), "b" -> phase("d")))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"have pre-defined phases from config" in {
|
"have pre-defined phases from config" in {
|
||||||
import CoordinatedShutdown._
|
import CoordinatedShutdown._
|
||||||
CoordinatedShutdown(system).orderedPhases should ===(List(
|
CoordinatedShutdown(system).orderedPhases should ===(
|
||||||
PhaseBeforeServiceUnbind,
|
List(PhaseBeforeServiceUnbind,
|
||||||
PhaseServiceUnbind,
|
PhaseServiceUnbind,
|
||||||
PhaseServiceRequestsDone,
|
PhaseServiceRequestsDone,
|
||||||
PhaseServiceStop,
|
PhaseServiceStop,
|
||||||
|
|
@ -134,10 +123,7 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
|
|
||||||
"run ordered phases" in {
|
"run ordered phases" in {
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
val phases = Map(
|
val phases = Map("a" -> emptyPhase, "b" -> phase("a"), "c" -> phase("b", "a"))
|
||||||
"a" -> emptyPhase,
|
|
||||||
"b" -> phase("a"),
|
|
||||||
"c" -> phase("b", "a"))
|
|
||||||
val co = new CoordinatedShutdown(extSys, phases)
|
val co = new CoordinatedShutdown(extSys, phases)
|
||||||
co.addTask("a", "a1") { () =>
|
co.addTask("a", "a1") { () =>
|
||||||
testActor ! "A"
|
testActor ! "A"
|
||||||
|
|
@ -164,10 +150,7 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
}
|
}
|
||||||
|
|
||||||
"run from a given phase" in {
|
"run from a given phase" in {
|
||||||
val phases = Map(
|
val phases = Map("a" -> emptyPhase, "b" -> phase("a"), "c" -> phase("b", "a"))
|
||||||
"a" -> emptyPhase,
|
|
||||||
"b" -> phase("a"),
|
|
||||||
"c" -> phase("b", "a"))
|
|
||||||
val co = new CoordinatedShutdown(extSys, phases)
|
val co = new CoordinatedShutdown(extSys, phases)
|
||||||
co.addTask("a", "a1") { () =>
|
co.addTask("a", "a1") { () =>
|
||||||
testActor ! "A"
|
testActor ! "A"
|
||||||
|
|
@ -205,8 +188,7 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
|
|
||||||
"continue after timeout or failure" in {
|
"continue after timeout or failure" in {
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
val phases = Map(
|
val phases = Map("a" -> emptyPhase,
|
||||||
"a" -> emptyPhase,
|
|
||||||
"b" -> Phase(dependsOn = Set("a"), timeout = 100.millis, recover = true, enabled = true),
|
"b" -> Phase(dependsOn = Set("a"), timeout = 100.millis, recover = true, enabled = true),
|
||||||
"c" -> phase("b", "a"))
|
"c" -> phase("b", "a"))
|
||||||
val co = new CoordinatedShutdown(extSys, phases)
|
val co = new CoordinatedShutdown(extSys, phases)
|
||||||
|
|
@ -231,7 +213,9 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
Future.successful(Done)
|
Future.successful(Done)
|
||||||
}
|
}
|
||||||
EventFilter.warning(message = "Task [a1] failed in phase [a]: boom", occurrences = 1).intercept {
|
EventFilter.warning(message = "Task [a1] failed in phase [a]: boom", occurrences = 1).intercept {
|
||||||
EventFilter.warning(message = "Coordinated shutdown phase [b] timed out after 100 milliseconds", occurrences = 1).intercept {
|
EventFilter
|
||||||
|
.warning(message = "Coordinated shutdown phase [b] timed out after 100 milliseconds", occurrences = 1)
|
||||||
|
.intercept {
|
||||||
Await.result(co.run(UnknownReason), remainingOrDefault)
|
Await.result(co.run(UnknownReason), remainingOrDefault)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -242,8 +226,7 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
}
|
}
|
||||||
|
|
||||||
"abort if recover=off" in {
|
"abort if recover=off" in {
|
||||||
val phases = Map(
|
val phases = Map("a" -> emptyPhase,
|
||||||
"a" -> emptyPhase,
|
|
||||||
"b" -> Phase(dependsOn = Set("a"), timeout = 100.millis, recover = false, enabled = true),
|
"b" -> Phase(dependsOn = Set("a"), timeout = 100.millis, recover = false, enabled = true),
|
||||||
"c" -> phase("b", "a"))
|
"c" -> phase("b", "a"))
|
||||||
val co = new CoordinatedShutdown(extSys, phases)
|
val co = new CoordinatedShutdown(extSys, phases)
|
||||||
|
|
@ -264,8 +247,7 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
}
|
}
|
||||||
|
|
||||||
"skip tasks in disabled phase" in {
|
"skip tasks in disabled phase" in {
|
||||||
val phases = Map(
|
val phases = Map("a" -> emptyPhase,
|
||||||
"a" -> emptyPhase,
|
|
||||||
"b" -> Phase(dependsOn = Set("a"), timeout = 100.millis, recover = false, enabled = false),
|
"b" -> Phase(dependsOn = Set("a"), timeout = 100.millis, recover = false, enabled = false),
|
||||||
"c" -> phase("b", "a"))
|
"c" -> phase("b", "a"))
|
||||||
val co = new CoordinatedShutdown(extSys, phases)
|
val co = new CoordinatedShutdown(extSys, phases)
|
||||||
|
|
@ -285,9 +267,7 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
}
|
}
|
||||||
|
|
||||||
"be possible to add tasks in later phase from task in earlier phase" in {
|
"be possible to add tasks in later phase from task in earlier phase" in {
|
||||||
val phases = Map(
|
val phases = Map("a" -> emptyPhase, "b" -> phase("a"))
|
||||||
"a" -> emptyPhase,
|
|
||||||
"b" -> phase("a"))
|
|
||||||
val co = new CoordinatedShutdown(extSys, phases)
|
val co = new CoordinatedShutdown(extSys, phases)
|
||||||
co.addTask("a", "a1") { () =>
|
co.addTask("a", "a1") { () =>
|
||||||
testActor ! "A"
|
testActor ! "A"
|
||||||
|
|
@ -303,8 +283,7 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
}
|
}
|
||||||
|
|
||||||
"parse phases from config" in {
|
"parse phases from config" in {
|
||||||
CoordinatedShutdown.phasesFromConfig(ConfigFactory.parseString(
|
CoordinatedShutdown.phasesFromConfig(ConfigFactory.parseString("""
|
||||||
"""
|
|
||||||
default-phase-timeout = 10s
|
default-phase-timeout = 10s
|
||||||
phases {
|
phases {
|
||||||
a = {}
|
a = {}
|
||||||
|
|
@ -317,8 +296,8 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
recover = off
|
recover = off
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""")) should ===(Map(
|
""")) should ===(
|
||||||
"a" -> Phase(dependsOn = Set.empty, timeout = 10.seconds, recover = true, enabled = true),
|
Map("a" -> Phase(dependsOn = Set.empty, timeout = 10.seconds, recover = true, enabled = true),
|
||||||
"b" -> Phase(dependsOn = Set("a"), timeout = 15.seconds, recover = true, enabled = true),
|
"b" -> Phase(dependsOn = Set("a"), timeout = 15.seconds, recover = true, enabled = true),
|
||||||
"c" -> Phase(dependsOn = Set("a", "b"), timeout = 10.seconds, recover = false, enabled = true)))
|
"c" -> Phase(dependsOn = Set("a", "b"), timeout = 10.seconds, recover = false, enabled = true)))
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +310,8 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
|
|
||||||
"default exit code to -1 when the Reason is ClusterDowning" in {
|
"default exit code to -1 when the Reason is ClusterDowning" in {
|
||||||
lazy val conf = ConfigFactory.load().getConfig("akka.coordinated-shutdown")
|
lazy val conf = ConfigFactory.load().getConfig("akka.coordinated-shutdown")
|
||||||
val confWithOverrides = CoordinatedShutdown.confWithOverrides(conf, Some(CoordinatedShutdown.ClusterDowningReason))
|
val confWithOverrides =
|
||||||
|
CoordinatedShutdown.confWithOverrides(conf, Some(CoordinatedShutdown.ClusterDowningReason))
|
||||||
confWithOverrides.getInt("exit-code") should ===(-1)
|
confWithOverrides.getInt("exit-code") should ===(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -344,16 +324,14 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
|
|
||||||
"add and remove user JVM hooks with run-by-jvm-shutdown-hook = off, terminate-actor-system = off" in new JvmHookTest {
|
"add and remove user JVM hooks with run-by-jvm-shutdown-hook = off, terminate-actor-system = off" in new JvmHookTest {
|
||||||
lazy val systemName = s"CoordinatedShutdownSpec-JvmHooks-1-${System.currentTimeMillis()}"
|
lazy val systemName = s"CoordinatedShutdownSpec-JvmHooks-1-${System.currentTimeMillis()}"
|
||||||
lazy val systemConfig = ConfigFactory.parseString(
|
lazy val systemConfig = ConfigFactory.parseString("""
|
||||||
"""
|
|
||||||
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = off
|
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = off
|
||||||
akka.coordinated-shutdown.terminate-actor-system = off
|
akka.coordinated-shutdown.terminate-actor-system = off
|
||||||
""")
|
""")
|
||||||
|
|
||||||
override def withSystemRunning(newSystem: ActorSystem): Unit = {
|
override def withSystemRunning(newSystem: ActorSystem): Unit = {
|
||||||
val cancellable = CoordinatedShutdown(newSystem).addCancellableJvmShutdownHook(
|
val cancellable =
|
||||||
println(s"User JVM hook from ${newSystem.name}")
|
CoordinatedShutdown(newSystem).addCancellableJvmShutdownHook(println(s"User JVM hook from ${newSystem.name}"))
|
||||||
)
|
|
||||||
myHooksCount should ===(1) // one user, none from system
|
myHooksCount should ===(1) // one user, none from system
|
||||||
cancellable.cancel()
|
cancellable.cancel()
|
||||||
}
|
}
|
||||||
|
|
@ -361,16 +339,14 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
|
|
||||||
"add and remove user JVM hooks with run-by-jvm-shutdown-hook = on, terminate-actor-system = off" in new JvmHookTest {
|
"add and remove user JVM hooks with run-by-jvm-shutdown-hook = on, terminate-actor-system = off" in new JvmHookTest {
|
||||||
lazy val systemName = s"CoordinatedShutdownSpec-JvmHooks-2-${System.currentTimeMillis()}"
|
lazy val systemName = s"CoordinatedShutdownSpec-JvmHooks-2-${System.currentTimeMillis()}"
|
||||||
lazy val systemConfig = ConfigFactory.parseString(
|
lazy val systemConfig = ConfigFactory.parseString("""
|
||||||
"""
|
|
||||||
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = on
|
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = on
|
||||||
akka.coordinated-shutdown.terminate-actor-system = off
|
akka.coordinated-shutdown.terminate-actor-system = off
|
||||||
""")
|
""")
|
||||||
|
|
||||||
override def withSystemRunning(newSystem: ActorSystem): Unit = {
|
override def withSystemRunning(newSystem: ActorSystem): Unit = {
|
||||||
val cancellable = CoordinatedShutdown(newSystem).addCancellableJvmShutdownHook(
|
val cancellable =
|
||||||
println(s"User JVM hook from ${newSystem.name}")
|
CoordinatedShutdown(newSystem).addCancellableJvmShutdownHook(println(s"User JVM hook from ${newSystem.name}"))
|
||||||
)
|
|
||||||
myHooksCount should ===(2) // one user, one from system
|
myHooksCount should ===(2) // one user, one from system
|
||||||
|
|
||||||
cancellable.cancel()
|
cancellable.cancel()
|
||||||
|
|
@ -379,16 +355,14 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
|
|
||||||
"add and remove user JVM hooks with run-by-jvm-shutdown-hook = on, terminate-actor-system = on" in new JvmHookTest {
|
"add and remove user JVM hooks with run-by-jvm-shutdown-hook = on, terminate-actor-system = on" in new JvmHookTest {
|
||||||
lazy val systemName = s"CoordinatedShutdownSpec-JvmHooks-3-${System.currentTimeMillis()}"
|
lazy val systemName = s"CoordinatedShutdownSpec-JvmHooks-3-${System.currentTimeMillis()}"
|
||||||
lazy val systemConfig = ConfigFactory.parseString(
|
lazy val systemConfig = ConfigFactory.parseString("""
|
||||||
"""
|
|
||||||
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = on
|
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = on
|
||||||
akka.coordinated-shutdown.terminate-actor-system = on
|
akka.coordinated-shutdown.terminate-actor-system = on
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def withSystemRunning(newSystem: ActorSystem): Unit = {
|
def withSystemRunning(newSystem: ActorSystem): Unit = {
|
||||||
val cancellable = CoordinatedShutdown(newSystem).addCancellableJvmShutdownHook(
|
val cancellable =
|
||||||
println(s"User JVM hook from ${newSystem.name}")
|
CoordinatedShutdown(newSystem).addCancellableJvmShutdownHook(println(s"User JVM hook from ${newSystem.name}"))
|
||||||
)
|
|
||||||
myHooksCount should ===(2) // one user, one from actor system
|
myHooksCount should ===(2) // one user, one from actor system
|
||||||
cancellable.cancel()
|
cancellable.cancel()
|
||||||
}
|
}
|
||||||
|
|
@ -396,16 +370,14 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
|
|
||||||
"add and remove user JVM hooks with run-by-jvm-shutdown-hook = on, akka.jvm-shutdown-hooks = off" in new JvmHookTest {
|
"add and remove user JVM hooks with run-by-jvm-shutdown-hook = on, akka.jvm-shutdown-hooks = off" in new JvmHookTest {
|
||||||
lazy val systemName = s"CoordinatedShutdownSpec-JvmHooks-4-${System.currentTimeMillis()}"
|
lazy val systemName = s"CoordinatedShutdownSpec-JvmHooks-4-${System.currentTimeMillis()}"
|
||||||
lazy val systemConfig = ConfigFactory.parseString(
|
lazy val systemConfig = ConfigFactory.parseString("""
|
||||||
"""
|
|
||||||
akka.jvm-shutdown-hooks = off
|
akka.jvm-shutdown-hooks = off
|
||||||
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = on
|
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = on
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def withSystemRunning(newSystem: ActorSystem): Unit = {
|
def withSystemRunning(newSystem: ActorSystem): Unit = {
|
||||||
val cancellable = CoordinatedShutdown(newSystem).addCancellableJvmShutdownHook(
|
val cancellable =
|
||||||
println(s"User JVM hook from ${newSystem.name}")
|
CoordinatedShutdown(newSystem).addCancellableJvmShutdownHook(println(s"User JVM hook from ${newSystem.name}"))
|
||||||
)
|
|
||||||
myHooksCount should ===(1) // one user, none from actor system
|
myHooksCount should ===(1) // one user, none from actor system
|
||||||
cancellable.cancel()
|
cancellable.cancel()
|
||||||
}
|
}
|
||||||
|
|
@ -413,8 +385,7 @@ class CoordinatedShutdownSpec extends AkkaSpec(ConfigFactory.parseString(
|
||||||
|
|
||||||
"access extension after system termination" in new JvmHookTest {
|
"access extension after system termination" in new JvmHookTest {
|
||||||
lazy val systemName = s"CoordinatedShutdownSpec-terminated-${System.currentTimeMillis()}"
|
lazy val systemName = s"CoordinatedShutdownSpec-terminated-${System.currentTimeMillis()}"
|
||||||
lazy val systemConfig = ConfigFactory.parseString(
|
lazy val systemConfig = ConfigFactory.parseString("""
|
||||||
"""
|
|
||||||
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = on
|
akka.coordinated-shutdown.run-by-jvm-shutdown-hook = on
|
||||||
akka.coordinated-shutdown.terminate-actor-system = on
|
akka.coordinated-shutdown.terminate-actor-system = on
|
||||||
""")
|
""")
|
||||||
|
|
|
||||||
|
|
@ -78,4 +78,3 @@ class DeadLetterSupressionSpec extends AkkaSpec with ImplicitSender {
|
||||||
allListener.expectNoMsg(Duration.Zero)
|
allListener.expectNoMsg(Duration.Zero)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ object DeathWatchSpec {
|
||||||
class Watcher(target: ActorRef, testActor: ActorRef) extends Actor {
|
class Watcher(target: ActorRef, testActor: ActorRef) extends Actor {
|
||||||
context.watch(target)
|
context.watch(target)
|
||||||
def receive = {
|
def receive = {
|
||||||
case t: Terminated => testActor forward WrappedTerminated(t)
|
case t: Terminated => testActor.forward(WrappedTerminated(t))
|
||||||
case x => testActor forward x
|
case x => testActor.forward(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,9 +36,11 @@ object DeathWatchSpec {
|
||||||
class NKOTBWatcher(testActor: ActorRef) extends Actor {
|
class NKOTBWatcher(testActor: ActorRef) extends Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
case "NKOTB" =>
|
case "NKOTB" =>
|
||||||
val currentKid = context.watch(context.actorOf(Props(new Actor { def receive = { case "NKOTB" => context stop self } }), "kid"))
|
val currentKid = context.watch(context.actorOf(Props(new Actor {
|
||||||
currentKid forward "NKOTB"
|
def receive = { case "NKOTB" => context.stop(self) }
|
||||||
context become {
|
}), "kid"))
|
||||||
|
currentKid.forward("NKOTB")
|
||||||
|
context.become {
|
||||||
case Terminated(`currentKid`) =>
|
case Terminated(`currentKid`) =>
|
||||||
testActor ! "GREEN"
|
testActor ! "GREEN"
|
||||||
context unbecome
|
context unbecome
|
||||||
|
|
@ -48,8 +50,8 @@ object DeathWatchSpec {
|
||||||
|
|
||||||
class WUWatcher extends Actor {
|
class WUWatcher extends Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
case W(ref) => context watch ref
|
case W(ref) => context.watch(ref)
|
||||||
case U(ref) => context unwatch ref
|
case U(ref) => context.unwatch(ref)
|
||||||
case Latches(t1: TestLatch, t2: TestLatch) =>
|
case Latches(t1: TestLatch, t2: TestLatch) =>
|
||||||
t1.countDown()
|
t1.countDown()
|
||||||
Await.ready(t2, 3.seconds)
|
Await.ready(t2, 3.seconds)
|
||||||
|
|
@ -78,7 +80,8 @@ trait DeathWatchSpec { this: AkkaSpec with ImplicitSender with DefaultTimeout =>
|
||||||
def startWatching(target: ActorRef) = Await.result((supervisor ? props(target, testActor)).mapTo[ActorRef], 3 seconds)
|
def startWatching(target: ActorRef) = Await.result((supervisor ? props(target, testActor)).mapTo[ActorRef], 3 seconds)
|
||||||
|
|
||||||
"The Death Watch" must {
|
"The Death Watch" must {
|
||||||
def expectTerminationOf(actorRef: ActorRef) = expectMsgPF(5 seconds, actorRef + ": Stopped or Already terminated when linking") {
|
def expectTerminationOf(actorRef: ActorRef) =
|
||||||
|
expectMsgPF(5 seconds, actorRef + ": Stopped or Already terminated when linking") {
|
||||||
case WrappedTerminated(Terminated(`actorRef`)) => true
|
case WrappedTerminated(Terminated(`actorRef`)) => true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,8 +147,8 @@ trait DeathWatchSpec { this: AkkaSpec with ImplicitSender with DefaultTimeout =>
|
||||||
|
|
||||||
"notify with a Terminated message once when an Actor is stopped but not when restarted" in {
|
"notify with a Terminated message once when an Actor is stopped but not when restarted" in {
|
||||||
filterException[ActorKilledException] {
|
filterException[ActorKilledException] {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor =
|
||||||
OneForOneStrategy(maxNrOfRetries = 2)(List(classOf[Exception])))))
|
system.actorOf(Props(new Supervisor(OneForOneStrategy(maxNrOfRetries = 2)(List(classOf[Exception])))))
|
||||||
val terminalProps = TestActors.echoActorProps
|
val terminalProps = TestActors.echoActorProps
|
||||||
val terminal = Await.result((supervisor ? terminalProps).mapTo[ActorRef], timeout.duration)
|
val terminal = Await.result((supervisor ? terminalProps).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
||||||
|
|
@ -166,7 +169,11 @@ trait DeathWatchSpec { this: AkkaSpec with ImplicitSender with DefaultTimeout =>
|
||||||
"fail a monitor which does not handle Terminated()" in {
|
"fail a monitor which does not handle Terminated()" in {
|
||||||
filterEvents(EventFilter[ActorKilledException](), EventFilter[DeathPactException]()) {
|
filterEvents(EventFilter[ActorKilledException](), EventFilter[DeathPactException]()) {
|
||||||
val strategy = new OneForOneStrategy()(SupervisorStrategy.defaultStrategy.decider) {
|
val strategy = new OneForOneStrategy()(SupervisorStrategy.defaultStrategy.decider) {
|
||||||
override def handleFailure(context: ActorContext, child: ActorRef, cause: Throwable, stats: ChildRestartStats, children: Iterable[ChildRestartStats]) = {
|
override def handleFailure(context: ActorContext,
|
||||||
|
child: ActorRef,
|
||||||
|
cause: Throwable,
|
||||||
|
stats: ChildRestartStats,
|
||||||
|
children: Iterable[ChildRestartStats]) = {
|
||||||
testActor.tell(FF(Failed(child, cause, 0)), child)
|
testActor.tell(FF(Failed(child, cause, 0)), child)
|
||||||
super.handleFailure(context, child, cause, stats, children)
|
super.handleFailure(context, child, cause, stats, children)
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +181,8 @@ trait DeathWatchSpec { this: AkkaSpec with ImplicitSender with DefaultTimeout =>
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(strategy)).withDeploy(Deploy.local))
|
val supervisor = system.actorOf(Props(new Supervisor(strategy)).withDeploy(Deploy.local))
|
||||||
|
|
||||||
val failed = Await.result((supervisor ? Props.empty).mapTo[ActorRef], timeout.duration)
|
val failed = Await.result((supervisor ? Props.empty).mapTo[ActorRef], timeout.duration)
|
||||||
val brother = Await.result((supervisor ? Props(classOf[EmptyWatcher], failed)).mapTo[ActorRef], timeout.duration)
|
val brother =
|
||||||
|
Await.result((supervisor ? Props(classOf[EmptyWatcher], failed)).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
||||||
startWatching(brother)
|
startWatching(brother)
|
||||||
|
|
||||||
|
|
@ -201,7 +209,8 @@ trait DeathWatchSpec { this: AkkaSpec with ImplicitSender with DefaultTimeout =>
|
||||||
"only notify when watching" in {
|
"only notify when watching" in {
|
||||||
val subject = system.actorOf(Props[EmptyActor]())
|
val subject = system.actorOf(Props[EmptyActor]())
|
||||||
|
|
||||||
testActor.asInstanceOf[InternalActorRef]
|
testActor
|
||||||
|
.asInstanceOf[InternalActorRef]
|
||||||
.sendSystemMessage(DeathWatchNotification(subject, existenceConfirmed = true, addressTerminated = false))
|
.sendSystemMessage(DeathWatchNotification(subject, existenceConfirmed = true, addressTerminated = false))
|
||||||
|
|
||||||
// the testActor is not watching subject and will not receive a Terminated msg
|
// the testActor is not watching subject and will not receive a Terminated msg
|
||||||
|
|
@ -216,7 +225,7 @@ trait DeathWatchSpec { this: AkkaSpec with ImplicitSender with DefaultTimeout =>
|
||||||
w ! Latches(t1, t2)
|
w ! Latches(t1, t2)
|
||||||
Await.ready(t1, 3.seconds)
|
Await.ready(t1, 3.seconds)
|
||||||
watch(p.ref)
|
watch(p.ref)
|
||||||
system stop p.ref
|
system.stop(p.ref)
|
||||||
expectTerminated(p.ref)
|
expectTerminated(p.ref)
|
||||||
w ! U(p.ref)
|
w ! U(p.ref)
|
||||||
t2.countDown()
|
t2.countDown()
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,8 @@ object DeployerSpec {
|
||||||
router = round-robin-pool
|
router = round-robin-pool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""", ConfigParseOptions.defaults)
|
""",
|
||||||
|
ConfigParseOptions.defaults)
|
||||||
|
|
||||||
class RecipeActor extends Actor {
|
class RecipeActor extends Actor {
|
||||||
def receive = { case _ => }
|
def receive = { case _ => }
|
||||||
|
|
@ -82,9 +83,9 @@ class DeployerSpec extends AkkaSpec(DeployerSpec.deployerConf) {
|
||||||
val service = "/service1"
|
val service = "/service1"
|
||||||
val deployment = system.asInstanceOf[ExtendedActorSystem].provider.deployer.lookup(service.split("/").drop(1))
|
val deployment = system.asInstanceOf[ExtendedActorSystem].provider.deployer.lookup(service.split("/").drop(1))
|
||||||
|
|
||||||
deployment should ===(Some(
|
deployment should ===(
|
||||||
Deploy(
|
Some(
|
||||||
service,
|
Deploy(service,
|
||||||
deployment.get.config,
|
deployment.get.config,
|
||||||
NoRouter,
|
NoRouter,
|
||||||
NoScopeGiven,
|
NoScopeGiven,
|
||||||
|
|
@ -102,9 +103,9 @@ class DeployerSpec extends AkkaSpec(DeployerSpec.deployerConf) {
|
||||||
val service = "/service3"
|
val service = "/service3"
|
||||||
val deployment = system.asInstanceOf[ExtendedActorSystem].provider.deployer.lookup(service.split("/").drop(1))
|
val deployment = system.asInstanceOf[ExtendedActorSystem].provider.deployer.lookup(service.split("/").drop(1))
|
||||||
|
|
||||||
deployment should ===(Some(
|
deployment should ===(
|
||||||
Deploy(
|
Some(
|
||||||
service,
|
Deploy(service,
|
||||||
deployment.get.config,
|
deployment.get.config,
|
||||||
NoRouter,
|
NoRouter,
|
||||||
NoScopeGiven,
|
NoScopeGiven,
|
||||||
|
|
@ -116,9 +117,9 @@ class DeployerSpec extends AkkaSpec(DeployerSpec.deployerConf) {
|
||||||
val service = "/service4"
|
val service = "/service4"
|
||||||
val deployment = system.asInstanceOf[ExtendedActorSystem].provider.deployer.lookup(service.split("/").drop(1))
|
val deployment = system.asInstanceOf[ExtendedActorSystem].provider.deployer.lookup(service.split("/").drop(1))
|
||||||
|
|
||||||
deployment should ===(Some(
|
deployment should ===(
|
||||||
Deploy(
|
Some(
|
||||||
service,
|
Deploy(service,
|
||||||
deployment.get.config,
|
deployment.get.config,
|
||||||
NoRouter,
|
NoRouter,
|
||||||
NoScopeGiven,
|
NoScopeGiven,
|
||||||
|
|
@ -128,14 +129,17 @@ class DeployerSpec extends AkkaSpec(DeployerSpec.deployerConf) {
|
||||||
|
|
||||||
"detect invalid number-of-instances" in {
|
"detect invalid number-of-instances" in {
|
||||||
intercept[com.typesafe.config.ConfigException.WrongType] {
|
intercept[com.typesafe.config.ConfigException.WrongType] {
|
||||||
val invalidDeployerConf = ConfigFactory.parseString("""
|
val invalidDeployerConf = ConfigFactory
|
||||||
|
.parseString("""
|
||||||
akka.actor.deployment {
|
akka.actor.deployment {
|
||||||
/service-invalid-number-of-instances {
|
/service-invalid-number-of-instances {
|
||||||
router = round-robin-pool
|
router = round-robin-pool
|
||||||
nr-of-instances = boom
|
nr-of-instances = boom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""", ConfigParseOptions.defaults).withFallback(AkkaSpec.testConf)
|
""",
|
||||||
|
ConfigParseOptions.defaults)
|
||||||
|
.withFallback(AkkaSpec.testConf)
|
||||||
|
|
||||||
shutdown(ActorSystem("invalid-number-of-instances", invalidDeployerConf))
|
shutdown(ActorSystem("invalid-number-of-instances", invalidDeployerConf))
|
||||||
}
|
}
|
||||||
|
|
@ -143,14 +147,17 @@ class DeployerSpec extends AkkaSpec(DeployerSpec.deployerConf) {
|
||||||
|
|
||||||
"detect invalid deployment path" in {
|
"detect invalid deployment path" in {
|
||||||
val e = intercept[InvalidActorNameException] {
|
val e = intercept[InvalidActorNameException] {
|
||||||
val invalidDeployerConf = ConfigFactory.parseString("""
|
val invalidDeployerConf = ConfigFactory
|
||||||
|
.parseString("""
|
||||||
akka.actor.deployment {
|
akka.actor.deployment {
|
||||||
/gul/ubåt {
|
/gul/ubåt {
|
||||||
router = round-robin-pool
|
router = round-robin-pool
|
||||||
nr-of-instances = 2
|
nr-of-instances = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""", ConfigParseOptions.defaults).withFallback(AkkaSpec.testConf)
|
""",
|
||||||
|
ConfigParseOptions.defaults)
|
||||||
|
.withFallback(AkkaSpec.testConf)
|
||||||
|
|
||||||
shutdown(ActorSystem("invalid-path", invalidDeployerConf))
|
shutdown(ActorSystem("invalid-path", invalidDeployerConf))
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +182,9 @@ class DeployerSpec extends AkkaSpec(DeployerSpec.deployerConf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
"be able to parse 'akka.actor.deployment._' with scatter-gather router" in {
|
"be able to parse 'akka.actor.deployment._' with scatter-gather router" in {
|
||||||
assertRouting("/service-scatter-gather", ScatterGatherFirstCompletedPool(nrOfInstances = 1, within = 2 seconds), "/service-scatter-gather")
|
assertRouting("/service-scatter-gather",
|
||||||
|
ScatterGatherFirstCompletedPool(nrOfInstances = 1, within = 2 seconds),
|
||||||
|
"/service-scatter-gather")
|
||||||
}
|
}
|
||||||
|
|
||||||
"be able to parse 'akka.actor.deployment._' with consistent-hashing router" in {
|
"be able to parse 'akka.actor.deployment._' with consistent-hashing router" in {
|
||||||
|
|
@ -189,7 +198,9 @@ class DeployerSpec extends AkkaSpec(DeployerSpec.deployerConf) {
|
||||||
|
|
||||||
"be able to use wildcards" in {
|
"be able to use wildcards" in {
|
||||||
assertRouting("/some/wildcardmatch", RandomPool(1), "/some/*")
|
assertRouting("/some/wildcardmatch", RandomPool(1), "/some/*")
|
||||||
assertRouting("/somewildcardmatch/some", ScatterGatherFirstCompletedPool(nrOfInstances = 1, within = 2 seconds), "/*/some")
|
assertRouting("/somewildcardmatch/some",
|
||||||
|
ScatterGatherFirstCompletedPool(nrOfInstances = 1, within = 2 seconds),
|
||||||
|
"/*/some")
|
||||||
}
|
}
|
||||||
|
|
||||||
"be able to use double wildcards" in {
|
"be able to use double wildcards" in {
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,8 @@ class ExtensionSpec extends WordSpec with Matchers {
|
||||||
|
|
||||||
"fail the actor system if an extension listed in akka.extensions fails to start" in {
|
"fail the actor system if an extension listed in akka.extensions fails to start" in {
|
||||||
intercept[RuntimeException] {
|
intercept[RuntimeException] {
|
||||||
val system = ActorSystem("failing", ConfigFactory.parseString(
|
val system = ActorSystem("failing",
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
akka.extensions = ["akka.actor.FailingTestExtension"]
|
akka.extensions = ["akka.actor.FailingTestExtension"]
|
||||||
"""))
|
"""))
|
||||||
|
|
||||||
|
|
@ -94,8 +94,8 @@ class ExtensionSpec extends WordSpec with Matchers {
|
||||||
}
|
}
|
||||||
|
|
||||||
"log an error if an extension listed in akka.extensions cannot be loaded" in {
|
"log an error if an extension listed in akka.extensions cannot be loaded" in {
|
||||||
val system = ActorSystem("failing", ConfigFactory.parseString(
|
val system = ActorSystem("failing",
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
akka.extensions = ["akka.actor.MissingExtension"]
|
akka.extensions = ["akka.actor.MissingExtension"]
|
||||||
"""))
|
"""))
|
||||||
EventFilter.error("While trying to load extension [akka.actor.MissingExtension], skipping.").intercept(())(system)
|
EventFilter.error("While trying to load extension [akka.actor.MissingExtension], skipping.").intercept(())(system)
|
||||||
|
|
@ -114,8 +114,8 @@ class ExtensionSpec extends WordSpec with Matchers {
|
||||||
|
|
||||||
"fail the actor system if a library-extension fails to start" in {
|
"fail the actor system if a library-extension fails to start" in {
|
||||||
intercept[FailingTestExtension.TestException] {
|
intercept[FailingTestExtension.TestException] {
|
||||||
ActorSystem("failing", ConfigFactory.parseString(
|
ActorSystem("failing",
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
akka.library-extensions += "akka.actor.FailingTestExtension"
|
akka.library-extensions += "akka.actor.FailingTestExtension"
|
||||||
""").withFallback(ConfigFactory.load()).resolve())
|
""").withFallback(ConfigFactory.load()).resolve())
|
||||||
}
|
}
|
||||||
|
|
@ -124,8 +124,8 @@ class ExtensionSpec extends WordSpec with Matchers {
|
||||||
|
|
||||||
"fail the actor system if a library-extension cannot be loaded" in {
|
"fail the actor system if a library-extension cannot be loaded" in {
|
||||||
intercept[RuntimeException] {
|
intercept[RuntimeException] {
|
||||||
ActorSystem("failing", ConfigFactory.parseString(
|
ActorSystem("failing",
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
akka.library-extensions += "akka.actor.MissingExtension"
|
akka.library-extensions += "akka.actor.MissingExtension"
|
||||||
""").withFallback(ConfigFactory.load()))
|
""").withFallback(ConfigFactory.load()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,17 +42,17 @@ object FSMActorSpec {
|
||||||
case Event(digit: Char, CodeState(soFar, code)) => {
|
case Event(digit: Char, CodeState(soFar, code)) => {
|
||||||
soFar + digit match {
|
soFar + digit match {
|
||||||
case incomplete if incomplete.length < code.length =>
|
case incomplete if incomplete.length < code.length =>
|
||||||
stay using CodeState(incomplete, code)
|
stay.using(CodeState(incomplete, code))
|
||||||
case codeTry if (codeTry == code) => {
|
case codeTry if (codeTry == code) => {
|
||||||
doUnlock()
|
doUnlock()
|
||||||
goto(Open) using CodeState("", code) forMax timeout
|
goto(Open).using(CodeState("", code)).forMax(timeout)
|
||||||
}
|
}
|
||||||
case wrong => {
|
case wrong => {
|
||||||
stay using CodeState("", code)
|
stay.using(CodeState("", code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case Event("hello", _) => stay replying "world"
|
case Event("hello", _) => stay.replying("world")
|
||||||
case Event("bye", _) => stop(FSM.Shutdown)
|
case Event("bye", _) => stop(FSM.Shutdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
|
||||||
|
|
||||||
"unlock the lock" in {
|
"unlock the lock" in {
|
||||||
|
|
||||||
import FSM.{ Transition, CurrentState, SubscribeTransitionCallBack }
|
import FSM.{ CurrentState, SubscribeTransitionCallBack, Transition }
|
||||||
|
|
||||||
val latches = new Latches
|
val latches = new Latches
|
||||||
import latches._
|
import latches._
|
||||||
|
|
@ -138,7 +138,7 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
|
||||||
Await.ready(transitionCallBackLatch, timeout.duration)
|
Await.ready(transitionCallBackLatch, timeout.duration)
|
||||||
Await.ready(lockedLatch, timeout.duration)
|
Await.ready(lockedLatch, timeout.duration)
|
||||||
|
|
||||||
EventFilter.warning(start = "unhandled event", occurrences = 1) intercept {
|
EventFilter.warning(start = "unhandled event", occurrences = 1).intercept {
|
||||||
lock ! "not_handled"
|
lock ! "not_handled"
|
||||||
Await.ready(unhandledLatch, timeout.duration)
|
Await.ready(unhandledLatch, timeout.duration)
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +166,7 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
val name = fsm.path.toString
|
val name = fsm.path.toString
|
||||||
EventFilter.error("Next state 2 does not exist", occurrences = 1) intercept {
|
EventFilter.error("Next state 2 does not exist", occurrences = 1).intercept {
|
||||||
system.eventStream.subscribe(testActor, classOf[Logging.Error])
|
system.eventStream.subscribe(testActor, classOf[Logging.Error])
|
||||||
fsm ! "go"
|
fsm ! "go"
|
||||||
expectMsgPF(1 second, hint = "Next state 2 does not exist") {
|
expectMsgPF(1 second, hint = "Next state 2 does not exist") {
|
||||||
|
|
@ -218,7 +218,7 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
|
||||||
lazy val fsmref = TestFSMRef(new Actor with FSM[String, Null] {
|
lazy val fsmref = TestFSMRef(new Actor with FSM[String, Null] {
|
||||||
startWith("not-started", null)
|
startWith("not-started", null)
|
||||||
when("not-started") {
|
when("not-started") {
|
||||||
case Event("start", _) => goto("started") replying "starting"
|
case Event("start", _) => goto("started").replying("starting")
|
||||||
}
|
}
|
||||||
when("started", stateTimeout = 10 seconds) {
|
when("started", stateTimeout = 10 seconds) {
|
||||||
case Event("stop", _) => stop()
|
case Event("stop", _) => stop()
|
||||||
|
|
@ -252,12 +252,15 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
|
||||||
|
|
||||||
"log events and transitions if asked to do so" in {
|
"log events and transitions if asked to do so" in {
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
val config = ConfigFactory.parseMap(Map("akka.loglevel" -> "DEBUG", "akka.actor.serialize-messages" -> "off",
|
val config = ConfigFactory
|
||||||
"akka.actor.debug.fsm" -> true).asJava).withFallback(system.settings.config)
|
.parseMap(Map("akka.loglevel" -> "DEBUG",
|
||||||
|
"akka.actor.serialize-messages" -> "off",
|
||||||
|
"akka.actor.debug.fsm" -> true).asJava)
|
||||||
|
.withFallback(system.settings.config)
|
||||||
val fsmEventSystem = ActorSystem("fsmEvent", config)
|
val fsmEventSystem = ActorSystem("fsmEvent", config)
|
||||||
try {
|
try {
|
||||||
new TestKit(fsmEventSystem) {
|
new TestKit(fsmEventSystem) {
|
||||||
EventFilter.debug(occurrences = 5) intercept {
|
EventFilter.debug(occurrences = 5).intercept {
|
||||||
val fsm = TestActorRef(new Actor with LoggingFSM[Int, Null] {
|
val fsm = TestActorRef(new Actor with LoggingFSM[Int, Null] {
|
||||||
startWith(1, null)
|
startWith(1, null)
|
||||||
when(1) {
|
when(1) {
|
||||||
|
|
@ -279,13 +282,17 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
|
||||||
system.eventStream.subscribe(testActor, classOf[Logging.Debug])
|
system.eventStream.subscribe(testActor, classOf[Logging.Debug])
|
||||||
fsm ! "go"
|
fsm ! "go"
|
||||||
expectMsgPF(1 second, hint = "processing Event(go,null)") {
|
expectMsgPF(1 second, hint = "processing Event(go,null)") {
|
||||||
case Logging.Debug(`name`, `fsmClass`, s: String) if s.startsWith("processing Event(go,null) from Actor[") => true
|
case Logging.Debug(`name`, `fsmClass`, s: String)
|
||||||
|
if s.startsWith("processing Event(go,null) from Actor[") =>
|
||||||
|
true
|
||||||
}
|
}
|
||||||
expectMsg(1 second, Logging.Debug(name, fsmClass, "setting timer 't'/1500 milliseconds: Shutdown"))
|
expectMsg(1 second, Logging.Debug(name, fsmClass, "setting timer 't'/1500 milliseconds: Shutdown"))
|
||||||
expectMsg(1 second, Logging.Debug(name, fsmClass, "transition 1 -> 2"))
|
expectMsg(1 second, Logging.Debug(name, fsmClass, "transition 1 -> 2"))
|
||||||
fsm ! "stop"
|
fsm ! "stop"
|
||||||
expectMsgPF(1 second, hint = "processing Event(stop,null)") {
|
expectMsgPF(1 second, hint = "processing Event(stop,null)") {
|
||||||
case Logging.Debug(`name`, `fsmClass`, s: String) if s.startsWith("processing Event(stop,null) from Actor[") => true
|
case Logging.Debug(`name`, `fsmClass`, s: String)
|
||||||
|
if s.startsWith("processing Event(stop,null) from Actor[") =>
|
||||||
|
true
|
||||||
}
|
}
|
||||||
expectMsgAllOf(1 second, Logging.Debug(name, fsmClass, "canceling timer 't'"), FSM.Normal)
|
expectMsgAllOf(1 second, Logging.Debug(name, fsmClass, "canceling timer 't'"), FSM.Normal)
|
||||||
expectNoMsg(1 second)
|
expectNoMsg(1 second)
|
||||||
|
|
@ -302,8 +309,8 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
|
||||||
override def logDepth = 3
|
override def logDepth = 3
|
||||||
startWith(1, 0)
|
startWith(1, 0)
|
||||||
when(1) {
|
when(1) {
|
||||||
case Event("count", c) => stay using (c + 1)
|
case Event("count", c) => stay.using(c + 1)
|
||||||
case Event("log", _) => stay replying getLog
|
case Event("log", _) => stay.replying(getLog)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
fsmref ! "log"
|
fsmref ! "log"
|
||||||
|
|
@ -324,7 +331,7 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
|
||||||
startWith(0, 0)
|
startWith(0, 0)
|
||||||
when(0)(transform {
|
when(0)(transform {
|
||||||
case Event("go", _) => stay
|
case Event("go", _) => stay
|
||||||
} using {
|
}.using {
|
||||||
case x => goto(1)
|
case x => goto(1)
|
||||||
})
|
})
|
||||||
when(1) {
|
when(1) {
|
||||||
|
|
@ -354,7 +361,7 @@ class FSMActorSpec extends AkkaSpec(Map("akka.actor.debug.fsm" -> true)) with Im
|
||||||
|
|
||||||
case Event(OverrideTimeoutToInf, _) =>
|
case Event(OverrideTimeoutToInf, _) =>
|
||||||
p.ref ! OverrideTimeoutToInf
|
p.ref ! OverrideTimeoutToInf
|
||||||
stay() forMax Duration.Inf
|
stay().forMax(Duration.Inf)
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize()
|
initialize()
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,8 @@ class FSMTimingSpec extends AkkaSpec with ImplicitSender {
|
||||||
expectMsg(500 millis, Tick)
|
expectMsg(500 millis, Tick)
|
||||||
Thread.sleep(200) // this is ugly: need to wait for StateTimeout to be queued
|
Thread.sleep(200) // this is ugly: need to wait for StateTimeout to be queued
|
||||||
resume(fsm)
|
resume(fsm)
|
||||||
expectMsg(500 millis, Transition(fsm, TestCancelStateTimerInNamedTimerMessage, TestCancelStateTimerInNamedTimerMessage2))
|
expectMsg(500 millis,
|
||||||
|
Transition(fsm, TestCancelStateTimerInNamedTimerMessage, TestCancelStateTimerInNamedTimerMessage2))
|
||||||
fsm ! Cancel
|
fsm ! Cancel
|
||||||
within(500 millis) {
|
within(500 millis) {
|
||||||
expectMsg(Cancel) // if this is not received, that means StateTimeout was not properly discarded
|
expectMsg(Cancel) // if this is not received, that means StateTimeout was not properly discarded
|
||||||
|
|
@ -122,7 +123,7 @@ class FSMTimingSpec extends AkkaSpec with ImplicitSender {
|
||||||
val seq = receiveWhile(2 seconds) {
|
val seq = receiveWhile(2 seconds) {
|
||||||
case Tick => Tick
|
case Tick => Tick
|
||||||
}
|
}
|
||||||
seq should have length 5
|
(seq should have).length(5)
|
||||||
within(500 millis) {
|
within(500 millis) {
|
||||||
expectMsg(Transition(fsm, TestRepeatedTimer, Initial))
|
expectMsg(Transition(fsm, TestRepeatedTimer, Initial))
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +132,9 @@ class FSMTimingSpec extends AkkaSpec with ImplicitSender {
|
||||||
"notify unhandled messages" taggedAs TimingTest in {
|
"notify unhandled messages" taggedAs TimingTest in {
|
||||||
filterEvents(
|
filterEvents(
|
||||||
EventFilter.warning("unhandled event Tick in state TestUnhandled", source = fsm.path.toString, occurrences = 1),
|
EventFilter.warning("unhandled event Tick in state TestUnhandled", source = fsm.path.toString, occurrences = 1),
|
||||||
EventFilter.warning("unhandled event Unhandled(test) in state TestUnhandled", source = fsm.path.toString, occurrences = 1)) {
|
EventFilter.warning("unhandled event Unhandled(test) in state TestUnhandled",
|
||||||
|
source = fsm.path.toString,
|
||||||
|
occurrences = 1)) {
|
||||||
fsm ! TestUnhandled
|
fsm ! TestUnhandled
|
||||||
within(3 second) {
|
within(3 second) {
|
||||||
fsm ! Tick
|
fsm ! Tick
|
||||||
|
|
@ -194,14 +197,14 @@ object FSMTimingSpec {
|
||||||
goto(TestSingleTimer)
|
goto(TestSingleTimer)
|
||||||
case Event(TestRepeatedTimer, _) =>
|
case Event(TestRepeatedTimer, _) =>
|
||||||
setTimer("tester", Tick, 100.millis.dilated, true)
|
setTimer("tester", Tick, 100.millis.dilated, true)
|
||||||
goto(TestRepeatedTimer) using 4
|
goto(TestRepeatedTimer).using(4)
|
||||||
case Event(TestStateTimeoutOverride, _) =>
|
case Event(TestStateTimeoutOverride, _) =>
|
||||||
goto(TestStateTimeout) forMax (Duration.Inf)
|
goto(TestStateTimeout).forMax(Duration.Inf)
|
||||||
case Event(x: FSMTimingSpec.State, _) => goto(x)
|
case Event(x: FSMTimingSpec.State, _) => goto(x)
|
||||||
}
|
}
|
||||||
when(TestStateTimeout, stateTimeout = 800.millis.dilated) {
|
when(TestStateTimeout, stateTimeout = 800.millis.dilated) {
|
||||||
case Event(StateTimeout, _) => goto(Initial)
|
case Event(StateTimeout, _) => goto(Initial)
|
||||||
case Event(Cancel, _) => goto(Initial) replying (Cancel)
|
case Event(Cancel, _) => goto(Initial).replying(Cancel)
|
||||||
}
|
}
|
||||||
when(TestSingleTimer) {
|
when(TestSingleTimer) {
|
||||||
case Event(Tick, _) =>
|
case Event(Tick, _) =>
|
||||||
|
|
@ -242,7 +245,7 @@ object FSMTimingSpec {
|
||||||
cancelTimer("tester")
|
cancelTimer("tester")
|
||||||
goto(Initial)
|
goto(Initial)
|
||||||
} else {
|
} else {
|
||||||
stay using (remaining - 1)
|
stay.using(remaining - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when(TestCancelStateTimerInNamedTimerMessage) {
|
when(TestCancelStateTimerInNamedTimerMessage) {
|
||||||
|
|
@ -251,7 +254,7 @@ object FSMTimingSpec {
|
||||||
suspend(self)
|
suspend(self)
|
||||||
setTimer("named", Tock, 1.millis.dilated)
|
setTimer("named", Tock, 1.millis.dilated)
|
||||||
TestKit.awaitCond(context.asInstanceOf[ActorCell].mailbox.hasMessages, 1.second.dilated)
|
TestKit.awaitCond(context.asInstanceOf[ActorCell].mailbox.hasMessages, 1.second.dilated)
|
||||||
stay forMax (1.millis.dilated) replying Tick
|
stay.forMax(1.millis.dilated).replying(Tick)
|
||||||
case Event(Tock, _) =>
|
case Event(Tock, _) =>
|
||||||
goto(TestCancelStateTimerInNamedTimerMessage2)
|
goto(TestCancelStateTimerInNamedTimerMessage2)
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +262,7 @@ object FSMTimingSpec {
|
||||||
case Event(StateTimeout, _) =>
|
case Event(StateTimeout, _) =>
|
||||||
goto(Initial)
|
goto(Initial)
|
||||||
case Event(Cancel, _) =>
|
case Event(Cancel, _) =>
|
||||||
goto(Initial) replying Cancel
|
goto(Initial).replying(Cancel)
|
||||||
}
|
}
|
||||||
when(TestUnhandled) {
|
when(TestUnhandled) {
|
||||||
case Event(SetHandler, _) =>
|
case Event(SetHandler, _) =>
|
||||||
|
|
@ -286,4 +289,3 @@ object FSMTimingSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ object FSMTransitionSpec {
|
||||||
case Event("tick", _) => goto(0)
|
case Event("tick", _) => goto(0)
|
||||||
}
|
}
|
||||||
whenUnhandled {
|
whenUnhandled {
|
||||||
case Event("reply", _) => stay replying "reply"
|
case Event("reply", _) => stay.replying("reply")
|
||||||
}
|
}
|
||||||
initialize()
|
initialize()
|
||||||
override def preRestart(reason: Throwable, msg: Option[Any]): Unit = { target ! "restarted" }
|
override def preRestart(reason: Throwable, msg: Option[Any]): Unit = { target ! "restarted" }
|
||||||
|
|
@ -45,7 +45,7 @@ object FSMTransitionSpec {
|
||||||
class OtherFSM(target: ActorRef) extends Actor with FSM[Int, Int] {
|
class OtherFSM(target: ActorRef) extends Actor with FSM[Int, Int] {
|
||||||
startWith(0, 0)
|
startWith(0, 0)
|
||||||
when(0) {
|
when(0) {
|
||||||
case Event("tick", _) => goto(1) using 1
|
case Event("tick", _) => goto(1).using(1)
|
||||||
case Event("stay", _) => stay()
|
case Event("stay", _) => stay()
|
||||||
}
|
}
|
||||||
when(1) {
|
when(1) {
|
||||||
|
|
@ -150,7 +150,7 @@ class FSMTransitionSpec extends AkkaSpec with ImplicitSender {
|
||||||
val fsmref = system.actorOf(Props(new Actor with FSM[Int, ActorRef] {
|
val fsmref = system.actorOf(Props(new Actor with FSM[Int, ActorRef] {
|
||||||
startWith(0, null)
|
startWith(0, null)
|
||||||
when(0) {
|
when(0) {
|
||||||
case Event("switch", _) => goto(1) using sender()
|
case Event("switch", _) => goto(1).using(sender())
|
||||||
}
|
}
|
||||||
onTransition {
|
onTransition {
|
||||||
case x -> y => nextStateData ! (x -> y)
|
case x -> y => nextStateData ! (x -> y)
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ object ForwardActorSpec {
|
||||||
def receive = { case x => sender() ! x }
|
def receive = { case x => sender() ! x }
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def mkforwarder(forwardTo: ActorRef) = system.actorOf(Props(
|
def mkforwarder(forwardTo: ActorRef) =
|
||||||
new Actor {
|
system.actorOf(Props(new Actor {
|
||||||
def receive = { case x => forwardTo forward x }
|
def receive = { case x => forwardTo.forward(x) }
|
||||||
}))
|
}))
|
||||||
|
|
||||||
mkforwarder(mkforwarder(mkforwarder(replier)))
|
mkforwarder(mkforwarder(mkforwarder(replier)))
|
||||||
|
|
@ -33,7 +33,9 @@ class ForwardActorSpec extends AkkaSpec {
|
||||||
"A Forward Actor" must {
|
"A Forward Actor" must {
|
||||||
|
|
||||||
"forward actor reference when invoking forward on tell" in {
|
"forward actor reference when invoking forward on tell" in {
|
||||||
val replyTo = system.actorOf(Props(new Actor { def receive = { case ExpectedMessage => testActor ! ExpectedMessage } }))
|
val replyTo = system.actorOf(Props(new Actor {
|
||||||
|
def receive = { case ExpectedMessage => testActor ! ExpectedMessage }
|
||||||
|
}))
|
||||||
|
|
||||||
val chain = createForwardingChain(system)
|
val chain = createForwardingChain(system)
|
||||||
|
|
||||||
|
|
@ -43,7 +45,7 @@ class ForwardActorSpec extends AkkaSpec {
|
||||||
|
|
||||||
"forward actor reference when invoking forward on ask" in {
|
"forward actor reference when invoking forward on ask" in {
|
||||||
val chain = createForwardingChain(system)
|
val chain = createForwardingChain(system)
|
||||||
chain.ask(ExpectedMessage)(5 seconds) pipeTo testActor
|
chain.ask(ExpectedMessage)(5 seconds).pipeTo(testActor)
|
||||||
expectMsg(5 seconds, ExpectedMessage)
|
expectMsg(5 seconds, ExpectedMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,9 @@ class FunctionRefSpec extends AkkaSpec with ImplicitSender {
|
||||||
"not be found" in {
|
"not be found" in {
|
||||||
val provider = system.asInstanceOf[ExtendedActorSystem].provider
|
val provider = system.asInstanceOf[ExtendedActorSystem].provider
|
||||||
val ref = new FunctionRef(testActor.path / "blabla", provider, system, (_, _) => ())
|
val ref = new FunctionRef(testActor.path / "blabla", provider, system, (_, _) => ())
|
||||||
EventFilter[SerializationCheckFailedException](start = "Failed to serialize and deserialize message of type akka.actor.FunctionRefSpec", occurrences = 1) intercept {
|
EventFilter[SerializationCheckFailedException](
|
||||||
|
start = "Failed to serialize and deserialize message of type akka.actor.FunctionRefSpec",
|
||||||
|
occurrences = 1).intercept {
|
||||||
// needs to be something that fails when the deserialized form is not a FunctionRef
|
// needs to be something that fails when the deserialized form is not a FunctionRef
|
||||||
// this relies upon serialize-messages during tests
|
// this relies upon serialize-messages during tests
|
||||||
testActor ! DropForwarder(ref)
|
testActor ! DropForwarder(ref)
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,7 @@ package akka.actor
|
||||||
import akka.testkit._
|
import akka.testkit._
|
||||||
|
|
||||||
object HotSwapSpec {
|
object HotSwapSpec {
|
||||||
abstract class Becomer extends Actor {
|
abstract class Becomer extends Actor {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HotSwapSpec extends AkkaSpec with ImplicitSender {
|
class HotSwapSpec extends AkkaSpec with ImplicitSender {
|
||||||
|
|
@ -79,7 +77,8 @@ class HotSwapSpec extends AkkaSpec with ImplicitSender {
|
||||||
val a = system.actorOf(Props(new Actor {
|
val a = system.actorOf(Props(new Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
case "init" => sender() ! "init"
|
case "init" => sender() ! "init"
|
||||||
case "swap" => context.become({
|
case "swap" =>
|
||||||
|
context.become({
|
||||||
case "swapped" => sender() ! "swapped"
|
case "swapped" => sender() ! "swapped"
|
||||||
case "revert" => context.unbecome()
|
case "revert" => context.unbecome()
|
||||||
})
|
})
|
||||||
|
|
@ -118,7 +117,7 @@ class HotSwapSpec extends AkkaSpec with ImplicitSender {
|
||||||
expectMsg("swapped")
|
expectMsg("swapped")
|
||||||
a ! "state"
|
a ! "state"
|
||||||
expectMsg("1")
|
expectMsg("1")
|
||||||
EventFilter[Exception](message = "Crash (expected)!", occurrences = 1) intercept { a ! "crash" }
|
EventFilter[Exception](message = "Crash (expected)!", occurrences = 1).intercept { a ! "crash" }
|
||||||
a ! "state"
|
a ! "state"
|
||||||
expectMsg("0")
|
expectMsg("0")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,14 +108,14 @@ class LocalActorRefProviderSpec extends AkkaSpec(LocalActorRefProviderSpec.confi
|
||||||
val child = expectMsgType[ActorRef]
|
val child = expectMsgType[ActorRef]
|
||||||
val childProps1 = child.asInstanceOf[LocalActorRef].underlying.props
|
val childProps1 = child.asInstanceOf[LocalActorRef].underlying.props
|
||||||
childProps1 should ===(Props.empty)
|
childProps1 should ===(Props.empty)
|
||||||
system stop a
|
system.stop(a)
|
||||||
expectTerminated(a)
|
expectTerminated(a)
|
||||||
// the fields are cleared after the Terminated message has been sent,
|
// the fields are cleared after the Terminated message has been sent,
|
||||||
// so we need to check for a reasonable time after we receive it
|
// so we need to check for a reasonable time after we receive it
|
||||||
awaitAssert({
|
awaitAssert({
|
||||||
val childProps2 = child.asInstanceOf[LocalActorRef].underlying.props
|
val childProps2 = child.asInstanceOf[LocalActorRef].underlying.props
|
||||||
childProps2 should not be theSameInstanceAs(childProps1)
|
childProps2 should not be theSameInstanceAs(childProps1)
|
||||||
childProps2 should be theSameInstanceAs ActorCell.terminatedProps
|
(childProps2 should be).theSameInstanceAs(ActorCell.terminatedProps)
|
||||||
}, 1 second)
|
}, 1 second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -131,8 +131,10 @@ class LocalActorRefProviderSpec extends AkkaSpec(LocalActorRefProviderSpec.confi
|
||||||
for (i <- 0 until 100) {
|
for (i <- 0 until 100) {
|
||||||
val address = "new-actor" + i
|
val address = "new-actor" + i
|
||||||
implicit val timeout = Timeout(5 seconds)
|
implicit val timeout = Timeout(5 seconds)
|
||||||
val actors = for (j <- 1 to 4) yield Future(system.actorOf(Props(new Actor { def receive = { case _ => } }), address))
|
val actors = for (j <- 1 to 4)
|
||||||
val set = Set() ++ actors.map(a => Await.ready(a, timeout.duration).value match {
|
yield Future(system.actorOf(Props(new Actor { def receive = { case _ => } }), address))
|
||||||
|
val set = Set() ++ actors.map(a =>
|
||||||
|
Await.ready(a, timeout.duration).value match {
|
||||||
case Some(Success(a: ActorRef)) => 1
|
case Some(Success(a: ActorRef)) => 1
|
||||||
case Some(Failure(ex: InvalidActorNameException)) => 2
|
case Some(Failure(ex: InvalidActorNameException)) => 2
|
||||||
case x => x
|
case x => x
|
||||||
|
|
@ -148,7 +150,7 @@ class LocalActorRefProviderSpec extends AkkaSpec(LocalActorRefProviderSpec.confi
|
||||||
val a, b = context.actorOf(Props.empty, "duplicate")
|
val a, b = context.actorOf(Props.empty, "duplicate")
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
EventFilter[InvalidActorNameException](occurrences = 1) intercept {
|
EventFilter[InvalidActorNameException](occurrences = 1).intercept {
|
||||||
supervisor ! ""
|
supervisor ! ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -156,20 +158,33 @@ class LocalActorRefProviderSpec extends AkkaSpec(LocalActorRefProviderSpec.confi
|
||||||
"throw suitable exceptions for malformed actor names" in {
|
"throw suitable exceptions for malformed actor names" in {
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, null)).getMessage should include("null")
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, null)).getMessage should include("null")
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "")).getMessage should include("empty")
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "")).getMessage should include("empty")
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "$hallo")).getMessage should include("not start with `$`")
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "$hallo")).getMessage should include(
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "a%")).getMessage should include("Invalid actor path element")
|
"not start with `$`")
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%3")).getMessage should include("Invalid actor path element")
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "a%")).getMessage should include(
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%xx")).getMessage should include("Invalid actor path element")
|
"Invalid actor path element")
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%0G")).getMessage should include("Invalid actor path element")
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%3")).getMessage should include(
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%gg")).getMessage should include("Invalid actor path element")
|
"Invalid actor path element")
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%")).getMessage should include("Invalid actor path element")
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%xx")).getMessage should include(
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%1t")).getMessage should include("Invalid actor path element")
|
"Invalid actor path element")
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "a?")).getMessage should include("Invalid actor path element")
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%0G")).getMessage should include(
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, "üß")).getMessage should include("include only ASCII")
|
"Invalid actor path element")
|
||||||
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%gg")).getMessage should include(
|
||||||
|
"Invalid actor path element")
|
||||||
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%")).getMessage should include(
|
||||||
|
"Invalid actor path element")
|
||||||
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "%1t")).getMessage should include(
|
||||||
|
"Invalid actor path element")
|
||||||
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "a?")).getMessage should include(
|
||||||
|
"Invalid actor path element")
|
||||||
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, "üß")).getMessage should include(
|
||||||
|
"include only ASCII")
|
||||||
|
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, """he"llo""")).getMessage should include("""["] at position: 2""")
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, """he"llo""")).getMessage should include(
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, """$hello""")).getMessage should include("""[$] at position: 0""")
|
"""["] at position: 2""")
|
||||||
intercept[InvalidActorNameException](system.actorOf(Props.empty, """hell>o""")).getMessage should include("""[>] at position: 4""")
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, """$hello""")).getMessage should include(
|
||||||
|
"""[$] at position: 0""")
|
||||||
|
intercept[InvalidActorNameException](system.actorOf(Props.empty, """hell>o""")).getMessage should include(
|
||||||
|
"""[>] at position: 4""")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,9 @@ class RestartStrategySpec extends AkkaSpec("akka.actor.serialize-messages = off"
|
||||||
"A RestartStrategy" must {
|
"A RestartStrategy" must {
|
||||||
|
|
||||||
"ensure that slave stays dead after max restarts within time range" in {
|
"ensure that slave stays dead after max restarts within time range" in {
|
||||||
val boss = system.actorOf(Props(new Supervisor(
|
val boss = system.actorOf(
|
||||||
OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 1 second)(List(classOf[Throwable])))))
|
Props(
|
||||||
|
new Supervisor(OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 1 second)(List(classOf[Throwable])))))
|
||||||
|
|
||||||
val restartLatch = new TestLatch
|
val restartLatch = new TestLatch
|
||||||
val secondRestartLatch = new TestLatch
|
val secondRestartLatch = new TestLatch
|
||||||
|
|
@ -91,14 +92,16 @@ class RestartStrategySpec extends AkkaSpec("akka.actor.serialize-messages = off"
|
||||||
})
|
})
|
||||||
val slave = Await.result((boss ? slaveProps).mapTo[ActorRef], timeout.duration)
|
val slave = Await.result((boss ? slaveProps).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
||||||
(1 to 100) foreach { _ => slave ! Crash }
|
(1 to 100).foreach { _ =>
|
||||||
|
slave ! Crash
|
||||||
|
}
|
||||||
Await.ready(countDownLatch, 2 minutes)
|
Await.ready(countDownLatch, 2 minutes)
|
||||||
assert(!slave.isTerminated)
|
assert(!slave.isTerminated)
|
||||||
}
|
}
|
||||||
|
|
||||||
"ensure that slave restarts after number of crashes not within time range" in {
|
"ensure that slave restarts after number of crashes not within time range" in {
|
||||||
val boss = system.actorOf(Props(new Supervisor(
|
val boss = system.actorOf(Props(
|
||||||
OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 500 millis)(List(classOf[Throwable])))))
|
new Supervisor(OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 500 millis)(List(classOf[Throwable])))))
|
||||||
|
|
||||||
val restartLatch = new TestLatch
|
val restartLatch = new TestLatch
|
||||||
val secondRestartLatch = new TestLatch
|
val secondRestartLatch = new TestLatch
|
||||||
|
|
@ -261,4 +264,3 @@ class RestartStrategySpec extends AkkaSpec("akka.actor.serialize-messages = off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ package akka.actor
|
||||||
import language.postfixOps
|
import language.postfixOps
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.util.concurrent._
|
import java.util.concurrent._
|
||||||
import atomic.{ AtomicReference, AtomicInteger }
|
import atomic.{ AtomicInteger, AtomicReference }
|
||||||
import scala.concurrent.{ Future, Await, ExecutionContext }
|
import scala.concurrent.{ Await, ExecutionContext, Future }
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import java.util.concurrent.ThreadLocalRandom
|
import java.util.concurrent.ThreadLocalRandom
|
||||||
import scala.util.Try
|
import scala.util.Try
|
||||||
|
|
@ -20,7 +20,8 @@ import akka.testkit._
|
||||||
import scala.util.control.NoStackTrace
|
import scala.util.control.NoStackTrace
|
||||||
|
|
||||||
object SchedulerSpec {
|
object SchedulerSpec {
|
||||||
val testConfRevolver = ConfigFactory.parseString("""
|
val testConfRevolver =
|
||||||
|
ConfigFactory.parseString("""
|
||||||
akka.scheduler.implementation = akka.actor.LightArrayRevolverScheduler
|
akka.scheduler.implementation = akka.actor.LightArrayRevolverScheduler
|
||||||
akka.scheduler.ticks-per-wheel = 32
|
akka.scheduler.ticks-per-wheel = 32
|
||||||
akka.actor.serialize-messages = off
|
akka.actor.serialize-messages = off
|
||||||
|
|
@ -74,7 +75,7 @@ trait SchedulerSpec extends BeforeAndAfterEach with DefaultTimeout with Implicit
|
||||||
expectMsg("msg")
|
expectMsg("msg")
|
||||||
|
|
||||||
// stop the actor and, hence, the continuous messaging from happening
|
// stop the actor and, hence, the continuous messaging from happening
|
||||||
system stop actor
|
system.stop(actor)
|
||||||
|
|
||||||
expectNoMsg(500 millis)
|
expectNoMsg(500 millis)
|
||||||
}
|
}
|
||||||
|
|
@ -194,7 +195,7 @@ trait SchedulerSpec extends BeforeAndAfterEach with DefaultTimeout with Implicit
|
||||||
|
|
||||||
collectCancellable(system.scheduler.schedule(500 milliseconds, 500 milliseconds, actor, Ping))
|
collectCancellable(system.scheduler.schedule(500 milliseconds, 500 milliseconds, actor, Ping))
|
||||||
// appx 2 pings before crash
|
// appx 2 pings before crash
|
||||||
EventFilter[Exception]("CRASH", occurrences = 1) intercept {
|
EventFilter[Exception]("CRASH", occurrences = 1).intercept {
|
||||||
collectCancellable(system.scheduler.scheduleOnce(1000 milliseconds, actor, Crash))
|
collectCancellable(system.scheduler.scheduleOnce(1000 milliseconds, actor, Crash))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -292,11 +293,14 @@ trait SchedulerSpec extends BeforeAndAfterEach with DefaultTimeout with Implicit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val latencies = within(10.seconds) {
|
val latencies = within(10.seconds) {
|
||||||
for (i <- 1 to N) yield try expectMsgType[Long] catch {
|
for (i <- 1 to N)
|
||||||
|
yield
|
||||||
|
try expectMsgType[Long]
|
||||||
|
catch {
|
||||||
case NonFatal(e) => throw new Exception(s"failed expecting the $i-th latency", e)
|
case NonFatal(e) => throw new Exception(s"failed expecting the $i-th latency", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val histogram = latencies groupBy (_ / 100000000L)
|
val histogram = latencies.groupBy(_ / 100000000L)
|
||||||
for (k <- histogram.keys.toSeq.sorted) {
|
for (k <- histogram.keys.toSeq.sorted) {
|
||||||
system.log.info(f"${k * 100}%3d: ${histogram(k).size}")
|
system.log.info(f"${k * 100}%3d: ${histogram(k).size}")
|
||||||
}
|
}
|
||||||
|
|
@ -362,11 +366,14 @@ class LightArrayRevolverSchedulerSpec extends AkkaSpec(SchedulerSpec.testConfRev
|
||||||
val cancelled = cancellations.sum
|
val cancelled = cancellations.sum
|
||||||
println(cancelled)
|
println(cancelled)
|
||||||
val latencies = within(10.seconds) {
|
val latencies = within(10.seconds) {
|
||||||
for (i <- 1 to (N - cancelled)) yield try expectMsgType[Long] catch {
|
for (i <- 1 to (N - cancelled))
|
||||||
|
yield
|
||||||
|
try expectMsgType[Long]
|
||||||
|
catch {
|
||||||
case NonFatal(e) => throw new Exception(s"failed expecting the $i-th latency", e)
|
case NonFatal(e) => throw new Exception(s"failed expecting the $i-th latency", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val histogram = latencies groupBy (_ / 100000000L)
|
val histogram = latencies.groupBy(_ / 100000000L)
|
||||||
for (k <- histogram.keys.toSeq.sorted) {
|
for (k <- histogram.keys.toSeq.sorted) {
|
||||||
system.log.info(f"${k * 100}%3d: ${histogram(k).size}")
|
system.log.info(f"${k * 100}%3d: ${histogram(k).size}")
|
||||||
}
|
}
|
||||||
|
|
@ -389,7 +396,7 @@ class LightArrayRevolverSchedulerSpec extends AkkaSpec(SchedulerSpec.testConfRev
|
||||||
}
|
}
|
||||||
def delay = if (ThreadLocalRandom.current.nextBoolean) step * 2 else step
|
def delay = if (ThreadLocalRandom.current.nextBoolean) step * 2 else step
|
||||||
val N = 1000000
|
val N = 1000000
|
||||||
(1 to N) foreach (_ => sched.scheduleOnce(delay)(counter.incrementAndGet()))
|
(1 to N).foreach(_ => sched.scheduleOnce(delay)(counter.incrementAndGet()))
|
||||||
sched.close()
|
sched.close()
|
||||||
Await.result(terminated, 3.seconds.dilated) should be > 10
|
Await.result(terminated, 3.seconds.dilated) should be > 10
|
||||||
awaitCond(counter.get == N)
|
awaitCond(counter.get == N)
|
||||||
|
|
@ -401,13 +408,13 @@ class LightArrayRevolverSchedulerSpec extends AkkaSpec(SchedulerSpec.testConfRev
|
||||||
implicit def ec = localEC
|
implicit def ec = localEC
|
||||||
import driver._
|
import driver._
|
||||||
val start = step / 2
|
val start = step / 2
|
||||||
(0 to 3) foreach (i => sched.scheduleOnce(start + step * i, testActor, "hello"))
|
(0 to 3).foreach(i => sched.scheduleOnce(start + step * i, testActor, "hello"))
|
||||||
expectNoMsg(step)
|
expectNoMsg(step)
|
||||||
wakeUp(step)
|
wakeUp(step)
|
||||||
expectWait(step)
|
expectWait(step)
|
||||||
wakeUp(step * 4 + step / 2)
|
wakeUp(step * 4 + step / 2)
|
||||||
expectWait(step / 2)
|
expectWait(step / 2)
|
||||||
(0 to 3) foreach (_ => expectMsg(Duration.Zero, "hello"))
|
(0 to 3).foreach(_ => expectMsg(Duration.Zero, "hello"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,7 +438,7 @@ class LightArrayRevolverSchedulerSpec extends AkkaSpec(SchedulerSpec.testConfRev
|
||||||
implicit def ec = localEC
|
implicit def ec = localEC
|
||||||
import driver._
|
import driver._
|
||||||
val start = step / 2
|
val start = step / 2
|
||||||
(0 to 3) foreach (i => sched.scheduleOnce(start + step * i, probe.ref, "hello"))
|
(0 to 3).foreach(i => sched.scheduleOnce(start + step * i, probe.ref, "hello"))
|
||||||
probe.expectNoMsg(step)
|
probe.expectNoMsg(step)
|
||||||
wakeUp(step)
|
wakeUp(step)
|
||||||
expectWait(step)
|
expectWait(step)
|
||||||
|
|
@ -458,7 +465,7 @@ class LightArrayRevolverSchedulerSpec extends AkkaSpec(SchedulerSpec.testConfRev
|
||||||
implicit def ec = localEC
|
implicit def ec = localEC
|
||||||
import driver._
|
import driver._
|
||||||
val start = step / 2
|
val start = step / 2
|
||||||
(0 to 3) foreach (i => sched.scheduleOnce(start + step * i, testActor, "hello"))
|
(0 to 3).foreach(i => sched.scheduleOnce(start + step * i, testActor, "hello"))
|
||||||
expectNoMsg(step)
|
expectNoMsg(step)
|
||||||
wakeUp(step)
|
wakeUp(step)
|
||||||
expectWait(step)
|
expectWait(step)
|
||||||
|
|
@ -494,12 +501,12 @@ class LightArrayRevolverSchedulerSpec extends AkkaSpec(SchedulerSpec.testConfRev
|
||||||
probe.expectMsgType[Long]
|
probe.expectMsgType[Long]
|
||||||
|
|
||||||
val nums = 0 until numEvents
|
val nums = 0 until numEvents
|
||||||
nums foreach (i => sched.scheduleOnce(start + step * i, testActor, "hello-" + i))
|
nums.foreach(i => sched.scheduleOnce(start + step * i, testActor, "hello-" + i))
|
||||||
expectNoMsg(step)
|
expectNoMsg(step)
|
||||||
wakeUp(step)
|
wakeUp(step)
|
||||||
expectWait(step)
|
expectWait(step)
|
||||||
|
|
||||||
nums foreach { i =>
|
nums.foreach { i =>
|
||||||
wakeUp(step)
|
wakeUp(step)
|
||||||
expectMsg("hello-" + i)
|
expectMsg("hello-" + i)
|
||||||
expectWait(step)
|
expectWait(step)
|
||||||
|
|
@ -542,7 +549,8 @@ class LightArrayRevolverSchedulerSpec extends AkkaSpec(SchedulerSpec.testConfRev
|
||||||
def reportFailure(t: Throwable): Unit = { t.printStackTrace() }
|
def reportFailure(t: Throwable): Unit = { t.printStackTrace() }
|
||||||
}
|
}
|
||||||
|
|
||||||
def withScheduler(start: Long = 0L, _startTick: Int = 0, config: Config = ConfigFactory.empty)(thunk: (Scheduler with Closeable, Driver) => Unit): Unit = {
|
def withScheduler(start: Long = 0L, _startTick: Int = 0, config: Config = ConfigFactory.empty)(
|
||||||
|
thunk: (Scheduler with Closeable, Driver) => Unit): Unit = {
|
||||||
import akka.actor.{ LightArrayRevolverScheduler => LARS }
|
import akka.actor.{ LightArrayRevolverScheduler => LARS }
|
||||||
val lbq = new AtomicReference[LinkedBlockingQueue[Long]](new LinkedBlockingQueue[Long])
|
val lbq = new AtomicReference[LinkedBlockingQueue[Long]](new LinkedBlockingQueue[Long])
|
||||||
val prb = TestProbe()
|
val prb = TestProbe()
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,18 @@
|
||||||
package akka.actor
|
package akka.actor
|
||||||
|
|
||||||
import language.postfixOps
|
import language.postfixOps
|
||||||
import java.util.concurrent.{ TimeUnit, CountDownLatch }
|
import java.util.concurrent.{ CountDownLatch, TimeUnit }
|
||||||
import scala.concurrent.Await
|
import scala.concurrent.Await
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import scala.util.Random
|
import scala.util.Random
|
||||||
import scala.util.control.NoStackTrace
|
import scala.util.control.NoStackTrace
|
||||||
import com.typesafe.config.{ ConfigFactory, Config }
|
import com.typesafe.config.{ Config, ConfigFactory }
|
||||||
import SupervisorStrategy.{ Resume, Restart, Stop, Directive }
|
import SupervisorStrategy.{ Directive, Restart, Resume, Stop }
|
||||||
import akka.actor.SupervisorStrategy.seqThrowable2Decider
|
import akka.actor.SupervisorStrategy.seqThrowable2Decider
|
||||||
import akka.dispatch.{ MessageDispatcher, DispatcherPrerequisites, DispatcherConfigurator, Dispatcher }
|
import akka.dispatch.{ Dispatcher, DispatcherConfigurator, DispatcherPrerequisites, MessageDispatcher }
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
import akka.testkit.{ ImplicitSender, EventFilter, DefaultTimeout, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, DefaultTimeout, EventFilter, ImplicitSender }
|
||||||
import akka.testkit.{ filterException, filterEvents, TestDuration, TestLatch }
|
import akka.testkit.{ filterEvents, filterException, TestDuration, TestLatch }
|
||||||
import akka.testkit.TestEvent.Mute
|
import akka.testkit.TestEvent.Mute
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
|
@ -63,8 +63,15 @@ object SupervisorHierarchySpec {
|
||||||
case object PongOfDeath
|
case object PongOfDeath
|
||||||
final case class Event(msg: Any, identity: Long) { val time: Long = System.nanoTime }
|
final case class Event(msg: Any, identity: Long) { val time: Long = System.nanoTime }
|
||||||
final case class ErrorLog(msg: String, log: Vector[Event])
|
final case class ErrorLog(msg: String, log: Vector[Event])
|
||||||
final case class Failure(directive: Directive, stop: Boolean, depth: Int, var failPre: Int, var failPost: Int, val failConstr: Int, stopKids: Int)
|
final case class Failure(directive: Directive,
|
||||||
extends RuntimeException("Failure") with NoStackTrace {
|
stop: Boolean,
|
||||||
|
depth: Int,
|
||||||
|
var failPre: Int,
|
||||||
|
var failPost: Int,
|
||||||
|
val failConstr: Int,
|
||||||
|
stopKids: Int)
|
||||||
|
extends RuntimeException("Failure")
|
||||||
|
with NoStackTrace {
|
||||||
override def toString = productPrefix + productIterator.mkString("(", ",", ")")
|
override def toString = productPrefix + productIterator.mkString("(", ",", ")")
|
||||||
}
|
}
|
||||||
final case class Dump(level: Int)
|
final case class Dump(level: Int)
|
||||||
|
|
@ -82,8 +89,7 @@ object SupervisorHierarchySpec {
|
||||||
extends DispatcherConfigurator(config, prerequisites) {
|
extends DispatcherConfigurator(config, prerequisites) {
|
||||||
|
|
||||||
private val instance: MessageDispatcher =
|
private val instance: MessageDispatcher =
|
||||||
new Dispatcher(
|
new Dispatcher(this,
|
||||||
this,
|
|
||||||
config.getString("id"),
|
config.getString("id"),
|
||||||
config.getInt("throughput"),
|
config.getInt("throughput"),
|
||||||
config.getNanosDuration("throughput-deadline-time"),
|
config.getNanosDuration("throughput-deadline-time"),
|
||||||
|
|
@ -139,7 +145,7 @@ object SupervisorHierarchySpec {
|
||||||
listener ! ErrorLog(msg, log)
|
listener ! ErrorLog(msg, log)
|
||||||
log = Vector(Event("log sent", identityHashCode(this)))
|
log = Vector(Event("log sent", identityHashCode(this)))
|
||||||
context.parent ! Abort
|
context.parent ! Abort
|
||||||
context stop self
|
context.stop(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
def setFlags(directive: Directive): Unit = directive match {
|
def setFlags(directive: Directive): Unit = directive match {
|
||||||
|
|
@ -161,8 +167,11 @@ object SupervisorHierarchySpec {
|
||||||
var rest = s % kids
|
var rest = s % kids
|
||||||
val propsTemplate = Props.empty.withDispatcher("hierarchy")
|
val propsTemplate = Props.empty.withDispatcher("hierarchy")
|
||||||
(1 to kids).iterator.map { (id) =>
|
(1 to kids).iterator.map { (id) =>
|
||||||
val kidSize = if (rest > 0) { rest -= 1; sizes + 1 } else sizes
|
val kidSize = if (rest > 0) {
|
||||||
val props = Props(new Hierarchy(kidSize, breadth, listener, myLevel + 1, random)).withDeploy(propsTemplate.deploy)
|
rest -= 1; sizes + 1
|
||||||
|
} else sizes
|
||||||
|
val props =
|
||||||
|
Props(new Hierarchy(kidSize, breadth, listener, myLevel + 1, random)).withDeploy(propsTemplate.deploy)
|
||||||
(context.watch(context.actorOf(props, id.toString)).path, kidSize)
|
(context.watch(context.actorOf(props, id.toString)).path, kidSize)
|
||||||
}.toMap
|
}.toMap
|
||||||
} else Map()
|
} else Map()
|
||||||
|
|
@ -178,7 +187,7 @@ object SupervisorHierarchySpec {
|
||||||
preRestartCalled = true
|
preRestartCalled = true
|
||||||
cause match {
|
cause match {
|
||||||
case f: Failure =>
|
case f: Failure =>
|
||||||
context.children.take(f.stopKids) foreach { child =>
|
context.children.take(f.stopKids).foreach { child =>
|
||||||
log :+= Event("killing " + child, identityHashCode(this))
|
log :+= Event("killing " + child, identityHashCode(this))
|
||||||
context.unwatch(child)
|
context.unwatch(child)
|
||||||
context.stop(child)
|
context.stop(child)
|
||||||
|
|
@ -198,7 +207,7 @@ object SupervisorHierarchySpec {
|
||||||
case x @ ActorInitializationException(_, _, f: Failure) => (f, x)
|
case x @ ActorInitializationException(_, _, f: Failure) => (f, x)
|
||||||
case x => (x, x)
|
case x => (x, x)
|
||||||
}
|
}
|
||||||
override val supervisorStrategy = OneForOneStrategy()(unwrap andThen {
|
override val supervisorStrategy = OneForOneStrategy()(unwrap.andThen {
|
||||||
case (_: Failure, _) if pongsToGo > 0 =>
|
case (_: Failure, _) if pongsToGo > 0 =>
|
||||||
log :+= Event("pongOfDeath resuming " + sender(), identityHashCode(this))
|
log :+= Event("pongOfDeath resuming " + sender(), identityHashCode(this))
|
||||||
Resume
|
Resume
|
||||||
|
|
@ -225,12 +234,13 @@ object SupervisorHierarchySpec {
|
||||||
val state = stateCache.get(self.path)
|
val state = stateCache.get(self.path)
|
||||||
log = state.log
|
log = state.log
|
||||||
log :+= Event("restarted " + suspendCount + " " + cause, identityHashCode(this))
|
log :+= Event("restarted " + suspendCount + " " + cause, identityHashCode(this))
|
||||||
state.kids foreach {
|
state.kids.foreach {
|
||||||
case (childPath, kidSize) =>
|
case (childPath, kidSize) =>
|
||||||
val name = childPath.name
|
val name = childPath.name
|
||||||
if (context.child(name).isEmpty) {
|
if (context.child(name).isEmpty) {
|
||||||
listener ! Died(childPath)
|
listener ! Died(childPath)
|
||||||
val props = Props(new Hierarchy(kidSize, breadth, listener, myLevel + 1, random)).withDispatcher("hierarchy")
|
val props =
|
||||||
|
Props(new Hierarchy(kidSize, breadth, listener, myLevel + 1, random)).withDispatcher("hierarchy")
|
||||||
context.watch(context.actorOf(props, name))
|
context.watch(context.actorOf(props, name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +275,8 @@ object SupervisorHierarchySpec {
|
||||||
abort("processing message while suspended")
|
abort("processing message while suspended")
|
||||||
false
|
false
|
||||||
} else if (!Thread.currentThread.getName.startsWith("SupervisorHierarchySpec-hierarchy")) {
|
} else if (!Thread.currentThread.getName.startsWith("SupervisorHierarchySpec-hierarchy")) {
|
||||||
abort("running on wrong thread " + Thread.currentThread + " dispatcher=" + context.props.dispatcher + "=>" +
|
abort(
|
||||||
|
"running on wrong thread " + Thread.currentThread + " dispatcher=" + context.props.dispatcher + "=>" +
|
||||||
context.asInstanceOf[ActorCell].dispatcher.id)
|
context.asInstanceOf[ActorCell].dispatcher.id)
|
||||||
false
|
false
|
||||||
} else true
|
} else true
|
||||||
|
|
@ -281,7 +292,7 @@ object SupervisorHierarchySpec {
|
||||||
throw f
|
throw f
|
||||||
case "ping" => { Thread.sleep((random.nextFloat * 1.03).toLong); sender() ! "pong" }
|
case "ping" => { Thread.sleep((random.nextFloat * 1.03).toLong); sender() ! "pong" }
|
||||||
case Dump(0) => abort("dump")
|
case Dump(0) => abort("dump")
|
||||||
case Dump(level) => context.children foreach (_ ! Dump(level - 1))
|
case Dump(level) => context.children.foreach(_ ! Dump(level - 1))
|
||||||
case Terminated(ref) =>
|
case Terminated(ref) =>
|
||||||
/*
|
/*
|
||||||
* It might be that we acted upon this death already in postRestart
|
* It might be that we acted upon this death already in postRestart
|
||||||
|
|
@ -306,15 +317,15 @@ object SupervisorHierarchySpec {
|
||||||
if (size > 1) {
|
if (size > 1) {
|
||||||
pongsToGo = context.children.size
|
pongsToGo = context.children.size
|
||||||
log :+= Event("sending " + pongsToGo + " pingOfDeath", identityHashCode(Hierarchy.this))
|
log :+= Event("sending " + pongsToGo + " pingOfDeath", identityHashCode(Hierarchy.this))
|
||||||
context.children foreach (_ ! PingOfDeath)
|
context.children.foreach(_ ! PingOfDeath)
|
||||||
} else {
|
} else {
|
||||||
context stop self
|
context.stop(self)
|
||||||
context.parent ! PongOfDeath
|
context.parent ! PongOfDeath
|
||||||
}
|
}
|
||||||
case PongOfDeath =>
|
case PongOfDeath =>
|
||||||
pongsToGo -= 1
|
pongsToGo -= 1
|
||||||
if (pongsToGo == 0) {
|
if (pongsToGo == 0) {
|
||||||
context stop self
|
context.stop(self)
|
||||||
context.parent ! PongOfDeath
|
context.parent ! PongOfDeath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -450,7 +461,8 @@ object SupervisorHierarchySpec {
|
||||||
|
|
||||||
when(Idle) {
|
when(Idle) {
|
||||||
case Event(Init, _) =>
|
case Event(Init, _) =>
|
||||||
hierarchy = context.watch(context.actorOf(Props(new Hierarchy(size, breadth, self, 0, random)).withDispatcher("hierarchy"), "head"))
|
hierarchy = context.watch(
|
||||||
|
context.actorOf(Props(new Hierarchy(size, breadth, self, 0, random)).withDispatcher("hierarchy"), "head"))
|
||||||
setTimer("phase", StateTimeout, 5 seconds, false)
|
setTimer("phase", StateTimeout, 5 seconds, false)
|
||||||
goto(Init)
|
goto(Init)
|
||||||
}
|
}
|
||||||
|
|
@ -490,9 +502,9 @@ object SupervisorHierarchySpec {
|
||||||
val deadGuy = path.elements
|
val deadGuy = path.elements
|
||||||
val deadGuySize = deadGuy.size
|
val deadGuySize = deadGuy.size
|
||||||
val isChild = (other: ActorRef) => other.path.elements.take(deadGuySize) == deadGuy
|
val isChild = (other: ActorRef) => other.path.elements.take(deadGuySize) == deadGuy
|
||||||
activeChildren = activeChildren filterNot isChild
|
activeChildren = activeChildren.filterNot(isChild)
|
||||||
idleChildren = idleChildren filterNot isChild
|
idleChildren = idleChildren.filterNot(isChild)
|
||||||
pingChildren = pingChildren filterNot isChild
|
pingChildren = pingChildren.filterNot(isChild)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ignoreNotResumedLogs = true
|
var ignoreNotResumedLogs = true
|
||||||
|
|
@ -505,7 +517,12 @@ object SupervisorHierarchySpec {
|
||||||
nextJob.next match {
|
nextJob.next match {
|
||||||
case Ping(ref) => ref ! "ping"
|
case Ping(ref) => ref ! "ping"
|
||||||
case Fail(ref, dir) =>
|
case Fail(ref, dir) =>
|
||||||
val f = Failure(dir, stop = random012 > 0, depth = random012, failPre = random012, failPost = random012, failConstr = random012,
|
val f = Failure(dir,
|
||||||
|
stop = random012 > 0,
|
||||||
|
depth = random012,
|
||||||
|
failPre = random012,
|
||||||
|
failPost = random012,
|
||||||
|
failConstr = random012,
|
||||||
stopKids = random012 match {
|
stopKids = random012 match {
|
||||||
case 0 => 0
|
case 0 => 0
|
||||||
case 1 => random.nextInt(breadth / 2)
|
case 1 => random.nextInt(breadth / 2)
|
||||||
|
|
@ -515,7 +532,7 @@ object SupervisorHierarchySpec {
|
||||||
}
|
}
|
||||||
if (idleChildren.nonEmpty) self ! Work
|
if (idleChildren.nonEmpty) self ! Work
|
||||||
else context.system.scheduler.scheduleOnce(workSchedule, self, Work)(context.dispatcher)
|
else context.system.scheduler.scheduleOnce(workSchedule, self, Work)(context.dispatcher)
|
||||||
stay using (x - 1)
|
stay.using(x - 1)
|
||||||
case Event(Work, _) => if (pingChildren.isEmpty) goto(LastPing) else goto(Finishing)
|
case Event(Work, _) => if (pingChildren.isEmpty) goto(LastPing) else goto(Finishing)
|
||||||
case Event(Died(path), _) =>
|
case Event(Died(path), _) =>
|
||||||
bury(path)
|
bury(path)
|
||||||
|
|
@ -526,10 +543,11 @@ object SupervisorHierarchySpec {
|
||||||
stay
|
stay
|
||||||
case Event(StateTimeout, todo) =>
|
case Event(StateTimeout, todo) =>
|
||||||
log.info("dumping state due to StateTimeout")
|
log.info("dumping state due to StateTimeout")
|
||||||
log.info("children: " + children.size + " pinged: " + pingChildren.size + " idle: " + idleChildren.size + " work: " + todo)
|
log.info(
|
||||||
pingChildren foreach println
|
"children: " + children.size + " pinged: " + pingChildren.size + " idle: " + idleChildren.size + " work: " + todo)
|
||||||
|
pingChildren.foreach(println)
|
||||||
println(system.asInstanceOf[ActorSystemImpl].printTree)
|
println(system.asInstanceOf[ActorSystemImpl].printTree)
|
||||||
pingChildren foreach getErrorsUp
|
pingChildren.foreach(getErrorsUp)
|
||||||
ignoreNotResumedLogs = false
|
ignoreNotResumedLogs = false
|
||||||
hierarchy ! Dump(2)
|
hierarchy ! Dump(2)
|
||||||
goto(Failed)
|
goto(Failed)
|
||||||
|
|
@ -551,7 +569,7 @@ object SupervisorHierarchySpec {
|
||||||
|
|
||||||
onTransition {
|
onTransition {
|
||||||
case _ -> LastPing =>
|
case _ -> LastPing =>
|
||||||
idleChildren foreach (_ ! "ping")
|
idleChildren.foreach(_ ! "ping")
|
||||||
pingChildren ++= idleChildren
|
pingChildren ++= idleChildren
|
||||||
idleChildren = Vector.empty
|
idleChildren = Vector.empty
|
||||||
}
|
}
|
||||||
|
|
@ -575,7 +593,7 @@ object SupervisorHierarchySpec {
|
||||||
when(Stopping, stateTimeout = 5.seconds.dilated) {
|
when(Stopping, stateTimeout = 5.seconds.dilated) {
|
||||||
case Event(PongOfDeath, _) => stay
|
case Event(PongOfDeath, _) => stay
|
||||||
case Event(Terminated(r), _) if r == hierarchy =>
|
case Event(Terminated(r), _) if r == hierarchy =>
|
||||||
val undead = children filterNot (_.isTerminated)
|
val undead = children.filterNot(_.isTerminated)
|
||||||
if (undead.nonEmpty) {
|
if (undead.nonEmpty) {
|
||||||
log.info("undead:\n" + undead.mkString("\n"))
|
log.info("undead:\n" + undead.mkString("\n"))
|
||||||
testActor ! "stressTestFailed (" + undead.size + " undead)"
|
testActor ! "stressTestFailed (" + undead.size + " undead)"
|
||||||
|
|
@ -588,7 +606,7 @@ object SupervisorHierarchySpec {
|
||||||
* failed. I’m leaving this code in so that manual inspection remains
|
* failed. I’m leaving this code in so that manual inspection remains
|
||||||
* an option (by setting the above condition to “true”).
|
* an option (by setting the above condition to “true”).
|
||||||
*/
|
*/
|
||||||
val weak = children map (new WeakReference(_))
|
val weak = children.map(new WeakReference(_))
|
||||||
children = Vector.empty
|
children = Vector.empty
|
||||||
pingChildren = Set.empty
|
pingChildren = Set.empty
|
||||||
idleChildren = Vector.empty
|
idleChildren = Vector.empty
|
||||||
|
|
@ -604,7 +622,7 @@ object SupervisorHierarchySpec {
|
||||||
println(system.asInstanceOf[ActorSystemImpl].printTree)
|
println(system.asInstanceOf[ActorSystemImpl].printTree)
|
||||||
getErrors(hierarchy, 10)
|
getErrors(hierarchy, 10)
|
||||||
printErrors()
|
printErrors()
|
||||||
idleChildren foreach println
|
idleChildren.foreach(println)
|
||||||
testActor ! "timeout in Stopping"
|
testActor ! "timeout in Stopping"
|
||||||
stop
|
stop
|
||||||
case Event(e: ErrorLog, _) =>
|
case Event(e: ErrorLog, _) =>
|
||||||
|
|
@ -614,7 +632,7 @@ object SupervisorHierarchySpec {
|
||||||
|
|
||||||
when(GC, stateTimeout = 10 seconds) {
|
when(GC, stateTimeout = 10 seconds) {
|
||||||
case Event(GCcheck(weak), _) =>
|
case Event(GCcheck(weak), _) =>
|
||||||
val next = weak filter (_.get ne null)
|
val next = weak.filter(_.get ne null)
|
||||||
if (next.nonEmpty) {
|
if (next.nonEmpty) {
|
||||||
println(next.size + " left")
|
println(next.size + " left")
|
||||||
context.system.scheduler.scheduleOnce(workSchedule, self, GCcheck(next))(context.dispatcher)
|
context.system.scheduler.scheduleOnce(workSchedule, self, GCcheck(next))(context.dispatcher)
|
||||||
|
|
@ -658,7 +676,7 @@ object SupervisorHierarchySpec {
|
||||||
case _ => errors :+= target -> ErrorLog("fetched", stateCache.get(target.path).log)
|
case _ => errors :+= target -> ErrorLog("fetched", stateCache.get(target.path).log)
|
||||||
}
|
}
|
||||||
if (depth > 0) {
|
if (depth > 0) {
|
||||||
l.underlying.children foreach (getErrors(_, depth - 1))
|
l.underlying.children.foreach(getErrors(_, depth - 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -675,17 +693,17 @@ object SupervisorHierarchySpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
def printErrors(): Unit = {
|
def printErrors(): Unit = {
|
||||||
errors collect {
|
errors.collect {
|
||||||
case (origin, ErrorLog("dump", _)) => getErrors(origin, 1)
|
case (origin, ErrorLog("dump", _)) => getErrors(origin, 1)
|
||||||
case (origin, ErrorLog(msg, _)) if msg startsWith "not resumed" => getErrorsUp(origin)
|
case (origin, ErrorLog(msg, _)) if msg.startsWith("not resumed") => getErrorsUp(origin)
|
||||||
}
|
}
|
||||||
val merged = errors.sortBy(_._1.toString) flatMap {
|
val merged = errors.sortBy(_._1.toString).flatMap {
|
||||||
case (ref, ErrorLog(msg, log)) =>
|
case (ref, ErrorLog(msg, log)) =>
|
||||||
println("Error: " + ref + " " + msg)
|
println("Error: " + ref + " " + msg)
|
||||||
log map (l => (l.time, ref, l.identity, l.msg.toString))
|
log.map(l => (l.time, ref, l.identity, l.msg.toString))
|
||||||
}
|
}
|
||||||
println("random seed: " + randomSeed)
|
println("random seed: " + randomSeed)
|
||||||
merged.sorted.distinct foreach println
|
merged.sorted.distinct.foreach(println)
|
||||||
}
|
}
|
||||||
|
|
||||||
whenUnhandled {
|
whenUnhandled {
|
||||||
|
|
@ -707,7 +725,7 @@ object SupervisorHierarchySpec {
|
||||||
// make sure that we get the logs of the remaining pingChildren
|
// make sure that we get the logs of the remaining pingChildren
|
||||||
pingChildren.foreach(getErrorsUp)
|
pingChildren.foreach(getErrorsUp)
|
||||||
// this will ensure that the error logs get printed and we stop the test
|
// this will ensure that the error logs get printed and we stop the test
|
||||||
context stop hierarchy
|
context.stop(hierarchy)
|
||||||
goto(Failed)
|
goto(Failed)
|
||||||
case Event(Abort, _) =>
|
case Event(Abort, _) =>
|
||||||
log.info("received Abort")
|
log.info("received Abort")
|
||||||
|
|
@ -757,7 +775,8 @@ class SupervisorHierarchySpec extends AkkaSpec(SupervisorHierarchySpec.config) w
|
||||||
override val supervisorStrategy =
|
override val supervisorStrategy =
|
||||||
OneForOneStrategy(maxNrOfRetries = 1, withinTimeRange = 5 seconds)(List(classOf[Throwable]))
|
OneForOneStrategy(maxNrOfRetries = 1, withinTimeRange = 5 seconds)(List(classOf[Throwable]))
|
||||||
|
|
||||||
val crasher = context.watch(context.actorOf(Props(new CountDownActor(countDownMessages, SupervisorStrategy.defaultStrategy))))
|
val crasher = context.watch(
|
||||||
|
context.actorOf(Props(new CountDownActor(countDownMessages, SupervisorStrategy.defaultStrategy))))
|
||||||
|
|
||||||
def receive = {
|
def receive = {
|
||||||
case "killCrasher" => crasher ! Kill
|
case "killCrasher" => crasher ! Kill
|
||||||
|
|
@ -782,7 +801,7 @@ class SupervisorHierarchySpec extends AkkaSpec(SupervisorHierarchySpec.config) w
|
||||||
val worker = expectMsgType[ActorRef]
|
val worker = expectMsgType[ActorRef]
|
||||||
worker ! "ping"
|
worker ! "ping"
|
||||||
expectMsg("pong")
|
expectMsg("pong")
|
||||||
EventFilter.warning("expected", occurrences = 1) intercept {
|
EventFilter.warning("expected", occurrences = 1).intercept {
|
||||||
middle ! "fail"
|
middle ! "fail"
|
||||||
}
|
}
|
||||||
middle ! "ping"
|
middle ! "ping"
|
||||||
|
|
@ -794,7 +813,9 @@ class SupervisorHierarchySpec extends AkkaSpec(SupervisorHierarchySpec.config) w
|
||||||
"suspend children while failing" taggedAs LongRunningTest in {
|
"suspend children while failing" taggedAs LongRunningTest in {
|
||||||
val latch = TestLatch()
|
val latch = TestLatch()
|
||||||
val slowResumer = system.actorOf(Props(new Actor {
|
val slowResumer = system.actorOf(Props(new Actor {
|
||||||
override def supervisorStrategy = OneForOneStrategy() { case _ => Await.ready(latch, 4.seconds.dilated); SupervisorStrategy.Resume }
|
override def supervisorStrategy = OneForOneStrategy() {
|
||||||
|
case _ => Await.ready(latch, 4.seconds.dilated); SupervisorStrategy.Resume
|
||||||
|
}
|
||||||
def receive = {
|
def receive = {
|
||||||
case "spawn" => sender() ! context.actorOf(Props[Resumer])
|
case "spawn" => sender() ! context.actorOf(Props[Resumer])
|
||||||
}
|
}
|
||||||
|
|
@ -807,7 +828,7 @@ class SupervisorHierarchySpec extends AkkaSpec(SupervisorHierarchySpec.config) w
|
||||||
val worker = expectMsgType[ActorRef]
|
val worker = expectMsgType[ActorRef]
|
||||||
worker ! "ping"
|
worker ! "ping"
|
||||||
expectMsg("pong")
|
expectMsg("pong")
|
||||||
EventFilter.warning("expected", occurrences = 1) intercept {
|
EventFilter.warning("expected", occurrences = 1).intercept {
|
||||||
boss ! "fail"
|
boss ! "fail"
|
||||||
awaitCond(worker.asInstanceOf[LocalActorRef].underlying.mailbox.isSuspended)
|
awaitCond(worker.asInstanceOf[LocalActorRef].underlying.mailbox.isSuspended)
|
||||||
worker ! "ping"
|
worker ! "ping"
|
||||||
|
|
@ -822,13 +843,14 @@ class SupervisorHierarchySpec extends AkkaSpec(SupervisorHierarchySpec.config) w
|
||||||
val preStartCalled = new AtomicInteger(0)
|
val preStartCalled = new AtomicInteger(0)
|
||||||
val postRestartCalled = new AtomicInteger(0)
|
val postRestartCalled = new AtomicInteger(0)
|
||||||
|
|
||||||
filterEvents(
|
filterEvents(EventFilter[Failure](),
|
||||||
EventFilter[Failure](),
|
|
||||||
EventFilter[ActorInitializationException](),
|
EventFilter[ActorInitializationException](),
|
||||||
EventFilter[IllegalArgumentException]("OH NO!"),
|
EventFilter[IllegalArgumentException]("OH NO!"),
|
||||||
EventFilter.error(start = "changing Recreate into Create"),
|
EventFilter.error(start = "changing Recreate into Create"),
|
||||||
EventFilter.error(start = "changing Resume into Create")) {
|
EventFilter.error(start = "changing Resume into Create")) {
|
||||||
val failResumer = system.actorOf(Props(new Actor {
|
val failResumer =
|
||||||
|
system.actorOf(
|
||||||
|
Props(new Actor {
|
||||||
override def supervisorStrategy = OneForOneStrategy() {
|
override def supervisorStrategy = OneForOneStrategy() {
|
||||||
case e: ActorInitializationException =>
|
case e: ActorInitializationException =>
|
||||||
if (createAttempt.get % 2 == 0) SupervisorStrategy.Resume else SupervisorStrategy.Restart
|
if (createAttempt.get % 2 == 0) SupervisorStrategy.Resume else SupervisorStrategy.Restart
|
||||||
|
|
@ -857,7 +879,8 @@ class SupervisorHierarchySpec extends AkkaSpec(SupervisorHierarchySpec.config) w
|
||||||
override def receive = {
|
override def receive = {
|
||||||
case m => child.forward(m)
|
case m => child.forward(m)
|
||||||
}
|
}
|
||||||
}), "failResumer")
|
}),
|
||||||
|
"failResumer")
|
||||||
|
|
||||||
failResumer ! "blahonga"
|
failResumer ! "blahonga"
|
||||||
expectMsg("blahonga")
|
expectMsg("blahonga")
|
||||||
|
|
@ -868,8 +891,8 @@ class SupervisorHierarchySpec extends AkkaSpec(SupervisorHierarchySpec.config) w
|
||||||
}
|
}
|
||||||
|
|
||||||
"survive being stressed" taggedAs LongRunningTest in {
|
"survive being stressed" taggedAs LongRunningTest in {
|
||||||
system.eventStream.publish(Mute(
|
system.eventStream.publish(
|
||||||
EventFilter[Failure](),
|
Mute(EventFilter[Failure](),
|
||||||
EventFilter.warning("Failure"),
|
EventFilter.warning("Failure"),
|
||||||
EventFilter[ActorInitializationException](),
|
EventFilter[ActorInitializationException](),
|
||||||
EventFilter[NoSuchElementException]("head of empty list"),
|
EventFilter[NoSuchElementException]("head of empty list"),
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import language.postfixOps
|
||||||
|
|
||||||
import akka.testkit.{ filterEvents, EventFilter }
|
import akka.testkit.{ filterEvents, EventFilter }
|
||||||
import scala.concurrent.Await
|
import scala.concurrent.Await
|
||||||
import java.util.concurrent.{ TimeUnit, CountDownLatch }
|
import java.util.concurrent.{ CountDownLatch, TimeUnit }
|
||||||
import akka.testkit.AkkaSpec
|
import akka.testkit.AkkaSpec
|
||||||
import akka.testkit.DefaultTimeout
|
import akka.testkit.DefaultTimeout
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
|
|
@ -35,8 +35,8 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul
|
||||||
filterEvents(EventFilter[Exception]("Kill")) {
|
filterEvents(EventFilter[Exception]("Kill")) {
|
||||||
val countDownLatch = new CountDownLatch(4)
|
val countDownLatch = new CountDownLatch(4)
|
||||||
|
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor = system.actorOf(Props(
|
||||||
OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 5 seconds)(List(classOf[Exception])))))
|
new Supervisor(OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 5 seconds)(List(classOf[Exception])))))
|
||||||
|
|
||||||
val workerProps = Props(new Actor {
|
val workerProps = Props(new Actor {
|
||||||
override def postRestart(cause: Throwable): Unit = { countDownLatch.countDown() }
|
override def postRestart(cause: Throwable): Unit = { countDownLatch.countDown() }
|
||||||
|
|
@ -46,11 +46,14 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
val actor1, actor2 = Await.result((supervisor ? workerProps.withDispatcher("pinned-dispatcher")).mapTo[ActorRef], timeout.duration)
|
val actor1, actor2 =
|
||||||
|
Await.result((supervisor ? workerProps.withDispatcher("pinned-dispatcher")).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
||||||
val actor3 = Await.result((supervisor ? workerProps.withDispatcher("test-dispatcher")).mapTo[ActorRef], timeout.duration)
|
val actor3 =
|
||||||
|
Await.result((supervisor ? workerProps.withDispatcher("test-dispatcher")).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
||||||
val actor4 = Await.result((supervisor ? workerProps.withDispatcher("pinned-dispatcher")).mapTo[ActorRef], timeout.duration)
|
val actor4 =
|
||||||
|
Await.result((supervisor ? workerProps.withDispatcher("pinned-dispatcher")).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
||||||
actor1 ! Kill
|
actor1 ! Kill
|
||||||
actor2 ! Kill
|
actor2 ! Kill
|
||||||
|
|
@ -59,9 +62,11 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul
|
||||||
|
|
||||||
countDownLatch.await(10, TimeUnit.SECONDS)
|
countDownLatch.await(10, TimeUnit.SECONDS)
|
||||||
|
|
||||||
Seq("actor1" -> actor1, "actor2" -> actor2, "actor3" -> actor3, "actor4" -> actor4) map {
|
Seq("actor1" -> actor1, "actor2" -> actor2, "actor3" -> actor3, "actor4" -> actor4)
|
||||||
|
.map {
|
||||||
case (id, ref) => (id, ref ? "status")
|
case (id, ref) => (id, ref ? "status")
|
||||||
} foreach {
|
}
|
||||||
|
.foreach {
|
||||||
case (id, f) => (id, Await.result(f, timeout.duration)) should ===((id, "OK"))
|
case (id, f) => (id, Await.result(f, timeout.duration)) should ===((id, "OK"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +79,7 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul
|
||||||
override def preStart(): Unit = testActor ! "preStart"
|
override def preStart(): Unit = testActor ! "preStart"
|
||||||
}))
|
}))
|
||||||
val m = "weird message"
|
val m = "weird message"
|
||||||
EventFilter[Exception](m, occurrences = 1) intercept {
|
EventFilter[Exception](m, occurrences = 1).intercept {
|
||||||
a ! new Exception(m)
|
a ! new Exception(m)
|
||||||
}
|
}
|
||||||
expectMsg("preStart")
|
expectMsg("preStart")
|
||||||
|
|
@ -127,7 +132,9 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul
|
||||||
"be able to create a similar kid in the fault handling strategy" in {
|
"be able to create a similar kid in the fault handling strategy" in {
|
||||||
val parent = system.actorOf(Props(new Actor {
|
val parent = system.actorOf(Props(new Actor {
|
||||||
override val supervisorStrategy = new OneForOneStrategy()(SupervisorStrategy.defaultStrategy.decider) {
|
override val supervisorStrategy = new OneForOneStrategy()(SupervisorStrategy.defaultStrategy.decider) {
|
||||||
override def handleChildTerminated(context: ActorContext, child: ActorRef, children: Iterable[ActorRef]): Unit = {
|
override def handleChildTerminated(context: ActorContext,
|
||||||
|
child: ActorRef,
|
||||||
|
children: Iterable[ActorRef]): Unit = {
|
||||||
val newKid = context.actorOf(Props.empty, child.path.name)
|
val newKid = context.actorOf(Props.empty, child.path.name)
|
||||||
testActor ! { if ((newKid ne child) && newKid.path == child.path) "green" else "red" }
|
testActor ! { if ((newKid ne child) && newKid.path == child.path) "green" else "red" }
|
||||||
}
|
}
|
||||||
|
|
@ -137,7 +144,7 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul
|
||||||
}))
|
}))
|
||||||
parent ! "engage"
|
parent ! "engage"
|
||||||
expectMsg("green")
|
expectMsg("green")
|
||||||
EventFilter[IllegalStateException]("handleChildTerminated failed", occurrences = 1) intercept {
|
EventFilter[IllegalStateException]("handleChildTerminated failed", occurrences = 1).intercept {
|
||||||
system.stop(parent)
|
system.stop(parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +158,7 @@ class SupervisorMiscSpec extends AkkaSpec(SupervisorMiscSpec.config) with Defaul
|
||||||
case "doit" => context.actorOf(Props.empty, "child") ! Kill
|
case "doit" => context.actorOf(Props.empty, "child") ! Kill
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
EventFilter[ActorKilledException](occurrences = 1) intercept {
|
EventFilter[ActorKilledException](occurrences = 1).intercept {
|
||||||
parent ! "doit"
|
parent ! "doit"
|
||||||
}
|
}
|
||||||
val p = expectMsgType[ActorRef].path
|
val p = expectMsgType[ActorRef].path
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ object SupervisorSpec {
|
||||||
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 0)(List(classOf[Exception]))
|
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 0)(List(classOf[Exception]))
|
||||||
|
|
||||||
def receive = {
|
def receive = {
|
||||||
case Die => temp forward Die
|
case Die => temp.forward(Die)
|
||||||
case Terminated(`temp`) => sendTo ! "terminated"
|
case Terminated(`temp`) => sendTo ! "terminated"
|
||||||
case Status.Failure(_) => /*Ignore*/
|
case Status.Failure(_) => /*Ignore*/
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +101,11 @@ error-mailbox {
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfterEach with ImplicitSender with DefaultTimeout {
|
class SupervisorSpec
|
||||||
|
extends AkkaSpec(SupervisorSpec.config)
|
||||||
|
with BeforeAndAfterEach
|
||||||
|
with ImplicitSender
|
||||||
|
with DefaultTimeout {
|
||||||
|
|
||||||
import SupervisorSpec._
|
import SupervisorSpec._
|
||||||
|
|
||||||
|
|
@ -111,17 +115,21 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
// Creating actors and supervisors
|
// Creating actors and supervisors
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
private def child(supervisor: ActorRef, props: Props): ActorRef = Await.result((supervisor ? props).mapTo[ActorRef], timeout.duration)
|
private def child(supervisor: ActorRef, props: Props): ActorRef =
|
||||||
|
Await.result((supervisor ? props).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
||||||
def temporaryActorAllForOne = {
|
def temporaryActorAllForOne = {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(AllForOneStrategy(maxNrOfRetries = 0)(List(classOf[Exception])))))
|
val supervisor =
|
||||||
|
system.actorOf(Props(new Supervisor(AllForOneStrategy(maxNrOfRetries = 0)(List(classOf[Exception])))))
|
||||||
val temporaryActor = child(supervisor, Props(new PingPongActor(testActor)))
|
val temporaryActor = child(supervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
||||||
(temporaryActor, supervisor)
|
(temporaryActor, supervisor)
|
||||||
}
|
}
|
||||||
|
|
||||||
def singleActorAllForOne = {
|
def singleActorAllForOne = {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor = system.actorOf(
|
||||||
|
Props(
|
||||||
|
new Supervisor(
|
||||||
AllForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
AllForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
||||||
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
||||||
|
|
@ -129,7 +137,9 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
}
|
}
|
||||||
|
|
||||||
def singleActorOneForOne = {
|
def singleActorOneForOne = {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor = system.actorOf(
|
||||||
|
Props(
|
||||||
|
new Supervisor(
|
||||||
OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
||||||
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
||||||
|
|
@ -137,7 +147,9 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
}
|
}
|
||||||
|
|
||||||
def multipleActorsAllForOne = {
|
def multipleActorsAllForOne = {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor = system.actorOf(
|
||||||
|
Props(
|
||||||
|
new Supervisor(
|
||||||
AllForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
AllForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
||||||
val pingpong1, pingpong2, pingpong3 = child(supervisor, Props(new PingPongActor(testActor)))
|
val pingpong1, pingpong2, pingpong3 = child(supervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
||||||
|
|
@ -145,7 +157,9 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
}
|
}
|
||||||
|
|
||||||
def multipleActorsOneForOne = {
|
def multipleActorsOneForOne = {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor = system.actorOf(
|
||||||
|
Props(
|
||||||
|
new Supervisor(
|
||||||
OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
||||||
val pingpong1, pingpong2, pingpong3 = child(supervisor, Props(new PingPongActor(testActor)))
|
val pingpong1, pingpong2, pingpong3 = child(supervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
||||||
|
|
@ -153,12 +167,15 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
}
|
}
|
||||||
|
|
||||||
def nestedSupervisorsAllForOne = {
|
def nestedSupervisorsAllForOne = {
|
||||||
val topSupervisor = system.actorOf(Props(new Supervisor(
|
val topSupervisor = system.actorOf(
|
||||||
|
Props(
|
||||||
|
new Supervisor(
|
||||||
AllForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
AllForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(List(classOf[Exception])))))
|
||||||
val pingpong1 = child(topSupervisor, Props(new PingPongActor(testActor)))
|
val pingpong1 = child(topSupervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
||||||
val middleSupervisor = child(topSupervisor, Props(new Supervisor(
|
val middleSupervisor = child(
|
||||||
AllForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(Nil))))
|
topSupervisor,
|
||||||
|
Props(new Supervisor(AllForOneStrategy(maxNrOfRetries = 3, withinTimeRange = DilatedTimeout)(Nil))))
|
||||||
val pingpong2, pingpong3 = child(middleSupervisor, Props(new PingPongActor(testActor)))
|
val pingpong2, pingpong3 = child(middleSupervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
||||||
(pingpong1, pingpong2, pingpong3, topSupervisor)
|
(pingpong1, pingpong2, pingpong3, topSupervisor)
|
||||||
|
|
@ -168,9 +185,7 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
system.eventStream.publish(Mute(EventFilter[RuntimeException](ExceptionMessage)))
|
system.eventStream.publish(Mute(EventFilter[RuntimeException](ExceptionMessage)))
|
||||||
}
|
}
|
||||||
|
|
||||||
override def beforeEach() = {
|
override def beforeEach() = {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
def ping(pingPongActor: ActorRef) = {
|
def ping(pingPongActor: ActorRef) = {
|
||||||
Await.result(pingPongActor.?(Ping)(DilatedTimeout), DilatedTimeout) should ===(PongMessage)
|
Await.result(pingPongActor.?(Ping)(DilatedTimeout), DilatedTimeout) should ===(PongMessage)
|
||||||
|
|
@ -206,8 +221,12 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
var postRestarts = 0
|
var postRestarts = 0
|
||||||
var preStarts = 0
|
var preStarts = 0
|
||||||
var postStops = 0
|
var postStops = 0
|
||||||
override def preRestart(reason: Throwable, message: Option[Any]): Unit = { preRestarts += 1; testActor ! ("preRestart" + preRestarts) }
|
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
|
||||||
override def postRestart(reason: Throwable): Unit = { postRestarts += 1; testActor ! ("postRestart" + postRestarts) }
|
preRestarts += 1; testActor ! ("preRestart" + preRestarts)
|
||||||
|
}
|
||||||
|
override def postRestart(reason: Throwable): Unit = {
|
||||||
|
postRestarts += 1; testActor ! ("postRestart" + postRestarts)
|
||||||
|
}
|
||||||
override def preStart(): Unit = { preStarts += 1; testActor ! ("preStart" + preStarts) }
|
override def preStart(): Unit = { preStarts += 1; testActor ! ("preStart" + preStarts) }
|
||||||
override def postStop(): Unit = { postStops += 1; testActor ! ("postStop" + postStops) }
|
override def postStop(): Unit = { postStops += 1; testActor ! ("postStop" + postStops) }
|
||||||
def receive = {
|
def receive = {
|
||||||
|
|
@ -219,7 +238,7 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = restarts)(List(classOf[Exception]))
|
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = restarts)(List(classOf[Exception]))
|
||||||
val child = context.actorOf(Props(childInstance))
|
val child = context.actorOf(Props(childInstance))
|
||||||
def receive = {
|
def receive = {
|
||||||
case msg => child forward msg
|
case msg => child.forward(msg)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
@ -229,8 +248,7 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
expectMsg("pong")
|
expectMsg("pong")
|
||||||
|
|
||||||
filterEvents(EventFilter[RuntimeException]("Expected", occurrences = restarts + 1)) {
|
filterEvents(EventFilter[RuntimeException]("Expected", occurrences = restarts + 1)) {
|
||||||
(1 to restarts) foreach {
|
(1 to restarts).foreach { i =>
|
||||||
i =>
|
|
||||||
master ! "crash"
|
master ! "crash"
|
||||||
expectMsg("crashed")
|
expectMsg("crashed")
|
||||||
|
|
||||||
|
|
@ -377,8 +395,8 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
|
|
||||||
"attempt restart when exception during restart" in {
|
"attempt restart when exception during restart" in {
|
||||||
val inits = new AtomicInteger(0)
|
val inits = new AtomicInteger(0)
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor = system.actorOf(Props(
|
||||||
OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 10 seconds)(classOf[Exception] :: Nil))))
|
new Supervisor(OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 10 seconds)(classOf[Exception] :: Nil))))
|
||||||
|
|
||||||
val dyingProps = Props(new Actor {
|
val dyingProps = Props(new Actor {
|
||||||
val init = inits.getAndIncrement()
|
val init = inits.getAndIncrement()
|
||||||
|
|
@ -399,8 +417,7 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
supervisor ! dyingProps
|
supervisor ! dyingProps
|
||||||
val dyingActor = expectMsgType[ActorRef]
|
val dyingActor = expectMsgType[ActorRef]
|
||||||
|
|
||||||
filterEvents(
|
filterEvents(EventFilter[RuntimeException]("Expected", occurrences = 1),
|
||||||
EventFilter[RuntimeException]("Expected", occurrences = 1),
|
|
||||||
EventFilter[PreRestartException]("Don't wanna!", occurrences = 1),
|
EventFilter[PreRestartException]("Don't wanna!", occurrences = 1),
|
||||||
EventFilter[PostRestartException]("Don't wanna!", occurrences = 1)) {
|
EventFilter[PostRestartException]("Don't wanna!", occurrences = 1)) {
|
||||||
intercept[RuntimeException] {
|
intercept[RuntimeException] {
|
||||||
|
|
@ -434,7 +451,7 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
|
|
||||||
// Overriding to disable auto-unwatch
|
// Overriding to disable auto-unwatch
|
||||||
override def preRestart(reason: Throwable, msg: Option[Any]): Unit = {
|
override def preRestart(reason: Throwable, msg: Option[Any]): Unit = {
|
||||||
context.children foreach context.stop
|
context.children.foreach(context.stop)
|
||||||
postStop()
|
postStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -442,8 +459,8 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
case Terminated(a) if a.path == child.path => testActor ! "child terminated"
|
case Terminated(a) if a.path == child.path => testActor ! "child terminated"
|
||||||
case l: TestLatch => child ! l
|
case l: TestLatch => child ! l
|
||||||
case "test" => sender() ! "green"
|
case "test" => sender() ! "green"
|
||||||
case "testchild" => child forward "test"
|
case "testchild" => child.forward("test")
|
||||||
case "testchildAndAck" => child forward "test"; sender() ! "ack"
|
case "testchildAndAck" => child.forward("test"); sender() ! "ack"
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
@ -451,8 +468,7 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
parent ! latch
|
parent ! latch
|
||||||
parent ! "testchildAndAck"
|
parent ! "testchildAndAck"
|
||||||
expectMsg("ack")
|
expectMsg("ack")
|
||||||
filterEvents(
|
filterEvents(EventFilter[IllegalStateException]("OHNOES", occurrences = 1),
|
||||||
EventFilter[IllegalStateException]("OHNOES", occurrences = 1),
|
|
||||||
EventFilter.warning(pattern = "dead.*test", occurrences = 1)) {
|
EventFilter.warning(pattern = "dead.*test", occurrences = 1)) {
|
||||||
latch.countDown()
|
latch.countDown()
|
||||||
}
|
}
|
||||||
|
|
@ -504,7 +520,8 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
}
|
}
|
||||||
|
|
||||||
"restarts a child infinitely if maxNrOfRetries = -1 and withinTimeRange = Duration.Inf" in {
|
"restarts a child infinitely if maxNrOfRetries = -1 and withinTimeRange = Duration.Inf" in {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor = system.actorOf(
|
||||||
|
Props(new Supervisor(
|
||||||
OneForOneStrategy(maxNrOfRetries = -1, withinTimeRange = Duration.Inf)(classOf[Exception] :: Nil))))
|
OneForOneStrategy(maxNrOfRetries = -1, withinTimeRange = Duration.Inf)(classOf[Exception] :: Nil))))
|
||||||
|
|
||||||
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
@ -520,8 +537,8 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
}
|
}
|
||||||
|
|
||||||
"treats maxNrOfRetries = -1 as maxNrOfRetries = 1 if withinTimeRange is non-infinite Duration" in {
|
"treats maxNrOfRetries = -1 as maxNrOfRetries = 1 if withinTimeRange is non-infinite Duration" in {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor = system.actorOf(Props(
|
||||||
OneForOneStrategy(maxNrOfRetries = -1, withinTimeRange = 10 seconds)(classOf[Exception] :: Nil))))
|
new Supervisor(OneForOneStrategy(maxNrOfRetries = -1, withinTimeRange = 10 seconds)(classOf[Exception] :: Nil))))
|
||||||
|
|
||||||
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
||||||
|
|
@ -532,8 +549,8 @@ class SupervisorSpec extends AkkaSpec(SupervisorSpec.config) with BeforeAndAfter
|
||||||
}
|
}
|
||||||
|
|
||||||
"treats withinTimeRange = Duration.Inf as a single infinite restart window" in {
|
"treats withinTimeRange = Duration.Inf as a single infinite restart window" in {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor = system.actorOf(Props(
|
||||||
OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = Duration.Inf)(classOf[Exception] :: Nil))))
|
new Supervisor(OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = Duration.Inf)(classOf[Exception] :: Nil))))
|
||||||
|
|
||||||
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
val pingpong = child(supervisor, Props(new PingPongActor(testActor)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,22 @@ import language.postfixOps
|
||||||
|
|
||||||
import scala.concurrent.Await
|
import scala.concurrent.Await
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import akka.testkit.{ EventFilter, AkkaSpec, ImplicitSender, DefaultTimeout }
|
import akka.testkit.{ AkkaSpec, DefaultTimeout, EventFilter, ImplicitSender }
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
|
|
||||||
class SupervisorTreeSpec extends AkkaSpec("akka.actor.serialize-messages = off") with ImplicitSender with DefaultTimeout {
|
class SupervisorTreeSpec
|
||||||
|
extends AkkaSpec("akka.actor.serialize-messages = off")
|
||||||
|
with ImplicitSender
|
||||||
|
with DefaultTimeout {
|
||||||
|
|
||||||
"In a 3 levels deep supervisor tree (linked in the constructor) we" must {
|
"In a 3 levels deep supervisor tree (linked in the constructor) we" must {
|
||||||
|
|
||||||
"be able to kill the middle actor and see itself and its child restarted" in {
|
"be able to kill the middle actor and see itself and its child restarted" in {
|
||||||
EventFilter[ActorKilledException](occurrences = 1) intercept {
|
EventFilter[ActorKilledException](occurrences = 1).intercept {
|
||||||
within(5 seconds) {
|
within(5 seconds) {
|
||||||
val p = Props(new Actor {
|
val p = Props(new Actor {
|
||||||
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 1 second)(List(classOf[Exception]))
|
override val supervisorStrategy =
|
||||||
|
OneForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 1 second)(List(classOf[Exception]))
|
||||||
def receive = {
|
def receive = {
|
||||||
case p: Props => sender() ! context.actorOf(p)
|
case p: Props => sender() ! context.actorOf(p)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ class Ticket669Spec extends AkkaSpec with BeforeAndAfterAll with ImplicitSender
|
||||||
"A supervised actor with lifecycle PERMANENT" should {
|
"A supervised actor with lifecycle PERMANENT" should {
|
||||||
"be able to reply on failure during preRestart" in {
|
"be able to reply on failure during preRestart" in {
|
||||||
filterEvents(EventFilter[Exception]("test", occurrences = 1)) {
|
filterEvents(EventFilter[Exception]("test", occurrences = 1)) {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor =
|
||||||
AllForOneStrategy(5, 10 seconds)(List(classOf[Exception])))))
|
system.actorOf(Props(new Supervisor(AllForOneStrategy(5, 10 seconds)(List(classOf[Exception])))))
|
||||||
val supervised = Await.result((supervisor ? Props[Supervised]).mapTo[ActorRef], timeout.duration)
|
val supervised = Await.result((supervisor ? Props[Supervised]).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
||||||
supervised.!("test")(testActor)
|
supervised.!("test")(testActor)
|
||||||
|
|
@ -38,8 +38,8 @@ class Ticket669Spec extends AkkaSpec with BeforeAndAfterAll with ImplicitSender
|
||||||
|
|
||||||
"be able to reply on failure during postStop" in {
|
"be able to reply on failure during postStop" in {
|
||||||
filterEvents(EventFilter[Exception]("test", occurrences = 1)) {
|
filterEvents(EventFilter[Exception]("test", occurrences = 1)) {
|
||||||
val supervisor = system.actorOf(Props(new Supervisor(
|
val supervisor =
|
||||||
AllForOneStrategy(maxNrOfRetries = 0)(List(classOf[Exception])))))
|
system.actorOf(Props(new Supervisor(AllForOneStrategy(maxNrOfRetries = 0)(List(classOf[Exception])))))
|
||||||
val supervised = Await.result((supervisor ? Props[Supervised]).mapTo[ActorRef], timeout.duration)
|
val supervised = Await.result((supervisor ? Props[Supervised]).mapTo[ActorRef], timeout.duration)
|
||||||
|
|
||||||
supervised.!("test")(testActor)
|
supervised.!("test")(testActor)
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,11 @@ object TimerSpec {
|
||||||
sealed trait Command
|
sealed trait Command
|
||||||
case class Tick(n: Int) extends Command
|
case class Tick(n: Int) extends Command
|
||||||
case object Bump extends Command
|
case object Bump extends Command
|
||||||
case class SlowThenBump(latch: TestLatch) extends Command
|
case class SlowThenBump(latch: TestLatch) extends Command with NoSerializationVerificationNeeded
|
||||||
with NoSerializationVerificationNeeded
|
|
||||||
case object End extends Command
|
case object End extends Command
|
||||||
case class Throw(e: Throwable) extends Command
|
case class Throw(e: Throwable) extends Command
|
||||||
case object Cancel extends Command
|
case object Cancel extends Command
|
||||||
case class SlowThenThrow(latch: TestLatch, e: Throwable) extends Command
|
case class SlowThenThrow(latch: TestLatch, e: Throwable) extends Command with NoSerializationVerificationNeeded
|
||||||
with NoSerializationVerificationNeeded
|
|
||||||
case object AutoReceive extends Command
|
case object AutoReceive extends Command
|
||||||
|
|
||||||
sealed trait Event
|
sealed trait Event
|
||||||
|
|
@ -34,7 +32,9 @@ object TimerSpec {
|
||||||
def target(monitor: ActorRef, interval: FiniteDuration, repeat: Boolean, initial: () => Int): Props =
|
def target(monitor: ActorRef, interval: FiniteDuration, repeat: Boolean, initial: () => Int): Props =
|
||||||
Props(new Target(monitor, interval, repeat, initial))
|
Props(new Target(monitor, interval, repeat, initial))
|
||||||
|
|
||||||
class Target(monitor: ActorRef, interval: FiniteDuration, repeat: Boolean, initial: () => Int) extends Actor with Timers {
|
class Target(monitor: ActorRef, interval: FiniteDuration, repeat: Boolean, initial: () => Int)
|
||||||
|
extends Actor
|
||||||
|
with Timers {
|
||||||
private var bumpCount = initial()
|
private var bumpCount = initial()
|
||||||
|
|
||||||
if (repeat)
|
if (repeat)
|
||||||
|
|
@ -86,7 +86,8 @@ object TimerSpec {
|
||||||
|
|
||||||
object TheState
|
object TheState
|
||||||
|
|
||||||
class FsmTarget(monitor: ActorRef, interval: FiniteDuration, repeat: Boolean, initial: () => Int) extends FSM[TheState.type, Int] {
|
class FsmTarget(monitor: ActorRef, interval: FiniteDuration, repeat: Boolean, initial: () => Int)
|
||||||
|
extends FSM[TheState.type, Int] {
|
||||||
|
|
||||||
private var restarting = false
|
private var restarting = false
|
||||||
|
|
||||||
|
|
@ -104,7 +105,7 @@ object TimerSpec {
|
||||||
|
|
||||||
def bump(bumpCount: Int): State = {
|
def bump(bumpCount: Int): State = {
|
||||||
setTimer("T", Tick(bumpCount + 1), interval, repeat)
|
setTimer("T", Tick(bumpCount + 1), interval, repeat)
|
||||||
stay using (bumpCount + 1)
|
stay.using(bumpCount + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
def autoReceive(): State = {
|
def autoReceive(): State = {
|
||||||
|
|
@ -148,13 +149,19 @@ object TimerSpec {
|
||||||
|
|
||||||
class TimerSpec extends AbstractTimerSpec {
|
class TimerSpec extends AbstractTimerSpec {
|
||||||
override def testName: String = "Timers"
|
override def testName: String = "Timers"
|
||||||
override def target(monitor: ActorRef, interval: FiniteDuration, repeat: Boolean, initial: () => Int = () => 1): Props =
|
override def target(monitor: ActorRef,
|
||||||
|
interval: FiniteDuration,
|
||||||
|
repeat: Boolean,
|
||||||
|
initial: () => Int = () => 1): Props =
|
||||||
TimerSpec.target(monitor, interval, repeat, initial)
|
TimerSpec.target(monitor, interval, repeat, initial)
|
||||||
}
|
}
|
||||||
|
|
||||||
class FsmTimerSpec extends AbstractTimerSpec {
|
class FsmTimerSpec extends AbstractTimerSpec {
|
||||||
override def testName: String = "FSM Timers"
|
override def testName: String = "FSM Timers"
|
||||||
override def target(monitor: ActorRef, interval: FiniteDuration, repeat: Boolean, initial: () => Int = () => 1): Props =
|
override def target(monitor: ActorRef,
|
||||||
|
interval: FiniteDuration,
|
||||||
|
repeat: Boolean,
|
||||||
|
initial: () => Int = () => 1): Props =
|
||||||
TimerSpec.fsmTarget(monitor, interval, repeat, initial)
|
TimerSpec.fsmTarget(monitor, interval, repeat, initial)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,8 +239,8 @@ abstract class AbstractTimerSpec extends AkkaSpec {
|
||||||
"discard timers from old incarnation after restart, alt 1" taggedAs TimingTest in {
|
"discard timers from old incarnation after restart, alt 1" taggedAs TimingTest in {
|
||||||
val probe = TestProbe()
|
val probe = TestProbe()
|
||||||
val startCounter = new AtomicInteger(0)
|
val startCounter = new AtomicInteger(0)
|
||||||
val ref = system.actorOf(target(probe.ref, dilatedInterval, repeat = true,
|
val ref = system.actorOf(
|
||||||
initial = () => startCounter.incrementAndGet()))
|
target(probe.ref, dilatedInterval, repeat = true, initial = () => startCounter.incrementAndGet()))
|
||||||
probe.expectMsg(Tock(1))
|
probe.expectMsg(Tock(1))
|
||||||
|
|
||||||
val latch = new TestLatch(1)
|
val latch = new TestLatch(1)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import akka.japi.{ Option => JOption }
|
||||||
import akka.pattern.ask
|
import akka.pattern.ask
|
||||||
import akka.routing.RoundRobinGroup
|
import akka.routing.RoundRobinGroup
|
||||||
import akka.serialization.{ JavaSerializer, SerializerWithStringManifest }
|
import akka.serialization.{ JavaSerializer, SerializerWithStringManifest }
|
||||||
import akka.testkit.{ AkkaSpec, DefaultTimeout, EventFilter, TimingTest, filterEvents }
|
import akka.testkit.{ filterEvents, AkkaSpec, DefaultTimeout, EventFilter, TimingTest }
|
||||||
import akka.util.Timeout
|
import akka.util.Timeout
|
||||||
import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach }
|
import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach }
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ object TypedActorSpec {
|
||||||
findNext
|
findNext
|
||||||
}
|
}
|
||||||
|
|
||||||
override def exists(f: T => Boolean): Boolean = items exists f
|
override def exists(f: T => Boolean): Boolean = items.exists(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
|
|
@ -108,7 +108,8 @@ object TypedActorSpec {
|
||||||
@throws(classOf[TimeoutException])
|
@throws(classOf[TimeoutException])
|
||||||
def read(): Int
|
def read(): Int
|
||||||
|
|
||||||
def testMethodCallSerialization(foo: Foo, s: String, i: Int, o: WithStringSerializedClass): Unit = throw new IllegalStateException("expected")
|
def testMethodCallSerialization(foo: Foo, s: String, i: Int, o: WithStringSerializedClass): Unit =
|
||||||
|
throw new IllegalStateException("expected")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Bar extends Foo with Serializable {
|
class Bar extends Foo with Serializable {
|
||||||
|
|
@ -177,7 +178,13 @@ object TypedActorSpec {
|
||||||
def crash(): Unit
|
def crash(): Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
class LifeCyclesImpl(val latch: CountDownLatch) extends PreStart with PostStop with PreRestart with PostRestart with LifeCycles with Receiver {
|
class LifeCyclesImpl(val latch: CountDownLatch)
|
||||||
|
extends PreStart
|
||||||
|
with PostStop
|
||||||
|
with PreRestart
|
||||||
|
with PostRestart
|
||||||
|
with LifeCycles
|
||||||
|
with Receiver {
|
||||||
|
|
||||||
private def ensureContextAvailable[T](f: => T): T = TypedActor.context match {
|
private def ensureContextAvailable[T](f: => T): T = TypedActor.context match {
|
||||||
case null => throw new IllegalStateException("TypedActor.context is null!")
|
case null => throw new IllegalStateException("TypedActor.context is null!")
|
||||||
|
|
@ -190,13 +197,13 @@ object TypedActorSpec {
|
||||||
|
|
||||||
override def postStop(): Unit = ensureContextAvailable(for (i <- 1 to 3) latch.countDown())
|
override def postStop(): Unit = ensureContextAvailable(for (i <- 1 to 3) latch.countDown())
|
||||||
|
|
||||||
override def preRestart(reason: Throwable, message: Option[Any]): Unit = ensureContextAvailable(for (i <- 1 to 5) latch.countDown())
|
override def preRestart(reason: Throwable, message: Option[Any]): Unit =
|
||||||
|
ensureContextAvailable(for (i <- 1 to 5) latch.countDown())
|
||||||
|
|
||||||
override def postRestart(reason: Throwable): Unit = ensureContextAvailable(for (i <- 1 to 7) latch.countDown())
|
override def postRestart(reason: Throwable): Unit = ensureContextAvailable(for (i <- 1 to 7) latch.countDown())
|
||||||
|
|
||||||
override def onReceive(msg: Any, sender: ActorRef): Unit = {
|
override def onReceive(msg: Any, sender: ActorRef): Unit = {
|
||||||
ensureContextAvailable(
|
ensureContextAvailable(msg match {
|
||||||
msg match {
|
|
||||||
case "pigdog" => sender ! "dogpig"
|
case "pigdog" => sender ! "dogpig"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -233,8 +240,11 @@ object TypedActorSpec {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypedActorSpec extends AkkaSpec(TypedActorSpec.config)
|
class TypedActorSpec
|
||||||
with BeforeAndAfterEach with BeforeAndAfterAll with DefaultTimeout {
|
extends AkkaSpec(TypedActorSpec.config)
|
||||||
|
with BeforeAndAfterEach
|
||||||
|
with BeforeAndAfterAll
|
||||||
|
with DefaultTimeout {
|
||||||
|
|
||||||
import akka.actor.TypedActorSpec._
|
import akka.actor.TypedActorSpec._
|
||||||
|
|
||||||
|
|
@ -244,7 +254,8 @@ class TypedActorSpec extends AkkaSpec(TypedActorSpec.config)
|
||||||
TypedActor(system).typedActorOf(TypedProps[Bar](classOf[Foo], classOf[Bar]).withTimeout(Timeout(d)))
|
TypedActor(system).typedActorOf(TypedProps[Bar](classOf[Foo], classOf[Bar]).withTimeout(Timeout(d)))
|
||||||
|
|
||||||
def newFooBar(dispatcher: String, d: FiniteDuration): Foo =
|
def newFooBar(dispatcher: String, d: FiniteDuration): Foo =
|
||||||
TypedActor(system).typedActorOf(TypedProps[Bar](classOf[Foo], classOf[Bar]).withTimeout(Timeout(d)).withDispatcher(dispatcher))
|
TypedActor(system).typedActorOf(
|
||||||
|
TypedProps[Bar](classOf[Foo], classOf[Bar]).withTimeout(Timeout(d)).withDispatcher(dispatcher))
|
||||||
|
|
||||||
def newStacked(): Stacked =
|
def newStacked(): Stacked =
|
||||||
TypedActor(system).typedActorOf(
|
TypedActor(system).typedActorOf(
|
||||||
|
|
@ -292,7 +303,7 @@ class TypedActorSpec extends AkkaSpec(TypedActorSpec.config)
|
||||||
"be able to call equals" in {
|
"be able to call equals" in {
|
||||||
val t = newFooBar
|
val t = newFooBar
|
||||||
t should ===(t)
|
t should ===(t)
|
||||||
t should not equal (null)
|
(t should not).equal(null)
|
||||||
mustStop(t)
|
mustStop(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -382,13 +393,15 @@ class TypedActorSpec extends AkkaSpec(TypedActorSpec.config)
|
||||||
case p: TypedProps[_] => context.sender() ! TypedActor(context).typedActorOf(p)
|
case p: TypedProps[_] => context.sender() ! TypedActor(context).typedActorOf(p)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
val t = Await.result((boss ? TypedProps[Bar](classOf[Foo], classOf[Bar]).withTimeout(2 seconds)).mapTo[Foo], timeout.duration)
|
val t = Await.result((boss ? TypedProps[Bar](classOf[Foo], classOf[Bar]).withTimeout(2 seconds)).mapTo[Foo],
|
||||||
|
timeout.duration)
|
||||||
|
|
||||||
t.incr()
|
t.incr()
|
||||||
t.failingPigdog()
|
t.failingPigdog()
|
||||||
t.read() should ===(1) //Make sure state is not reset after failure
|
t.read() should ===(1) //Make sure state is not reset after failure
|
||||||
|
|
||||||
intercept[IllegalStateException] { Await.result(t.failingFuturePigdog, 2 seconds) }.getMessage should ===("expected")
|
intercept[IllegalStateException] { Await.result(t.failingFuturePigdog, 2 seconds) }.getMessage should ===(
|
||||||
|
"expected")
|
||||||
t.read() should ===(1) //Make sure state is not reset after failure
|
t.read() should ===(1) //Make sure state is not reset after failure
|
||||||
|
|
||||||
(intercept[IllegalStateException] { t.failingJOptionPigdog }).getMessage should ===("expected")
|
(intercept[IllegalStateException] { t.failingJOptionPigdog }).getMessage should ===("expected")
|
||||||
|
|
@ -474,7 +487,11 @@ class TypedActorSpec extends AkkaSpec(TypedActorSpec.config)
|
||||||
import java.io._
|
import java.io._
|
||||||
val someFoo: Foo = new Bar
|
val someFoo: Foo = new Bar
|
||||||
JavaSerializer.currentSystem.withValue(system.asInstanceOf[ExtendedActorSystem]) {
|
JavaSerializer.currentSystem.withValue(system.asInstanceOf[ExtendedActorSystem]) {
|
||||||
val m = TypedActor.MethodCall(classOf[Foo].getDeclaredMethod("testMethodCallSerialization", Array[Class[_]](classOf[Foo], classOf[String], classOf[Int], classOf[WithStringSerializedClass]): _*), Array[AnyRef](someFoo, null, 1.asInstanceOf[AnyRef], WithStringSerializedClass()))
|
val m = TypedActor.MethodCall(
|
||||||
|
classOf[Foo].getDeclaredMethod(
|
||||||
|
"testMethodCallSerialization",
|
||||||
|
Array[Class[_]](classOf[Foo], classOf[String], classOf[Int], classOf[WithStringSerializedClass]): _*),
|
||||||
|
Array[AnyRef](someFoo, null, 1.asInstanceOf[AnyRef], WithStringSerializedClass()))
|
||||||
val baos = new ByteArrayOutputStream(8192 * 4)
|
val baos = new ByteArrayOutputStream(8192 * 4)
|
||||||
val out = new ObjectOutputStream(baos)
|
val out = new ObjectOutputStream(baos)
|
||||||
|
|
||||||
|
|
@ -526,12 +543,12 @@ class TypedActorSpec extends AkkaSpec(TypedActorSpec.config)
|
||||||
val latch = new CountDownLatch(16)
|
val latch = new CountDownLatch(16)
|
||||||
val ta = TypedActor(system)
|
val ta = TypedActor(system)
|
||||||
val t: LifeCycles = ta.typedActorOf(TypedProps[LifeCyclesImpl](classOf[LifeCycles], new LifeCyclesImpl(latch)))
|
val t: LifeCycles = ta.typedActorOf(TypedProps[LifeCyclesImpl](classOf[LifeCycles], new LifeCyclesImpl(latch)))
|
||||||
EventFilter[IllegalStateException]("Crash!", occurrences = 1) intercept {
|
EventFilter[IllegalStateException]("Crash!", occurrences = 1).intercept {
|
||||||
t.crash()
|
t.crash()
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sneak in a check for the Receiver override
|
//Sneak in a check for the Receiver override
|
||||||
val ref = ta getActorRefFor t
|
val ref = ta.getActorRefFor(t)
|
||||||
|
|
||||||
ref.tell("pigdog", testActor)
|
ref.tell("pigdog", testActor)
|
||||||
|
|
||||||
|
|
@ -545,8 +562,11 @@ class TypedActorSpec extends AkkaSpec(TypedActorSpec.config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypedActorRouterSpec extends AkkaSpec(TypedActorSpec.config)
|
class TypedActorRouterSpec
|
||||||
with BeforeAndAfterEach with BeforeAndAfterAll with DefaultTimeout {
|
extends AkkaSpec(TypedActorSpec.config)
|
||||||
|
with BeforeAndAfterEach
|
||||||
|
with BeforeAndAfterAll
|
||||||
|
with DefaultTimeout {
|
||||||
|
|
||||||
import akka.actor.TypedActorSpec._
|
import akka.actor.TypedActorSpec._
|
||||||
|
|
||||||
|
|
@ -564,7 +584,9 @@ class TypedActorRouterSpec extends AkkaSpec(TypedActorSpec.config)
|
||||||
val t2 = newFooBar
|
val t2 = newFooBar
|
||||||
val t3 = newFooBar
|
val t3 = newFooBar
|
||||||
val t4 = newFooBar
|
val t4 = newFooBar
|
||||||
val routees = List(t1, t2, t3, t4) map { t => TypedActor(system).getActorRefFor(t).path.toStringWithoutAddress }
|
val routees = List(t1, t2, t3, t4).map { t =>
|
||||||
|
TypedActor(system).getActorRefFor(t).path.toStringWithoutAddress
|
||||||
|
}
|
||||||
|
|
||||||
TypedActor(system).isTypedActor(t1) should ===(true)
|
TypedActor(system).isTypedActor(t1) should ===(true)
|
||||||
TypedActor(system).isTypedActor(t2) should ===(true)
|
TypedActor(system).isTypedActor(t2) should ===(true)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
package akka.actor
|
package akka.actor
|
||||||
|
|
||||||
import akka.testkit.{ TestProbe, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, TestProbe }
|
||||||
import akka.actor.SupervisorStrategy.{ Restart, Stop }
|
import akka.actor.SupervisorStrategy.{ Restart, Stop }
|
||||||
import akka.dispatch.sysmsg.SystemMessage
|
import akka.dispatch.sysmsg.SystemMessage
|
||||||
import akka.event.EventStream
|
import akka.event.EventStream
|
||||||
|
|
@ -12,15 +12,16 @@ import scala.util.control.NoStackTrace
|
||||||
|
|
||||||
object UidClashTest {
|
object UidClashTest {
|
||||||
|
|
||||||
class TerminatedForNonWatchedActor extends Exception("Received Terminated for actor that was not actually watched")
|
class TerminatedForNonWatchedActor
|
||||||
|
extends Exception("Received Terminated for actor that was not actually watched")
|
||||||
with NoStackTrace
|
with NoStackTrace
|
||||||
|
|
||||||
@volatile var oldActor: ActorRef = _
|
@volatile var oldActor: ActorRef = _
|
||||||
|
|
||||||
private[akka] class EvilCollidingActorRef(
|
private[akka] class EvilCollidingActorRef(override val provider: ActorRefProvider,
|
||||||
override val provider: ActorRefProvider,
|
|
||||||
override val path: ActorPath,
|
override val path: ActorPath,
|
||||||
val eventStream: EventStream) extends MinimalActorRef {
|
val eventStream: EventStream)
|
||||||
|
extends MinimalActorRef {
|
||||||
|
|
||||||
//Ignore everything
|
//Ignore everything
|
||||||
override def isTerminated: Boolean = true
|
override def isTerminated: Boolean = true
|
||||||
|
|
@ -52,7 +53,7 @@ object UidClashTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
|
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
|
||||||
context.children foreach { child =>
|
context.children.foreach { child =>
|
||||||
oldActor = child
|
oldActor = child
|
||||||
context.unwatch(child)
|
context.unwatch(child)
|
||||||
context.stop(child)
|
context.stop(child)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ package akka.actor.dispatch
|
||||||
import language.postfixOps
|
import language.postfixOps
|
||||||
|
|
||||||
import java.rmi.RemoteException
|
import java.rmi.RemoteException
|
||||||
import java.util.concurrent.{ TimeUnit, CountDownLatch, ConcurrentHashMap }
|
import java.util.concurrent.{ ConcurrentHashMap, CountDownLatch, TimeUnit }
|
||||||
import java.util.concurrent.atomic.{ AtomicLong, AtomicInteger }
|
import java.util.concurrent.atomic.{ AtomicInteger, AtomicLong }
|
||||||
|
|
||||||
import org.scalatest.Assertions._
|
import org.scalatest.Assertions._
|
||||||
|
|
||||||
|
|
@ -91,7 +91,10 @@ object ActorModelSpec {
|
||||||
case Increment(count) => { ack(); count.incrementAndGet(); busy.switchOff(()) }
|
case Increment(count) => { ack(); count.incrementAndGet(); busy.switchOff(()) }
|
||||||
case CountDownNStop(l) => { ack(); l.countDown(); context.stop(self); busy.switchOff(()) }
|
case CountDownNStop(l) => { ack(); l.countDown(); context.stop(self); busy.switchOff(()) }
|
||||||
case Restart => { ack(); busy.switchOff(()); throw new Exception("Restart requested") }
|
case Restart => { ack(); busy.switchOff(()); throw new Exception("Restart requested") }
|
||||||
case Interrupt => { ack(); sender() ! Status.Failure(new ActorInterruptedException(new InterruptedException("Ping!"))); busy.switchOff(()); throw new InterruptedException("Ping!") }
|
case Interrupt => {
|
||||||
|
ack(); sender() ! Status.Failure(new ActorInterruptedException(new InterruptedException("Ping!")));
|
||||||
|
busy.switchOff(()); throw new InterruptedException("Ping!")
|
||||||
|
}
|
||||||
case InterruptNicely(msg) => { ack(); sender() ! msg; busy.switchOff(()); Thread.currentThread().interrupt() }
|
case InterruptNicely(msg) => { ack(); sender() ! msg; busy.switchOff(()); Thread.currentThread().interrupt() }
|
||||||
case ThrowException(e: Throwable) => { ack(); busy.switchOff(()); throw e }
|
case ThrowException(e: Throwable) => { ack(); busy.switchOff(()); throw e }
|
||||||
case DoubleStop => { ack(); context.stop(self); context.stop(self); busy.switchOff }
|
case DoubleStop => { ack(); context.stop(self); context.stop(self); busy.switchOff }
|
||||||
|
|
@ -106,7 +109,8 @@ object ActorModelSpec {
|
||||||
val msgsReceived = new AtomicLong(0)
|
val msgsReceived = new AtomicLong(0)
|
||||||
val msgsProcessed = new AtomicLong(0)
|
val msgsProcessed = new AtomicLong(0)
|
||||||
val restarts = new AtomicLong(0)
|
val restarts = new AtomicLong(0)
|
||||||
override def toString = "InterceptorStats(susp=" + suspensions +
|
override def toString =
|
||||||
|
"InterceptorStats(susp=" + suspensions +
|
||||||
",res=" + resumes + ",reg=" + registers + ",unreg=" + unregisters +
|
",res=" + resumes + ",reg=" + registers + ",unreg=" + unregisters +
|
||||||
",recv=" + msgsReceived + ",proc=" + msgsProcessed + ",restart=" + restarts
|
",recv=" + msgsReceived + ",proc=" + msgsProcessed + ",restart=" + restarts
|
||||||
}
|
}
|
||||||
|
|
@ -160,14 +164,18 @@ object ActorModelSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def assertDispatcher(dispatcher: MessageDispatcherInterceptor)(
|
def assertDispatcher(dispatcher: MessageDispatcherInterceptor)(stops: Long = dispatcher.stops.get())(
|
||||||
stops: Long = dispatcher.stops.get())(implicit system: ActorSystem): Unit = {
|
implicit system: ActorSystem): Unit = {
|
||||||
val deadline = System.currentTimeMillis + dispatcher.shutdownTimeout.toMillis * 5
|
val deadline = System.currentTimeMillis + dispatcher.shutdownTimeout.toMillis * 5
|
||||||
try {
|
try {
|
||||||
await(deadline)(stops == dispatcher.stops.get)
|
await(deadline)(stops == dispatcher.stops.get)
|
||||||
} catch {
|
} catch {
|
||||||
case e: Throwable =>
|
case e: Throwable =>
|
||||||
system.eventStream.publish(Error(e, dispatcher.toString, dispatcher.getClass, "actual: stops=" + dispatcher.stops.get +
|
system.eventStream.publish(
|
||||||
|
Error(e,
|
||||||
|
dispatcher.toString,
|
||||||
|
dispatcher.getClass,
|
||||||
|
"actual: stops=" + dispatcher.stops.get +
|
||||||
" required: stops=" + stops))
|
" required: stops=" + stops))
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
@ -194,14 +202,7 @@ object ActorModelSpec {
|
||||||
msgsReceived: Long = 0,
|
msgsReceived: Long = 0,
|
||||||
msgsProcessed: Long = 0,
|
msgsProcessed: Long = 0,
|
||||||
restarts: Long = 0)(implicit system: ActorSystem): Unit = {
|
restarts: Long = 0)(implicit system: ActorSystem): Unit = {
|
||||||
assertRef(actorRef, dispatcher)(
|
assertRef(actorRef, dispatcher)(suspensions, resumes, registers, unregisters, msgsReceived, msgsProcessed, restarts)
|
||||||
suspensions,
|
|
||||||
resumes,
|
|
||||||
registers,
|
|
||||||
unregisters,
|
|
||||||
msgsReceived,
|
|
||||||
msgsProcessed,
|
|
||||||
restarts)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def assertRef(actorRef: ActorRef, dispatcher: MessageDispatcher = null)(
|
def assertRef(actorRef: ActorRef, dispatcher: MessageDispatcher = null)(
|
||||||
|
|
@ -212,7 +213,9 @@ object ActorModelSpec {
|
||||||
msgsReceived: Long = statsFor(actorRef, dispatcher).msgsReceived.get(),
|
msgsReceived: Long = statsFor(actorRef, dispatcher).msgsReceived.get(),
|
||||||
msgsProcessed: Long = statsFor(actorRef, dispatcher).msgsProcessed.get(),
|
msgsProcessed: Long = statsFor(actorRef, dispatcher).msgsProcessed.get(),
|
||||||
restarts: Long = statsFor(actorRef, dispatcher).restarts.get())(implicit system: ActorSystem): Unit = {
|
restarts: Long = statsFor(actorRef, dispatcher).restarts.get())(implicit system: ActorSystem): Unit = {
|
||||||
val stats = statsFor(actorRef, Option(dispatcher).getOrElse(actorRef.asInstanceOf[ActorRefWithCell].underlying.asInstanceOf[ActorCell].dispatcher))
|
val stats = statsFor(actorRef,
|
||||||
|
Option(dispatcher).getOrElse(
|
||||||
|
actorRef.asInstanceOf[ActorRefWithCell].underlying.asInstanceOf[ActorCell].dispatcher))
|
||||||
val deadline = System.currentTimeMillis + 1000
|
val deadline = System.currentTimeMillis + 1000
|
||||||
try {
|
try {
|
||||||
await(deadline)(stats.suspensions.get() == suspensions)
|
await(deadline)(stats.suspensions.get() == suspensions)
|
||||||
|
|
@ -224,10 +227,10 @@ object ActorModelSpec {
|
||||||
await(deadline)(stats.restarts.get() == restarts)
|
await(deadline)(stats.restarts.get() == restarts)
|
||||||
} catch {
|
} catch {
|
||||||
case e: Throwable =>
|
case e: Throwable =>
|
||||||
system.eventStream.publish(Error(
|
system.eventStream.publish(
|
||||||
e,
|
Error(e,
|
||||||
Option(dispatcher).toString,
|
Option(dispatcher).toString,
|
||||||
(Option(dispatcher) getOrElse this).getClass,
|
Option(dispatcher).getOrElse(this).getClass,
|
||||||
"actual: " + stats + ", required: InterceptorStats(susp=" + suspensions +
|
"actual: " + stats + ", required: InterceptorStats(susp=" + suspensions +
|
||||||
",res=" + resumes + ",reg=" + registers + ",unreg=" + unregisters +
|
",res=" + resumes + ",reg=" + registers + ",unreg=" + unregisters +
|
||||||
",recv=" + msgsReceived + ",proc=" + msgsProcessed + ",restart=" + restarts))
|
",recv=" + msgsReceived + ",proc=" + msgsProcessed + ",restart=" + restarts))
|
||||||
|
|
@ -273,8 +276,7 @@ abstract class ActorModelSpec(config: String) extends AkkaSpec(config) with Defa
|
||||||
assertDispatcher(dispatcher)(stops = 0)
|
assertDispatcher(dispatcher)(stops = 0)
|
||||||
system.stop(a)
|
system.stop(a)
|
||||||
assertDispatcher(dispatcher)(stops = 1)
|
assertDispatcher(dispatcher)(stops = 1)
|
||||||
assertRef(a, dispatcher)(
|
assertRef(a, dispatcher)(suspensions = 0,
|
||||||
suspensions = 0,
|
|
||||||
resumes = 0,
|
resumes = 0,
|
||||||
registers = 1,
|
registers = 1,
|
||||||
unregisters = 1,
|
unregisters = 1,
|
||||||
|
|
@ -335,7 +337,8 @@ abstract class ActorModelSpec(config: String) extends AkkaSpec(config) with Defa
|
||||||
def spawn(f: => Unit): Unit = {
|
def spawn(f: => Unit): Unit = {
|
||||||
(new Thread {
|
(new Thread {
|
||||||
override def run(): Unit =
|
override def run(): Unit =
|
||||||
try f catch {
|
try f
|
||||||
|
catch {
|
||||||
case e: Throwable => system.eventStream.publish(Error(e, "spawn", this.getClass, "error in spawned thread"))
|
case e: Throwable => system.eventStream.publish(Error(e, "spawn", this.getClass, "error in spawned thread"))
|
||||||
}
|
}
|
||||||
}).start()
|
}).start()
|
||||||
|
|
@ -353,12 +356,15 @@ abstract class ActorModelSpec(config: String) extends AkkaSpec(config) with Defa
|
||||||
|
|
||||||
a.resume(causedByFailure = null)
|
a.resume(causedByFailure = null)
|
||||||
assertCountDown(done, 3.seconds.dilated.toMillis, "Should resume processing of messages when resumed")
|
assertCountDown(done, 3.seconds.dilated.toMillis, "Should resume processing of messages when resumed")
|
||||||
assertRefDefaultZero(a)(registers = 1, msgsReceived = 1, msgsProcessed = 1,
|
assertRefDefaultZero(a)(registers = 1, msgsReceived = 1, msgsProcessed = 1, suspensions = 1, resumes = 1)
|
||||||
suspensions = 1, resumes = 1)
|
|
||||||
|
|
||||||
system.stop(a)
|
system.stop(a)
|
||||||
assertRefDefaultZero(a)(registers = 1, unregisters = 1, msgsReceived = 1, msgsProcessed = 1,
|
assertRefDefaultZero(a)(registers = 1,
|
||||||
suspensions = 1, resumes = 1)
|
unregisters = 1,
|
||||||
|
msgsReceived = 1,
|
||||||
|
msgsProcessed = 1,
|
||||||
|
suspensions = 1,
|
||||||
|
resumes = 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
"handle waves of actors" in {
|
"handle waves of actors" in {
|
||||||
|
|
@ -381,7 +387,8 @@ abstract class ActorModelSpec(config: String) extends AkkaSpec(config) with Defa
|
||||||
// the boss doesn't create children fast enough to keep the dispatcher from becoming empty
|
// the boss doesn't create children fast enough to keep the dispatcher from becoming empty
|
||||||
// and it needs to be on a separate thread to not deadlock the calling thread dispatcher
|
// and it needs to be on a separate thread to not deadlock the calling thread dispatcher
|
||||||
new Thread(new Runnable {
|
new Thread(new Runnable {
|
||||||
def run() = Future {
|
def run() =
|
||||||
|
Future {
|
||||||
keepAliveLatch.await(waitTime, TimeUnit.MILLISECONDS)
|
keepAliveLatch.await(waitTime, TimeUnit.MILLISECONDS)
|
||||||
}(dispatcher)
|
}(dispatcher)
|
||||||
}).start()
|
}).start()
|
||||||
|
|
@ -395,18 +402,18 @@ abstract class ActorModelSpec(config: String) extends AkkaSpec(config) with Defa
|
||||||
val team = dispatcher.team
|
val team = dispatcher.team
|
||||||
val mq = dispatcher.messageQueue
|
val mq = dispatcher.messageQueue
|
||||||
|
|
||||||
System.err.println("Teammates left: " + team.size + " stopLatch: " + stopLatch.getCount + " inhab:" + dispatcher.inhabitants)
|
System.err.println(
|
||||||
|
"Teammates left: " + team.size + " stopLatch: " + stopLatch.getCount + " inhab:" + dispatcher.inhabitants)
|
||||||
|
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
team.asScala.toList
|
team.asScala.toList.sortBy(_.self.path).foreach { cell: ActorCell =>
|
||||||
.sortBy(_.self.path)
|
System.err.println(
|
||||||
.foreach { cell: ActorCell =>
|
" - " + cell.self.path + " " + cell.isTerminated + " " + cell.mailbox.currentStatus + " "
|
||||||
System.err.println(" - " + cell.self.path + " " + cell.isTerminated + " " + cell.mailbox.currentStatus + " "
|
|
||||||
+ cell.mailbox.numberOfMessages + " " + cell.mailbox.systemDrain(SystemMessageList.LNil).size)
|
+ cell.mailbox.numberOfMessages + " " + cell.mailbox.systemDrain(SystemMessageList.LNil).size)
|
||||||
}
|
}
|
||||||
|
|
||||||
System.err.println("Mailbox: " + mq.numberOfMessages + " " + mq.hasMessages)
|
System.err.println("Mailbox: " + mq.numberOfMessages + " " + mq.hasMessages)
|
||||||
Iterator.continually(mq.dequeue) takeWhile (_ ne null) foreach System.err.println
|
Iterator.continually(mq.dequeue).takeWhile(_ ne null).foreach(System.err.println)
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,8 +432,7 @@ abstract class ActorModelSpec(config: String) extends AkkaSpec(config) with Defa
|
||||||
}
|
}
|
||||||
|
|
||||||
"continue to process messages when a thread gets interrupted and throws an exception" in {
|
"continue to process messages when a thread gets interrupted and throws an exception" in {
|
||||||
filterEvents(
|
filterEvents(EventFilter[InterruptedException](),
|
||||||
EventFilter[InterruptedException](),
|
|
||||||
EventFilter[ActorInterruptedException](),
|
EventFilter[ActorInterruptedException](),
|
||||||
EventFilter[akka.event.Logging.LoggerException]()) {
|
EventFilter[akka.event.Logging.LoggerException]()) {
|
||||||
implicit val dispatcher = interceptedDispatcher()
|
implicit val dispatcher = interceptedDispatcher()
|
||||||
|
|
@ -442,10 +448,10 @@ abstract class ActorModelSpec(config: String) extends AkkaSpec(config) with Defa
|
||||||
|
|
||||||
val c = system.scheduler.scheduleOnce(2.seconds) {
|
val c = system.scheduler.scheduleOnce(2.seconds) {
|
||||||
import collection.JavaConverters._
|
import collection.JavaConverters._
|
||||||
Thread.getAllStackTraces().asScala foreach {
|
Thread.getAllStackTraces().asScala.foreach {
|
||||||
case (thread, stack) =>
|
case (thread, stack) =>
|
||||||
println(s"$thread:")
|
println(s"$thread:")
|
||||||
stack foreach (s => println(s"\t$s"))
|
stack.foreach(s => println(s"\t$s"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(Await.result(f1, timeout.duration) === "foo")
|
assert(Await.result(f1, timeout.duration) === "foo")
|
||||||
|
|
@ -535,8 +541,7 @@ object DispatcherModelSpec {
|
||||||
import akka.util.Helpers.ConfigOps
|
import akka.util.Helpers.ConfigOps
|
||||||
|
|
||||||
private val instance: MessageDispatcher =
|
private val instance: MessageDispatcher =
|
||||||
new Dispatcher(
|
new Dispatcher(this,
|
||||||
this,
|
|
||||||
config.getString("id"),
|
config.getString("id"),
|
||||||
config.getInt("throughput"),
|
config.getInt("throughput"),
|
||||||
config.getNanosDuration("throughput-deadline-time"),
|
config.getNanosDuration("throughput-deadline-time"),
|
||||||
|
|
@ -554,7 +559,9 @@ class DispatcherModelSpec extends ActorModelSpec(DispatcherModelSpec.config) {
|
||||||
|
|
||||||
override def interceptedDispatcher(): MessageDispatcherInterceptor = {
|
override def interceptedDispatcher(): MessageDispatcherInterceptor = {
|
||||||
// use new id for each test, since the MessageDispatcherInterceptor holds state
|
// use new id for each test, since the MessageDispatcherInterceptor holds state
|
||||||
system.dispatchers.lookup("test-dispatcher-" + dispatcherCount.incrementAndGet()).asInstanceOf[MessageDispatcherInterceptor]
|
system.dispatchers
|
||||||
|
.lookup("test-dispatcher-" + dispatcherCount.incrementAndGet())
|
||||||
|
.asInstanceOf[MessageDispatcherInterceptor]
|
||||||
}
|
}
|
||||||
|
|
||||||
override def dispatcherType = "Dispatcher"
|
override def dispatcherType = "Dispatcher"
|
||||||
|
|
@ -596,7 +603,8 @@ object BalancingDispatcherModelSpec {
|
||||||
}
|
}
|
||||||
""" +
|
""" +
|
||||||
// use unique dispatcher id for each test, since MessageDispatcherInterceptor holds state
|
// use unique dispatcher id for each test, since MessageDispatcherInterceptor holds state
|
||||||
(for (n <- 1 to 30) yield """
|
(for (n <- 1 to 30)
|
||||||
|
yield """
|
||||||
test-balancing-dispatcher-%s {
|
test-balancing-dispatcher-%s {
|
||||||
type = "akka.actor.dispatch.BalancingDispatcherModelSpec$BalancingMessageDispatcherInterceptorConfigurator"
|
type = "akka.actor.dispatch.BalancingDispatcherModelSpec$BalancingMessageDispatcherInterceptorConfigurator"
|
||||||
throughput=1
|
throughput=1
|
||||||
|
|
@ -609,8 +617,7 @@ object BalancingDispatcherModelSpec {
|
||||||
import akka.util.Helpers.ConfigOps
|
import akka.util.Helpers.ConfigOps
|
||||||
|
|
||||||
override protected def create(mailboxType: MailboxType): BalancingDispatcher =
|
override protected def create(mailboxType: MailboxType): BalancingDispatcher =
|
||||||
new BalancingDispatcher(
|
new BalancingDispatcher(this,
|
||||||
this,
|
|
||||||
config.getString("id"),
|
config.getString("id"),
|
||||||
config.getInt("throughput"),
|
config.getInt("throughput"),
|
||||||
config.getNanosDuration("throughput-deadline-time"),
|
config.getNanosDuration("throughput-deadline-time"),
|
||||||
|
|
@ -628,7 +635,9 @@ class BalancingDispatcherModelSpec extends ActorModelSpec(BalancingDispatcherMod
|
||||||
|
|
||||||
override def interceptedDispatcher(): MessageDispatcherInterceptor = {
|
override def interceptedDispatcher(): MessageDispatcherInterceptor = {
|
||||||
// use new id for each test, since the MessageDispatcherInterceptor holds state
|
// use new id for each test, since the MessageDispatcherInterceptor holds state
|
||||||
system.dispatchers.lookup("test-balancing-dispatcher-" + dispatcherCount.incrementAndGet()).asInstanceOf[MessageDispatcherInterceptor]
|
system.dispatchers
|
||||||
|
.lookup("test-balancing-dispatcher-" + dispatcherCount.incrementAndGet())
|
||||||
|
.asInstanceOf[MessageDispatcherInterceptor]
|
||||||
}
|
}
|
||||||
|
|
||||||
override def dispatcherType = "Balancing Dispatcher"
|
override def dispatcherType = "Balancing Dispatcher"
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
package akka.actor.dispatch
|
package akka.actor.dispatch
|
||||||
|
|
||||||
import java.util.concurrent.{ TimeUnit, CountDownLatch }
|
import java.util.concurrent.{ CountDownLatch, TimeUnit }
|
||||||
|
|
||||||
import akka.actor.{ Props, ActorRefWithCell, ActorCell, Actor }
|
import akka.actor.{ Actor, ActorCell, ActorRefWithCell, Props }
|
||||||
import akka.dispatch.Mailbox
|
import akka.dispatch.Mailbox
|
||||||
import akka.testkit.AkkaSpec
|
import akka.testkit.AkkaSpec
|
||||||
|
|
||||||
|
|
@ -48,15 +48,18 @@ class BalancingDispatcherSpec extends AkkaSpec(BalancingDispatcherSpec.config) {
|
||||||
def receive = { case _ => {} }
|
def receive = { case _ => {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChildActor extends ParentActor {
|
class ChildActor extends ParentActor {}
|
||||||
}
|
|
||||||
|
|
||||||
"A BalancingDispatcher" must {
|
"A BalancingDispatcher" must {
|
||||||
"have fast actor stealing work from slow actor" in {
|
"have fast actor stealing work from slow actor" in {
|
||||||
val finishedCounter = new CountDownLatch(110)
|
val finishedCounter = new CountDownLatch(110)
|
||||||
|
|
||||||
val slow = system.actorOf(Props(new DelayableActor(50, finishedCounter)).withDispatcher(delayableActorDispatcher)).asInstanceOf[ActorRefWithCell]
|
val slow = system
|
||||||
val fast = system.actorOf(Props(new DelayableActor(10, finishedCounter)).withDispatcher(delayableActorDispatcher)).asInstanceOf[ActorRefWithCell]
|
.actorOf(Props(new DelayableActor(50, finishedCounter)).withDispatcher(delayableActorDispatcher))
|
||||||
|
.asInstanceOf[ActorRefWithCell]
|
||||||
|
val fast = system
|
||||||
|
.actorOf(Props(new DelayableActor(10, finishedCounter)).withDispatcher(delayableActorDispatcher))
|
||||||
|
.asInstanceOf[ActorRefWithCell]
|
||||||
|
|
||||||
var sentToFast = 0
|
var sentToFast = 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import language.postfixOps
|
||||||
import java.util.concurrent.{ CountDownLatch, TimeUnit }
|
import java.util.concurrent.{ CountDownLatch, TimeUnit }
|
||||||
import java.util.concurrent.atomic.{ AtomicBoolean }
|
import java.util.concurrent.atomic.{ AtomicBoolean }
|
||||||
import akka.testkit.{ AkkaSpec }
|
import akka.testkit.{ AkkaSpec }
|
||||||
import akka.actor.{ Props, Actor }
|
import akka.actor.{ Actor, Props }
|
||||||
import scala.concurrent.Await
|
import scala.concurrent.Await
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import akka.testkit.DefaultTimeout
|
import akka.testkit.DefaultTimeout
|
||||||
|
|
@ -80,11 +80,9 @@ class DispatcherActorSpec extends AkkaSpec(DispatcherActorSpec.config) with Defa
|
||||||
val latch = new CountDownLatch(100)
|
val latch = new CountDownLatch(100)
|
||||||
val start = new CountDownLatch(1)
|
val start = new CountDownLatch(1)
|
||||||
val fastOne = system.actorOf(
|
val fastOne = system.actorOf(
|
||||||
Props(new Actor { def receive = { case "sabotage" => works.set(false) } })
|
Props(new Actor { def receive = { case "sabotage" => works.set(false) } }).withDispatcher(throughputDispatcher))
|
||||||
.withDispatcher(throughputDispatcher))
|
|
||||||
|
|
||||||
val slowOne = system.actorOf(
|
val slowOne = system.actorOf(Props(new Actor {
|
||||||
Props(new Actor {
|
|
||||||
def receive = {
|
def receive = {
|
||||||
case "hogexecutor" => { sender() ! "OK"; start.await }
|
case "hogexecutor" => { sender() ! "OK"; start.await }
|
||||||
case "ping" => if (works.get) latch.countDown()
|
case "ping" => if (works.get) latch.countDown()
|
||||||
|
|
@ -92,7 +90,9 @@ class DispatcherActorSpec extends AkkaSpec(DispatcherActorSpec.config) with Defa
|
||||||
}).withDispatcher(throughputDispatcher))
|
}).withDispatcher(throughputDispatcher))
|
||||||
|
|
||||||
assert(Await.result(slowOne ? "hogexecutor", timeout.duration) === "OK")
|
assert(Await.result(slowOne ? "hogexecutor", timeout.duration) === "OK")
|
||||||
(1 to 100) foreach { _ => slowOne ! "ping" }
|
(1 to 100).foreach { _ =>
|
||||||
|
slowOne ! "ping"
|
||||||
|
}
|
||||||
fastOne ! "sabotage"
|
fastOne ! "sabotage"
|
||||||
start.countDown()
|
start.countDown()
|
||||||
latch.await(10, TimeUnit.SECONDS)
|
latch.await(10, TimeUnit.SECONDS)
|
||||||
|
|
@ -110,15 +110,13 @@ class DispatcherActorSpec extends AkkaSpec(DispatcherActorSpec.config) with Defa
|
||||||
val start = new CountDownLatch(1)
|
val start = new CountDownLatch(1)
|
||||||
val ready = new CountDownLatch(1)
|
val ready = new CountDownLatch(1)
|
||||||
|
|
||||||
val fastOne = system.actorOf(
|
val fastOne = system.actorOf(Props(new Actor {
|
||||||
Props(new Actor {
|
|
||||||
def receive = {
|
def receive = {
|
||||||
case "ping" => if (works.get) latch.countDown(); context.stop(self)
|
case "ping" => if (works.get) latch.countDown(); context.stop(self)
|
||||||
}
|
}
|
||||||
}).withDispatcher(throughputDispatcher))
|
}).withDispatcher(throughputDispatcher))
|
||||||
|
|
||||||
val slowOne = system.actorOf(
|
val slowOne = system.actorOf(Props(new Actor {
|
||||||
Props(new Actor {
|
|
||||||
def receive = {
|
def receive = {
|
||||||
case "hogexecutor" => { ready.countDown(); start.await }
|
case "hogexecutor" => { ready.countDown(); start.await }
|
||||||
case "ping" => { works.set(false); context.stop(self) }
|
case "ping" => { works.set(false); context.stop(self) }
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,8 @@ object DispatchersSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
class OneShotMailboxType(settings: ActorSystem.Settings, config: Config)
|
class OneShotMailboxType(settings: ActorSystem.Settings, config: Config)
|
||||||
extends MailboxType with ProducesMessageQueue[DoublingMailbox] {
|
extends MailboxType
|
||||||
|
with ProducesMessageQueue[DoublingMailbox] {
|
||||||
val created = new AtomicBoolean(false)
|
val created = new AtomicBoolean(false)
|
||||||
override def create(owner: Option[ActorRef], system: Option[ActorSystem]) =
|
override def create(owner: Option[ActorRef], system: Option[ActorSystem]) =
|
||||||
if (created.compareAndSet(false, true)) {
|
if (created.compareAndSet(false, true)) {
|
||||||
|
|
@ -82,8 +83,8 @@ object DispatchersSpec {
|
||||||
class DoublingMailbox(owner: Option[ActorRef]) extends UnboundedQueueBasedMessageQueue {
|
class DoublingMailbox(owner: Option[ActorRef]) extends UnboundedQueueBasedMessageQueue {
|
||||||
final val queue = new ConcurrentLinkedQueue[Envelope]()
|
final val queue = new ConcurrentLinkedQueue[Envelope]()
|
||||||
override def enqueue(receiver: ActorRef, handle: Envelope): Unit = {
|
override def enqueue(receiver: ActorRef, handle: Envelope): Unit = {
|
||||||
queue add handle
|
queue.add(handle)
|
||||||
queue add handle
|
queue.add(handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,19 +109,20 @@ class DispatchersSpec extends AkkaSpec(DispatchersSpec.config) with ImplicitSend
|
||||||
val id = "id"
|
val id = "id"
|
||||||
|
|
||||||
def instance(dispatcher: MessageDispatcher): (MessageDispatcher) => Boolean = _ == dispatcher
|
def instance(dispatcher: MessageDispatcher): (MessageDispatcher) => Boolean = _ == dispatcher
|
||||||
def ofType[T <: MessageDispatcher: ClassTag]: (MessageDispatcher) => Boolean = _.getClass == implicitly[ClassTag[T]].runtimeClass
|
def ofType[T <: MessageDispatcher: ClassTag]: (MessageDispatcher) => Boolean =
|
||||||
|
_.getClass == implicitly[ClassTag[T]].runtimeClass
|
||||||
|
|
||||||
def typesAndValidators: Map[String, (MessageDispatcher) => Boolean] = Map(
|
def typesAndValidators: Map[String, (MessageDispatcher) => Boolean] =
|
||||||
"PinnedDispatcher" -> ofType[PinnedDispatcher],
|
Map("PinnedDispatcher" -> ofType[PinnedDispatcher], "Dispatcher" -> ofType[Dispatcher])
|
||||||
"Dispatcher" -> ofType[Dispatcher])
|
|
||||||
|
|
||||||
def validTypes = typesAndValidators.keys.toList
|
def validTypes = typesAndValidators.keys.toList
|
||||||
|
|
||||||
val defaultDispatcherConfig = settings.config.getConfig("akka.actor.default-dispatcher")
|
val defaultDispatcherConfig = settings.config.getConfig("akka.actor.default-dispatcher")
|
||||||
|
|
||||||
lazy val allDispatchers: Map[String, MessageDispatcher] = {
|
lazy val allDispatchers: Map[String, MessageDispatcher] = {
|
||||||
validTypes.map(t => (t, from(ConfigFactory.parseMap(Map(tipe -> t, id -> t).asJava).
|
validTypes
|
||||||
withFallback(defaultDispatcherConfig)))).toMap
|
.map(t => (t, from(ConfigFactory.parseMap(Map(tipe -> t, id -> t).asJava).withFallback(defaultDispatcherConfig))))
|
||||||
|
.toMap
|
||||||
}
|
}
|
||||||
|
|
||||||
def assertMyDispatcherIsUsed(actor: ActorRef): Unit = {
|
def assertMyDispatcherIsUsed(actor: ActorRef): Unit = {
|
||||||
|
|
@ -157,8 +159,10 @@ class DispatchersSpec extends AkkaSpec(DispatchersSpec.config) with ImplicitSend
|
||||||
|
|
||||||
"throw ConfigurationException if type does not exist" in {
|
"throw ConfigurationException if type does not exist" in {
|
||||||
intercept[ConfigurationException] {
|
intercept[ConfigurationException] {
|
||||||
from(ConfigFactory.parseMap(Map(tipe -> "typedoesntexist", id -> "invalid-dispatcher").asJava).
|
from(
|
||||||
withFallback(defaultDispatcherConfig))
|
ConfigFactory
|
||||||
|
.parseMap(Map(tipe -> "typedoesntexist", id -> "invalid-dispatcher").asJava)
|
||||||
|
.withFallback(defaultDispatcherConfig))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ package akka.actor.dispatch
|
||||||
import java.util.concurrent.{ CountDownLatch, TimeUnit }
|
import java.util.concurrent.{ CountDownLatch, TimeUnit }
|
||||||
|
|
||||||
import akka.testkit._
|
import akka.testkit._
|
||||||
import akka.actor.{ Props, Actor }
|
import akka.actor.{ Actor, Props }
|
||||||
import akka.testkit.AkkaSpec
|
import akka.testkit.AkkaSpec
|
||||||
import org.scalatest.BeforeAndAfterEach
|
import org.scalatest.BeforeAndAfterEach
|
||||||
import scala.concurrent.Await
|
import scala.concurrent.Await
|
||||||
|
|
@ -38,7 +38,8 @@ class PinnedActorSpec extends AkkaSpec(PinnedActorSpec.config) with BeforeAndAft
|
||||||
|
|
||||||
"support tell" in {
|
"support tell" in {
|
||||||
var oneWay = new CountDownLatch(1)
|
var oneWay = new CountDownLatch(1)
|
||||||
val actor = system.actorOf(Props(new Actor { def receive = { case "OneWay" => oneWay.countDown() } }).withDispatcher("pinned-dispatcher"))
|
val actor = system.actorOf(
|
||||||
|
Props(new Actor { def receive = { case "OneWay" => oneWay.countDown() } }).withDispatcher("pinned-dispatcher"))
|
||||||
val result = actor ! "OneWay"
|
val result = actor ! "OneWay"
|
||||||
assert(oneWay.await(1, TimeUnit.SECONDS))
|
assert(oneWay.await(1, TimeUnit.SECONDS))
|
||||||
system.stop(actor)
|
system.stop(actor)
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,9 @@ class DispatchSpec extends AkkaSpec("akka.actor.serialize-messages = on") with D
|
||||||
"The dispatcher" should {
|
"The dispatcher" should {
|
||||||
"log an appropriate message when akka.actor.serialize-messages triggers a serialization error" in {
|
"log an appropriate message when akka.actor.serialize-messages triggers a serialization error" in {
|
||||||
val actor = system.actorOf(Props[EmptyActor])
|
val actor = system.actorOf(Props[EmptyActor])
|
||||||
EventFilter[Exception](pattern = ".*NoSerializationVerificationNeeded.*", occurrences = 1) intercept {
|
EventFilter[Exception](pattern = ".*NoSerializationVerificationNeeded.*", occurrences = 1).intercept {
|
||||||
actor ! new UnserializableMessageClass
|
actor ! new UnserializableMessageClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,13 @@ class ListenerSpec extends AkkaSpec {
|
||||||
val barCount = new AtomicInteger(0)
|
val barCount = new AtomicInteger(0)
|
||||||
|
|
||||||
val broadcast = system.actorOf(Props(new Actor with Listeners {
|
val broadcast = system.actorOf(Props(new Actor with Listeners {
|
||||||
def receive = listenerManagement orElse {
|
def receive = listenerManagement.orElse {
|
||||||
case "foo" => gossip("bar")
|
case "foo" => gossip("bar")
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def newListener = system.actorOf(Props(new Actor {
|
def newListener =
|
||||||
|
system.actorOf(Props(new Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
case "bar" =>
|
case "bar" =>
|
||||||
barCount.incrementAndGet
|
barCount.incrementAndGet
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,7 @@ class ActorSystemSetupSpec extends WordSpec with Matchers {
|
||||||
|
|
||||||
"store and retrieve a setup" in {
|
"store and retrieve a setup" in {
|
||||||
val setup = DummySetup("Al Dente")
|
val setup = DummySetup("Al Dente")
|
||||||
val setups = ActorSystemSetup()
|
val setups = ActorSystemSetup().withSetup(setup)
|
||||||
.withSetup(setup)
|
|
||||||
|
|
||||||
setups.get[DummySetup] should ===(Some(setup))
|
setups.get[DummySetup] should ===(Some(setup))
|
||||||
setups.get[DummySetup2] should ===(None)
|
setups.get[DummySetup2] should ===(None)
|
||||||
|
|
@ -28,9 +27,7 @@ class ActorSystemSetupSpec extends WordSpec with Matchers {
|
||||||
"replace setup if already defined" in {
|
"replace setup if already defined" in {
|
||||||
val setup1 = DummySetup("Al Dente")
|
val setup1 = DummySetup("Al Dente")
|
||||||
val setup2 = DummySetup("Earl E. Bird")
|
val setup2 = DummySetup("Earl E. Bird")
|
||||||
val setups = ActorSystemSetup()
|
val setups = ActorSystemSetup().withSetup(setup1).withSetup(setup2)
|
||||||
.withSetup(setup1)
|
|
||||||
.withSetup(setup2)
|
|
||||||
|
|
||||||
setups.get[DummySetup] should ===(Some(setup2))
|
setups.get[DummySetup] should ===(Some(setup2))
|
||||||
}
|
}
|
||||||
|
|
@ -61,10 +58,7 @@ class ActorSystemSetupSpec extends WordSpec with Matchers {
|
||||||
val setup = DummySetup("Tad Moore")
|
val setup = DummySetup("Tad Moore")
|
||||||
system = ActorSystem("name", ActorSystemSetup(setup))
|
system = ActorSystem("name", ActorSystemSetup(setup))
|
||||||
|
|
||||||
system
|
system.settings.setup.get[DummySetup] should ===(Some(setup))
|
||||||
.settings
|
|
||||||
.setup
|
|
||||||
.get[DummySetup] should ===(Some(setup))
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
TestKit.shutdownActorSystem(system)
|
TestKit.shutdownActorSystem(system)
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ class Future2ActorSpec extends AkkaSpec with DefaultTimeout {
|
||||||
"The Future2Actor bridge" must {
|
"The Future2Actor bridge" must {
|
||||||
|
|
||||||
"support convenient sending to multiple destinations" in {
|
"support convenient sending to multiple destinations" in {
|
||||||
Future(42) pipeTo testActor pipeTo testActor
|
Future(42).pipeTo(testActor).pipeTo(testActor)
|
||||||
expectMsgAllOf(1 second, 42, 42)
|
expectMsgAllOf(1 second, 42, 42)
|
||||||
}
|
}
|
||||||
|
|
||||||
"support convenient sending to multiple destinations with implicit sender" in {
|
"support convenient sending to multiple destinations with implicit sender" in {
|
||||||
implicit val someActor = system.actorOf(Props(new Actor { def receive = Actor.emptyBehavior }))
|
implicit val someActor = system.actorOf(Props(new Actor { def receive = Actor.emptyBehavior }))
|
||||||
Future(42) pipeTo testActor pipeTo testActor
|
Future(42).pipeTo(testActor).pipeTo(testActor)
|
||||||
expectMsgAllOf(1 second, 42, 42)
|
expectMsgAllOf(1 second, 42, 42)
|
||||||
lastSender should ===(someActor)
|
lastSender should ===(someActor)
|
||||||
}
|
}
|
||||||
|
|
@ -40,8 +40,8 @@ class Future2ActorSpec extends AkkaSpec with DefaultTimeout {
|
||||||
"support reply via sender" in {
|
"support reply via sender" in {
|
||||||
val actor = system.actorOf(Props(new Actor {
|
val actor = system.actorOf(Props(new Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
case "do" => Future(31) pipeTo context.sender()
|
case "do" => Future(31).pipeTo(context.sender())
|
||||||
case "ex" => Future(throw new AssertionError) pipeTo context.sender()
|
case "ex" => Future(throw new AssertionError).pipeTo(context.sender())
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
Await.result(actor ? "do", timeout.duration) should ===(31)
|
Await.result(actor ? "do", timeout.duration) should ===(31)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
package akka.dispatch
|
package akka.dispatch
|
||||||
|
|
||||||
import akka.testkit.{ DefaultTimeout, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, DefaultTimeout }
|
||||||
import akka.actor.{ Actor, Props }
|
import akka.actor.{ Actor, Props }
|
||||||
|
|
||||||
object ControlAwareDispatcherSpec {
|
object ControlAwareDispatcherSpec {
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,10 @@ class DispatcherShutdownSpec extends WordSpec with Matchers {
|
||||||
"eventually shutdown when used after system terminate" in {
|
"eventually shutdown when used after system terminate" in {
|
||||||
|
|
||||||
val threads = ManagementFactory.getThreadMXBean()
|
val threads = ManagementFactory.getThreadMXBean()
|
||||||
def threadCount = threads
|
def threadCount =
|
||||||
.dumpAllThreads(false, false).toList
|
threads
|
||||||
|
.dumpAllThreads(false, false)
|
||||||
|
.toList
|
||||||
.map(_.getThreadName)
|
.map(_.getThreadName)
|
||||||
.filter(_.startsWith("DispatcherShutdownSpec-akka.actor.default"))
|
.filter(_.startsWith("DispatcherShutdownSpec-akka.actor.default"))
|
||||||
.size
|
.size
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
package akka.dispatch
|
package akka.dispatch
|
||||||
|
|
||||||
import java.util.concurrent.{ ExecutorService, Executor, Executors }
|
import java.util.concurrent.{ Executor, ExecutorService, Executors }
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import scala.concurrent.{ ExecutionContext, ExecutionContextExecutor, ExecutionContextExecutorService }
|
import scala.concurrent.{ ExecutionContext, ExecutionContextExecutor, ExecutionContextExecutorService }
|
||||||
import scala.concurrent.{ Await, blocking, Promise, Future }
|
import scala.concurrent.{ blocking, Await, Future, Promise }
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import akka.testkit.{ TestLatch, AkkaSpec, DefaultTimeout }
|
import akka.testkit.{ AkkaSpec, DefaultTimeout, TestLatch }
|
||||||
import akka.util.SerializedSuspendableExecutionContext
|
import akka.util.SerializedSuspendableExecutionContext
|
||||||
import akka.testkit.TestActorRef
|
import akka.testkit.TestActorRef
|
||||||
import akka.actor.Props
|
import akka.actor.Props
|
||||||
|
|
@ -45,7 +45,8 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
|
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
|
|
||||||
def batchable[T](f: => T)(implicit ec: ExecutionContext): Unit = ec.execute(new Batchable {
|
def batchable[T](f: => T)(implicit ec: ExecutionContext): Unit =
|
||||||
|
ec.execute(new Batchable {
|
||||||
override def isBatchable = true
|
override def isBatchable = true
|
||||||
override def run: Unit = f
|
override def run: Unit = f
|
||||||
})
|
})
|
||||||
|
|
@ -54,12 +55,13 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
batchable {
|
batchable {
|
||||||
val lock, callingThreadLock, count = new AtomicInteger(0)
|
val lock, callingThreadLock, count = new AtomicInteger(0)
|
||||||
callingThreadLock.compareAndSet(0, 1) // Enable the lock
|
callingThreadLock.compareAndSet(0, 1) // Enable the lock
|
||||||
(1 to 100) foreach { i =>
|
(1 to 100).foreach { i =>
|
||||||
batchable {
|
batchable {
|
||||||
if (callingThreadLock.get != 0) p.tryFailure(new IllegalStateException("Batch was executed inline!"))
|
if (callingThreadLock.get != 0) p.tryFailure(new IllegalStateException("Batch was executed inline!"))
|
||||||
else if (count.incrementAndGet == 100) p.trySuccess(()) //Done
|
else if (count.incrementAndGet == 100) p.trySuccess(()) //Done
|
||||||
else if (lock.compareAndSet(0, 1)) {
|
else if (lock.compareAndSet(0, 1)) {
|
||||||
try Thread.sleep(10) finally lock.compareAndSet(1, 0)
|
try Thread.sleep(10)
|
||||||
|
finally lock.compareAndSet(1, 0)
|
||||||
} else p.tryFailure(new IllegalStateException("Executed batch in parallel!"))
|
} else p.tryFailure(new IllegalStateException("Executed batch in parallel!"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,14 +74,15 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
system.dispatcher.isInstanceOf[BatchingExecutor] should ===(true)
|
system.dispatcher.isInstanceOf[BatchingExecutor] should ===(true)
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
|
|
||||||
def batchable[T](f: => T)(implicit ec: ExecutionContext): Unit = ec.execute(new Batchable {
|
def batchable[T](f: => T)(implicit ec: ExecutionContext): Unit =
|
||||||
|
ec.execute(new Batchable {
|
||||||
override def isBatchable = true
|
override def isBatchable = true
|
||||||
override def run: Unit = f
|
override def run: Unit = f
|
||||||
})
|
})
|
||||||
|
|
||||||
val latch = TestLatch(101)
|
val latch = TestLatch(101)
|
||||||
batchable {
|
batchable {
|
||||||
(1 to 100) foreach { i =>
|
(1 to 100).foreach { i =>
|
||||||
batchable {
|
batchable {
|
||||||
val deadlock = TestLatch(1)
|
val deadlock = TestLatch(1)
|
||||||
batchable { deadlock.open() }
|
batchable { deadlock.open() }
|
||||||
|
|
@ -100,7 +103,9 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
// this needs to be within an OnCompleteRunnable so that things are added to the batch
|
// this needs to be within an OnCompleteRunnable so that things are added to the batch
|
||||||
val p = Future.successful(42)
|
val p = Future.successful(42)
|
||||||
// we need the callback list to be non-empty when the blocking{} call is executing
|
// we need the callback list to be non-empty when the blocking{} call is executing
|
||||||
p.onComplete { _ => () }
|
p.onComplete { _ =>
|
||||||
|
()
|
||||||
|
}
|
||||||
val r = p.map { _ =>
|
val r = p.map { _ =>
|
||||||
// trigger the resubmitUnbatched() call
|
// trigger the resubmitUnbatched() call
|
||||||
blocking { () }
|
blocking { () }
|
||||||
|
|
@ -109,7 +114,9 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
// now try again to blockOn()
|
// now try again to blockOn()
|
||||||
blocking { () }
|
blocking { () }
|
||||||
}
|
}
|
||||||
p.onComplete { _ => () }
|
p.onComplete { _ =>
|
||||||
|
()
|
||||||
|
}
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
Await.result(f, 3.seconds) should be(())
|
Await.result(f, 3.seconds) should be(())
|
||||||
|
|
@ -157,7 +164,7 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
}))
|
}))
|
||||||
val b = TestActorRef(Props(new Actor {
|
val b = TestActorRef(Props(new Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
case msg => a forward msg
|
case msg => a.forward(msg)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
val p = TestProbe()
|
val p = TestProbe()
|
||||||
|
|
@ -193,7 +200,7 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
"be suspendable and resumable" in {
|
"be suspendable and resumable" in {
|
||||||
val sec = SerializedSuspendableExecutionContext(1)(ExecutionContext.global)
|
val sec = SerializedSuspendableExecutionContext(1)(ExecutionContext.global)
|
||||||
val counter = new AtomicInteger(0)
|
val counter = new AtomicInteger(0)
|
||||||
def perform(f: Int => Int) = sec execute new Runnable { def run = counter.set(f(counter.get)) }
|
def perform(f: Int => Int) = sec.execute(new Runnable { def run = counter.set(f(counter.get)) })
|
||||||
perform(_ + 1)
|
perform(_ + 1)
|
||||||
perform(x => { sec.suspend(); x * 2 })
|
perform(x => { sec.suspend(); x * 2 })
|
||||||
awaitCond(counter.get == 2)
|
awaitCond(counter.get == 2)
|
||||||
|
|
@ -220,10 +227,12 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
val throughput = 25
|
val throughput = 25
|
||||||
val sec = SerializedSuspendableExecutionContext(throughput)(underlying)
|
val sec = SerializedSuspendableExecutionContext(throughput)(underlying)
|
||||||
sec.suspend()
|
sec.suspend()
|
||||||
def perform(f: Int => Int) = sec execute new Runnable { def run = counter.set(f(counter.get)) }
|
def perform(f: Int => Int) = sec.execute(new Runnable { def run = counter.set(f(counter.get)) })
|
||||||
|
|
||||||
val total = 1000
|
val total = 1000
|
||||||
1 to total foreach { _ => perform(_ + 1) }
|
(1 to total).foreach { _ =>
|
||||||
|
perform(_ + 1)
|
||||||
|
}
|
||||||
sec.size() should ===(total)
|
sec.size() should ===(total)
|
||||||
sec.resume()
|
sec.resume()
|
||||||
awaitCond(counter.get == total)
|
awaitCond(counter.get == total)
|
||||||
|
|
@ -235,9 +244,11 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
val sec = SerializedSuspendableExecutionContext(1)(ExecutionContext.global)
|
val sec = SerializedSuspendableExecutionContext(1)(ExecutionContext.global)
|
||||||
val total = 10000
|
val total = 10000
|
||||||
val counter = new AtomicInteger(0)
|
val counter = new AtomicInteger(0)
|
||||||
def perform(f: Int => Int) = sec execute new Runnable { def run = counter.set(f(counter.get)) }
|
def perform(f: Int => Int) = sec.execute(new Runnable { def run = counter.set(f(counter.get)) })
|
||||||
|
|
||||||
1 to total foreach { i => perform(c => if (c == (i - 1)) c + 1 else c) }
|
(1 to total).foreach { i =>
|
||||||
|
perform(c => if (c == (i - 1)) c + 1 else c)
|
||||||
|
}
|
||||||
awaitCond(counter.get == total)
|
awaitCond(counter.get == total)
|
||||||
sec.isEmpty should ===(true)
|
sec.isEmpty should ===(true)
|
||||||
}
|
}
|
||||||
|
|
@ -252,9 +263,11 @@ class ExecutionContextSpec extends AkkaSpec with DefaultTimeout {
|
||||||
val throughput = 25
|
val throughput = 25
|
||||||
val sec = SerializedSuspendableExecutionContext(throughput)(underlying)
|
val sec = SerializedSuspendableExecutionContext(throughput)(underlying)
|
||||||
sec.suspend()
|
sec.suspend()
|
||||||
def perform(f: Int => Int) = sec execute new Runnable { def run = counter.set(f(counter.get)) }
|
def perform(f: Int => Int) = sec.execute(new Runnable { def run = counter.set(f(counter.get)) })
|
||||||
perform(_ + 1)
|
perform(_ + 1)
|
||||||
1 to 10 foreach { _ => perform(identity) }
|
(1 to 10).foreach { _ =>
|
||||||
|
perform(identity)
|
||||||
|
}
|
||||||
perform(x => { sec.suspend(); x * 2 })
|
perform(x => { sec.suspend(); x * 2 })
|
||||||
perform(_ + 8)
|
perform(_ + 8)
|
||||||
sec.size should ===(13)
|
sec.size should ===(13)
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,11 @@
|
||||||
package akka.dispatch
|
package akka.dispatch
|
||||||
|
|
||||||
import akka.actor.{ Actor, Props }
|
import akka.actor.{ Actor, Props }
|
||||||
import akka.testkit.{ ImplicitSender, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, ImplicitSender }
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
|
|
||||||
object ForkJoinPoolStarvationSpec {
|
object ForkJoinPoolStarvationSpec {
|
||||||
val config = ConfigFactory.parseString(
|
val config = ConfigFactory.parseString("""
|
||||||
"""
|
|
||||||
|actorhang {
|
|actorhang {
|
||||||
|
|
|
|
||||||
| task-dispatcher {
|
| task-dispatcher {
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@ package akka.dispatch
|
||||||
|
|
||||||
import language.postfixOps
|
import language.postfixOps
|
||||||
|
|
||||||
import java.util.concurrent.{ ConcurrentLinkedQueue, BlockingQueue }
|
import java.util.concurrent.{ BlockingQueue, ConcurrentLinkedQueue }
|
||||||
import org.scalatest.{ BeforeAndAfterEach, BeforeAndAfterAll }
|
import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach }
|
||||||
import com.typesafe.config.{ Config, ConfigFactory }
|
import com.typesafe.config.{ Config, ConfigFactory }
|
||||||
import akka.actor._
|
import akka.actor._
|
||||||
import akka.testkit.{ EventFilter, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, EventFilter }
|
||||||
import scala.concurrent.{ Future, Await, ExecutionContext }
|
import scala.concurrent.{ Await, ExecutionContext, Future }
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAndAfterEach {
|
abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAndAfterEach {
|
||||||
|
|
@ -126,17 +126,16 @@ abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAn
|
||||||
q.hasMessages should ===(false)
|
q.hasMessages should ===(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
def testEnqueueDequeue(
|
def testEnqueueDequeue(config: MailboxType,
|
||||||
config: MailboxType,
|
|
||||||
enqueueN: Int = 10000,
|
enqueueN: Int = 10000,
|
||||||
dequeueN: Int = 10000,
|
dequeueN: Int = 10000,
|
||||||
parallel: Boolean = true): Unit = within(10 seconds) {
|
parallel: Boolean = true): Unit = within(10 seconds) {
|
||||||
val q = factory(config)
|
val q = factory(config)
|
||||||
ensureInitialMailboxState(config, q)
|
ensureInitialMailboxState(config, q)
|
||||||
|
|
||||||
EventFilter.warning(
|
EventFilter
|
||||||
pattern = "received dead letter without sender",
|
.warning(pattern = "received dead letter without sender", occurrences = (enqueueN - dequeueN))
|
||||||
occurrences = (enqueueN - dequeueN)) intercept {
|
.intercept {
|
||||||
|
|
||||||
def createProducer(fromNum: Int, toNum: Int): Future[Vector[Envelope]] = spawn {
|
def createProducer(fromNum: Int, toNum: Int): Future[Vector[Envelope]] = spawn {
|
||||||
val messages = Vector() ++ (for (i <- fromNum to toNum) yield createMessageInvocation(i))
|
val messages = Vector() ++ (for (i <- fromNum to toNum) yield createMessageInvocation(i))
|
||||||
|
|
@ -149,7 +148,7 @@ abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAn
|
||||||
val ps = for (i <- (1 to enqueueN by step).toList) yield createProducer(i, Math.min(enqueueN, i + step - 1))
|
val ps = for (i <- (1 to enqueueN by step).toList) yield createProducer(i, Math.min(enqueueN, i + step - 1))
|
||||||
|
|
||||||
if (parallel == false)
|
if (parallel == false)
|
||||||
ps foreach { Await.ready(_, remainingOrDefault) }
|
ps.foreach { Await.ready(_, remainingOrDefault) }
|
||||||
|
|
||||||
ps
|
ps
|
||||||
}
|
}
|
||||||
|
|
@ -157,8 +156,9 @@ abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAn
|
||||||
def createConsumer: Future[Vector[Envelope]] = spawn {
|
def createConsumer: Future[Vector[Envelope]] = spawn {
|
||||||
var r = Vector[Envelope]()
|
var r = Vector[Envelope]()
|
||||||
|
|
||||||
while (producers.exists(_.isCompleted == false) || q.hasMessages)
|
while (producers.exists(_.isCompleted == false) || q.hasMessages) Option(q.dequeue).foreach { message =>
|
||||||
Option(q.dequeue) foreach { message => r = r :+ message }
|
r = r :+ message
|
||||||
|
}
|
||||||
|
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
@ -173,9 +173,9 @@ abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAn
|
||||||
//No message is allowed to be consumed by more than one consumer
|
//No message is allowed to be consumed by more than one consumer
|
||||||
cs.flatten.distinct.size should ===(dequeueN)
|
cs.flatten.distinct.size should ===(dequeueN)
|
||||||
//All consumed messages should have been produced
|
//All consumed messages should have been produced
|
||||||
(cs.flatten diff ps.flatten).size should ===(0)
|
cs.flatten.diff(ps.flatten).size should ===(0)
|
||||||
//The ones that were produced and not consumed
|
//The ones that were produced and not consumed
|
||||||
(ps.flatten diff cs.flatten).size should ===(enqueueN - dequeueN)
|
ps.flatten.diff(cs.flatten).size should ===(enqueueN - dequeueN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +193,8 @@ class PriorityMailboxSpec extends MailboxSpec {
|
||||||
lazy val name = "The priority mailbox implementation"
|
lazy val name = "The priority mailbox implementation"
|
||||||
def factory = {
|
def factory = {
|
||||||
case UnboundedMailbox() => new UnboundedPriorityMailbox(comparator).create(None, None)
|
case UnboundedMailbox() => new UnboundedPriorityMailbox(comparator).create(None, None)
|
||||||
case BoundedMailbox(capacity, pushTimeOut) => new BoundedPriorityMailbox(comparator, capacity, pushTimeOut).create(None, None)
|
case BoundedMailbox(capacity, pushTimeOut) =>
|
||||||
|
new BoundedPriorityMailbox(comparator, capacity, pushTimeOut).create(None, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,7 +203,8 @@ class StablePriorityMailboxSpec extends MailboxSpec {
|
||||||
lazy val name = "The stable priority mailbox implementation"
|
lazy val name = "The stable priority mailbox implementation"
|
||||||
def factory = {
|
def factory = {
|
||||||
case UnboundedMailbox() => new UnboundedStablePriorityMailbox(comparator).create(None, None)
|
case UnboundedMailbox() => new UnboundedStablePriorityMailbox(comparator).create(None, None)
|
||||||
case BoundedMailbox(capacity, pushTimeOut) => new BoundedStablePriorityMailbox(comparator, capacity, pushTimeOut).create(None, None)
|
case BoundedMailbox(capacity, pushTimeOut) =>
|
||||||
|
new BoundedStablePriorityMailbox(comparator, capacity, pushTimeOut).create(None, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,7 +212,8 @@ class ControlAwareMailboxSpec extends MailboxSpec {
|
||||||
lazy val name = "The control aware mailbox implementation"
|
lazy val name = "The control aware mailbox implementation"
|
||||||
def factory = {
|
def factory = {
|
||||||
case UnboundedMailbox() => new UnboundedControlAwareMailbox().create(None, None)
|
case UnboundedMailbox() => new UnboundedControlAwareMailbox().create(None, None)
|
||||||
case BoundedMailbox(capacity, pushTimeOut) => new BoundedControlAwareMailbox(capacity, pushTimeOut).create(None, None)
|
case BoundedMailbox(capacity, pushTimeOut) =>
|
||||||
|
new BoundedControlAwareMailbox(capacity, pushTimeOut).create(None, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,26 +274,26 @@ object SingleConsumerOnlyMailboxVerificationSpec {
|
||||||
}""")
|
}""")
|
||||||
}
|
}
|
||||||
|
|
||||||
class SingleConsumerOnlyMailboxVerificationSpec extends AkkaSpec(SingleConsumerOnlyMailboxVerificationSpec.mailboxConf) {
|
class SingleConsumerOnlyMailboxVerificationSpec
|
||||||
|
extends AkkaSpec(SingleConsumerOnlyMailboxVerificationSpec.mailboxConf) {
|
||||||
import SingleConsumerOnlyMailboxVerificationSpec.Ping
|
import SingleConsumerOnlyMailboxVerificationSpec.Ping
|
||||||
|
|
||||||
def pathologicalPingPong(dispatcherId: String): Unit = {
|
def pathologicalPingPong(dispatcherId: String): Unit = {
|
||||||
val total = 2000000
|
val total = 2000000
|
||||||
val runner = system.actorOf(Props(new Actor {
|
val runner = system.actorOf(Props(new Actor {
|
||||||
val a, b = context.watch(
|
val a, b = context.watch(context.actorOf(Props(new Actor {
|
||||||
context.actorOf(Props(new Actor {
|
|
||||||
var n = total / 2
|
var n = total / 2
|
||||||
def receive = {
|
def receive = {
|
||||||
case Ping =>
|
case Ping =>
|
||||||
n -= 1
|
n -= 1
|
||||||
sender() ! Ping
|
sender() ! Ping
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
context stop self
|
context.stop(self)
|
||||||
}
|
}
|
||||||
}).withDispatcher(dispatcherId)))
|
}).withDispatcher(dispatcherId)))
|
||||||
def receive = {
|
def receive = {
|
||||||
case Ping => a.tell(Ping, b)
|
case Ping => a.tell(Ping, b)
|
||||||
case Terminated(`a` | `b`) => if (context.children.isEmpty) context stop self
|
case Terminated(`a` | `b`) => if (context.children.isEmpty) context.stop(self)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
watch(runner)
|
watch(runner)
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ import language.postfixOps
|
||||||
|
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
|
|
||||||
import akka.actor.{ Props, ActorSystem, Actor }
|
import akka.actor.{ Actor, ActorSystem, Props }
|
||||||
import akka.testkit.{ DefaultTimeout, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, DefaultTimeout }
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
object PriorityDispatcherSpec {
|
object PriorityDispatcherSpec {
|
||||||
|
|
@ -22,12 +22,14 @@ object PriorityDispatcherSpec {
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Unbounded(settings: ActorSystem.Settings, config: Config) extends UnboundedPriorityMailbox(PriorityGenerator({
|
class Unbounded(settings: ActorSystem.Settings, config: Config)
|
||||||
|
extends UnboundedPriorityMailbox(PriorityGenerator({
|
||||||
case i: Int => i //Reverse order
|
case i: Int => i //Reverse order
|
||||||
case 'Result => Int.MaxValue
|
case 'Result => Int.MaxValue
|
||||||
}: Any => Int))
|
}: Any => Int))
|
||||||
|
|
||||||
class Bounded(settings: ActorSystem.Settings, config: Config) extends BoundedPriorityMailbox(PriorityGenerator({
|
class Bounded(settings: ActorSystem.Settings, config: Config)
|
||||||
|
extends BoundedPriorityMailbox(PriorityGenerator({
|
||||||
case i: Int => i //Reverse order
|
case i: Int => i //Reverse order
|
||||||
case 'Result => Int.MaxValue
|
case 'Result => Int.MaxValue
|
||||||
}: Any => Int), 1000, 10 seconds)
|
}: Any => Int), 1000, 10 seconds)
|
||||||
|
|
@ -60,7 +62,9 @@ class PriorityDispatcherSpec extends AkkaSpec(PriorityDispatcherSpec.config) wit
|
||||||
|
|
||||||
val acc = scala.collection.mutable.ListBuffer[Int]()
|
val acc = scala.collection.mutable.ListBuffer[Int]()
|
||||||
|
|
||||||
scala.util.Random.shuffle(msgs) foreach { m => self ! m }
|
scala.util.Random.shuffle(msgs).foreach { m =>
|
||||||
|
self ! m
|
||||||
|
}
|
||||||
|
|
||||||
self.tell('Result, testActor)
|
self.tell('Result, testActor)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ import language.postfixOps
|
||||||
|
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
|
|
||||||
import akka.actor.{ Props, ActorSystem, Actor }
|
import akka.actor.{ Actor, ActorSystem, Props }
|
||||||
import akka.testkit.{ DefaultTimeout, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, DefaultTimeout }
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
object StablePriorityDispatcherSpec {
|
object StablePriorityDispatcherSpec {
|
||||||
|
|
@ -22,13 +22,15 @@ object StablePriorityDispatcherSpec {
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Unbounded(settings: ActorSystem.Settings, config: Config) extends UnboundedStablePriorityMailbox(PriorityGenerator({
|
class Unbounded(settings: ActorSystem.Settings, config: Config)
|
||||||
|
extends UnboundedStablePriorityMailbox(PriorityGenerator({
|
||||||
case i: Int if i <= 100 => i // Small integers have high priority
|
case i: Int if i <= 100 => i // Small integers have high priority
|
||||||
case i: Int => 101 // Don't care for other integers
|
case i: Int => 101 // Don't care for other integers
|
||||||
case 'Result => Int.MaxValue
|
case 'Result => Int.MaxValue
|
||||||
}: Any => Int))
|
}: Any => Int))
|
||||||
|
|
||||||
class Bounded(settings: ActorSystem.Settings, config: Config) extends BoundedStablePriorityMailbox(PriorityGenerator({
|
class Bounded(settings: ActorSystem.Settings, config: Config)
|
||||||
|
extends BoundedStablePriorityMailbox(PriorityGenerator({
|
||||||
case i: Int if i <= 100 => i // Small integers have high priority
|
case i: Int if i <= 100 => i // Small integers have high priority
|
||||||
case i: Int => 101 // Don't care for other integers
|
case i: Int => 101 // Don't care for other integers
|
||||||
case 'Result => Int.MaxValue
|
case 'Result => Int.MaxValue
|
||||||
|
|
@ -64,7 +66,9 @@ class StablePriorityDispatcherSpec extends AkkaSpec(StablePriorityDispatcherSpec
|
||||||
|
|
||||||
val acc = scala.collection.mutable.ListBuffer[Int]()
|
val acc = scala.collection.mutable.ListBuffer[Int]()
|
||||||
|
|
||||||
shuffled foreach { m => self ! m }
|
shuffled.foreach { m =>
|
||||||
|
self ! m
|
||||||
|
}
|
||||||
|
|
||||||
self.tell('Result, testActor)
|
self.tell('Result, testActor)
|
||||||
|
|
||||||
|
|
@ -81,7 +85,7 @@ class StablePriorityDispatcherSpec extends AkkaSpec(StablePriorityDispatcherSpec
|
||||||
// Low messages should come out first, and in priority order. High messages follow - they are equal priority and
|
// Low messages should come out first, and in priority order. High messages follow - they are equal priority and
|
||||||
// should come out in the same order in which they were sent.
|
// should come out in the same order in which they were sent.
|
||||||
val lo = (1 to 100) toList
|
val lo = (1 to 100) toList
|
||||||
val hi = shuffled filter { _ > 100 }
|
val hi = shuffled.filter { _ > 100 }
|
||||||
expectMsgType[List[Int]] should ===(lo ++ hi)
|
expectMsgType[List[Int]] should ===(lo ++ hi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,21 @@ import org.scalatest.BeforeAndAfterEach
|
||||||
import akka.testkit._
|
import akka.testkit._
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
import akka.actor.{ Props, Actor, ActorRef, ActorSystem, PoisonPill }
|
import akka.actor.{ Actor, ActorRef, ActorSystem, PoisonPill, Props }
|
||||||
import akka.japi.{ Procedure }
|
import akka.japi.{ Procedure }
|
||||||
import com.typesafe.config.{ Config, ConfigFactory }
|
import com.typesafe.config.{ Config, ConfigFactory }
|
||||||
|
|
||||||
object EventBusSpec {
|
object EventBusSpec {
|
||||||
class TestActorWrapperActor(testActor: ActorRef) extends Actor {
|
class TestActorWrapperActor(testActor: ActorRef) extends Actor {
|
||||||
def receive = {
|
def receive = {
|
||||||
case x => testActor forward x
|
case x => testActor.forward(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class EventBusSpec(busName: String, conf: Config = ConfigFactory.empty()) extends AkkaSpec(conf) with BeforeAndAfterEach {
|
abstract class EventBusSpec(busName: String, conf: Config = ConfigFactory.empty())
|
||||||
|
extends AkkaSpec(conf)
|
||||||
|
with BeforeAndAfterEach {
|
||||||
type BusType <: EventBus
|
type BusType <: EventBus
|
||||||
|
|
||||||
def createNewEventBus(): BusType
|
def createNewEventBus(): BusType
|
||||||
|
|
@ -40,7 +42,8 @@ abstract class EventBusSpec(busName: String, conf: Config = ConfigFactory.empty(
|
||||||
busName must {
|
busName must {
|
||||||
def createNewSubscriber() = createSubscriber(testActor).asInstanceOf[bus.Subscriber]
|
def createNewSubscriber() = createSubscriber(testActor).asInstanceOf[bus.Subscriber]
|
||||||
def getClassifierFor(event: BusType#Event) = classifierFor(event).asInstanceOf[bus.Classifier]
|
def getClassifierFor(event: BusType#Event) = classifierFor(event).asInstanceOf[bus.Classifier]
|
||||||
def createNewEvents(numberOfEvents: Int): Iterable[bus.Event] = createEvents(numberOfEvents).asInstanceOf[Iterable[bus.Event]]
|
def createNewEvents(numberOfEvents: Int): Iterable[bus.Event] =
|
||||||
|
createEvents(numberOfEvents).asInstanceOf[Iterable[bus.Event]]
|
||||||
|
|
||||||
val events = createNewEvents(100)
|
val events = createNewEvents(100)
|
||||||
val event = events.head
|
val event = events.head
|
||||||
|
|
@ -74,13 +77,15 @@ abstract class EventBusSpec(busName: String, conf: Config = ConfigFactory.empty(
|
||||||
}
|
}
|
||||||
|
|
||||||
"allow to add multiple subscribers" in {
|
"allow to add multiple subscribers" in {
|
||||||
val subscribers = (1 to 10) map { _ => createNewSubscriber() }
|
val subscribers = (1 to 10).map { _ =>
|
||||||
|
createNewSubscriber()
|
||||||
|
}
|
||||||
val events = createEvents(10)
|
val events = createEvents(10)
|
||||||
val classifiers = events map getClassifierFor
|
val classifiers = events.map(getClassifierFor)
|
||||||
subscribers.zip(classifiers) forall { case (s, c) => bus.subscribe(s, c) } should ===(true)
|
subscribers.zip(classifiers).forall { case (s, c) => bus.subscribe(s, c) } should ===(true)
|
||||||
subscribers.zip(classifiers) forall { case (s, c) => bus.unsubscribe(s, c) } should ===(true)
|
subscribers.zip(classifiers).forall { case (s, c) => bus.unsubscribe(s, c) } should ===(true)
|
||||||
|
|
||||||
subscribers foreach (disposeSubscriber(system, _))
|
subscribers.foreach(disposeSubscriber(system, _))
|
||||||
}
|
}
|
||||||
|
|
||||||
"publishing events without any subscribers shouldn't be a problem" in {
|
"publishing events without any subscribers shouldn't be a problem" in {
|
||||||
|
|
@ -109,11 +114,17 @@ abstract class EventBusSpec(busName: String, conf: Config = ConfigFactory.empty(
|
||||||
|
|
||||||
"publish the given event to all intended subscribers" in {
|
"publish the given event to all intended subscribers" in {
|
||||||
val range = 0 until 10
|
val range = 0 until 10
|
||||||
val subscribers = range map (_ => createNewSubscriber())
|
val subscribers = range.map(_ => createNewSubscriber())
|
||||||
subscribers foreach { s => bus.subscribe(s, classifier) should ===(true) }
|
subscribers.foreach { s =>
|
||||||
|
bus.subscribe(s, classifier) should ===(true)
|
||||||
|
}
|
||||||
bus.publish(event)
|
bus.publish(event)
|
||||||
range foreach { _ => expectMsg(event) }
|
range.foreach { _ =>
|
||||||
subscribers foreach { s => bus.unsubscribe(s, classifier) should ===(true); disposeSubscriber(system, s) }
|
expectMsg(event)
|
||||||
|
}
|
||||||
|
subscribers.foreach { s =>
|
||||||
|
bus.unsubscribe(s, classifier) should ===(true); disposeSubscriber(system, s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"not publish the given event to any other subscribers than the intended ones" in {
|
"not publish the given event to any other subscribers than the intended ones" in {
|
||||||
|
|
@ -142,8 +153,10 @@ abstract class EventBusSpec(busName: String, conf: Config = ConfigFactory.empty(
|
||||||
}
|
}
|
||||||
|
|
||||||
object ActorEventBusSpec {
|
object ActorEventBusSpec {
|
||||||
class MyActorEventBus(protected val system: ActorSystem) extends ActorEventBus
|
class MyActorEventBus(protected val system: ActorSystem)
|
||||||
with ManagedActorClassification with ActorClassifier {
|
extends ActorEventBus
|
||||||
|
with ManagedActorClassification
|
||||||
|
with ActorClassifier {
|
||||||
|
|
||||||
type Event = Notification
|
type Event = Notification
|
||||||
|
|
||||||
|
|
@ -261,7 +274,7 @@ class ActorEventBusSpec(conf: Config) extends EventBusSpec("ActorEventBus", conf
|
||||||
private def expectUnsubscribedByUnsubscriber(p: TestProbe, a: ActorRef): Unit = {
|
private def expectUnsubscribedByUnsubscriber(p: TestProbe, a: ActorRef): Unit = {
|
||||||
val expectedMsg = s"actor $a has terminated, unsubscribing it from $bus"
|
val expectedMsg = s"actor $a has terminated, unsubscribing it from $bus"
|
||||||
p.fishForMessage(1 second, hint = expectedMsg) {
|
p.fishForMessage(1 second, hint = expectedMsg) {
|
||||||
case Logging.Debug(_, _, msg) if msg equals expectedMsg => true
|
case Logging.Debug(_, _, msg) if msg.equals(expectedMsg) => true
|
||||||
case other => false
|
case other => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -269,7 +282,7 @@ class ActorEventBusSpec(conf: Config) extends EventBusSpec("ActorEventBus", conf
|
||||||
private def expectUnregisterFromUnsubscriber(p: TestProbe, a: ActorRef): Unit = {
|
private def expectUnregisterFromUnsubscriber(p: TestProbe, a: ActorRef): Unit = {
|
||||||
val expectedMsg = s"unregistered watch of $a in $bus"
|
val expectedMsg = s"unregistered watch of $a in $bus"
|
||||||
p.fishForMessage(1 second, hint = expectedMsg) {
|
p.fishForMessage(1 second, hint = expectedMsg) {
|
||||||
case Logging.Debug(_, _, msg) if msg equals expectedMsg => true
|
case Logging.Debug(_, _, msg) if msg.equals(expectedMsg) => true
|
||||||
case other => false
|
case other => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -282,7 +295,7 @@ object ScanningEventBusSpec {
|
||||||
type Subscriber = Procedure[Int]
|
type Subscriber = Procedure[Int]
|
||||||
type Classifier = String
|
type Classifier = String
|
||||||
|
|
||||||
protected def compareClassifiers(a: Classifier, b: Classifier): Int = a compareTo b
|
protected def compareClassifiers(a: Classifier, b: Classifier): Int = a.compareTo(b)
|
||||||
protected def compareSubscribers(a: Subscriber, b: Subscriber): Int = akka.util.Helpers.compareIdentityHash(a, b)
|
protected def compareSubscribers(a: Subscriber, b: Subscriber): Int = akka.util.Helpers.compareIdentityHash(a, b)
|
||||||
|
|
||||||
protected def matches(classifier: Classifier, event: Event): Boolean = event.toString == classifier
|
protected def matches(classifier: Classifier, event: Event): Boolean = event.toString == classifier
|
||||||
|
|
@ -337,4 +350,3 @@ class LookupEventBusSpec extends EventBusSpec("LookupEventBus") {
|
||||||
|
|
||||||
def disposeSubscriber(system: ActorSystem, subscriber: BusType#Subscriber): Unit = ()
|
def disposeSubscriber(system: ActorSystem, subscriber: BusType#Subscriber): Unit = ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import language.postfixOps
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
import akka.actor._
|
import akka.actor._
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import akka.testkit.{ TestProbe, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, TestProbe }
|
||||||
|
|
||||||
object EventStreamSpec {
|
object EventStreamSpec {
|
||||||
|
|
||||||
|
|
@ -32,8 +32,7 @@ object EventStreamSpec {
|
||||||
""")
|
""")
|
||||||
|
|
||||||
val configUnhandledWithDebug =
|
val configUnhandledWithDebug =
|
||||||
ConfigFactory.parseString("akka.actor.debug.event-stream = on")
|
ConfigFactory.parseString("akka.actor.debug.event-stream = on").withFallback(configUnhandled)
|
||||||
.withFallback(configUnhandled)
|
|
||||||
|
|
||||||
final case class M(i: Int)
|
final case class M(i: Int)
|
||||||
|
|
||||||
|
|
@ -93,12 +92,14 @@ class EventStreamSpec extends AkkaSpec(EventStreamSpec.config) {
|
||||||
|
|
||||||
"not allow null as subscriber" in {
|
"not allow null as subscriber" in {
|
||||||
val bus = new EventStream(system, true)
|
val bus = new EventStream(system, true)
|
||||||
intercept[IllegalArgumentException] { bus.subscribe(null, classOf[M]) }.getMessage should ===("subscriber is null")
|
intercept[IllegalArgumentException] { bus.subscribe(null, classOf[M]) }.getMessage should ===(
|
||||||
|
"subscriber is null")
|
||||||
}
|
}
|
||||||
|
|
||||||
"not allow null as unsubscriber" in {
|
"not allow null as unsubscriber" in {
|
||||||
val bus = new EventStream(system, true)
|
val bus = new EventStream(system, true)
|
||||||
intercept[IllegalArgumentException] { bus.unsubscribe(null, classOf[M]) }.getMessage should ===("subscriber is null")
|
intercept[IllegalArgumentException] { bus.unsubscribe(null, classOf[M]) }.getMessage should ===(
|
||||||
|
"subscriber is null")
|
||||||
intercept[IllegalArgumentException] { bus.unsubscribe(null) }.getMessage should ===("subscriber is null")
|
intercept[IllegalArgumentException] { bus.unsubscribe(null) }.getMessage should ===("subscriber is null")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,7 +109,10 @@ class EventStreamSpec extends AkkaSpec(EventStreamSpec.config) {
|
||||||
sys.eventStream.subscribe(testActor, classOf[AnyRef])
|
sys.eventStream.subscribe(testActor, classOf[AnyRef])
|
||||||
val m = UnhandledMessage(42, sys.deadLetters, sys.deadLetters)
|
val m = UnhandledMessage(42, sys.deadLetters, sys.deadLetters)
|
||||||
sys.eventStream.publish(m)
|
sys.eventStream.publish(m)
|
||||||
expectMsgAllOf(m, Logging.Debug(sys.deadLetters.path.toString, sys.deadLetters.getClass, "unhandled message from " + sys.deadLetters + ": 42"))
|
expectMsgAllOf(m,
|
||||||
|
Logging.Debug(sys.deadLetters.path.toString,
|
||||||
|
sys.deadLetters.getClass,
|
||||||
|
"unhandled message from " + sys.deadLetters + ": 42"))
|
||||||
sys.eventStream.unsubscribe(testActor)
|
sys.eventStream.unsubscribe(testActor)
|
||||||
} finally {
|
} finally {
|
||||||
shutdown(sys)
|
shutdown(sys)
|
||||||
|
|
@ -289,7 +293,7 @@ class EventStreamSpec extends AkkaSpec(EventStreamSpec.config) {
|
||||||
val tm = new A
|
val tm = new A
|
||||||
|
|
||||||
val target = sys.actorOf(Props(new Actor {
|
val target = sys.actorOf(Props(new Actor {
|
||||||
def receive = { case in => a1.ref forward in }
|
def receive = { case in => a1.ref.forward(in) }
|
||||||
}), "to-be-killed")
|
}), "to-be-killed")
|
||||||
|
|
||||||
es.subscribe(a2.ref, classOf[Any])
|
es.subscribe(a2.ref, classOf[Any])
|
||||||
|
|
@ -317,7 +321,7 @@ class EventStreamSpec extends AkkaSpec(EventStreamSpec.config) {
|
||||||
val a1, a2 = TestProbe()
|
val a1, a2 = TestProbe()
|
||||||
|
|
||||||
val target = system.actorOf(Props(new Actor {
|
val target = system.actorOf(Props(new Actor {
|
||||||
def receive = { case in => a1.ref forward in }
|
def receive = { case in => a1.ref.forward(in) }
|
||||||
}), "to-be-killed")
|
}), "to-be-killed")
|
||||||
|
|
||||||
watch(target)
|
watch(target)
|
||||||
|
|
@ -408,15 +412,16 @@ class EventStreamSpec extends AkkaSpec(EventStreamSpec.config) {
|
||||||
|
|
||||||
private def verifyLevel(bus: LoggingBus, level: Logging.LogLevel): Unit = {
|
private def verifyLevel(bus: LoggingBus, level: Logging.LogLevel): Unit = {
|
||||||
import Logging._
|
import Logging._
|
||||||
val allmsg = Seq(Debug("", null, "debug"), Info("", null, "info"), Warning("", null, "warning"), Error("", null, "error"))
|
val allmsg =
|
||||||
val msg = allmsg filter (_.level <= level)
|
Seq(Debug("", null, "debug"), Info("", null, "info"), Warning("", null, "warning"), Error("", null, "error"))
|
||||||
allmsg foreach bus.publish
|
val msg = allmsg.filter(_.level <= level)
|
||||||
msg foreach (expectMsg(_))
|
allmsg.foreach(bus.publish)
|
||||||
|
msg.foreach(expectMsg(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
private def fishForDebugMessage(a: TestProbe, messagePrefix: String, max: Duration = 3 seconds): Unit = {
|
private def fishForDebugMessage(a: TestProbe, messagePrefix: String, max: Duration = 3 seconds): Unit = {
|
||||||
a.fishForMessage(max, hint = "expected debug message prefix: " + messagePrefix) {
|
a.fishForMessage(max, hint = "expected debug message prefix: " + messagePrefix) {
|
||||||
case Logging.Debug(_, _, msg: String) if msg startsWith messagePrefix => true
|
case Logging.Debug(_, _, msg: String) if msg.startsWith(messagePrefix) => true
|
||||||
case other => false
|
case other => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,8 @@ object LoggerSpec {
|
||||||
}
|
}
|
||||||
""").withFallback(AkkaSpec.testConf)
|
""").withFallback(AkkaSpec.testConf)
|
||||||
|
|
||||||
val multipleConfig = ConfigFactory.parseString("""
|
val multipleConfig =
|
||||||
|
ConfigFactory.parseString("""
|
||||||
akka {
|
akka {
|
||||||
stdout-loglevel = "OFF"
|
stdout-loglevel = "OFF"
|
||||||
loglevel = "WARNING"
|
loglevel = "WARNING"
|
||||||
|
|
@ -97,10 +98,10 @@ object LoggerSpec {
|
||||||
ref ! ("OK")
|
ref ! ("OK")
|
||||||
case event: LogEvent if !event.mdc.isEmpty =>
|
case event: LogEvent if !event.mdc.isEmpty =>
|
||||||
print(event)
|
print(event)
|
||||||
target foreach { _ ! event }
|
target.foreach { _ ! event }
|
||||||
case event: LogEvent =>
|
case event: LogEvent =>
|
||||||
print(event)
|
print(event)
|
||||||
target foreach { _ ! event.message }
|
target.foreach { _ ! event.message }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,7 +249,8 @@ class LoggerSpec extends WordSpec with Matchers {
|
||||||
|
|
||||||
ref ! "Current Message in MDC"
|
ref ! "Current Message in MDC"
|
||||||
probe.expectMsgPF(max = 3.seconds) {
|
probe.expectMsgPF(max = 3.seconds) {
|
||||||
case w @ Warning(_, _, "Current Message in MDC") if w.mdc.size == 3 &&
|
case w @ Warning(_, _, "Current Message in MDC")
|
||||||
|
if w.mdc.size == 3 &&
|
||||||
w.mdc("requestId") == 3 &&
|
w.mdc("requestId") == 3 &&
|
||||||
w.mdc("currentMsg") == "Current Message in MDC" &&
|
w.mdc("currentMsg") == "Current Message in MDC" &&
|
||||||
w.mdc("currentMsgLength") == 22 =>
|
w.mdc("currentMsgLength") == 22 =>
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,14 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
akka.loglevel=DEBUG # test verifies debug
|
akka.loglevel=DEBUG # test verifies debug
|
||||||
akka.actor.serialize-messages = off # debug noise from serialization
|
akka.actor.serialize-messages = off # debug noise from serialization
|
||||||
""").withFallback(AkkaSpec.testConf)
|
""").withFallback(AkkaSpec.testConf)
|
||||||
val appLogging = ActorSystem("logging", ConfigFactory.parseMap(Map("akka.actor.debug.receive" -> true).asJava).withFallback(config))
|
val appLogging =
|
||||||
val appAuto = ActorSystem("autoreceive", ConfigFactory.parseMap(Map("akka.actor.debug.autoreceive" -> true).asJava).withFallback(config))
|
ActorSystem("logging", ConfigFactory.parseMap(Map("akka.actor.debug.receive" -> true).asJava).withFallback(config))
|
||||||
val appLifecycle = ActorSystem("lifecycle", ConfigFactory.parseMap(Map("akka.actor.debug.lifecycle" -> true).asJava).withFallback(config))
|
val appAuto = ActorSystem(
|
||||||
|
"autoreceive",
|
||||||
|
ConfigFactory.parseMap(Map("akka.actor.debug.autoreceive" -> true).asJava).withFallback(config))
|
||||||
|
val appLifecycle = ActorSystem(
|
||||||
|
"lifecycle",
|
||||||
|
ConfigFactory.parseMap(Map("akka.actor.debug.lifecycle" -> true).asJava).withFallback(config))
|
||||||
|
|
||||||
val filter = TestEvent.Mute(EventFilter.custom {
|
val filter = TestEvent.Mute(EventFilter.custom {
|
||||||
case _: Logging.Debug => true
|
case _: Logging.Debug => true
|
||||||
|
|
@ -62,12 +67,15 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
system.eventStream.subscribe(testActor, classOf[Logging.Debug])
|
system.eventStream.subscribe(testActor, classOf[Logging.Debug])
|
||||||
system.eventStream.subscribe(testActor, classOf[UnhandledMessage])
|
system.eventStream.subscribe(testActor, classOf[UnhandledMessage])
|
||||||
val a = system.actorOf(Props(new Actor {
|
val a = system.actorOf(Props(new Actor {
|
||||||
def receive = new LoggingReceive(Some("funky"), {
|
def receive =
|
||||||
|
new LoggingReceive(Some("funky"), {
|
||||||
case null =>
|
case null =>
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
a ! "hallo"
|
a ! "hallo"
|
||||||
expectMsg(1 second, Logging.Debug("funky", classOf[DummyClassForStringSources],
|
expectMsg(1 second,
|
||||||
|
Logging.Debug("funky",
|
||||||
|
classOf[DummyClassForStringSources],
|
||||||
"received unhandled message hallo from " + system.deadLetters))
|
"received unhandled message hallo from " + system.deadLetters))
|
||||||
expectMsgType[UnhandledMessage](1 second)
|
expectMsgType[UnhandledMessage](1 second)
|
||||||
}
|
}
|
||||||
|
|
@ -85,15 +93,17 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
|
|
||||||
val actor = TestActorRef(new Actor {
|
val actor = TestActorRef(new Actor {
|
||||||
def switch: Actor.Receive = { case "becomenull" => context.become(r, false) }
|
def switch: Actor.Receive = { case "becomenull" => context.become(r, false) }
|
||||||
def receive = switch orElse LoggingReceive {
|
def receive =
|
||||||
|
switch.orElse(LoggingReceive {
|
||||||
case x => sender() ! "x"
|
case x => sender() ! "x"
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
val name = actor.path.toString
|
val name = actor.path.toString
|
||||||
actor ! "buh"
|
actor ! "buh"
|
||||||
expectMsg(Logging.Debug(actor.path.toString, actor.underlyingActor.getClass,
|
expectMsg(
|
||||||
"received handled message buh from " + self))
|
Logging
|
||||||
|
.Debug(actor.path.toString, actor.underlyingActor.getClass, "received handled message buh from " + self))
|
||||||
expectMsg("x")
|
expectMsg("x")
|
||||||
|
|
||||||
actor ! "becomenull"
|
actor ! "becomenull"
|
||||||
|
|
@ -109,13 +119,15 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
new TestKit(appLogging) with ImplicitSender {
|
new TestKit(appLogging) with ImplicitSender {
|
||||||
system.eventStream.subscribe(testActor, classOf[Logging.Debug])
|
system.eventStream.subscribe(testActor, classOf[Logging.Debug])
|
||||||
val actor = TestActorRef(new Actor {
|
val actor = TestActorRef(new Actor {
|
||||||
def receive = LoggingReceive(LoggingReceive {
|
def receive =
|
||||||
|
LoggingReceive(LoggingReceive {
|
||||||
case _ => sender() ! "x"
|
case _ => sender() ! "x"
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
actor ! "buh"
|
actor ! "buh"
|
||||||
expectMsg(Logging.Debug(actor.path.toString, actor.underlyingActor.getClass,
|
expectMsg(
|
||||||
"received handled message buh from " + self))
|
Logging
|
||||||
|
.Debug(actor.path.toString, actor.underlyingActor.getClass, "received handled message buh from " + self))
|
||||||
expectMsg("x")
|
expectMsg("x")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -146,8 +158,9 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
actor ! "buh"
|
actor ! "buh"
|
||||||
expectMsg(Logging.Info(actor.path.toString, actor.underlyingActor.getClass,
|
expectMsg(
|
||||||
"received handled message buh from " + self))
|
Logging
|
||||||
|
.Info(actor.path.toString, actor.underlyingActor.getClass, "received handled message buh from " + self))
|
||||||
expectMsg("x")
|
expectMsg("x")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +180,9 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
val name = actor.path.toString
|
val name = actor.path.toString
|
||||||
actor ! PoisonPill
|
actor ! PoisonPill
|
||||||
fishForMessage(hint = "received AutoReceiveMessage Envelope(PoisonPill") {
|
fishForMessage(hint = "received AutoReceiveMessage Envelope(PoisonPill") {
|
||||||
case Logging.Debug(`name`, _, msg: String) if msg startsWith "received AutoReceiveMessage Envelope(PoisonPill" => true
|
case Logging.Debug(`name`, _, msg: String)
|
||||||
|
if msg.startsWith("received AutoReceiveMessage Envelope(PoisonPill") =>
|
||||||
|
true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
awaitCond(actor.isTerminated)
|
awaitCond(actor.isTerminated)
|
||||||
|
|
@ -184,14 +199,14 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
val sname = supervisor.path.toString
|
val sname = supervisor.path.toString
|
||||||
|
|
||||||
fishForMessage(hint = "now supervising") {
|
fishForMessage(hint = "now supervising") {
|
||||||
case Logging.Debug(`lname`, _, msg: String) if msg startsWith "now supervising" => true
|
case Logging.Debug(`lname`, _, msg: String) if msg.startsWith("now supervising") => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
TestActorRef[TestLogActor](Props[TestLogActor], supervisor, "none")
|
TestActorRef[TestLogActor](Props[TestLogActor], supervisor, "none")
|
||||||
|
|
||||||
fishForMessage(hint = "now supervising") {
|
fishForMessage(hint = "now supervising") {
|
||||||
case Logging.Debug(`sname`, _, msg: String) if msg startsWith "now supervising" => true
|
case Logging.Debug(`sname`, _, msg: String) if msg.startsWith("now supervising") => true
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -207,13 +222,13 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
val actor = TestActorRef[TestLogActor](Props[TestLogActor], supervisor, "none")
|
val actor = TestActorRef[TestLogActor](Props[TestLogActor], supervisor, "none")
|
||||||
val aname = actor.path.toString
|
val aname = actor.path.toString
|
||||||
|
|
||||||
supervisor watch actor
|
supervisor.watch(actor)
|
||||||
fishForMessage(hint = "now watched by") {
|
fishForMessage(hint = "now watched by") {
|
||||||
case Logging.Debug(`aname`, `sclass`, msg: String) if msg.startsWith("now watched by") => true
|
case Logging.Debug(`aname`, `sclass`, msg: String) if msg.startsWith("now watched by") => true
|
||||||
case m => false
|
case m => false
|
||||||
}
|
}
|
||||||
|
|
||||||
supervisor unwatch actor
|
supervisor.unwatch(actor)
|
||||||
fishForMessage(hint = "no longer watched by") {
|
fishForMessage(hint = "no longer watched by") {
|
||||||
case Logging.Debug(`aname`, `sclass`, msg: String) if msg.startsWith("no longer watched by") => true
|
case Logging.Debug(`aname`, `sclass`, msg: String) if msg.startsWith("no longer watched by") => true
|
||||||
case _ => false
|
case _ => false
|
||||||
|
|
@ -232,8 +247,8 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
val sclass = classOf[TestLogActor]
|
val sclass = classOf[TestLogActor]
|
||||||
|
|
||||||
expectMsgAllPF(messages = 2) {
|
expectMsgAllPF(messages = 2) {
|
||||||
case Logging.Debug(`sname`, `sclass`, msg: String) if msg startsWith "started" => 0
|
case Logging.Debug(`sname`, `sclass`, msg: String) if msg.startsWith("started") => 0
|
||||||
case Logging.Debug(_, _, msg: String) if msg startsWith "now supervising" => 1
|
case Logging.Debug(_, _, msg: String) if msg.startsWith("now supervising") => 1
|
||||||
}
|
}
|
||||||
|
|
||||||
val actor = TestActorRef[TestLogActor](Props[TestLogActor], supervisor, "none")
|
val actor = TestActorRef[TestLogActor](Props[TestLogActor], supervisor, "none")
|
||||||
|
|
@ -241,11 +256,13 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
val aclass = classOf[TestLogActor]
|
val aclass = classOf[TestLogActor]
|
||||||
|
|
||||||
expectMsgAllPF(messages = 2) {
|
expectMsgAllPF(messages = 2) {
|
||||||
case Logging.Debug(`aname`, `aclass`, msg: String) if msg.startsWith("started (" + classOf[TestLogActor].getName) => 0
|
case Logging.Debug(`aname`, `aclass`, msg: String)
|
||||||
|
if msg.startsWith("started (" + classOf[TestLogActor].getName) =>
|
||||||
|
0
|
||||||
case Logging.Debug(`sname`, `sclass`, msg: String) if msg == s"now supervising TestActor[$aname]" => 1
|
case Logging.Debug(`sname`, `sclass`, msg: String) if msg == s"now supervising TestActor[$aname]" => 1
|
||||||
}
|
}
|
||||||
|
|
||||||
EventFilter[ActorKilledException](occurrences = 1) intercept {
|
EventFilter[ActorKilledException](occurrences = 1).intercept {
|
||||||
actor ! Kill
|
actor ! Kill
|
||||||
expectMsgAllPF(messages = 3) {
|
expectMsgAllPF(messages = 3) {
|
||||||
case Logging.Error(_: ActorKilledException, `aname`, _, "Kill") => 0
|
case Logging.Error(_: ActorKilledException, `aname`, _, "Kill") => 0
|
||||||
|
|
@ -255,8 +272,7 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
}
|
}
|
||||||
|
|
||||||
system.stop(supervisor)
|
system.stop(supervisor)
|
||||||
expectMsgAllOf(
|
expectMsgAllOf(Logging.Debug(aname, aclass, "stopped"),
|
||||||
Logging.Debug(aname, aclass, "stopped"),
|
|
||||||
Logging.Debug(sname, sclass, "stopping"),
|
Logging.Debug(sname, sclass, "stopping"),
|
||||||
Logging.Debug(sname, sclass, "stopped"))
|
Logging.Debug(sname, sclass, "stopped"))
|
||||||
}
|
}
|
||||||
|
|
@ -269,7 +285,8 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterAll {
|
||||||
else if (gotMatching.size == messages) gotMatching
|
else if (gotMatching.size == messages) gotMatching
|
||||||
else {
|
else {
|
||||||
val msg = receiveOne(remainingOrDefault)
|
val msg = receiveOne(remainingOrDefault)
|
||||||
assert(msg ne null, s"timeout ($max) during expectMsgAllPF, got matching " +
|
assert(msg ne null,
|
||||||
|
s"timeout ($max) during expectMsgAllPF, got matching " +
|
||||||
s"[${gotMatching.mkString(", ")}], got unknown: [${unknown.mkString(", ")}]")
|
s"[${gotMatching.mkString(", ")}], got unknown: [${unknown.mkString(", ")}]")
|
||||||
if (matchers.isDefinedAt(msg)) receiveNMatching(gotMatching + matchers(msg), Vector.empty)
|
if (matchers.isDefinedAt(msg)) receiveNMatching(gotMatching + matchers(msg), Vector.empty)
|
||||||
else receiveNMatching(gotMatching, unknown :+ msg) // unknown message, just ignore
|
else receiveNMatching(gotMatching, unknown :+ msg) // unknown message, just ignore
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ import akka.testkit._
|
||||||
|
|
||||||
class MarkerLoggingSpec extends AkkaSpec with ImplicitSender {
|
class MarkerLoggingSpec extends AkkaSpec with ImplicitSender {
|
||||||
"A MarkerLoggerAdapter" should {
|
"A MarkerLoggerAdapter" should {
|
||||||
val markerLogging = new MarkerLoggingAdapter(system.eventStream, getClass.getName, this.getClass, new DefaultLoggingFilter(() => Logging.InfoLevel))
|
val markerLogging = new MarkerLoggingAdapter(system.eventStream,
|
||||||
|
getClass.getName,
|
||||||
|
this.getClass,
|
||||||
|
new DefaultLoggingFilter(() => Logging.InfoLevel))
|
||||||
|
|
||||||
"add markers to logging" in {
|
"add markers to logging" in {
|
||||||
system.eventStream.subscribe(self, classOf[Info])
|
system.eventStream.subscribe(self, classOf[Info])
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
package akka.io
|
package akka.io
|
||||||
|
|
||||||
import akka.testkit.{ TestProbe, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, TestProbe }
|
||||||
import akka.testkit.SocketUtil.temporaryServerAddresses
|
import akka.testkit.SocketUtil.temporaryServerAddresses
|
||||||
import Tcp._
|
import Tcp._
|
||||||
|
|
||||||
|
|
@ -12,12 +12,12 @@ class CapacityLimitSpec extends AkkaSpec("""
|
||||||
akka.loglevel = ERROR
|
akka.loglevel = ERROR
|
||||||
akka.io.tcp.max-channels = 4
|
akka.io.tcp.max-channels = 4
|
||||||
akka.actor.serialize-creators = on
|
akka.actor.serialize-creators = on
|
||||||
""")
|
""") with TcpIntegrationSpecSupport {
|
||||||
with TcpIntegrationSpecSupport {
|
|
||||||
|
|
||||||
"The TCP transport implementation" should {
|
"The TCP transport implementation" should {
|
||||||
|
|
||||||
"reply with CommandFailed to a Bind or Connect command if max-channels capacity has been reached" in new TestSetup(runClientInExtraSystem = false) {
|
"reply with CommandFailed to a Bind or Connect command if max-channels capacity has been reached" in new TestSetup(
|
||||||
|
runClientInExtraSystem = false) {
|
||||||
establishNewClientConnection()
|
establishNewClientConnection()
|
||||||
|
|
||||||
// we now have three channels registered: a listener, a server connection and a client connection
|
// we now have three channels registered: a listener, a server connection and a client connection
|
||||||
|
|
@ -31,11 +31,11 @@ class CapacityLimitSpec extends AkkaSpec("""
|
||||||
|
|
||||||
val bindToFail = Bind(bindHandler.ref, addresses(1))
|
val bindToFail = Bind(bindHandler.ref, addresses(1))
|
||||||
commander.send(IO(Tcp), bindToFail)
|
commander.send(IO(Tcp), bindToFail)
|
||||||
commander.expectMsgType[CommandFailed].cmd should be theSameInstanceAs (bindToFail)
|
(commander.expectMsgType[CommandFailed].cmd should be).theSameInstanceAs(bindToFail)
|
||||||
|
|
||||||
val connectToFail = Connect(endpoint)
|
val connectToFail = Connect(endpoint)
|
||||||
commander.send(IO(Tcp), connectToFail)
|
commander.send(IO(Tcp), connectToFail)
|
||||||
commander.expectMsgType[CommandFailed].cmd should be theSameInstanceAs (connectToFail)
|
(commander.expectMsgType[CommandFailed].cmd should be).theSameInstanceAs(connectToFail)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,11 +88,10 @@ class InetAddressDnsResolverSpec extends AkkaSpec("""
|
||||||
private def secondsToMillis(seconds: Int) = TimeUnit.SECONDS.toMillis(seconds)
|
private def secondsToMillis(seconds: Int) = TimeUnit.SECONDS.toMillis(seconds)
|
||||||
|
|
||||||
private def dnsResolver = {
|
private def dnsResolver = {
|
||||||
val actorRef = TestActorRef[InetAddressDnsResolver](Props(
|
val actorRef = TestActorRef[InetAddressDnsResolver](
|
||||||
classOf[InetAddressDnsResolver],
|
Props(classOf[InetAddressDnsResolver],
|
||||||
new SimpleDnsCache(),
|
new SimpleDnsCache(),
|
||||||
system.settings.config.getConfig("akka.io.dns.inet-address")
|
system.settings.config.getConfig("akka.io.dns.inet-address")))
|
||||||
))
|
|
||||||
actorRef.underlyingActor
|
actorRef.underlyingActor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,8 +116,7 @@ class InetAddressDnsResolverSpec extends AkkaSpec("""
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
class InetAddressDnsResolverConfigSpec extends AkkaSpec(
|
class InetAddressDnsResolverConfigSpec extends AkkaSpec("""
|
||||||
"""
|
|
||||||
akka.io.dns.inet-address.positive-ttl = forever
|
akka.io.dns.inet-address.positive-ttl = forever
|
||||||
akka.io.dns.inet-address.negative-ttl = never
|
akka.io.dns.inet-address.negative-ttl = never
|
||||||
akka.actor.serialize-creators = on
|
akka.actor.serialize-creators = on
|
||||||
|
|
@ -137,11 +135,10 @@ class InetAddressDnsResolverConfigSpec extends AkkaSpec(
|
||||||
}
|
}
|
||||||
|
|
||||||
private def dnsResolver = {
|
private def dnsResolver = {
|
||||||
val actorRef = TestActorRef[InetAddressDnsResolver](Props(
|
val actorRef = TestActorRef[InetAddressDnsResolver](
|
||||||
classOf[InetAddressDnsResolver],
|
Props(classOf[InetAddressDnsResolver],
|
||||||
new SimpleDnsCache(),
|
new SimpleDnsCache(),
|
||||||
system.settings.config.getConfig("akka.io.dns.inet-address")
|
system.settings.config.getConfig("akka.io.dns.inet-address")))
|
||||||
))
|
|
||||||
actorRef.underlyingActor
|
actorRef.underlyingActor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
val connectionActor = createConnectionActor(options = Vector(SO.KeepAlive(false)))
|
val connectionActor = createConnectionActor(options = Vector(SO.KeepAlive(false)))
|
||||||
val clientChannel = connectionActor.underlyingActor.channel
|
val clientChannel = connectionActor.underlyingActor.channel
|
||||||
clientChannel.socket.getKeepAlive should ===(true) // only set after connection is established
|
clientChannel.socket.getKeepAlive should ===(true) // only set after connection is established
|
||||||
EventFilter.warning(pattern = "registration timeout", occurrences = 1) intercept {
|
EventFilter.warning(pattern = "registration timeout", occurrences = 1).intercept {
|
||||||
selector.send(connectionActor, ChannelConnectable)
|
selector.send(connectionActor, ChannelConnectable)
|
||||||
clientChannel.socket.getKeepAlive should ===(false)
|
clientChannel.socket.getKeepAlive should ===(false)
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +156,8 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
interestCallReceiver.expectMsg(OP_CONNECT)
|
interestCallReceiver.expectMsg(OP_CONNECT)
|
||||||
|
|
||||||
selector.send(connectionActor, ChannelConnectable)
|
selector.send(connectionActor, ChannelConnectable)
|
||||||
userHandler.expectMsg(Connected(serverAddress, clientSideChannel.socket.getLocalSocketAddress.asInstanceOf[InetSocketAddress]))
|
userHandler.expectMsg(
|
||||||
|
Connected(serverAddress, clientSideChannel.socket.getLocalSocketAddress.asInstanceOf[InetSocketAddress]))
|
||||||
|
|
||||||
userHandler.send(connectionActor, Register(userHandler.ref))
|
userHandler.send(connectionActor, Register(userHandler.ref))
|
||||||
interestCallReceiver.expectMsg(OP_READ)
|
interestCallReceiver.expectMsg(OP_READ)
|
||||||
|
|
@ -304,7 +305,8 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
new EstablishedConnectionTest() {
|
new EstablishedConnectionTest() {
|
||||||
override lazy val connectionActor = createConnectionActor(options = List(Inet.SO.ReceiveBufferSize(1000000)))
|
override lazy val connectionActor = createConnectionActor(options = List(Inet.SO.ReceiveBufferSize(1000000)))
|
||||||
run {
|
run {
|
||||||
info("Currently ignored as SO_SNDBUF is usually a lower bound on the send buffer so the test fails as no real " +
|
info(
|
||||||
|
"Currently ignored as SO_SNDBUF is usually a lower bound on the send buffer so the test fails as no real " +
|
||||||
"backpressure present.")
|
"backpressure present.")
|
||||||
pending
|
pending
|
||||||
ignoreIfWindows()
|
ignoreIfWindows()
|
||||||
|
|
@ -376,8 +378,7 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
"respect pull mode" in new EstablishedConnectionTest(pullMode = true) {
|
"respect pull mode" in new EstablishedConnectionTest(pullMode = true) {
|
||||||
// override config to decrease default buffer size
|
// override config to decrease default buffer size
|
||||||
def config =
|
def config =
|
||||||
ConfigFactory.parseString("akka.io.tcp.direct-buffer-size = 1k")
|
ConfigFactory.parseString("akka.io.tcp.direct-buffer-size = 1k").withFallback(AkkaSpec.testConf)
|
||||||
.withFallback(AkkaSpec.testConf)
|
|
||||||
override implicit lazy val system: ActorSystem = ActorSystem("respectPullModeTest", config)
|
override implicit lazy val system: ActorSystem = ActorSystem("respectPullModeTest", config)
|
||||||
|
|
||||||
try run {
|
try run {
|
||||||
|
|
@ -415,8 +416,7 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
selector.send(connectionActor, ChannelReadable)
|
selector.send(connectionActor, ChannelReadable)
|
||||||
|
|
||||||
connectionHandler.expectMsgType[Received].data.decodeString("ASCII") should ===(vs)
|
connectionHandler.expectMsgType[Received].data.decodeString("ASCII") should ===(vs)
|
||||||
}
|
} finally shutdown(system)
|
||||||
finally shutdown(system)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"close the connection and reply with `Closed` upon reception of a `Close` command" in
|
"close the connection and reply with `Closed` upon reception of a `Close` command" in
|
||||||
|
|
@ -661,7 +661,8 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
|
|
||||||
"report failed connection attempt when timing out" in
|
"report failed connection attempt when timing out" in
|
||||||
new UnacceptedConnectionTest() {
|
new UnacceptedConnectionTest() {
|
||||||
override lazy val connectionActor = createConnectionActor(serverAddress = UnboundAddress, timeout = Option(100.millis))
|
override lazy val connectionActor =
|
||||||
|
createConnectionActor(serverAddress = UnboundAddress, timeout = Option(100.millis))
|
||||||
run {
|
run {
|
||||||
connectionActor.toString should not be ("")
|
connectionActor.toString should not be ("")
|
||||||
userHandler.expectMsg(CommandFailed(Connect(UnboundAddress, timeout = Option(100.millis))))
|
userHandler.expectMsg(CommandFailed(Connect(UnboundAddress, timeout = Option(100.millis))))
|
||||||
|
|
@ -675,7 +676,8 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
localServerChannel.accept()
|
localServerChannel.accept()
|
||||||
|
|
||||||
selector.send(connectionActor, ChannelConnectable)
|
selector.send(connectionActor, ChannelConnectable)
|
||||||
userHandler.expectMsg(Connected(serverAddress, clientSideChannel.socket.getLocalSocketAddress.asInstanceOf[InetSocketAddress]))
|
userHandler.expectMsg(
|
||||||
|
Connected(serverAddress, clientSideChannel.socket.getLocalSocketAddress.asInstanceOf[InetSocketAddress]))
|
||||||
|
|
||||||
watch(connectionActor)
|
watch(connectionActor)
|
||||||
expectTerminated(connectionActor)
|
expectTerminated(connectionActor)
|
||||||
|
|
@ -684,7 +686,7 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
|
|
||||||
"close the connection when user handler dies while connecting" in new UnacceptedConnectionTest {
|
"close the connection when user handler dies while connecting" in new UnacceptedConnectionTest {
|
||||||
run {
|
run {
|
||||||
EventFilter[DeathPactException](occurrences = 1) intercept {
|
EventFilter[DeathPactException](occurrences = 1).intercept {
|
||||||
userHandler.ref ! PoisonPill
|
userHandler.ref ! PoisonPill
|
||||||
|
|
||||||
watch(connectionActor)
|
watch(connectionActor)
|
||||||
|
|
@ -697,7 +699,7 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
run {
|
run {
|
||||||
watch(connectionHandler.ref)
|
watch(connectionHandler.ref)
|
||||||
watch(connectionActor)
|
watch(connectionActor)
|
||||||
EventFilter[DeathPactException](occurrences = 1) intercept {
|
EventFilter[DeathPactException](occurrences = 1).intercept {
|
||||||
system.stop(connectionHandler.ref)
|
system.stop(connectionHandler.ref)
|
||||||
val deaths = Set(expectMsgType[Terminated].actor, expectMsgType[Terminated].actor)
|
val deaths = Set(expectMsgType[Terminated].actor, expectMsgType[Terminated].actor)
|
||||||
deaths should ===(Set(connectionHandler.ref, connectionActor))
|
deaths should ===(Set(connectionHandler.ref, connectionActor))
|
||||||
|
|
@ -879,6 +881,7 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class LocalServerTest extends ChannelRegistry {
|
abstract class LocalServerTest extends ChannelRegistry {
|
||||||
|
|
||||||
/** Allows overriding the system used */
|
/** Allows overriding the system used */
|
||||||
implicit def system: ActorSystem = thisSpecs.system
|
implicit def system: ActorSystem = thisSpecs.system
|
||||||
|
|
||||||
|
|
@ -909,8 +912,7 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
|
|
||||||
def setServerSocketOptions() = ()
|
def setServerSocketOptions() = ()
|
||||||
|
|
||||||
def createConnectionActor(
|
def createConnectionActor(serverAddress: InetSocketAddress = serverAddress,
|
||||||
serverAddress: InetSocketAddress = serverAddress,
|
|
||||||
options: immutable.Seq[SocketOption] = Nil,
|
options: immutable.Seq[SocketOption] = Nil,
|
||||||
timeout: Option[FiniteDuration] = None,
|
timeout: Option[FiniteDuration] = None,
|
||||||
pullMode: Boolean = false): TestActorRef[TcpOutgoingConnection] = {
|
pullMode: Boolean = false): TestActorRef[TcpOutgoingConnection] = {
|
||||||
|
|
@ -928,13 +930,14 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
|
|
||||||
protected def onCancelAndClose(andThen: () => Unit): Unit = andThen()
|
protected def onCancelAndClose(andThen: () => Unit): Unit = andThen()
|
||||||
|
|
||||||
def createConnectionActorWithoutRegistration(
|
def createConnectionActorWithoutRegistration(serverAddress: InetSocketAddress = serverAddress,
|
||||||
serverAddress: InetSocketAddress = serverAddress,
|
|
||||||
options: immutable.Seq[SocketOption] = Nil,
|
options: immutable.Seq[SocketOption] = Nil,
|
||||||
timeout: Option[FiniteDuration] = None,
|
timeout: Option[FiniteDuration] = None,
|
||||||
pullMode: Boolean = false): TestActorRef[TcpOutgoingConnection] =
|
pullMode: Boolean = false): TestActorRef[TcpOutgoingConnection] =
|
||||||
TestActorRef(
|
TestActorRef(
|
||||||
new TcpOutgoingConnection(Tcp(system), this, userHandler.ref,
|
new TcpOutgoingConnection(Tcp(system),
|
||||||
|
this,
|
||||||
|
userHandler.ref,
|
||||||
Connect(serverAddress, options = options, timeout = timeout, pullMode = pullMode)) {
|
Connect(serverAddress, options = options, timeout = timeout, pullMode = pullMode)) {
|
||||||
override def postRestart(reason: Throwable): Unit = context.stop(self) // ensure we never restart
|
override def postRestart(reason: Throwable): Unit = context.stop(self) // ensure we never restart
|
||||||
})
|
})
|
||||||
|
|
@ -957,8 +960,7 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class EstablishedConnectionTest(
|
abstract class EstablishedConnectionTest(keepOpenOnPeerClosed: Boolean = false,
|
||||||
keepOpenOnPeerClosed: Boolean = false,
|
|
||||||
useResumeWriting: Boolean = true,
|
useResumeWriting: Boolean = true,
|
||||||
pullMode: Boolean = false)
|
pullMode: Boolean = false)
|
||||||
extends UnacceptedConnectionTest(pullMode) {
|
extends UnacceptedConnectionTest(pullMode) {
|
||||||
|
|
@ -991,7 +993,8 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
|
|
||||||
interestCallReceiver.expectMsg(OP_CONNECT)
|
interestCallReceiver.expectMsg(OP_CONNECT)
|
||||||
selector.send(connectionActor, ChannelConnectable)
|
selector.send(connectionActor, ChannelConnectable)
|
||||||
userHandler.expectMsg(Connected(serverAddress, clientSideChannel.socket.getLocalSocketAddress.asInstanceOf[InetSocketAddress]))
|
userHandler.expectMsg(
|
||||||
|
Connected(serverAddress, clientSideChannel.socket.getLocalSocketAddress.asInstanceOf[InetSocketAddress]))
|
||||||
|
|
||||||
userHandler.send(connectionActor, Register(connectionHandler.ref, keepOpenOnPeerClosed, useResumeWriting))
|
userHandler.send(connectionActor, Register(connectionHandler.ref, keepOpenOnPeerClosed, useResumeWriting))
|
||||||
ignoreWindowsWorkaroundForTicket15766()
|
ignoreWindowsWorkaroundForTicket15766()
|
||||||
|
|
@ -1051,7 +1054,8 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
/**
|
/**
|
||||||
* Tries to simultaneously act on client and server side to read from the server all pending data from the client.
|
* Tries to simultaneously act on client and server side to read from the server all pending data from the client.
|
||||||
*/
|
*/
|
||||||
@tailrec final def pullFromServerSide(remaining: Int, remainingTries: Int = 1000,
|
@tailrec final def pullFromServerSide(remaining: Int,
|
||||||
|
remainingTries: Int = 1000,
|
||||||
into: ByteBuffer = defaultbuffer): Unit =
|
into: ByteBuffer = defaultbuffer): Unit =
|
||||||
if (remainingTries <= 0)
|
if (remainingTries <= 0)
|
||||||
throw new AssertionError("Pulling took too many loops, remaining data: " + remaining)
|
throw new AssertionError("Pulling took too many loops, remaining data: " + remaining)
|
||||||
|
|
@ -1072,7 +1076,8 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
if (nioSelector.selectedKeys().contains(serverSelectionKey)) {
|
if (nioSelector.selectedKeys().contains(serverSelectionKey)) {
|
||||||
if (into eq defaultbuffer) into.clear()
|
if (into eq defaultbuffer) into.clear()
|
||||||
serverSideChannel.read(into) match {
|
serverSideChannel.read(into) match {
|
||||||
case -1 => throw new IllegalStateException("Connection was closed unexpectedly with remaining bytes " + remaining)
|
case -1 =>
|
||||||
|
throw new IllegalStateException("Connection was closed unexpectedly with remaining bytes " + remaining)
|
||||||
case 0 => throw new IllegalStateException("Made no progress")
|
case 0 => throw new IllegalStateException("Made no progress")
|
||||||
case other => other
|
case other => other
|
||||||
}
|
}
|
||||||
|
|
@ -1104,10 +1109,11 @@ class TcpConnectionSpec extends AkkaSpec("""
|
||||||
def selectedAs(interest: Int, duration: Duration): BeMatcher[SelectionKey] =
|
def selectedAs(interest: Int, duration: Duration): BeMatcher[SelectionKey] =
|
||||||
new BeMatcher[SelectionKey] {
|
new BeMatcher[SelectionKey] {
|
||||||
def apply(key: SelectionKey) =
|
def apply(key: SelectionKey) =
|
||||||
MatchResult(
|
MatchResult(checkFor(key, interest, duration.toMillis.toInt),
|
||||||
checkFor(key, interest, duration.toMillis.toInt),
|
"%s key was not selected for %s after %s".format(key.attachment(),
|
||||||
"%s key was not selected for %s after %s" format (key.attachment(), interestsDesc(interest), duration),
|
interestsDesc(interest),
|
||||||
"%s key was selected for %s after %s" format (key.attachment(), interestsDesc(interest), duration))
|
duration),
|
||||||
|
"%s key was selected for %s after %s".format(key.attachment(), interestsDesc(interest), duration))
|
||||||
}
|
}
|
||||||
|
|
||||||
val interestsNames =
|
val interestsNames =
|
||||||
|
|
|
||||||
|
|
@ -195,15 +195,14 @@ class TcpIntegrationSpec extends AkkaSpec("""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def chitchat(
|
def chitchat(clientHandler: TestProbe,
|
||||||
clientHandler: TestProbe,
|
|
||||||
clientConnection: ActorRef,
|
clientConnection: ActorRef,
|
||||||
serverHandler: TestProbe,
|
serverHandler: TestProbe,
|
||||||
serverConnection: ActorRef,
|
serverConnection: ActorRef,
|
||||||
rounds: Int = 100) = {
|
rounds: Int = 100) = {
|
||||||
|
|
||||||
val testData = ByteString(0)
|
val testData = ByteString(0)
|
||||||
(1 to rounds) foreach { _ =>
|
(1 to rounds).foreach { _ =>
|
||||||
clientHandler.send(clientConnection, Write(testData))
|
clientHandler.send(clientConnection, Write(testData))
|
||||||
serverHandler.expectMsg(Received(testData))
|
serverHandler.expectMsg(Received(testData))
|
||||||
serverHandler.send(serverConnection, Write(testData))
|
serverHandler.send(serverConnection, Write(testData))
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@ trait TcpIntegrationSpecSupport { _: AkkaSpec =>
|
||||||
if (runClientInExtraSystem) {
|
if (runClientInExtraSystem) {
|
||||||
val res = ActorSystem("TcpIntegrationSpec-client", system.settings.config)
|
val res = ActorSystem("TcpIntegrationSpec-client", system.settings.config)
|
||||||
// terminate clientSystem after server system
|
// terminate clientSystem after server system
|
||||||
system.whenTerminated.onComplete { _ => res.terminate() }(ExecutionContexts.sameThreadExecutionContext)
|
system.whenTerminated.onComplete { _ =>
|
||||||
|
res.terminate()
|
||||||
|
}(ExecutionContexts.sameThreadExecutionContext)
|
||||||
res
|
res
|
||||||
} else system
|
} else system
|
||||||
val bindHandler = TestProbe()
|
val bindHandler = TestProbe()
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ class TcpListenerSpec extends AkkaSpec("""
|
||||||
listener ! ChannelAcceptable
|
listener ! ChannelAcceptable
|
||||||
val channel = expectWorkerForCommand
|
val channel = expectWorkerForCommand
|
||||||
|
|
||||||
EventFilter.warning(pattern = "selector capacity limit", occurrences = 1) intercept {
|
EventFilter.warning(pattern = "selector capacity limit", occurrences = 1).intercept {
|
||||||
listener ! FailedRegisterIncoming(channel)
|
listener ! FailedRegisterIncoming(channel)
|
||||||
awaitCond(!channel.isOpen)
|
awaitCond(!channel.isOpen)
|
||||||
}
|
}
|
||||||
|
|
@ -175,12 +175,16 @@ class TcpListenerSpec extends AkkaSpec("""
|
||||||
|
|
||||||
private class ListenerParent(pullMode: Boolean) extends Actor with ChannelRegistry {
|
private class ListenerParent(pullMode: Boolean) extends Actor with ChannelRegistry {
|
||||||
val listener = context.actorOf(
|
val listener = context.actorOf(
|
||||||
props = Props(classOf[TcpListener], selectorRouter.ref, Tcp(system), this, bindCommander.ref,
|
props = Props(classOf[TcpListener],
|
||||||
|
selectorRouter.ref,
|
||||||
|
Tcp(system),
|
||||||
|
this,
|
||||||
|
bindCommander.ref,
|
||||||
Bind(handler.ref, endpoint, 100, Nil, pullMode)).withDeploy(Deploy.local),
|
Bind(handler.ref, endpoint, 100, Nil, pullMode)).withDeploy(Deploy.local),
|
||||||
name = "test-listener-" + counter.next())
|
name = "test-listener-" + counter.next())
|
||||||
parent.watch(listener)
|
parent.watch(listener)
|
||||||
def receive: Receive = {
|
def receive: Receive = {
|
||||||
case msg => parent.ref forward msg
|
case msg => parent.ref.forward(msg)
|
||||||
}
|
}
|
||||||
override def supervisorStrategy = SupervisorStrategy.stoppingStrategy
|
override def supervisorStrategy = SupervisorStrategy.stoppingStrategy
|
||||||
|
|
||||||
|
|
@ -191,5 +195,6 @@ class TcpListenerSpec extends AkkaSpec("""
|
||||||
|
|
||||||
}
|
}
|
||||||
object TcpListenerSpec {
|
object TcpListenerSpec {
|
||||||
final case class RegisterChannel(channel: SelectableChannel, initialOps: Int) extends NoSerializationVerificationNeeded
|
final case class RegisterChannel(channel: SelectableChannel, initialOps: Int)
|
||||||
|
extends NoSerializationVerificationNeeded
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
package akka.io
|
package akka.io
|
||||||
|
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import akka.testkit.{ TestProbe, ImplicitSender, AkkaSpec }
|
import akka.testkit.{ AkkaSpec, ImplicitSender, TestProbe }
|
||||||
import akka.util.ByteString
|
import akka.util.ByteString
|
||||||
import akka.actor.ActorRef
|
import akka.actor.ActorRef
|
||||||
import akka.testkit.SocketUtil.temporaryServerAddresses
|
import akka.testkit.SocketUtil.temporaryServerAddresses
|
||||||
|
|
@ -24,7 +24,9 @@ class UdpConnectedIntegrationSpec extends AkkaSpec("""
|
||||||
commander.sender()
|
commander.sender()
|
||||||
}
|
}
|
||||||
|
|
||||||
def connectUdp(localAddress: Option[InetSocketAddress], remoteAddress: InetSocketAddress, handler: ActorRef): ActorRef = {
|
def connectUdp(localAddress: Option[InetSocketAddress],
|
||||||
|
remoteAddress: InetSocketAddress,
|
||||||
|
handler: ActorRef): ActorRef = {
|
||||||
val commander = TestProbe()
|
val commander = TestProbe()
|
||||||
commander.send(IO(UdpConnected), UdpConnected.Connect(handler, remoteAddress, localAddress, Nil))
|
commander.send(IO(UdpConnected), UdpConnected.Connect(handler, remoteAddress, localAddress, Nil))
|
||||||
commander.expectMsg(UdpConnected.Connected)
|
commander.expectMsg(UdpConnected.Connected)
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,7 @@ The configuration to start a bind DNS server in Docker with this configuration
|
||||||
is included, and the test will automatically start this container when the
|
is included, and the test will automatically start this container when the
|
||||||
test starts and tear it down when it finishes.
|
test starts and tear it down when it finishes.
|
||||||
*/
|
*/
|
||||||
class AsyncDnsResolverIntegrationSpec extends AkkaSpec(
|
class AsyncDnsResolverIntegrationSpec extends AkkaSpec(s"""
|
||||||
s"""
|
|
||||||
akka.loglevel = DEBUG
|
akka.loglevel = DEBUG
|
||||||
akka.loggers = ["akka.testkit.SilenceAllTestEventListener"]
|
akka.loggers = ["akka.testkit.SilenceAllTestEventListener"]
|
||||||
akka.io.dns.resolver = async-dns
|
akka.io.dns.resolver = async-dns
|
||||||
|
|
@ -62,17 +61,16 @@ class AsyncDnsResolverIntegrationSpec extends AkkaSpec(
|
||||||
val name = "a-double.foo.test"
|
val name = "a-double.foo.test"
|
||||||
val answer = resolve(name)
|
val answer = resolve(name)
|
||||||
answer.name shouldEqual name
|
answer.name shouldEqual name
|
||||||
answer.records.map(_.asInstanceOf[ARecord].ip).toSet shouldEqual Set(
|
answer.records.map(_.asInstanceOf[ARecord].ip).toSet shouldEqual Set(InetAddress.getByName("192.168.1.21"),
|
||||||
InetAddress.getByName("192.168.1.21"),
|
InetAddress.getByName("192.168.1.22"))
|
||||||
InetAddress.getByName("192.168.1.22")
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"resolve single AAAA record" in {
|
"resolve single AAAA record" in {
|
||||||
val name = "aaaa-single.foo.test"
|
val name = "aaaa-single.foo.test"
|
||||||
val answer = resolve(name)
|
val answer = resolve(name)
|
||||||
answer.name shouldEqual name
|
answer.name shouldEqual name
|
||||||
answer.records.map(_.asInstanceOf[AAAARecord].ip) shouldEqual Seq(InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:1"))
|
answer.records.map(_.asInstanceOf[AAAARecord].ip) shouldEqual Seq(
|
||||||
|
InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:1"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"resolve double AAAA records" in {
|
"resolve double AAAA records" in {
|
||||||
|
|
@ -81,8 +79,7 @@ class AsyncDnsResolverIntegrationSpec extends AkkaSpec(
|
||||||
answer.name shouldEqual name
|
answer.name shouldEqual name
|
||||||
answer.records.map(_.asInstanceOf[AAAARecord].ip).toSet shouldEqual Set(
|
answer.records.map(_.asInstanceOf[AAAARecord].ip).toSet shouldEqual Set(
|
||||||
InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:2"),
|
InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:2"),
|
||||||
InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:3")
|
InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:3"))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"resolve mixed A/AAAA records" in {
|
"resolve mixed A/AAAA records" in {
|
||||||
|
|
@ -90,40 +87,29 @@ class AsyncDnsResolverIntegrationSpec extends AkkaSpec(
|
||||||
val answer = resolve(name)
|
val answer = resolve(name)
|
||||||
answer.name shouldEqual name
|
answer.name shouldEqual name
|
||||||
|
|
||||||
answer.records.collect { case r: ARecord => r.ip }.toSet shouldEqual Set(
|
answer.records.collect { case r: ARecord => r.ip }.toSet shouldEqual Set(InetAddress.getByName("192.168.1.23"),
|
||||||
InetAddress.getByName("192.168.1.23"),
|
InetAddress.getByName("192.168.1.24"))
|
||||||
InetAddress.getByName("192.168.1.24")
|
|
||||||
)
|
|
||||||
|
|
||||||
answer.records.collect { case r: AAAARecord => r.ip }.toSet shouldEqual Set(
|
answer.records.collect { case r: AAAARecord => r.ip }.toSet shouldEqual Set(
|
||||||
InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:4"),
|
InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:4"),
|
||||||
InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:5")
|
InetAddress.getByName("fd4d:36b2:3eca:a2d8:0:0:0:5"))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"resolve external CNAME record" in {
|
"resolve external CNAME record" in {
|
||||||
val name = "cname-ext.foo.test"
|
val name = "cname-ext.foo.test"
|
||||||
val answer = (IO(Dns) ? DnsProtocol.Resolve(name)).mapTo[DnsProtocol.Resolved].futureValue
|
val answer = (IO(Dns) ? DnsProtocol.Resolve(name)).mapTo[DnsProtocol.Resolved].futureValue
|
||||||
answer.name shouldEqual name
|
answer.name shouldEqual name
|
||||||
answer.records.collect { case r: CNameRecord => r.canonicalName }.toSet shouldEqual Set(
|
answer.records.collect { case r: CNameRecord => r.canonicalName }.toSet shouldEqual Set("a-single.bar.example")
|
||||||
"a-single.bar.example"
|
answer.records.collect { case r: ARecord => r.ip }.toSet shouldEqual Set(InetAddress.getByName("192.168.2.20"))
|
||||||
)
|
|
||||||
answer.records.collect { case r: ARecord => r.ip }.toSet shouldEqual Set(
|
|
||||||
InetAddress.getByName("192.168.2.20")
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"resolve internal CNAME record" in {
|
"resolve internal CNAME record" in {
|
||||||
val name = "cname-in.foo.test"
|
val name = "cname-in.foo.test"
|
||||||
val answer = resolve(name)
|
val answer = resolve(name)
|
||||||
answer.name shouldEqual name
|
answer.name shouldEqual name
|
||||||
answer.records.collect { case r: CNameRecord => r.canonicalName }.toSet shouldEqual Set(
|
answer.records.collect { case r: CNameRecord => r.canonicalName }.toSet shouldEqual Set("a-double.foo.test")
|
||||||
"a-double.foo.test"
|
answer.records.collect { case r: ARecord => r.ip }.toSet shouldEqual Set(InetAddress.getByName("192.168.1.21"),
|
||||||
)
|
InetAddress.getByName("192.168.1.22"))
|
||||||
answer.records.collect { case r: ARecord => r.ip }.toSet shouldEqual Set(
|
|
||||||
InetAddress.getByName("192.168.1.21"),
|
|
||||||
InetAddress.getByName("192.168.1.22")
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"resolve SRV record" in {
|
"resolve SRV record" in {
|
||||||
|
|
@ -133,13 +119,14 @@ class AsyncDnsResolverIntegrationSpec extends AkkaSpec(
|
||||||
answer.name shouldEqual name
|
answer.name shouldEqual name
|
||||||
answer.records.collect { case r: SRVRecord => r }.toSet shouldEqual Set(
|
answer.records.collect { case r: SRVRecord => r }.toSet shouldEqual Set(
|
||||||
SRVRecord("_service._tcp.foo.test", Ttl.fromPositive(86400.seconds), 10, 65534, 5060, "a-single.foo.test"),
|
SRVRecord("_service._tcp.foo.test", Ttl.fromPositive(86400.seconds), 10, 65534, 5060, "a-single.foo.test"),
|
||||||
SRVRecord("_service._tcp.foo.test", Ttl.fromPositive(86400.seconds), 65533, 40, 65535, "a-double.foo.test")
|
SRVRecord("_service._tcp.foo.test", Ttl.fromPositive(86400.seconds), 65533, 40, 65535, "a-double.foo.test"))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"resolve same address twice" in {
|
"resolve same address twice" in {
|
||||||
resolve("a-single.foo.test").records.map(_.asInstanceOf[ARecord].ip) shouldEqual Seq(InetAddress.getByName("192.168.1.20"))
|
resolve("a-single.foo.test").records.map(_.asInstanceOf[ARecord].ip) shouldEqual Seq(
|
||||||
resolve("a-single.foo.test").records.map(_.asInstanceOf[ARecord].ip) shouldEqual Seq(InetAddress.getByName("192.168.1.20"))
|
InetAddress.getByName("192.168.1.20"))
|
||||||
|
resolve("a-single.foo.test").records.map(_.asInstanceOf[ARecord].ip) shouldEqual Seq(
|
||||||
|
InetAddress.getByName("192.168.1.20"))
|
||||||
}
|
}
|
||||||
|
|
||||||
"handle nonexistent domains" in {
|
"handle nonexistent domains" in {
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ class DnsSettingsSpec extends AkkaSpec {
|
||||||
"DNS settings" must {
|
"DNS settings" must {
|
||||||
|
|
||||||
"use host servers if set to default" in {
|
"use host servers if set to default" in {
|
||||||
val dnsSettings = new DnsSettings(eas, ConfigFactory.parseString(
|
val dnsSettings = new DnsSettings(eas,
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
nameservers = "default"
|
nameservers = "default"
|
||||||
resolve-timeout = 1s
|
resolve-timeout = 1s
|
||||||
search-domains = []
|
search-domains = []
|
||||||
|
|
@ -30,8 +30,8 @@ class DnsSettingsSpec extends AkkaSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
"parse a single name server" in {
|
"parse a single name server" in {
|
||||||
val dnsSettings = new DnsSettings(eas, ConfigFactory.parseString(
|
val dnsSettings = new DnsSettings(eas,
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
nameservers = "127.0.0.1"
|
nameservers = "127.0.0.1"
|
||||||
resolve-timeout = 1s
|
resolve-timeout = 1s
|
||||||
search-domains = []
|
search-domains = []
|
||||||
|
|
@ -42,22 +42,21 @@ class DnsSettingsSpec extends AkkaSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
"parse a list of name servers" in {
|
"parse a list of name servers" in {
|
||||||
val dnsSettings = new DnsSettings(eas, ConfigFactory.parseString(
|
val dnsSettings = new DnsSettings(eas,
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
nameservers = ["127.0.0.1", "127.0.0.2"]
|
nameservers = ["127.0.0.1", "127.0.0.2"]
|
||||||
resolve-timeout = 1s
|
resolve-timeout = 1s
|
||||||
search-domains = []
|
search-domains = []
|
||||||
ndots = 1
|
ndots = 1
|
||||||
"""))
|
"""))
|
||||||
|
|
||||||
dnsSettings.NameServers.map(_.getAddress) shouldEqual List(
|
dnsSettings.NameServers.map(_.getAddress) shouldEqual List(InetAddress.getByName("127.0.0.1"),
|
||||||
InetAddress.getByName("127.0.0.1"), InetAddress.getByName("127.0.0.2")
|
InetAddress.getByName("127.0.0.2"))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"use host search domains if set to default" in {
|
"use host search domains if set to default" in {
|
||||||
val dnsSettings = new DnsSettings(eas, ConfigFactory.parseString(
|
val dnsSettings = new DnsSettings(eas,
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
nameservers = "127.0.0.1"
|
nameservers = "127.0.0.1"
|
||||||
resolve-timeout = 1s
|
resolve-timeout = 1s
|
||||||
search-domains = "default"
|
search-domains = "default"
|
||||||
|
|
@ -69,8 +68,8 @@ class DnsSettingsSpec extends AkkaSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
"parse a single search domain" in {
|
"parse a single search domain" in {
|
||||||
val dnsSettings = new DnsSettings(eas, ConfigFactory.parseString(
|
val dnsSettings = new DnsSettings(eas,
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
nameservers = "127.0.0.1"
|
nameservers = "127.0.0.1"
|
||||||
resolve-timeout = 1s
|
resolve-timeout = 1s
|
||||||
search-domains = "example.com"
|
search-domains = "example.com"
|
||||||
|
|
@ -81,8 +80,8 @@ class DnsSettingsSpec extends AkkaSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
"parse a single list of search domains" in {
|
"parse a single list of search domains" in {
|
||||||
val dnsSettings = new DnsSettings(eas, ConfigFactory.parseString(
|
val dnsSettings = new DnsSettings(eas,
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
nameservers = "127.0.0.1"
|
nameservers = "127.0.0.1"
|
||||||
resolve-timeout = 1s
|
resolve-timeout = 1s
|
||||||
search-domains = [ "example.com", "example.net" ]
|
search-domains = [ "example.com", "example.net" ]
|
||||||
|
|
@ -93,8 +92,8 @@ class DnsSettingsSpec extends AkkaSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
"use host ndots if set to default" in {
|
"use host ndots if set to default" in {
|
||||||
val dnsSettings = new DnsSettings(eas, ConfigFactory.parseString(
|
val dnsSettings = new DnsSettings(eas,
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
nameservers = "127.0.0.1"
|
nameservers = "127.0.0.1"
|
||||||
resolve-timeout = 1s
|
resolve-timeout = 1s
|
||||||
search-domains = "example.com"
|
search-domains = "example.com"
|
||||||
|
|
@ -106,8 +105,8 @@ class DnsSettingsSpec extends AkkaSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
"parse ndots" in {
|
"parse ndots" in {
|
||||||
val dnsSettings = new DnsSettings(eas, ConfigFactory.parseString(
|
val dnsSettings = new DnsSettings(eas,
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
nameservers = "127.0.0.1"
|
nameservers = "127.0.0.1"
|
||||||
resolve-timeout = 1s
|
resolve-timeout = 1s
|
||||||
search-domains = "example.com"
|
search-domains = "example.com"
|
||||||
|
|
|
||||||
|
|
@ -38,25 +38,30 @@ trait DockerBindDnsService extends Eventually { self: AkkaSpec =>
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val containerConfig = ContainerConfig.builder()
|
val containerConfig = ContainerConfig
|
||||||
|
.builder()
|
||||||
.image(image)
|
.image(image)
|
||||||
.env("NO_CHOWN=true")
|
.env("NO_CHOWN=true")
|
||||||
.cmd("-4") // only listen on ipv4
|
.cmd("-4") // only listen on ipv4
|
||||||
.hostConfig(
|
.hostConfig(
|
||||||
HostConfig.builder()
|
HostConfig
|
||||||
.portBindings(Map(
|
.builder()
|
||||||
"53/tcp" -> List(PortBinding.of("", hostPort)).asJava,
|
.portBindings(Map("53/tcp" -> List(PortBinding.of("", hostPort)).asJava,
|
||||||
"53/udp" -> List(PortBinding.of("", hostPort)).asJava
|
"53/udp" -> List(PortBinding.of("", hostPort)).asJava).asJava)
|
||||||
).asJava)
|
.binds(HostConfig.Bind
|
||||||
.binds(HostConfig.Bind.from(new java.io.File("akka-actor-tests/src/test/bind/").getAbsolutePath).to("/data/bind").build())
|
.from(new java.io.File("akka-actor-tests/src/test/bind/").getAbsolutePath)
|
||||||
.build()
|
.to("/data/bind")
|
||||||
)
|
.build())
|
||||||
|
.build())
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val containerName = "akka-test-dns-" + getClass.getCanonicalName
|
val containerName = "akka-test-dns-" + getClass.getCanonicalName
|
||||||
|
|
||||||
client.listContainers(ListContainersParam.allContainers()).asScala
|
client
|
||||||
.find(_.names().asScala.exists(_.contains(containerName))).foreach(c => {
|
.listContainers(ListContainersParam.allContainers())
|
||||||
|
.asScala
|
||||||
|
.find(_.names().asScala.exists(_.contains(containerName)))
|
||||||
|
.foreach(c => {
|
||||||
if ("running" == c.state()) {
|
if ("running" == c.state()) {
|
||||||
client.killContainer(c.id)
|
client.killContainer(c.id)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,17 @@ class NameserverAddressParserSpec extends WordSpec with Matchers {
|
||||||
DnsSettings.parseNameserverAddress("8.8.8.8:153") shouldEqual new InetSocketAddress("8.8.8.8", 153)
|
DnsSettings.parseNameserverAddress("8.8.8.8:153") shouldEqual new InetSocketAddress("8.8.8.8", 153)
|
||||||
}
|
}
|
||||||
"handle explicit port in IPv6 address" in {
|
"handle explicit port in IPv6 address" in {
|
||||||
DnsSettings.parseNameserverAddress("[2001:4860:4860::8888]:153") shouldEqual new InetSocketAddress("2001:4860:4860::8888", 153)
|
DnsSettings.parseNameserverAddress("[2001:4860:4860::8888]:153") shouldEqual new InetSocketAddress(
|
||||||
|
"2001:4860:4860::8888",
|
||||||
|
153)
|
||||||
}
|
}
|
||||||
"handle default port in IPv4 address" in {
|
"handle default port in IPv4 address" in {
|
||||||
DnsSettings.parseNameserverAddress("8.8.8.8") shouldEqual new InetSocketAddress("8.8.8.8", 53)
|
DnsSettings.parseNameserverAddress("8.8.8.8") shouldEqual new InetSocketAddress("8.8.8.8", 53)
|
||||||
}
|
}
|
||||||
"handle default port in IPv6 address" in {
|
"handle default port in IPv6 address" in {
|
||||||
DnsSettings.parseNameserverAddress("[2001:4860:4860::8888]") shouldEqual new InetSocketAddress("2001:4860:4860::8888", 53)
|
DnsSettings.parseNameserverAddress("[2001:4860:4860::8888]") shouldEqual new InetSocketAddress(
|
||||||
|
"2001:4860:4860::8888",
|
||||||
|
53)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,7 @@ import akka.testkit.{ AkkaSpec, ImplicitSender }
|
||||||
|
|
||||||
import scala.collection.immutable.Seq
|
import scala.collection.immutable.Seq
|
||||||
|
|
||||||
class AsyncDnsManagerSpec extends AkkaSpec(
|
class AsyncDnsManagerSpec extends AkkaSpec("""
|
||||||
"""
|
|
||||||
akka.loglevel = DEBUG
|
akka.loglevel = DEBUG
|
||||||
akka.loggers = ["akka.testkit.SilenceAllTestEventListener"]
|
akka.loggers = ["akka.testkit.SilenceAllTestEventListener"]
|
||||||
akka.io.dns.resolver = async-dns
|
akka.io.dns.resolver = async-dns
|
||||||
|
|
@ -46,7 +45,7 @@ class AsyncDnsManagerSpec extends AkkaSpec(
|
||||||
|
|
||||||
"provide access to cache" in {
|
"provide access to cache" in {
|
||||||
dns ! AsyncDnsManager.GetCache
|
dns ! AsyncDnsManager.GetCache
|
||||||
expectMsgType[AsyncDnsCache] should be theSameInstanceAs Dns(system).cache
|
(expectMsgType[AsyncDnsCache] should be).theSameInstanceAs(Dns(system).cache)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,7 @@ import akka.testkit.WithLogCapturing
|
||||||
import scala.collection.{ immutable => im }
|
import scala.collection.{ immutable => im }
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
class AsyncDnsResolverSpec extends AkkaSpec(
|
class AsyncDnsResolverSpec extends AkkaSpec("""
|
||||||
"""
|
|
||||||
akka.loglevel = DEBUG
|
akka.loglevel = DEBUG
|
||||||
akka.loggers = ["akka.testkit.SilenceAllTestEventListener"]
|
akka.loggers = ["akka.testkit.SilenceAllTestEventListener"]
|
||||||
""") with WithLogCapturing {
|
""") with WithLogCapturing {
|
||||||
|
|
@ -106,8 +105,7 @@ class AsyncDnsResolverSpec extends AkkaSpec(
|
||||||
dnsClient1.expectNoMessage(50.millis)
|
dnsClient1.expectNoMessage(50.millis)
|
||||||
val answer = senderProbe.expectMsgType[Resolved]
|
val answer = senderProbe.expectMsgType[Resolved]
|
||||||
answer.records.collect { case r: ARecord => r }.toSet shouldEqual Set(
|
answer.records.collect { case r: ARecord => r }.toSet shouldEqual Set(
|
||||||
ARecord("127.0.0.1", Ttl.effectivelyForever, InetAddress.getByName("127.0.0.1"))
|
ARecord("127.0.0.1", Ttl.effectivelyForever, InetAddress.getByName("127.0.0.1")))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"response immediately for IPv6 address" in new Setup {
|
"response immediately for IPv6 address" in new Setup {
|
||||||
|
|
@ -115,7 +113,9 @@ class AsyncDnsResolverSpec extends AkkaSpec(
|
||||||
r ! Resolve(name)
|
r ! Resolve(name)
|
||||||
dnsClient1.expectNoMessage(50.millis)
|
dnsClient1.expectNoMessage(50.millis)
|
||||||
val answer = senderProbe.expectMsgType[Resolved]
|
val answer = senderProbe.expectMsgType[Resolved]
|
||||||
val Seq(AAAARecord("1:2:3:0:0:0:0:0", Ttl.effectivelyForever, _)) = answer.records.collect { case r: AAAARecord => r }
|
val Seq(AAAARecord("1:2:3:0:0:0:0:0", Ttl.effectivelyForever, _)) = answer.records.collect {
|
||||||
|
case r: AAAARecord => r
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"return additional records for SRV requests" in new Setup {
|
"return additional records for SRV requests" in new Setup {
|
||||||
|
|
@ -134,8 +134,8 @@ class AsyncDnsResolverSpec extends AkkaSpec(
|
||||||
}
|
}
|
||||||
|
|
||||||
def resolver(clients: List[ActorRef]): ActorRef = {
|
def resolver(clients: List[ActorRef]): ActorRef = {
|
||||||
val settings = new DnsSettings(system.asInstanceOf[ExtendedActorSystem], ConfigFactory.parseString(
|
val settings = new DnsSettings(system.asInstanceOf[ExtendedActorSystem],
|
||||||
"""
|
ConfigFactory.parseString("""
|
||||||
nameservers = ["one","two"]
|
nameservers = ["one","two"]
|
||||||
resolve-timeout = 300ms
|
resolve-timeout = 300ms
|
||||||
search-domains = []
|
search-domains = []
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ import org.scalatest.{ Matchers, WordSpec }
|
||||||
class MessageSpec extends WordSpec with Matchers {
|
class MessageSpec extends WordSpec with Matchers {
|
||||||
"The Message" should {
|
"The Message" should {
|
||||||
"parse a response that is truncated mid-message" in {
|
"parse a response that is truncated mid-message" in {
|
||||||
val bytes = ByteString(0, 4, -125, -128, 0, 1, 0, 48, 0, 0, 0, 0, 4, 109, 97, 110, 121, 4, 98, 122, 122, 116, 3, 110, 101, 116, 0, 0, 28, 0, 1)
|
val bytes = ByteString(0, 4, -125, -128, 0, 1, 0, 48, 0, 0, 0, 0, 4, 109, 97, 110, 121, 4, 98, 122, 122, 116, 3,
|
||||||
|
110, 101, 116, 0, 0, 28, 0, 1)
|
||||||
val msg = Message.parse(bytes)
|
val msg = Message.parse(bytes)
|
||||||
msg.id should be(4)
|
msg.id should be(4)
|
||||||
msg.flags.isTruncated should be(true)
|
msg.flags.isTruncated should be(true)
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue