You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2024/06/25 11:51:05 UTC
(tomcat) 01/02: Increase test coverage of WsServerContainer
This is an automated email from the ASF dual-hosted git repository.
remm pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 245710c973e639e4bc232e0c98a584436db0d69c
Author: Dimitris Soumis <ji...@gmail.com>
AuthorDate: Sun Jun 23 03:00:09 2024 +0300
Increase test coverage of WsServerContainer
---
.../catalina/filters/TesterHttpServletRequest.java | 63 ++++-
.../websocket/server/TestWsServerContainer.java | 307 ++++++++++++++++++++-
2 files changed, 346 insertions(+), 24 deletions(-)
diff --git a/test/org/apache/catalina/filters/TesterHttpServletRequest.java b/test/org/apache/catalina/filters/TesterHttpServletRequest.java
index 449963e6ec..2f24746cfa 100644
--- a/test/org/apache/catalina/filters/TesterHttpServletRequest.java
+++ b/test/org/apache/catalina/filters/TesterHttpServletRequest.java
@@ -19,6 +19,7 @@ package org.apache.catalina.filters;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
@@ -49,8 +50,8 @@ import jakarta.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;
@@ -111,9 +112,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
@@ -184,9 +190,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
@@ -247,7 +258,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
@@ -289,9 +300,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
@@ -304,9 +320,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
@@ -314,9 +335,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
@@ -329,9 +355,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
@@ -425,10 +456,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 8bc0094131..24bae4bd7a 100644
--- a/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java
+++ b/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java
@@ -16,30 +16,36 @@
*/
package org.apache.tomcat.websocket.server;
-import java.net.URI;
-import java.util.Queue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import jakarta.websocket.ContainerProvider;
-import jakarta.websocket.DeploymentException;
-import jakarta.websocket.Session;
-import jakarta.websocket.WebSocketContainer;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterRegistration;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import jakarta.websocket.server.ServerEndpointConfig;
-
-import org.junit.Assert;
-import org.junit.Test;
-
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleState;
+import org.apache.catalina.filters.TesterHttpServletRequest;
+import org.apache.catalina.filters.TesterHttpServletResponse;
import org.apache.catalina.servlets.DefaultServlet;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.unittest.TesterServletContext;
+import org.apache.tomcat.websocket.Constants;
import org.apache.tomcat.websocket.TesterEchoServer;
import org.apache.tomcat.websocket.TesterMessageCountClient.BasicText;
import org.apache.tomcat.websocket.WebSocketBaseTest;
import org.apache.tomcat.websocket.pojo.TesterUtil.SimpleClient;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public class TestWsServerContainer extends WebSocketBaseTest {
@@ -135,6 +141,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 +290,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 +385,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 +432,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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org