diff --git a/.idea/libraries/junit_jupiter.xml b/.idea/libraries/junit_jupiter.xml new file mode 100644 index 0000000..7bbe2d4 --- /dev/null +++ b/.idea/libraries/junit_jupiter.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/mockito_core.xml b/.idea/libraries/mockito_core.xml new file mode 100644 index 0000000..fa3e0af --- /dev/null +++ b/.idea/libraries/mockito_core.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/apiguardian-api-1.1.2.jar b/lib/apiguardian-api-1.1.2.jar new file mode 100644 index 0000000..2b678e1 Binary files /dev/null and b/lib/apiguardian-api-1.1.2.jar differ diff --git a/lib/junit-jupiter-5.9.0.jar b/lib/junit-jupiter-5.9.0.jar new file mode 100644 index 0000000..ba53fad Binary files /dev/null and b/lib/junit-jupiter-5.9.0.jar differ diff --git a/lib/junit-jupiter-api-5.9.0.jar b/lib/junit-jupiter-api-5.9.0.jar new file mode 100644 index 0000000..6f4cc94 Binary files /dev/null and b/lib/junit-jupiter-api-5.9.0.jar differ diff --git a/lib/junit-jupiter-engine-5.9.0.jar b/lib/junit-jupiter-engine-5.9.0.jar new file mode 100644 index 0000000..3a116cd Binary files /dev/null and b/lib/junit-jupiter-engine-5.9.0.jar differ diff --git a/lib/junit-jupiter-params-5.9.0.jar b/lib/junit-jupiter-params-5.9.0.jar new file mode 100644 index 0000000..ead9506 Binary files /dev/null and b/lib/junit-jupiter-params-5.9.0.jar differ diff --git a/lib/junit-platform-commons-1.9.0.jar b/lib/junit-platform-commons-1.9.0.jar new file mode 100644 index 0000000..5b7a2da Binary files /dev/null and b/lib/junit-platform-commons-1.9.0.jar differ diff --git a/lib/junit-platform-engine-1.9.0.jar b/lib/junit-platform-engine-1.9.0.jar new file mode 100644 index 0000000..5b29d89 Binary files /dev/null and b/lib/junit-platform-engine-1.9.0.jar differ diff --git a/lib/opentest4j-1.2.0.jar b/lib/opentest4j-1.2.0.jar new file mode 100644 index 0000000..d500636 Binary files /dev/null and b/lib/opentest4j-1.2.0.jar differ diff --git a/src/main/java/at/nanopenguin/mtcg/http/Router.java b/src/main/java/at/nanopenguin/mtcg/http/Router.java index d47cb35..b09daeb 100644 --- a/src/main/java/at/nanopenguin/mtcg/http/Router.java +++ b/src/main/java/at/nanopenguin/mtcg/http/Router.java @@ -1,6 +1,7 @@ package at.nanopenguin.mtcg.http; import at.nanopenguin.mtcg.application.service.Service; +import lombok.NonNull; import java.util.*; import java.util.stream.IntStream; @@ -8,11 +9,14 @@ import java.util.stream.IntStream; public class Router { private final Map> routeMap = new HashMap<>(); - public void addRoute(final HttpMethod method, final String route, final Service service, final int[] pathVars) { - Map map = this.routeMap.get(method); - if (method != null && map == null) { - this.routeMap.put(method, (map = new HashMap<>())); + public Router() { + for (HttpMethod httpMethod : HttpMethod.values()) { + this.routeMap.put(httpMethod, new HashMap<>()); } + } + + public void addRoute(@NonNull final HttpMethod method, final String route, final Service service, final int[] pathVars) { + Map map = this.routeMap.get(method); List routeComponents = new ArrayList<>(Arrays.asList(route.split("/"))); for ( Integer pathVarPos : pathVars) { diff --git a/src/test/java/at/nanopenguin/mtcg/http/RouterTest.java b/src/test/java/at/nanopenguin/mtcg/http/RouterTest.java new file mode 100644 index 0000000..d7ae726 --- /dev/null +++ b/src/test/java/at/nanopenguin/mtcg/http/RouterTest.java @@ -0,0 +1,162 @@ +package at.nanopenguin.mtcg.http; + +import at.nanopenguin.mtcg.application.service.Service; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +public class RouterTest { + private static Router router; + @BeforeEach + void setup() { + router = new Router(); + } + + @Test + void simpleRoute() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get", mockedService, new int[]{}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get"); + Assertions.assertNotNull(result); + result.handleRequest(null); + Mockito.verify(mockedService, Mockito.times(1)).handleRequest(null); + } + + @Test + void wrongPath() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get", mockedService, new int[]{}); + + Assertions.assertNull(router.resolveRoute(HttpMethod.GET, "/different")); + } + + @Test + void wrongMethod() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get", mockedService, new int[]{}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get"); + Assertions.assertNotNull(result); + result.handleRequest(null); + + Assertions.assertNull(router.resolveRoute(HttpMethod.POST, "/get")); + Assertions.assertNull(router.resolveRoute(HttpMethod.PUT, "/get")); + Assertions.assertNull(router.resolveRoute(HttpMethod.DELETE, "/get")); + } + + @Test + void differentHttpExists() throws SQLException, JsonProcessingException { + Service mockedServiceGet = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get", mockedServiceGet, new int[]{}); + + Service mockedServicePost = Mockito.mock(Service.class); + router.addRoute(HttpMethod.POST, "/get", mockedServicePost, new int[]{}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get"); + Assertions.assertNotNull(result); + result.handleRequest(null); + Mockito.verify(mockedServiceGet, Mockito.times(1)).handleRequest(null); + Mockito.verify(mockedServicePost, Mockito.times(0)).handleRequest(null); + } + + @Test + void longerPathExists() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get", mockedService, new int[]{}); + + Service mockedServiceLong = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get/long", mockedServiceLong, new int[]{}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get"); + Assertions.assertNotNull(result); + result.handleRequest(null); + Mockito.verify(mockedService, Mockito.times(1)).handleRequest(null); + Mockito.verify(mockedServiceLong, Mockito.times(0)).handleRequest(null); + } + + @Test + void shorterPathExists() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get/path", mockedService, new int[]{}); + + Service mockedServiceShort = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get", mockedServiceShort, new int[]{}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get/path"); + Assertions.assertNotNull(result); + result.handleRequest(null); + Mockito.verify(mockedService, Mockito.times(1)).handleRequest(null); + Mockito.verify(mockedServiceShort, Mockito.times(0)).handleRequest(null); + } + + @Test + void pathWithVar() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get/{var}", mockedService, new int[]{2}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get/value"); + Assertions.assertNotNull(result); + result.handleRequest(null); + Mockito.verify(mockedService, Mockito.times(1)).handleRequest(null); + } + + @Test + void longerPathWithVarExists() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get", mockedService, new int[]{}); + + Service mockedServiceVar = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get/{var}", mockedServiceVar, new int[]{2}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get"); + Assertions.assertNotNull(result); + result.handleRequest(null); + Mockito.verify(mockedService, Mockito.times(1)).handleRequest(null); + Mockito.verify(mockedServiceVar, Mockito.times(0)).handleRequest(null); + } + + @Test + void pathBeforeVarIsValid() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get/{var}", mockedService, new int[]{2}); + + Service mockedServiceNoVar = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get", mockedServiceNoVar, new int[]{}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get/value"); + Assertions.assertNotNull(result); + result.handleRequest(null); + Mockito.verify(mockedService, Mockito.times(1)).handleRequest(null); + Mockito.verify(mockedServiceNoVar, Mockito.times(0)).handleRequest(null); + } + + @Test + void pathContinuesAfterVar() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get/{var}/path", mockedService, new int[]{2}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get/value/path"); + Assertions.assertNotNull(result); + result.handleRequest(null); + Mockito.verify(mockedService, Mockito.times(1)).handleRequest(null); + } + + @Test + void pathWithTwoVars() throws SQLException, JsonProcessingException { + Service mockedService = Mockito.mock(Service.class); + router.addRoute(HttpMethod.GET, "/get/{var}/path/{var}", mockedService, new int[]{2, 4}); + + Service result = router.resolveRoute(HttpMethod.GET, "/get/value/path/other_value"); + Assertions.assertNotNull(result); + result.handleRequest(null); + Mockito.verify(mockedService, Mockito.times(1)).handleRequest(null); + } +}