diff options
Diffstat (limited to 'src/test/java/com/keuin')
18 files changed, 854 insertions, 0 deletions
diff --git a/src/test/java/com/keuin/crosslink/messaging/action/BaseFilterActionTest.java b/src/test/java/com/keuin/crosslink/messaging/action/BaseFilterActionTest.java new file mode 100644 index 0000000..5b3e1e5 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/action/BaseFilterActionTest.java @@ -0,0 +1,36 @@ +package com.keuin.crosslink.messaging.action; + +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.sender.ISender; +import com.keuin.crosslink.testable.FakeEndpoint; +import org.junit.jupiter.api.Test; + +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; + +class BaseFilterActionTest { + @Test + void processAlwaysTrue() { + var action = new BaseFilterAction(m -> true); + var sender = ISender.create("123", UUID.randomUUID()); + var source = new FakeEndpoint(); + var message = IMessage.create(source, sender, "message"); + assertTrue(action.process(message).isValid()); + assertFalse(action.process(message).isDropped()); + assertFalse(action.process(message).isFiltered()); + assertNotNull(action.process(message).getResult()); + } + + @Test + void processAlwaysFalse() { + var action = new BaseFilterAction(m -> false); + var sender = ISender.create("123", UUID.randomUUID()); + var source = new FakeEndpoint(); + var message = IMessage.create(source, sender, "message"); + var result = action.process(message); + assertFalse(result.isValid()); + assertFalse(result.isDropped()); + assertTrue(result.isFiltered()); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/action/BaseReplaceActionTest.java b/src/test/java/com/keuin/crosslink/messaging/action/BaseReplaceActionTest.java new file mode 100644 index 0000000..78d4e6e --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/action/BaseReplaceActionTest.java @@ -0,0 +1,23 @@ +package com.keuin.crosslink.messaging.action; + +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.sender.ISender; +import com.keuin.crosslink.testable.FakeEndpoint; +import org.junit.jupiter.api.Test; + +import java.util.Objects; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class BaseReplaceActionTest { + @Test + void processSimpleReplace() { + var action = new BaseReplaceAction((msg) -> IMessage.create(msg.source(), msg.sender(), "replaced")); + var sender = ISender.create("123", UUID.randomUUID()); + var source = new FakeEndpoint(); + var message = IMessage.create(source, sender, "message"); + assertEquals("message", message.pureString()); + assertEquals("replaced", Objects.requireNonNull(action.process(message).getResult()).pureString()); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/action/DropActionTest.java b/src/test/java/com/keuin/crosslink/messaging/action/DropActionTest.java new file mode 100644 index 0000000..4e0f441 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/action/DropActionTest.java @@ -0,0 +1,25 @@ +package com.keuin.crosslink.messaging.action; + +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.sender.ISender; +import com.keuin.crosslink.testable.FakeEndpoint; +import org.junit.jupiter.api.Test; + +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class DropActionTest { + + @Test + void testDrop() { + var action = new DropAction(); + var sender = ISender.create("123", UUID.randomUUID()); + var source = new FakeEndpoint(); + var message = IMessage.create(source, sender, "message"); + var result = action.process(message); + assertTrue(result.isDropped()); + assertFalse(result.isFiltered()); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/action/Re2placeActionTest.java b/src/test/java/com/keuin/crosslink/messaging/action/Re2placeActionTest.java new file mode 100644 index 0000000..79431f1 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/action/Re2placeActionTest.java @@ -0,0 +1,30 @@ +package com.keuin.crosslink.messaging.action; + +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.sender.ISender; +import com.keuin.crosslink.testable.FakeEndpoint; +import org.junit.jupiter.api.Test; + +import java.util.Objects; +import java.util.UUID; +import java.util.regex.Pattern; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class Re2placeActionTest { + @Test + public void testRemoveHeadingSharp() { + var action = new Re2placeAction(Pattern.compile("^#(.*)"), "$1"); + var sender = ISender.create("123", UUID.randomUUID()); + var source = new FakeEndpoint(); + var message = IMessage.create(source, sender, "#message"); + assertEquals("#message", message.pureString()); + assertEquals("message", Objects.requireNonNull(action.process(message).getResult()).pureString()); + message = IMessage.create(source, sender, "message"); + assertEquals("message", message.pureString()); + assertEquals("message", Objects.requireNonNull(action.process(message).getResult()).pureString()); + message = IMessage.create(source, sender, "mess#age"); + assertEquals("mess#age", message.pureString()); + assertEquals("mess#age", Objects.requireNonNull(action.process(message).getResult()).pureString()); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/action/ReFilterActionTest.java b/src/test/java/com/keuin/crosslink/messaging/action/ReFilterActionTest.java new file mode 100644 index 0000000..257a54c --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/action/ReFilterActionTest.java @@ -0,0 +1,42 @@ +package com.keuin.crosslink.messaging.action; + +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.sender.ISender; +import com.keuin.crosslink.testable.FakeEndpoint; +import org.junit.jupiter.api.Test; + +import java.util.UUID; +import java.util.regex.Pattern; + +import static org.junit.jupiter.api.Assertions.*; + +class ReFilterActionTest { + @Test + public void testFilterHeadingSharp() { + var action = new ReFilterAction(Pattern.compile("#.*")); + var sender = ISender.create("123", UUID.randomUUID()); + var source = new FakeEndpoint(); + var message1 = IMessage.create(source, sender, "#good"); + var message2 = IMessage.create(source, sender, "bad"); + assertFalse(action.process(message1).isFiltered()); + assertFalse(action.process(message1).isDropped()); + assertNotNull(action.process(message1).getResult()); + assertTrue(action.process(message2).isFiltered()); + assertFalse(action.process(message2).isDropped()); + } + + @Test + public void testFilterAlwaysTrue() { + var action = new ReFilterAction(Pattern.compile(".*")); + var sender = ISender.create("123", UUID.randomUUID()); + var source = new FakeEndpoint(); + var message1 = IMessage.create(source, sender, "#good"); + var message2 = IMessage.create(source, sender, "bad"); + assertFalse(action.process(message1).isFiltered()); + assertFalse(action.process(message1).isDropped()); + assertNotNull(action.process(message1).getResult()); + assertFalse(action.process(message2).isFiltered()); + assertFalse(action.process(message2).isDropped()); + assertNotNull(action.process(message2).getResult()); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/action/RouteActionTest.java b/src/test/java/com/keuin/crosslink/messaging/action/RouteActionTest.java new file mode 100644 index 0000000..b9ad631 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/action/RouteActionTest.java @@ -0,0 +1,46 @@ +package com.keuin.crosslink.messaging.action; + +import com.keuin.crosslink.messaging.endpoint.IEndpoint; +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.sender.ISender; +import com.keuin.crosslink.testable.FakeEndpoint; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; + +class RouteActionTest { + + @Test + void testRouteNoBackflow() { + var dest1 = new FakeEndpoint("a"); + var dest2 = new FakeEndpoint("b"); + var dest3 = new FakeEndpoint("c"); + var dests = new HashSet<IEndpoint>(Arrays.asList(dest1, dest2, dest3)); + var action = new RouteAction(() -> dests, false); + var sender = ISender.create("123", UUID.randomUUID()); + var message = IMessage.create(dest1, sender, "message"); + assertSame(message, action.process(message).getResult()); + assertTrue(dest1.messages.isEmpty()); + assertEquals(1, dest2.messages.size()); + assertEquals(1, dest3.messages.size()); + } + + @Test + void testRouteWithBackflow() { + var dest1 = new FakeEndpoint("a"); + var dest2 = new FakeEndpoint("b"); + var dest3 = new FakeEndpoint("c"); + var dests = new HashSet<IEndpoint>(Arrays.asList(dest1, dest2, dest3)); + var action = new RouteAction(() -> dests, true); + var sender = ISender.create("123", UUID.randomUUID()); + var message = IMessage.create(dest1, sender, "message"); + assertSame(message, action.process(message).getResult()); + assertEquals(1, dest1.messages.size()); + assertEquals(1, dest2.messages.size()); + assertEquals(1, dest3.messages.size()); + } +} diff --git a/src/test/java/com/keuin/crosslink/messaging/config/RouterConfigurerTest.java b/src/test/java/com/keuin/crosslink/messaging/config/RouterConfigurerTest.java new file mode 100644 index 0000000..6c9738e --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/config/RouterConfigurerTest.java @@ -0,0 +1,89 @@ +package com.keuin.crosslink.messaging.config; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.keuin.crosslink.messaging.config.router.RouterConfigurer; +import com.keuin.crosslink.messaging.rule.IRule; +import com.keuin.crosslink.messaging.rule.ObjectType; +import com.keuin.crosslink.testable.FakeRouter; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class RouterConfigurerTest { + + private static final String config = """ + [ + // all rules are processed sequentially + // a message may match multiple rules and thus may be duplicate in your case + // if the message is dropped in an action in one rule, + // (the action type is just "drop" and it does not have any argument) + // all subsequent rules will NOT see this message + { + // inbound chat messages (remote -> all servers) + "object": "chat_message", // match chat messages + "from": "remote:.*", // regexp matching source, + // only messages with matched source will be + // processed by this rule, otherwise this rule is skipped + "actions": [{ // actions run sequentially + "type": "route", // route this message to matched destinations + "to": "server:.*" // regexp matching destination \s + }, { + "type": "format", + "color": "green" + }] + }, + { + // outbound messages (starting with '#', server -> all remotes) + "object": "chat_message", + "from": "server:.*", + "actions": [{ + "type": "filter", // filter the message using given regexp + // if the message does not match given pattern, + // it won't be passed into subsequent actions + "pattern": "#.+" // match all messages starts with char '#' + }, { + "type": "replace", // replace the message, removing heading '#' + "from": "^#\\\\(.*\\\\)", // capture all chars after the heading '#' + "to": "$1" // and make them as the output + }, { + "type": "route", // send the message to all remotes + "to": "remote:.*" + }] + }, + { + // cross-server messages (server -> all other servers) + "object": "chat_message", + "from": "server:.*", + "actions": [{ + "type": "route", + "to": "server:.*", + "backflow": false // do not repeat to sender, true by default + // since the destination pattern will match the source, + // we have to set backflow to false to prevent + // players from seeing duplicate messages + }] + } + ]"""; + + @Test + void decode() throws ConfigSyntaxError, JsonProcessingException { + var router = new FakeRouter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); + var rc = new RouterConfigurer(mapper.readTree(config)); + rc.configure(router); + var chain = router.getRules(); + + IRule r; + assertEquals(3, chain.size()); + r = chain.get(0); + assertEquals(r.object(), ObjectType.CHAT_MESSAGE); + r = chain.get(1); + assertEquals(r.object(), ObjectType.CHAT_MESSAGE); + r = chain.get(2); + assertEquals(r.object(), ObjectType.CHAT_MESSAGE); + // TODO + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/config/RuleListsTest.java b/src/test/java/com/keuin/crosslink/messaging/config/RuleListsTest.java new file mode 100644 index 0000000..b9a10d6 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/config/RuleListsTest.java @@ -0,0 +1,38 @@ +package com.keuin.crosslink.messaging.config; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +class RuleListsTest { + + @Test + void fromJson() throws JsonProcessingException { + var json = new String(Base64.getDecoder() + .decode("WwogICAgLy8gYWxsIHJ1bGVzIGFyZSBwcm9jZXNzZWQgc2VxdWVudGlhbGx5CiAgICAvLyBhIG1lc3NhZ2UgbWF5IG1hdGNoIG11bHRpcGxlIHJ1bGVzIGFuZCB0aHVzIG1heSBiZSBkdXBsaWNhdGUgaW4geW91ciBjYXNlCiAgICAvLyBpZiB0aGUgbWVzc2FnZSBpcyBkcm9wcGVkIGluIGFuIGFjdGlvbiBpbiBvbmUgcnVsZSwKICAgIC8vICh0aGUgYWN0aW9uIHR5cGUgaXMganVzdCAiZHJvcCIgYW5kIGl0IGRvZXMgbm90IGhhdmUgYW55IGFyZ3VtZW50KQogICAgLy8gYWxsIHN1YnNlcXVlbnQgcnVsZXMgd2lsbCBOT1Qgc2VlIHRoaXMgbWVzc2FnZQogICAgewogICAgICAgIC8vIGluYm91bmQgY2hhdCBtZXNzYWdlcyAocmVtb3RlIC0+IGFsbCBzZXJ2ZXJzKQogICAgICAgICJvYmplY3QiOiAiY2hhdF9tZXNzYWdlIiwgLy8gbWF0Y2ggY2hhdCBtZXNzYWdlcwogICAgICAgICJmcm9tIjogInJlbW90ZTouKiIsICAgICAgLy8gcmVnZXhwIG1hdGNoaW5nIHNvdXJjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9ubHkgbWVzc2FnZXMgd2l0aCBtYXRjaGVkIHNvdXJjZSB3aWxsIGJlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwcm9jZXNzZWQgYnkgdGhpcyBydWxlLCBvdGhlcndpc2UgdGhpcyBydWxlIGlzIHNraXBwZWQKICAgICAgICAiYWN0aW9ucyI6IFt7ICAgICAgICAgICAgIC8vIGFjdGlvbnMgcnVuIHNlcXVlbnRpYWxseQogICAgICAgICAgICAidHlwZSI6ICJyb3V0ZSIsICAgICAgLy8gcm91dGUgdGhpcyBtZXNzYWdlIHRvIG1hdGNoZWQgZGVzdGluYXRpb25zCiAgICAgICAgICAgICJ0byI6ICJzZXJ2ZXI6LioiICAgICAvLyByZWdleHAgbWF0Y2hpbmcgZGVzdGluYXRpb24gIAogICAgICAgIH1dCiAgICB9LAogICAgewogICAgICAgIC8vIG91dGJvdW5kIG1lc3NhZ2VzIChzdGFydGluZyB3aXRoICcjJywgc2VydmVyIC0+IGFsbCByZW1vdGVzKQogICAgICAgICJvYmplY3QiOiAiY2hhdF9tZXNzYWdlIiwKICAgICAgICAiZnJvbSI6ICJzZXJ2ZXI6LioiLAogICAgICAgICJhY3Rpb25zIjogW3sKICAgICAgICAgICAgInR5cGUiOiAiZmlsdGVyIiwgICAgIC8vIGZpbHRlciB0aGUgbWVzc2FnZSB1c2luZyBnaXZlbiByZWdleHAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBtZXNzYWdlIGRvZXMgbm90IG1hdGNoIGdpdmVuIHBhdHRlcm4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdCB3b24ndCBiZSBwYXNzZWQgaW50byBzdWJzZXF1ZW50IGFjdGlvbnMKICAgICAgICAgICAgInBhdHRlcm4iOiAiIy4rIiAgICAgIC8vIG1hdGNoIGFsbCBtZXNzYWdlcyBzdGFydHMgd2l0aCBjaGFyICcjJwogICAgICAgIH0sIHsKICAgICAgICAgICAgInR5cGUiOiAicmVwbGFjZSIsICAgIC8vIHJlcGxhY2UgdGhlIG1lc3NhZ2UsIHJlbW92aW5nIGhlYWRpbmcgJyMnCiAgICAgICAgICAgICJmcm9tIjogIl4jXFwoLipcXCkiLCAvLyBjYXB0dXJlIGFsbCBjaGFycyBhZnRlciB0aGUgaGVhZGluZyAnIycKICAgICAgICAgICAgInRvIjogIiQxIiAgICAgICAgICAgIC8vIGFuZCBtYWtlIHRoZW0gYXMgdGhlIG91dHB1dAogICAgICAgIH0sIHsKICAgICAgICAgICAgInR5cGUiOiAicm91dGUiLCAgICAgIC8vIHNlbmQgdGhlIG1lc3NhZ2UgdG8gYWxsIHJlbW90ZXMKICAgICAgICAgICAgInRvIjogInJlbW90ZTouKiIKICAgICAgICB9XQogICAgfSwKICAgIHsKICAgICAgICAvLyBjcm9zcy1zZXJ2ZXIgbWVzc2FnZXMgKHNlcnZlciAtPiBhbGwgb3RoZXIgc2VydmVycykKICAgICAgICAib2JqZWN0IjogImNoYXRfbWVzc2FnZSIsCiAgICAgICAgImZvcm0iOiAic2VydmVyOi4qIiwKICAgICAgICAiYWN0aW9ucyI6IFt7CiAgICAgICAgICAgICJ0eXBlIjogInJvdXRlIiwKICAgICAgICAgICAgInRvIjogInNlcnZlcjouKiIsCiAgICAgICAgICAgICJiYWNrZmxvdyI6IGZhbHNlICAvLyBkbyBub3QgcmVwZWF0IHRvIHNlbmRlciwgdHJ1ZSBieSBkZWZhdWx0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzaW5jZSB0aGUgZGVzdGluYXRpb24gcGF0dGVybiB3aWxsIG1hdGNoIHRoZSBzb3VyY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBoYXZlIHRvIHNldCBiYWNrZmxvdyB0byBmYWxzZSB0byBwcmV2ZW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwbGF5ZXJzIGZyb20gc2VlaW5nIGR1cGxpY2F0ZSBtZXNzYWdlcwogICAgICAgIH1dCiAgICB9Cl0="), + StandardCharsets.UTF_8); + var mapper = new ObjectMapper(); + mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); + var t = mapper.readTree(json); + for (var rule : t) { + var object = rule.get("object"); + var from = rule.get("from"); + var actions = rule.get("actions"); + System.out.printf("%s | %s | %s%n", object, from, actions); + } + } + + @Test + void testReadObjectType() { + + } + + @Test + void testReadReIdFilter() { + + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/filter/IFilterTest.java b/src/test/java/com/keuin/crosslink/messaging/filter/IFilterTest.java new file mode 100644 index 0000000..be20077 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/filter/IFilterTest.java @@ -0,0 +1,32 @@ +package com.keuin.crosslink.messaging.filter; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class IFilterTest { + + @Test + void fromPatternString() throws ReIdFilter.InvalidPatternStringException { + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString(":::")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("::")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString(":")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("server:::")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("server::")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("server:")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString(":server::")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString(":server:")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString(":server")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString(":::server")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("::server")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("server")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("server:")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("server:bbb:")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("server:aaa:bbb")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("remote:aa\n")); + assertThrows(ReIdFilter.InvalidPatternStringException.class, () -> IFilter.fromPatternString("server:aa\n")); + assertDoesNotThrow(() -> IFilter.fromPatternString("server:b")); + assertDoesNotThrow(() -> IFilter.fromPatternString("remote:bbb")); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/message/ComponentBackedMessageTest.java b/src/test/java/com/keuin/crosslink/messaging/message/ComponentBackedMessageTest.java new file mode 100644 index 0000000..ad483d5 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/message/ComponentBackedMessageTest.java @@ -0,0 +1,22 @@ +package com.keuin.crosslink.messaging.message; + +import com.keuin.crosslink.messaging.sender.ISender; +import com.keuin.crosslink.testable.FakeEndpoint; +import net.kyori.adventure.text.Component; +import org.junit.jupiter.api.Test; + +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ComponentBackedMessageTest { + + @Test + void testPureString() { + var source = new FakeEndpoint("endpoint"); + var sender = ISender.create("sender", UUID.randomUUID()); + var comp = Component.text("text").append(Component.text("message")); + var msg = new ComponentBackedMessage(source, sender, comp); + assertEquals("textmessage", msg.pureString()); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/router/ConcreteRouterTest.java b/src/test/java/com/keuin/crosslink/messaging/router/ConcreteRouterTest.java new file mode 100644 index 0000000..b9ace8d --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/router/ConcreteRouterTest.java @@ -0,0 +1,132 @@ +package com.keuin.crosslink.messaging.router; + +import com.keuin.crosslink.messaging.action.DropAction; +import com.keuin.crosslink.messaging.action.ReFilterAction; +import com.keuin.crosslink.messaging.action.RouteAction; +import com.keuin.crosslink.messaging.filter.IFilter; +import com.keuin.crosslink.messaging.filter.ReIdFilter; +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.rule.IRule; +import com.keuin.crosslink.messaging.rule.ImmutableRule; +import com.keuin.crosslink.messaging.rule.ObjectType; +import com.keuin.crosslink.messaging.sender.ISender; +import com.keuin.crosslink.testable.FakeEndpoint; +import com.keuin.crosslink.testable.FakeRouter; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.regex.Pattern; + +import static org.junit.jupiter.api.Assertions.*; + +class ConcreteRouterTest { + + private ConcreteRouter router; + private FakeEndpoint ep1 = new FakeEndpoint("a"); + private FakeEndpoint ep2 = new FakeEndpoint("b"); + private FakeEndpoint ep3 = new FakeEndpoint("c"); + + @BeforeEach + void setUp() { + router = new ConcreteRouter(); + router.addEndpoint(ep1); + router.addEndpoint(ep2); + router.addEndpoint(ep3); + } + + @Test + void testBroadcast() throws ReIdFilter.InvalidPatternStringException { + var ep0 = new FakeEndpoint("z"); + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(ep0, sender, "MSG,,,"); + var action = new RouteAction(() -> router.resolveEndpoints("server", Pattern.compile(".*")), true); + var rule = new ImmutableRule(ObjectType.CHAT_MESSAGE, IFilter.fromPatternString("server:z"), Collections.singletonList(action)); + router.updateRuleChain(Collections.singletonList(rule)); + router.sendMessage(msg); + assertEquals(1, ep1.messages.size()); + assertEquals(1, ep2.messages.size()); + assertEquals(1, ep3.messages.size()); + assertEquals(msg, ep1.messages.get(0)); + assertEquals(msg, ep2.messages.get(0)); + assertEquals(msg, ep3.messages.get(0)); + } + + @Test + void testBroadcastBackflow() throws ReIdFilter.InvalidPatternStringException { + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(ep1, sender, "MSG,,,"); + var action = new RouteAction(() -> router.resolveEndpoints("server", Pattern.compile(".*")), true); + var rule = new ImmutableRule(ObjectType.CHAT_MESSAGE, IFilter.fromPatternString("server:a"), Collections.singletonList(action)); + router.updateRuleChain(Collections.singletonList(rule)); + router.sendMessage(msg); + assertEquals(1, ep1.messages.size()); + assertEquals(1, ep2.messages.size()); + assertEquals(1, ep3.messages.size()); + assertEquals(msg, ep1.messages.get(0)); + assertEquals(msg, ep2.messages.get(0)); + assertEquals(msg, ep3.messages.get(0)); + } + + @Test + void testBroadcastBackflowDisabled() throws ReIdFilter.InvalidPatternStringException { + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(ep1, sender, "MSG,,,"); + var action = new RouteAction(() -> router.resolveEndpoints("server", Pattern.compile(".*")), false); + var rule = new ImmutableRule(ObjectType.CHAT_MESSAGE, IFilter.fromPatternString("server:a"), Collections.singletonList(action)); + router.updateRuleChain(Collections.singletonList(rule)); + router.sendMessage(msg); + assertEquals(0, ep1.messages.size()); + assertEquals(1, ep2.messages.size()); + assertEquals(1, ep3.messages.size()); + assertEquals(msg, ep2.messages.get(0)); + assertEquals(msg, ep3.messages.get(0)); + } + + @Test + void testFilteredMessagePass() throws ReIdFilter.InvalidPatternStringException { + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(ep1, sender, "MSG,,,"); + var filter = new ReFilterAction(Pattern.compile("asdasdasda")); + var action = new RouteAction(() -> router.resolveEndpoints("server", Pattern.compile(".*")), false); + var rule1 = new ImmutableRule(ObjectType.CHAT_MESSAGE, IFilter.fromPatternString("server:.+"), Collections.singletonList(filter)); + var rule2 = new ImmutableRule(ObjectType.CHAT_MESSAGE, IFilter.fromPatternString("server:a"), List.of(filter, action)); + var rule3 = new ImmutableRule(ObjectType.CHAT_MESSAGE, IFilter.fromPatternString("server:a"), List.of(action)); + router.updateRuleChain(List.of(rule1, rule2, rule3)); + router.sendMessage(msg); + assertEquals(0, ep1.messages.size()); + assertEquals(1, ep2.messages.size()); + assertEquals(1, ep3.messages.size()); + assertEquals(msg, ep2.messages.get(0)); + assertEquals(msg, ep3.messages.get(0)); + } + + @Test + void testDropMessagePass() throws ReIdFilter.InvalidPatternStringException { + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(ep1, sender, "MSG,,,"); + var drop = new DropAction(); + var action = new RouteAction(() -> router.resolveEndpoints("server", Pattern.compile(".*")), false); + var rule1 = new ImmutableRule(ObjectType.CHAT_MESSAGE, IFilter.fromPatternString("server:a"), List.of(action)); + var rule2 = new ImmutableRule(ObjectType.CHAT_MESSAGE, IFilter.fromPatternString("server:.+"), Collections.singletonList(drop)); + var rule3 = new ImmutableRule(ObjectType.CHAT_MESSAGE, IFilter.fromPatternString("server:a"), List.of(action)); + router.updateRuleChain(List.of(rule1, rule2, rule3)); + router.sendMessage(msg); + assertEquals(0, ep1.messages.size()); + assertEquals(1, ep2.messages.size()); + assertEquals(1, ep3.messages.size()); + assertEquals(msg, ep2.messages.get(0)); + assertEquals(msg, ep3.messages.get(0)); + } + + @AfterEach + void tearDown() throws Exception { + ep1.close(); + ep2.close(); + ep3.close(); + router.close(); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/messaging/rule/ImmutableRuleTest.java b/src/test/java/com/keuin/crosslink/messaging/rule/ImmutableRuleTest.java new file mode 100644 index 0000000..f50425f --- /dev/null +++ b/src/test/java/com/keuin/crosslink/messaging/rule/ImmutableRuleTest.java @@ -0,0 +1,95 @@ +package com.keuin.crosslink.messaging.rule; + +import com.keuin.crosslink.messaging.action.Re2placeAction; +import com.keuin.crosslink.messaging.action.ReFilterAction; +import com.keuin.crosslink.messaging.filter.IFilter; +import com.keuin.crosslink.messaging.filter.ReIdFilter; +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.sender.ISender; +import com.keuin.crosslink.testable.FakeEndpoint; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; + +class ImmutableRuleTest { + + @Test + void testEmptyRule() throws ReIdFilter.InvalidPatternStringException { + var fromFilter = IFilter.fromPatternString("server:.*"); + var rule = new ImmutableRule(ObjectType.CHAT_MESSAGE, fromFilter, Collections.emptyList()); + var source = new FakeEndpoint("endpoint"); + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(source, sender, "message"); + var result = rule.process(msg); + assertTrue(result.isValid()); + assertEquals(msg, result.getResult()); + } + + @Test + void testSingleFilter() throws ReIdFilter.InvalidPatternStringException { + var fromFilter = IFilter.fromPatternString("server:.*"); + var msgFilter = new ReFilterAction(Pattern.compile("mess...")); + var rule = new ImmutableRule(ObjectType.CHAT_MESSAGE, fromFilter, Collections.singletonList(msgFilter)); + var source = new FakeEndpoint("endpoint"); + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(source, sender, "message"); + var result = rule.process(msg); + assertTrue(result.isValid()); + assertEquals(msg, result.getResult()); + } + + @Test + void testFilterReplace() throws ReIdFilter.InvalidPatternStringException { + var fromFilter = IFilter.fromPatternString("server:.*"); + var msgFilter = new ReFilterAction(Pattern.compile("mess...")); + var msgReplace = new Re2placeAction(Pattern.compile("me."), "u"); + var rule = new ImmutableRule(ObjectType.CHAT_MESSAGE, fromFilter, List.of(msgFilter, msgReplace)); + var source = new FakeEndpoint("endpoint"); + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(source, sender, "message"); + var result = rule.process(msg); + assertTrue(result.isValid()); + assertFalse(result.isFiltered()); + assertFalse(result.isDropped()); + assertEquals("usage", Objects.requireNonNull(result.getResult()).pureString()); + } + + @Test + void testFilterReplaceFilter1() throws ReIdFilter.InvalidPatternStringException { + var fromFilter = IFilter.fromPatternString("server:.*"); + var msgFilter = new ReFilterAction(Pattern.compile("mess...")); + var msgReplace = new Re2placeAction(Pattern.compile("me."), "u"); + var rule = new ImmutableRule(ObjectType.CHAT_MESSAGE, fromFilter, List.of(msgFilter, msgReplace, msgFilter)); + var source = new FakeEndpoint("endpoint"); + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(source, sender, "message"); + var result = rule.process(msg); + assertTrue(result.isFiltered()); + assertFalse(result.isDropped()); + assertFalse(result.isValid()); + } + + @Test + void testFilterReplaceFilter2() throws ReIdFilter.InvalidPatternStringException { + var fromFilter = IFilter.fromPatternString("server:.*"); + var msgFilter = new ReFilterAction(Pattern.compile("mess...")); + var msgReplace = new Re2placeAction(Pattern.compile("me."), "u"); + var msgFilter2 = new ReFilterAction(Pattern.compile("us...")); + var rule = new ImmutableRule(ObjectType.CHAT_MESSAGE, fromFilter, List.of(msgFilter, msgReplace, msgFilter2)); + var source = new FakeEndpoint("endpoint"); + var sender = ISender.create("sender", UUID.randomUUID()); + var msg = IMessage.create(source, sender, "message"); + var result = rule.process(msg); + assertFalse(result.isFiltered()); + assertFalse(result.isDropped()); + assertTrue(result.isValid()); + assertEquals("usage", Objects.requireNonNull(result.getResult()).pureString()); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/testable/FakeEndpoint.java b/src/test/java/com/keuin/crosslink/testable/FakeEndpoint.java new file mode 100644 index 0000000..ada299e --- /dev/null +++ b/src/test/java/com/keuin/crosslink/testable/FakeEndpoint.java @@ -0,0 +1,51 @@ +package com.keuin.crosslink.testable; + +import com.keuin.crosslink.messaging.endpoint.EndpointNamespace; +import com.keuin.crosslink.messaging.endpoint.IEndpoint; +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.router.IRouter; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class FakeEndpoint implements IEndpoint { + public final List<IMessage> messages = new ArrayList<>(); + public IRouter router = null; + private final String id; + + public FakeEndpoint(String id) { + this.id = id; + } + + public FakeEndpoint() { + this.id = "fake"; + } + + @Override + public void sendMessage(IMessage message) { + Objects.requireNonNull(message); + messages.add(message); + } + + @Override + public void setRouter(IRouter router) { + this.router = router; + } + + @Override + public void close() { + + } + + @Override + public @NotNull String id() { + return id; + } + + @Override + public @NotNull EndpointNamespace namespace() { + return EndpointNamespace.SERVER; + } +} diff --git a/src/test/java/com/keuin/crosslink/testable/FakeRouter.java b/src/test/java/com/keuin/crosslink/testable/FakeRouter.java new file mode 100644 index 0000000..0512b3e --- /dev/null +++ b/src/test/java/com/keuin/crosslink/testable/FakeRouter.java @@ -0,0 +1,65 @@ +package com.keuin.crosslink.testable; + +import com.keuin.crosslink.messaging.endpoint.IEndpoint; +import com.keuin.crosslink.messaging.message.IMessage; +import com.keuin.crosslink.messaging.router.IRouter; +import com.keuin.crosslink.messaging.rule.IRule; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class FakeRouter implements IRouter { + private final List<IMessage> messages = new ArrayList<>(); + private final AtomicBoolean isClosed = new AtomicBoolean(false); + private final List<IEndpoint> endpoints = new ArrayList<>(); + private List<IRule> rules = Collections.emptyList(); + + @Override + public void sendMessage(IMessage message) { + messages.add(message); + } + + @Override + public void close() throws Exception { + isClosed.set(true); + } + + @Override + public boolean addEndpoint(@NotNull IEndpoint endpoint) { + return endpoints.add(endpoint); + } + + @Override + public @NotNull Set<IEndpoint> resolveEndpoints(@NotNull String namespace, @NotNull Pattern idPattern) { + return endpoints.stream() + .filter((ep) -> ep.namespace().toString().equals(namespace) && idPattern.matcher(ep.id()).matches()) + .collect(Collectors.toUnmodifiableSet()); + } + + @Override + public void updateRuleChain(@NotNull List<IRule> newChain) { + this.rules = newChain; + } + + public List<IMessage> getMessages() { + return messages; + } + + public AtomicBoolean getIsClosed() { + return isClosed; + } + + public List<IEndpoint> getEndpoints() { + return endpoints; + } + + public List<IRule> getRules() { + return rules; + } +} diff --git a/src/test/java/com/keuin/crosslink/util/EggFactoryTest.java b/src/test/java/com/keuin/crosslink/util/EggFactoryTest.java new file mode 100644 index 0000000..2c26e38 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/util/EggFactoryTest.java @@ -0,0 +1,38 @@ +package com.keuin.crosslink.util; + +import net.time4j.PlainDate; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EggFactoryTest { + + @Test + void getEgg() { + // 2021 lunar new year (2021.02.12) + assertFalse(EggFactory.getEgg(PlainDate.of(2021, 2, 11)).isPresent()); + assertTrue(EggFactory.getEgg(PlainDate.of(2021, 2, 12)).isPresent()); + assertFalse(EggFactory.getEgg(PlainDate.of(2021, 2, 13)).isPresent()); + + // 2022 lunar new year (2022.02.01) + assertFalse(EggFactory.getEgg(PlainDate.of(2022, 1, 31)).isPresent()); + assertTrue(EggFactory.getEgg(PlainDate.of(2022, 2, 1)).isPresent()); + assertFalse(EggFactory.getEgg(PlainDate.of(2022, 2, 2)).isPresent()); + + // 2023 lunar new year (2023.01.22) + assertFalse(EggFactory.getEgg(PlainDate.of(2023, 1, 21)).isPresent()); + assertTrue(EggFactory.getEgg(PlainDate.of(2023, 1, 22)).isPresent()); + assertFalse(EggFactory.getEgg(PlainDate.of(2023, 1, 23)).isPresent()); + + // 2024 lunar new year (2024.02.10) + assertFalse(EggFactory.getEgg(PlainDate.of(2024, 2, 9)).isPresent()); + assertTrue(EggFactory.getEgg(PlainDate.of(2024, 2, 10)).isPresent()); + assertFalse(EggFactory.getEgg(PlainDate.of(2024, 2, 11)).isPresent()); + + // 2025 lunar new year (2025.01.29) + assertFalse(EggFactory.getEgg(PlainDate.of(2025, 1, 28)).isPresent()); + assertTrue(EggFactory.getEgg(PlainDate.of(2025, 1, 29)).isPresent()); + assertFalse(EggFactory.getEgg(PlainDate.of(2025, 1, 30)).isPresent()); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/util/HttpQueryTest.java b/src/test/java/com/keuin/crosslink/util/HttpQueryTest.java new file mode 100644 index 0000000..480c854 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/util/HttpQueryTest.java @@ -0,0 +1,48 @@ +package com.keuin.crosslink.util; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class HttpQueryTest { + @Test + void testMixedFlagValue() { + var map = HttpQuery.getParamMap("var1=1&flag1"); + assertTrue(map.containsKey("flag1")); + assertTrue(map.containsKey("var1")); + assertEquals("1", map.get("var1")); + assertEquals("", map.get("flag1")); + } + + @Test + void testSingleFlag() { + var map = HttpQuery.getParamMap("flag1"); + assertTrue(map.containsKey("flag1")); + assertEquals("", map.get("flag1")); + } + + @Test + void testSingleVar() { + var map = HttpQuery.getParamMap("var1=value"); + assertTrue(map.containsKey("var1")); + assertEquals("value", map.get("var1")); + } + + @Test + void testMultipleValue() { + var map = HttpQuery.getParamMap("var1=111&var2=222"); + assertTrue(map.containsKey("var1")); + assertTrue(map.containsKey("var2")); + assertEquals("111", map.get("var1")); + assertEquals("222", map.get("var2")); + } + + @Test + void testMultipleKey() { + var map = HttpQuery.getParamMap("flag1&flag2"); + assertTrue(map.containsKey("flag1")); + assertTrue(map.containsKey("flag2")); + assertEquals("", map.get("flag1")); + assertEquals("", map.get("flag2")); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/util/LazyEvaluatedTest.java b/src/test/java/com/keuin/crosslink/util/LazyEvaluatedTest.java new file mode 100644 index 0000000..e8ffdc9 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/util/LazyEvaluatedTest.java @@ -0,0 +1,28 @@ +package com.keuin.crosslink.util; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.*; + +class LazyEvaluatedTest { + + @Test + void get() { + var flag = new AtomicBoolean(false); // if evaluated + var cnt = new AtomicInteger(0); // counter + var le = new LazyEvaluated<>(() -> { + flag.set(true); + return cnt.getAndIncrement(); + }); + assertFalse(flag.get()); + assertEquals(0, le.get()); + assertTrue(flag.get()); + assertEquals(0, le.get()); + assertEquals(0, le.get()); + assertEquals(0, le.get()); + assertEquals(0, le.get()); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/crosslink/util/LoggerNamingTest.java b/src/test/java/com/keuin/crosslink/util/LoggerNamingTest.java new file mode 100644 index 0000000..5fbdcf1 --- /dev/null +++ b/src/test/java/com/keuin/crosslink/util/LoggerNamingTest.java @@ -0,0 +1,14 @@ +package com.keuin.crosslink.util; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class LoggerNamingTest { + + @Test + void name() { + assertEquals("crosslink", LoggerNaming.name().toString()); + assertEquals("crosslink.actions.replace", LoggerNaming.name().of("actions").of("replace").toString()); + } +}
\ No newline at end of file |