summaryrefslogtreecommitdiffstats
path: root/container-core/src/test/java
diff options
context:
space:
mode:
authorJon Marius Venstad <jonmv@users.noreply.github.com>2021-12-03 08:11:22 +0100
committerGitHub <noreply@github.com>2021-12-03 08:11:22 +0100
commit258c5987675c7b757c8c574a59e1793d1f68ea72 (patch)
tree8bd0929c62fbd2cf4ad761101ffb5df6bcce79fa /container-core/src/test/java
parent6e2ddaa1b917dadfda06f882a08c69a3c6b56558 (diff)
Revert "Remove Servlet integration from container-core [run-systemtest]"
Diffstat (limited to 'container-core/src/test/java')
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/filter/ServletFilterRequestTest.java173
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/filter/ServletFilterResponseTest.java87
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/JDiscFilterForServletTest.java165
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/ServletAccessLoggingTest.java63
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/ServletTestBase.java132
5 files changed, 620 insertions, 0 deletions
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/filter/ServletFilterRequestTest.java b/container-core/src/test/java/com/yahoo/jdisc/http/filter/ServletFilterRequestTest.java
new file mode 100644
index 00000000000..dfd240d3723
--- /dev/null
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/filter/ServletFilterRequestTest.java
@@ -0,0 +1,173 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.http.filter;
+
+import com.yahoo.jdisc.http.Cookie;
+import com.yahoo.jdisc.http.HttpHeaders;
+import com.yahoo.jdisc.http.server.jetty.JettyMockRequestBuilder;
+import com.yahoo.jdisc.http.servlet.ServletRequest;
+import org.eclipse.jetty.server.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static com.yahoo.jdisc.http.HttpRequest.Version;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test the parts of the DiscFilterRequest API that are implemented
+ * by ServletFilterRequest, both directly and indirectly via
+ * {@link com.yahoo.jdisc.http.servlet.ServletRequest}.
+ *
+ * @author gjoranv
+ */
+public class ServletFilterRequestTest {
+
+ private final String host = "host1";
+ private final int port = 8080;
+ private final String path = "/path1";
+ private final String paramName = "param1";
+ private final String paramValue = "p1";
+ private final String listParamName = "listParam";
+ private final String[] listParamValue = new String[]{"1", "2"};
+ private final String headerName = "header1";
+ private final String headerValue = "h1";
+ private final String attributeName = "attribute1";
+ private final String attributeValue = "a1";
+
+ private URI uri;
+ private DiscFilterRequest filterRequest;
+ private ServletRequest parentRequest;
+
+ @Before
+ public void init() throws Exception {
+ uri = new URI("http", null, host, port, path, paramName + "=" + paramValue, null);
+
+ filterRequest = new ServletFilterRequest(newServletRequest());
+ parentRequest = ((ServletFilterRequest)filterRequest).getServletRequest();
+ }
+
+ private ServletRequest newServletRequest() {
+ Request parent = JettyMockRequestBuilder.newBuilder()
+ .remote("1.2.3.4", host, port)
+ .header(headerName, List.of(headerValue))
+ .parameter(paramName, List.of(paramValue))
+ .parameter(listParamName, List.of(listParamValue))
+ .attribute(attributeName, attributeValue)
+ .build();
+ return new ServletRequest(parent, uri);
+ }
+
+ @Test
+ public void parent_properties_are_propagated_to_disc_filter_request() throws Exception {
+ assertEquals(filterRequest.getVersion(), Version.HTTP_1_1);
+ assertEquals(filterRequest.getMethod(), "GET");
+ assertEquals(filterRequest.getUri(), uri);
+ assertEquals(filterRequest.getRemoteHost(), host);
+ assertEquals(filterRequest.getRemotePort(), port);
+ assertEquals(filterRequest.getRequestURI(), path); // getRequestUri return only the path by design
+
+ assertEquals(filterRequest.getParameter(paramName), paramValue);
+ assertEquals(filterRequest.getParameterMap().get(paramName),
+ Collections.singletonList(paramValue));
+ assertEquals(filterRequest.getParameterValuesAsList(listParamName), Arrays.asList(listParamValue));
+
+ assertEquals(filterRequest.getHeader(headerName), headerValue);
+ assertEquals(filterRequest.getAttribute(attributeName), attributeValue);
+ }
+
+ @Test
+ public void untreatedHeaders_is_populated_from_the_parent_request() {
+ assertEquals(filterRequest.getUntreatedHeaders().getFirst(headerName), headerValue);
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void uri_can_be_set() throws Exception {
+ URI newUri = new URI("http", null, host, port + 1, path, paramName + "=" + paramValue, null);
+ filterRequest.setUri(newUri);
+
+ assertEquals(filterRequest.getUri(), newUri);
+ assertEquals(parentRequest.getUri(), newUri);
+ }
+
+ @Test
+ public void attributes_can_be_set() throws Exception {
+ String name = "newAttribute";
+ String value = name + "Value";
+ filterRequest.setAttribute(name, value);
+
+ assertEquals(filterRequest.getAttribute(name), value);
+ assertEquals(parentRequest.getAttribute(name), value);
+ }
+
+ @Test
+ public void attributes_can_be_removed() {
+ filterRequest.removeAttribute(attributeName);
+
+ assertEquals(filterRequest.getAttribute(attributeName), null);
+ assertEquals(parentRequest.getAttribute(attributeName), null);
+ }
+
+ @Test
+ public void headers_can_be_set() throws Exception {
+ String name = "myHeader";
+ String value = name + "Value";
+ filterRequest.setHeaders(name, value);
+
+ assertEquals(filterRequest.getHeader(name), value);
+ assertEquals(parentRequest.getHeader(name), value);
+ }
+
+ @Test
+ public void headers_can_be_removed() throws Exception {
+ filterRequest.removeHeaders(headerName);
+
+ assertEquals(filterRequest.getHeader(headerName), null);
+ assertEquals(parentRequest.getHeader(headerName), null);
+ }
+
+ @Test
+ public void headers_can_be_added() {
+ String value = "h2";
+ filterRequest.addHeader(headerName, value);
+
+ List<String> expected = Arrays.asList(headerValue, value);
+ assertEquals(filterRequest.getHeadersAsList(headerName), expected);
+ assertEquals(Collections.list(parentRequest.getHeaders(headerName)), expected);
+ }
+
+ @Test
+ public void cookies_can_be_added_and_removed() {
+ Cookie cookie = new Cookie("name", "value");
+ filterRequest.addCookie(JDiscCookieWrapper.wrap(cookie));
+
+ assertEquals(filterRequest.getCookies(), Collections.singletonList(cookie));
+ assertEquals(parentRequest.getCookies().length, 1);
+
+ javax.servlet.http.Cookie servletCookie = parentRequest.getCookies()[0];
+ assertEquals(servletCookie.getName(), cookie.getName());
+ assertEquals(servletCookie.getValue(), cookie.getValue());
+
+ filterRequest.clearCookies();
+ assertTrue(filterRequest.getCookies().isEmpty());
+ assertEquals(parentRequest.getCookies().length, 0);
+ }
+
+ @Test
+ public void character_encoding_can_be_set() throws Exception {
+ // ContentType must be non-null before setting character encoding
+ filterRequest.setHeaders(HttpHeaders.Names.CONTENT_TYPE, "");
+
+ String encoding = "myEncoding";
+ filterRequest.setCharacterEncoding(encoding);
+
+ assertTrue(filterRequest.getCharacterEncoding().contains(encoding));
+ assertTrue(parentRequest.getCharacterEncoding().contains(encoding));
+ }
+
+}
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/filter/ServletFilterResponseTest.java b/container-core/src/test/java/com/yahoo/jdisc/http/filter/ServletFilterResponseTest.java
new file mode 100644
index 00000000000..1b49ad7ddd1
--- /dev/null
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/filter/ServletFilterResponseTest.java
@@ -0,0 +1,87 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.http.filter;
+
+import com.yahoo.jdisc.http.Cookie;
+import com.yahoo.jdisc.http.HttpHeaders;
+import com.yahoo.jdisc.http.servlet.ServletResponse;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author gjoranv
+ * @since 5.27
+ */
+public class ServletFilterResponseTest {
+
+ private final String headerName = "header1";
+ private final String headerValue = "h1";
+
+ private DiscFilterResponse filterResponse;
+ private ServletResponse parentResponse;
+
+ @Before
+ public void init() throws Exception {
+ filterResponse = new ServletFilterResponse(newServletResponse());
+ parentResponse = ((ServletFilterResponse)filterResponse).getServletResponse();
+
+ }
+
+ private ServletResponse newServletResponse() throws Exception {
+ MockServletResponse parent = new MockServletResponse();
+ parent.addHeader(headerName, headerValue);
+ return new ServletResponse(parent);
+ }
+
+
+ @Test
+ public void headers_can_be_set() throws Exception {
+ String name = "myHeader";
+ String value = name + "Value";
+ filterResponse.setHeaders(name, value);
+
+ assertEquals(filterResponse.getHeader(name), value);
+ assertEquals(parentResponse.getHeader(name), value);
+ }
+
+ @Test
+ public void headers_can_be_added() throws Exception {
+ String newValue = "h2";
+ filterResponse.addHeader(headerName, newValue);
+
+ // The DiscFilterResponse has no getHeaders()
+ assertEquals(filterResponse.getHeader(headerName), newValue);
+
+ assertEquals(parentResponse.getHeaders(headerName), Arrays.asList(headerValue, newValue));
+ }
+
+ @Test
+ public void headers_can_be_removed() throws Exception {
+ filterResponse.removeHeaders(headerName);
+
+ assertEquals(filterResponse.getHeader(headerName), null);
+ assertEquals(parentResponse.getHeader(headerName), null);
+ }
+
+ @Test
+ public void set_cookie_overwrites_old_values() {
+ Cookie to_be_removed = new Cookie("to-be-removed", "");
+ Cookie to_keep = new Cookie("to-keep", "");
+ filterResponse.setCookie(to_be_removed.getName(), to_be_removed.getValue());
+ filterResponse.setCookie(to_keep.getName(), to_keep.getValue());
+
+ assertEquals(filterResponse.getCookies(), Arrays.asList(to_keep));
+ assertEquals(parentResponse.getHeaders(HttpHeaders.Names.SET_COOKIE), Arrays.asList(to_keep.toString()));
+ }
+
+
+ private static class MockServletResponse extends org.eclipse.jetty.server.Response {
+ private MockServletResponse() {
+ super(null, null);
+ }
+ }
+
+}
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/JDiscFilterForServletTest.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/JDiscFilterForServletTest.java
new file mode 100644
index 00000000000..c6d416b2b99
--- /dev/null
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/JDiscFilterForServletTest.java
@@ -0,0 +1,165 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.http.server.jetty.servlet;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
+import com.yahoo.jdisc.AbstractResource;
+import com.yahoo.jdisc.Request;
+import com.yahoo.jdisc.Response;
+import com.yahoo.jdisc.handler.ContentChannel;
+import com.yahoo.jdisc.handler.ResponseHandler;
+import com.yahoo.jdisc.http.HttpRequest;
+import com.yahoo.jdisc.http.filter.RequestFilter;
+import com.yahoo.jdisc.http.filter.ResponseFilter;
+import com.yahoo.jdisc.http.server.jetty.FilterBindings;
+import com.yahoo.jdisc.http.server.jetty.FilterInvoker;
+import com.yahoo.jdisc.http.server.jetty.SimpleHttpClient.ResponseValidator;
+import com.yahoo.jdisc.http.server.jetty.JettyTestDriver;
+import org.junit.Test;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+
+/**
+ * @author Tony Vaagenes
+ * @author bjorncs
+ */
+public class JDiscFilterForServletTest extends ServletTestBase {
+ @Test
+ public void request_filter_can_return_response() throws IOException, InterruptedException {
+ JettyTestDriver testDriver = requestFilterTestDriver();
+ ResponseValidator response = httpGet(testDriver, TestServlet.PATH).execute();
+
+ response.expectContent(containsString(TestRequestFilter.responseContent));
+ }
+
+ @Test
+ public void request_can_be_forwarded_through_request_filter_to_servlet() throws IOException {
+ JettyTestDriver testDriver = requestFilterTestDriver();
+ ResponseValidator response = httpGet(testDriver, TestServlet.PATH).
+ addHeader(TestRequestFilter.BYPASS_FILTER_HEADER, Boolean.TRUE.toString()).
+ execute();
+
+ response.expectContent(containsString(TestServlet.RESPONSE_CONTENT));
+ }
+
+ @Test
+ public void response_filter_can_modify_response() throws IOException {
+ JettyTestDriver testDriver = responseFilterTestDriver();
+ ResponseValidator response = httpGet(testDriver, TestServlet.PATH).execute();
+
+ response.expectHeader(TestResponseFilter.INVOKED_HEADER, is(Boolean.TRUE.toString()));
+ }
+
+ @Test
+ public void response_filter_is_run_on_empty_sync_response() throws IOException {
+ JettyTestDriver testDriver = responseFilterTestDriver();
+ ResponseValidator response = httpGet(testDriver, NoContentTestServlet.PATH).execute();
+
+ response.expectHeader(TestResponseFilter.INVOKED_HEADER, is(Boolean.TRUE.toString()));
+ }
+
+ @Test
+ public void response_filter_is_run_on_empty_async_response() throws IOException {
+ JettyTestDriver testDriver = responseFilterTestDriver();
+ ResponseValidator response = httpGet(testDriver, NoContentTestServlet.PATH).
+ addHeader(NoContentTestServlet.HEADER_ASYNC, Boolean.TRUE.toString()).
+ execute();
+
+ response.expectHeader(TestResponseFilter.INVOKED_HEADER, is(Boolean.TRUE.toString()));
+ }
+
+ private JettyTestDriver requestFilterTestDriver() throws IOException {
+ FilterBindings filterBindings = new FilterBindings.Builder()
+ .addRequestFilter("my-request-filter", new TestRequestFilter())
+ .addRequestFilterBinding("my-request-filter", "http://*/*")
+ .build();
+ return JettyTestDriver.newInstance(dummyRequestHandler, bindings(filterBindings));
+ }
+
+ private JettyTestDriver responseFilterTestDriver() throws IOException {
+ FilterBindings filterBindings = new FilterBindings.Builder()
+ .addResponseFilter("my-response-filter", new TestResponseFilter())
+ .addResponseFilterBinding("my-response-filter", "http://*/*")
+ .build();
+ return JettyTestDriver.newInstance(dummyRequestHandler, bindings(filterBindings));
+ }
+
+
+
+ private Module bindings(FilterBindings filterBindings) {
+ return Modules.combine(
+ new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(FilterBindings.class).toInstance(filterBindings);
+ bind(FilterInvoker.class).toInstance(new FilterInvoker() {
+ @Override
+ public HttpServletRequest invokeRequestFilterChain(
+ RequestFilter requestFilter,
+ URI uri,
+ HttpServletRequest httpRequest,
+ ResponseHandler responseHandler) {
+ TestRequestFilter filter = (TestRequestFilter) requestFilter;
+ filter.runAsSecurityFilter(httpRequest, responseHandler);
+ return httpRequest;
+ }
+
+ @Override
+ public void invokeResponseFilterChain(
+ ResponseFilter responseFilter,
+ URI uri,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ TestResponseFilter filter = (TestResponseFilter) responseFilter;
+ filter.runAsSecurityFilter(request, response);
+ }
+ });
+ }
+ },
+ guiceModule());
+ }
+
+ static class TestRequestFilter extends AbstractResource implements RequestFilter {
+ static final String simpleName = TestRequestFilter.class.getSimpleName();
+ static final String responseContent = "Rejected by " + simpleName;
+ static final String BYPASS_FILTER_HEADER = "BYPASS_HEADER" + simpleName;
+
+ @Override
+ public void filter(HttpRequest request, ResponseHandler handler) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void runAsSecurityFilter(HttpServletRequest request, ResponseHandler responseHandler) {
+ if (Boolean.parseBoolean(request.getHeader(BYPASS_FILTER_HEADER)))
+ return;
+
+ ContentChannel contentChannel = responseHandler.handleResponse(new Response(500));
+ contentChannel.write(ByteBuffer.wrap(responseContent.getBytes(StandardCharsets.UTF_8)), null);
+ contentChannel.close(null);
+ }
+ }
+
+
+ static class TestResponseFilter extends AbstractResource implements ResponseFilter {
+ static final String INVOKED_HEADER = TestResponseFilter.class.getSimpleName() + "_INVOKED_HEADER";
+
+ @Override
+ public void filter(Response response, Request request) {
+ throw new UnsupportedClassVersionError();
+ }
+
+ public void runAsSecurityFilter(HttpServletRequest request, HttpServletResponse response) {
+ response.addHeader(INVOKED_HEADER, Boolean.TRUE.toString());
+ }
+ }
+}
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/ServletAccessLoggingTest.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/ServletAccessLoggingTest.java
new file mode 100644
index 00000000000..17802b7f466
--- /dev/null
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/ServletAccessLoggingTest.java
@@ -0,0 +1,63 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.http.server.jetty.servlet;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
+import com.yahoo.container.logging.AccessLog;
+import com.yahoo.container.logging.RequestLog;
+import com.yahoo.container.logging.RequestLogEntry;
+import com.yahoo.jdisc.http.server.jetty.JettyTestDriver;
+import org.junit.Test;
+import org.mockito.verification.VerificationMode;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+/**
+ * @author bakksjo
+ * @author bjorncs
+ */
+public class ServletAccessLoggingTest extends ServletTestBase {
+ private static final long MAX_LOG_WAIT_TIME_MILLIS = TimeUnit.SECONDS.toMillis(60);
+
+ @Test
+ public void accessLogIsInvokedForNonJDiscServlet() throws Exception {
+ final AccessLog accessLog = mock(AccessLog.class);
+ final JettyTestDriver testDriver = newTestDriver(accessLog);
+ httpGet(testDriver, TestServlet.PATH).execute();
+ verifyCallsLog(accessLog, timeout(MAX_LOG_WAIT_TIME_MILLIS).times(1));
+ }
+
+ @Test
+ public void accessLogIsInvokedForJDiscServlet() throws Exception {
+ final AccessLog accessLog = mock(AccessLog.class);
+ final JettyTestDriver testDriver = newTestDriver(accessLog);
+ testDriver.client().newGet("/status.html").execute();
+ verifyCallsLog(accessLog, timeout(MAX_LOG_WAIT_TIME_MILLIS).times(1));
+ }
+
+ private void verifyCallsLog(RequestLog requestLog, final VerificationMode verificationMode) {
+ verify(requestLog, verificationMode).log(any(RequestLogEntry.class));
+ }
+
+ private JettyTestDriver newTestDriver(RequestLog requestLog) throws IOException {
+ return JettyTestDriver.newInstance(dummyRequestHandler, bindings(requestLog));
+ }
+
+ private Module bindings(RequestLog requestLog) {
+ return Modules.combine(
+ new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(RequestLog.class).toInstance(requestLog);
+ }
+ },
+ guiceModule());
+ }
+}
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/ServletTestBase.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/ServletTestBase.java
new file mode 100644
index 00000000000..f13769dec38
--- /dev/null
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/servlet/ServletTestBase.java
@@ -0,0 +1,132 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.http.server.jetty.servlet;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+import com.yahoo.component.ComponentId;
+import com.yahoo.component.provider.ComponentRegistry;
+import com.yahoo.jdisc.Request;
+import com.yahoo.jdisc.handler.AbstractRequestHandler;
+import com.yahoo.jdisc.handler.ContentChannel;
+import com.yahoo.jdisc.handler.RequestHandler;
+import com.yahoo.jdisc.handler.ResponseHandler;
+import com.yahoo.jdisc.http.ServletPathsConfig;
+import com.yahoo.jdisc.http.ServletPathsConfig.Servlets.Builder;
+import com.yahoo.jdisc.http.server.jetty.SimpleHttpClient.RequestExecutor;
+import com.yahoo.jdisc.http.server.jetty.JettyTestDriver;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * @author Tony Vaagenes
+ * @author bakksjo
+ */
+public class ServletTestBase {
+
+ private static class ServletInstance {
+ final ComponentId componentId; final String path; final HttpServlet instance;
+
+ ServletInstance(ComponentId componentId, String path, HttpServlet instance) {
+ this.componentId = componentId;
+ this.path = path;
+ this.instance = instance;
+ }
+ }
+
+ private final List<ServletInstance> servlets = List.of(
+ new ServletInstance(TestServlet.ID, TestServlet.PATH, new TestServlet()),
+ new ServletInstance(NoContentTestServlet.ID, NoContentTestServlet.PATH, new NoContentTestServlet()));
+
+ protected RequestExecutor httpGet(JettyTestDriver testDriver, String path) {
+ return testDriver.client().newGet("/" + path);
+ }
+
+ protected ServletPathsConfig createServletPathConfig() {
+ ServletPathsConfig.Builder configBuilder = new ServletPathsConfig.Builder();
+
+ servlets.forEach(servlet ->
+ configBuilder.servlets(
+ servlet.componentId.stringValue(),
+ new Builder().path(servlet.path)));
+
+ return new ServletPathsConfig(configBuilder);
+ }
+
+ protected ComponentRegistry<ServletHolder> servlets() {
+ ComponentRegistry<ServletHolder> result = new ComponentRegistry<>();
+
+ servlets.forEach(servlet ->
+ result.register(servlet.componentId, new ServletHolder(servlet.instance)));
+
+ result.freeze();
+ return result;
+ }
+
+ protected Module guiceModule() {
+ return new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(new TypeLiteral<ComponentRegistry<ServletHolder>>(){}).toInstance(servlets());
+ bind(ServletPathsConfig.class).toInstance(createServletPathConfig());
+ }
+ };
+ }
+
+ protected static class TestServlet extends HttpServlet {
+ static final String PATH = "servlet/test-servlet";
+ static final ComponentId ID = ComponentId.fromString("test-servlet");
+ static final String RESPONSE_CONTENT = "Response from " + TestServlet.class.getSimpleName();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ PrintWriter writer = response.getWriter();
+ writer.write(RESPONSE_CONTENT);
+ writer.close();
+ }
+ }
+
+ @WebServlet(asyncSupported = true)
+ protected static class NoContentTestServlet extends HttpServlet {
+ static final String HEADER_ASYNC = "HEADER_ASYNC";
+
+ static final String PATH = "servlet/no-content-test-servlet";
+ static final ComponentId ID = ComponentId.fromString("no-content-test-servlet");
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ if (request.getHeader(HEADER_ASYNC) != null) {
+ asyncGet(request);
+ }
+ }
+
+ private void asyncGet(HttpServletRequest request) {
+ request.startAsync().start(() -> {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ log("Interrupted", e);
+ } finally {
+ request.getAsyncContext().complete();
+ }
+ });
+ }
+ }
+
+
+ protected static final RequestHandler dummyRequestHandler = new AbstractRequestHandler() {
+ @Override
+ public ContentChannel handleRequest(Request request, ResponseHandler handler) {
+ throw new UnsupportedOperationException();
+ }
+ };
+}