format source with scalafmt

This commit is contained in:
Auto Format 2019-03-11 10:38:24 +01:00 committed by Patrik Nordwall
parent 0f40491d42
commit ce404e4f53
1669 changed files with 43208 additions and 35404 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -83,4 +83,3 @@ import scala.compat.java8.FunctionConverters._
super.scheduleOnce(delay, target, message) super.scheduleOnce(delay, target, message)
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -78,4 +78,3 @@ class DeadLetterSupressionSpec extends AkkaSpec with ImplicitSender {
allListener.expectNoMsg(Duration.Zero) allListener.expectNoMsg(Duration.Zero)
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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. Im leaving this code in so that manual inspection remains * failed. Im 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"),

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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