Merge with master

This commit is contained in:
Viktor Klang 2012-08-14 16:29:38 +02:00
commit 4a15892b84
13 changed files with 159 additions and 269 deletions

View file

@ -7,14 +7,15 @@ package akka.camel;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.testkit.JavaTestKit;
import scala.concurrent.Await;
import scala.concurrent.ExecutionContext;
import scala.concurrent.util.Duration;
import org.junit.AfterClass;
import org.junit.Test;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import akka.testkit.AkkaSpec;
import akka.testkit.JavaTestKit.EventFilter;
import static org.junit.Assert.assertEquals;
@ -24,9 +25,7 @@ import static org.junit.Assert.assertEquals;
*/
public class ConsumerJavaTestBase {
static ActorSystem system = ActorSystem.create("test");
static Camel camel = CamelExtension.get(system);
static ActorSystem system = ActorSystem.create("test", AkkaSpec.testConf());
@AfterClass
public static void tearDownAfterClass() {
@ -35,13 +34,24 @@ public class ConsumerJavaTestBase {
@Test
public void shouldHandleExceptionThrownByActorAndGenerateCustomResponse() throws Exception {
Duration timeout = Duration.create(1, TimeUnit.SECONDS);
ExecutionContext executionContext = system.dispatcher();
ActorRef ref = Await.result(
camel.activationFutureFor(system.actorOf(new Props(SampleErrorHandlingConsumer.class)), timeout, executionContext),
timeout);
String result = camel.template().requestBody("direct:error-handler-test-java", "hello", String.class);
assertEquals("error: hello", result);
new JavaTestKit(system) {{
String result = new EventFilter<String>(Exception.class) {
protected String run() {
Duration timeout = Duration.create(1, TimeUnit.SECONDS);
Camel camel = CamelExtension.get(system);
ExecutionContext executionContext = system.dispatcher();
try {
ActorRef ref = Await.result(
camel.activationFutureFor(system.actorOf(new Props(SampleErrorHandlingConsumer.class)), timeout, executionContext),
timeout);
return camel.template().requestBody("direct:error-handler-test-java", "hello", String.class);
}
catch (Exception e) {
return e.getMessage();
}
}
}.occurrences(1).exec();
assertEquals("error: hello", result);
}};
}
}

View file

@ -15,10 +15,10 @@ import org.apache.camel.model.RouteDefinition
import org.apache.camel.builder.Builder
import org.apache.camel.{ FailedToCreateRouteException, CamelExecutionException }
import java.util.concurrent.{ ExecutionException, TimeUnit, TimeoutException }
import akka.testkit.TestLatch
import akka.actor.Status.Failure
import scala.concurrent.util.duration._
import concurrent.{ ExecutionContext, Await }
import akka.testkit._
class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedCamelSystem {
"ConsumerIntegrationTest" must {
@ -26,8 +26,12 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC
implicit def ec: ExecutionContext = system.dispatcher
"Consumer must throw FailedToCreateRouteException, while awaiting activation, if endpoint is invalid" in {
val actorRef = system.actorOf(Props(new TestActor(uri = "some invalid uri")))
intercept[FailedToCreateRouteException] { Await.result(camel.activationFutureFor(actorRef), defaultTimeout) }
filterEvents(EventFilter[ActorInitializationException](occurrences = 1), EventFilter[FailedToCreateRouteException](occurrences = 1)) {
val actorRef = system.actorOf(Props(new TestActor(uri = "some invalid uri")))
intercept[FailedToCreateRouteException] {
Await.result(camel.activationFutureFor(actorRef), defaultTimeout)
}
}
}
"Consumer must support in-out messaging" in {
@ -63,7 +67,7 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC
def endpointUri = "direct:a2"
def receive = {
case "throw" throw new Exception
case "throw" throw new TestException("")
case m: CamelMessage sender ! "received " + m.bodyAs[String]
}
@ -71,11 +75,12 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC
restarted.countDown()
}
})
consumer ! "throw"
Await.ready(restarted, defaultTimeout)
filterEvents(EventFilter[TestException](occurrences = 1)) {
consumer ! "throw"
Await.ready(restarted, defaultTimeout)
val response = camel.sendTo("direct:a2", msg = "xyz")
response must be("received xyz")
camel.sendTo("direct:a2", msg = "xyz") must be("received xyz")
}
}
"Consumer must unregister itself when stopped" in {
@ -104,19 +109,23 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC
"Error passing consumer supports error handling through route modification" in {
start(new ErrorThrowingConsumer("direct:error-handler-test") with ErrorPassing {
override def onRouteDefinition(rd: RouteDefinition) = {
rd.onException(classOf[Exception]).handled(true).transform(Builder.exceptionMessage).end
rd.onException(classOf[TestException]).handled(true).transform(Builder.exceptionMessage).end
}
})
camel.sendTo("direct:error-handler-test", msg = "hello") must be("error: hello")
filterEvents(EventFilter[TestException](occurrences = 1)) {
camel.sendTo("direct:error-handler-test", msg = "hello") must be("error: hello")
}
}
"Error passing consumer supports redelivery through route modification" in {
start(new FailingOnceConsumer("direct:failing-once-concumer") with ErrorPassing {
override def onRouteDefinition(rd: RouteDefinition) = {
rd.onException(classOf[Exception]).maximumRedeliveries(1).end
rd.onException(classOf[TestException]).maximumRedeliveries(1).end
}
})
camel.sendTo("direct:failing-once-concumer", msg = "hello") must be("accepted: hello")
filterEvents(EventFilter[TestException](occurrences = 1)) {
camel.sendTo("direct:failing-once-concumer", msg = "hello") must be("accepted: hello")
}
}
"Consumer supports manual Ack" in {
@ -155,7 +164,7 @@ class ConsumerIntegrationTest extends WordSpec with MustMatchers with NonSharedC
class ErrorThrowingConsumer(override val endpointUri: String) extends Consumer {
def receive = {
case msg: CamelMessage throw new Exception("error: %s" format msg.body)
case msg: CamelMessage throw new TestException("error: %s" format msg.body)
}
}
@ -166,7 +175,7 @@ class FailingOnceConsumer(override val endpointUri: String) extends Consumer {
if (msg.headerAs[Boolean]("CamelRedelivered").getOrElse(false))
sender ! ("accepted: %s" format msg.body)
else
throw new Exception("rejected: %s" format msg.body)
throw new TestException("rejected: %s" format msg.body)
}
}
@ -185,3 +194,5 @@ trait ErrorPassing {
trait ManualAckConsumer extends Consumer {
override def autoAck = false
}
class TestException(msg: String) extends Exception(msg)

View file

@ -18,7 +18,7 @@ import akka.pattern._
import scala.concurrent.util.duration._
import akka.util.Timeout
import org.scalatest.matchers.MustMatchers
import akka.testkit.TestLatch
import akka.testkit._
/**
* Tests the features of the Camel Producer.
@ -70,14 +70,10 @@ class ProducerFeatureTest extends WordSpec with BeforeAndAfterAll with BeforeAnd
}))
val producer = Await.result[ActorRef](supervisor.ask(Props(new TestProducer("direct:producer-test-2"))).mapTo[ActorRef], timeoutDuration)
val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123"))
val future = producer.ask(message)(timeoutDuration).failed
Await.ready(future, timeoutDuration).value match {
case Some(Right(e: AkkaCamelException))
// a failure response must have been returned by the producer
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123"))
case unexpected fail("Actor responded with unexpected message:" + unexpected)
filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) {
val e = intercept[AkkaCamelException] { Await.result(producer.ask(message)(timeoutDuration), timeoutDuration) }
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123"))
}
Await.ready(latch, timeoutDuration)
deadActor must be(Some(producer))
@ -117,14 +113,11 @@ class ProducerFeatureTest extends WordSpec with BeforeAndAfterAll with BeforeAnd
"produce message to direct:producer-test-3 and receive failure response" in {
val producer = system.actorOf(Props(new TestProducer("direct:producer-test-3")))
val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123"))
val future = producer.ask(message)(timeoutDuration).failed
Await.ready(future, timeoutDuration).value match {
case Some(Right(e: AkkaCamelException))
// a failure response must have been returned by the producer
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123"))
case unexpected fail("Actor responded with unexpected message:" + unexpected)
filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) {
val e = intercept[AkkaCamelException] { Await.result(producer.ask(message)(timeoutDuration), timeoutDuration) }
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123"))
}
}
@ -148,13 +141,10 @@ class ProducerFeatureTest extends WordSpec with BeforeAndAfterAll with BeforeAnd
val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-2", target)))
val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123"))
val future = producer.ask(message)(timeoutDuration).failed
Await.ready(future, timeoutDuration).value match {
case Some(Right(e: AkkaCamelException))
// a failure response must have been returned by the forward target
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123", "test" -> "failure"))
case unexpected fail("Actor responded with unexpected message:" + unexpected)
filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) {
val e = intercept[AkkaCamelException] { Await.result(producer.ask(message)(timeoutDuration), timeoutDuration) }
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123", "test" -> "failure"))
}
}
@ -169,10 +159,12 @@ class ProducerFeatureTest extends WordSpec with BeforeAndAfterAll with BeforeAnd
"produce message, forward failure response to a producing target actor and produce response to direct:forward-test-1" in {
val target = system.actorOf(Props[ProducingForwardTarget])
val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-2", target)))
mockEndpoint.expectedMessageCount(1)
mockEndpoint.message(0).body().isInstanceOf(classOf[akka.actor.Status.Failure])
producer.tell(CamelMessage("fail", Map()), producer)
mockEndpoint.assertIsSatisfied()
filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) {
mockEndpoint.expectedMessageCount(1)
mockEndpoint.message(0).body().isInstanceOf(classOf[akka.actor.Status.Failure])
producer.tell(CamelMessage("fail", Map()), producer)
mockEndpoint.assertIsSatisfied()
}
}
"produce message, forward normal response from direct:producer-test-3 to a replying target actor and receive response" in {
@ -194,12 +186,10 @@ class ProducerFeatureTest extends WordSpec with BeforeAndAfterAll with BeforeAnd
val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-3", target)))
val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123"))
val future = producer.ask(message)(timeoutDuration).failed
Await.ready(future, timeoutDuration).value match {
case Some(Right(e: AkkaCamelException))
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123", "test" -> "failure"))
case unexpected fail("Actor responded with unexpected message:" + unexpected)
filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) {
val e = intercept[AkkaCamelException] { Await.result(producer.ask(message)(timeoutDuration), timeoutDuration) }
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123", "test" -> "failure"))
}
}
@ -214,10 +204,12 @@ class ProducerFeatureTest extends WordSpec with BeforeAndAfterAll with BeforeAnd
"produce message, forward failure response from direct:producer-test-3 to a producing target actor and produce response to direct:forward-test-1" in {
val target = system.actorOf(Props[ProducingForwardTarget])
val producer = system.actorOf(Props(new TestForwarder("direct:producer-test-3", target)))
mockEndpoint.expectedMessageCount(1)
mockEndpoint.message(0).body().isInstanceOf(classOf[akka.actor.Status.Failure])
producer.tell(CamelMessage("fail", Map()), producer)
mockEndpoint.assertIsSatisfied()
filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) {
mockEndpoint.expectedMessageCount(1)
mockEndpoint.message(0).body().isInstanceOf(classOf[akka.actor.Status.Failure])
producer.tell(CamelMessage("fail", Map()), producer)
mockEndpoint.assertIsSatisfied()
}
}
}

View file

@ -16,6 +16,7 @@ import scala.reflect.ClassTag
import akka.actor.{ ActorRef, Props, ActorSystem, Actor }
import concurrent.Await
import akka.util.Timeout
import akka.testkit.AkkaSpec
private[camel] object TestSupport {
@ -47,7 +48,7 @@ private[camel] object TestSupport {
}
trait SharedCamelSystem extends BeforeAndAfterAll { this: Suite
implicit lazy val system = ActorSystem("test")
implicit lazy val system = ActorSystem("test", AkkaSpec.testConf)
implicit lazy val camel = CamelExtension(system)
abstract override protected def afterAll() {
@ -62,7 +63,7 @@ private[camel] object TestSupport {
override protected def beforeEach() {
super.beforeEach()
system = ActorSystem("test")
system = ActorSystem("test", AkkaSpec.testConf)
camel = CamelExtension(system)
}

View file

@ -16,6 +16,7 @@ import akka.pattern._
import scala.concurrent.Await
import scala.concurrent.util.duration._
import org.scalatest._
import akka.testkit._
import matchers.MustMatchers
class UntypedProducerTest extends WordSpec with MustMatchers with BeforeAndAfterAll with BeforeAndAfterEach with SharedCamelSystem with GivenWhenThen {
@ -49,13 +50,15 @@ class UntypedProducerTest extends WordSpec with MustMatchers with BeforeAndAfter
val producer = system.actorOf(Props[SampleUntypedReplyingProducer])
val message = CamelMessage("fail", Map(CamelMessage.MessageExchangeId -> "123"))
val future = producer.ask(message)(timeout).failed
filterEvents(EventFilter[AkkaCamelException](occurrences = 1)) {
val future = producer.ask(message)(timeout).failed
Await.ready(future, timeout).value match {
case Some(Right(e: AkkaCamelException))
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123"))
case unexpected fail("Actor responded with unexpected message:" + unexpected)
Await.ready(future, timeout).value match {
case Some(Right(e: AkkaCamelException))
e.getMessage must be("failure")
e.headers must be(Map(CamelMessage.MessageExchangeId -> "123"))
case unexpected fail("Actor responded with unexpected message:" + unexpected)
}
}
}
}
@ -67,7 +70,6 @@ class UntypedProducerTest extends WordSpec with MustMatchers with BeforeAndAfter
mockEndpoint.expectedBodiesReceived("received test")
producer.tell(CamelMessage("test", Map[String, Any]()), producer)
mockEndpoint.assertIsSatisfied
}

View file

@ -13,7 +13,7 @@ Akka is using ``Scalariform`` to format the source code as part of the build. So
Process
-------
* Make sure you have signed the Akka CLA, if not, ask for it on the Mailing List.
* Make sure you have signed the Akka CLA, if not, `sign it online <http://www.typesafe.com/contribute/cla>`_.
* Pick a ticket, if there is no ticket for your work then create one first.
* Start working in a feature branch. Name it something like ``wip-<ticket number>-<descriptive name>-<your username>``.
* When you are done, create a GitHub Pull-Request towards the targeted branch and email the Akka Mailing List that you want it reviewed

View file

@ -146,7 +146,7 @@ If you want to see all messages that are received through remoting at DEBUG log
}
}
Also see the logging options for TestKit: :ref:`actor.logging`.
Also see the logging options for TestKit: :ref:`actor.logging-java`.
Event Handler

View file

@ -29,168 +29,8 @@ Akka License
Akka Committer License Agreement
--------------------------------
All committers have signed this CLA
::
Based on: http://www.apache.org/licenses/icla.txt
Typesafe Inc.
Individual Contributor License Agreement ("Agreement") V2.0
http://www.scalablesolutions.se/licenses/
Thank you for your interest in Akka, a Typesafe Inc. (the
"Company") Open Source project. In order to clarify the intellectual
property license granted with Contributions from any person or entity,
the Company must have a Contributor License Agreement ("CLA") on file
that has been signed by each Contributor, indicating agreement to the
license terms below. This license is for your protection as a
Contributor as well as the protection of the Company and its users;
it does not change your rights to use your own Contributions for any
other purpose.
Full name: ______________________________________________________
Mailing Address: ________________________________________________
_________________________________________________________________
_________________________________________________________________
Country: ______________________________________________________
Telephone: ______________________________________________________
Facsimile: ______________________________________________________
E-Mail: ______________________________________________________
You accept and agree to the following terms and conditions for Your
present and future Contributions submitted to the Company. In
return, the Company shall not use Your Contributions in a way that
is contrary to the public benefit or inconsistent with its nonprofit
status and bylaws in effect at the time of the Contribution. Except
for the license granted herein to the Company and recipients of
software distributed by the Company, You reserve all right, title,
and interest in and to Your Contributions.
1. Definitions.
"You" (or "Your") shall mean the copyright owner or legal entity
authorized by the copyright owner that is making this Agreement
with the Company. For legal entities, the entity making a
Contribution and all other entities that control, are controlled
by, or are under common control with that entity are considered to
be a single Contributor. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"Contribution" shall mean any original work of authorship,
including any modifications or additions to an existing work, that
is intentionally submitted by You to the Company for inclusion
in, or documentation of, any of the products owned or managed by
the Company (the "Work"). For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written
communication sent to the Company or its representatives,
including but not limited to communication on electronic mailing
lists, source code control systems, and issue tracking systems that
are managed by, or on behalf of, the Company for the purpose of
discussing and improving the Work, but excluding communication that
is conspicuously marked or otherwise designated in writing by You
as "Not a Contribution."
2. Grant of Copyright License. Subject to the terms and conditions of
this Agreement, You hereby grant to the Company and to
recipients of software distributed by the Company a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare derivative works of,
publicly display, publicly perform, sublicense, and distribute Your
Contributions and such derivative works.
3. Grant of Patent License. Subject to the terms and conditions of
this Agreement, You hereby grant to the Company and to
recipients of software distributed by the Company a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the
Work, where such license applies only to those patent claims
licensable by You that are necessarily infringed by Your
Contribution(s) alone or by combination of Your Contribution(s)
with the Work to which such Contribution(s) was submitted. If any
entity institutes patent litigation against You or any other entity
(including a cross-claim or counterclaim in a lawsuit) alleging
that your Contribution, or the Work to which you have contributed,
constitutes direct or contributory patent infringement, then any
patent licenses granted to that entity under this Agreement for
that Contribution or Work shall terminate as of the date such
litigation is filed.
4. You agree that all Contributions are and will be given entirely
voluntarily. Company will not be required to use, or to refrain
from using, any Contributions that You, will not, absent a
separate written agreement signed by Company, create any
confidentiality obligation of Company, and Company has not
undertaken any obligation to treat any Contributions or other
information You have given Company or will give Company in the
future as confidential or proprietary information. Furthermore,
except as otherwise provided in a separate subsequence written
agreement between You and Company, Company will be free to use,
disclose, reproduce, license or otherwise distribute, and exploit
the Contributions as it sees fit, entirely without obligation or
restriction of any kind on account of any proprietary or
intellectual property rights or otherwise.
5. You represent that you are legally entitled to grant the above
license. If your employer(s) has rights to intellectual property
that you create that includes your Contributions, you represent
that you have received permission to make Contributions on behalf
of that employer, that your employer has waived such rights for
your Contributions to the Company, or that your employer has
executed a separate Corporate CLA with the Company.
6. You represent that each of Your Contributions is Your original
creation (see section 7 for submissions on behalf of others). You
represent that Your Contribution submissions include complete
details of any third-party license or other restriction (including,
but not limited to, related patents and trademarks) of which you
are personally aware and which are associated with any part of Your
Contributions.
7. You are not expected to provide support for Your Contributions,
except to the extent You desire to provide support. You may provide
support for free, for a fee, or not at all. Unless required by
applicable law or agreed to in writing, You provide Your
Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied, including, without
limitation, any warranties or conditions of TITLE, NON-
INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
8. Should You wish to submit work that is not Your original creation,
You may submit it to the Company separately from any
Contribution, identifying the complete details of its source and of
any license or other restriction (including, but not limited to,
related patents, trademarks, and license agreements) of which you
are personally aware, and conspicuously marking the work as
"Submitted on behalf of a third-party: [named here]".
9. You agree to notify the Company of any facts or circumstances of
which you become aware that would make these representations
inaccurate in any respect.
9. The validity of the interpretation of this Agreements shall be
governed by, and constructed and enforced in accordance with, the
laws of Sweden, applicable to the agreements made there (excluding
the conflict of law rules). This Agreement embodies the entire
agreement and understanding of the parties hereto and supersedes
any and all prior agreements, arrangements and understandings
relating to the matters provided for herein. No alteration, waiver,
amendment changed or supplement hereto shall be binding more
effective unless the same as set forth in writing signed by both
parties.
Please sign: __________________________________ Date: ________________
All committers have signed this `CLA <http://www.typesafe.com/contribute/current-cla>`_.
It can be `signed online <http://www.typesafe.com/contribute/cla>`_.
Licenses for Dependency Libraries
---------------------------------

View file

@ -58,7 +58,7 @@ After extracting data from a ``ByteIterator``, the remaining content can also be
.. includecode:: code/akka/docs/io/BinaryCoding.scala
:include: rest-to-seq
with no copying from bytes to rest involved. In general, conversions from ByteString to ByteIterator and vice versa are O(1) for non-chunked ``ByteString``s and (at worst) O(nChunks) for chunked ByteStrings.
with no copying from bytes to rest involved. In general, conversions from ByteString to ByteIterator and vice versa are O(1) for non-chunked ByteStrings and (at worst) O(nChunks) for chunked ByteStrings.
Encoding of data also is very natural, using ``ByteStringBuilder``

View file

@ -165,7 +165,7 @@ If you want to see all messages that are received through remoting at DEBUG log
}
}
Also see the logging options for TestKit: :ref:`actor.logging`.
Also see the logging options for TestKit: :ref:`actor.logging-scala`.
Translating Log Source to String and Class
------------------------------------------

View file

@ -38,17 +38,21 @@ class SimpleNamespaceHandlerTest extends WordSpec with MustMatchers with PojoSRT
"simple.xml" must {
"set up ActorSystem when bundle starts" in {
serviceForType[ActorSystem] must not be (null)
filterErrors() {
serviceForType[ActorSystem] must not be (null)
}
}
"stop the ActorSystem when bundle stops" in {
val system = serviceForType[ActorSystem]
system.isTerminated must be(false)
filterErrors() {
val system = serviceForType[ActorSystem]
system.isTerminated must be(false)
bundleForName(TEST_BUNDLE_NAME).stop()
bundleForName(TEST_BUNDLE_NAME).stop()
system.awaitTermination()
system.isTerminated must be(true)
system.awaitTermination()
system.isTerminated must be(true)
}
}
}
@ -64,19 +68,23 @@ class ConfigNamespaceHandlerTest extends WordSpec with MustMatchers with PojoSRT
"config.xml" must {
"set up ActorSystem when bundle starts" in {
val system = serviceForType[ActorSystem]
system must not be (null)
system.settings.config.getString("some.config.key") must be("value")
filterErrors() {
val system = serviceForType[ActorSystem]
system must not be (null)
system.settings.config.getString("some.config.key") must be("value")
}
}
"stop the ActorSystem when bundle stops" in {
val system = serviceForType[ActorSystem]
system.isTerminated must be(false)
filterErrors() {
val system = serviceForType[ActorSystem]
system.isTerminated must be(false)
bundleForName(TEST_BUNDLE_NAME).stop()
bundleForName(TEST_BUNDLE_NAME).stop()
system.awaitTermination()
system.isTerminated must be(true)
system.awaitTermination()
system.isTerminated must be(true)
}
}
}
@ -93,9 +101,11 @@ class DependencyInjectionNamespaceHandlerTest extends WordSpec with MustMatchers
"injection.xml" must {
"set up bean containing ActorSystem" in {
val bean = serviceForType[ActorSystemAwareBean]
bean must not be (null)
bean.system must not be (null)
filterErrors() {
val bean = serviceForType[ActorSystemAwareBean]
bean must not be (null)
bean.system must not be (null)
}
}
}

View file

@ -38,21 +38,24 @@ class PingPongActorSystemActivatorTest extends WordSpec with MustMatchers with P
"PingPongActorSystemActivator" must {
"start and register the ActorSystem when bundle starts" in {
val system = serviceForType[ActorSystem]
val actor = system.actorFor("/user/pong")
filterErrors() {
val system = serviceForType[ActorSystem]
val actor = system.actorFor("/user/pong")
implicit val timeout = Timeout(5 seconds)
Await.result(actor ? Ping, timeout.duration) must be(Pong)
implicit val timeout = Timeout(5 seconds)
Await.result(actor ? Ping, timeout.duration) must be(Pong)
}
}
"stop the ActorSystem when bundle stops" in {
val system = serviceForType[ActorSystem]
system.isTerminated must be(false)
filterErrors() {
val system = serviceForType[ActorSystem]
system.isTerminated must be(false)
bundleForName(TEST_BUNDLE_NAME).stop()
system.awaitTermination()
system.isTerminated must be(true)
bundleForName(TEST_BUNDLE_NAME).stop()
system.awaitTermination()
system.isTerminated must be(true)
}
}
}
@ -67,7 +70,9 @@ class RuntimeNameActorSystemActivatorTest extends WordSpec with MustMatchers wit
"RuntimeNameActorSystemActivator" must {
"register an ActorSystem and add the bundle id to the system name" in {
serviceForType[ActorSystem].name must equal(TestActivators.ACTOR_SYSTEM_NAME_PATTERN.format(bundleForName(TEST_BUNDLE_NAME).getBundleId))
filterErrors() {
serviceForType[ActorSystem].name must equal(TestActivators.ACTOR_SYSTEM_NAME_PATTERN.format(bundleForName(TEST_BUNDLE_NAME).getBundleId))
}
}
}

View file

@ -13,10 +13,11 @@ import org.osgi.framework._
import java.net.URL
import java.util.jar.JarInputStream
import java.io.{ FileInputStream, FileOutputStream, File }
import java.io._
import org.scalatest.{ BeforeAndAfterAll, Suite }
import java.util.{ UUID, Date, ServiceLoader, HashMap }
import scala.reflect.ClassTag
import scala.Some
/**
* Trait that provides support for building akka-osgi tests using PojoSR
@ -32,6 +33,8 @@ trait PojoSRTestSupport extends Suite with BeforeAndAfterAll {
*/
def testBundles: Seq[BundleDescriptor]
val bufferedLoadingErrors = new ByteArrayOutputStream()
lazy val context: BundleContext = {
val config = new HashMap[String, AnyRef]()
System.setProperty("org.osgi.framework.storage", "target/akka-osgi/" + UUID.randomUUID().toString)
@ -40,7 +43,15 @@ trait PojoSRTestSupport extends Suite with BeforeAndAfterAll {
bundles.addAll(testBundles)
config.put(PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS, bundles)
ServiceLoader.load(classOf[PojoServiceRegistryFactory]).iterator.next.newPojoServiceRegistry(config).getBundleContext
val oldErr = System.err
System.setErr(new PrintStream(bufferedLoadingErrors))
try {
ServiceLoader.load(classOf[PojoServiceRegistryFactory]).iterator.next.newPojoServiceRegistry(config).getBundleContext
} catch {
case e: Throwable oldErr.write(bufferedLoadingErrors.toByteArray); throw e
} finally {
System.setErr(oldErr)
}
}
// Ensure bundles get stopped at the end of the test to release resources and stop threads
@ -72,6 +83,14 @@ trait PojoSRTestSupport extends Suite with BeforeAndAfterAll {
}
protected def buildTestBundles(builders: Seq[BundleDescriptorBuilder]): Seq[BundleDescriptor] = builders map (_.build)
def filterErrors()(block: Unit): Unit = {
try {
block
} catch {
case e: Throwable System.err.write(bufferedLoadingErrors.toByteArray); throw e
}
}
}
object PojoSRTestSupport {