This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 7681964ea893fbd4f5a516fe1686968151c49ed2 Author: Dimitris Soumis <jimsou...@gmail.com> AuthorDate: Sun Jun 23 03:00:09 2024 +0300 Increase test coverage of WsServerContainer --- .../catalina/filters/TesterHttpServletRequest.java | 62 ++++- .../websocket/server/TestWsServerContainer.java | 275 +++++++++++++++++++++ 2 files changed, 326 insertions(+), 11 deletions(-) diff --git a/test/org/apache/catalina/filters/TesterHttpServletRequest.java b/test/org/apache/catalina/filters/TesterHttpServletRequest.java index bf196118b3..288e754030 100644 --- a/test/org/apache/catalina/filters/TesterHttpServletRequest.java +++ b/test/org/apache/catalina/filters/TesterHttpServletRequest.java @@ -48,8 +48,8 @@ import javax.servlet.http.PushBuilder; public class TesterHttpServletRequest implements HttpServletRequest { - private Map<String, Object> attributes = new HashMap<>(); - private Map<String, List<String>> headers = new HashMap<>(); + private final Map<String, Object> attributes = new HashMap<>(); + private final Map<String, List<String>> headers = new HashMap<>(); private String method; private String scheme; private String serverName; @@ -110,9 +110,14 @@ public class TesterHttpServletRequest implements HttpServletRequest { throw new RuntimeException("Not implemented"); } + /** + * {@inheritDoc} + * <p> + * This test implementation is hard coded to return an empty Hashmap. + */ @Override public Map<String, String[]> getParameterMap() { - throw new RuntimeException("Not implemented"); + return new HashMap<>(); } @Override @@ -183,9 +188,14 @@ public class TesterHttpServletRequest implements HttpServletRequest { throw new RuntimeException("Not implemented"); } + /** + * {@inheritDoc} + * <p> + * This test implementation is hard coded to return false. + */ @Override public boolean isSecure() { - throw new RuntimeException("Not implemented"); + return false; } @Override @@ -251,7 +261,7 @@ public class TesterHttpServletRequest implements HttpServletRequest { @Override public Enumeration<String> getHeaders(String name) { - throw new RuntimeException("Not implemented"); + return Collections.enumeration(headers.get(name)); } @Override @@ -293,9 +303,14 @@ public class TesterHttpServletRequest implements HttpServletRequest { throw new RuntimeException("Not implemented"); } + /** + * {@inheritDoc} + * <p> + * This test implementation is hard coded to return null. + */ @Override public String getQueryString() { - throw new RuntimeException("Not implemented"); + return null; } @Override @@ -308,9 +323,14 @@ public class TesterHttpServletRequest implements HttpServletRequest { throw new RuntimeException("Not implemented"); } + /** + * {@inheritDoc} + * <p> + * This test implementation is hard coded to return null. + */ @Override public Principal getUserPrincipal() { - throw new RuntimeException("Not implemented"); + return null; } @Override @@ -318,9 +338,14 @@ public class TesterHttpServletRequest implements HttpServletRequest { throw new RuntimeException("Not implemented"); } + /** + * {@inheritDoc} + * <p> + * This test implementation is hard coded to return null. + */ @Override public String getRequestURI() { - throw new RuntimeException("Not implemented"); + return null; } @Override @@ -333,9 +358,14 @@ public class TesterHttpServletRequest implements HttpServletRequest { throw new RuntimeException("Not implemented"); } + /** + * {@inheritDoc} + * <p> + * This test implementation is hard coded to return null. + */ @Override public HttpSession getSession(boolean create) { - throw new RuntimeException("Not implemented"); + return null; } @Override @@ -434,10 +464,20 @@ public class TesterHttpServletRequest implements HttpServletRequest { throw new RuntimeException("Not implemented"); } + /** + * {@inheritDoc} + * <p> + * This test implementation is hard coded to return a new instance of the httpUpgradeHandlerClass. + */ @Override public <T extends HttpUpgradeHandler> T upgrade(Class<T> httpUpgradeHandlerClass) - throws IOException, ServletException { - throw new RuntimeException("Not implemented"); + throws IOException, ServletException { + try { + return httpUpgradeHandlerClass.getDeclaredConstructor().newInstance(); + }catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ignore){ + + } + return null; } @Override diff --git a/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java b/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java index 67f0c3b5f2..db6a24e6ee 100644 --- a/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java +++ b/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java @@ -135,6 +135,46 @@ public class TestWsServerContainer extends WebSocketBaseTest { Assert.assertEquals(configB, sc.findMapping("/b/d").getConfig()); } + @Test + public void testSpecExample5() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/a").build(); + + sc.addEndpoint(configA); + + Assert.assertNull(sc.findMapping("invalidPath")); + } + + @Test + public void testSpecExample6() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/a").build(); + + sc.addEndpoint(configA); + + Assert.assertNull(sc.findMapping("/b")); + } + + @Test + public void testSpecExample7() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + // Use reflection to set the configTemplateMatchMap field to have a key "2" with value an empty ConcurrentSkipListMap + Field configTemplateMatchMapField = WsServerContainer.class.getDeclaredField("configTemplateMatchMap"); + configTemplateMatchMapField.setAccessible(true); + @SuppressWarnings("unchecked") + Map<Integer, ConcurrentSkipListMap<String, Object>> configTemplateMatchMap = + (Map<Integer, ConcurrentSkipListMap<String, Object>>) configTemplateMatchMapField.get(sc); + + ConcurrentSkipListMap<String, Object> newSkipListMap = new ConcurrentSkipListMap<>(); + + configTemplateMatchMap.put(Integer.valueOf(2), newSkipListMap); + + Assert.assertNull(sc.findMapping("/a/0")); + } + @Test(expected = DeploymentException.class) public void testDuplicatePaths01() throws Exception { @@ -244,6 +284,43 @@ public class TestWsServerContainer extends WebSocketBaseTest { sc.addEndpoint(configA); } + @Test(expected = DeploymentException.class) + public void testDuplicatePaths15() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/foo").build(); + + sc.addEndpoint(configA); + sc.addEndpoint(Pojo.class, true); + } + + @Test(expected = DeploymentException.class) + public void testDuplicatePaths16() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/foo").build(); + + sc.addEndpoint(configA); + sc.addEndpoint(Pojo.class, false); + } + + @Test(expected = DeploymentException.class) + public void testDuplicatePaths17() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + sc.addEndpoint(Pojo.class, true); + sc.addEndpoint(Pojo.class, true); + } + + @Test(expected = DeploymentException.class) + public void testDuplicatePaths18() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/foo").build(); + + sc.addEndpoint(Pojo.class, true); + sc.addEndpoint(configA, true); + } /* * Simulates a class that gets picked up for extending Endpoint and for being annotated. @@ -302,6 +379,43 @@ public class TestWsServerContainer extends WebSocketBaseTest { sc.addEndpoint(configA); } + @Test(expected = DeploymentException.class) + public void testDuplicatePaths25() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/foo/{a}").build(); + + sc.addEndpoint(configA); + sc.addEndpoint(PojoTemplate.class, true); + } + + @Test(expected = DeploymentException.class) + public void testDuplicatePaths26() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/foo/{a}").build(); + + sc.addEndpoint(configA); + sc.addEndpoint(PojoTemplate.class, false); + } + + @Test(expected = DeploymentException.class) + public void testDuplicatePaths27() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + sc.addEndpoint(PojoTemplate.class, true); + sc.addEndpoint(PojoTemplate.class, true); + } + + @Test(expected = DeploymentException.class) + public void testDuplicatePaths28() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/foo/{a}").build(); + + sc.addEndpoint(PojoTemplate.class, true); + sc.addEndpoint(configA, true); + } @ServerEndpoint("/foo") public static class Pojo { @@ -312,4 +426,165 @@ public class TestWsServerContainer extends WebSocketBaseTest { public static class PojoTemplate { } + @Test + public void testUpgradeHttpToWebSocket01() throws Exception { + TesterHttpServletRequest request = new TesterHttpServletRequest(); + + request.setScheme("http"); + + request.setHeader(Constants.CONNECTION_HEADER_NAME, Constants.CONNECTION_HEADER_VALUE); + request.setHeader(Constants.WS_VERSION_HEADER_NAME, Constants.WS_VERSION_HEADER_VALUE); + //Random 16-byte value encoded in 24 base64 characters. + request.setHeader(Constants.WS_KEY_HEADER_NAME, "1b4pqvztbM4cor6UUZSDqw=="); + request.setHeader(Constants.WS_PROTOCOL_HEADER_NAME, "testProtocol"); + request.setHeader(Constants.WS_EXTENSIONS_HEADER_NAME, "testExtension"); + + HttpServletResponse response = new TesterHttpServletResponse(); + + ServerEndpointConfig sec = ServerEndpointConfig.Builder.create(Object.class, "/").subprotocols(List.of("testProtocol")).build(); + + WsServerContainer container = new WsServerContainer(new TesterServletContext()); + + container.upgradeHttpToWebSocket(request, response, sec, new HashMap<>()); + + Assert.assertEquals(Constants.UPGRADE_HEADER_VALUE, response.getHeader(Constants.UPGRADE_HEADER_NAME)); + Assert.assertEquals("aJvXj0bbnSSeXm32ngvbBilP0lE=", response.getHeader(HandshakeResponse.SEC_WEBSOCKET_ACCEPT)); + } + + @Test(expected = DeploymentException.class) + public void testUpgradeHttpToWebSocket02() throws Exception { + TesterHttpServletRequest request = new TesterHttpServletRequest(); + + request.setHeader(Constants.CONNECTION_HEADER_NAME, Constants.CONNECTION_HEADER_VALUE); + request.setHeader(Constants.WS_VERSION_HEADER_NAME, Constants.WS_VERSION_HEADER_VALUE); + //Random 16-byte value encoded in 24 base64 characters. + request.setHeader(Constants.WS_KEY_HEADER_NAME, "1b4pqvztbM4cor6UUZSDqw=="); + request.setHeader(Constants.WS_PROTOCOL_HEADER_NAME, "testProtocol"); + request.setHeader(Constants.WS_EXTENSIONS_HEADER_NAME, "testExtension"); + + HttpServletResponse response = new TesterHttpServletResponse(); + + ServerEndpointConfig sec = ServerEndpointConfig.Builder.create(Object.class, "/").decoders(List.of(DummyDecoder.class)).build(); + + WsServerContainer container = new WsServerContainer(new TesterServletContext()); + + container.upgradeHttpToWebSocket(request, response, sec, new HashMap<>()); + } + + private static class DummyDecoder implements Decoder { + public DummyDecoder(String ignoredParam) { + } + } + + @Test + public void testFilterRegistrationFailure() { + new WsServerContainer(new TesterServletContext(){ + @Override + public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) { + return null; + } + }); + + } + + @Test(expected = DeploymentException.class) + public void testAddEndpointNullServletContext() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/").build(); + + // Use reflection to set the servletContext field to null + Field servletContextField = WsServerContainer.class.getDeclaredField("servletContext"); + servletContextField.setAccessible(true); + servletContextField.set(sc, null); + + sc.addEndpoint(configA); + } + + @Test(expected = DeploymentException.class) + public void testAddEndpointDeploymentFailed01() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + ServerEndpointConfig configA = ServerEndpointConfig.Builder.create(Object.class, "/a/b/c").build(); + ServerEndpointConfig configB = ServerEndpointConfig.Builder.create(Object.class, "/a/b/c").build(); + + try { + sc.addEndpoint(configA); + sc.addEndpoint(configB); + }catch (DeploymentException ignore){ + sc.addEndpoint(configB); + } + + } + + @Test(expected = DeploymentException.class) + public void testAddEndpointDeploymentFailed02() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + try { + sc.addEndpoint(Pojo.class, true); + sc.addEndpoint(Pojo.class, true); + }catch (DeploymentException ignore){ + sc.addEndpoint(Pojo.class, true); + } + + } + + @Test(expected = DeploymentException.class) + public void testAddEndpointMissingAnnotationFromPojoClass() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + sc.addEndpoint(DummyPojo.class, true); + + } + + public static class DummyPojo { + } + + @Test(expected = DeploymentException.class) + public void testAddEndpointConfiguratorFail() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + sc.addEndpoint(DummyPojo2.class, true); + + } + + @ServerEndpoint(value = "/foo", configurator = DummyConfigurator.class) + public static class DummyPojo2 { + } + + private static class DummyConfigurator extends ServerEndpointConfig.Configurator { + public DummyConfigurator(String ignoredParam) { + } + + } + @Test + public void testValidateEncoders01() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + sc.addEndpoint(DummyPojo3.class); + + } + + @ServerEndpoint(value = "/foo", encoders = DummyEncoder.class) + public static class DummyPojo3 { + } + + private static class DummyEncoder implements Encoder { + public DummyEncoder() { + } + } + + @Test(expected = DeploymentException.class) + public void testValidateEncoders02() throws Exception { + WsServerContainer sc = new WsServerContainer(new TesterServletContext()); + + sc.addEndpoint(DummyPojo4.class); + + } + + @ServerEndpoint(value = "/foo", encoders = Encoder.class) + public static class DummyPojo4 { + } + } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org