Let Jetty pick its own available port

In an attempt to make our Jetty-based integration tests more robust,
this commit discontinues use of SocketUtils for picking a random,
available port and instead lets the Jetty Server pick its own port.
This commit is contained in:
Sam Brannen 2015-08-22 18:58:55 +02:00
parent 6085be3a71
commit 2df3646e90
5 changed files with 85 additions and 51 deletions

View File

@ -20,6 +20,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Map; import java.util.Map;
import javax.servlet.GenericServlet; import javax.servlet.GenericServlet;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
@ -28,31 +29,34 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass; import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.springframework.util.SocketUtils;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
import static org.junit.Assert.*;
/** /**
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Sam Brannen
*/ */
public abstract class AbstractJettyServerTestCase { public abstract class AbstractJettyServerTestCase {
protected static String baseUrl;
private static Server jettyServer; private static Server jettyServer;
protected static String baseUrl;
@BeforeClass @BeforeClass
public static void startJettyServer() throws Exception { public static void startJettyServer() throws Exception {
int port = SocketUtils.findAvailableTcpPort();
jettyServer = new Server(port); // Let server pick its own random, available port.
baseUrl = "http://localhost:" + port; jettyServer = new Server(0);
ServletContextHandler handler = new ServletContextHandler(); ServletContextHandler handler = new ServletContextHandler();
handler.setContextPath("/"); handler.setContextPath("/");
@ -71,6 +75,10 @@ public abstract class AbstractJettyServerTestCase {
jettyServer.setHandler(handler); jettyServer.setHandler(handler);
jettyServer.start(); jettyServer.start();
Connector[] connectors = jettyServer.getConnectors();
NetworkConnector connector = (NetworkConnector) connectors[0];
baseUrl = "http://localhost:" + connector.getLocalPort();
} }
@AfterClass @AfterClass

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,11 +25,13 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part; import javax.servlet.http.Part;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -39,7 +41,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.util.SocketUtils;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.context.request.ServletWebRequest;
@ -47,36 +48,30 @@ import static org.junit.Assert.*;
/** /**
* @author Brian Clozel * @author Brian Clozel
* @author Sam Brannen
*/ */
public class WebRequestDataBinderIntegrationTests { public class WebRequestDataBinderIntegrationTests {
private static Server jettyServer;
private static final PartsServlet partsServlet = new PartsServlet();
private static final PartListServlet partListServlet = new PartListServlet();
private final RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
protected static String baseUrl; protected static String baseUrl;
protected static MediaType contentType; protected static MediaType contentType;
private static Server jettyServer;
private RestTemplate template;
private static PartsServlet partsServlet;
private static PartListServlet partListServlet;
@Before
public void createTemplate() {
template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
}
@BeforeClass @BeforeClass
public static void startJettyServer() throws Exception { public static void startJettyServer() throws Exception {
int port = SocketUtils.findAvailableTcpPort();
jettyServer = new Server(port);
baseUrl = "http://localhost:" + port;
ServletContextHandler handler = new ServletContextHandler();
partsServlet = new PartsServlet(); // Let server pick its own random, available port.
partListServlet = new PartListServlet(); jettyServer = new Server(0);
ServletContextHandler handler = new ServletContextHandler();
MultipartConfigElement multipartConfig = new MultipartConfigElement(""); MultipartConfigElement multipartConfig = new MultipartConfigElement("");
@ -87,8 +82,13 @@ public class WebRequestDataBinderIntegrationTests {
holder = new ServletHolder(partListServlet); holder = new ServletHolder(partListServlet);
holder.getRegistration().setMultipartConfig(multipartConfig); holder.getRegistration().setMultipartConfig(multipartConfig);
handler.addServlet(holder, "/partlist"); handler.addServlet(holder, "/partlist");
jettyServer.setHandler(handler); jettyServer.setHandler(handler);
jettyServer.start(); jettyServer.start();
Connector[] connectors = jettyServer.getConnectors();
NetworkConnector connector = (NetworkConnector) connectors[0];
baseUrl = "http://localhost:" + connector.getLocalPort();
} }
@AfterClass @AfterClass

View File

@ -33,47 +33,58 @@ import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.util.SocketUtils;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Sam Brannen
*/ */
public class AbstractJettyServerTestCase { public class AbstractJettyServerTestCase {
protected static final String helloWorld = "H\u00e9llo W\u00f6rld"; protected static final String helloWorld = "H\u00e9llo W\u00f6rld";
protected static final int port = SocketUtils.findAvailableTcpPort(); protected static final MediaType textContentType = new MediaType("text", "plain",
Collections.singletonMap("charset", "UTF-8"));
protected static final String baseUrl = "http://localhost:" + port; protected static final MediaType jsonContentType = new MediaType("application",
"json", Collections.singletonMap("charset", "utf-8"));
protected static final MediaType textContentType = new MediaType("text", "plain", Collections.singletonMap("charset", "UTF-8")); private static Server jettyServer;
protected static final MediaType jsonContentType = new MediaType("application", "json", Collections.singletonMap("charset", "utf-8")); protected static int port;
protected static String baseUrl;
private static final Server jettyServer = new Server(port);
@BeforeClass @BeforeClass
public static void startJettyServer() throws Exception { public static void startJettyServer() throws Exception {
// Let server pick its own random, available port.
jettyServer = new Server(0);
ServletContextHandler handler = new ServletContextHandler(); ServletContextHandler handler = new ServletContextHandler();
byte[] bytes = helloWorld.getBytes("utf-8"); byte[] bytes = helloWorld.getBytes("utf-8");
handler.addServlet(new ServletHolder(new GetServlet(bytes, textContentType)), "/get"); handler.addServlet(new ServletHolder(new GetServlet(bytes, textContentType)), "/get");
handler.addServlet(new ServletHolder(new GetServlet(new byte[0], textContentType)), "/get/nothing"); handler.addServlet(new ServletHolder(new GetServlet(new byte[0], textContentType)), "/get/nothing");
handler.addServlet(new ServletHolder(new GetServlet(bytes, null)), "/get/nocontenttype"); handler.addServlet(new ServletHolder(new GetServlet(bytes, null)), "/get/nocontenttype");
handler.addServlet( handler.addServlet(
new ServletHolder(new PostServlet(helloWorld, baseUrl + "/post/1", bytes, textContentType)), new ServletHolder(new PostServlet(helloWorld, "/post/1", bytes, textContentType)),
"/post"); "/post");
handler.addServlet( handler.addServlet(
new ServletHolder(new JsonPostServlet(baseUrl + "/jsonpost/1", jsonContentType)), new ServletHolder(new JsonPostServlet("/jsonpost/1", jsonContentType)),
"/jsonpost"); "/jsonpost");
handler.addServlet(new ServletHolder(new StatusCodeServlet(204)), "/status/nocontent"); handler.addServlet(new ServletHolder(new StatusCodeServlet(204)), "/status/nocontent");
handler.addServlet(new ServletHolder(new StatusCodeServlet(304)), "/status/notmodified"); handler.addServlet(new ServletHolder(new StatusCodeServlet(304)), "/status/notmodified");
@ -86,8 +97,14 @@ public class AbstractJettyServerTestCase {
handler.addServlet( handler.addServlet(
new ServletHolder(new PutServlet(helloWorld, bytes, textContentType)), new ServletHolder(new PutServlet(helloWorld, bytes, textContentType)),
"/put"); "/put");
jettyServer.setHandler(handler); jettyServer.setHandler(handler);
jettyServer.start(); jettyServer.start();
Connector[] connectors = jettyServer.getConnectors();
NetworkConnector connector = (NetworkConnector) connectors[0];
port = connector.getLocalPort();
baseUrl = "http://localhost:" + port;
} }
@AfterClass @AfterClass
@ -179,7 +196,7 @@ public class AbstractJettyServerTestCase {
String body = FileCopyUtils.copyToString(request.getReader()); String body = FileCopyUtils.copyToString(request.getReader());
assertEquals("Invalid request body", s, body); assertEquals("Invalid request body", s, body);
response.setStatus(HttpServletResponse.SC_CREATED); response.setStatus(HttpServletResponse.SC_CREATED);
response.setHeader("Location", location); response.setHeader("Location", baseUrl + location);
response.setContentLength(buf.length); response.setContentLength(buf.length);
response.setContentType(contentType.toString()); response.setContentType(contentType.toString());
FileCopyUtils.copy(buf, response.getOutputStream()); FileCopyUtils.copy(buf, response.getOutputStream());
@ -205,7 +222,7 @@ public class AbstractJettyServerTestCase {
assertNotNull("No content-type", request.getContentType()); assertNotNull("No content-type", request.getContentType());
String body = FileCopyUtils.copyToString(request.getReader()); String body = FileCopyUtils.copyToString(request.getReader());
response.setStatus(HttpServletResponse.SC_CREATED); response.setStatus(HttpServletResponse.SC_CREATED);
response.setHeader("Location", location); response.setHeader("Location", baseUrl +location);
response.setContentType(contentType.toString()); response.setContentType(contentType.toString());
byte[] bytes = body.getBytes("utf-8"); byte[] bytes = body.getBytes("utf-8");
response.setContentLength(bytes.length);; response.setContentLength(bytes.length);;

View File

@ -16,8 +16,6 @@
package org.springframework.web.servlet.mvc.method.annotation; package org.springframework.web.servlet.mvc.method.annotation;
import static org.junit.Assert.*;
import java.net.URI; import java.net.URI;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
@ -26,9 +24,12 @@ import java.util.List;
import javax.servlet.MultipartConfigElement; import javax.servlet.MultipartConfigElement;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -52,7 +53,6 @@ import org.springframework.http.converter.support.AllEncompassingFormHttpMessage
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.util.SocketUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RequestPart;
@ -66,11 +66,14 @@ import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import static org.junit.Assert.*;
/** /**
* Test access to parts of a multipart request with {@link RequestPart}. * Test access to parts of a multipart request with {@link RequestPart}.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Brian Clozel * @author Brian Clozel
* @author Sam Brannen
*/ */
public class RequestPartIntegrationTests { public class RequestPartIntegrationTests {
@ -83,10 +86,10 @@ public class RequestPartIntegrationTests {
@BeforeClass @BeforeClass
public static void startServer() throws Exception { public static void startServer() throws Exception {
int port = SocketUtils.findAvailableTcpPort();
baseUrl = "http://localhost:" + port;
server = new Server(port); // Let server pick its own random, available port.
server = new Server(0);
ServletContextHandler handler = new ServletContextHandler(); ServletContextHandler handler = new ServletContextHandler();
handler.setContextPath("/"); handler.setContextPath("/");
@ -105,6 +108,10 @@ public class RequestPartIntegrationTests {
server.setHandler(handler); server.setHandler(handler);
server.start(); server.start();
Connector[] connectors = server.getConnectors();
NetworkConnector connector = (NetworkConnector) connectors[0];
baseUrl = "http://localhost:" + connector.getLocalPort();
} }
@Before @Before

View File

@ -17,18 +17,17 @@
package org.springframework.web.socket; package org.springframework.web.socket;
import java.util.EnumSet; import java.util.EnumSet;
import javax.servlet.DispatcherType; import javax.servlet.DispatcherType;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.springframework.util.Assert;
import org.springframework.util.SocketUtils;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.DispatcherServlet;
@ -49,8 +48,8 @@ public class JettyWebSocketTestServer implements WebSocketTestServer {
@Override @Override
public void setup() { public void setup() {
this.port = SocketUtils.findAvailableTcpPort(); // Let server pick its own random, available port.
this.jettyServer = new Server(this.port); this.jettyServer = new Server(0);
} }
@Override @Override
@ -60,7 +59,6 @@ public class JettyWebSocketTestServer implements WebSocketTestServer {
@Override @Override
public void deployConfig(WebApplicationContext wac, Filter... filters) { public void deployConfig(WebApplicationContext wac, Filter... filters) {
Assert.state(this.port != -1, "setup() was never called.");
ServletHolder servletHolder = new ServletHolder(new DispatcherServlet(wac)); ServletHolder servletHolder = new ServletHolder(new DispatcherServlet(wac));
this.contextHandler = new ServletContextHandler(); this.contextHandler = new ServletContextHandler();
this.contextHandler.addServlet(servletHolder, "/"); this.contextHandler.addServlet(servletHolder, "/");
@ -87,6 +85,10 @@ public class JettyWebSocketTestServer implements WebSocketTestServer {
@Override @Override
public void start() throws Exception { public void start() throws Exception {
this.jettyServer.start(); this.jettyServer.start();
Connector[] connectors = jettyServer.getConnectors();
NetworkConnector connector = (NetworkConnector) connectors[0];
this.port = connector.getLocalPort();
} }
@Override @Override