From d91ee5b04f9682f6526db91f0b6ac9c25b9a25f5 Mon Sep 17 00:00:00 2001 From: Lars Simon Winzer Date: Sun, 26 Apr 2026 19:10:11 +0200 Subject: [PATCH] Test: Add unit tests for ResponseEncoder --- .../dispatcher/ResponseEncoderTest.java | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/test/java/ch/unibas/dmi/dbis/cs108/casono/server/network/protocol/response/dispatcher/ResponseEncoderTest.java diff --git a/src/test/java/ch/unibas/dmi/dbis/cs108/casono/server/network/protocol/response/dispatcher/ResponseEncoderTest.java b/src/test/java/ch/unibas/dmi/dbis/cs108/casono/server/network/protocol/response/dispatcher/ResponseEncoderTest.java new file mode 100644 index 0000000..f1b819d --- /dev/null +++ b/src/test/java/ch/unibas/dmi/dbis/cs108/casono/server/network/protocol/response/dispatcher/ResponseEncoderTest.java @@ -0,0 +1,130 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext; +import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.PrimitiveResponse; +import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.Response; +import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBlock; +import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody; +import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseParameter; +import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionId; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.UUID; +import org.junit.jupiter.api.Test; + +public class ResponseEncoderTest { + private class TestResponse extends Response { + public TestResponse(RequestContext context, ResponseBody body) { + super(context, body); + } + + @Override + public String prefix() { + return "+OK"; + } + } + + @Test + void testEncodeParameterSimple() { + ResponseBody body = ResponseBody.builder().param("param", "value").build(); + + RequestContext ctx = new RequestContext(new SessionId(), 42); + Response response = new TestResponse(ctx, body); + + PrimitiveResponse pr = ResponseEncoder.encode(response); + + String expected = "+OK\n\tparam=value\nEND"; + assertEquals(expected, pr.payload()); + } + + @Test + void testEncodeParameterMasking() { + ResponseBody body = ResponseBody.builder().param("msg", "It's a me, malario").build(); + + RequestContext ctx = new RequestContext(new SessionId(), 42); + Response response = new TestResponse(ctx, body); + + PrimitiveResponse pr = ResponseEncoder.encode(response); + String expected = "+OK\n\tmsg='It\\'s a me, malario'\nEND"; + assertEquals(expected, pr.payload()); + } + + @Test + void testEncodeNestedBlock() { + ResponseBody body = + ResponseBody.builder().block("TAG", b -> b.param("param", "key")).build(); + + RequestContext ctx = new RequestContext(new SessionId(UUID.randomUUID()), 42); + Response response = new TestResponse(ctx, body); + + PrimitiveResponse pr = ResponseEncoder.encode(response); + + String expected = "+OK\n\tTAG\n\t\tparam=key\n\tEND\nEND"; + assertEquals(expected, pr.payload()); + } + + @Test + void testPrivateEncodeParameter() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + var param = new ResponseParameter("p", "v"); + StringBuilder sb = new StringBuilder(); + + Method m = + ResponseEncoder.class.getDeclaredMethod( + "encodeParameter", ResponseParameter.class, StringBuilder.class, int.class); + m.setAccessible(true); + m.invoke(null, param, sb, 1); + + assertEquals("\tp=v", sb.toString()); + } + + @Test + void testWordNoMask() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + Method m = ResponseEncoder.class.getDeclaredMethod("maskIfNeeded", String.class); + m.setAccessible(true); + + String noMask = (String) m.invoke(null, "abc"); + assertEquals("abc", noMask); + } + + @Test + void testMaskString() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + Method m = ResponseEncoder.class.getDeclaredMethod("maskIfNeeded", String.class); + m.setAccessible(true); + + String withSpace = (String) m.invoke(null, "a b"); + assertEquals("'a b'", withSpace); + } + + @Test + void testEscapeSingleQuote() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + Method m = ResponseEncoder.class.getDeclaredMethod("maskIfNeeded", String.class); + m.setAccessible(true); + + String withSpace = (String) m.invoke(null, "a b"); + assertEquals("'a b'", withSpace); + } + + @Test + void testPrivateEncodeBlock() + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + var child = new ResponseParameter("a", "b"); + var block = new ResponseBlock("TAG", List.of(child)); + StringBuilder sb = new StringBuilder(); + + Method m = + ResponseEncoder.class.getDeclaredMethod( + "encodeBlock", ResponseBlock.class, StringBuilder.class, int.class); + m.setAccessible(true); + m.invoke(null, block, sb, 1); + + String expected = "\tTAG\n\t\ta=b\n\tEND"; + assertEquals(expected, sb.toString()); + } +} -- 2.52.0