make akka-actor-tests compile again

This commit is contained in:
Roland 2011-10-11 16:05:48 +02:00
parent 1e1409e796
commit 93b1ef3703
67 changed files with 1576 additions and 1813 deletions

View file

@ -1,5 +1,6 @@
package akka.actor;
import akka.AkkaApplication;
import akka.japi.Creator;
import org.junit.Test;
import akka.actor.Actors;
@ -8,32 +9,34 @@ import static org.junit.Assert.*;
public class JavaAPI {
private AkkaApplication app = new AkkaApplication();
@Test void mustBeAbleToUseUntypedActor() {
final RemoteSupport remote = Actors.remote();
final RemoteSupport remote = app.remote();
assertNotNull(remote);
}
@Test void mustInteractWithActorRegistry() {
final ActorRegistry registry = Actors.registry();
final ActorRegistry registry = app.registry();
assertNotNull(registry);
}
@Test void mustBeAbleToCreateActorRefFromClass() {
ActorRef ref = Actors.actorOf(JavaAPITestActor.class);
ActorRef ref = app.createActor(JavaAPITestActor.class);
assertNotNull(ref);
}
@Test void mustBeAbleToCreateActorRefFromFactory() {
ActorRef ref = Actors.actorOf(new Creator<Actor>() {
ActorRef ref = app.createActor(new Props().withCreator(new Creator<Actor>() {
public Actor create() {
return new JavaAPITestActor();
}
});
}));
assertNotNull(ref);
}
@Test void mustAcceptSingleArgTryTell() {
ActorRef ref = Actors.actorOf(JavaAPITestActor.class);
ActorRef ref = app.createActor(JavaAPITestActor.class);
ref.tryTell("hallo");
ref.tryTell("hallo", ref);
}

View file

@ -1,6 +1,7 @@
package akka.dispatch;
import akka.actor.Timeout;
import akka.AkkaApplication;
import org.junit.Test;
import static org.junit.Assert.*;
import java.util.concurrent.Callable;
@ -15,12 +16,15 @@ import akka.japi.Procedure;
import akka.japi.Option;
import scala.Some;
import scala.Right;
import static akka.dispatch.Futures.*;
public class JavaFutureTests {
private final AkkaApplication app = new AkkaApplication();
private final Timeout t = app.akkaConfig().TIMEOUT();
private final FutureFactory ff = new FutureFactory(app.dispatcher(), t);
@Test public void mustBeAbleToMapAFuture() {
Future<String> f1 = future(new Callable<String>() {
Future<String> f1 = ff.future(new Callable<String>() {
public String call() {
return "Hello";
}
@ -30,14 +34,14 @@ public class JavaFutureTests {
public String apply(String s) {
return s + " World";
}
});
}, t);
assertEquals("Hello World", f2.get());
}
@Test public void mustBeAbleToExecuteAnOnResultCallback() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, Dispatchers.defaultGlobalDispatcher());
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, app.dispatcherFactory().defaultGlobalDispatcher());
Future<String> f = cf;
f.onResult(new Procedure<String>() {
public void apply(String result) {
@ -53,7 +57,7 @@ public class JavaFutureTests {
@Test public void mustBeAbleToExecuteAnOnExceptionCallback() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, Dispatchers.defaultGlobalDispatcher());
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, app.dispatcherFactory().defaultGlobalDispatcher());
Future<String> f = cf;
f.onException(new Procedure<Throwable>() {
public void apply(Throwable t) {
@ -70,7 +74,7 @@ public class JavaFutureTests {
@Test public void mustBeAbleToExecuteAnOnTimeoutCallback() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, Dispatchers.defaultGlobalDispatcher());
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, app.dispatcherFactory().defaultGlobalDispatcher());
Future<String> f = cf;
f.onTimeout(new Procedure<Future<String>>() {
public void apply(Future<String> future) {
@ -84,7 +88,7 @@ public class JavaFutureTests {
@Test public void mustBeAbleToExecuteAnOnCompleteCallback() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, Dispatchers.defaultGlobalDispatcher());
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, app.dispatcherFactory().defaultGlobalDispatcher());
Future<String> f = cf;
f.onComplete(new Procedure<Future<String>>() {
public void apply(akka.dispatch.Future<String> future) {
@ -99,7 +103,7 @@ public class JavaFutureTests {
@Test public void mustBeAbleToForeachAFuture() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, Dispatchers.defaultGlobalDispatcher());
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, app.dispatcherFactory().defaultGlobalDispatcher());
Future<String> f = cf;
f.foreach(new Procedure<String>() {
public void apply(String future) {
@ -114,17 +118,17 @@ public class JavaFutureTests {
@Test public void mustBeAbleToFlatMapAFuture() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, Dispatchers.defaultGlobalDispatcher());
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, app.dispatcherFactory().defaultGlobalDispatcher());
cf.completeWithResult("1000");
Future<String> f = cf;
Future<Integer> r = f.flatMap(new Function<String, Future<Integer>>() {
public Future<Integer> apply(String r) {
latch.countDown();
Promise<Integer> cf = new akka.dispatch.DefaultPromise<Integer>(1000, TimeUnit.MILLISECONDS, Dispatchers.defaultGlobalDispatcher());
Promise<Integer> cf = new akka.dispatch.DefaultPromise<Integer>(1000, TimeUnit.MILLISECONDS, app.dispatcherFactory().defaultGlobalDispatcher());
cf.completeWithResult(Integer.parseInt(r));
return cf;
}
});
}, t);
assertEquals(f.get(), "1000");
assertEquals(r.get().intValue(), 1000);
@ -133,14 +137,14 @@ public class JavaFutureTests {
@Test public void mustBeAbleToFilterAFuture() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, Dispatchers.defaultGlobalDispatcher());
Promise<String> cf = new akka.dispatch.DefaultPromise<String>(1000, TimeUnit.MILLISECONDS, app.dispatcherFactory().defaultGlobalDispatcher());
Future<String> f = cf;
Future<String> r = f.filter(new Function<String, Boolean>() {
public Boolean apply(String r) {
latch.countDown();
return r.equals("foo");
}
});
}, t);
cf.completeWithResult("foo");
assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
@ -155,14 +159,14 @@ public class JavaFutureTests {
for (int i = 0; i < 10; i++) {
listExpected.add("test");
listFutures.add(future(new Callable<String>() {
listFutures.add(ff.future(new Callable<String>() {
public String call() {
return "test";
}
}));
}
Future<Iterable<String>> futureList = sequence(listFutures);
Future<Iterable<String>> futureList = ff.sequence(listFutures, t);
assertEquals(futureList.get(), listExpected);
}
@ -174,14 +178,14 @@ public class JavaFutureTests {
for (int i = 0; i < 10; i++) {
expected.append("test");
listFutures.add(future(new Callable<String>() {
listFutures.add(ff.future(new Callable<String>() {
public String call() {
return "test";
}
}));
}
Future<String> result = fold("", 15000,listFutures, new Function2<String,String,String>() {
Future<String> result = ff.fold("", 15000,listFutures, new Function2<String,String,String>() {
public String apply(String r, String t) {
return r + t;
}
@ -196,14 +200,14 @@ public class JavaFutureTests {
for (int i = 0; i < 10; i++) {
expected.append("test");
listFutures.add(future(new Callable<String>() {
listFutures.add(ff.future(new Callable<String>() {
public String call() {
return "test";
}
}));
}
Future<String> result = reduce(listFutures, 15000, new Function2<String,String,String>() {
Future<String> result = ff.reduce(listFutures, 15000, new Function2<String,String,String>() {
public String apply(String r, String t) {
return r + t;
}
@ -221,9 +225,9 @@ public class JavaFutureTests {
listStrings.add("test");
}
Future<Iterable<String>> result = traverse(listStrings, new Function<String,Future<String>>() {
Future<Iterable<String>> result = ff.traverse(listStrings, t, new Function<String,Future<String>>() {
public Future<String> apply(final String r) {
return future(new Callable<String>() {
return ff.future(new Callable<String>() {
public String call() {
return r.toUpperCase();
}
@ -238,18 +242,18 @@ public class JavaFutureTests {
LinkedList<Future<Integer>> listFutures = new LinkedList<Future<Integer>>();
for (int i = 0; i < 10; i++) {
final Integer fi = i;
listFutures.add(future(new Callable<Integer>() {
listFutures.add(ff.future(new Callable<Integer>() {
public Integer call() {
return fi;
}
}));
}
final Integer expect = 5;
Future<Option<Integer>> f = Futures.find(listFutures, new Function<Integer,Boolean>() {
Future<Option<Integer>> f = ff.find(listFutures, new Function<Integer,Boolean>() {
public Boolean apply(Integer i) {
return i == 5;
}
}, Timeout.getDefault());
}, t);
final Integer got = f.get().get();
assertEquals(expect, got);

View file

@ -65,16 +65,16 @@ class ActorFireForgetRequestReplySpec extends AkkaSpec with BeforeAndAfterEach {
"An Actor" must {
"reply to bang message using reply" in {
val replyActor = actorOf[ReplyActor]
val senderActor = actorOf(new SenderActor(replyActor))
val replyActor = createActor[ReplyActor]
val senderActor = createActor(new SenderActor(replyActor))
senderActor ! "Init"
state.finished.await
state.s must be("Reply")
}
"reply to bang message using implicit sender" in {
val replyActor = actorOf[ReplyActor]
val senderActor = actorOf(new SenderActor(replyActor))
val replyActor = createActor[ReplyActor]
val senderActor = createActor(new SenderActor(replyActor))
senderActor ! "InitImplicit"
state.finished.await
state.s must be("ReplyImplicit")
@ -82,8 +82,8 @@ class ActorFireForgetRequestReplySpec extends AkkaSpec with BeforeAndAfterEach {
"should shutdown crashed temporary actor" in {
filterEvents(EventFilter[Exception]("Expected")) {
val supervisor = actorOf(Props[Supervisor].withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(0))))
val actor = actorOf(Props[CrashingActor].withSupervisor(supervisor))
val supervisor = createActor(Props[Supervisor].withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(0))))
val actor = createActor(Props[CrashingActor].withSupervisor(supervisor))
actor.isShutdown must be(false)
actor ! "Die"
state.finished.await

View file

@ -4,7 +4,7 @@
package akka.actor
import org.scalatest.{ WordSpec, BeforeAndAfterAll, BeforeAndAfterEach }
import org.scalatest.BeforeAndAfterEach
import org.scalatest.matchers.MustMatchers
import akka.actor.Actor._
@ -16,7 +16,7 @@ object ActorLifeCycleSpec {
}
class ActorLifeCycleSpec extends WordSpec with MustMatchers with TestKit with BeforeAndAfterEach {
class ActorLifeCycleSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSender {
import ActorLifeCycleSpec._
class LifeCycleTestActor(id: String, generationProvider: AtomicInteger) extends Actor {
@ -33,9 +33,9 @@ class ActorLifeCycleSpec extends WordSpec with MustMatchers with TestKit with Be
"invoke preRestart, preStart, postRestart when using OneForOneStrategy" in {
filterException[ActorKilledException] {
val id = newUuid().toString
val supervisor = actorOf(Props(self { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(3))))
val supervisor = createActor(Props(self { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(3))))
val gen = new AtomicInteger(0)
val restarter = actorOf(Props(new LifeCycleTestActor(id, gen) {
val restarter = createActor(Props(new LifeCycleTestActor(id, gen) {
override def preRestart(reason: Throwable, message: Option[Any]) { report("preRestart") }
override def postRestart(reason: Throwable) { report("postRestart") }
}).withSupervisor(supervisor))
@ -66,9 +66,9 @@ class ActorLifeCycleSpec extends WordSpec with MustMatchers with TestKit with Be
"default for preRestart and postRestart is to call postStop and preStart respectively" in {
filterException[ActorKilledException] {
val id = newUuid().toString
val supervisor = actorOf(Props(self { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(3))))
val supervisor = createActor(Props(self { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(3))))
val gen = new AtomicInteger(0)
val restarter = actorOf(Props(new LifeCycleTestActor(id, gen)).withSupervisor(supervisor))
val restarter = createActor(Props(new LifeCycleTestActor(id, gen)).withSupervisor(supervisor))
expectMsg(("preStart", id, 0))
restarter ! Kill
@ -95,9 +95,9 @@ class ActorLifeCycleSpec extends WordSpec with MustMatchers with TestKit with Be
"not invoke preRestart and postRestart when never restarted using OneForOneStrategy" in {
val id = newUuid().toString
val supervisor = actorOf(Props(self { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(3))))
val supervisor = createActor(Props(self { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(3))))
val gen = new AtomicInteger(0)
val a = actorOf(Props(new LifeCycleTestActor(id, gen)).withSupervisor(supervisor))
val a = createActor(Props(new LifeCycleTestActor(id, gen)).withSupervisor(supervisor))
expectMsg(("preStart", id, 0))
a ! "status"
expectMsg(("OK", id, 0))

View file

@ -12,7 +12,6 @@ import akka.util.duration._
import akka.testkit.Testing.sleepFor
import java.lang.IllegalStateException
import akka.util.ReflectiveAccess
import akka.actor.Actor.actorOf
import akka.dispatch.{ DefaultPromise, Promise, Future }
import java.util.concurrent.{ CountDownLatch, TimeUnit }
@ -28,11 +27,11 @@ object ActorRefSpec {
def receive = {
case "complexRequest" {
replyTo = channel
val worker = actorOf(Props[WorkerActor])
val worker = context.createActor(Props[WorkerActor])
worker ! "work"
}
case "complexRequest2"
val worker = actorOf(Props[WorkerActor])
val worker = context.createActor(Props[WorkerActor])
worker ! ReplyTo(channel)
case "workDone" replyTo ! "complexReply"
case "simpleRequest" reply("simpleReply")
@ -113,7 +112,7 @@ object ActorRefSpec {
}
}
class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
class ActorRefSpec extends AkkaSpec {
import akka.actor.ActorRefSpec._
def promiseIntercept(f: Actor)(to: Promise[Actor]): Actor = try {
@ -135,7 +134,7 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
"An ActorRef" must {
"not allow Actors to be created outside of an actorOf" in {
"not allow Actors to be created outside of an createActor" in {
intercept[akka.actor.ActorInitializationException] {
new Actor { def receive = { case _ } }
}
@ -145,7 +144,7 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
filterException[akka.actor.ActorInitializationException] {
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new Actor {
createActor(new Actor {
val nested = promiseIntercept(new Actor { def receive = { case _ } })(result)
def receive = { case _ }
}))
@ -155,49 +154,49 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(promiseIntercept(new FailingOuterActor(actorOf(new InnerActor)))(result)))
createActor(promiseIntercept(new FailingOuterActor(createActor(new InnerActor)))(result)))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new OuterActor(actorOf(promiseIntercept(new FailingInnerActor)(result)))))
createActor(new OuterActor(createActor(promiseIntercept(new FailingInnerActor)(result)))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(promiseIntercept(new FailingInheritingOuterActor(actorOf(new InnerActor)))(result)))
createActor(promiseIntercept(new FailingInheritingOuterActor(createActor(new InnerActor)))(result)))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new FailingOuterActor(actorOf(promiseIntercept(new FailingInheritingInnerActor)(result)))))
createActor(new FailingOuterActor(createActor(promiseIntercept(new FailingInheritingInnerActor)(result)))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new FailingInheritingOuterActor(actorOf(promiseIntercept(new FailingInheritingInnerActor)(result)))))
createActor(new FailingInheritingOuterActor(createActor(promiseIntercept(new FailingInheritingInnerActor)(result)))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new FailingInheritingOuterActor(actorOf(promiseIntercept(new FailingInnerActor)(result)))))
createActor(new FailingInheritingOuterActor(createActor(promiseIntercept(new FailingInnerActor)(result)))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new OuterActor(actorOf(new InnerActor {
createActor(new OuterActor(createActor(new InnerActor {
val a = promiseIntercept(new InnerActor)(result)
}))))
}
@ -206,21 +205,21 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new FailingOuterActor(actorOf(promiseIntercept(new FailingInheritingInnerActor)(result)))))
createActor(new FailingOuterActor(createActor(promiseIntercept(new FailingInheritingInnerActor)(result)))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new OuterActor(actorOf(promiseIntercept(new FailingInheritingInnerActor)(result)))))
createActor(new OuterActor(createActor(promiseIntercept(new FailingInheritingInnerActor)(result)))))
}
contextStackMustBeEmpty
intercept[akka.actor.ActorInitializationException] {
wrap(result
actorOf(new OuterActor(actorOf(promiseIntercept({ new InnerActor; new InnerActor })(result)))))
createActor(new OuterActor(createActor(promiseIntercept({ new InnerActor; new InnerActor })(result)))))
}
contextStackMustBeEmpty
@ -229,7 +228,7 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
filterException[java.lang.IllegalStateException] {
(intercept[java.lang.IllegalStateException] {
wrap(result
actorOf(new OuterActor(actorOf(promiseIntercept({ throw new IllegalStateException("Ur state be b0rked"); new InnerActor })(result)))))
createActor(new OuterActor(createActor(promiseIntercept({ throw new IllegalStateException("Ur state be b0rked"); new InnerActor })(result)))))
}).getMessage must be === "Ur state be b0rked"
contextStackMustBeEmpty
@ -237,7 +236,7 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
}
"be serializable using Java Serialization on local node" in {
val a = actorOf[InnerActor]
val a = createActor[InnerActor]
import java.io._
@ -258,23 +257,22 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
}
"must throw exception on deserialize if not present in local registry and remoting is not enabled" in {
ReflectiveAccess.RemoteModule.isEnabled must be === false
app.reflective.RemoteModule.isEnabled must be === false
val latch = new CountDownLatch(1)
val a = actorOf(new InnerActor {
val a = createActor(new InnerActor {
override def postStop {
Actor.registry.unregister(self)
app.registry.unregister(self)
latch.countDown
}
})
val inetAddress = ReflectiveAccess.RemoteModule.configDefaultAddress
val inetAddress = app.reflective.RemoteModule.configDefaultAddress
val expectedSerializedRepresentation = SerializedActorRef(
a.uuid,
a.address,
inetAddress.getAddress.getHostAddress,
inetAddress.getPort,
a.timeout)
inetAddress.getPort)
import java.io._
@ -295,9 +293,9 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
}).getMessage must be === "Trying to deserialize ActorRef [" + expectedSerializedRepresentation + "] but it's not found in the local registry and remoting is not enabled."
}
"support nested actorOfs" in {
val a = actorOf(new Actor {
val nested = actorOf(new Actor { def receive = { case _ } })
"support nested createActors" in {
val a = createActor(new Actor {
val nested = createActor(new Actor { def receive = { case _ } })
def receive = { case _ reply(nested) }
})
@ -307,8 +305,8 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
(a ne nested) must be === true
}
"support advanced nested actorOfs" in {
val a = actorOf(Props(new OuterActor(actorOf(Props(new InnerActor)))))
"support advanced nested createActors" in {
val a = createActor(Props(new OuterActor(createActor(Props(new InnerActor)))))
val inner = (a ? "innerself").as[Any].get
(a ? a).as[ActorRef].get must be(a)
@ -319,8 +317,8 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
}
"support reply via channel" in {
val serverRef = actorOf(Props[ReplyActor])
val clientRef = actorOf(Props(new SenderActor(serverRef)))
val serverRef = createActor(Props[ReplyActor])
val clientRef = createActor(Props(new SenderActor(serverRef)))
clientRef ! "complex"
clientRef ! "simple"
@ -344,7 +342,7 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
"stop when sent a poison pill" in {
val timeout = Timeout(20000)
val ref = actorOf(Props(new Actor {
val ref = createActor(Props(new Actor {
def receive = {
case 5 tryReply("five")
case null tryReply("null")
@ -369,9 +367,9 @@ class ActorRefSpec extends WordSpec with MustMatchers with TestKit {
filterException[ActorKilledException] {
val latch = new CountDownLatch(2)
val boss = actorOf(Props(new Actor {
val boss = createActor(Props(new Actor {
val ref = actorOf(
val ref = createActor(
Props(new Actor {
def receive = { case _ }
override def preRestart(reason: Throwable, msg: Option[Any]) = latch.countDown()

View file

@ -1,128 +0,0 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach }
import akka.testkit._
import Actor._
import java.util.concurrent.{ ConcurrentLinkedQueue, CyclicBarrier, TimeUnit, CountDownLatch }
import akka.dispatch.Future
object ActorRegistrySpec {
class TestActor extends Actor {
def receive = {
case "ping" reply("got ping")
}
}
class StartStopTestActor(startedLatch: TestLatch, stoppedLatch: TestLatch) extends Actor {
override def preStart = {
startedLatch.countDown
}
def receive = {
case "ping" reply("got ping")
}
override def postStop = {
stoppedLatch.countDown
}
}
}
class ActorRegistrySpec extends WordSpec with MustMatchers with BeforeAndAfterAll with BeforeAndAfterEach {
import ActorRegistrySpec._
override def afterAll = {
Actor.registry.local.shutdownAll
akka.event.EventHandler.start()
}
override def beforeEach = {
Actor.registry.local.shutdownAll
}
"Actor Registry" must {
"get actor by address from registry" ignore {
val started = TestLatch(1)
val stopped = TestLatch(1)
val actor = actorOf(new StartStopTestActor(started, stopped), "test-actor-1")
started.await()
val registered = Actor.registry.actorFor(actor.address)
registered.isDefined must be(true)
registered.get.address must be(actor.address)
registered.get.address must be("test-actor-1")
registered.get.stop
stopped.await
Actor.registry.actorFor(actor.address).isEmpty must be(true)
}
"get actor by uuid from local registry" ignore {
val started = TestLatch(1)
val stopped = TestLatch(1)
val actor = actorOf(new StartStopTestActor(started, stopped), "test-actor-1")
started.await
val uuid = actor.uuid
val registered = Actor.registry.local.actorFor(uuid)
registered.isDefined must be(true)
registered.get.uuid must be(uuid)
registered.get.address must be("test-actor-1")
actor.stop
stopped.await
Actor.registry.local.actorFor(uuid).isEmpty must be(true)
}
"find things from local registry" ignore {
val actor = actorOf[TestActor]("test-actor-1")
val found: Option[LocalActorRef] = Actor.registry.local.find({ case a: LocalActorRef if a.underlyingActorInstance.isInstanceOf[TestActor] a })
found.isDefined must be(true)
found.get.underlyingActorInstance.isInstanceOf[TestActor] must be(true)
found.get.address must be("test-actor-1")
actor.stop
}
"get all actors from local registry" ignore {
val actor1 = actorOf[TestActor]("test-actor-1")
val actor2 = actorOf[TestActor]("test-actor-2")
val actors = Actor.registry.local.actors
actors.size must be(2)
actors.find(_.address == "test-actor-2").get.asInstanceOf[LocalActorRef].underlyingActorInstance.isInstanceOf[TestActor] must be(true)
actors.find(_.address == "test-actor-1").get.asInstanceOf[LocalActorRef].underlyingActorInstance.isInstanceOf[TestActor] must be(true)
actor1.stop
actor2.stop
}
"get response from all actors in local registry using foreach" ignore {
val actor1 = actorOf[TestActor]("test-actor-1")
val actor2 = actorOf[TestActor]("test-actor-2")
val results = new ConcurrentLinkedQueue[Future[String]]
Actor.registry.local.foreach(actor results.add(actor.?("ping").mapTo[String]))
results.size must be(2)
val i = results.iterator
while (i.hasNext) assert(i.next.get === "got ping")
actor1.stop()
actor2.stop()
}
"shutdown all actors in local registry" ignore {
val actor1 = actorOf[TestActor]("test-actor-1")
val actor2 = actorOf[TestActor]("test-actor-2")
Actor.registry.local.shutdownAll
Actor.registry.local.actors.size must be(0)
}
"remove when unregistering actors from local registry" ignore {
val actor1 = actorOf[TestActor]("test-actor-1")
val actor2 = actorOf[TestActor]("test-actor-2")
Actor.registry.local.actors.size must be(2)
Actor.registry.unregister(actor1)
Actor.registry.local.actors.size must be(1)
Actor.registry.unregister(actor2)
Actor.registry.local.actors.size must be(0)
}
}
}

View file

@ -3,30 +3,26 @@
*/
package akka.actor
import org.scalatest.{ WordSpec, BeforeAndAfterAll }
import org.scalatest.matchers.MustMatchers
import akka.testkit.TestKit
import org.scalatest.BeforeAndAfterAll
import akka.dispatch.FutureTimeoutException
import akka.util.duration._
import akka.testkit.AkkaSpec
class ActorTimeoutSpec
extends WordSpec
with BeforeAndAfterAll
with MustMatchers
with TestKit {
class ActorTimeoutSpec extends AkkaSpec with BeforeAndAfterAll {
def actorWithTimeout(t: Timeout): ActorRef = Actor.actorOf(Props(creator = () new Actor {
def actorWithTimeout(t: Timeout): ActorRef = createActor(Props(creator = () new Actor {
def receive = {
case x
}
}, timeout = t))
val testTimeout = if (Timeout.default.duration < 400.millis) 500 millis else 100 millis
val defaultTimeout = app.AkkaConfig.TIMEOUT.duration
val testTimeout = if (app.AkkaConfig.TIMEOUT.duration < 400.millis) 500 millis else 100 millis
"An Actor-based Future" must {
"use the global default timeout if no implicit in scope" in {
within((Actor.TIMEOUT - 100).millis, (Actor.TIMEOUT + 400).millis) {
within(defaultTimeout - 100.millis, defaultTimeout + 400.millis) {
val echo = actorWithTimeout(Timeout(12))
try {
val f = echo ? "hallo"

View file

@ -5,7 +5,7 @@
*/
package akka.actor
import akka.actor.Actor._
import akka.AkkaApplication
object Chameneos {
@ -78,7 +78,7 @@ object Chameneos {
var numFaded = 0
override def preStart() = {
for (i 0 until numChameneos) actorOf(new Chameneo(self, colours(i % 3), i))
for (i 0 until numChameneos) context.createActor(new Chameneo(self, colours(i % 3), i))
}
def receive = {
@ -109,7 +109,7 @@ object Chameneos {
def run {
// System.setProperty("akka.config", "akka.conf")
Chameneos.start = System.currentTimeMillis
actorOf(new Mall(1000000, 4))
AkkaApplication().createActor(new Mall(1000000, 4))
Thread.sleep(10000)
println("Elapsed: " + (end - start))
}

View file

@ -4,12 +4,11 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.dispatch._
import akka.testkit.TestActorRef
import akka.testkit.AkkaSpec
class ChannelSpec extends WordSpec with MustMatchers {
class ChannelSpec extends AkkaSpec {
"A Channel" must {

View file

@ -1,14 +1,15 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.config.Config
import akka.testkit.AkkaSpec
class ClusterSpec extends WordSpec with MustMatchers {
class ClusterSpec extends AkkaSpec {
"ClusterSpec: A Deployer" must {
"be able to parse 'akka.actor.cluster._' config elements" in {
import Config.config._
// TODO: make it use its own special config?
val config = app.config
import config._
//akka.cluster
getString("akka.cluster.name") must equal(Some("test-cluster"))

View file

@ -4,20 +4,12 @@
package akka.actor
import org.scalatest.{ WordSpec, BeforeAndAfterAll, BeforeAndAfterEach }
import org.scalatest.matchers.MustMatchers
import akka.actor.Actor._
import org.scalatest.BeforeAndAfterEach
import akka.testkit._
import akka.util.duration._
import java.util.concurrent.atomic._
object DeathWatchSpec {
}
class DeathWatchSpec extends WordSpec with MustMatchers with TestKit with BeforeAndAfterEach {
import DeathWatchSpec._
class DeathWatchSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSender {
"The Death Watch" must {
def expectTerminationOf(actorRef: ActorRef) = expectMsgPF(5 seconds, "stopped") {
@ -25,7 +17,7 @@ class DeathWatchSpec extends WordSpec with MustMatchers with TestKit with Before
}
"notify with one Terminated message when an Actor is stopped" in {
val terminal = actorOf(Props(context { case _ context.self.stop() }))
val terminal = createActor(Props(context { case _ context.self.stop() }))
testActor link terminal
@ -38,8 +30,8 @@ class DeathWatchSpec extends WordSpec with MustMatchers with TestKit with Before
}
"notify with all monitors with one Terminated message when an Actor is stopped" in {
val monitor1, monitor2 = actorOf(Props(context { case t: Terminated testActor ! t }))
val terminal = actorOf(Props(context { case _ context.self.stop() }))
val monitor1, monitor2 = createActor(Props(context { case t: Terminated testActor ! t }))
val terminal = createActor(Props(context { case _ context.self.stop() }))
monitor1 link terminal
monitor2 link terminal
@ -58,8 +50,8 @@ class DeathWatchSpec extends WordSpec with MustMatchers with TestKit with Before
}
"notify with _current_ monitors with one Terminated message when an Actor is stopped" in {
val monitor1, monitor2 = actorOf(Props(context { case t: Terminated testActor ! t }))
val terminal = actorOf(Props(context { case _ context.self.stop() }))
val monitor1, monitor2 = createActor(Props(context { case t: Terminated testActor ! t }))
val terminal = createActor(Props(context { case _ context.self.stop() }))
monitor1 link terminal
monitor2 link terminal
@ -80,8 +72,8 @@ class DeathWatchSpec extends WordSpec with MustMatchers with TestKit with Before
"notify with a Terminated message once when an Actor is stopped but not when restarted" in {
filterException[ActorKilledException] {
val supervisor = actorOf(Props(context { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(2))))
val terminal = actorOf(Props(context { case x context.channel ! x }).withSupervisor(supervisor))
val supervisor = createActor(Props(context { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(2))))
val terminal = createActor(Props(context { case x context.channel ! x }).withSupervisor(supervisor))
testActor link terminal

View file

@ -4,15 +4,14 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit.AkkaSpec
import DeploymentConfig._
class DeployerSpec extends WordSpec with MustMatchers {
class DeployerSpec extends AkkaSpec {
"A Deployer" must {
"be able to parse 'akka.actor.deployment._' config elements" in {
val deployment = Deployer.lookupInConfig("service-ping")
val deployment = app.deployer.lookupInConfig("service-ping")
deployment must be('defined)
deployment must equal(Some(
@ -22,7 +21,7 @@ class DeployerSpec extends WordSpec with MustMatchers {
LeastCPU,
NrOfInstances(3),
BannagePeriodFailureDetector(10),
RemoteScope(List(
app.deployment.RemoteScope(List(
RemoteAddress("wallace", 2552), RemoteAddress("gromit", 2552))))))
// ClusterScope(
// List(Node("node1")),

View file

@ -4,8 +4,7 @@
package akka.actor
import org.scalatest.{ WordSpec, BeforeAndAfterAll, BeforeAndAfterEach }
import org.scalatest.matchers.MustMatchers
import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach }
import akka.testkit._
import TestEvent.{ Mute, UnMuteAll }
@ -97,7 +96,7 @@ object FSMActorSpec {
case class CodeState(soFar: String, code: String)
}
class FSMActorSpec extends WordSpec with MustMatchers with TestKit with BeforeAndAfterAll with BeforeAndAfterEach {
class FSMActorSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAndAfterEach with ImplicitSender {
import FSMActorSpec._
val eh_level = EventHandler.level
@ -134,9 +133,9 @@ class FSMActorSpec extends WordSpec with MustMatchers with TestKit with BeforeAn
"unlock the lock" in {
// lock that locked after being open for 1 sec
val lock = Actor.actorOf(new Lock("33221", 1 second))
val lock = createActor(new Lock("33221", 1 second))
val transitionTester = Actor.actorOf(new Actor {
val transitionTester = createActor(new Actor {
def receive = {
case Transition(_, _, _) transitionCallBackLatch.open
case CurrentState(_, Locked) initialStateLatch.open
@ -168,7 +167,7 @@ class FSMActorSpec extends WordSpec with MustMatchers with TestKit with BeforeAn
val answerLatch = TestLatch()
object Hello
object Bye
val tester = Actor.actorOf(new Actor {
val tester = createActor(new Actor {
protected def receive = {
case Hello lock ! "hello"
case "world" answerLatch.open
@ -189,7 +188,7 @@ class FSMActorSpec extends WordSpec with MustMatchers with TestKit with BeforeAn
case Ev("go") goto(2)
}
})
logger = Actor.actorOf(new Actor {
logger = createActor(new Actor {
def receive = {
case x testActor forward x
}
@ -211,7 +210,7 @@ class FSMActorSpec extends WordSpec with MustMatchers with TestKit with BeforeAn
case x testActor ! x
}
}
val ref = Actor.actorOf(fsm)
val ref = createActor(fsm)
started.await
ref.stop()
expectMsg(1 second, fsm.StopEvent(Shutdown, 1, null))
@ -235,7 +234,7 @@ class FSMActorSpec extends WordSpec with MustMatchers with TestKit with BeforeAn
}
})
val fsm = fsmref.underlyingActor
logger = Actor.actorOf(new Actor {
logger = createActor(new Actor {
def receive = {
case x testActor forward x
}

View file

@ -4,18 +4,15 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit.TestKit
import akka.testkit.{ AkkaSpec, ImplicitSender }
import akka.util.Duration
import akka.util.duration._
class FSMTimingSpec extends WordSpec with MustMatchers with TestKit {
class FSMTimingSpec extends AkkaSpec with ImplicitSender {
import FSMTimingSpec._
import FSM._
val fsm = Actor.actorOf(new StateMachine(testActor))
val fsm = createActor(new StateMachine(testActor))
fsm ! SubscribeTransitionCallBack(testActor)
expectMsg(200 millis, CurrentState(fsm, Initial))

View file

@ -3,10 +3,6 @@
*/
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit._
import akka.testkit._
import akka.util.duration._
import akka.event.EventHandler
@ -40,14 +36,14 @@ object FSMTransitionSpec {
}
class FSMTransitionSpec extends WordSpec with MustMatchers with TestKit {
class FSMTransitionSpec extends AkkaSpec with ImplicitSender {
import FSMTransitionSpec._
"A FSM transition notifier" must {
"notify listeners" in {
val fsm = Actor.actorOf(new MyFSM(testActor))
val fsm = createActor(new MyFSM(testActor))
within(1 second) {
fsm ! SubscribeTransitionCallBack(testActor)
expectMsg(CurrentState(fsm, 0))
@ -59,9 +55,9 @@ class FSMTransitionSpec extends WordSpec with MustMatchers with TestKit {
}
"not fail when listener goes away" in {
val forward = Actor.actorOf(new Forwarder(testActor))
val fsm = Actor.actorOf(new MyFSM(testActor))
val sup = Actor.actorOf(Props[Supervisor].withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), None, None)))
val forward = createActor(new Forwarder(testActor))
val fsm = createActor(new MyFSM(testActor))
val sup = createActor(Props[Supervisor].withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), None, None)))
sup link fsm
within(300 millis) {
fsm ! SubscribeTransitionCallBack(forward)

View file

@ -4,24 +4,21 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit._
import akka.util.duration._
import Actor._
import akka.util.Duration
import akka.AkkaApplication
object ForwardActorSpec {
val ExpectedMessage = "FOO"
def createForwardingChain(): ActorRef = {
val replier = actorOf(new Actor {
def createForwardingChain(app: AkkaApplication): ActorRef = {
val replier = app.createActor(new Actor {
def receive = { case x reply(x) }
})
def mkforwarder(forwardTo: ActorRef) = actorOf(
def mkforwarder(forwardTo: ActorRef) = app.createActor(
new Actor {
def receive = { case x forwardTo forward x }
})
@ -30,7 +27,7 @@ object ForwardActorSpec {
}
}
class ForwardActorSpec extends WordSpec with MustMatchers {
class ForwardActorSpec extends AkkaSpec {
import ForwardActorSpec._
"A Forward Actor" must {
@ -38,16 +35,16 @@ class ForwardActorSpec extends WordSpec with MustMatchers {
"forward actor reference when invoking forward on bang" in {
val latch = new TestLatch(1)
val replyTo = actorOf(new Actor { def receive = { case ExpectedMessage latch.countDown() } })
val replyTo = createActor(new Actor { def receive = { case ExpectedMessage latch.countDown() } })
val chain = createForwardingChain()
val chain = createForwardingChain(app)
chain.tell(ExpectedMessage, replyTo)
latch.await(Duration(5, "s")) must be === true
}
"forward actor reference when invoking forward on bang bang" in {
val chain = createForwardingChain()
val chain = createForwardingChain(app)
chain.ask(ExpectedMessage, 5000).get must be === ExpectedMessage
}
}

View file

@ -4,14 +4,9 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit._
import Actor._
class HotSwapSpec extends WordSpec with MustMatchers {
class HotSwapSpec extends AkkaSpec {
"An Actor" must {
@ -19,7 +14,7 @@ class HotSwapSpec extends WordSpec with MustMatchers {
val barrier = TestBarrier(2)
@volatile
var _log = ""
val a = actorOf(new Actor {
val a = createActor(new Actor {
def receive = { case _ _log += "default" }
})
a ! HotSwap(self {
@ -36,7 +31,7 @@ class HotSwapSpec extends WordSpec with MustMatchers {
val barrier = TestBarrier(2)
@volatile
var _log = ""
val a = actorOf(new Actor {
val a = createActor(new Actor {
def receive = {
case "init"
_log += "init"
@ -65,7 +60,7 @@ class HotSwapSpec extends WordSpec with MustMatchers {
val barrier = TestBarrier(2)
@volatile
var _log = ""
val a = actorOf(new Actor {
val a = createActor(new Actor {
def receive = {
case "init"
_log += "init"
@ -111,7 +106,7 @@ class HotSwapSpec extends WordSpec with MustMatchers {
val barrier = TestBarrier(2)
@volatile
var _log = ""
val a = actorOf(new Actor {
val a = createActor(new Actor {
def receive = {
case "init"
_log += "init"

View file

@ -4,8 +4,6 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import org.scalatest.BeforeAndAfterEach
import akka.util.ByteString
@ -24,7 +22,7 @@ object IOActorSpec {
started.open()
}
def createWorker = Actor.actorOf(Props(new Actor with IO {
def createWorker = context.createActor(Props(new Actor with IO {
def receiveIO = {
case NewClient(server)
val socket = server.accept()
@ -45,7 +43,7 @@ object IOActorSpec {
class SimpleEchoClient(host: String, port: Int, ioManager: ActorRef) extends Actor with IO {
lazy val socket: SocketHandle = connect(ioManager, host, port, reader)
lazy val reader: ActorRef = Actor.actorOf {
lazy val reader: ActorRef = context.createActor {
new Actor with IO {
def receiveIO = {
case length: Int
@ -72,7 +70,7 @@ object IOActorSpec {
started.open()
}
def createWorker = Actor.actorOf(Props(new Actor with IO {
def createWorker = context.createActor(Props(new Actor with IO {
def receiveIO = {
case NewClient(server)
val socket = server.accept()
@ -170,16 +168,16 @@ object IOActorSpec {
}
class IOActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach {
class IOActorSpec extends AkkaSpec with BeforeAndAfterEach {
import IOActorSpec._
"an IO Actor" must {
"run echo server" in {
val started = TestLatch(1)
val ioManager = Actor.actorOf(new IOManager(2)) // teeny tiny buffer
val server = Actor.actorOf(new SimpleEchoServer("localhost", 8064, ioManager, started))
val ioManager = createActor(new IOManager(2)) // teeny tiny buffer
val server = createActor(new SimpleEchoServer("localhost", 8064, ioManager, started))
started.await
val client = Actor.actorOf(new SimpleEchoClient("localhost", 8064, ioManager))
val client = createActor(new SimpleEchoClient("localhost", 8064, ioManager))
val f1 = client ? ByteString("Hello World!1")
val f2 = client ? ByteString("Hello World!2")
val f3 = client ? ByteString("Hello World!3")
@ -193,10 +191,10 @@ class IOActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach {
"run echo server under high load" in {
val started = TestLatch(1)
val ioManager = Actor.actorOf(new IOManager())
val server = Actor.actorOf(new SimpleEchoServer("localhost", 8065, ioManager, started))
val ioManager = createActor(new IOManager())
val server = createActor(new SimpleEchoServer("localhost", 8065, ioManager, started))
started.await
val client = Actor.actorOf(new SimpleEchoClient("localhost", 8065, ioManager))
val client = createActor(new SimpleEchoClient("localhost", 8065, ioManager))
val list = List.range(0, 1000)
val f = Future.traverse(list)(i client ? ByteString(i.toString))
assert(f.get.size === 1000)
@ -207,10 +205,10 @@ class IOActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach {
"run echo server under high load with small buffer" in {
val started = TestLatch(1)
val ioManager = Actor.actorOf(new IOManager(2))
val server = Actor.actorOf(new SimpleEchoServer("localhost", 8066, ioManager, started))
val ioManager = createActor(new IOManager(2))
val server = createActor(new SimpleEchoServer("localhost", 8066, ioManager, started))
started.await
val client = Actor.actorOf(new SimpleEchoClient("localhost", 8066, ioManager))
val client = createActor(new SimpleEchoClient("localhost", 8066, ioManager))
val list = List.range(0, 1000)
val f = Future.traverse(list)(i client ? ByteString(i.toString))
assert(f.get.size === 1000)
@ -221,11 +219,11 @@ class IOActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach {
"run key-value store" in {
val started = TestLatch(1)
val ioManager = Actor.actorOf(new IOManager(2)) // teeny tiny buffer
val server = Actor.actorOf(new KVStore("localhost", 8067, ioManager, started))
val ioManager = createActor(new IOManager(2)) // teeny tiny buffer
val server = createActor(new KVStore("localhost", 8067, ioManager, started))
started.await
val client1 = Actor.actorOf(new KVClient("localhost", 8067, ioManager))
val client2 = Actor.actorOf(new KVClient("localhost", 8067, ioManager))
val client1 = createActor(new KVClient("localhost", 8067, ioManager))
val client2 = createActor(new KVClient("localhost", 8067, ioManager))
val f1 = client1 ? (('set, "hello", ByteString("World")))
val f2 = client1 ? (('set, "test", ByteString("No one will read me")))
val f3 = client1 ? (('get, "hello"))

View file

@ -4,13 +4,9 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit._
import akka.util.duration._
import akka.testkit.Testing.sleepFor
import akka.actor.Actor._
import java.util.concurrent.{ TimeUnit, CountDownLatch }
@ -23,13 +19,13 @@ object LocalActorRefProviderSpec {
}
}
class LocalActorRefProviderSpec extends WordSpec with MustMatchers {
class LocalActorRefProviderSpec extends AkkaSpec {
import akka.actor.LocalActorRefProviderSpec._
"An LocalActorRefProvider" must {
"only create one instance of an actor with a specific address in a concurrent environment" in {
val provider = new LocalActorRefProvider
val provider = app.provider
for (i 0 until 100) { // 100 concurrent runs
val latch = new CountDownLatch(4)
@ -42,19 +38,19 @@ class LocalActorRefProviderSpec extends WordSpec with MustMatchers {
val address = "new-actor" + i
spawn {
a1 = provider.actorOf(Props(creator = () new NewActor), address, false)
a1 = provider.actorOf(Props(creator = () new NewActor), address)
latch.countDown()
}
spawn {
a2 = provider.actorOf(Props(creator = () new NewActor), address, false)
a2 = provider.actorOf(Props(creator = () new NewActor), address)
latch.countDown()
}
spawn {
a3 = provider.actorOf(Props(creator = () new NewActor), address, false)
a3 = provider.actorOf(Props(creator = () new NewActor), address)
latch.countDown()
}
spawn {
a4 = provider.actorOf(Props(creator = () new NewActor), address, false)
a4 = provider.actorOf(Props(creator = () new NewActor), address)
latch.countDown()
}

View file

@ -3,13 +3,11 @@
*/
package akka.actor
import org.scalatest.{ WordSpec, BeforeAndAfterAll, BeforeAndAfterEach }
import org.scalatest.matchers.MustMatchers
import akka.testkit.{ TestKit, TestActorRef, EventFilter, TestEvent }
import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach }
import akka.testkit.{ TestKit, TestActorRef, EventFilter, TestEvent, ImplicitSender }
import akka.event.EventHandler
import Actor._
import akka.util.duration._
import akka.config.Config.config
import akka.testkit.AkkaSpec
object LoggingReceiveSpec {
class TestLogActor extends Actor {
@ -17,12 +15,7 @@ object LoggingReceiveSpec {
}
}
class LoggingReceiveSpec
extends WordSpec
with BeforeAndAfterEach
with BeforeAndAfterAll
with MustMatchers
with TestKit {
class LoggingReceiveSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfterAll with ImplicitSender {
import LoggingReceiveSpec._
val level = EventHandler.level
@ -68,10 +61,10 @@ class LoggingReceiveSpec
"A LoggingReceive" must {
"decorate a Receive" in {
val r: Receive = {
val r: Actor.Receive = {
case null
}
val log = LoggingReceive(this, r)
val log = Actor.LoggingReceive(this, r)
log.isDefinedAt("hallo")
expectMsg(1 second, EventHandler.Debug(this, "received unhandled message hallo"))
}
@ -90,7 +83,7 @@ class LoggingReceiveSpec
expectMsg(EventHandler.Debug(actor.underlyingActor, "received handled message buh"))
expectMsg("x")
}
val r: Receive = {
val r: Actor.Receive = {
case null
}
actor ! HotSwap(_ r, false)

View file

@ -4,24 +4,19 @@
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit._
import akka.util.duration._
import Actor._
import java.util.concurrent.atomic.AtomicInteger
class ReceiveTimeoutSpec extends WordSpec with MustMatchers {
import Actor._
class ReceiveTimeoutSpec extends AkkaSpec {
"An actor with receive timeout" must {
"get timeout" in {
val timeoutLatch = TestLatch()
val timeoutActor = actorOf(new Actor {
val timeoutActor = createActor(new Actor {
receiveTimeout = Some(500L)
protected def receive = {
@ -36,7 +31,7 @@ class ReceiveTimeoutSpec extends WordSpec with MustMatchers {
"get timeout when swapped" in {
val timeoutLatch = TestLatch()
val timeoutActor = actorOf(new Actor {
val timeoutActor = createActor(new Actor {
receiveTimeout = Some(500L)
protected def receive = {
@ -60,7 +55,7 @@ class ReceiveTimeoutSpec extends WordSpec with MustMatchers {
val timeoutLatch = TestLatch()
case object Tick
val timeoutActor = actorOf(new Actor {
val timeoutActor = createActor(new Actor {
receiveTimeout = Some(500L)
protected def receive = {
@ -80,7 +75,7 @@ class ReceiveTimeoutSpec extends WordSpec with MustMatchers {
val timeoutLatch = TestLatch()
case object Tick
val timeoutActor = actorOf(new Actor {
val timeoutActor = createActor(new Actor {
receiveTimeout = Some(500L)
protected def receive = {
@ -102,7 +97,7 @@ class ReceiveTimeoutSpec extends WordSpec with MustMatchers {
"not receive timeout message when not specified" in {
val timeoutLatch = TestLatch()
val timeoutActor = actorOf(new Actor {
val timeoutActor = createActor(new Actor {
protected def receive = {
case ReceiveTimeout timeoutLatch.open
}

View file

@ -5,19 +5,15 @@
package akka.actor
import java.lang.Thread.sleep
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import org.scalatest.BeforeAndAfterAll
import akka.event.EventHandler
import akka.testkit.TestEvent._
import akka.testkit.EventFilter
import Actor._
import java.util.concurrent.{ TimeUnit, CountDownLatch }
import org.multiverse.api.latches.StandardLatch
import akka.testkit.AkkaSpec
class RestartStrategySpec extends JUnitSuite with BeforeAndAfterAll {
class RestartStrategySpec extends AkkaSpec with BeforeAndAfterAll {
override def beforeAll() {
EventHandler.notify(Mute(EventFilter[Exception]("Crashing...")))
@ -30,244 +26,238 @@ class RestartStrategySpec extends JUnitSuite with BeforeAndAfterAll {
object Ping
object Crash
@Test
def slaveShouldStayDeadAfterMaxRestartsWithinTimeRange = {
"A RestartStrategy" must {
val boss = actorOf(Props(new Actor {
protected def receive = { case _ () }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), 2, 1000)))
"ensure that slave stays dead after max restarts within time range" in {
val boss = createActor(Props(new Actor {
protected def receive = { case _ () }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), 2, 1000)))
val restartLatch = new StandardLatch
val secondRestartLatch = new StandardLatch
val countDownLatch = new CountDownLatch(3)
val stopLatch = new StandardLatch
val restartLatch = new StandardLatch
val secondRestartLatch = new StandardLatch
val countDownLatch = new CountDownLatch(3)
val stopLatch = new StandardLatch
val slave = actorOf(Props(new Actor {
val slave = createActor(Props(new Actor {
protected def receive = {
case Ping countDownLatch.countDown()
case Crash throw new Exception("Crashing...")
}
override def postRestart(reason: Throwable) = {
if (!restartLatch.isOpen)
restartLatch.open
else
secondRestartLatch.open
}
override def postStop() = {
stopLatch.open
}
}).withSupervisor(boss))
slave ! Ping
slave ! Crash
slave ! Ping
// test restart and post restart ping
assert(restartLatch.tryAwait(1, TimeUnit.SECONDS))
// now crash again... should not restart
slave ! Crash
slave ! Ping
assert(secondRestartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(countDownLatch.await(1, TimeUnit.SECONDS))
slave ! Crash
assert(stopLatch.tryAwait(1, TimeUnit.SECONDS))
}
@Test
def slaveShouldBeImmortalWithoutMaxRestartsAndTimeRange = {
val boss = actorOf(Props(new Actor {
def receive = { case _ () }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), None, None)))
val countDownLatch = new CountDownLatch(100)
val slave = actorOf(Props(new Actor {
protected def receive = {
case Crash throw new Exception("Crashing...")
}
override def postRestart(reason: Throwable) = {
countDownLatch.countDown()
}
}).withSupervisor(boss))
(1 to 100) foreach { _ slave ! Crash }
assert(countDownLatch.await(120, TimeUnit.SECONDS))
assert(!slave.isShutdown)
}
@Test
def slaveShouldRestartAfterNumberOfCrashesNotWithinTimeRange = {
val boss = actorOf(Props(new Actor {
def receive = { case _ () }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), 2, 500)))
val restartLatch = new StandardLatch
val secondRestartLatch = new StandardLatch
val thirdRestartLatch = new StandardLatch
val pingLatch = new StandardLatch
val secondPingLatch = new StandardLatch
val slave = actorOf(Props(new Actor {
protected def receive = {
case Ping
if (!pingLatch.isOpen) pingLatch.open else secondPingLatch.open
case Crash throw new Exception("Crashing...")
}
override def postRestart(reason: Throwable) = {
if (!restartLatch.isOpen)
restartLatch.open
else if (!secondRestartLatch.isOpen)
secondRestartLatch.open
else
thirdRestartLatch.open
}
override def postStop() = {
if (restartLatch.isOpen) {
secondRestartLatch.open
protected def receive = {
case Ping countDownLatch.countDown()
case Crash throw new Exception("Crashing...")
}
override def postRestart(reason: Throwable) = {
if (!restartLatch.isOpen)
restartLatch.open
else
secondRestartLatch.open
}
}
}).withSupervisor(boss))
slave ! Ping
slave ! Crash
override def postStop() = {
stopLatch.open
}
}).withSupervisor(boss))
assert(restartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(pingLatch.tryAwait(1, TimeUnit.SECONDS))
slave ! Ping
slave ! Crash
slave ! Ping
slave ! Ping
slave ! Crash
// test restart and post restart ping
assert(restartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(secondRestartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(secondPingLatch.tryAwait(1, TimeUnit.SECONDS))
// now crash again... should not restart
slave ! Crash
slave ! Ping
// sleep to go out of the restart strategy's time range
sleep(700L)
assert(secondRestartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(countDownLatch.await(1, TimeUnit.SECONDS))
// now crash again... should and post restart ping
slave ! Crash
slave ! Ping
slave ! Crash
assert(stopLatch.tryAwait(1, TimeUnit.SECONDS))
}
assert(thirdRestartLatch.tryAwait(1, TimeUnit.SECONDS))
"ensure that slave is immortal without max restarts and time range" in {
val boss = createActor(Props(new Actor {
def receive = { case _ () }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), None, None)))
assert(!slave.isShutdown)
}
val countDownLatch = new CountDownLatch(100)
@Test
def slaveShouldNotRestartAfterMaxRetries = {
val boss = actorOf(Props(new Actor {
def receive = { case _ () }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), Some(2), None)))
val slave = createActor(Props(new Actor {
val restartLatch = new StandardLatch
val secondRestartLatch = new StandardLatch
val countDownLatch = new CountDownLatch(3)
val stopLatch = new StandardLatch
protected def receive = {
case Crash throw new Exception("Crashing...")
}
val slave = actorOf(Props(new Actor {
override def postRestart(reason: Throwable) = {
countDownLatch.countDown()
}
}).withSupervisor(boss))
protected def receive = {
case Ping countDownLatch.countDown()
case Crash throw new Exception("Crashing...")
}
override def postRestart(reason: Throwable) = {
if (!restartLatch.isOpen)
(1 to 100) foreach { _ slave ! Crash }
assert(countDownLatch.await(120, TimeUnit.SECONDS))
assert(!slave.isShutdown)
}
"ensure that slave restarts after number of crashes not within time range" in {
val boss = createActor(Props(new Actor {
def receive = { case _ () }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), 2, 500)))
val restartLatch = new StandardLatch
val secondRestartLatch = new StandardLatch
val thirdRestartLatch = new StandardLatch
val pingLatch = new StandardLatch
val secondPingLatch = new StandardLatch
val slave = createActor(Props(new Actor {
protected def receive = {
case Ping
if (!pingLatch.isOpen) pingLatch.open else secondPingLatch.open
case Crash throw new Exception("Crashing...")
}
override def postRestart(reason: Throwable) = {
if (!restartLatch.isOpen)
restartLatch.open
else if (!secondRestartLatch.isOpen)
secondRestartLatch.open
else
thirdRestartLatch.open
}
override def postStop() = {
if (restartLatch.isOpen) {
secondRestartLatch.open
}
}
}).withSupervisor(boss))
slave ! Ping
slave ! Crash
assert(restartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(pingLatch.tryAwait(1, TimeUnit.SECONDS))
slave ! Ping
slave ! Crash
assert(secondRestartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(secondPingLatch.tryAwait(1, TimeUnit.SECONDS))
// sleep to go out of the restart strategy's time range
sleep(700L)
// now crash again... should and post restart ping
slave ! Crash
slave ! Ping
assert(thirdRestartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(!slave.isShutdown)
}
"ensure that slave is not restarted after max retries" in {
val boss = createActor(Props(new Actor {
def receive = { case _ () }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), Some(2), None)))
val restartLatch = new StandardLatch
val secondRestartLatch = new StandardLatch
val countDownLatch = new CountDownLatch(3)
val stopLatch = new StandardLatch
val slave = createActor(Props(new Actor {
protected def receive = {
case Ping countDownLatch.countDown()
case Crash throw new Exception("Crashing...")
}
override def postRestart(reason: Throwable) = {
if (!restartLatch.isOpen)
restartLatch.open
else
secondRestartLatch.open
}
override def postStop() = {
stopLatch.open
}
}).withSupervisor(boss))
slave ! Ping
slave ! Crash
slave ! Ping
// test restart and post restart ping
assert(restartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(!slave.isShutdown)
// now crash again... should not restart
slave ! Crash
slave ! Ping
assert(secondRestartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(countDownLatch.await(1, TimeUnit.SECONDS))
sleep(700L)
slave ! Crash
assert(stopLatch.tryAwait(1, TimeUnit.SECONDS))
sleep(500L)
assert(slave.isShutdown)
}
"ensure that slave is not restarted within time range" in {
val restartLatch, stopLatch, maxNoOfRestartsLatch = new StandardLatch
val countDownLatch = new CountDownLatch(2)
val boss = createActor(Props(new Actor {
def receive = { case t: Terminated maxNoOfRestartsLatch.open }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), None, Some(1000))))
val slave = createActor(Props(new Actor {
protected def receive = {
case Ping countDownLatch.countDown()
case Crash throw new Exception("Crashing...")
}
override def postRestart(reason: Throwable) = {
restartLatch.open
else
secondRestartLatch.open
}
}
override def postStop() = {
stopLatch.open
}
}).withSupervisor(boss))
override def postStop() = {
stopLatch.open
}
}).withSupervisor(boss))
slave ! Ping
slave ! Crash
slave ! Ping
boss.link(slave)
// test restart and post restart ping
assert(restartLatch.tryAwait(1, TimeUnit.SECONDS))
slave ! Ping
slave ! Crash
slave ! Ping
assert(!slave.isShutdown)
// test restart and post restart ping
assert(restartLatch.tryAwait(1, TimeUnit.SECONDS))
// now crash again... should not restart
slave ! Crash
slave ! Ping
assert(!slave.isShutdown)
assert(secondRestartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(countDownLatch.await(1, TimeUnit.SECONDS))
// now crash again... should not restart
slave ! Crash
sleep(700L)
// may not be running
slave ! Ping
assert(countDownLatch.await(1, TimeUnit.SECONDS))
slave ! Crash
assert(stopLatch.tryAwait(1, TimeUnit.SECONDS))
sleep(500L)
assert(slave.isShutdown)
}
// may not be running
slave ! Crash
@Test
def slaveShouldNotRestartWithinTimeRange = {
assert(stopLatch.tryAwait(1, TimeUnit.SECONDS))
val restartLatch, stopLatch, maxNoOfRestartsLatch = new StandardLatch
val countDownLatch = new CountDownLatch(2)
val boss = actorOf(Props(new Actor {
def receive = { case t: Terminated maxNoOfRestartsLatch.open }
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), None, Some(1000))))
val slave = actorOf(Props(new Actor {
protected def receive = {
case Ping countDownLatch.countDown()
case Crash throw new Exception("Crashing...")
}
override def postRestart(reason: Throwable) = {
restartLatch.open
}
override def postStop() = {
stopLatch.open
}
}).withSupervisor(boss))
boss.link(slave)
slave ! Ping
slave ! Crash
slave ! Ping
// test restart and post restart ping
assert(restartLatch.tryAwait(1, TimeUnit.SECONDS))
assert(!slave.isShutdown)
// now crash again... should not restart
slave ! Crash
// may not be running
slave ! Ping
assert(countDownLatch.await(1, TimeUnit.SECONDS))
// may not be running
slave ! Crash
assert(stopLatch.tryAwait(1, TimeUnit.SECONDS))
assert(maxNoOfRestartsLatch.tryAwait(1, TimeUnit.SECONDS))
sleep(500L)
assert(slave.isShutdown)
assert(maxNoOfRestartsLatch.tryAwait(1, TimeUnit.SECONDS))
sleep(500L)
assert(slave.isShutdown)
}
}
}

View file

@ -1,16 +1,14 @@
package akka.actor
import org.scalatest.junit.JUnitSuite
import org.scalatest.BeforeAndAfterEach
import akka.event.EventHandler
import akka.testkit.TestEvent._
import akka.testkit.EventFilter
import Actor._
import org.multiverse.api.latches.StandardLatch
import org.junit.{ Test, Before, After }
import java.util.concurrent.{ ScheduledFuture, ConcurrentLinkedQueue, CountDownLatch, TimeUnit }
import akka.testkit.AkkaSpec
class SchedulerSpec extends JUnitSuite {
class SchedulerSpec extends AkkaSpec with BeforeAndAfterEach {
private val futures = new ConcurrentLinkedQueue[ScheduledFuture[AnyRef]]()
def collectFuture(f: ScheduledFuture[AnyRef]): ScheduledFuture[AnyRef] = {
@ -19,120 +17,114 @@ class SchedulerSpec extends JUnitSuite {
future
}
@Before
def beforeEach {
override def beforeEach {
EventHandler.notify(Mute(EventFilter[Exception]("CRASH")))
}
@After
def afterEach {
override def afterEach {
while (futures.peek() ne null) { Option(futures.poll()).foreach(_.cancel(true)) }
Actor.registry.local.shutdownAll
app.registry.local.shutdownAll
EventHandler.start()
}
@Test
def schedulerShouldScheduleMoreThanOnce = {
"A Scheduler" must {
case object Tick
val countDownLatch = new CountDownLatch(3)
val tickActor = actorOf(new Actor {
def receive = { case Tick countDownLatch.countDown() }
})
// run every 50 millisec
collectFuture(Scheduler.schedule(tickActor, Tick, 0, 50, TimeUnit.MILLISECONDS))
"schedule more than once" in {
case object Tick
val countDownLatch = new CountDownLatch(3)
val tickActor = createActor(new Actor {
def receive = { case Tick countDownLatch.countDown() }
})
// run every 50 millisec
collectFuture(Scheduler.schedule(tickActor, Tick, 0, 50, TimeUnit.MILLISECONDS))
// after max 1 second it should be executed at least the 3 times already
assert(countDownLatch.await(1, TimeUnit.SECONDS))
// after max 1 second it should be executed at least the 3 times already
assert(countDownLatch.await(1, TimeUnit.SECONDS))
val countDownLatch2 = new CountDownLatch(3)
val countDownLatch2 = new CountDownLatch(3)
collectFuture(Scheduler.schedule(() countDownLatch2.countDown(), 0, 50, TimeUnit.MILLISECONDS))
collectFuture(Scheduler.schedule(() countDownLatch2.countDown(), 0, 50, TimeUnit.MILLISECONDS))
// after max 1 second it should be executed at least the 3 times already
assert(countDownLatch2.await(2, TimeUnit.SECONDS))
}
@Test
def schedulerShouldScheduleOnce = {
case object Tick
val countDownLatch = new CountDownLatch(3)
val tickActor = actorOf(new Actor {
def receive = { case Tick countDownLatch.countDown() }
})
// run every 50 millisec
collectFuture(Scheduler.scheduleOnce(tickActor, Tick, 50, TimeUnit.MILLISECONDS))
collectFuture(Scheduler.scheduleOnce(() countDownLatch.countDown(), 50, TimeUnit.MILLISECONDS))
// after 1 second the wait should fail
assert(countDownLatch.await(2, TimeUnit.SECONDS) == false)
// should still be 1 left
assert(countDownLatch.getCount == 1)
}
/**
* ticket #372
*/
@Test
def schedulerShouldntCreateActors = {
object Ping
val ticks = new CountDownLatch(1000)
val actor = actorOf(new Actor {
def receive = { case Ping ticks.countDown }
})
val numActors = Actor.registry.local.actors.length
(1 to 1000).foreach(_ collectFuture(Scheduler.scheduleOnce(actor, Ping, 1, TimeUnit.MILLISECONDS)))
assert(ticks.await(10, TimeUnit.SECONDS))
assert(Actor.registry.local.actors.length === numActors)
}
/**
* ticket #372
*/
@Test
def schedulerShouldBeCancellable = {
object Ping
val ticks = new CountDownLatch(1)
val actor = actorOf(new Actor {
def receive = { case Ping ticks.countDown() }
})
(1 to 10).foreach { i
val future = collectFuture(Scheduler.scheduleOnce(actor, Ping, 1, TimeUnit.SECONDS))
future.cancel(true)
// after max 1 second it should be executed at least the 3 times already
assert(countDownLatch2.await(2, TimeUnit.SECONDS))
}
assert(ticks.await(3, TimeUnit.SECONDS) == false) //No counting down should've been made
}
/**
* ticket #307
*/
@Test
def actorRestartShouldPickUpScheduleAgain = {
"schedule once" in {
case object Tick
val countDownLatch = new CountDownLatch(3)
val tickActor = createActor(new Actor {
def receive = { case Tick countDownLatch.countDown() }
})
// run every 50 millisec
collectFuture(Scheduler.scheduleOnce(tickActor, Tick, 50, TimeUnit.MILLISECONDS))
collectFuture(Scheduler.scheduleOnce(() countDownLatch.countDown(), 50, TimeUnit.MILLISECONDS))
object Ping
object Crash
// after 1 second the wait should fail
assert(countDownLatch.await(2, TimeUnit.SECONDS) == false)
// should still be 1 left
assert(countDownLatch.getCount == 1)
}
val restartLatch = new StandardLatch
val pingLatch = new CountDownLatch(6)
/**
* ticket #372
*/
"not create actors" in {
object Ping
val ticks = new CountDownLatch(1000)
val actor = createActor(new Actor {
def receive = { case Ping ticks.countDown }
})
val numActors = app.registry.local.actors.length
(1 to 1000).foreach(_ collectFuture(Scheduler.scheduleOnce(actor, Ping, 1, TimeUnit.MILLISECONDS)))
assert(ticks.await(10, TimeUnit.SECONDS))
assert(app.registry.local.actors.length === numActors)
}
val supervisor = actorOf(Props(context { case _ }).withFaultHandler(AllForOneStrategy(List(classOf[Exception]), 3, 1000)))
val actor = actorOf(Props(new Actor {
def receive = {
case Ping pingLatch.countDown()
case Crash throw new Exception("CRASH")
/**
* ticket #372
*/
"be cancellable" in {
object Ping
val ticks = new CountDownLatch(1)
val actor = createActor(new Actor {
def receive = { case Ping ticks.countDown() }
})
(1 to 10).foreach { i
val future = collectFuture(Scheduler.scheduleOnce(actor, Ping, 1, TimeUnit.SECONDS))
future.cancel(true)
}
assert(ticks.await(3, TimeUnit.SECONDS) == false) //No counting down should've been made
}
override def postRestart(reason: Throwable) = restartLatch.open
}).withSupervisor(supervisor))
/**
* ticket #307
*/
"pick up schedule after actor restart" in {
object Ping
object Crash
collectFuture(Scheduler.schedule(actor, Ping, 500, 500, TimeUnit.MILLISECONDS))
// appx 2 pings before crash
collectFuture(Scheduler.scheduleOnce(actor, Crash, 1000, TimeUnit.MILLISECONDS))
val restartLatch = new StandardLatch
val pingLatch = new CountDownLatch(6)
assert(restartLatch.tryAwait(2, TimeUnit.SECONDS))
// should be enough time for the ping countdown to recover and reach 6 pings
assert(pingLatch.await(4, TimeUnit.SECONDS))
val supervisor = createActor(Props(context { case _ }).withFaultHandler(AllForOneStrategy(List(classOf[Exception]), 3, 1000)))
val actor = createActor(Props(new Actor {
def receive = {
case Ping pingLatch.countDown()
case Crash throw new Exception("CRASH")
}
override def postRestart(reason: Throwable) = restartLatch.open
}).withSupervisor(supervisor))
collectFuture(Scheduler.schedule(actor, Ping, 500, 500, TimeUnit.MILLISECONDS))
// appx 2 pings before crash
collectFuture(Scheduler.scheduleOnce(actor, Crash, 1000, TimeUnit.MILLISECONDS))
assert(restartLatch.tryAwait(2, TimeUnit.SECONDS))
// should be enough time for the ping countdown to recover and reach 6 pings
assert(pingLatch.await(4, TimeUnit.SECONDS))
}
}
}

View file

@ -4,10 +4,6 @@
package akka.actor
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import Actor._
import akka.testkit._
import java.util.concurrent.{ TimeUnit, CountDownLatch }
@ -23,51 +19,50 @@ object SupervisorHierarchySpec {
}
}
class SupervisorHierarchySpec extends JUnitSuite {
class SupervisorHierarchySpec extends AkkaSpec {
import SupervisorHierarchySpec._
@Test
def killWorkerShouldRestartMangerAndOtherWorkers = {
val countDown = new CountDownLatch(4)
"A Supervisor Hierarchy" must {
val boss = actorOf(Props(self { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), None, None)), "boss")
"restart manager and workers in AllForOne" in {
val countDown = new CountDownLatch(4)
val manager = actorOf(Props(new CountDownActor(countDown)).withFaultHandler(AllForOneStrategy(List(), None, None)).withSupervisor(boss), "manager")
val boss = createActor(Props(self { case _ }).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), None, None)))
val workerProps = Props(new CountDownActor(countDown)).withSupervisor(manager)
val workerOne = actorOf(workerProps, "workerOne")
val workerTwo = actorOf(workerProps, "workerTwo")
val workerThree = actorOf(workerProps, "workerThree")
val manager = createActor(Props(new CountDownActor(countDown)).withFaultHandler(AllForOneStrategy(List(), None, None)).withSupervisor(boss))
filterException[ActorKilledException] {
workerOne ! Kill
val workerProps = Props(new CountDownActor(countDown)).withSupervisor(manager)
val workerOne, workerTwo, workerThree = createActor(workerProps)
// manager + all workers should be restarted by only killing a worker
// manager doesn't trap exits, so boss will restart manager
filterException[ActorKilledException] {
workerOne ! Kill
assert(countDown.await(2, TimeUnit.SECONDS))
}
}
// manager + all workers should be restarted by only killing a worker
// manager doesn't trap exits, so boss will restart manager
@Test
def supervisorShouldReceiveNotificationMessageWhenMaximumNumberOfRestartsWithinTimeRangeIsReached = {
val countDownMessages = new CountDownLatch(1)
val countDownMax = new CountDownLatch(1)
val boss = actorOf(Props(new Actor {
val crasher = self.link(actorOf(Props(new CountDownActor(countDownMessages)).withSupervisor(self)))
protected def receive = {
case "killCrasher" crasher ! Kill
case Terminated(_, _) countDownMax.countDown()
assert(countDown.await(2, TimeUnit.SECONDS))
}
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), 1, 5000)))
}
filterException[ActorKilledException] {
boss ! "killCrasher"
boss ! "killCrasher"
"send notification to supervisor when permanent failure" in {
val countDownMessages = new CountDownLatch(1)
val countDownMax = new CountDownLatch(1)
val boss = createActor(Props(new Actor {
val crasher = self.link(createActor(Props(new CountDownActor(countDownMessages)).withSupervisor(self)))
assert(countDownMessages.await(2, TimeUnit.SECONDS))
assert(countDownMax.await(2, TimeUnit.SECONDS))
protected def receive = {
case "killCrasher" crasher ! Kill
case Terminated(_, _) countDownMax.countDown()
}
}).withFaultHandler(OneForOneStrategy(List(classOf[Throwable]), 1, 5000)))
filterException[ActorKilledException] {
boss ! "killCrasher"
boss ! "killCrasher"
assert(countDownMessages.await(2, TimeUnit.SECONDS))
assert(countDownMax.await(2, TimeUnit.SECONDS))
}
}
}
}

View file

@ -3,20 +3,20 @@
*/
package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit.{ filterEvents, EventFilter }
import akka.dispatch.{ PinnedDispatcher, Dispatchers }
import java.util.concurrent.{ TimeUnit, CountDownLatch }
import akka.testkit.AkkaSpec
class SupervisorMiscSpec extends WordSpec with MustMatchers {
"A Supervisor" should {
class SupervisorMiscSpec extends AkkaSpec {
"A Supervisor" must {
"restart a crashing actor and its dispatcher for any dispatcher" in {
filterEvents(EventFilter[Exception]("Kill")) {
val countDownLatch = new CountDownLatch(4)
val supervisor = Actor.actorOf(Props(new Actor {
val supervisor = createActor(Props(new Actor {
def receive = { case _ }
}).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), 3, 5000)))
@ -29,13 +29,13 @@ class SupervisorMiscSpec extends WordSpec with MustMatchers {
}
}).withSupervisor(supervisor)
val actor1 = Actor.actorOf(workerProps.withDispatcher(new PinnedDispatcher()))
val actor1 = createActor(workerProps.withDispatcher(app.dispatcherFactory.newPinnedDispatcher("pinned")))
val actor2 = Actor.actorOf(workerProps.withDispatcher(new PinnedDispatcher()))
val actor2 = createActor(workerProps.withDispatcher(app.dispatcherFactory.newPinnedDispatcher("pinned")))
val actor3 = Actor.actorOf(workerProps.withDispatcher(Dispatchers.newDispatcher("test").build))
val actor3 = createActor(workerProps.withDispatcher(app.dispatcherFactory.newDispatcher("test").build))
val actor4 = Actor.actorOf(workerProps.withDispatcher(new PinnedDispatcher()))
val actor4 = createActor(workerProps.withDispatcher(app.dispatcherFactory.newPinnedDispatcher("pinned")))
actor1 ! Kill
actor2 ! Kill

View file

@ -8,7 +8,6 @@ import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import org.scalatest.BeforeAndAfterEach
import org.scalatest.BeforeAndAfterAll
import akka.testkit.Testing.sleepFor
import akka.util.duration._
import akka.{ Die, Ping }
@ -16,11 +15,11 @@ import akka.actor.Actor._
import akka.event.EventHandler
import akka.testkit.TestEvent._
import akka.testkit.EventFilter
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.LinkedBlockingQueue
import akka.testkit.AkkaSpec
object SupervisorSpec {
class SupervisorSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfterAll {
val Timeout = 5 seconds
val TimeoutMillis = Timeout.dilated.toMillis.toInt
@ -56,7 +55,7 @@ object SupervisorSpec {
class Master extends Actor {
val temp = actorOf(Props[PingPongActor].withSupervisor(self))
val temp = context.createActor(Props[PingPongActor].withSupervisor(self))
override def receive = {
case Die (temp.?(Die, TimeoutMillis)).get
@ -69,58 +68,54 @@ object SupervisorSpec {
// =====================================================
def temporaryActorAllForOne = {
val supervisor = Supervisor(AllForOneStrategy(List(classOf[Exception]), Some(0)))
val temporaryActor = actorOf(Props[PingPongActor].withSupervisor(supervisor))
val supervisor = createActor(Props(AllForOneStrategy(List(classOf[Exception]), Some(0))))
val temporaryActor = createActor(Props[PingPongActor].withSupervisor(supervisor))
(temporaryActor, supervisor)
}
def singleActorAllForOne = {
val supervisor = Supervisor(AllForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis))
val pingpong = actorOf(Props[PingPongActor].withSupervisor(supervisor))
val supervisor = createActor(Props(AllForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis)))
val pingpong = createActor(Props[PingPongActor].withSupervisor(supervisor))
(pingpong, supervisor)
}
def singleActorOneForOne = {
val supervisor = Supervisor(OneForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis))
val pingpong = actorOf(Props[PingPongActor].withSupervisor(supervisor))
val supervisor = createActor(Props(OneForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis)))
val pingpong = createActor(Props[PingPongActor].withSupervisor(supervisor))
(pingpong, supervisor)
}
def multipleActorsAllForOne = {
val supervisor = Supervisor(AllForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis))
val pingpong1 = actorOf(Props[PingPongActor].withSupervisor(supervisor))
val pingpong2 = actorOf(Props[PingPongActor].withSupervisor(supervisor))
val pingpong3 = actorOf(Props[PingPongActor].withSupervisor(supervisor))
val supervisor = createActor(Props(AllForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis)))
val pingpong1 = createActor(Props[PingPongActor].withSupervisor(supervisor))
val pingpong2 = createActor(Props[PingPongActor].withSupervisor(supervisor))
val pingpong3 = createActor(Props[PingPongActor].withSupervisor(supervisor))
(pingpong1, pingpong2, pingpong3, supervisor)
}
def multipleActorsOneForOne = {
val supervisor = Supervisor(OneForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis))
val pingpong1 = actorOf(Props[PingPongActor].withSupervisor(supervisor))
val pingpong2 = actorOf(Props[PingPongActor].withSupervisor(supervisor))
val pingpong3 = actorOf(Props[PingPongActor].withSupervisor(supervisor))
val supervisor = createActor(Props(OneForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis)))
val pingpong1 = createActor(Props[PingPongActor].withSupervisor(supervisor))
val pingpong2 = createActor(Props[PingPongActor].withSupervisor(supervisor))
val pingpong3 = createActor(Props[PingPongActor].withSupervisor(supervisor))
(pingpong1, pingpong2, pingpong3, supervisor)
}
def nestedSupervisorsAllForOne = {
val topSupervisor = Supervisor(AllForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis))
val pingpong1 = actorOf(Props[PingPongActor].withSupervisor(topSupervisor))
val topSupervisor = createActor(Props(AllForOneStrategy(List(classOf[Exception]), 3, TimeoutMillis)))
val pingpong1 = createActor(Props[PingPongActor].withSupervisor(topSupervisor))
val middleSupervisor = Supervisor(AllForOneStrategy(Nil, 3, TimeoutMillis), topSupervisor)
val pingpong2 = actorOf(Props[PingPongActor].withSupervisor(middleSupervisor))
val pingpong3 = actorOf(Props[PingPongActor].withSupervisor(middleSupervisor))
val middleSupervisor = createActor(Props(AllForOneStrategy(Nil, 3, TimeoutMillis)).withSupervisor(topSupervisor))
val pingpong2 = createActor(Props[PingPongActor].withSupervisor(middleSupervisor))
val pingpong3 = createActor(Props[PingPongActor].withSupervisor(middleSupervisor))
(pingpong1, pingpong2, pingpong3, topSupervisor)
}
}
class SupervisorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach with BeforeAndAfterAll {
import SupervisorSpec._
override def beforeAll() = {
EventHandler notify Mute(EventFilter[Exception]("Die"),
@ -149,7 +144,7 @@ class SupervisorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
"A supervisor" must {
"not restart programmatically linked temporary actor" in {
val master = actorOf(Props[Master].withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(0))))
val master = createActor(Props[Master].withFaultHandler(OneForOneStrategy(List(classOf[Exception]), Some(0))))
intercept[RuntimeException] {
(master.?(Die, TimeoutMillis)).get
@ -291,9 +286,9 @@ class SupervisorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
"must attempt restart when exception during restart" in {
val inits = new AtomicInteger(0)
val supervisor = Supervisor(OneForOneStrategy(classOf[Exception] :: Nil, 3, 10000))
val supervisor = createActor(Props(OneForOneStrategy(classOf[Exception] :: Nil, 3, 10000)))
val dyingActor = actorOf(Props(new Actor {
val dyingActor = createActor(Props(new Actor {
inits.incrementAndGet
if (inits.get % 2 == 0) throw new IllegalStateException("Don't wanna!")

View file

@ -5,14 +5,15 @@ package akka.actor
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.util.duration._
import akka.testkit.Testing.sleepFor
import akka.dispatch.Dispatchers
import akka.actor.Actor._
import akka.testkit.{ TestKit, EventFilter, filterEvents, filterException }
import akka.testkit.AkkaSpec
import akka.testkit.ImplicitSender
class SupervisorTreeSpec extends WordSpec with MustMatchers with TestKit {
class SupervisorTreeSpec extends AkkaSpec with ImplicitSender {
"In a 3 levels deep supervisor tree (linked in the constructor) we" must {
@ -23,9 +24,9 @@ class SupervisorTreeSpec extends WordSpec with MustMatchers with TestKit {
def receive = { case false }
override def preRestart(reason: Throwable, msg: Option[Any]) { testActor ! self.address }
}).withFaultHandler(OneForOneStrategy(List(classOf[Exception]), 3, 1000))
val headActor = actorOf(p, "headActor")
val middleActor = actorOf(p.withSupervisor(headActor), "middleActor")
val lastActor = actorOf(p.withSupervisor(middleActor), "lastActor")
val headActor = createActor(p)
val middleActor = createActor(p.withSupervisor(headActor))
val lastActor = createActor(p.withSupervisor(middleActor))
middleActor ! Kill
expectMsg(middleActor.address)

View file

@ -4,27 +4,27 @@
package akka.actor
import java.util.concurrent.{ CountDownLatch, TimeUnit }
import akka.actor._
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
import org.scalatest.matchers.MustMatchers
import org.scalatest.BeforeAndAfterAll
import akka.testkit.{ TestKit, filterEvents, EventFilter }
import akka.testkit.AkkaSpec
import akka.testkit.ImplicitSender
class Ticket669Spec extends WordSpec with MustMatchers with BeforeAndAfterAll with TestKit {
class Ticket669Spec extends AkkaSpec with BeforeAndAfterAll with ImplicitSender {
import Ticket669Spec._
override def beforeAll = Thread.interrupted() //remove interrupted status.
override def afterAll = {
Actor.registry.local.shutdownAll
app.registry.local.shutdownAll
akka.event.EventHandler.start()
}
"A supervised actor with lifecycle PERMANENT" should {
"be able to reply on failure during preRestart" in {
filterEvents(EventFilter[Exception]("test")) {
val supervisor = Supervisor(AllForOneStrategy(List(classOf[Exception]), 5, 10000))
val supervised = Actor.actorOf(Props[Supervised].withSupervisor(supervisor))
val supervisor = createActor(Props(AllForOneStrategy(List(classOf[Exception]), 5, 10000)))
val supervised = createActor(Props[Supervised].withSupervisor(supervisor))
supervised.!("test")(Some(testActor))
expectMsg("failure1")
@ -34,8 +34,8 @@ class Ticket669Spec extends WordSpec with MustMatchers with BeforeAndAfterAll wi
"be able to reply on failure during postStop" in {
filterEvents(EventFilter[Exception]("test")) {
val supervisor = Supervisor(AllForOneStrategy(List(classOf[Exception]), Some(0), None))
val supervised = Actor.actorOf(Props[Supervised].withSupervisor(supervisor))
val supervisor = createActor(Props(AllForOneStrategy(List(classOf[Exception]), Some(0), None)))
val supervised = createActor(Props[Supervised].withSupervisor(supervisor))
supervised.!("test")(Some(testActor))
expectMsg("failure2")

View file

@ -4,19 +4,15 @@ package akka.actor
* Copyright (C) 2009-2011 Typesafe Inc. <http://www.typesafe.com>
*/
import org.scalatest.matchers.MustMatchers
import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith
import org.scalatest.{ BeforeAndAfterAll, WordSpec, BeforeAndAfterEach }
import akka.actor.TypedActor._
import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach }
import akka.japi.{ Option JOption }
import akka.util.Duration
import akka.dispatch.{ Dispatchers, Future, KeptPromise }
import java.util.concurrent.atomic.AtomicReference
import annotation.tailrec
import akka.testkit.{ EventFilter, filterEvents }
import akka.testkit.{ EventFilter, filterEvents, AkkaSpec }
object TypedActorSpec {
class TypedActorSpec extends AkkaSpec with BeforeAndAfterEach with BeforeAndAfterAll {
class CyclicIterator[T](val items: Seq[T]) extends Iterator[T] {
@ -46,7 +42,7 @@ object TypedActorSpec {
trait Foo {
def pigdog(): String
def self = TypedActor.self[Foo]
def self = app.typedActor.self[Foo]
def futurePigdog(): Future[String]
@ -135,31 +131,24 @@ object TypedActorSpec {
override def stacked: String = "FOOBAR" //Uppercase
}
}
@RunWith(classOf[JUnitRunner])
class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach with BeforeAndAfterAll {
import akka.actor.TypedActorSpec._
def newFooBar: Foo = newFooBar(Duration(2, "s"))
def newFooBar(d: Duration): Foo =
newFooBar(Props().withTimeout(Timeout(d)))
def newFooBar(props: Props): Foo =
typedActorOf(classOf[Foo], classOf[Bar], props)
app.typedActor.typedActorOf(classOf[Foo], classOf[Bar], props)
def newStacked(props: Props = Props().withTimeout(Timeout(2000))): Stacked =
typedActorOf(classOf[Stacked], classOf[StackedImpl], props)
app.typedActor.typedActorOf(classOf[Stacked], classOf[StackedImpl], props)
def mustStop(typedActor: AnyRef) = stop(typedActor) must be(true)
def mustStop(typedActor: AnyRef) = app.typedActor.stop(typedActor) must be(true)
"TypedActors" must {
"be able to instantiate" in {
val t = newFooBar
isTypedActor(t) must be(true)
app.typedActor.isTypedActor(t) must be(true)
mustStop(t)
}
@ -169,13 +158,13 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
}
"not stop non-started ones" in {
stop(null) must be(false)
app.typedActor.stop(null) must be(false)
}
"throw an IllegalStateExcpetion when TypedActor.self is called in the wrong scope" in {
filterEvents(EventFilter[IllegalStateException]("Calling")) {
(intercept[IllegalStateException] {
TypedActor.self[Foo]
app.typedActor.self[Foo]
}).getMessage must equal("Calling TypedActor.self outside of a TypedActor implementation method!")
}
}
@ -188,7 +177,7 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
"be able to call toString" in {
val t = newFooBar
t.toString must be(getActorRefFor(t).toString)
t.toString must be(app.typedActor.getActorRefFor(t).toString)
mustStop(t)
}
@ -201,7 +190,7 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
"be able to call hashCode" in {
val t = newFooBar
t.hashCode must be(getActorRefFor(t).hashCode)
t.hashCode must be(app.typedActor.getActorRefFor(t).hashCode)
mustStop(t)
}
@ -295,7 +284,7 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
}
"be able to support implementation only typed actors" in {
val t = typedActorOf[Foo, Bar](Props())
val t = app.typedActor.typedActorOf[Foo, Bar](Props())
val f = t.futurePigdog(200)
val f2 = t.futurePigdog(0)
f2.isCompleted must be(false)
@ -305,7 +294,7 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
}
"be able to support implementation only typed actors with complex interfaces" in {
val t = typedActorOf[Stackable1 with Stackable2, StackedImpl]()
val t = app.typedActor.typedActorOf[Stackable1 with Stackable2, StackedImpl]()
t.stackable1 must be("foo")
t.stackable2 must be("bar")
mustStop(t)
@ -314,7 +303,7 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
"be able to use work-stealing dispatcher" in {
val props = Props(
timeout = Timeout(6600),
dispatcher = Dispatchers.newBalancingDispatcher("pooled-dispatcher")
dispatcher = app.dispatcherFactory.newBalancingDispatcher("pooled-dispatcher")
.withNewThreadPoolWithLinkedBlockingQueueWithUnboundedCapacity
.setCorePoolSize(60)
.setMaxPoolSize(60)
@ -332,7 +321,7 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
"be able to serialize and deserialize invocations" in {
import java.io._
val m = MethodCall(classOf[Foo].getDeclaredMethod("pigdog"), Array[AnyRef]())
val m = app.typedActor.MethodCall(classOf[Foo].getDeclaredMethod("pigdog"), Array[AnyRef]())
val baos = new ByteArrayOutputStream(8192 * 4)
val out = new ObjectOutputStream(baos)
@ -341,7 +330,7 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
val in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray))
val mNew = in.readObject().asInstanceOf[MethodCall]
val mNew = in.readObject().asInstanceOf[app.typedActor.MethodCall]
mNew.method must be(m.method)
}
@ -349,7 +338,7 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
"be able to serialize and deserialize invocations' parameters" in {
import java.io._
val someFoo: Foo = new Bar
val m = MethodCall(classOf[Foo].getDeclaredMethod("testMethodCallSerialization", Array[Class[_]](classOf[Foo], classOf[String], classOf[Int]): _*), Array[AnyRef](someFoo, null, 1.asInstanceOf[AnyRef]))
val m = app.typedActor.MethodCall(classOf[Foo].getDeclaredMethod("testMethodCallSerialization", Array[Class[_]](classOf[Foo], classOf[String], classOf[Int]): _*), Array[AnyRef](someFoo, null, 1.asInstanceOf[AnyRef]))
val baos = new ByteArrayOutputStream(8192 * 4)
val out = new ObjectOutputStream(baos)
@ -358,7 +347,7 @@ class TypedActorSpec extends WordSpec with MustMatchers with BeforeAndAfterEach
val in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray))
val mNew = in.readObject().asInstanceOf[MethodCall]
val mNew = in.readObject().asInstanceOf[app.typedActor.MethodCall]
mNew.method must be(m.method)
mNew.parameters must have size 3

View file

@ -4,21 +4,19 @@
package akka.actor.dispatch
import akka.event.EventHandler
import org.scalatest.junit.JUnitSuite
import org.scalatest.Assertions._
import akka.testkit.{ Testing, filterEvents, EventFilter }
import akka.testkit.{ Testing, filterEvents, EventFilter, AkkaSpec }
import akka.dispatch._
import akka.actor.Actor._
import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.{ ConcurrentHashMap, CountDownLatch, TimeUnit }
import akka.actor.dispatch.ActorModelSpec.MessageDispatcherInterceptor
import akka.util.Switch
import java.rmi.RemoteException
import org.junit.{ After, Test }
import akka.actor._
import util.control.NoStackTrace
import akka.AkkaApplication
object ActorModelSpec {
abstract class ActorModelSpec extends AkkaSpec {
sealed trait ActorModelMessage
@ -241,274 +239,272 @@ object ActorModelSpec {
throw new AssertionError("await failed")
}
def newTestActor(implicit d: MessageDispatcherInterceptor) = actorOf(Props[DispatcherActor].withDispatcher(d))
}
abstract class ActorModelSpec extends JUnitSuite {
import ActorModelSpec._
def newTestActor(implicit app: AkkaApplication) = app.createActor(Props[DispatcherActor].withDispatcher(app.dispatcher))
protected def newInterceptedDispatcher: MessageDispatcherInterceptor
protected def dispatcherType: String
@Test
def dispatcherShouldDynamicallyHandleItsOwnLifeCycle {
implicit val dispatcher = newInterceptedDispatcher
assertDispatcher(dispatcher)(starts = 0, stops = 0)
val a = newTestActor
assertDispatcher(dispatcher)(starts = 1, stops = 0)
a.stop()
assertDispatcher(dispatcher)(starts = 1, stops = 1)
assertRef(a, dispatcher)(
suspensions = 0,
resumes = 0,
registers = 1,
unregisters = 1,
msgsReceived = 0,
msgsProcessed = 0,
restarts = 0)
"A " + dispatcherType must {
val futures = for (i 1 to 10) yield Future {
i
}
assertDispatcher(dispatcher)(starts = 2, stops = 2)
val a2 = newTestActor
val futures2 = for (i 1 to 10) yield Future { i }
assertDispatcher(dispatcher)(starts = 3, stops = 2)
a2.stop
assertDispatcher(dispatcher)(starts = 3, stops = 3)
}
@Test
def dispatcherShouldProcessMessagesOneAtATime {
implicit val dispatcher = newInterceptedDispatcher
val start, oneAtATime = new CountDownLatch(1)
val a = newTestActor
a ! CountDown(start)
assertCountDown(start, Testing.testTime(3000), "Should process first message within 3 seconds")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 1, msgsProcessed = 1)
a ! Wait(1000)
a ! CountDown(oneAtATime)
// in case of serialization violation, restart would happen instead of count down
assertCountDown(oneAtATime, Testing.testTime(1500), "Processed message when allowed")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 3, msgsProcessed = 3)
a.stop()
assertRefDefaultZero(a)(registers = 1, unregisters = 1, msgsReceived = 3, msgsProcessed = 3)
}
@Test
def dispatcherShouldHandleQueueingFromMultipleThreads {
implicit val dispatcher = newInterceptedDispatcher
val counter = new CountDownLatch(200)
val a = newTestActor
for (i 1 to 10) {
spawn {
for (i 1 to 20) {
a ! WaitAck(1, counter)
}
}
}
assertCountDown(counter, Testing.testTime(3000), "Should process 200 messages")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 200, msgsProcessed = 200)
a.stop()
}
def spawn(f: Unit) {
val thread = new Thread {
override def run {
try {
f
} catch {
case e EventHandler.error(e, this, "error in spawned thread")
}
}
}
thread.start()
}
@Test
def dispatcherShouldProcessMessagesInParallel {
implicit val dispatcher = newInterceptedDispatcher
val aStart, aStop, bParallel = new CountDownLatch(1)
val a, b = newTestActor
a ! Meet(aStart, aStop)
assertCountDown(aStart, Testing.testTime(3000), "Should process first message within 3 seconds")
b ! CountDown(bParallel)
assertCountDown(bParallel, Testing.testTime(3000), "Should process other actors in parallel")
aStop.countDown()
a.stop
b.stop
while (!a.isShutdown && !b.isShutdown) {} //Busy wait for termination
assertRefDefaultZero(a)(registers = 1, unregisters = 1, msgsReceived = 1, msgsProcessed = 1)
assertRefDefaultZero(b)(registers = 1, unregisters = 1, msgsReceived = 1, msgsProcessed = 1)
}
@Test
def dispatcherShouldSuspendAndResumeAFailingNonSupervisedPermanentActor {
filterEvents(EventFilter[Exception]("Restart")) {
"must dynamically handle its own life cycle" in {
implicit val dispatcher = newInterceptedDispatcher
assertDispatcher(dispatcher)(starts = 0, stops = 0)
val a = newTestActor
val done = new CountDownLatch(1)
a ! Restart
a ! CountDown(done)
assertCountDown(done, Testing.testTime(3000), "Should be suspended+resumed and done with next message within 3 seconds")
assertDispatcher(dispatcher)(starts = 1, stops = 0)
a.stop()
assertRefDefaultZero(a)(registers = 1, unregisters = 1, msgsReceived = 2,
msgsProcessed = 2, suspensions = 1, resumes = 1)
}
}
assertDispatcher(dispatcher)(starts = 1, stops = 1)
assertRef(a, dispatcher)(
suspensions = 0,
resumes = 0,
registers = 1,
unregisters = 1,
msgsReceived = 0,
msgsProcessed = 0,
restarts = 0)
@Test
def dispatcherShouldNotProcessMessagesForASuspendedActor {
implicit val dispatcher = newInterceptedDispatcher
val a = newTestActor.asInstanceOf[LocalActorRef]
val done = new CountDownLatch(1)
a.suspend
a ! CountDown(done)
assertNoCountDown(done, 1000, "Should not process messages while suspended")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 1, suspensions = 1)
a.resume
assertCountDown(done, Testing.testTime(3000), "Should resume processing of messages when resumed")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 1, msgsProcessed = 1,
suspensions = 1, resumes = 1)
a.stop()
assertRefDefaultZero(a)(registers = 1, unregisters = 1, msgsReceived = 1, msgsProcessed = 1,
suspensions = 1, resumes = 1)
}
@Test
def dispatcherShouldHandleWavesOfActors {
implicit val dispatcher = newInterceptedDispatcher
def flood(num: Int) {
val cachedMessage = CountDownNStop(new CountDownLatch(num))
(1 to num) foreach { _
newTestActor ! cachedMessage
val futures = for (i 1 to 10) yield Future {
i
}
try {
assertCountDown(cachedMessage.latch, Testing.testTime(10000), "Should process " + num + " countdowns")
} catch {
case e
System.err.println("Error: " + e.getMessage + " missing count downs == " + cachedMessage.latch.getCount() + " out of " + num)
//EventHandler.error(new Exception with NoStackTrace, null, cachedMessage.latch.getCount())
}
}
for (run 1 to 3) {
flood(40000)
try {
assertDispatcher(dispatcher)(starts = run, stops = run)
} catch {
case e
assertDispatcher(dispatcher)(starts = 2, stops = 2)
Actor.registry.local.foreach {
case actor: LocalActorRef
val cell = actor.underlying
val mbox = cell.mailbox
System.err.println("Left in the registry: " + actor.address + " => " + cell + " => " + mbox.hasMessages + " " + mbox.hasSystemMessages + " " + mbox.numberOfMessages + " " + mbox.isScheduled)
var message = mbox.dequeue()
while (message ne null) {
System.err.println("Lingering message for " + cell + " " + message)
message = mbox.dequeue()
}
val a2 = newTestActor
val futures2 = for (i 1 to 10) yield Future { i }
assertDispatcher(dispatcher)(starts = 3, stops = 2)
a2.stop
assertDispatcher(dispatcher)(starts = 3, stops = 3)
}
"process messages one at a time" in {
implicit val dispatcher = newInterceptedDispatcher
val start, oneAtATime = new CountDownLatch(1)
val a = newTestActor
a ! CountDown(start)
assertCountDown(start, Testing.testTime(3000), "Should process first message within 3 seconds")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 1, msgsProcessed = 1)
a ! Wait(1000)
a ! CountDown(oneAtATime)
// in case of serialization violation, restart would happen instead of count down
assertCountDown(oneAtATime, Testing.testTime(1500), "Processed message when allowed")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 3, msgsProcessed = 3)
a.stop()
assertRefDefaultZero(a)(registers = 1, unregisters = 1, msgsReceived = 3, msgsProcessed = 3)
}
"handle queueing from multiple threads" in {
implicit val dispatcher = newInterceptedDispatcher
val counter = new CountDownLatch(200)
val a = newTestActor
for (i 1 to 10) {
spawn {
for (i 1 to 20) {
a ! WaitAck(1, counter)
}
}
}
assertCountDown(counter, Testing.testTime(3000), "Should process 200 messages")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 200, msgsProcessed = 200)
throw e
a.stop()
}
def spawn(f: Unit) {
val thread = new Thread {
override def run {
try {
f
} catch {
case e EventHandler.error(e, this, "error in spawned thread")
}
}
}
thread.start()
}
"process messages in parallel" in {
implicit val dispatcher = newInterceptedDispatcher
val aStart, aStop, bParallel = new CountDownLatch(1)
val a, b = newTestActor
a ! Meet(aStart, aStop)
assertCountDown(aStart, Testing.testTime(3000), "Should process first message within 3 seconds")
b ! CountDown(bParallel)
assertCountDown(bParallel, Testing.testTime(3000), "Should process other actors in parallel")
aStop.countDown()
a.stop
b.stop
while (!a.isShutdown && !b.isShutdown) {} //Busy wait for termination
assertRefDefaultZero(a)(registers = 1, unregisters = 1, msgsReceived = 1, msgsProcessed = 1)
assertRefDefaultZero(b)(registers = 1, unregisters = 1, msgsReceived = 1, msgsProcessed = 1)
}
"suspend and resume a failing non supervised permanent actor" in {
filterEvents(EventFilter[Exception]("Restart")) {
implicit val dispatcher = newInterceptedDispatcher
val a = newTestActor
val done = new CountDownLatch(1)
a ! Restart
a ! CountDown(done)
assertCountDown(done, Testing.testTime(3000), "Should be suspended+resumed and done with next message within 3 seconds")
a.stop()
assertRefDefaultZero(a)(registers = 1, unregisters = 1, msgsReceived = 2,
msgsProcessed = 2, suspensions = 1, resumes = 1)
}
}
}
@Test
def dispatcherShouldCompleteAllUncompletedSenderFuturesOnDeregister {
implicit val dispatcher = newInterceptedDispatcher
val a = newTestActor.asInstanceOf[LocalActorRef]
a.suspend
val f1: Future[String] = a ? Reply("foo") mapTo manifest[String]
val stopped = a ? PoisonPill
val shouldBeCompleted = for (i 1 to 10) yield a ? Reply(i)
a.resume
assert(f1.get == "foo")
stopped.await
for (each shouldBeCompleted)
assert(each.await.exception.get.isInstanceOf[ActorKilledException])
a.stop()
}
@Test
def dispatcherShouldContinueToProcessMessagesWhenAThreadGetsInterrupted {
filterEvents(EventFilter[InterruptedException]("Ping!"), EventFilter[akka.event.EventHandler.EventHandlerException]) {
"not process messages for a suspended actor" in {
implicit val dispatcher = newInterceptedDispatcher
val a = newTestActor
val f1 = a ? Reply("foo")
val f2 = a ? Reply("bar")
val f3 = a ? Interrupt
val f4 = a ? Reply("foo2")
val f5 = a ? Interrupt
val f6 = a ? Reply("bar2")
val a = newTestActor.asInstanceOf[LocalActorRef]
val done = new CountDownLatch(1)
a.suspend
a ! CountDown(done)
assertNoCountDown(done, 1000, "Should not process messages while suspended")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 1, suspensions = 1)
assert(f1.get === "foo")
assert(f2.get === "bar")
assert((intercept[InterruptedException] {
f3.get
}).getMessage === "Ping!")
assert(f4.get === "foo2")
assert((intercept[InterruptedException] {
f5.get
}).getMessage === "Ping!")
assert(f6.get === "bar2")
a.resume
assertCountDown(done, Testing.testTime(3000), "Should resume processing of messages when resumed")
assertRefDefaultZero(a)(registers = 1, msgsReceived = 1, msgsProcessed = 1,
suspensions = 1, resumes = 1)
a.stop()
assertRefDefaultZero(a)(registers = 1, unregisters = 1, msgsReceived = 1, msgsProcessed = 1,
suspensions = 1, resumes = 1)
}
}
@Test
def dispatcherShouldContinueToProcessMessagesWhenExceptionIsThrown {
filterEvents(EventFilter[IndexOutOfBoundsException], EventFilter[RemoteException]) {
"handle waves of actors" in {
implicit val dispatcher = newInterceptedDispatcher
val a = newTestActor
val f1 = a ? Reply("foo")
val f2 = a ? Reply("bar")
val f3 = a ? new ThrowException(new IndexOutOfBoundsException("IndexOutOfBoundsException"))
val f4 = a ? Reply("foo2")
val f5 = a ? new ThrowException(new RemoteException("RemoteException"))
val f6 = a ? Reply("bar2")
assert(f1.get === "foo")
assert(f2.get === "bar")
assert((intercept[IndexOutOfBoundsException] {
f3.get
}).getMessage === "IndexOutOfBoundsException")
assert(f4.get === "foo2")
assert((intercept[RemoteException] {
f5.get
}).getMessage === "RemoteException")
assert(f6.get === "bar2")
def flood(num: Int) {
val cachedMessage = CountDownNStop(new CountDownLatch(num))
(1 to num) foreach { _
newTestActor ! cachedMessage
}
try {
assertCountDown(cachedMessage.latch, Testing.testTime(10000), "Should process " + num + " countdowns")
} catch {
case e
System.err.println("Error: " + e.getMessage + " missing count downs == " + cachedMessage.latch.getCount() + " out of " + num)
//EventHandler.error(new Exception with NoStackTrace, null, cachedMessage.latch.getCount())
}
}
for (run 1 to 3) {
flood(40000)
try {
assertDispatcher(dispatcher)(starts = run, stops = run)
} catch {
case e
app.registry.local.foreach {
case actor: LocalActorRef
val cell = actor.underlying
val mbox = cell.mailbox
System.err.println("Left in the registry: " + actor.address + " => " + cell + " => " + mbox.hasMessages + " " + mbox.hasSystemMessages + " " + mbox.numberOfMessages + " " + mbox.isScheduled)
var message = mbox.dequeue()
while (message ne null) {
System.err.println("Lingering message for " + cell + " " + message)
message = mbox.dequeue()
}
}
throw e
}
}
}
"complete all uncompleted sender futures on deregister" in {
implicit val dispatcher = newInterceptedDispatcher
val a = newTestActor.asInstanceOf[LocalActorRef]
a.suspend
val f1: Future[String] = a ? Reply("foo") mapTo manifest[String]
val stopped = a ? PoisonPill
val shouldBeCompleted = for (i 1 to 10) yield a ? Reply(i)
a.resume
assert(f1.get == "foo")
stopped.await
for (each shouldBeCompleted)
assert(each.await.exception.get.isInstanceOf[ActorKilledException])
a.stop()
}
"continue to process messages when a thread gets interrupted" in {
filterEvents(EventFilter[InterruptedException]("Ping!"), EventFilter[akka.event.EventHandler.EventHandlerException]) {
implicit val dispatcher = newInterceptedDispatcher
val a = newTestActor
val f1 = a ? Reply("foo")
val f2 = a ? Reply("bar")
val f3 = a ? Interrupt
val f4 = a ? Reply("foo2")
val f5 = a ? Interrupt
val f6 = a ? Reply("bar2")
assert(f1.get === "foo")
assert(f2.get === "bar")
assert((intercept[InterruptedException] {
f3.get
}).getMessage === "Ping!")
assert(f4.get === "foo2")
assert((intercept[InterruptedException] {
f5.get
}).getMessage === "Ping!")
assert(f6.get === "bar2")
}
}
"continue to process messages when exception is thrown" in {
filterEvents(EventFilter[IndexOutOfBoundsException], EventFilter[RemoteException]) {
implicit val dispatcher = newInterceptedDispatcher
val a = newTestActor
val f1 = a ? Reply("foo")
val f2 = a ? Reply("bar")
val f3 = a ? new ThrowException(new IndexOutOfBoundsException("IndexOutOfBoundsException"))
val f4 = a ? Reply("foo2")
val f5 = a ? new ThrowException(new RemoteException("RemoteException"))
val f6 = a ? Reply("bar2")
assert(f1.get === "foo")
assert(f2.get === "bar")
assert((intercept[IndexOutOfBoundsException] {
f3.get
}).getMessage === "IndexOutOfBoundsException")
assert(f4.get === "foo2")
assert((intercept[RemoteException] {
f5.get
}).getMessage === "RemoteException")
assert(f6.get === "bar2")
}
}
}
}
class DispatcherModelTest extends ActorModelSpec {
def newInterceptedDispatcher =
new Dispatcher("foo") with MessageDispatcherInterceptor
def newInterceptedDispatcher = ThreadPoolConfigDispatcherBuilder(config
new Dispatcher("foo", app.AkkaConfig.DispatcherThroughput,
app.dispatcherFactory.THROUGHPUT_DEADLINE_TIME_MILLIS, app.dispatcherFactory.MAILBOX_TYPE,
config, app.dispatcherFactory.DISPATCHER_SHUTDOWN_TIMEOUT) with MessageDispatcherInterceptor,
ThreadPoolConfig()).build.asInstanceOf[MessageDispatcherInterceptor]
def dispatcherType = "Dispatcher"
}
class BalancingDispatcherModelTest extends ActorModelSpec {
def newInterceptedDispatcher =
new BalancingDispatcher("foo", throughput = 1) with MessageDispatcherInterceptor
def newInterceptedDispatcher = ThreadPoolConfigDispatcherBuilder(config
new BalancingDispatcher("foo", 1, // TODO check why 1 here? (came from old test)
app.dispatcherFactory.THROUGHPUT_DEADLINE_TIME_MILLIS, app.dispatcherFactory.MAILBOX_TYPE,
config, app.dispatcherFactory.DISPATCHER_SHUTDOWN_TIMEOUT) with MessageDispatcherInterceptor,
ThreadPoolConfig()).build.asInstanceOf[MessageDispatcherInterceptor]
def dispatcherType = "Balancing Dispatcher"
override def dispatcherShouldCompleteAllUncompletedSenderFuturesOnDeregister {
//This is not true for the BalancingDispatcher
}
// TOOD: fix this: disabling tests in this way does not work anymore with WordSpec
//override def dispatcherShouldCompleteAllUncompletedSenderFuturesOnDeregister {
//This is not true for the BalancingDispatcher
//}
}

View file

@ -1,18 +1,13 @@
package akka.actor.dispatch
import org.scalatest.matchers.MustMatchers
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import java.util.concurrent.{ TimeUnit, CountDownLatch }
import akka.actor.Actor._
import akka.dispatch.{ Mailbox, Dispatchers }
import akka.actor.{ LocalActorRef, IllegalActorStateException, Actor, Props }
import akka.testkit.AkkaSpec
object BalancingDispatcherSpec {
class BalancingDispatcherSpec extends AkkaSpec {
def newWorkStealer() = Dispatchers.newBalancingDispatcher("pooled-dispatcher", 1).build
def newWorkStealer() = app.dispatcherFactory.newBalancingDispatcher("pooled-dispatcher", 1).build
val delayableActorDispatcher, sharedActorDispatcher, parentActorDispatcher = newWorkStealer()
@ -43,49 +38,43 @@ object BalancingDispatcherSpec {
class ChildActor extends ParentActor {
}
}
/**
* @author Jan Van Besien
*/
class BalancingDispatcherSpec extends JUnitSuite with MustMatchers {
import BalancingDispatcherSpec._
"A BalancingDispatcher" must {
"have fast actor stealing work from slow actor" in {
val finishedCounter = new CountDownLatch(110)
@Test
def fastActorShouldStealWorkFromSlowActor {
val finishedCounter = new CountDownLatch(110)
val slow = createActor(Props(new DelayableActor(50, finishedCounter)).withDispatcher(delayableActorDispatcher)).asInstanceOf[LocalActorRef]
val fast = createActor(Props(new DelayableActor(10, finishedCounter)).withDispatcher(delayableActorDispatcher)).asInstanceOf[LocalActorRef]
val slow = actorOf(Props(new DelayableActor(50, finishedCounter)).withDispatcher(delayableActorDispatcher), "slow").asInstanceOf[LocalActorRef]
val fast = actorOf(Props(new DelayableActor(10, finishedCounter)).withDispatcher(delayableActorDispatcher), "fast").asInstanceOf[LocalActorRef]
var sentToFast = 0
var sentToFast = 0
for (i 1 to 100) {
// send most work to slow actor
if (i % 20 == 0) {
fast ! i
sentToFast += 1
} else
slow ! i
}
for (i 1 to 100) {
// send most work to slow actor
if (i % 20 == 0) {
fast ! i
sentToFast += 1
} else
slow ! i
// now send some messages to actors to keep the dispatcher dispatching messages
for (i 1 to 10) {
Thread.sleep(150)
if (i % 2 == 0) {
fast ! i
sentToFast += 1
} else
slow ! i
}
finishedCounter.await(5, TimeUnit.SECONDS)
fast.underlying.mailbox.asInstanceOf[Mailbox].hasMessages must be(false)
slow.underlying.mailbox.asInstanceOf[Mailbox].hasMessages must be(false)
fast.underlyingActorInstance.asInstanceOf[DelayableActor].invocationCount must be > sentToFast
fast.underlyingActorInstance.asInstanceOf[DelayableActor].invocationCount must be >
(slow.underlyingActorInstance.asInstanceOf[DelayableActor].invocationCount)
slow.stop()
fast.stop()
}
// now send some messages to actors to keep the dispatcher dispatching messages
for (i 1 to 10) {
Thread.sleep(150)
if (i % 2 == 0) {
fast ! i
sentToFast += 1
} else
slow ! i
}
finishedCounter.await(5, TimeUnit.SECONDS)
fast.underlying.mailbox.asInstanceOf[Mailbox].hasMessages must be(false)
slow.underlying.mailbox.asInstanceOf[Mailbox].hasMessages must be(false)
fast.underlyingActorInstance.asInstanceOf[DelayableActor].invocationCount must be > sentToFast
fast.underlyingActorInstance.asInstanceOf[DelayableActor].invocationCount must be >
(slow.underlyingActorInstance.asInstanceOf[DelayableActor].invocationCount)
slow.stop()
fast.stop()
}
}

View file

@ -1,11 +1,8 @@
package akka.actor.dispatch
import java.util.concurrent.{ CountDownLatch, TimeUnit }
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import akka.actor.Actor._
import java.util.concurrent.atomic.{ AtomicBoolean, AtomicInteger }
import akka.testkit.{ filterEvents, EventFilter }
import akka.testkit.{ filterEvents, EventFilter, AkkaSpec }
import akka.dispatch.{ PinnedDispatcher, Dispatchers, Dispatcher }
import akka.actor.{ Props, Actor }
@ -26,108 +23,107 @@ object DispatcherActorSpec {
}
}
}
class DispatcherActorSpec extends JUnitSuite {
class DispatcherActorSpec extends AkkaSpec {
import DispatcherActorSpec._
private val unit = TimeUnit.MILLISECONDS
@Test
def shouldTell = {
val actor = actorOf(Props[OneWayTestActor].withDispatcher(new PinnedDispatcher()))
val result = actor ! "OneWay"
assert(OneWayTestActor.oneWay.await(1, TimeUnit.SECONDS))
actor.stop()
}
"A Dispatcher and an Actor" must {
@Test
def shouldSendReplySync = {
val actor = actorOf(Props[TestActor].withDispatcher(new PinnedDispatcher()))
val result = (actor.?("Hello", 10000)).as[String]
assert("World" === result.get)
actor.stop()
}
@Test
def shouldSendReplyAsync = {
val actor = actorOf(Props[TestActor].withDispatcher(new PinnedDispatcher()))
val result = (actor ? "Hello").as[String]
assert("World" === result.get)
actor.stop()
}
@Test
def shouldSendReceiveException = {
filterEvents(EventFilter[RuntimeException]("Expected")) {
val actor = actorOf(Props[TestActor].withDispatcher(new PinnedDispatcher()))
try {
(actor ? "Failure").get
fail("Should have thrown an exception")
} catch {
case e
assert("Expected exception; to test fault-tolerance" === e.getMessage())
}
"support tell" in {
val actor = createActor(Props[OneWayTestActor].withDispatcher(app.dispatcherFactory.newDispatcher("test").build))
val result = actor ! "OneWay"
assert(OneWayTestActor.oneWay.await(1, TimeUnit.SECONDS))
actor.stop()
}
}
@Test
def shouldRespectThroughput {
val throughputDispatcher = Dispatchers.
newDispatcher("THROUGHPUT", 101, 0, Dispatchers.MAILBOX_TYPE).
setCorePoolSize(1).
build
"support sendReplySync" in {
val actor = createActor(Props[TestActor].withDispatcher(app.dispatcherFactory.newDispatcher("test").build))
val result = (actor.?("Hello", 10000)).as[String]
assert("World" === result.get)
actor.stop()
sys.error("what sense does this test make?")
}
val works = new AtomicBoolean(true)
val latch = new CountDownLatch(100)
val start = new CountDownLatch(1)
val fastOne = actorOf(
Props(context { case "sabotage" works.set(false) }).withDispatcher(throughputDispatcher))
"support ask/reply" in {
val actor = createActor(Props[TestActor].withDispatcher(app.dispatcherFactory.newDispatcher("test").build))
val result = (actor ? "Hello").as[String]
assert("World" === result.get)
actor.stop()
}
val slowOne = actorOf(
Props(context {
case "hogexecutor" start.await
case "ping" if (works.get) latch.countDown()
}).withDispatcher(throughputDispatcher))
"support ask/exception" in {
filterEvents(EventFilter[RuntimeException]("Expected")) {
val actor = createActor(Props[TestActor].withDispatcher(app.dispatcherFactory.newDispatcher("test").build))
try {
(actor ? "Failure").get
fail("Should have thrown an exception")
} catch {
case e
assert("Expected exception; to test fault-tolerance" === e.getMessage())
}
actor.stop()
}
}
slowOne ! "hogexecutor"
(1 to 100) foreach { _ slowOne ! "ping" }
fastOne ! "sabotage"
start.countDown()
val result = latch.await(5, TimeUnit.SECONDS)
fastOne.stop()
slowOne.stop()
assert(result === true)
}
"respect the throughput setting" in {
val throughputDispatcher = app.dispatcherFactory.
newDispatcher("THROUGHPUT", 101, 0, app.dispatcherFactory.MAILBOX_TYPE).
setCorePoolSize(1).
build
@Test
def shouldRespectThroughputDeadline {
val deadlineMs = 100
val throughputDispatcher = Dispatchers.
newDispatcher("THROUGHPUT", 2, deadlineMs, Dispatchers.MAILBOX_TYPE).
setCorePoolSize(1).
build
val works = new AtomicBoolean(true)
val latch = new CountDownLatch(1)
val start = new CountDownLatch(1)
val ready = new CountDownLatch(1)
val works = new AtomicBoolean(true)
val latch = new CountDownLatch(100)
val start = new CountDownLatch(1)
val fastOne = createActor(
Props(context { case "sabotage" works.set(false) }).withDispatcher(throughputDispatcher))
val fastOne = actorOf(
Props(context {
case "ping" if (works.get) latch.countDown(); context.self.stop()
}).withDispatcher(throughputDispatcher))
val slowOne = createActor(
Props(context {
case "hogexecutor" start.await
case "ping" if (works.get) latch.countDown()
}).withDispatcher(throughputDispatcher))
val slowOne = actorOf(
Props(context {
case "hogexecutor" ready.countDown(); start.await
case "ping" works.set(false); context.self.stop()
}).withDispatcher(throughputDispatcher))
slowOne ! "hogexecutor"
(1 to 100) foreach { _ slowOne ! "ping" }
fastOne ! "sabotage"
start.countDown()
val result = latch.await(5, TimeUnit.SECONDS)
fastOne.stop()
slowOne.stop()
assert(result === true)
}
slowOne ! "hogexecutor"
slowOne ! "ping"
fastOne ! "ping"
assert(ready.await(2, TimeUnit.SECONDS) === true)
Thread.sleep(deadlineMs + 10) // wait just a bit more than the deadline
start.countDown()
assert(latch.await(2, TimeUnit.SECONDS) === true)
"respect throughput deadline" in {
val deadlineMs = 100
val throughputDispatcher = app.dispatcherFactory.
newDispatcher("THROUGHPUT", 2, deadlineMs, app.dispatcherFactory.MAILBOX_TYPE).
setCorePoolSize(1).
build
val works = new AtomicBoolean(true)
val latch = new CountDownLatch(1)
val start = new CountDownLatch(1)
val ready = new CountDownLatch(1)
val fastOne = createActor(
Props(context {
case "ping" if (works.get) latch.countDown(); context.self.stop()
}).withDispatcher(throughputDispatcher))
val slowOne = createActor(
Props(context {
case "hogexecutor" ready.countDown(); start.await
case "ping" works.set(false); context.self.stop()
}).withDispatcher(throughputDispatcher))
slowOne ! "hogexecutor"
slowOne ! "ping"
fastOne ! "ping"
assert(ready.await(2, TimeUnit.SECONDS) === true)
Thread.sleep(deadlineMs + 10) // wait just a bit more than the deadline
start.countDown()
assert(latch.await(2, TimeUnit.SECONDS) === true)
}
}
}

View file

@ -1,18 +1,15 @@
package akka.actor.dispatch
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import org.scalatest.matchers.MustMatchers
import java.util.concurrent.CountDownLatch
import akka.actor.Actor
import Actor._
import akka.testkit.AkkaSpec
/**
* Tests the behavior of the executor based event driven dispatcher when multiple actors are being dispatched on it.
*
* @author Jan Van Besien
*/
class DispatcherActorsSpec extends JUnitSuite with MustMatchers {
class DispatcherActorsSpec extends AkkaSpec {
class SlowActor(finishedCounter: CountDownLatch) extends Actor {
def receive = {
@ -31,29 +28,30 @@ class DispatcherActorsSpec extends JUnitSuite with MustMatchers {
}
}
@Test
def slowActorShouldntBlockFastActor {
val sFinished = new CountDownLatch(50)
val fFinished = new CountDownLatch(10)
val s = actorOf(new SlowActor(sFinished), "SlowActor")
val f = actorOf(new FastActor(fFinished), "FastActor")
"A dispatcher and two actors" must {
"not block fast actors by slow actors" in {
val sFinished = new CountDownLatch(50)
val fFinished = new CountDownLatch(10)
val s = createActor(new SlowActor(sFinished))
val f = createActor(new FastActor(fFinished))
// send a lot of stuff to s
for (i 1 to 50) {
s ! i
// send a lot of stuff to s
for (i 1 to 50) {
s ! i
}
// send some messages to f
for (i 1 to 10) {
f ! i
}
// now assert that f is finished while s is still busy
fFinished.await
assert(sFinished.getCount > 0)
sFinished.await
assert(sFinished.getCount === 0)
f.stop()
s.stop()
}
// send some messages to f
for (i 1 to 10) {
f ! i
}
// now assert that f is finished while s is still busy
fFinished.await
assert(sFinished.getCount > 0)
sFinished.await
assert(sFinished.getCount === 0)
f.stop()
s.stop()
}
}

View file

@ -4,16 +4,15 @@
package akka.actor.dispatch
import java.util.concurrent.{ CountDownLatch, TimeUnit }
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import akka.config.Configuration
import scala.reflect.{ Manifest }
import akka.dispatch._
import akka.testkit.AkkaSpec
import akka.config.Configuration
class DispatchersSpec extends AkkaSpec {
import app.dispatcherFactory._
object DispatchersSpec {
import Dispatchers._
//
val tipe = "type"
val keepalivems = "keep-alive-time"
val corepoolsizefactor = "core-pool-size-factor"
@ -35,34 +34,29 @@ object DispatchersSpec {
lazy val allDispatchers: Map[String, Option[MessageDispatcher]] = {
validTypes.map(t (t, from(Configuration.fromMap(Map(tipe -> t))))).toMap
}
}
class DispatchersSpec extends JUnitSuite {
"Dispatchers" must {
import Dispatchers._
import DispatchersSpec._
"yield None if type is missing" in {
assert(from(Configuration.fromMap(Map())) === None)
}
@Test
def shouldYieldNoneIfTypeIsMissing {
assert(from(Configuration.fromMap(Map())) === None)
}
"throw IllegalArgumentException if type does not exist" in {
intercept[IllegalArgumentException] {
from(Configuration.fromMap(Map(tipe -> "typedoesntexist")))
}
}
@Test(expected = classOf[IllegalArgumentException])
def shouldThrowIllegalArgumentExceptionIfTypeDoesntExist {
from(Configuration.fromMap(Map(tipe -> "typedoesntexist")))
}
"get the correct types of dispatchers" in {
//It can create/obtain all defined types
assert(allDispatchers.values.forall(_.isDefined))
//All created/obtained dispatchers are of the expeced type/instance
assert(typesAndValidators.forall(tuple tuple._2(allDispatchers(tuple._1).get)))
}
@Test
def shouldGetTheCorrectTypesOfDispatchers {
//It can create/obtain all defined types
assert(allDispatchers.values.forall(_.isDefined))
//All created/obtained dispatchers are of the expeced type/instance
assert(typesAndValidators.forall(tuple tuple._2(allDispatchers(tuple._1).get)))
}
@Test
def defaultingToDefaultWhileLoadingTheDefaultShouldWork {
assert(from(Configuration.fromMap(Map())).getOrElse(defaultGlobalDispatcher) == defaultGlobalDispatcher)
"default to default while loading the default" in {
assert(from(Configuration.fromMap(Map())).getOrElse(defaultGlobalDispatcher) == defaultGlobalDispatcher)
}
}
}

View file

@ -1,16 +1,14 @@
package akka.actor.dispatch
import java.util.concurrent.{ CountDownLatch, TimeUnit }
import org.scalatest.junit.JUnitSuite
import org.junit.{ Test, Before, After }
import akka.actor.Actor._
import akka.event.EventHandler
import akka.testkit.TestEvent._
import akka.testkit.EventFilter
import akka.dispatch.{ PinnedDispatcher, Dispatchers }
import akka.actor.{ Props, Actor }
import akka.testkit.AkkaSpec
import org.scalatest.BeforeAndAfterEach
object PinnedActorSpec {
class TestActor extends Actor {
@ -21,57 +19,55 @@ object PinnedActorSpec {
}
}
class PinnedActorSpec extends JUnitSuite {
class PinnedActorSpec extends AkkaSpec with BeforeAndAfterEach {
import PinnedActorSpec._
private val unit = TimeUnit.MILLISECONDS
@Before
def beforeEach {
override def beforeEach {
EventHandler.notify(Mute(EventFilter[RuntimeException]("Failure")))
}
@After
def afterEach {
override def afterEach {
EventHandler.notify(UnMuteAll)
}
@Test
def shouldTell {
var oneWay = new CountDownLatch(1)
val actor = actorOf(Props(self { case "OneWay" oneWay.countDown() }).withDispatcher(new PinnedDispatcher()))
val result = actor ! "OneWay"
assert(oneWay.await(1, TimeUnit.SECONDS))
actor.stop()
}
"A PinnedActor" must {
@Test
def shouldSendReplySync = {
val actor = actorOf(Props[TestActor].withDispatcher(new PinnedDispatcher()))
val result = (actor.?("Hello", 10000)).as[String]
assert("World" === result.get)
actor.stop()
}
@Test
def shouldSendReplyAsync = {
val actor = actorOf(Props[TestActor].withDispatcher(new PinnedDispatcher()))
val result = (actor ? "Hello").as[String]
assert("World" === result.get)
actor.stop()
}
@Test
def shouldSendReceiveException = {
val actor = actorOf(Props[TestActor].withDispatcher(new PinnedDispatcher()))
EventHandler.notify(Mute(EventFilter[RuntimeException]("Expected exception; to test fault-tolerance")))
try {
(actor ? "Failure").get
fail("Should have thrown an exception")
} catch {
case e
assert("Expected exception; to test fault-tolerance" === e.getMessage())
"support tell" in {
var oneWay = new CountDownLatch(1)
val actor = createActor(Props(self { case "OneWay" oneWay.countDown() }).withDispatcher(app.dispatcherFactory.newPinnedDispatcher("test")))
val result = actor ! "OneWay"
assert(oneWay.await(1, TimeUnit.SECONDS))
actor.stop()
}
"support ask/reply sync" in {
val actor = createActor(Props[TestActor].withDispatcher(app.dispatcherFactory.newPinnedDispatcher("test")))
val result = (actor.?("Hello", 10000)).as[String]
assert("World" === result.get)
actor.stop()
sys.error("why does this test make sense?")
}
"support ask/reply" in {
val actor = createActor(Props[TestActor].withDispatcher(app.dispatcherFactory.newPinnedDispatcher("test")))
val result = (actor ? "Hello").as[String]
assert("World" === result.get)
actor.stop()
}
"support ask/exception" in {
val actor = createActor(Props[TestActor].withDispatcher(app.dispatcherFactory.newPinnedDispatcher("test")))
EventHandler.notify(Mute(EventFilter[RuntimeException]("Expected exception; to test fault-tolerance")))
try {
(actor ? "Failure").get
fail("Should have thrown an exception")
} catch {
case e
assert("Expected exception; to test fault-tolerance" === e.getMessage())
}
actor.stop()
}
actor.stop()
}
}

View file

@ -1,15 +1,12 @@
package akka.actor.routing
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit._
import akka.actor._
import akka.actor.Actor._
import akka.routing._
import java.util.concurrent.atomic.AtomicInteger
class ListenerSpec extends WordSpec with MustMatchers {
class ListenerSpec extends AkkaSpec {
"Listener" must {
@ -18,13 +15,13 @@ class ListenerSpec extends WordSpec with MustMatchers {
val barLatch = TestLatch(2)
val barCount = new AtomicInteger(0)
val broadcast = actorOf(new Actor with Listeners {
val broadcast = createActor(new Actor with Listeners {
def receive = listenerManagement orElse {
case "foo" gossip("bar")
}
})
def newListener = actorOf(new Actor {
def newListener = createActor(new Actor {
def receive = {
case "bar"
barCount.incrementAndGet

View file

@ -4,17 +4,15 @@
package akka.config
import org.junit.runner.RunWith
import org.scalatest.WordSpec
import org.scalatest.junit.JUnitRunner
import org.scalatest.matchers.MustMatchers
import akka.testkit.AkkaSpec
@RunWith(classOf[JUnitRunner])
class ConfigSpec extends WordSpec with MustMatchers {
class ConfigSpec extends AkkaSpec {
"The default configuration file (i.e. akka-reference.conf)" must {
"contain all configuration properties for akka-actor that are used in code with their correct defaults" in {
import Config.config._
val config = app.config
import config._
getList("akka.boot") must equal(Nil)
getString("akka.time-unit") must equal(Some("seconds"))

View file

@ -1,21 +1,18 @@
package akka.dispatch
import org.scalatest.junit.JUnitSuite
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import org.scalatest.BeforeAndAfterAll
import org.scalatest.prop.Checkers
import org.scalacheck._
import org.scalacheck.Arbitrary._
import org.scalacheck.Prop._
import org.scalacheck.Gen._
import akka.actor.{ Actor, ActorRef, Timeout }
import Actor._
import akka.testkit.{ EventFilter, filterEvents, filterException }
import akka.util.duration._
import org.multiverse.api.latches.StandardLatch
import java.util.concurrent.{ TimeUnit, CountDownLatch }
import akka.testkit.AkkaSpec
import org.scalatest.junit.JUnitSuite
object FutureSpec {
class TestActor extends Actor {
@ -43,7 +40,7 @@ object FutureSpec {
class JavaFutureSpec extends JavaFutureTests with JUnitSuite
class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAndAfterAll {
class FutureSpec extends AkkaSpec with Checkers with BeforeAndAfterAll {
import FutureSpec._
"A Promise" when {
@ -119,7 +116,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"from an Actor" that {
"returns a result" must {
behave like futureWithResult { test
val actor = actorOf[TestActor]
val actor = createActor[TestActor]
val future = actor ? "Hello"
future.await
test(future, "World")
@ -129,7 +126,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"throws an exception" must {
behave like futureWithException[RuntimeException] { test
filterException[RuntimeException] {
val actor = actorOf[TestActor]
val actor = createActor[TestActor]
val future = actor ? "Failure"
future.await
test(future, "Expected exception; to test fault-tolerance")
@ -142,8 +139,8 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"using flatMap with an Actor" that {
"will return a result" must {
behave like futureWithResult { test
val actor1 = actorOf[TestActor]
val actor2 = actorOf(new Actor { def receive = { case s: String reply(s.toUpperCase) } })
val actor1 = createActor[TestActor]
val actor2 = createActor(new Actor { def receive = { case s: String reply(s.toUpperCase) } })
val future = actor1 ? "Hello" flatMap { case s: String actor2 ? s }
future.await
test(future, "WORLD")
@ -154,8 +151,8 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"will throw an exception" must {
behave like futureWithException[ArithmeticException] { test
filterException[ArithmeticException] {
val actor1 = actorOf[TestActor]
val actor2 = actorOf(new Actor { def receive = { case s: String reply(s.length / 0) } })
val actor1 = createActor[TestActor]
val actor2 = createActor(new Actor { def receive = { case s: String reply(s.length / 0) } })
val future = actor1 ? "Hello" flatMap { case s: String actor2 ? s }
future.await
test(future, "/ by zero")
@ -167,8 +164,8 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"will throw a MatchError when matching wrong type" must {
behave like futureWithException[MatchError] { test
filterException[MatchError] {
val actor1 = actorOf[TestActor]
val actor2 = actorOf(new Actor { def receive = { case s: String reply(s.toUpperCase) } })
val actor1 = createActor[TestActor]
val actor2 = createActor(new Actor { def receive = { case s: String reply(s.toUpperCase) } })
val future = actor1 ? "Hello" flatMap { case i: Int actor2 ? i }
future.await
test(future, "World (of class java.lang.String)")
@ -183,7 +180,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"compose with for-comprehensions" in {
filterException[ClassCastException] {
val actor = actorOf(new Actor {
val actor = createActor(new Actor {
def receive = {
case s: String reply(s.length)
case i: Int reply((i * 2).toString)
@ -215,7 +212,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
filterException[MatchError] {
case class Req[T](req: T)
case class Res[T](res: T)
val actor = actorOf(new Actor {
val actor = createActor(new Actor {
def receive = {
case Req(s: String) reply(Res(s.length))
case Req(i: Int) reply(Res((i * 2).toString))
@ -260,7 +257,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
val future7 = future3 recover { case e: ArithmeticException "You got ERROR" }
val actor = actorOf[TestActor]
val actor = createActor[TestActor]
val future8 = actor ? "Failure"
val future9 = actor ? "Failure" recover {
@ -294,27 +291,27 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"find" in {
val futures = for (i 1 to 10) yield Future { i }
val result = Future.find[Int](_ == 3)(futures)
val result = Future.find[Int](futures)(_ == 3)
result.get must be(Some(3))
val notFound = Future.find[Int](_ == 11)(futures)
val notFound = Future.find[Int](futures)(_ == 11)
notFound.get must be(None)
}
"fold" in {
val actors = (1 to 10).toList map { _
actorOf(new Actor {
createActor(new Actor {
def receive = { case (add: Int, wait: Int) Thread.sleep(wait); tryReply(add) }
})
}
val timeout = 10000
def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) actor.?((idx, idx * 200), timeout).mapTo[Int] }
Future.fold(0, timeout)(futures)(_ + _).get must be(45)
Future.fold(futures, timeout)(0)(_ + _).get must be(45)
}
"fold by composing" in {
val actors = (1 to 10).toList map { _
actorOf(new Actor {
createActor(new Actor {
def receive = { case (add: Int, wait: Int) Thread.sleep(wait); tryReply(add) }
})
}
@ -325,7 +322,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"fold with an exception" in {
filterException[IllegalArgumentException] {
val actors = (1 to 10).toList map { _
actorOf(new Actor {
createActor(new Actor {
def receive = {
case (add: Int, wait: Int)
Thread.sleep(wait)
@ -336,7 +333,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
}
val timeout = 10000
def futures = actors.zipWithIndex map { case (actor: ActorRef, idx: Int) actor.?((idx, idx * 100), timeout).mapTo[Int] }
Future.fold(0, timeout)(futures)(_ + _).await.exception.get.getMessage must be("shouldFoldResultsWithException: expected")
Future.fold(futures, timeout)(0)(_ + _).await.exception.get.getMessage must be("shouldFoldResultsWithException: expected")
}
}
@ -344,7 +341,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
import scala.collection.mutable.ArrayBuffer
def test(testNumber: Int) {
val fs = (0 to 1000) map (i Future(i, 10000))
val result = Future.fold(ArrayBuffer.empty[AnyRef], 10000)(fs) {
val result = Future.fold(fs, 10000)(ArrayBuffer.empty[AnyRef]) {
case (l, i) if i % 2 == 0 l += i.asInstanceOf[AnyRef]
case (l, _) l
}.get.asInstanceOf[ArrayBuffer[Int]].sum
@ -356,12 +353,12 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
}
"return zero value if folding empty list" in {
Future.fold(0)(List[Future[Int]]())(_ + _).get must be(0)
Future.fold(List[Future[Int]]())(0)(_ + _).get must be(0)
}
"shouldReduceResults" in {
val actors = (1 to 10).toList map { _
actorOf(new Actor {
createActor(new Actor {
def receive = { case (add: Int, wait: Int) Thread.sleep(wait); tryReply(add) }
})
}
@ -373,7 +370,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"shouldReduceResultsWithException" in {
filterException[IllegalArgumentException] {
val actors = (1 to 10).toList map { _
actorOf(new Actor {
createActor(new Actor {
def receive = {
case (add: Int, wait: Int)
Thread.sleep(wait)
@ -396,14 +393,14 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"receiveShouldExecuteOnComplete" in {
val latch = new StandardLatch
val actor = actorOf[TestActor]
val actor = createActor[TestActor]
actor ? "Hello" onResult { case "World" latch.open }
assert(latch.tryAwait(5, TimeUnit.SECONDS))
actor.stop()
}
"shouldTraverseFutures" in {
val oddActor = actorOf(new Actor {
val oddActor = createActor(new Actor {
var counter = 1
def receive = {
case 'GetNext
@ -445,7 +442,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
Thread sleep 100
// make sure all futures are completed in dispatcher
assert(Dispatchers.defaultGlobalDispatcher.tasks === 0)
assert(implicitly[MessageDispatcher].tasks === 0)
}
}
@ -470,7 +467,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"futureComposingWithContinuations" in {
import Future.flow
val actor = actorOf[TestActor]
val actor = createActor[TestActor]
val x = Future("Hello")
val y = x flatMap (actor ? _) mapTo manifest[String]
@ -499,7 +496,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
filterException[ClassCastException] {
import Future.flow
val actor = actorOf[TestActor]
val actor = createActor[TestActor]
val x = Future(3)
val y = (actor ? "Hello").mapTo[Int]
@ -514,7 +511,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
filterException[ClassCastException] {
import Future.flow
val actor = actorOf[TestActor]
val actor = createActor[TestActor]
val x = Future("Hello")
val y = actor ? "Hello" mapTo manifest[Nothing]
@ -566,7 +563,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
Thread.sleep(100)
// make sure all futures are completed in dispatcher
assert(Dispatchers.defaultGlobalDispatcher.tasks === 0)
assert(implicitly[MessageDispatcher].tasks === 0)
}
"shouldNotAddOrRunCallbacksAfterFailureToBeCompletedBeforeExpiry" in {
@ -777,7 +774,7 @@ class FutureSpec extends WordSpec with MustMatchers with Checkers with BeforeAnd
"ticket812FutureDispatchCleanup" in {
filterException[FutureTimeoutException] {
implicit val dispatcher = new Dispatcher("ticket812FutureDispatchCleanup")
implicit val dispatcher = app.dispatcherFactory.newDispatcher("ticket812FutureDispatchCleanup").build
assert(dispatcher.tasks === 0)
val future = Future({ Thread.sleep(100); "Done" }, 10)
intercept[FutureTimeoutException] { future.await }

View file

@ -4,15 +4,15 @@ import org.scalatest.matchers.MustMatchers
import org.scalatest.{ BeforeAndAfterAll, BeforeAndAfterEach }
import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith
import akka.actor.Actor.{ actorOf }
import java.util.concurrent.{ TimeUnit, CountDownLatch, BlockingQueue }
import java.util.{ Queue }
import akka.util._
import akka.util.Duration._
import akka.actor.{ LocalActorRef, Actor, ActorRegistry, NullChannel }
import akka.testkit.AkkaSpec
@RunWith(classOf[JUnitRunner])
abstract class MailboxSpec extends WordSpec with MustMatchers with BeforeAndAfterAll with BeforeAndAfterEach {
abstract class MailboxSpec extends AkkaSpec with BeforeAndAfterAll with BeforeAndAfterEach {
def name: String
def factory: MailboxType Mailbox
@ -82,7 +82,7 @@ abstract class MailboxSpec extends WordSpec with MustMatchers with BeforeAndAfte
def createMessageInvocation(msg: Any): Envelope = {
new Envelope(
actorOf(new Actor { //Dummy actor
createActor(new Actor { //Dummy actor
def receive = { case _ }
}).asInstanceOf[LocalActorRef].underlying, msg, NullChannel)
}

View file

@ -1,11 +1,9 @@
package akka.dispatch
import akka.actor.Actor._
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.actor.{ Props, LocalActorRef, Actor }
import akka.testkit.AkkaSpec
class PriorityDispatcherSpec extends WordSpec with MustMatchers {
class PriorityDispatcherSpec extends AkkaSpec {
"A PriorityDispatcher" must {
"Order it's messages according to the specified comparator using an unbounded mailbox" in {
@ -19,14 +17,14 @@ class PriorityDispatcherSpec extends WordSpec with MustMatchers {
testOrdering(BoundedPriorityMailbox(PriorityGenerator({
case i: Int i //Reverse order
case 'Result Int.MaxValue
}: Any Int), 1000))
}: Any Int), 1000, app.AkkaConfig.MailboxPushTimeout))
}
}
def testOrdering(mboxType: MailboxType) {
val dispatcher = new Dispatcher("Test", throughput = 1, mailboxType = mboxType)
val dispatcher = app.dispatcherFactory.newDispatcher("Test", 1, -1, mboxType).build
val actor = actorOf(Props(new Actor {
val actor = createActor(Props(new Actor {
var acc: List[Int] = Nil
def receive = {

View file

@ -1,172 +1,167 @@
package akka.dispatch
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import Future.flow
import akka.util.cps._
import akka.actor.Timeout
import akka.util.duration._
import akka.testkit.AkkaSpec
class PromiseStreamSpec extends JUnitSuite {
@Test
def simpleTest {
val a, b, c = Promise[Int]()
val q = PromiseStream[Int]()
flow { q << (1, 2, 3) }
flow {
a << q()
b << q
c << q()
}
assert(a.get === 1)
assert(b.get === 2)
assert(c.get === 3)
}
class PromiseStreamSpec extends AkkaSpec {
@Test
def pendingTest {
val a, b, c = Promise[Int]()
val q = PromiseStream[Int]()
flow {
a << q
b << q()
c << q
}
flow { q <<< List(1, 2, 3) }
assert(a.get === 1)
assert(b.get === 2)
assert(c.get === 3)
}
"A PromiseStream" must {
@Test
def timeoutTest {
val a, c = Promise[Int]()
val b = Promise[Int](0)
val q = PromiseStream[Int](1000)
flow {
a << q()
b << q()
c << q()
}
Thread.sleep(10)
flow {
q << (1, 2)
q << 3
}
assert(a.get === 1)
intercept[FutureTimeoutException] { b.get }
assert(c.get === 3)
}
@Test
def timeoutTest2 {
val q = PromiseStream[Int](500)
val a = q.dequeue()
val b = q.dequeue()
q += 1
Thread.sleep(500)
q += (2, 3)
val c = q.dequeue()
val d = q.dequeue()
assert(a.get === 1)
intercept[FutureTimeoutException] { b.get }
assert(c.get === 2)
assert(d.get === 3)
}
@Test
def pendingTest2 {
val a, b, c, d = Promise[Int]()
val q1, q2 = PromiseStream[Int]()
val oneTwo = Future(List(1, 2))
flow {
a << q2
b << q2
q1 << 3 << 4
}
flow {
q2 <<< oneTwo
c << q1
d << q1
}
assert(a.get === 1)
assert(b.get === 2)
assert(c.get === 3)
assert(d.get === 4)
}
@Test
def pendingEnqueueTest {
val q = PromiseStream[Int]()
val a = q.dequeue()
val b = q.dequeue()
val c, d = Promise[Int]()
flow {
c << q
d << q
}
q ++= List(1, 2, 3, 4)
assert(a.get === 1)
assert(b.get === 2)
assert(c.get === 3)
assert(d.get === 4)
}
@Test
def mapTest {
val qs = PromiseStream[String]()
val qi = qs.map(_.length)
val a, c = Promise[Int]()
val b = Promise[String]()
flow {
a << qi
b << qs
c << qi
}
flow {
qs << ("Hello", "World!", "Test")
}
assert(a.get === 5)
assert(b.get === "World!")
assert(c.get === 4)
}
@Test
def concurrentStressTest {
implicit val timeout = Timeout(60 seconds)
val q = PromiseStream[Long](timeout.duration.toMillis)
flow {
var n = 0L
repeatC(50000) {
n += 1
q << n
"work" in {
val a, b, c = Promise[Int]()
val q = PromiseStream[Int]()
flow { q << (1, 2, 3) }
flow {
a << q()
b << q
c << q()
}
assert(a.get === 1)
assert(b.get === 2)
assert(c.get === 3)
}
val future = Future sequence {
List.fill(10) {
flow {
var total = 0L
repeatC(10000) {
val n = q()
total += n
}
total
"pend" in {
val a, b, c = Promise[Int]()
val q = PromiseStream[Int]()
flow {
a << q
b << q()
c << q
}
flow { q <<< List(1, 2, 3) }
assert(a.get === 1)
assert(b.get === 2)
assert(c.get === 3)
}
"timeout" in {
val a, c = Promise[Int]()
val b = Promise[Int](0)
val q = PromiseStream[Int](1000)
flow {
a << q()
b << q()
c << q()
}
Thread.sleep(10)
flow {
q << (1, 2)
q << 3
}
assert(a.get === 1)
intercept[FutureTimeoutException] { b.get }
assert(c.get === 3)
}
"timeout again" in {
val q = PromiseStream[Int](500)
val a = q.dequeue()
val b = q.dequeue()
q += 1
Thread.sleep(500)
q += (2, 3)
val c = q.dequeue()
val d = q.dequeue()
assert(a.get === 1)
intercept[FutureTimeoutException] { b.get }
assert(c.get === 2)
assert(d.get === 3)
}
"pend again" in {
val a, b, c, d = Promise[Int]()
val q1, q2 = PromiseStream[Int]()
val oneTwo = Future(List(1, 2))
flow {
a << q2
b << q2
q1 << 3 << 4
}
flow {
q2 <<< oneTwo
c << q1
d << q1
}
assert(a.get === 1)
assert(b.get === 2)
assert(c.get === 3)
assert(d.get === 4)
}
"enque" in {
val q = PromiseStream[Int]()
val a = q.dequeue()
val b = q.dequeue()
val c, d = Promise[Int]()
flow {
c << q
d << q
}
q ++= List(1, 2, 3, 4)
assert(a.get === 1)
assert(b.get === 2)
assert(c.get === 3)
assert(d.get === 4)
}
"map" in {
val qs = PromiseStream[String]()
val qi = qs.map(_.length)
val a, c = Promise[Int]()
val b = Promise[String]()
flow {
a << qi
b << qs
c << qi
}
flow {
qs << ("Hello", "World!", "Test")
}
assert(a.get === 5)
assert(b.get === "World!")
assert(c.get === 4)
}
"not fail under concurrent stress" in {
implicit val timeout = Timeout(60 seconds)
val q = PromiseStream[Long](timeout.duration.toMillis)
flow {
var n = 0L
repeatC(50000) {
n += 1
q << n
}
}
} map (_.sum)
flow {
var n = 50000L
repeatC(50000) {
n += 1
q << n
val future = Future sequence {
List.fill(10) {
flow {
var total = 0L
repeatC(10000) {
val n = q()
total += n
}
total
}
}
} map (_.sum)
flow {
var n = 50000L
repeatC(50000) {
n += 1
q << n
}
}
}
val result = future.get
assert(result === (1L to 100000L).sum)
val result = future.get
assert(result === (1L to 100000L).sum)
}
}
}

View file

@ -1,27 +1,24 @@
package akka.performance.trading.common
import org.junit._
import Assert._
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import akka.performance.trading.domain._
import akka.performance.trading.common._
import akka.actor.Actor.actorOf
import akka.dispatch.Dispatchers
import akka.event.EventHandler
import akka.actor.{ Props, ActorRef, Actor, PoisonPill }
import akka.AkkaApplication
abstract class AkkaPerformanceTest extends BenchmarkScenarios {
abstract class AkkaPerformanceTest(val app: AkkaApplication) extends BenchmarkScenarios {
type TS = AkkaTradingSystem
val clientDispatcher = Dispatchers.newDispatcher("client-dispatcher")
val clientDispatcher = app.dispatcherFactory.newDispatcher("client-dispatcher")
.withNewThreadPoolWithLinkedBlockingQueueWithUnboundedCapacity
.setCorePoolSize(maxClients)
.setMaxPoolSize(maxClients)
.build
override def createTradingSystem: TS = new AkkaTradingSystem
override def createTradingSystem: TS = new AkkaTradingSystem(app)
/**
* Implemented in subclass
@ -38,14 +35,14 @@ abstract class AkkaPerformanceTest extends BenchmarkScenarios {
val clients = (for (i 0 until numberOfClients) yield {
val receiver = receivers(i % receivers.size)
Props(new Client(receiver, orders, latch, repeatsPerClient + (if (i < oddRepeats) 1 else 0), delayMs)).withDispatcher(clientDispatcher)
}).toList.map(actorOf(_))
}).toList.map(app.createActor(_))
clients.foreach(_ ! "run")
val ok = latch.await((5000 + (2 + delayMs) * totalNumberOfRequests) * timeDilation, TimeUnit.MILLISECONDS)
val durationNs = (System.nanoTime - start)
assertTrue(ok)
assertEquals((orders.size / 2) * repeat, TotalTradeCounter.counter.get)
assert(ok)
assert((orders.size / 2) * repeat == TotalTradeCounter.counter.get)
logMeasurement(scenario, numberOfClients, durationNs)
clients.foreach(_ ! PoisonPill)
}

View file

@ -1,15 +1,12 @@
package akka.performance.trading.common
import java.util.Random
import scala.collection.immutable.TreeMap
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics
import org.apache.commons.math.stat.descriptive.SynchronizedDescriptiveStatistics
import org.junit.After
import org.junit.Before
import org.scalatest.junit.JUnitSuite
import akka.performance.trading.domain.Ask
import akka.performance.trading.domain.Bid
import akka.performance.trading.domain.Order
@ -17,9 +14,12 @@ import akka.performance.trading.domain.TotalTradeCounter
import akka.performance.workbench.BenchResultRepository
import akka.performance.workbench.Report
import akka.performance.workbench.Stats
import akka.AkkaApplication
trait PerformanceTest extends JUnitSuite {
def app: AkkaApplication
// jvm parameters
// -server -Xms512m -Xmx1024m -XX:+UseConcMarkSweepGC
@ -52,7 +52,7 @@ trait PerformanceTest extends JUnitSuite {
var stat: DescriptiveStatistics = _
val resultRepository = BenchResultRepository()
lazy val report = new Report(resultRepository, compareResultWith)
lazy val report = new Report(app, resultRepository, compareResultWith)
type TS <: TradingSystem

View file

@ -5,6 +5,7 @@ import akka.performance.trading.domain.OrderbookRepository
import akka.actor.Actor._
import akka.dispatch.MessageDispatcher
import akka.actor.{ Props, ActorRef, PoisonPill }
import akka.AkkaApplication
trait TradingSystem {
type ME
@ -33,7 +34,7 @@ trait TradingSystem {
case class MatchingEngineInfo(primary: ME, standby: Option[ME], orderbooks: List[Orderbook])
}
class AkkaTradingSystem extends TradingSystem {
class AkkaTradingSystem(val app: AkkaApplication) extends TradingSystem {
type ME = ActorRef
type OR = ActorRef
@ -69,8 +70,8 @@ class AkkaTradingSystem extends TradingSystem {
def createMatchingEngine(meId: String, orderbooks: List[Orderbook]) =
meDispatcher match {
case Some(d) actorOf(Props(new AkkaMatchingEngine(meId, orderbooks)).withDispatcher(d))
case _ actorOf(Props(new AkkaMatchingEngine(meId, orderbooks)))
case Some(d) app.createActor(Props(new AkkaMatchingEngine(meId, orderbooks)).withDispatcher(d))
case _ app.createActor(Props(new AkkaMatchingEngine(meId, orderbooks)))
}
override def createOrderReceivers: List[ActorRef] = {
@ -90,8 +91,8 @@ class AkkaTradingSystem extends TradingSystem {
}
def createOrderReceiver() = orDispatcher match {
case Some(d) actorOf(Props(new AkkaOrderReceiver()).withDispatcher(d))
case _ actorOf(Props(new AkkaOrderReceiver()))
case Some(d) app.createActor(Props(new AkkaOrderReceiver()).withDispatcher(d))
case _ app.createActor(Props(new AkkaOrderReceiver()))
}
override def start() {

View file

@ -1,21 +1,19 @@
package akka.performance.trading.oneway
import java.util.concurrent.TimeUnit
import org.junit.Test
import akka.actor.Actor.actorOf
import akka.performance.trading.common.AkkaPerformanceTest
import akka.performance.trading.common.Rsp
import akka.performance.trading.domain._
import akka.actor.{ Props, ActorRef }
import akka.AkkaApplication
class OneWayPerformanceTest extends AkkaPerformanceTest {
class OneWayPerformanceTest extends AkkaPerformanceTest(AkkaApplication()) {
override def createTradingSystem: TS = new OneWayTradingSystem {
override def createTradingSystem: TS = new OneWayTradingSystem(app) {
override def createMatchingEngine(meId: String, orderbooks: List[Orderbook]) = meDispatcher match {
case Some(d) actorOf(Props(new OneWayMatchingEngine(meId, orderbooks) with LatchMessageCountDown).withDispatcher(d))
case _ actorOf(new OneWayMatchingEngine(meId, orderbooks) with LatchMessageCountDown)
case Some(d) app.createActor(Props(new OneWayMatchingEngine(meId, orderbooks) with LatchMessageCountDown).withDispatcher(d))
case _ app.createActor(new OneWayMatchingEngine(meId, orderbooks) with LatchMessageCountDown)
}
}

View file

@ -1,20 +1,20 @@
package akka.performance.trading.oneway
import akka.actor.Actor.actorOf
import akka.performance.trading.common.AkkaTradingSystem
import akka.performance.trading.domain.Orderbook
import akka.actor.{ Props, ActorRef }
import akka.AkkaApplication
class OneWayTradingSystem extends AkkaTradingSystem {
class OneWayTradingSystem(_app: AkkaApplication) extends AkkaTradingSystem(_app) {
override def createMatchingEngine(meId: String, orderbooks: List[Orderbook]) = meDispatcher match {
case Some(d) actorOf(Props(new OneWayMatchingEngine(meId, orderbooks)).withDispatcher(d))
case _ actorOf(Props(new OneWayMatchingEngine(meId, orderbooks)))
case Some(d) app.createActor(Props(new OneWayMatchingEngine(meId, orderbooks)).withDispatcher(d))
case _ app.createActor(Props(new OneWayMatchingEngine(meId, orderbooks)))
}
override def createOrderReceiver() = orDispatcher match {
case Some(d) actorOf(Props[OneWayOrderReceiver].withDispatcher(d))
case _ actorOf(Props[OneWayOrderReceiver])
case Some(d) app.createActor(Props[OneWayOrderReceiver].withDispatcher(d))
case _ app.createActor(Props[OneWayOrderReceiver])
}
}

View file

@ -1,13 +1,15 @@
package akka.performance.trading.response
import org.junit.Test
import akka.actor.ActorRef
import akka.performance.trading.common.AkkaPerformanceTest
import akka.performance.trading.domain.Order
import akka.performance.trading.common.Rsp
import akka.AkkaApplication
class RspPerformanceTest extends AkkaPerformanceTest {
class RspPerformanceTest extends AkkaPerformanceTest(AkkaApplication()) {
implicit def appl = app
override def placeOrder(orderReceiver: ActorRef, order: Order): Rsp = {
(orderReceiver ? order).get.asInstanceOf[Rsp]

View file

@ -3,17 +3,14 @@ package akka.performance.workbench
import java.lang.management.ManagementFactory
import java.text.SimpleDateFormat
import java.util.Date
import scala.collection.JavaConversions.asScalaBuffer
import scala.collection.JavaConversions.enumerationAsScalaIterator
import akka.event.EventHandler
import akka.config.Config
import akka.config.Config.config
import akka.AkkaApplication
class Report(
resultRepository: BenchResultRepository,
compareResultWith: Option[String] = None) {
class Report(app: AkkaApplication,
resultRepository: BenchResultRepository,
compareResultWith: Option[String] = None) {
private def log = System.getProperty("benchmark.logResult", "true").toBoolean
@ -189,11 +186,11 @@ class Report(
sb.append("Args:\n ").append(args)
sb.append("\n")
sb.append("Akka version: ").append(Config.CONFIG_VERSION)
sb.append("Akka version: ").append(app.AkkaConfig.CONFIG_VERSION)
sb.append("\n")
sb.append("Akka config:")
for (key config.keys) {
sb.append("\n ").append(key).append("=").append(config(key))
for (key app.config.keys) {
sb.append("\n ").append(key).append("=").append(app.config(key))
}
sb.toString

View file

@ -1,17 +1,14 @@
package akka.routing
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.dispatch.{ KeptPromise, Future }
import akka.actor._
import akka.actor.Actor._
import akka.testkit.Testing._
import akka.actor.{ TypedActor, Actor, Props }
import akka.testkit.{ TestLatch, filterEvents, EventFilter, filterException }
import akka.util.duration._
import java.util.concurrent.atomic.{ AtomicBoolean, AtomicInteger }
import akka.testkit.AkkaSpec
object ActorPoolSpec {
class ActorPoolSpec extends AkkaSpec {
trait Foo {
def sq(x: Int, sleep: Long): Future[Int]
@ -25,10 +22,6 @@ object ActorPoolSpec {
}
val faultHandler = OneForOneStrategy(List(classOf[Exception]), 5, 1000)
}
class ActorPoolSpec extends WordSpec with MustMatchers {
import akka.routing.ActorPoolSpec._
"Actor Pool" must {
@ -36,9 +29,9 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
val latch = TestLatch(2)
val count = new AtomicInteger(0)
val pool = actorOf(
val pool = createActor(
Props(new Actor with DefaultActorPool with FixedCapacityStrategy with SmallestMailboxSelector {
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
def receive = {
case _
count.incrementAndGet
@ -54,7 +47,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
}).withFaultHandler(faultHandler))
val successes = TestLatch(2)
val successCounter = actorOf(new Actor {
val successCounter = createActor(new Actor {
def receive = {
case "success" successes.countDown()
}
@ -75,7 +68,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
}
"pass ticket #705" in {
val pool = actorOf(
val pool = createActor(
Props(new Actor with DefaultActorPool with BoundedCapacityStrategy with MailboxPressureCapacitor with SmallestMailboxSelector with BasicFilter {
def lowerBound = 2
def upperBound = 20
@ -86,7 +79,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
def selectionCount = 1
def receive = _route
def pressureThreshold = 1
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
def receive = {
case req: String {
sleepFor(10 millis)
@ -112,9 +105,9 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
var latch = TestLatch(3)
val count = new AtomicInteger(0)
val pool = actorOf(
val pool = createActor(
Props(new Actor with DefaultActorPool with BoundedCapacityStrategy with ActiveFuturesPressureCapacitor with SmallestMailboxSelector with BasicNoBackoffFilter {
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
def receive = {
case n: Int
sleepFor(n millis)
@ -176,9 +169,9 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
var latch = TestLatch(3)
val count = new AtomicInteger(0)
val pool = actorOf(
val pool = createActor(
Props(new Actor with DefaultActorPool with BoundedCapacityStrategy with MailboxPressureCapacitor with SmallestMailboxSelector with BasicNoBackoffFilter {
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
def receive = {
case n: Int
sleepFor(n millis)
@ -229,10 +222,10 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
val latch1 = TestLatch(2)
val delegates = new java.util.concurrent.ConcurrentHashMap[String, String]
val pool1 = actorOf(
val pool1 = createActor(
Props(new Actor with DefaultActorPool with FixedCapacityStrategy with RoundRobinSelector with BasicNoBackoffFilter {
def instance(p: Props): ActorRef = actorOf(p.withCreator(new Actor {
def instance(p: Props): ActorRef = createActor(p.withCreator(new Actor {
def receive = {
case _
delegates put (self.uuid.toString, "")
@ -258,9 +251,9 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
val latch2 = TestLatch(2)
delegates.clear()
val pool2 = actorOf(
val pool2 = createActor(
Props(new Actor with DefaultActorPool with FixedCapacityStrategy with RoundRobinSelector with BasicNoBackoffFilter {
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
def receive = {
case _
delegates put (self.uuid.toString, "")
@ -287,9 +280,9 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
"backoff" in {
val latch = TestLatch(10)
val pool = actorOf(
val pool = createActor(
Props(new Actor with DefaultActorPool with BoundedCapacityStrategy with MailboxPressureCapacitor with SmallestMailboxSelector with Filter with RunningMeanBackoff with BasicRampup {
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
def receive = {
case n: Int
sleepFor(n millis)
@ -332,7 +325,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
"support typed actors" in {
import RoutingSpec._
import TypedActor._
import app.typedActor._
def createPool = new Actor with DefaultActorPool with BoundedCapacityStrategy with MailboxPressureCapacitor with SmallestMailboxSelector with Filter with RunningMeanBackoff with BasicRampup {
def lowerBound = 1
def upperBound = 5
@ -359,7 +352,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
val deathCount = new AtomicInteger(0)
val keepDying = new AtomicBoolean(false)
val pool1 = actorOf(
val pool1 = createActor(
Props(new Actor with DefaultActorPool with BoundedCapacityStrategy with ActiveFuturesPressureCapacitor with SmallestMailboxSelector with BasicFilter {
def lowerBound = 2
def upperBound = 5
@ -370,7 +363,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
def selectionCount = 1
def receive = _route
def pressureThreshold = 1
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
if (deathCount.get > 5) deathCount.set(0)
if (deathCount.get > 0) { deathCount.incrementAndGet; throw new IllegalStateException("keep dying") }
def receive = {
@ -382,7 +375,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
}))
}).withFaultHandler(faultHandler))
val pool2 = actorOf(
val pool2 = createActor(
Props(new Actor with DefaultActorPool with BoundedCapacityStrategy with ActiveFuturesPressureCapacitor with SmallestMailboxSelector with BasicFilter {
def lowerBound = 2
def upperBound = 5
@ -393,7 +386,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
def selectionCount = 1
def receive = _route
def pressureThreshold = 1
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
if (deathCount.get > 5) deathCount.set(0)
if (deathCount.get > 0) { deathCount.incrementAndGet; throw new IllegalStateException("keep dying") }
def receive = {
@ -405,7 +398,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
}))
}).withFaultHandler(faultHandler))
val pool3 = actorOf(
val pool3 = createActor(
Props(new Actor with DefaultActorPool with BoundedCapacityStrategy with ActiveFuturesPressureCapacitor with RoundRobinSelector with BasicFilter {
def lowerBound = 2
def upperBound = 5
@ -416,7 +409,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
def selectionCount = 1
def receive = _route
def pressureThreshold = 1
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
if (deathCount.get > 5) deathCount.set(0)
if (deathCount.get > 0) { deathCount.incrementAndGet; throw new IllegalStateException("keep dying") }
@ -503,7 +496,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
object BadState
val pool1 = actorOf(
val pool1 = createActor(
Props(new Actor with DefaultActorPool with BoundedCapacityStrategy with ActiveFuturesPressureCapacitor with SmallestMailboxSelector with BasicFilter {
def lowerBound = 2
def upperBound = 5
@ -514,7 +507,7 @@ class ActorPoolSpec extends WordSpec with MustMatchers {
def selectionCount = 1
def receive = _route
def pressureThreshold = 1
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
if (deathCount.get > 5) deathCount.set(0)
if (deathCount.get > 0) { deathCount.incrementAndGet; throw new IllegalStateException("keep dying") }
def receive = {

View file

@ -1,25 +1,21 @@
package akka.routing
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.actor._
import Actor._
import DeploymentConfig._
import akka.routing._
import Routing.Broadcast
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.{ CountDownLatch, TimeUnit }
import akka.testkit.AkkaSpec
import akka.actor.DeploymentConfig._
import akka.routing.Routing.Broadcast
class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
class ConfiguredLocalRoutingSpec extends AkkaSpec {
"round robin router" must {
"be able to shut down its instance" in {
val address = "round-robin-0"
Deployer.deploy(
app.deployer.deploy(
Deploy(
address,
None,
@ -31,7 +27,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
val helloLatch = new CountDownLatch(5)
val stopLatch = new CountDownLatch(5)
val actor = actorOf(new Actor {
val actor = app.createActor(Props(new Actor {
def receive = {
case "hello" helloLatch.countDown()
}
@ -39,7 +35,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
override def postStop() {
stopLatch.countDown()
}
}, address)
}), address)
actor ! "hello"
actor ! "hello"
@ -55,7 +51,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
"deliver messages in a round robin fashion" in {
val address = "round-robin-1"
Deployer.deploy(
app.deployer.deploy(
Deploy(
address,
None,
@ -74,13 +70,13 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
replies = replies + (i -> 0)
}
val actor = actorOf(new Actor {
val actor = app.createActor(Props(new Actor {
lazy val id = counter.getAndIncrement()
def receive = {
case "hit" reply(id)
case "end" doneLatch.countDown()
}
}, address)
}), address)
for (i 0 until iterationCount) {
for (k 0 until connectionCount) {
@ -100,7 +96,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
"deliver a broadcast message using the !" in {
val address = "round-robin-2"
Deployer.deploy(
app.deployer.deploy(
Deploy(
address,
None,
@ -112,7 +108,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
val helloLatch = new CountDownLatch(5)
val stopLatch = new CountDownLatch(5)
val actor = actorOf(new Actor {
val actor = app.createActor(Props(new Actor {
def receive = {
case "hello" helloLatch.countDown()
}
@ -120,7 +116,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
override def postStop() {
stopLatch.countDown()
}
}, address)
}), address)
actor ! Broadcast("hello")
helloLatch.await(5, TimeUnit.SECONDS) must be(true)
@ -135,7 +131,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
"be able to shut down its instance" in {
val address = "random-0"
Deployer.deploy(
app.deployer.deploy(
Deploy(
address,
None,
@ -146,7 +142,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
val stopLatch = new CountDownLatch(7)
val actor = actorOf(new Actor {
val actor = app.createActor(Props(new Actor {
def receive = {
case "hello" {}
}
@ -154,7 +150,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
override def postStop() {
stopLatch.countDown()
}
}, address)
}), address)
actor ! "hello"
actor ! "hello"
@ -169,7 +165,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
"deliver messages in a random fashion" in {
val address = "random-1"
Deployer.deploy(
app.deployer.deploy(
Deploy(
address,
None,
@ -188,13 +184,13 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
replies = replies + (i -> 0)
}
val actor = actorOf(new Actor {
val actor = app.createActor(Props(new Actor {
lazy val id = counter.getAndIncrement()
def receive = {
case "hit" reply(id)
case "end" doneLatch.countDown()
}
}, address)
}), address)
for (i 0 until iterationCount) {
for (k 0 until connectionCount) {
@ -214,7 +210,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
"deliver a broadcast message using the !" in {
val address = "random-2"
Deployer.deploy(
app.deployer.deploy(
Deploy(
address,
None,
@ -226,7 +222,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
val helloLatch = new CountDownLatch(6)
val stopLatch = new CountDownLatch(6)
val actor = actorOf(new Actor {
val actor = app.createActor(Props(new Actor {
def receive = {
case "hello" helloLatch.countDown()
}
@ -234,7 +230,7 @@ class ConfiguredLocalRoutingSpec extends WordSpec with MustMatchers {
override def postStop() {
stopLatch.countDown()
}
}, address)
}), address)
actor ! Broadcast("hello")
helloLatch.await(5, TimeUnit.SECONDS) must be(true)

View file

@ -1,14 +1,12 @@
package akka.routing
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.routing._
import java.util.concurrent.atomic.AtomicInteger
import akka.actor.Actor._
import akka.actor.{ ActorRef, Actor }
import collection.mutable.LinkedList
import akka.routing.Routing.Broadcast
import java.util.concurrent.{ CountDownLatch, TimeUnit }
import akka.testkit.AkkaSpec
object RoutingSpec {
@ -20,23 +18,23 @@ object RoutingSpec {
}
}
class RoutingSpec extends WordSpec with MustMatchers {
class RoutingSpec extends AkkaSpec {
import akka.routing.RoutingSpec._
"direct router" must {
"be started when constructed" in {
val actor1 = Actor.actorOf[TestActor]
val actor1 = createActor[TestActor]
val props = RoutedProps(() new DirectRouter, List(actor1))
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor.isShutdown must be(false)
}
"throw IllegalArgumentException at construction when no connections" in {
try {
val props = RoutedProps(() new DirectRouter, List())
Routing.actorOf(props, "foo")
app.routing.actorOf(props, "foo")
fail()
} catch {
case e: IllegalArgumentException
@ -47,7 +45,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
val doneLatch = new CountDownLatch(1)
val counter = new AtomicInteger(0)
val connection1 = actorOf(new Actor {
val connection1 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case _ counter.incrementAndGet
@ -55,7 +53,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
})
val props = RoutedProps(() new DirectRouter, List(connection1))
val routedActor = Routing.actorOf(props, "foo")
val routedActor = app.routing.actorOf(props, "foo")
routedActor ! "hello"
routedActor ! "end"
@ -68,7 +66,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
val doneLatch = new CountDownLatch(1)
val counter1 = new AtomicInteger
val connection1 = actorOf(new Actor {
val connection1 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter1.addAndGet(msg)
@ -76,7 +74,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
})
val props = RoutedProps(() new DirectRouter, List(connection1))
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor ! Broadcast(1)
actor ! "end"
@ -90,17 +88,17 @@ class RoutingSpec extends WordSpec with MustMatchers {
"round robin router" must {
"be started when constructed" in {
val actor1 = Actor.actorOf[TestActor]
val actor1 = createActor[TestActor]
val props = RoutedProps(() new RoundRobinRouter, List(actor1))
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor.isShutdown must be(false)
}
"throw IllegalArgumentException at construction when no connections" in {
try {
val props = RoutedProps(() new RoundRobinRouter, List())
Routing.actorOf(props, "foo")
app.routing.actorOf(props, "foo")
fail()
} catch {
case e: IllegalArgumentException
@ -122,7 +120,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
for (i 0 until connectionCount) {
counters = counters :+ new AtomicInteger()
val connection = actorOf(new Actor {
val connection = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counters.get(i).get.addAndGet(msg)
@ -133,7 +131,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
//create the routed actor.
val props = RoutedProps(() new RoundRobinRouter, connections)
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
//send messages to the actor.
for (i 0 until iterationCount) {
@ -156,7 +154,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
val doneLatch = new CountDownLatch(2)
val counter1 = new AtomicInteger
val connection1 = actorOf(new Actor {
val connection1 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter1.addAndGet(msg)
@ -164,7 +162,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
})
val counter2 = new AtomicInteger
val connection2 = actorOf(new Actor {
val connection2 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter2.addAndGet(msg)
@ -172,7 +170,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
})
val props = RoutedProps(() new RoundRobinRouter, List(connection1, connection2))
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor ! Broadcast(1)
actor ! Broadcast("end")
@ -187,7 +185,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
val doneLatch = new CountDownLatch(1)
val counter1 = new AtomicInteger
val connection1 = actorOf(new Actor {
val connection1 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case _ counter1.incrementAndGet()
@ -195,7 +193,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
})
val props = RoutedProps(() new RoundRobinRouter, List(connection1))
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
try {
actor ? Broadcast(1)
@ -214,17 +212,17 @@ class RoutingSpec extends WordSpec with MustMatchers {
"be started when constructed" in {
val actor1 = Actor.actorOf[TestActor]
val actor1 = createActor[TestActor]
val props = RoutedProps(() new RandomRouter, List(actor1))
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor.isShutdown must be(false)
}
"throw IllegalArgumentException at construction when no connections" in {
try {
val props = RoutedProps(() new RandomRouter, List())
Routing.actorOf(props, "foo")
app.routing.actorOf(props, "foo")
fail()
} catch {
case e: IllegalArgumentException
@ -239,7 +237,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
val doneLatch = new CountDownLatch(2)
val counter1 = new AtomicInteger
val connection1 = actorOf(new Actor {
val connection1 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter1.addAndGet(msg)
@ -247,7 +245,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
})
val counter2 = new AtomicInteger
val connection2 = actorOf(new Actor {
val connection2 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter2.addAndGet(msg)
@ -255,7 +253,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
})
val props = RoutedProps(() new RandomRouter, List(connection1, connection2))
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor ! Broadcast(1)
actor ! Broadcast("end")
@ -270,7 +268,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
val doneLatch = new CountDownLatch(1)
val counter1 = new AtomicInteger
val connection1 = actorOf(new Actor {
val connection1 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case _ counter1.incrementAndGet()
@ -278,7 +276,7 @@ class RoutingSpec extends WordSpec with MustMatchers {
})
val props = RoutedProps(() new RandomRouter, List(connection1))
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
try {
actor ? Broadcast(1)

View file

@ -4,10 +4,9 @@
package akka.serialization
import org.scalatest.junit.JUnitSuite
import org.junit.Test
import akka.serialization.Serialization._
import scala.reflect._
import akka.testkit.AkkaSpec
object SerializeSpec {
@BeanInfo
@ -18,46 +17,48 @@ object SerializeSpec {
case class Record(id: Int, person: Person)
}
class SerializeSpec extends JUnitSuite {
class SerializeSpec extends AkkaSpec {
import SerializeSpec._
@Test
def shouldSerializeAddress {
val addr = Address("120", "Monroe Street", "Santa Clara", "95050")
val b = serialize(addr) match {
case Left(exception) fail(exception)
case Right(bytes) bytes
}
deserialize(b.asInstanceOf[Array[Byte]], classOf[Address], None) match {
case Left(exception) fail(exception)
case Right(add) assert(add === addr)
}
}
import app.serialization._
@Test
def shouldSerializePerson {
val person = Person("debasish ghosh", 25, Address("120", "Monroe Street", "Santa Clara", "95050"))
val b = serialize(person) match {
case Left(exception) fail(exception)
case Right(bytes) bytes
}
deserialize(b.asInstanceOf[Array[Byte]], classOf[Person], None) match {
case Left(exception) fail(exception)
case Right(p) assert(p === person)
}
}
"Serialization" must {
@Test
def shouldSerializeRecordWithDefaultSerializer {
val person = Person("debasish ghosh", 25, Address("120", "Monroe Street", "Santa Clara", "95050"))
val r = Record(100, person)
val b = serialize(r) match {
case Left(exception) fail(exception)
case Right(bytes) bytes
"serialize Address" in {
val addr = Address("120", "Monroe Street", "Santa Clara", "95050")
val b = serialize(addr) match {
case Left(exception) fail(exception)
case Right(bytes) bytes
}
deserialize(b.asInstanceOf[Array[Byte]], classOf[Address], None) match {
case Left(exception) fail(exception)
case Right(add) assert(add === addr)
}
}
deserialize(b.asInstanceOf[Array[Byte]], classOf[Record], None) match {
case Left(exception) fail(exception)
case Right(p) assert(p === r)
"serialize Person" in {
val person = Person("debasish ghosh", 25, Address("120", "Monroe Street", "Santa Clara", "95050"))
val b = serialize(person) match {
case Left(exception) fail(exception)
case Right(bytes) bytes
}
deserialize(b.asInstanceOf[Array[Byte]], classOf[Person], None) match {
case Left(exception) fail(exception)
case Right(p) assert(p === person)
}
}
"serialize record with default serializer" in {
val person = Person("debasish ghosh", 25, Address("120", "Monroe Street", "Santa Clara", "95050"))
val r = Record(100, person)
val b = serialize(r) match {
case Left(exception) fail(exception)
case Right(bytes) bytes
}
deserialize(b.asInstanceOf[Array[Byte]], classOf[Record], None) match {
case Left(exception) fail(exception)
case Right(p) assert(p === r)
}
}
}
}

View file

@ -8,39 +8,39 @@ import java.util.concurrent.CountDownLatch
import org.junit.{ After, Test }
class CallingThreadDispatcherModelSpec extends ActorModelSpec {
import ActorModelSpec._
def newInterceptedDispatcher = new CallingThreadDispatcher with MessageDispatcherInterceptor
def dispatcherType = "Calling Thread Dispatcher"
// A CallingThreadDispatcher can by design not process messages in parallel,
// so disable this test
override def dispatcherShouldProcessMessagesInParallel {}
//override def dispatcherShouldProcessMessagesInParallel {}
// This test needs to be adapted: CTD runs the flood completely sequentially
// with start, invocation, stop, schedule shutdown, abort shutdown, repeat;
// add "keeper" actor to lock down the dispatcher instance, since the
// frequent attempted shutdown seems rather costly (random timing failures
// without this fix)
override def dispatcherShouldHandleWavesOfActors {
implicit val dispatcher = newInterceptedDispatcher
// override def dispatcherShouldHandleWavesOfActors {
// implicit val dispatcher = newInterceptedDispatcher
//
// def flood(num: Int) {
// val cachedMessage = CountDownNStop(new CountDownLatch(num))
// val keeper = newTestActor
// (1 to num) foreach { _
// newTestActor ! cachedMessage
// }
// keeper.stop()
// assertCountDown(cachedMessage.latch, 10000, "Should process " + num + " countdowns")
// }
// for (run 1 to 3) {
// flood(10000)
// assertDispatcher(dispatcher)(starts = run, stops = run)
// }
// }
def flood(num: Int) {
val cachedMessage = CountDownNStop(new CountDownLatch(num))
val keeper = newTestActor
(1 to num) foreach { _
newTestActor ! cachedMessage
}
keeper.stop()
assertCountDown(cachedMessage.latch, 10000, "Should process " + num + " countdowns")
}
for (run 1 to 3) {
flood(10000)
assertDispatcher(dispatcher)(starts = run, stops = run)
}
}
override def dispatcherShouldCompleteAllUncompletedSenderFuturesOnDeregister {
//Can't handle this...
}
//override def dispatcherShouldCompleteAllUncompletedSenderFuturesOnDeregister {
//Can't handle this...
//}
@After
def after {

View file

@ -1,16 +1,13 @@
package akka.ticket
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.routing._
import akka.actor.Actor._
import akka.actor.{ ActorRef, Actor }
import java.util.concurrent.atomic.AtomicInteger
import collection.mutable.LinkedList
import akka.routing.Routing.Broadcast
import akka.testkit._
class Ticket1111Spec extends WordSpec with MustMatchers {
class Ticket1111Spec extends AkkaSpec {
"Scatter-gather router" must {
@ -22,7 +19,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
.withConnections(List(newActor(0, Some(shutdownLatch)), newActor(1, Some(shutdownLatch))))
.withRouter(() new ScatterGatherFirstCompletedRouter())
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor ! Broadcast(Stop(Some(0)))
@ -39,7 +36,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
.withConnections(List(newActor(0, Some(shutdownLatch)), newActor(1, Some(shutdownLatch))))
.withRouter(() new ScatterGatherFirstCompletedRouter())
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor ! Broadcast(Stop())
@ -57,7 +54,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
.withConnections(List(newActor(0), newActor(1)))
.withRouter(() new ScatterGatherFirstCompletedRouter())
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
(actor ? Broadcast("Hi!")).get.asInstanceOf[Int] must be(0)
@ -68,7 +65,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
.withConnections(List(newActor(0), newActor(1)))
.withRouter(() new ScatterGatherFirstCompletedRouter())
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
(actor ? Broadcast(0)).get.asInstanceOf[Int] must be(1)
@ -78,7 +75,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
val props = RoutedProps()
.withConnections(List(newActor(0)))
.withRouter(() new ScatterGatherFirstCompletedRouter())
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor.isShutdown must be(false)
@ -90,7 +87,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
.withRouter(() new ScatterGatherFirstCompletedRouter())
try {
Routing.actorOf(props, "foo")
app.routing.actorOf(props, "foo")
fail()
} catch {
case e: IllegalArgumentException
@ -107,7 +104,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
for (i 0 until connectionCount) {
counters = counters :+ new AtomicInteger()
val connection = actorOf(new Actor {
val connection = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counters.get(i).get.addAndGet(msg)
@ -120,7 +117,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
.withConnections(connections)
.withRouter(() new ScatterGatherFirstCompletedRouter())
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
for (i 0 until iterationCount) {
for (k 0 until connectionCount) {
@ -142,7 +139,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
val doneLatch = new TestLatch(2)
val counter1 = new AtomicInteger
val connection1 = actorOf(new Actor {
val connection1 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter1.addAndGet(msg)
@ -150,7 +147,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
})
val counter2 = new AtomicInteger
val connection2 = actorOf(new Actor {
val connection2 = createActor(new Actor {
def receive = {
case "end" doneLatch.countDown()
case msg: Int counter2.addAndGet(msg)
@ -161,7 +158,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
.withConnections(List(connection1, connection2))
.withRouter(() new ScatterGatherFirstCompletedRouter())
val actor = Routing.actorOf(props, "foo")
val actor = app.routing.actorOf(props, "foo")
actor ! Broadcast(1)
actor ! Broadcast("end")
@ -174,7 +171,7 @@ class Ticket1111Spec extends WordSpec with MustMatchers {
case class Stop(id: Option[Int] = None)
def newActor(id: Int, shudownLatch: Option[TestLatch] = None) = actorOf(new Actor {
def newActor(id: Int, shudownLatch: Option[TestLatch] = None) = createActor(new Actor {
def receive = {
case Stop(None) self.stop()
case Stop(Some(_id)) if (_id == id) self.stop()

View file

@ -1,16 +1,14 @@
package akka.ticket
import akka.actor._
import akka.actor.Actor._
import akka.routing._
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.testkit.AkkaSpec
class Ticket703Spec extends WordSpec with MustMatchers {
class Ticket703Spec extends AkkaSpec {
"A ? call to an actor pool" should {
"reuse the proper timeout" in {
val actorPool = actorOf(
val actorPool = createActor(
Props(new Actor with DefaultActorPool with BoundedCapacityStrategy with MailboxPressureCapacitor with SmallestMailboxSelector with BasicNoBackoffFilter {
def lowerBound = 2
def upperBound = 20
@ -19,7 +17,7 @@ class Ticket703Spec extends WordSpec with MustMatchers {
def selectionCount = 1
def receive = _route
def pressureThreshold = 1
def instance(p: Props) = actorOf(p.withCreator(new Actor {
def instance(p: Props) = createActor(p.withCreator(new Actor {
def receive = {
case req: String
Thread.sleep(6000L)

View file

@ -108,33 +108,23 @@ class AkkaApplication(val name: String, val config: Configuration) extends Actor
val REMOTE_SERVER_PORT = getInt("akka.remote.server.port", 2552)
}
// Java API
val akkaConfig = AkkaConfig
object MistSettings {
val JettyServer = "jetty"
val TimeoutAttribute = "timeout"
val ConnectionClose = config.getBool("akka.http.connection-close", true)
val RootActorBuiltin = config.getBool("akka.http.root-actor-builtin", true)
val RootActorID = config.getString("akka.http.root-actor-id", "_httproot")
val DefaultTimeout = config.getLong("akka.http.timeout", 1000)
val ExpiredHeaderName = config.getString("akka.http.expired-header-name", "Async-Timeout")
val ExpiredHeaderValue = config.getString("akka.http.expired-header-value", "expired")
}
import AkkaConfig._
if (CONFIG_VERSION != VERSION)
throw new ConfigurationException("Akka JAR version [" + VERSION +
"] does not match the provided config version [" + CONFIG_VERSION + "]")
// TODO correctly pull its config from the config
val dispatcherFactory = new Dispatchers(this)
implicit val dispatcher = dispatcherFactory.defaultGlobalDispatcher
// TODO think about memory consistency effects when doing funky stuff inside an ActorRefProvider's constructor
val provider: ActorRefProvider = new LocalActorRefProvider(this)
/**
* Handle to the ActorRegistry.
* TODO: delete me!
*/
val registry = new ActorRegistry
// TODO check memory consistency issues
val reflective = new ReflectiveAccess(this)
val routing = new Routing(this)
val serialization = new Serialization(this)
val startTime = System.currentTimeMillis
def uptime = (System.currentTimeMillis - startTime) / 1000
@ -148,4 +138,37 @@ class AkkaApplication(val name: String, val config: Configuration) extends Actor
case value value
}
if (CONFIG_VERSION != VERSION)
throw new ConfigurationException("Akka JAR version [" + VERSION +
"] does not match the provided config version [" + CONFIG_VERSION + "]")
// TODO correctly pull its config from the config
val dispatcherFactory = new Dispatchers(this)
implicit val dispatcher = dispatcherFactory.defaultGlobalDispatcher
// TODO think about memory consistency effects when doing funky stuff inside an ActorRefProvider's constructor
val deployer = new Deployer(this)
val deployment = new DeploymentConfig(this)
// TODO think about memory consistency effects when doing funky stuff inside an ActorRefProvider's constructor
val provider: ActorRefProvider = new LocalActorRefProvider(this, deployer)
/**
* Handle to the ActorRegistry.
* TODO: delete me!
*/
val registry = new ActorRegistry
// TODO check memory consistency issues
val reflective = new ReflectiveAccess(this)
val routing = new Routing(this)
val remote = reflective.RemoteModule.defaultRemoteSupport map (_.apply) getOrElse null
val typedActor = new TypedActor(this)
val serialization = new Serialization(this)
}

View file

@ -139,12 +139,32 @@ object Timeout {
implicit def durationToTimeout(duration: Duration) = new Timeout(duration)
implicit def intToTimeout(timeout: Int) = new Timeout(timeout)
implicit def longToTimeout(timeout: Long) = new Timeout(timeout)
implicit def defaultTimeout(implicit application: AkkaApplication) = application.AkkaConfig.TIMEOUT
}
object Actor {
type Receive = PartialFunction[Any, Unit]
/**
* This decorator adds invocation logging to a Receive function.
*/
class LoggingReceive(source: AnyRef, r: Receive) extends Receive {
def isDefinedAt(o: Any) = {
val handled = r.isDefinedAt(o)
EventHandler.debug(source, "received " + (if (handled) "handled" else "unhandled") + " message " + o)
handled
}
def apply(o: Any): Unit = r(o)
}
object LoggingReceive {
def apply(source: AnyRef, r: Receive): Receive = r match {
case _: LoggingReceive r
case _ new LoggingReceive(source, r)
}
}
}
/**
@ -164,6 +184,9 @@ object Actor {
*/
trait Actor {
import Actor._
// to make type Receive known in subclasses without import
type Receive = Actor.Receive
/**
@ -188,34 +211,15 @@ trait Actor {
context
}
implicit def application = context.application
implicit def app = context.application
private def config = application.AkkaConfig
private def config = context.application.AkkaConfig
/**
* The default timeout, based on the config setting 'akka.actor.timeout'
*/
implicit val defaultTimeout = config.TIMEOUT
/**
* This decorator adds invocation logging to a Receive function.
*/
class LoggingReceive(source: AnyRef, r: Receive) extends Receive {
def isDefinedAt(o: Any) = {
val handled = r.isDefinedAt(o)
EventHandler.debug(source, "received " + (if (handled) "handled" else "unhandled") + " message " + o)
handled
}
def apply(o: Any): Unit = r(o)
}
object LoggingReceive {
def apply(source: AnyRef, r: Receive): Receive = r match {
case _: LoggingReceive r
case _ new LoggingReceive(source, r)
}
}
/**
* Wrap a Receive partial function in a logging enclosure, which sends a
* debug message to the EventHandler each time before a message is matched.

View file

@ -51,6 +51,12 @@ trait ActorRefFactory {
provider.actorOf(p, address).get
}
def createActor[T <: Actor](implicit m: Manifest[T]): ActorRef = createActor(Props(m.erasure.asInstanceOf[Class[_ <: Actor]]))
def createActor[T <: Actor](clazz: Class[T]): ActorRef = createActor(Props(clazz))
def createActor(factory: Actor): ActorRef = createActor(Props(() factory))
def findActor(address: String): Option[ActorRef] = provider.findActorRef(address)
}
@ -67,12 +73,11 @@ object ActorRefProvider {
/**
* Local ActorRef provider.
*/
class LocalActorRefProvider(application: AkkaApplication) extends ActorRefProvider {
class LocalActorRefProvider(val application: AkkaApplication, val deployer: Deployer) extends ActorRefProvider {
import application.dispatcher
private val actors = new ConcurrentHashMap[String, Promise[Option[ActorRef]]]
private val deployer = new Deployer(application)
def actorOf(props: Props, address: String): Option[ActorRef] = actorOf(props, address, false)

View file

@ -58,6 +58,8 @@ object Props {
def apply(creator: Creator[_ <: Actor]): Props = default.withCreator(creator.create)
def apply(behavior: ActorContext Actor.Receive): Props = apply(new Actor { def receive = behavior(context) })
def apply(faultHandler: FaultHandlingStrategy): Props = apply(new Actor { def receive = { case _ } }).withFaultHandler(faultHandler)
}
/**

View file

@ -60,6 +60,8 @@ object MessageDispatcher {
val UNSCHEDULED = 0
val SCHEDULED = 1
val RESCHEDULED = 2
implicit def defaultDispatcher(implicit application: AkkaApplication) = application.dispatcher
}
/**

View file

@ -10,7 +10,8 @@ import scala.annotation.{ tailrec }
import akka.actor.Timeout
object PromiseStream {
def apply[A](implicit dispatcher: MessageDispatcher, timeout: Timeout): PromiseStream[A] = new PromiseStream[A]
def apply[A]()(implicit dispatcher: MessageDispatcher, timeout: Timeout): PromiseStream[A] = new PromiseStream[A]
def apply[A](timeout: Long)(implicit dispatcher: MessageDispatcher): PromiseStream[A] = new PromiseStream[A]()(dispatcher, Timeout(timeout))
private sealed trait State
private case object Normal extends State

View file

@ -9,13 +9,15 @@ package akka.http
import org.eclipse.jetty.server._
import org.eclipse.jetty.continuation._
import Types._
import akka.AkkaApplication
/**
* @author Garrick Evans
*/
trait JettyContinuation extends ContinuationListener {
import javax.servlet.http.HttpServletResponse
import MistSettings._
protected def application: AkkaApplication
val builder: () tAsyncRequestContext
val context: Option[tAsyncRequestContext] = Some(builder())
@ -33,7 +35,7 @@ trait JettyContinuation extends ContinuationListener {
// the fresh continuation (coming through getAsyncContinuation)
//
case (true, false, false) {
continuation.setTimeout(DefaultTimeout)
continuation.setTimeout(application.MistSettings.DefaultTimeout)
continuation.addContinuationListener(this)
continuation.suspend
@ -45,7 +47,7 @@ trait JettyContinuation extends ContinuationListener {
//
case (true, true, false) {
continuation.setTimeout(DefaultTimeout)
continuation.setTimeout(application.MistSettings.DefaultTimeout)
continuation.addContinuationListener(this)
Some(continuation)
@ -56,9 +58,9 @@ trait JettyContinuation extends ContinuationListener {
//
case (false, false, false) {
continuation.setTimeout(continuation.getAttribute(TimeoutAttribute).asInstanceOf[Long])
continuation.setTimeout(continuation.getAttribute(application.MistSettings.TimeoutAttribute).asInstanceOf[Long])
continuation.suspend
continuation.removeAttribute(TimeoutAttribute)
continuation.removeAttribute(application.MistSettings.TimeoutAttribute)
None
}
@ -68,8 +70,8 @@ trait JettyContinuation extends ContinuationListener {
//
case (false, true, false) {
continuation.setTimeout(continuation.getAttribute(TimeoutAttribute).asInstanceOf[Long])
continuation.removeAttribute(TimeoutAttribute)
continuation.setTimeout(continuation.getAttribute(application.MistSettings.TimeoutAttribute).asInstanceOf[Long])
continuation.removeAttribute(application.MistSettings.TimeoutAttribute)
None
}
@ -85,13 +87,13 @@ trait JettyContinuation extends ContinuationListener {
def suspended: Boolean = _continuation match {
case None false
case Some(continuation) (continuation.isSuspended || (continuation.getAttribute(TimeoutAttribute) ne null))
case Some(continuation) (continuation.isSuspended || (continuation.getAttribute(application.MistSettings.TimeoutAttribute) ne null))
}
def timeout(ms: Long): Boolean = _continuation match {
case None false
case Some(continuation)
continuation.setAttribute(TimeoutAttribute, ms)
continuation.setAttribute(application.MistSettings.TimeoutAttribute, ms)
continuation.resume
true
}
@ -101,18 +103,21 @@ trait JettyContinuation extends ContinuationListener {
//
def onComplete(c: Continuation) = {}
def onTimeout(c: Continuation) = {
c.getServletResponse.asInstanceOf[HttpServletResponse].addHeader(ExpiredHeaderName, ExpiredHeaderValue)
c.getServletResponse.asInstanceOf[HttpServletResponse].addHeader(application.MistSettings.ExpiredHeaderName, application.MistSettings.ExpiredHeaderValue)
c.complete
}
}
object JettyContinuationMethodFactory extends RequestMethodFactory {
def Delete(f: () tAsyncRequestContext): RequestMethod = new Delete(f) with JettyContinuation
def Get(f: () tAsyncRequestContext): RequestMethod = new Get(f) with JettyContinuation
def Head(f: () tAsyncRequestContext): RequestMethod = new Head(f) with JettyContinuation
def Options(f: () tAsyncRequestContext): RequestMethod = new Options(f) with JettyContinuation
def Post(f: () tAsyncRequestContext): RequestMethod = new Post(f) with JettyContinuation
def Put(f: () tAsyncRequestContext): RequestMethod = new Put(f) with JettyContinuation
def Trace(f: () tAsyncRequestContext): RequestMethod = new Trace(f) with JettyContinuation
class JettyContinuationMethodFactory(val _application: AkkaApplication) extends RequestMethodFactory {
trait App {
def application = _application
}
def Delete(f: () tAsyncRequestContext): RequestMethod = new Delete(f) with JettyContinuation with App
def Get(f: () tAsyncRequestContext): RequestMethod = new Get(f) with JettyContinuation with App
def Head(f: () tAsyncRequestContext): RequestMethod = new Head(f) with JettyContinuation with App
def Options(f: () tAsyncRequestContext): RequestMethod = new Options(f) with JettyContinuation with App
def Post(f: () tAsyncRequestContext): RequestMethod = new Post(f) with JettyContinuation with App
def Put(f: () tAsyncRequestContext): RequestMethod = new Put(f) with JettyContinuation with App
def Trace(f: () tAsyncRequestContext): RequestMethod = new Trace(f) with JettyContinuation with App
}

View file

@ -6,30 +6,17 @@ package akka.http
import akka.event.EventHandler
import akka.config.ConfigurationException
import javax.servlet.http.{ HttpServletResponse, HttpServletRequest }
import javax.servlet.http.HttpServlet
import javax.servlet.Filter
import java.lang.UnsupportedOperationException
import akka.actor.{ NullChannel, ActorRef, Actor }
import Types._
import akka.AkkaApplication
/**
* @author Garrick Evans
*/
object MistSettings {
import akka.config.Config._
val JettyServer = "jetty"
val TimeoutAttribute = "timeout"
val ConnectionClose = config.getBool("akka.http.connection-close", true)
val RootActorBuiltin = config.getBool("akka.http.root-actor-builtin", true)
val RootActorID = config.getString("akka.http.root-actor-id", "_httproot")
val DefaultTimeout = config.getLong("akka.http.timeout", 1000)
val ExpiredHeaderName = config.getString("akka.http.expired-header-name", "Async-Timeout")
val ExpiredHeaderValue = config.getString("akka.http.expired-header-value", "expired")
}
/**
* Structural type alias's required to work with both Servlet 3.0 and Jetty's Continuation API
*
@ -60,14 +47,15 @@ object Types {
def Headers(): Headers = Nil
}
import Types._
/**
*
*/
trait Mist {
import javax.servlet.ServletContext
import MistSettings._
protected def application: AkkaApplication
/**
* The root endpoint actor
@ -113,7 +101,7 @@ trait Mist {
// shoot the message to the root endpoint for processing
// IMPORTANT: the suspend method is invoked on the server thread not in the actor
val method = builder(() suspend(ConnectionClose))
val method = builder(() suspend(application.MistSettings.ConnectionClose))
if (method.go) root ! method
}
@ -125,9 +113,9 @@ trait Mist {
val server = context.getServerInfo
val (major, minor) = (context.getMajorVersion, context.getMinorVersion)
factory = if (major >= 3) {
Some(Servlet30ContextMethodFactory)
} else if (server.toLowerCase startsWith JettyServer) {
Some(JettyContinuationMethodFactory)
Some(new Servlet30ContextMethodFactory(application))
} else if (server.toLowerCase startsWith application.MistSettings.JettyServer) {
Some(new JettyContinuationMethodFactory(application))
} else {
None
}
@ -137,12 +125,14 @@ trait Mist {
trait RootEndpointLocator {
var root: ActorRef = null
protected def application: AkkaApplication
def configureRoot(address: String) {
def findRoot(address: String): ActorRef =
Actor.registry.actorFor(address).getOrElse(
application.registry.actorFor(address).getOrElse(
throw new ConfigurationException("akka.http.root-actor-id configuration option does not have a valid actor address [" + address + "]"))
root = if ((address eq null) || address == "") findRoot(MistSettings.RootActorID) else findRoot(address)
root = if ((address eq null) || address == "") findRoot(application.MistSettings.RootActorID) else findRoot(address)
}
}
@ -150,7 +140,7 @@ trait RootEndpointLocator {
* AkkaMistServlet adds support to bridge Http and Actors in an asynchronous fashion
* Async impls currently supported: Servlet3.0, Jetty Continuations
*/
class AkkaMistServlet extends HttpServlet with Mist with RootEndpointLocator {
class AkkaMistServlet(val application: AkkaApplication) extends HttpServlet with Mist with RootEndpointLocator {
import javax.servlet.{ ServletConfig }
/**
@ -169,7 +159,7 @@ class AkkaMistServlet extends HttpServlet with Mist with RootEndpointLocator {
* Proof-of-concept, use at own risk
* Will be officially supported in a later release
*/
class AkkaMistFilter extends Filter with Mist with RootEndpointLocator {
class AkkaMistFilter(val application: AkkaApplication) extends Filter with Mist with RootEndpointLocator {
import javax.servlet.{ ServletRequest, ServletResponse, FilterConfig, FilterChain }
/**
@ -205,7 +195,7 @@ object Endpoint {
/**
* leverage the akka config to tweak the dispatcher for our endpoints
*/
lazy val Dispatcher = Dispatchers.fromConfig("akka.http.mist-dispatcher")
//lazy val Dispatcher = Dispatchers.fromConfig("akka.http.mist-dispatcher")
type Hook = PartialFunction[String, ActorRef]
@ -276,7 +266,6 @@ trait Endpoint { this: Actor ⇒
class RootEndpoint extends Actor with Endpoint {
import Endpoint._
import MistSettings._
final val Root = "/"

View file

@ -4,17 +4,18 @@
package akka.http
import javax.servlet.{ AsyncContext, AsyncListener, AsyncEvent };
import javax.servlet.{ AsyncContext, AsyncListener, AsyncEvent }
import Types._
import akka.event.EventHandler
import akka.AkkaApplication
/**
* @author Garrick Evans
*/
trait Servlet30Context extends AsyncListener {
import javax.servlet.http.HttpServletResponse
import MistSettings._
protected def application: AkkaApplication
val builder: () tAsyncRequestContext
val context: Option[tAsyncRequestContext] = Some(builder())
@ -22,7 +23,7 @@ trait Servlet30Context extends AsyncListener {
protected val _ac: AsyncContext = {
val ac = context.get.asInstanceOf[AsyncContext]
ac setTimeout DefaultTimeout
ac setTimeout application.MistSettings.DefaultTimeout
ac addListener this
ac
}
@ -50,18 +51,21 @@ trait Servlet30Context extends AsyncListener {
}
def onStartAsync(e: AsyncEvent) {}
def onTimeout(e: AsyncEvent) = {
e.getSuppliedResponse.asInstanceOf[HttpServletResponse].addHeader(ExpiredHeaderName, ExpiredHeaderValue)
e.getSuppliedResponse.asInstanceOf[HttpServletResponse].addHeader(application.MistSettings.ExpiredHeaderName, application.MistSettings.ExpiredHeaderValue)
e.getAsyncContext.complete
}
}
object Servlet30ContextMethodFactory extends RequestMethodFactory {
def Delete(f: () tAsyncRequestContext): RequestMethod = new Delete(f) with Servlet30Context
def Get(f: () tAsyncRequestContext): RequestMethod = new Get(f) with Servlet30Context
def Head(f: () tAsyncRequestContext): RequestMethod = new Head(f) with Servlet30Context
def Options(f: () tAsyncRequestContext): RequestMethod = new Options(f) with Servlet30Context
def Post(f: () tAsyncRequestContext): RequestMethod = new Post(f) with Servlet30Context
def Put(f: () tAsyncRequestContext): RequestMethod = new Put(f) with Servlet30Context
def Trace(f: () tAsyncRequestContext): RequestMethod = new Trace(f) with Servlet30Context
class Servlet30ContextMethodFactory(val _application: AkkaApplication) extends RequestMethodFactory {
trait App {
def application = _application
}
def Delete(f: () tAsyncRequestContext): RequestMethod = new Delete(f) with Servlet30Context with App
def Get(f: () tAsyncRequestContext): RequestMethod = new Get(f) with Servlet30Context with App
def Head(f: () tAsyncRequestContext): RequestMethod = new Head(f) with Servlet30Context with App
def Options(f: () tAsyncRequestContext): RequestMethod = new Options(f) with Servlet30Context with App
def Post(f: () tAsyncRequestContext): RequestMethod = new Post(f) with Servlet30Context with App
def Put(f: () tAsyncRequestContext): RequestMethod = new Put(f) with Servlet30Context with App
def Trace(f: () tAsyncRequestContext): RequestMethod = new Trace(f) with Servlet30Context with App
}

View file

@ -4,18 +4,17 @@
package akka.config
import akka.testkit.AkkaSpec
import org.junit.runner.RunWith
import org.scalatest.WordSpec
import org.scalatest.junit.JUnitRunner
import org.scalatest.matchers.MustMatchers
@RunWith(classOf[JUnitRunner])
class ConfigSpec extends WordSpec with MustMatchers {
class ConfigSpec extends AkkaSpec {
"The default configuration file (i.e. akka-reference.conf)" should {
"contain all configuration properties for akka-http that are used in code with their correct defaults" in {
import Config.config._
import application.config._
getBool("akka.http.connection-close") must equal(Some(true))
getString("akka.http.expired-header-name") must equal(Some("Async-Timeout"))
getString("akka.http.hostname") must equal(Some("localhost"))

View file

@ -90,9 +90,7 @@ class TestKit(_app: AkkaApplication) {
import TestActor.{ Message, RealMessage, NullMessage }
implicit val application = _app
implicit val defaultFutureTimeout = _app.AkkaConfig.TIMEOUT
implicit val defaultFutureDispatcher = _app.dispatcher
implicit val app = _app
private val queue = new LinkedBlockingDeque[Message]()
private[akka] var lastMessage: Message = NullMessage
@ -101,7 +99,7 @@ class TestKit(_app: AkkaApplication) {
* ActorRef of the test actor. Access is provided to enable e.g.
* registration as message target.
*/
implicit val testActor: ActorRef = new LocalActorRef(application, Props(new TestActor(queue)).copy(dispatcher = CallingThreadDispatcher.global), "testActor" + TestKit.testActorId.incrementAndGet(), true)
val testActor: ActorRef = new LocalActorRef(app, Props(new TestActor(queue)).copy(dispatcher = CallingThreadDispatcher.global), "testActor" + TestKit.testActorId.incrementAndGet(), true)
private var end: Duration = Duration.Inf
@ -580,3 +578,7 @@ class TestProbe(_application: AkkaApplication) extends TestKit(_application) {
object TestProbe {
def apply()(implicit application: AkkaApplication) = new TestProbe(application)
}
trait ImplicitSender { this: TestKit
implicit def implicitSenderTestActor = testActor
}

View file

@ -7,17 +7,20 @@ import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.AkkaApplication
import akka.actor.{ Actor, ActorRef, Props }
import akka.dispatch.MessageDispatcher
abstract class AkkaSpec(_application: AkkaApplication = AkkaApplication())
extends TestKit(_application) with WordSpec with MustMatchers {
def app = _application
def createActor(props: Props): ActorRef = app.createActor(props)
def actorOf(props: Props): ActorRef = app.createActor(props)
def createActor[T <: Actor](clazz: Class[T]): ActorRef = createActor(Props(clazz))
def actorOf[T <: Actor](clazz: Class[T]): ActorRef = actorOf(Props(clazz))
def createActor[T <: Actor: Manifest]: ActorRef = createActor(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]])
def actorOf[T <: Actor: Manifest]: ActorRef = actorOf(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]])
def createActor[T <: Actor](factory: T): ActorRef = createActor(Props(factory))
def actorOf[T <: Actor](factory: T): ActorRef = actorOf(Props(factory))
def spawn(body: Unit)(implicit dispatcher: MessageDispatcher) {
createActor(Props(ctx { case "go" try body finally ctx.self.stop() }).withDispatcher(dispatcher)) ! "go"
}
}