Akka.net: ActorSelection wildcard matching rules

Created on 27 Sep 2017  Â·  11Comments  Â·  Source: akkadotnet/akka.net

var sys = ActorSystem.Create("sys");
var worker = sys.ActorOf<Worker>("worker");
sys.ActorSelection("akka://sys/user/ker*").Tell(42);

Why in this case worker receives the message? I'd expected that "akka://sys/user/*ker*" matches "worker" but "akka://sys/user/ker*" should not. If it is not a proper behaviour it can be fixed in "Util/StringLike.cs"

akka-actor confirmed bug good for first-time contributors up for grabs

Most helpful comment

I will be working on this.

All 11 comments

It’s indeed a bug within the Regex in StringLike. The problem is that it matches worker with ker.*? ( * is replaced with .*? ) so it will return true for any apperance of ker no matter if it starts with ker or not. I don’t have much Regex skills but I think the solution would be to add ^ at the beginning of the pattern, i.e. ^ker.*?. This will only match if the string starts with ker. The old behavior could still be archived by using the wildcard *ker*.

I will be working on this.

Suggested solution:
if(pattern[0] == '*' && pattern[pattern.Length-1]!='*'){
pattern = pattern.Replace("*", "(.*?)");
pattern = pattern + "(?!.)";
}else if(pattern[0]!='*' && pattern[pattern.Length-1]=='*'){
pattern = pattern.Replace("*", "(.*?)");
pattern = @"\A" + pattern;
}else{
pattern = pattern.Replace("*", "(.*?)");
}

@nbparrell
I think it’s even simpler, just add a „^“ at the beginning of the patter, I.e. „ker.*?“ becomes „^ker.*?“ and that wouldn’t match for „worker“, while „^.*?ker.*?“ would match again.

Would also be good to add a unit test to verify the new behavior.

In either case we would have to figure out the placement of the * in order to make sure that we are placing the new regex expression in the correct place. If we passed it *ker we do not want it to be replaced to make (^.*?)ker. This pattern would not find worker which is what we are expecting it to find. We would want it replaced with just (.*?)ker which would find both worker and workers. In order to make it only find worker we append the negative look ahead (?!.) which makes it so that it will not match workers because workers has an s after the ker and we do not want any characters appearing after ker.

That being said I used \A because is clarifies that the particular pattern has to be at the beginning of a string where as ^ can be the beginning of a line.

So we could change the code to :

if(pattern[0] == '*' && pattern[pattern.Length-1]!='*'){
pattern = pattern.Replace("", "(.*?)");
pattern = pattern + "(?!.)";
}else if(pattern[0]!='*' && pattern[pattern.Length-1]=='*'){
pattern = pattern.Replace("
", "(^.*?)");
//pattern = @"\A" + pattern; remove this line.
}else{
pattern = pattern.Replace("*", "(.*?)");
}

@nbparrell alright, go ahead, looks like your Regex skills are much more advanced than mine 😜

@marcpiechura I would not go so far as to say that but I have done the testing and those were my results lol. I will be building a unit test for this before committing. Please test the code also so as to make sure that I am not mistaken in anyway. Always better having more eyes on it. :)

Is there a specific Unit test you would like me to update? Or would you prefer a new Unit test specifically for this?

@nbparrell I would suggest to add one for the fix, i.e. test that ker* doesn't match for worker and one for the "anywhere" case, i.e. *ker* matches worker234

Closed via #3601

Was this page helpful?
0 / 5 - 0 ratings