Is there a way for setting configuration for remote actor selection simliar to the remote actor creation as specified in Akka docs:
akka {
actor {
deployment {
/sampleActor {
remote = "akka.tcp://sampleActorSystem#127.0.0.1:2553"
}
}
}
}
I prefer not to define custom variable for that.
system.actorSelection("sampleActor")
There are only two forms of the actor selection method, from the docs:
def actorSelection(path: ActorPath): ActorSelection
Construct an akka.actor.ActorSelection from the given path, which is
parsed for wildcards (these are replaced by regular expressions
internally). No attempt is made to verify the existence of any part of
the supplied path, it is recommended to send a message and gather the
replies in order to resolve the matching set of actors.
def actorSelection(path: String): ActorSelection
Construct
an akka.actor.ActorSelection from the given path, which is parsed for
wildcards (these are replaced by regular expressions internally). No
attempt is made to verify the existence of any part of the supplied
path, it is recommended to send a message and gather the replies in
order to resolve the matching set of actors.
And an ActorPath is just created from a string anyway:
def
fromString(s: String): ActorPath
Parse string as actor path; throws java.net.MalformedURLException if unable to do so.
So there isn't a direct way to do actor selection just by setting a particular value in config. However it is quite easy to pull a value from config and use it for actor selection. Given the config:
akka {
actor {
selections: {
sampleActor: {
path: "akka.tcp://sampleActorSystem#127.0.0.1:2553/user/sampleActor"
}
}
}
}
You could use:
val sampleActorSelection =
system.actorSelection(
system.settings.config.getString("akka.actor.selections.sampleActor.path"))
If this was a method you found yourself using frequently, you could use an implicit class to add a helper method to system:
implicit class ActorSystemExtension(system: ActorSystem) {
def actorSelectionFromConfig(actorName: String): ActorSelection {
system.actorSelection(
system.settings.config.getString(s"akka.actor.selections.${actorName}.path"))
}
}
Related
I am having a strange issue when mocking the log field of a class. Running the same test twice shows an error the second time. This is an example of code:
class AccountConfigJSON {
static Logger log = Logger.getLogger(AccountConfigJSON.class)
def AccountConfigJSON(String jsonString) {
if (jsonString) {
json = new JSONObject(jsonString)
} else {
log.debug("No JSON string for account config. Will not parse")
}
}
}
and this is the specification
class AccountConfigJSONUnitSpec extends UnitSpec {
def loggerMock
def setup(){
loggerMock = Mock(org.apache.log4j.Logger)
org.apache.log4j.Logger.metaClass.static.getLogger = { Class clazz -> loggerMock }
}
def 'If jsonString is null, a log is written'(){
when:
new AccountConfigJSON("")
then:
1 * loggerMock.debug("No JSON string for account config. Will not parse")
}
def 'If jsonString is empty, a log is written'(){
when:
new AccountConfigJSON("")
then:
1 * loggerMock.debug("No JSON string for account config. Will not parse")
}
}
The second test fails showing
| Too few invocations for:
1 * loggerMock.debug("No JSON string for account config. Will not parse") (0 invocations)
but debugging the app using Idea, clearly it runs this sentence. Any idea?
Looks odd that the actual call is executed but the interaction in not recorded. You can get around with it by explicitly assigning the mocked logger to the class as below:
def setup(){
loggerMock = Mock(org.apache.log4j.Logger)
AccountConfigJSON.log = loggerMock
}
From the definition of "interaction", I think the above setup is the best way to go.
Is an Interaction Just a Regular Method Invocation?
Not quite. While an interaction looks similar to a regular method
invocation, it is simply a way to express which method invocations are
expected to occur. A good way to think of an interaction is as a
regular expression that all incoming invocations on mock objects are
matched against. Depending on the circumstances, the interaction may
match zero, one, or multiple invocations.
This only happens while dealing with static object properties in a class. The moment logger is defined non-static in the class under test, everything works as expected without the work around.
I want to extend the Wso2 CEP product in our needs and try to write a custom condition as indicated in this official wso2 cep link.
I am able to write an extension class that extends "org.wso2.siddhi.core.executor.conditon.AbstractGenericConditionExecutor" and implement its abstract method as indicated below:
#SiddhiExtension(namespace = "myext", function = "startswithA")
public class StringUtils extends
org.wso2.siddhi.core.executor.conditon.AbstractGenericConditionExecutor {
static Log log = LogFactory.getLog(StringUtils.class);
#Override
public boolean execute(AtomicEvent atomicEvent) {
log.error("Entered the execute method");
log.error("Atomic event to string: " + atomicEvent.toString());
return true;
}
}
when i use this extensioned method as:
from allEventsStream[myext:startswithA(name)]
insert into selectedEventsStream *;
In this situation, i want that startswithA method returns true if the name field has 'A' at the begining of it. However when i run this query in CEP the whole event drops into my execute function i.e. there is no sign to show that i send "name" field is sent to startswithA method as argument.
How can i understand which field of the stream is sent to my extended method as argument?
Also i want to write conditions like
from allEventsStream[myext:startswith('A', name)]
insert into selectedEventsStream *;
How can i achive this?
In 'AbstractGenericConditionExecutor' there's another method that gives you the set of expression executors that are included in the parameters when executor instantiates:
public void setExpressionExecutors(List<ExpressionExecutor> expressionExecutors)
You don't necessarily have to override this method and store the list, it is already stored there in the 'AbastractGenericConditionExecutor' as a list named expressionExecutors. You can pass the event to these executors to retrieve the relevant values from the event in order.
For an example, if you include a variable (like 'name') in the query (as a parameter at index 0), you'll get a 'VariableExpressionExecutor' in the list at index 0 that will fetch you the value of the variable from the event. Similarly for a constant like 'A', you'll get a different executor that will give you the value 'A' when called.
To add to Rajeev's answer, if you want to filter all the names that starts with 'A', you can override the execute method of your custom Siddhi extension similar to the following segment.
#Override
public boolean execute(AtomicEvent atomicEvent) {
if(!this.expressionExecutors.isEmpty()) {
String name = (String)this.expressionExecutors.get(0).execute(atomicEvent);
if(name.startsWith("A")) {
return true;
}
}
return false;
}
When writing the query, it would be similar to
from allEventStream[myext:startsWithA(name)]
insert into filteredStream *;
You can extend this behaviour to achieve an extension that supports
from allEventsStream[myext:startswith('A', name)]
type queries as well.
HTH,
Lasantha
I'm learnin about remote actors in Akka 2.1 and I tried to adapt the counter example provided by Typesafe.
I implemented a quick'n'dirty UI from the console to send ticks. And to quit with asking(and showing the result) the current count.
The idea is to start a master node that will run the Counter actor and some client node that will send messages to it through remoting. However I'd like to achieve this through configuration and minimal changes to code. So by changing the configuration local actors could be used.
I found this blog entry about similar problem where it was necessary that all API calls go through one actor even though there are many instances running.
I wrote similar configuration but I cant get it to work. My current code does use remoting but it creates a new actor on the master for each new node and I can't get it to connect to existing actor without explicitly giving it the path(and defying the point of configuration). However this is not what I want since state cannot be shared between JVMs this way.
Full runnable code available through a git repo
This is my config file
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
deployment {
/counter {
remote = "akka://ticker#127.0.0.1:2552"
}
}
}
remote {
transport = "akka.remote.netty.NettyRemoteTransport"
log-sent-messages = on
netty {
hostname = "127.0.0.1"
}
}
}
And full source
import akka.actor._
import akka.pattern.ask
import scala.concurrent.duration._
import akka.util.Timeout
import scala.util._
case object Tick
case object Get
class Counter extends Actor {
var count = 0
val id = math.random.toString.substring(2)
println(s"\nmy name is $id\ni'm at ${self.path}\n")
def log(s: String) = println(s"$id: $s")
def receive = {
case Tick =>
count += 1
log(s"got a tick, now at $count")
case Get =>
sender ! count
log(s"asked for count, replied with $count")
}
}
object AkkaProjectInScala extends App {
val system = ActorSystem("ticker")
implicit val ec = system.dispatcher
val counter = system.actorOf(Props[Counter], "counter")
def step {
print("tick or quit? ")
readLine() match {
case "tick" => counter ! Tick
case "quit" => return
case _ =>
}
step
}
step
implicit val timeout = Timeout(5.seconds)
val f = counter ? Get
f onComplete {
case Failure(e) => throw e
case Success(count) => println("Count is " + count)
}
system.shutdown()
}
I used sbt run and in another window sbt run -Dakka.remote.netty.port=0 to run it.
I found out I can use some sort of pattern. Akka remote allows only for deploying on remote systems(can't find a way to make it look up on remote just through configuration..am I mistaken here?).
So I can deploy a "scout" that will pass back the ActorRef. Runnable code available on the original repo under branch "scout-hack". Because this feels like a hack. I will still appreciate configuration based solution.
The actor
case object Fetch
class Scout extends Actor{
def receive = {
case Fetch => sender ! AkkaProjectInScala._counter
}
}
Counter actor creating is now lazy
lazy val _counter = system.actorOf(Props[Counter], "counter")
So it only executes on the master(determined by the port) and can be fetched like this
val counter: ActorRef = {
val scout = system.actorOf(Props[Scout], "scout")
val ref = Await.result(scout ? Fetch, timeout.duration) match {
case r: ActorRef => r
}
scout ! PoisonPill
ref
}
And full config
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
deployment {
/scout {
remote = "akka://ticker#127.0.0.1:2552"
}
}
}
remote {
transport = "akka.remote.netty.NettyRemoteTransport"
log-sent-messages = on
netty {
hostname = "127.0.0.1"
}
}
}
EDIT: I also found a clean-ish way: check configuration for "counterPath" anf if present actorFor(path) else create actor. Nice and you can inject the master when running and code is much cleaner than with the "scout" but it still has to decide weather to look up or create an actor. I guess this cannot be avoided.
I tried your git project and it actually works fine, aside from a compilation error, and that you must start the sbt session with -Dakka.remote.netty.port=0 parameter to the jvm, not as parameter to run.
You should also understand that you don't have to start the Counter actor in both processes. In this example it's intended to be created from the client and deployed on the server (port 2552). You don't have to start it on the server. It should be enough to create the actor system on the server for this example.
The test class below verifies that a simple HttpService gets content from a given URL. Both the implementations shown make the test pass, though one is clearly wrong because it constructs the URL with an incorrect argument.
To avoid this and correctly specify the behaviour I want, I'd like to verify that in the use block of the test case, I construct one (and only one) instance of the URL class, and that the url argument to the constructor is correct. A Groovy enhancement seems like it would let me add the statement
mockURLContext.demand.URL { assertEquals "http://www.foo.com", url }
but what can I do without that Groovy enhancement?
Update: Replaced "mock" with "stub" in the title, as I'm only interested in checking the state not necessarily the detail of the interactions. Groovy has a StubFor mechanism that I haven't used, so I'll leave my code as is, but I think you could just replace MockFor with StubFor throughout.
import grails.test.*
import groovy.mock.interceptor.MockFor
class HttpServiceTests extends GrailsUnitTestCase {
void testGetsContentForURL() {
def content = [text : "<html><body>Hello, world</body></html>"]
def mockURLContext = new MockFor(URL.class)
mockURLContext.demand.getContent { content }
mockURLContext.use {
def httpService = new HttpService()
assertEquals content.text, httpService.getContentFor("http://www.foo.com")
}
}
}
// This is the intended implementation.
class HttpService {
def getContentFor(url) {
new URL(url).content.text
}
}
// This intentionally wrong implementation also passes the test!
class HttpService {
def getContentFor(url) {
new URL("http://www.wrongurl.com").content.text
}
}
What does mocking the URL get you? It makes the test difficult to write. You won't be able to react to feedback the mock objects give you about the design of the API of the URL class, because it's not under your control. And if you don't precisely fake the behaviour of the URL and what it exposes about the HTTP protocol, the test will not be reliable.
You want to test that your "HttpService" object actually loads the data correctly from a given URL, copes with different content type encodings correctly, handles different classes of HTTP status code appropriately, and so forth. When I need to test this kind object -- one that merely wraps some underlying technical infrastructure -- I write a real integration test that verifies that the object really does use the underlying technology correctly.
For HTTP I write a test that creates an HTTP server, plugs a servlet into the server that will return some canned data, passed the URL of the servlet to the object to make it load the data, check that the loaded result is the same as the canned data used to initialise the servlet, and stop the server in the fixture tear-down. I use Jetty or the simple HTTP server that is bundled with JDK 6.
I'd only use mock objects to test the behaviour of objects that talk to the interface(s) of that object I've integration tested.
Putting on my "Programming in the Small" and "Unit test 100%" hat, you could consider this as a single method that does too many things. You could refactor the HttpService to:
class HttpService {
def newURLFrom(urlString) {
new URL(urlString)
}
def getContentText(url) {
url.content.text
}
def getContentFor(urlString) {
getContentText(newURLFrom(urlString))
}
}
This would give you a few more options for testing, as well as split out the factory aspect from the property manipulation. The testing options are bit more mundane then:
class HttpServiceTests extends GroovyTestCase {
def urlString = "http://stackoverflow.com"
def fauxHtml = "<html><body>Hello, world</body></html>";
def fauxURL = [content : [text : fauxHtml]]
void testMakesURLs() {
assertEquals(urlString,
new HTTPService().newURLFrom(urlString).toExternalForm())
}
void testCanDeriveContentText() {
assertEquals(fauxHtml, new HTTPService().getContentText(fauxURL));
}
// Going a bit overboard to test the line combining the two methods
void testGetsContentForURL() {
def service = new HTTPService()
def emc = new ExpandoMetaClass( service.class, false )
emc.newURLFrom = { input -> assertEquals(urlString, input); return fauxURL }
emc.initialize()
service.metaClass = emc
assertEquals(fauxHtml, service.getContentFor(urlString))
}
}
I think that this makes all the assertions that you want, but at the cost of sacrificing test readability in the last case.
I would agree with Nat about this making more sense as an integration test. (You are integrating with Java's URL library on some level.) But assuming that this example simplifies some complex logic, you could use the metaclass to override the instances class effictvely partially mocking the instance.
It's tough to mock out JDK classes that are declared final... Your problem, as you reference through the enhancement, is that there is no way to create a URL other than calling the constructor.
I try to separate the creation of these kinds of objects from the rest of my code; I'd create a factory to separate the creation the URLs. This should be simple enough to not warrant a test. Others take a typical wrapper/decorator approach. Or you may be able to apply the adapter pattern to translate to domain objects that you write.
Here is a similar answer to a surprisingly similar problem: Mocking a URL in Java
I think this demonstrates something that a lot of people learn after doing more testing: the code we write to make things more testable is meant to isolate what we desire to test from what we can safely say is already tested somewhere else. It's a fundamental assumption we have to make in order to do unit testing. It can also provide a decent example of why good unit tests aren't necessarily about 100% code coverage. They have to be economical, too.
Hope this helps.
What exactly are you expecting to have fail? It is not readily apparent what you are trying to test with that code. By Mocking URL.getContent you are telling Groovy to always return the variable content when URL.getContent() is invoked. Are you wishing to make the return value of URL.getContent() conditional based upon the URL string? If that is the case, the following accomplishes that:
import grails.test.*
import groovy.mock.interceptor.MockFor
class HttpServiceTests extends GrailsUnitTestCase {
def connectionUrl
void testGetsContentForURL() {
// put the desired "correct" URL as the key in the next line
def content = ["http://www.foo.com" : "<html><body>Hello, world</body></html>"]
def mockURLContext = new MockFor(URL.class)
mockURLContext.demand.getContent { [text : content[this.connectionUrl]] }
mockURLContext.use {
def httpService = new HttpService()
this.connectionUrl = "http://www.wrongurl.com"
assertEquals content.text, httpService.getContentFor(this.connectionUrl)
}
}
}
Anyone know of a good way to unit test Scala actors? In the general sense I have an actor that receives a message and will send out other messages in response. This is done on multiple threads, and an actor that is not correct may either send the wrong messages or no message at all. I need a simple way of creating a mockup actor that send and receives messages to the actor being tested. Any experiences in this area?
Because of the dynamic nature of actor-style message passing, mocking actors is usually no trouble at all. Just create an actor which receives the desired message and you're home free. You will of course need to ensure that this mock actor is the one to which messages are passed, but that shouldn't be a problem as long as the actor you are attempting to test is reentrant.
I think the complexity depends on a couple factors...
How stateful is the actor?
If it behaves like a idempotent function, only asynchronous, then it should be a simple matter of mocking up an actor that sends a message and then checks that it receives the expected messages back. You probably want to use a react/receiveWithin on the mock actor in case there is response within a reasonable period of time you can fail rather than hanging.
However if the messages aren't independent of one another, then you should test it with various sequences of messages and expected results.
How many actors will the actor being tested interact with?
If an actor is expected to interact with many others, and it is stateful, then it should be tested with several actors sending/receiving messages. Since you probably have no guarantee of the order in which the messages will arrive, you should be sure to either permute the orders in which the actors send the messages or introduce random pauses in the actors generating messages and run the test many times.
I'm not aware of any prebuilt frameworks for testing actors, but you could possibly look to Erlang for inspiration.
http://svn.process-one.net/contribs/trunk/eunit/doc/overview-summary.html
I have been wondering about how to test Actors myself.
Here is what I came up with, does anybody see problems with this approach?
Rather than send messages directly, what if your actor delegated message sending to a function?
Then your tests can swap out the function with one that tracks the number of times called and/or the arguments with which the method was called:
class MyActor extends Actor {
var sendMessage:(Actor, ContactMsg) => Unit = {
(contactActor, msg) => {
Log.trace("real sendMessage called")
contactActor ! msg
}
}
var reactImpl:PartialFunction(Any, Unit) = {
case INCOMING(otherActor1, otherActor2, args) => {
/* logic to test */
if(args){
sendMessage(otherActor1, OUTGOING_1("foo"))
} else {
sendMessage(otherActor2, OUTGOING_2("bar"))
}
}
}
final def act = loop {
react {
reactImpl
}
}
Your test case might contain code like:
// setup the test
var myActor = new MyActor
var target1 = new MyActor
var target2 = new MyActor
var sendMessageCalls:List[(Actor, String)] = Nil
/*
* Create a fake implementation of sendMessage
* that tracks the arguments it was called with
* in the sendMessageCalls list:
*/
myActor.sendMessage = (actor, message) => {
Log.trace("fake sendMessage called")
message match {
case OUTGOING_1(payload) => {
sendMessageCalls = (actor, payload) :: sendMessageCalls
}
case _ => { fail("Unexpected Message sent:"+message) }
}
}
// run the test
myActor.start
myActor.reactImpl(Incoming(target1, target2, true))
// assert the results
assertEquals(1, sendMessageCalls.size)
val(sentActor, sentPayload) = sendMessageCalls(0)
assertSame(target1, sentActor)
assertEquals("foo", sentPayload)
// .. etc.
My attempt at unit testing an actor (it works). I'm using Specs as a framework.
object ControllerSpec extends Specification {
"ChatController" should{
"add a listener and respond SendFriends" in{
var res = false
val a = actor{}
val mos = {ChatController !? AddListener(a)}
mos match{
case SendFriends => res = true
case _ => res = false
}
res must beTrue
}
How this works is by sending a synchronous call to the singleton ChatController. ChatController responds by use of reply(). The response is sent as a return of the called function, which gets stored into mos. Then a match is applied to mos getting the case class that was sent from ChatController. If the result is what is expected (SendFriends) set res to true. The res must beTrue assertion determines the success or failure of test.
My actor singleton that I'm testing
import ldc.socialirc.model._
import scala.collection.mutable.{HashMap, HashSet}
import scala.actors.Actor
import scala.actors.Actor._
import net.liftweb.util.Helpers._
//Message types
case class AddListener(listener: Actor)
case class RemoveListener(listener: Actor)
case class SendFriends
//Data Types
case class Authority(usr: Actor, role: String)
case class Channel(channelName: String, password: String, creator: String, motd: String, users: HashSet[Authority])
object ChatController extends Actor {
// The Channel List - Shows what actors are in each Chan
val chanList = new HashMap[String, Channel]
// The Actor List - Shows what channels its in
val actorList = new HashMap[Actor, HashSet[String]]
def notifyListeners = {
}
def act = {
loop {
react {
case AddListener(listener: Actor)=>
actorList += listener -> new HashSet[String]
reply(SendFriends)
}
}
}
start //Dont forget to start
}
Though its not complete it does return the Sendfriends case class as expected.
Suite for unit testing of Actors has recently been added to Akka. You can find some information and code snippets in this blogpost.