Minimise our usage of SocketUtils.findAvailableTcpPort
Closes gh-9382
This commit is contained in:
		
							parent
							
								
									10868519e1
								
							
						
					
					
						commit
						f7e9ec5f42
					
				| 
						 | 
				
			
			@ -17,8 +17,6 @@
 | 
			
		|||
package org.springframework.boot.actuate.autoconfigure;
 | 
			
		||||
 | 
			
		||||
import java.io.FileNotFoundException;
 | 
			
		||||
import java.net.InetSocketAddress;
 | 
			
		||||
import java.net.ServerSocket;
 | 
			
		||||
import java.net.SocketException;
 | 
			
		||||
import java.net.URI;
 | 
			
		||||
import java.nio.charset.Charset;
 | 
			
		||||
| 
						 | 
				
			
			@ -67,12 +65,10 @@ import org.springframework.boot.logging.LoggingSystem;
 | 
			
		|||
import org.springframework.boot.test.util.TestPropertyValues;
 | 
			
		||||
import org.springframework.boot.testutil.Matched;
 | 
			
		||||
import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer;
 | 
			
		||||
import org.springframework.boot.web.context.WebServerInitializedEvent;
 | 
			
		||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
 | 
			
		||||
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
 | 
			
		||||
import org.springframework.boot.web.server.WebServer;
 | 
			
		||||
import org.springframework.boot.web.server.WebServerException;
 | 
			
		||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
 | 
			
		||||
import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent;
 | 
			
		||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
 | 
			
		||||
import org.springframework.context.ApplicationContext;
 | 
			
		||||
import org.springframework.context.ApplicationListener;
 | 
			
		||||
| 
						 | 
				
			
			@ -80,6 +76,7 @@ import org.springframework.context.ConfigurableApplicationContext;
 | 
			
		|||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.context.annotation.Import;
 | 
			
		||||
import org.springframework.context.event.ContextRefreshedEvent;
 | 
			
		||||
import org.springframework.http.HttpMethod;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.client.ClientHttpRequest;
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +85,6 @@ import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
 | 
			
		|||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
 | 
			
		||||
import org.springframework.stereotype.Controller;
 | 
			
		||||
import org.springframework.test.util.ReflectionTestUtils;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
import org.springframework.util.StreamUtils;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.ResponseBody;
 | 
			
		||||
| 
						 | 
				
			
			@ -134,7 +130,6 @@ public class EndpointWebMvcAutoConfigurationTests {
 | 
			
		|||
	@After
 | 
			
		||||
	public void cleanUp() throws Exception {
 | 
			
		||||
		this.applicationContext.close();
 | 
			
		||||
		assertAllClosed();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
| 
						 | 
				
			
			@ -146,8 +141,6 @@ public class EndpointWebMvcAutoConfigurationTests {
 | 
			
		|||
		this.applicationContext.refresh();
 | 
			
		||||
		assertContent("/controller", ports.get().server, "controlleroutput");
 | 
			
		||||
		assertContent("/endpoint", ports.get().server, "endpointoutput");
 | 
			
		||||
		assertContent("/controller", ports.get().management, null);
 | 
			
		||||
		assertContent("/endpoint", ports.get().management, null);
 | 
			
		||||
		assertThat(hasHeader("/endpoint", ports.get().server, "X-Application-Context"))
 | 
			
		||||
				.isFalse();
 | 
			
		||||
		assertThat(this.applicationContext.containsBean("applicationContextIdFilter"))
 | 
			
		||||
| 
						 | 
				
			
			@ -274,25 +267,6 @@ public class EndpointWebMvcAutoConfigurationTests {
 | 
			
		|||
		assertContent("/endpoint", ports.get().management, null);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void onRandomPort() throws Exception {
 | 
			
		||||
		TestPropertyValues.of("management.port=0", "management.security.enabled=false")
 | 
			
		||||
				.applyTo(this.applicationContext);
 | 
			
		||||
		this.applicationContext.register(RootConfig.class, EndpointConfig.class,
 | 
			
		||||
				BaseConfiguration.class, EndpointWebMvcAutoConfiguration.class,
 | 
			
		||||
				ErrorMvcAutoConfiguration.class);
 | 
			
		||||
		GrabManagementPort grabManagementPort = new GrabManagementPort(
 | 
			
		||||
				this.applicationContext);
 | 
			
		||||
		this.applicationContext.addApplicationListener(grabManagementPort);
 | 
			
		||||
		this.applicationContext.refresh();
 | 
			
		||||
		int managementPort = grabManagementPort.getWebServer().getPort();
 | 
			
		||||
		assertThat(managementPort).isNotEqualTo(ports.get().server);
 | 
			
		||||
		assertContent("/controller", ports.get().server, "controlleroutput");
 | 
			
		||||
		assertContent("/endpoint", ports.get().server, null);
 | 
			
		||||
		assertContent("/controller", managementPort, null);
 | 
			
		||||
		assertContent("/endpoint", managementPort, "endpointoutput");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void onDifferentPortWithPrimaryFailure() throws Exception {
 | 
			
		||||
		TestPropertyValues.of("management.port=" + ports.get().management)
 | 
			
		||||
| 
						 | 
				
			
			@ -340,20 +314,22 @@ public class EndpointWebMvcAutoConfigurationTests {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void specificPortsViaPropertiesWithClash() throws Exception {
 | 
			
		||||
		int managementPort = ports.get().management;
 | 
			
		||||
		try (ServerSocket serverSocket = new ServerSocket()) {
 | 
			
		||||
			serverSocket.bind(new InetSocketAddress(managementPort));
 | 
			
		||||
			TestPropertyValues
 | 
			
		||||
					.of("server.port:" + ports.get().server,
 | 
			
		||||
							"management.port:" + ports.get().management)
 | 
			
		||||
					.applyTo(this.applicationContext);
 | 
			
		||||
			this.applicationContext.register(RootConfig.class, EndpointConfig.class,
 | 
			
		||||
					BaseConfiguration.class, EndpointWebMvcAutoConfiguration.class,
 | 
			
		||||
					ErrorMvcAutoConfiguration.class);
 | 
			
		||||
			this.thrown.expect(WebServerException.class);
 | 
			
		||||
			this.applicationContext.refresh();
 | 
			
		||||
		}
 | 
			
		||||
	public void managementContextFailureCausesMainContextFailure() throws Exception {
 | 
			
		||||
		TestPropertyValues
 | 
			
		||||
				.of("server.port:" + ports.get().server,
 | 
			
		||||
						"management.port:" + ports.get().management)
 | 
			
		||||
				.applyTo(this.applicationContext);
 | 
			
		||||
		this.applicationContext.register(RootConfig.class, EndpointConfig.class,
 | 
			
		||||
				BaseConfiguration.class, EndpointWebMvcAutoConfiguration.class,
 | 
			
		||||
				ErrorMvcAutoConfiguration.class);
 | 
			
		||||
		this.applicationContext.addApplicationListener(
 | 
			
		||||
				(ApplicationListener<ContextRefreshedEvent>) (event) -> {
 | 
			
		||||
					if (event.getApplicationContext().getParent() != null) {
 | 
			
		||||
						throw new RuntimeException();
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
		this.thrown.expect(RuntimeException.class);
 | 
			
		||||
		this.applicationContext.refresh();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
| 
						 | 
				
			
			@ -671,13 +647,6 @@ public class EndpointWebMvcAutoConfigurationTests {
 | 
			
		|||
		assertThat(this.applicationContext.getBeansOfType(type)).hasSize(1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void assertAllClosed() throws Exception {
 | 
			
		||||
		assertContent("/controller", ports.get().server, null);
 | 
			
		||||
		assertContent("/endpoint", ports.get().server, null);
 | 
			
		||||
		assertContent("/controller", ports.get().management, null);
 | 
			
		||||
		assertContent("/endpoint", ports.get().management, null);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void assertHttpsContent(String url, int port, Object expected)
 | 
			
		||||
			throws Exception {
 | 
			
		||||
		assertContent("https", url, port, expected);
 | 
			
		||||
| 
						 | 
				
			
			@ -733,9 +702,9 @@ public class EndpointWebMvcAutoConfigurationTests {
 | 
			
		|||
 | 
			
		||||
	private static class Ports {
 | 
			
		||||
 | 
			
		||||
		final int server = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
		int server = 0;
 | 
			
		||||
 | 
			
		||||
		final int management = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
		int management = 0;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -758,6 +727,19 @@ public class EndpointWebMvcAutoConfigurationTests {
 | 
			
		|||
			return new TestController();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public ApplicationListener<WebServerInitializedEvent> serverPortListener() {
 | 
			
		||||
			return (event) -> {
 | 
			
		||||
				int port = event.getWebServer().getPort();
 | 
			
		||||
				if (event.getApplicationContext().getParent() == null) {
 | 
			
		||||
					ports.get().server = port;
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					ports.get().management = port;
 | 
			
		||||
				}
 | 
			
		||||
			};
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
| 
						 | 
				
			
			@ -886,30 +868,6 @@ public class EndpointWebMvcAutoConfigurationTests {
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class GrabManagementPort
 | 
			
		||||
			implements ApplicationListener<ServletWebServerInitializedEvent> {
 | 
			
		||||
 | 
			
		||||
		private ApplicationContext rootContext;
 | 
			
		||||
 | 
			
		||||
		private WebServer webServer;
 | 
			
		||||
 | 
			
		||||
		GrabManagementPort(ApplicationContext rootContext) {
 | 
			
		||||
			this.rootContext = rootContext;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void onApplicationEvent(ServletWebServerInitializedEvent event) {
 | 
			
		||||
			if (event.getApplicationContext() != this.rootContext) {
 | 
			
		||||
				this.webServer = event.getWebServer();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public WebServer getWebServer() {
 | 
			
		||||
			return this.webServer;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class SpecificServletWebServerFactory
 | 
			
		||||
			extends TomcatServletWebServerFactory {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,7 +57,6 @@ import org.springframework.core.annotation.Order;
 | 
			
		|||
import org.springframework.dao.DataAccessException;
 | 
			
		||||
import org.springframework.jdbc.core.ConnectionCallback;
 | 
			
		||||
import org.springframework.jdbc.core.JdbcTemplate;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.junit.Assert.fail;
 | 
			
		||||
| 
						 | 
				
			
			@ -347,9 +346,7 @@ public class PublicMetricsAutoConfigurationTests {
 | 
			
		|||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public TomcatServletWebServerFactory webServerFactory() {
 | 
			
		||||
			TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
 | 
			
		||||
			factory.setPort(SocketUtils.findAvailableTcpPort(40000));
 | 
			
		||||
			return factory;
 | 
			
		||||
			return new TomcatServletWebServerFactory(0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,6 @@ import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactor
 | 
			
		|||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -55,9 +54,7 @@ public class TomcatPublicMetricsTests {
 | 
			
		|||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public TomcatServletWebServerFactory webServerFactory() {
 | 
			
		||||
			TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
 | 
			
		||||
			factory.setPort(SocketUtils.findAvailableTcpPort(40000));
 | 
			
		||||
			return factory;
 | 
			
		||||
			return new TomcatServletWebServerFactory(0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,6 @@ import org.junit.Test;
 | 
			
		|||
 | 
			
		||||
import org.springframework.boot.actuate.metrics.Metric;
 | 
			
		||||
import org.springframework.boot.actuate.metrics.writer.Delta;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,12 +39,10 @@ import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		|||
 */
 | 
			
		||||
public class StatsdMetricWriterTests {
 | 
			
		||||
 | 
			
		||||
	private int port = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
 | 
			
		||||
	private DummyStatsDServer server = new DummyStatsDServer(this.port);
 | 
			
		||||
	private DummyStatsDServer server = new DummyStatsDServer(0);
 | 
			
		||||
 | 
			
		||||
	private StatsdMetricWriter writer = new StatsdMetricWriter("me", "localhost",
 | 
			
		||||
			this.port);
 | 
			
		||||
			this.server.getPort());
 | 
			
		||||
 | 
			
		||||
	@After
 | 
			
		||||
	public void close() {
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +81,7 @@ public class StatsdMetricWriterTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void nullPrefix() throws Exception {
 | 
			
		||||
		this.writer = new StatsdMetricWriter("localhost", this.port);
 | 
			
		||||
		this.writer = new StatsdMetricWriter("localhost", this.server.getPort());
 | 
			
		||||
		this.writer.set(new Metric<>("gauge.foo", 3L));
 | 
			
		||||
		this.server.waitForMessage();
 | 
			
		||||
		assertThat(this.server.messagesReceived().get(0)).isEqualTo("gauge.foo:3|g");
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +89,7 @@ public class StatsdMetricWriterTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void periodPrefix() throws Exception {
 | 
			
		||||
		this.writer = new StatsdMetricWriter("my.", "localhost", this.port);
 | 
			
		||||
		this.writer = new StatsdMetricWriter("my.", "localhost", this.server.getPort());
 | 
			
		||||
		this.writer.set(new Metric<>("gauge.foo", 3L));
 | 
			
		||||
		this.server.waitForMessage();
 | 
			
		||||
		assertThat(this.server.messagesReceived().get(0)).isEqualTo("my.gauge.foo:3|g");
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +126,10 @@ public class StatsdMetricWriterTests {
 | 
			
		|||
			new Thread(this).start();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		int getPort() {
 | 
			
		||||
			return this.server.getLocalPort();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void stop() {
 | 
			
		||||
			this.server.close();
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,11 @@
 | 
			
		|||
 | 
			
		||||
package org.springframework.boot.autoconfigure.elasticsearch.jest;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Paths;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +30,7 @@ import io.searchbox.client.config.HttpClientConfig;
 | 
			
		|||
import io.searchbox.client.http.JestHttpClient;
 | 
			
		||||
import io.searchbox.core.Index;
 | 
			
		||||
import io.searchbox.core.Search;
 | 
			
		||||
import org.elasticsearch.client.node.NodeClient;
 | 
			
		||||
import org.elasticsearch.index.query.QueryBuilders;
 | 
			
		||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
 | 
			
		||||
import org.junit.After;
 | 
			
		||||
| 
						 | 
				
			
			@ -33,15 +38,20 @@ import org.junit.Rule;
 | 
			
		|||
import org.junit.Test;
 | 
			
		||||
import org.junit.rules.ExpectedException;
 | 
			
		||||
 | 
			
		||||
import org.springframework.beans.BeansException;
 | 
			
		||||
import org.springframework.beans.FatalBeanException;
 | 
			
		||||
import org.springframework.beans.factory.BeanCreationException;
 | 
			
		||||
import org.springframework.beans.factory.config.BeanPostProcessor;
 | 
			
		||||
import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration;
 | 
			
		||||
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
 | 
			
		||||
import org.springframework.boot.test.util.TestPropertyValues;
 | 
			
		||||
import org.springframework.context.ApplicationContext;
 | 
			
		||||
import org.springframework.context.ApplicationContextAware;
 | 
			
		||||
import org.springframework.context.ConfigurableApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.context.annotation.Import;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
| 
						 | 
				
			
			@ -105,12 +115,12 @@ public class JestAutoConfigurationTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void jestCanCommunicateWithElasticsearchInstance() throws IOException {
 | 
			
		||||
		int port = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
		load(ElasticsearchAutoConfiguration.class,
 | 
			
		||||
		new File("target/elastic/logs").mkdirs();
 | 
			
		||||
		load(HttpPortConfiguration.class,
 | 
			
		||||
				"spring.data.elasticsearch.properties.path.home:target/elastic",
 | 
			
		||||
				"spring.data.elasticsearch.properties.http.enabled:true",
 | 
			
		||||
				"spring.data.elasticsearch.properties.http.port:" + port,
 | 
			
		||||
				"spring.elasticsearch.jest.uris:http://localhost:" + port);
 | 
			
		||||
				"spring.data.elasticsearch.properties.http.port:0",
 | 
			
		||||
				"spring.data.elasticsearch.properties.node.portsfile:true");
 | 
			
		||||
		JestClient client = this.context.getBean(JestClient.class);
 | 
			
		||||
		Map<String, String> source = new HashMap<>();
 | 
			
		||||
		source.put("a", "alpha");
 | 
			
		||||
| 
						 | 
				
			
			@ -182,4 +192,53 @@ public class JestAutoConfigurationTests {
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@Import(ElasticsearchAutoConfiguration.class)
 | 
			
		||||
	static class HttpPortConfiguration {
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public static BeanPostProcessor portPropertyConfigurer() {
 | 
			
		||||
			return new PortPropertyConfigurer();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static final class PortPropertyConfigurer
 | 
			
		||||
				implements BeanPostProcessor, ApplicationContextAware {
 | 
			
		||||
 | 
			
		||||
			private ConfigurableApplicationContext applicationContext;
 | 
			
		||||
 | 
			
		||||
			@Override
 | 
			
		||||
			public Object postProcessAfterInitialization(Object bean, String beanName)
 | 
			
		||||
					throws BeansException {
 | 
			
		||||
				if (bean instanceof NodeClient) {
 | 
			
		||||
					this.applicationContext.getBean(JestProperties.class)
 | 
			
		||||
							.setUris(Arrays.asList("http://localhost:" + readHttpPort()));
 | 
			
		||||
				}
 | 
			
		||||
				return bean;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			@Override
 | 
			
		||||
			public void setApplicationContext(ApplicationContext applicationContext)
 | 
			
		||||
					throws BeansException {
 | 
			
		||||
				this.applicationContext = (ConfigurableApplicationContext) applicationContext;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			private int readHttpPort() {
 | 
			
		||||
				try {
 | 
			
		||||
					for (String line : Files
 | 
			
		||||
							.readAllLines(Paths.get("target/elastic/logs/http.ports"))) {
 | 
			
		||||
						if (line.startsWith("127.0.0.1")) {
 | 
			
		||||
							return Integer
 | 
			
		||||
									.parseInt(line.substring(line.indexOf(":") + 1));
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					throw new FatalBeanException("HTTP port not found");
 | 
			
		||||
				}
 | 
			
		||||
				catch (IOException ex) {
 | 
			
		||||
					throw new FatalBeanException("Failed to read HTTP port", ex);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,6 @@ import org.springframework.context.annotation.Bean;
 | 
			
		|||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.data.mongodb.core.MongoTemplate;
 | 
			
		||||
import org.springframework.util.FileSystemUtils;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -157,9 +156,7 @@ public class EmbeddedMongoAutoConfigurationTests {
 | 
			
		|||
	private void assertVersionConfiguration(String configuredVersion,
 | 
			
		||||
			String expectedVersion) {
 | 
			
		||||
		this.context = new AnnotationConfigApplicationContext();
 | 
			
		||||
		int mongoPort = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
		TestPropertyValues.of("spring.data.mongodb.port=" + mongoPort)
 | 
			
		||||
				.applyTo(this.context);
 | 
			
		||||
		TestPropertyValues.of("spring.data.mongodb.port=0").applyTo(this.context);
 | 
			
		||||
		if (configuredVersion != null) {
 | 
			
		||||
			TestPropertyValues.of("spring.mongodb.embedded.version=" + configuredVersion)
 | 
			
		||||
					.applyTo(this.context);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2012-2016 the original author or authors.
 | 
			
		||||
 * Copyright 2012-2017 the original author or authors.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +24,6 @@ import org.springframework.boot.cli.command.archive.WarCommand;
 | 
			
		|||
import org.springframework.boot.cli.infrastructure.CommandLineInvoker;
 | 
			
		||||
import org.springframework.boot.cli.infrastructure.CommandLineInvoker.Invocation;
 | 
			
		||||
import org.springframework.boot.loader.tools.JavaExecutable;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,15 +40,13 @@ public class WarCommandIT {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void warCreation() throws Exception {
 | 
			
		||||
		int port = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
		File war = new File("target/test-app.war");
 | 
			
		||||
		Invocation invocation = this.cli.invoke("war", war.getAbsolutePath(),
 | 
			
		||||
				"war.groovy");
 | 
			
		||||
		invocation.await();
 | 
			
		||||
		assertThat(war.exists()).isTrue();
 | 
			
		||||
		Process process = new JavaExecutable()
 | 
			
		||||
				.processBuilder("-jar", war.getAbsolutePath(), "--server.port=" + port)
 | 
			
		||||
				.start();
 | 
			
		||||
				.processBuilder("-jar", war.getAbsolutePath(), "--server.port=0").start();
 | 
			
		||||
		invocation = new Invocation(process);
 | 
			
		||||
		invocation.await();
 | 
			
		||||
		assertThat(invocation.getOutput()).contains("onStart error");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ package org.springframework.boot.cli;
 | 
			
		|||
 | 
			
		||||
import java.io.BufferedReader;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileReader;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +42,7 @@ import org.springframework.boot.cli.command.archive.JarCommand;
 | 
			
		|||
import org.springframework.boot.cli.command.grab.GrabCommand;
 | 
			
		||||
import org.springframework.boot.cli.command.run.RunCommand;
 | 
			
		||||
import org.springframework.boot.test.rule.OutputCapture;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
import org.springframework.util.FileCopyUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * {@link TestRule} that can be used to invoke CLI commands.
 | 
			
		||||
| 
						 | 
				
			
			@ -60,8 +61,6 @@ public class CliTester implements TestRule {
 | 
			
		|||
 | 
			
		||||
	private final String prefix;
 | 
			
		||||
 | 
			
		||||
	private final int port = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
 | 
			
		||||
	public CliTester(String prefix) {
 | 
			
		||||
		this.prefix = prefix;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +70,21 @@ public class CliTester implements TestRule {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	public String run(String... args) throws Exception {
 | 
			
		||||
		Future<RunCommand> future = submitCommand(new RunCommand(), args);
 | 
			
		||||
		List<String> updatedArgs = new ArrayList<>();
 | 
			
		||||
		boolean classpathUpdated = false;
 | 
			
		||||
		for (String arg : args) {
 | 
			
		||||
			if (arg.startsWith("--classpath=")) {
 | 
			
		||||
				arg = arg + ":" + new File("target/test-classes").getAbsolutePath();
 | 
			
		||||
				classpathUpdated = true;
 | 
			
		||||
			}
 | 
			
		||||
			updatedArgs.add(arg);
 | 
			
		||||
		}
 | 
			
		||||
		if (!classpathUpdated) {
 | 
			
		||||
			updatedArgs.add(
 | 
			
		||||
					"--classpath=.:" + new File("target/test-classes").getAbsolutePath());
 | 
			
		||||
		}
 | 
			
		||||
		Future<RunCommand> future = submitCommand(new RunCommand(),
 | 
			
		||||
				updatedArgs.toArray(new String[updatedArgs.size()]));
 | 
			
		||||
		this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS));
 | 
			
		||||
		return getOutput();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -96,13 +109,19 @@ public class CliTester implements TestRule {
 | 
			
		|||
			@Override
 | 
			
		||||
			public T call() throws Exception {
 | 
			
		||||
				ClassLoader loader = Thread.currentThread().getContextClassLoader();
 | 
			
		||||
				System.setProperty("server.port", String.valueOf(CliTester.this.port));
 | 
			
		||||
				System.setProperty("server.port", "0");
 | 
			
		||||
				System.setProperty("spring.application.class.name",
 | 
			
		||||
						"org.springframework.boot.cli.CliTesterSpringApplication");
 | 
			
		||||
				System.setProperty("portfile",
 | 
			
		||||
						new File("target/server.port").getAbsolutePath());
 | 
			
		||||
				try {
 | 
			
		||||
					command.run(sources);
 | 
			
		||||
					return command;
 | 
			
		||||
				}
 | 
			
		||||
				finally {
 | 
			
		||||
					System.clearProperty("server.port");
 | 
			
		||||
					System.clearProperty("spring.application.class.name");
 | 
			
		||||
					System.clearProperty("portfile");
 | 
			
		||||
					Thread.currentThread().setContextClassLoader(loader);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +156,7 @@ public class CliTester implements TestRule {
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				sources[i] = this.prefix + arg;
 | 
			
		||||
				sources[i] = new File(arg).isAbsolute() ? arg : this.prefix + arg;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return sources;
 | 
			
		||||
| 
						 | 
				
			
			@ -172,7 +191,9 @@ public class CliTester implements TestRule {
 | 
			
		|||
 | 
			
		||||
	public String getHttpOutput(String uri) {
 | 
			
		||||
		try {
 | 
			
		||||
			InputStream stream = URI.create("http://localhost:" + this.port + uri).toURL()
 | 
			
		||||
			int port = Integer.parseInt(
 | 
			
		||||
					FileCopyUtils.copyToString(new FileReader("target/server.port")));
 | 
			
		||||
			InputStream stream = URI.create("http://localhost:" + port + uri).toURL()
 | 
			
		||||
					.openStream();
 | 
			
		||||
			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
 | 
			
		||||
			String line;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2012-2017 the original author or authors.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.springframework.boot.cli;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.SpringApplication;
 | 
			
		||||
import org.springframework.boot.system.EmbeddedServerPortFileWriter;
 | 
			
		||||
import org.springframework.context.ConfigurableApplicationContext;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Custom {@link SpringApplication} used by {@link CliTester}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Andy Wilkinson
 | 
			
		||||
 */
 | 
			
		||||
public class CliTesterSpringApplication extends SpringApplication {
 | 
			
		||||
 | 
			
		||||
	public CliTesterSpringApplication(Class<?>... sources) {
 | 
			
		||||
		super(sources);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
 | 
			
		||||
		context.addApplicationListener(new EmbeddedServerPortFileWriter());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -112,13 +112,15 @@ public class LiveReloadServer {
 | 
			
		|||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Start the livereload server and accept incoming connections.
 | 
			
		||||
	 * @return the port on which the server is listening
 | 
			
		||||
	 * @throws IOException in case of I/O errors
 | 
			
		||||
	 */
 | 
			
		||||
	public void start() throws IOException {
 | 
			
		||||
	public int start() throws IOException {
 | 
			
		||||
		synchronized (this.monitor) {
 | 
			
		||||
			Assert.state(!isStarted(), "Server already started");
 | 
			
		||||
			logger.debug("Starting live reload server on port " + this.port);
 | 
			
		||||
			this.serverSocket = new ServerSocket(this.port);
 | 
			
		||||
			int localPort = this.serverSocket.getLocalPort();
 | 
			
		||||
			this.listenThread = this.threadFactory.newThread(new Runnable() {
 | 
			
		||||
 | 
			
		||||
				@Override
 | 
			
		||||
| 
						 | 
				
			
			@ -130,6 +132,7 @@ public class LiveReloadServer {
 | 
			
		|||
			this.listenThread.setDaemon(true);
 | 
			
		||||
			this.listenThread.setName("Live Reload Server");
 | 
			
		||||
			this.listenThread.start();
 | 
			
		||||
			return localPort;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,7 +57,7 @@ public class TunnelClient implements SmartInitializingSingleton {
 | 
			
		|||
	private ServerThread serverThread;
 | 
			
		||||
 | 
			
		||||
	public TunnelClient(int listenPort, TunnelConnection tunnelConnection) {
 | 
			
		||||
		Assert.isTrue(listenPort > 0, "ListenPort must be positive");
 | 
			
		||||
		Assert.isTrue(listenPort >= 0, "ListenPort must be greater than or equal to 0");
 | 
			
		||||
		Assert.notNull(tunnelConnection, "TunnelConnection must not be null");
 | 
			
		||||
		this.listenPort = listenPort;
 | 
			
		||||
		this.tunnelConnection = tunnelConnection;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,18 +78,20 @@ public class TunnelClient implements SmartInitializingSingleton {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Start the client and accept incoming connections on the port.
 | 
			
		||||
	 * Start the client and accept incoming connections.
 | 
			
		||||
	 * @return the port on which the client is listening
 | 
			
		||||
	 * @throws IOException in case of I/O errors
 | 
			
		||||
	 */
 | 
			
		||||
	public void start() throws IOException {
 | 
			
		||||
	public int start() throws IOException {
 | 
			
		||||
		synchronized (this.monitor) {
 | 
			
		||||
			Assert.state(this.serverThread == null, "Server already started");
 | 
			
		||||
			ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
 | 
			
		||||
			serverSocketChannel.socket().bind(new InetSocketAddress(this.listenPort));
 | 
			
		||||
			logger.trace(
 | 
			
		||||
					"Listening for TCP traffic to tunnel on port " + this.listenPort);
 | 
			
		||||
			int port = serverSocketChannel.socket().getLocalPort();
 | 
			
		||||
			logger.trace("Listening for TCP traffic to tunnel on port " + port);
 | 
			
		||||
			this.serverThread = new ServerThread(serverSocketChannel);
 | 
			
		||||
			this.serverThread.start();
 | 
			
		||||
			return port;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +102,6 @@ public class TunnelClient implements SmartInitializingSingleton {
 | 
			
		|||
	public void stop() throws IOException {
 | 
			
		||||
		synchronized (this.monitor) {
 | 
			
		||||
			if (this.serverThread != null) {
 | 
			
		||||
				logger.trace("Closing tunnel client on port " + this.listenPort);
 | 
			
		||||
				this.serverThread.close();
 | 
			
		||||
				try {
 | 
			
		||||
					this.serverThread.join(2000);
 | 
			
		||||
| 
						 | 
				
			
			@ -143,6 +144,8 @@ public class TunnelClient implements SmartInitializingSingleton {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		public void close() throws IOException {
 | 
			
		||||
			logger.trace("Closing tunnel client on port "
 | 
			
		||||
					+ this.serverSocketChannel.socket().getLocalPort());
 | 
			
		||||
			this.serverSocketChannel.close();
 | 
			
		||||
			this.acceptConnections = false;
 | 
			
		||||
			interrupt();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,7 +53,6 @@ import org.springframework.context.event.ContextRefreshedEvent;
 | 
			
		|||
import org.springframework.data.redis.connection.RedisConnectionFactory;
 | 
			
		||||
import org.springframework.data.redis.core.RedisTemplate;
 | 
			
		||||
import org.springframework.test.util.ReflectionTestUtils;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.any;
 | 
			
		||||
| 
						 | 
				
			
			@ -77,8 +76,6 @@ public class LocalDevToolsAutoConfigurationTests {
 | 
			
		|||
	@Rule
 | 
			
		||||
	public MockRestarter mockRestarter = new MockRestarter();
 | 
			
		||||
 | 
			
		||||
	private int liveReloadPort = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
 | 
			
		||||
	private ConfigurableApplicationContext context;
 | 
			
		||||
 | 
			
		||||
	@After
 | 
			
		||||
| 
						 | 
				
			
			@ -270,7 +267,7 @@ public class LocalDevToolsAutoConfigurationTests {
 | 
			
		|||
			Map<String, Object> specifiedProperties) {
 | 
			
		||||
		Map<String, Object> properties = new HashMap<>();
 | 
			
		||||
		properties.put("spring.thymeleaf.check-template-location", false);
 | 
			
		||||
		properties.put("spring.devtools.livereload.port", this.liveReloadPort);
 | 
			
		||||
		properties.put("spring.devtools.livereload.port", 0);
 | 
			
		||||
		properties.put("server.port", 0);
 | 
			
		||||
		properties.putAll(specifiedProperties);
 | 
			
		||||
		return properties;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,13 +16,14 @@
 | 
			
		|||
 | 
			
		||||
package org.springframework.boot.devtools.integrationtest;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Value;
 | 
			
		||||
import org.springframework.boot.devtools.integrationtest.HttpTunnelIntegrationTests.TunnelConfiguration.TestTunnelClient;
 | 
			
		||||
import org.springframework.boot.devtools.remote.server.AccessManager;
 | 
			
		||||
import org.springframework.boot.devtools.remote.server.Dispatcher;
 | 
			
		||||
import org.springframework.boot.devtools.remote.server.DispatcherFilter;
 | 
			
		||||
| 
						 | 
				
			
			@ -33,22 +34,19 @@ import org.springframework.boot.devtools.tunnel.client.TunnelClient;
 | 
			
		|||
import org.springframework.boot.devtools.tunnel.client.TunnelConnection;
 | 
			
		||||
import org.springframework.boot.devtools.tunnel.server.HttpTunnelServer;
 | 
			
		||||
import org.springframework.boot.devtools.tunnel.server.HttpTunnelServerHandler;
 | 
			
		||||
import org.springframework.boot.devtools.tunnel.server.PortProvider;
 | 
			
		||||
import org.springframework.boot.devtools.tunnel.server.SocketTargetServerConnection;
 | 
			
		||||
import org.springframework.boot.devtools.tunnel.server.StaticPortProvider;
 | 
			
		||||
import org.springframework.boot.devtools.tunnel.server.TargetServerConnection;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 | 
			
		||||
import org.springframework.boot.test.util.TestPropertyValues;
 | 
			
		||||
import org.springframework.boot.test.web.client.TestRestTemplate;
 | 
			
		||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
 | 
			
		||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
 | 
			
		||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
 | 
			
		||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
 | 
			
		||||
import org.springframework.test.context.junit4.SpringRunner;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.springframework.web.servlet.DispatcherServlet;
 | 
			
		||||
| 
						 | 
				
			
			@ -61,62 +59,48 @@ import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		|||
 *
 | 
			
		||||
 * @author Phillip Webb
 | 
			
		||||
 */
 | 
			
		||||
@RunWith(SpringRunner.class)
 | 
			
		||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
 | 
			
		||||
public class HttpTunnelIntegrationTests {
 | 
			
		||||
 | 
			
		||||
	@Autowired
 | 
			
		||||
	private Config config;
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void httpServerDirect() throws Exception {
 | 
			
		||||
		String url = "http://localhost:" + this.config.httpServerPort + "/hello";
 | 
			
		||||
		AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext();
 | 
			
		||||
		context.register(ServerConfiguration.class);
 | 
			
		||||
		context.refresh();
 | 
			
		||||
		String url = "http://localhost:" + context.getWebServer().getPort() + "/hello";
 | 
			
		||||
		ResponseEntity<String> entity = new TestRestTemplate().getForEntity(url,
 | 
			
		||||
				String.class);
 | 
			
		||||
		assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
 | 
			
		||||
		assertThat(entity.getBody()).isEqualTo("Hello World");
 | 
			
		||||
		context.close();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void viaTunnel() throws Exception {
 | 
			
		||||
		String url = "http://localhost:" + this.config.clientPort + "/hello";
 | 
			
		||||
		AnnotationConfigServletWebServerApplicationContext serverContext = new AnnotationConfigServletWebServerApplicationContext();
 | 
			
		||||
		serverContext.register(ServerConfiguration.class);
 | 
			
		||||
		serverContext.refresh();
 | 
			
		||||
		AnnotationConfigApplicationContext tunnelContext = new AnnotationConfigApplicationContext();
 | 
			
		||||
		TestPropertyValues.of("server.port:" + serverContext.getWebServer().getPort())
 | 
			
		||||
				.applyTo(tunnelContext);
 | 
			
		||||
		tunnelContext.register(TunnelConfiguration.class);
 | 
			
		||||
		tunnelContext.refresh();
 | 
			
		||||
		String url = "http://localhost:"
 | 
			
		||||
				+ tunnelContext.getBean(TestTunnelClient.class).port + "/hello";
 | 
			
		||||
		ResponseEntity<String> entity = new TestRestTemplate().getForEntity(url,
 | 
			
		||||
				String.class);
 | 
			
		||||
		assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
 | 
			
		||||
		assertThat(entity.getBody()).isEqualTo("Hello World");
 | 
			
		||||
		serverContext.close();
 | 
			
		||||
		tunnelContext.close();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@EnableWebMvc
 | 
			
		||||
	static class Config {
 | 
			
		||||
 | 
			
		||||
		private int clientPort = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
 | 
			
		||||
		private int httpServerPort = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
	static class ServerConfiguration {
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public ServletWebServerFactory container() {
 | 
			
		||||
			return new TomcatServletWebServerFactory(this.httpServerPort);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public DispatcherFilter filter() {
 | 
			
		||||
			PortProvider port = new StaticPortProvider(this.httpServerPort);
 | 
			
		||||
			TargetServerConnection connection = new SocketTargetServerConnection(port);
 | 
			
		||||
			HttpTunnelServer server = new HttpTunnelServer(connection);
 | 
			
		||||
			HandlerMapper mapper = new UrlHandlerMapper("/httptunnel",
 | 
			
		||||
					new HttpTunnelServerHandler(server));
 | 
			
		||||
			Collection<HandlerMapper> mappers = Collections.singleton(mapper);
 | 
			
		||||
			Dispatcher dispatcher = new Dispatcher(AccessManager.PERMIT_ALL, mappers);
 | 
			
		||||
			return new DispatcherFilter(dispatcher);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public TunnelClient tunnelClient() {
 | 
			
		||||
			String url = "http://localhost:" + this.httpServerPort + "/httptunnel";
 | 
			
		||||
			TunnelConnection connection = new HttpTunnelConnection(url,
 | 
			
		||||
					new SimpleClientHttpRequestFactory());
 | 
			
		||||
			return new TunnelClient(this.clientPort, connection);
 | 
			
		||||
			return new TomcatServletWebServerFactory(0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +113,47 @@ public class HttpTunnelIntegrationTests {
 | 
			
		|||
			return new MyController();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public DispatcherFilter filter(
 | 
			
		||||
				AnnotationConfigServletWebServerApplicationContext context) {
 | 
			
		||||
			TargetServerConnection connection = new SocketTargetServerConnection(
 | 
			
		||||
					() -> context.getWebServer().getPort());
 | 
			
		||||
			HttpTunnelServer server = new HttpTunnelServer(connection);
 | 
			
		||||
			HandlerMapper mapper = new UrlHandlerMapper("/httptunnel",
 | 
			
		||||
					new HttpTunnelServerHandler(server));
 | 
			
		||||
			Collection<HandlerMapper> mappers = Collections.singleton(mapper);
 | 
			
		||||
			Dispatcher dispatcher = new Dispatcher(AccessManager.PERMIT_ALL, mappers);
 | 
			
		||||
			return new DispatcherFilter(dispatcher);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static class TunnelConfiguration {
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public TunnelClient tunnelClient(@Value("${server.port}") int serverPort) {
 | 
			
		||||
			String url = "http://localhost:" + serverPort + "/httptunnel";
 | 
			
		||||
			TunnelConnection connection = new HttpTunnelConnection(url,
 | 
			
		||||
					new SimpleClientHttpRequestFactory());
 | 
			
		||||
			return new TestTunnelClient(0, connection);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		static class TestTunnelClient extends TunnelClient {
 | 
			
		||||
 | 
			
		||||
			private int port;
 | 
			
		||||
 | 
			
		||||
			TestTunnelClient(int listenPort, TunnelConnection tunnelConnection) {
 | 
			
		||||
				super(listenPort, tunnelConnection);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			@Override
 | 
			
		||||
			public int start() throws IOException {
 | 
			
		||||
				this.port = super.start();
 | 
			
		||||
				return this.port;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@RestController
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,6 @@ import org.junit.Before;
 | 
			
		|||
import org.junit.Ignore;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
import org.springframework.web.client.RestTemplate;
 | 
			
		||||
import org.springframework.web.socket.CloseStatus;
 | 
			
		||||
import org.springframework.web.socket.PingMessage;
 | 
			
		||||
| 
						 | 
				
			
			@ -56,14 +55,14 @@ public class LiveReloadServerTests {
 | 
			
		|||
	private static final String HANDSHAKE = "{command: 'hello', "
 | 
			
		||||
			+ "protocols: ['http://livereload.com/protocols/official-7']}";
 | 
			
		||||
 | 
			
		||||
	private int port = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
	private int port;
 | 
			
		||||
 | 
			
		||||
	private MonitoredLiveReloadServer server;
 | 
			
		||||
 | 
			
		||||
	@Before
 | 
			
		||||
	public void setUp() throws Exception {
 | 
			
		||||
		this.server = new MonitoredLiveReloadServer(this.port);
 | 
			
		||||
		this.server.start();
 | 
			
		||||
		this.server = new MonitoredLiveReloadServer(0);
 | 
			
		||||
		this.port = this.server.start();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@After
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
 | 
			
		|||
import org.springframework.boot.test.util.TestPropertyValues;
 | 
			
		||||
import org.springframework.context.annotation.ConditionContext;
 | 
			
		||||
import org.springframework.mock.env.MockEnvironment;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.mockito.BDDMockito.given;
 | 
			
		||||
| 
						 | 
				
			
			@ -39,13 +38,11 @@ import static org.mockito.Mockito.mock;
 | 
			
		|||
 */
 | 
			
		||||
public class LocalDebugPortAvailableConditionTests {
 | 
			
		||||
 | 
			
		||||
	private int port = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
 | 
			
		||||
	private LocalDebugPortAvailableCondition condition = new LocalDebugPortAvailableCondition();
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void portAvailable() throws Exception {
 | 
			
		||||
		ConditionOutcome outcome = getOutcome();
 | 
			
		||||
		ConditionOutcome outcome = getOutcome(0);
 | 
			
		||||
		assertThat(outcome.isMatch()).isTrue();
 | 
			
		||||
		assertThat(outcome.getMessage())
 | 
			
		||||
				.isEqualTo("Local Debug Port Condition found local debug port");
 | 
			
		||||
| 
						 | 
				
			
			@ -53,19 +50,19 @@ public class LocalDebugPortAvailableConditionTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void portInUse() throws Exception {
 | 
			
		||||
		final ServerSocket serverSocket = ServerSocketFactory.getDefault()
 | 
			
		||||
				.createServerSocket(this.port);
 | 
			
		||||
		ConditionOutcome outcome = getOutcome();
 | 
			
		||||
		ServerSocket serverSocket = ServerSocketFactory.getDefault()
 | 
			
		||||
				.createServerSocket(0);
 | 
			
		||||
		ConditionOutcome outcome = getOutcome(serverSocket.getLocalPort());
 | 
			
		||||
		serverSocket.close();
 | 
			
		||||
		assertThat(outcome.isMatch()).isFalse();
 | 
			
		||||
		assertThat(outcome.getMessage())
 | 
			
		||||
				.isEqualTo("Local Debug Port Condition did not find local debug port");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private ConditionOutcome getOutcome() {
 | 
			
		||||
	private ConditionOutcome getOutcome(int port) {
 | 
			
		||||
		MockEnvironment environment = new MockEnvironment();
 | 
			
		||||
		TestPropertyValues.of(
 | 
			
		||||
				"spring.devtools.remote.debug.local-port:" + this.port).applyTo(environment);
 | 
			
		||||
		TestPropertyValues.of("spring.devtools.remote.debug.local-port:" + port)
 | 
			
		||||
				.applyTo(environment);
 | 
			
		||||
		ConditionContext context = mock(ConditionContext.class);
 | 
			
		||||
		given(context.getEnvironment()).willReturn(environment);
 | 
			
		||||
		ConditionOutcome outcome = this.condition.getMatchOutcome(context, null);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,11 +43,11 @@ import org.springframework.boot.test.rule.OutputCapture;
 | 
			
		|||
import org.springframework.boot.test.util.TestPropertyValues;
 | 
			
		||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
 | 
			
		||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.http.server.ServerHttpRequest;
 | 
			
		||||
import org.springframework.http.server.ServerHttpResponse;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.any;
 | 
			
		||||
| 
						 | 
				
			
			@ -73,13 +73,16 @@ public class RemoteClientConfigurationTests {
 | 
			
		|||
 | 
			
		||||
	private AnnotationConfigServletWebServerApplicationContext context;
 | 
			
		||||
 | 
			
		||||
	private static int remotePort = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
	private AnnotationConfigApplicationContext clientContext;
 | 
			
		||||
 | 
			
		||||
	@After
 | 
			
		||||
	public void cleanup() {
 | 
			
		||||
		if (this.context != null) {
 | 
			
		||||
			this.context.close();
 | 
			
		||||
		}
 | 
			
		||||
		if (this.clientContext != null) {
 | 
			
		||||
			this.clientContext.close();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
| 
						 | 
				
			
			@ -114,12 +117,12 @@ public class RemoteClientConfigurationTests {
 | 
			
		|||
		configure();
 | 
			
		||||
		Set<ChangedFiles> changeSet = new HashSet<>();
 | 
			
		||||
		ClassPathChangedEvent event = new ClassPathChangedEvent(this, changeSet, false);
 | 
			
		||||
		this.context.publishEvent(event);
 | 
			
		||||
		LiveReloadConfiguration configuration = this.context
 | 
			
		||||
		this.clientContext.publishEvent(event);
 | 
			
		||||
		LiveReloadConfiguration configuration = this.clientContext
 | 
			
		||||
				.getBean(LiveReloadConfiguration.class);
 | 
			
		||||
		configuration.getExecutor().shutdown();
 | 
			
		||||
		configuration.getExecutor().awaitTermination(2, TimeUnit.SECONDS);
 | 
			
		||||
		LiveReloadServer server = this.context.getBean(LiveReloadServer.class);
 | 
			
		||||
		LiveReloadServer server = this.clientContext.getBean(LiveReloadServer.class);
 | 
			
		||||
		verify(server).triggerReload();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -150,17 +153,24 @@ public class RemoteClientConfigurationTests {
 | 
			
		|||
 | 
			
		||||
	private void configure(String remoteUrl, boolean setSecret, String... pairs) {
 | 
			
		||||
		this.context = new AnnotationConfigServletWebServerApplicationContext();
 | 
			
		||||
		new RestartScopeInitializer().initialize(this.context);
 | 
			
		||||
		this.context.register(Config.class, RemoteClientConfiguration.class);
 | 
			
		||||
		String remoteUrlProperty = "remoteUrl:" + remoteUrl + ":"
 | 
			
		||||
				+ RemoteClientConfigurationTests.remotePort;
 | 
			
		||||
		TestPropertyValues.of(remoteUrlProperty).applyTo(this.context);
 | 
			
		||||
		TestPropertyValues.of(pairs).applyTo(this.context);
 | 
			
		||||
		this.context.register(Config.class);
 | 
			
		||||
		if (setSecret) {
 | 
			
		||||
			TestPropertyValues.of(
 | 
			
		||||
					"spring.devtools.remote.secret:secret").applyTo(this.context);
 | 
			
		||||
			TestPropertyValues.of("spring.devtools.remote.secret:secret")
 | 
			
		||||
					.applyTo(this.context);
 | 
			
		||||
		}
 | 
			
		||||
		this.context.refresh();
 | 
			
		||||
		this.clientContext = new AnnotationConfigApplicationContext();
 | 
			
		||||
		TestPropertyValues.of(pairs).applyTo(this.clientContext);
 | 
			
		||||
		new RestartScopeInitializer().initialize(this.clientContext);
 | 
			
		||||
		this.clientContext.register(ClientConfig.class, RemoteClientConfiguration.class);
 | 
			
		||||
		if (setSecret) {
 | 
			
		||||
			TestPropertyValues.of("spring.devtools.remote.secret:secret")
 | 
			
		||||
					.applyTo(this.clientContext);
 | 
			
		||||
		}
 | 
			
		||||
		String remoteUrlProperty = "remoteUrl:" + remoteUrl + ":"
 | 
			
		||||
				+ this.context.getWebServer().getPort();
 | 
			
		||||
		TestPropertyValues.of(remoteUrlProperty).applyTo(this.clientContext);
 | 
			
		||||
		this.clientContext.refresh();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
| 
						 | 
				
			
			@ -168,12 +178,7 @@ public class RemoteClientConfigurationTests {
 | 
			
		|||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public TomcatServletWebServerFactory tomcat() {
 | 
			
		||||
			return new TomcatServletWebServerFactory(remotePort);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public LiveReloadServer liveReloadServer() {
 | 
			
		||||
			return mock(LiveReloadServer.class);
 | 
			
		||||
			return new TomcatServletWebServerFactory(0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
| 
						 | 
				
			
			@ -191,4 +196,14 @@ public class RemoteClientConfigurationTests {
 | 
			
		|||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	static class ClientConfig {
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public LiveReloadServer liveReloadServer() {
 | 
			
		||||
			return mock(LiveReloadServer.class);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2012-2016 the original author or authors.
 | 
			
		||||
 * Copyright 2012-2017 the original author or authors.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +36,6 @@ import org.springframework.boot.devtools.test.MockClientHttpRequestFactory;
 | 
			
		|||
import org.springframework.boot.devtools.tunnel.client.HttpTunnelConnection.TunnelChannel;
 | 
			
		||||
import org.springframework.boot.test.rule.OutputCapture;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.hamcrest.Matchers.containsString;
 | 
			
		||||
| 
						 | 
				
			
			@ -59,8 +58,6 @@ public class HttpTunnelConnectionTests {
 | 
			
		|||
	@Rule
 | 
			
		||||
	public OutputCapture outputCapture = new OutputCapture();
 | 
			
		||||
 | 
			
		||||
	private int port = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
 | 
			
		||||
	private String url;
 | 
			
		||||
 | 
			
		||||
	private ByteArrayOutputStream incomingData;
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +72,7 @@ public class HttpTunnelConnectionTests {
 | 
			
		|||
	@Before
 | 
			
		||||
	public void setup() {
 | 
			
		||||
		MockitoAnnotations.initMocks(this);
 | 
			
		||||
		this.url = "http://localhost:" + this.port;
 | 
			
		||||
		this.url = "http://localhost:12345";
 | 
			
		||||
		this.incomingData = new ByteArrayOutputStream();
 | 
			
		||||
		this.incomingChannel = Channels.newChannel(this.incomingData);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -164,8 +161,7 @@ public class HttpTunnelConnectionTests {
 | 
			
		|||
		TunnelChannel tunnel = openTunnel(true);
 | 
			
		||||
		assertThat(tunnel.isOpen()).isFalse();
 | 
			
		||||
		this.outputCapture.expect(containsString(
 | 
			
		||||
				"Failed to connect to remote application at http://localhost:"
 | 
			
		||||
						+ this.port));
 | 
			
		||||
				"Failed to connect to remote application at http://localhost:12345"));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void write(TunnelChannel channel, String string) throws IOException {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,8 +29,6 @@ import org.junit.Rule;
 | 
			
		|||
import org.junit.Test;
 | 
			
		||||
import org.junit.rules.ExpectedException;
 | 
			
		||||
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.any;
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,15 +44,13 @@ public class TunnelClientTests {
 | 
			
		|||
	@Rule
 | 
			
		||||
	public ExpectedException thrown = ExpectedException.none();
 | 
			
		||||
 | 
			
		||||
	private int listenPort = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
 | 
			
		||||
	private MockTunnelConnection tunnelConnection = new MockTunnelConnection();
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void listenPortMustBePositive() throws Exception {
 | 
			
		||||
	public void listenPortMustNotBeNegative() throws Exception {
 | 
			
		||||
		this.thrown.expect(IllegalArgumentException.class);
 | 
			
		||||
		this.thrown.expectMessage("ListenPort must be positive");
 | 
			
		||||
		new TunnelClient(0, this.tunnelConnection);
 | 
			
		||||
		this.thrown.expectMessage("ListenPort must be greater than or equal to 0");
 | 
			
		||||
		new TunnelClient(-5, this.tunnelConnection);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
| 
						 | 
				
			
			@ -66,10 +62,9 @@ public class TunnelClientTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void typicalTraffic() throws Exception {
 | 
			
		||||
		TunnelClient client = new TunnelClient(this.listenPort, this.tunnelConnection);
 | 
			
		||||
		client.start();
 | 
			
		||||
		SocketChannel channel = SocketChannel
 | 
			
		||||
				.open(new InetSocketAddress(this.listenPort));
 | 
			
		||||
		TunnelClient client = new TunnelClient(0, this.tunnelConnection);
 | 
			
		||||
		int port = client.start();
 | 
			
		||||
		SocketChannel channel = SocketChannel.open(new InetSocketAddress(port));
 | 
			
		||||
		channel.write(ByteBuffer.wrap("hello".getBytes()));
 | 
			
		||||
		ByteBuffer buffer = ByteBuffer.allocate(5);
 | 
			
		||||
		channel.read(buffer);
 | 
			
		||||
| 
						 | 
				
			
			@ -80,10 +75,9 @@ public class TunnelClientTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void socketChannelClosedTriggersTunnelClose() throws Exception {
 | 
			
		||||
		TunnelClient client = new TunnelClient(this.listenPort, this.tunnelConnection);
 | 
			
		||||
		client.start();
 | 
			
		||||
		SocketChannel channel = SocketChannel
 | 
			
		||||
				.open(new InetSocketAddress(this.listenPort));
 | 
			
		||||
		TunnelClient client = new TunnelClient(0, this.tunnelConnection);
 | 
			
		||||
		int port = client.start();
 | 
			
		||||
		SocketChannel channel = SocketChannel.open(new InetSocketAddress(port));
 | 
			
		||||
		Thread.sleep(200);
 | 
			
		||||
		channel.close();
 | 
			
		||||
		client.getServerThread().stopAcceptingConnections();
 | 
			
		||||
| 
						 | 
				
			
			@ -94,10 +88,9 @@ public class TunnelClientTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void stopTriggersTunnelClose() throws Exception {
 | 
			
		||||
		TunnelClient client = new TunnelClient(this.listenPort, this.tunnelConnection);
 | 
			
		||||
		client.start();
 | 
			
		||||
		SocketChannel channel = SocketChannel
 | 
			
		||||
				.open(new InetSocketAddress(this.listenPort));
 | 
			
		||||
		TunnelClient client = new TunnelClient(0, this.tunnelConnection);
 | 
			
		||||
		int port = client.start();
 | 
			
		||||
		SocketChannel channel = SocketChannel.open(new InetSocketAddress(port));
 | 
			
		||||
		Thread.sleep(200);
 | 
			
		||||
		client.stop();
 | 
			
		||||
		assertThat(this.tunnelConnection.getOpenedTimes()).isEqualTo(1);
 | 
			
		||||
| 
						 | 
				
			
			@ -107,12 +100,11 @@ public class TunnelClientTests {
 | 
			
		|||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void addListener() throws Exception {
 | 
			
		||||
		TunnelClient client = new TunnelClient(this.listenPort, this.tunnelConnection);
 | 
			
		||||
		TunnelClient client = new TunnelClient(0, this.tunnelConnection);
 | 
			
		||||
		TunnelClientListener listener = mock(TunnelClientListener.class);
 | 
			
		||||
		client.addListener(listener);
 | 
			
		||||
		client.start();
 | 
			
		||||
		SocketChannel channel = SocketChannel
 | 
			
		||||
				.open(new InetSocketAddress(this.listenPort));
 | 
			
		||||
		int port = client.start();
 | 
			
		||||
		SocketChannel channel = SocketChannel.open(new InetSocketAddress(port));
 | 
			
		||||
		Thread.sleep(200);
 | 
			
		||||
		channel.close();
 | 
			
		||||
		client.getServerThread().stopAcceptingConnections();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2012-2016 the original author or authors.
 | 
			
		||||
 * Copyright 2012-2017 the original author or authors.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
| 
						 | 
				
			
			@ -27,8 +27,6 @@ import java.nio.channels.SocketChannel;
 | 
			
		|||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.junit.Assert.fail;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,18 +39,14 @@ public class SocketTargetServerConnectionTests {
 | 
			
		|||
 | 
			
		||||
	private static final int DEFAULT_TIMEOUT = 1000;
 | 
			
		||||
 | 
			
		||||
	private int port;
 | 
			
		||||
 | 
			
		||||
	private MockServer server;
 | 
			
		||||
 | 
			
		||||
	private SocketTargetServerConnection connection;
 | 
			
		||||
 | 
			
		||||
	@Before
 | 
			
		||||
	public void setup() throws IOException {
 | 
			
		||||
		this.port = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
		this.server = new MockServer(this.port);
 | 
			
		||||
		StaticPortProvider portProvider = new StaticPortProvider(this.port);
 | 
			
		||||
		this.connection = new SocketTargetServerConnection(portProvider);
 | 
			
		||||
		this.server = new MockServer();
 | 
			
		||||
		this.connection = new SocketTargetServerConnection(() -> this.server.getPort());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
| 
						 | 
				
			
			@ -107,9 +101,13 @@ public class SocketTargetServerConnectionTests {
 | 
			
		|||
 | 
			
		||||
		private ServerThread thread;
 | 
			
		||||
 | 
			
		||||
		MockServer(int port) throws IOException {
 | 
			
		||||
		MockServer() throws IOException {
 | 
			
		||||
			this.serverSocket = ServerSocketChannel.open();
 | 
			
		||||
			this.serverSocket.bind(new InetSocketAddress(port));
 | 
			
		||||
			this.serverSocket.bind(new InetSocketAddress(0));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		int getPort() {
 | 
			
		||||
			return this.serverSocket.socket().getLocalPort();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void delay(int delay) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,13 +17,14 @@
 | 
			
		|||
package org.springframework.boot.devtools.tests;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileReader;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.devtools.RemoteSpringApplication;
 | 
			
		||||
import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm;
 | 
			
		||||
import org.springframework.util.FileCopyUtils;
 | 
			
		||||
import org.springframework.util.FileSystemUtils;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
import org.springframework.util.StringUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -37,14 +38,15 @@ abstract class RemoteApplicationLauncher implements ApplicationLauncher {
 | 
			
		|||
	@Override
 | 
			
		||||
	public LaunchedApplication launchApplication(JvmLauncher javaLauncher)
 | 
			
		||||
			throws Exception {
 | 
			
		||||
		int port = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
		LaunchedJvm applicationJvm = javaLauncher.launch("app",
 | 
			
		||||
				createApplicationClassPath(), "com.example.DevToolsTestApplication",
 | 
			
		||||
				"--server.port=" + port, "--spring.devtools.remote.secret=secret");
 | 
			
		||||
				"--server.port=12345", "--spring.devtools.remote.secret=secret");
 | 
			
		||||
		awaitServerPort(applicationJvm.getStandardOut());
 | 
			
		||||
		LaunchedJvm remoteSpringApplicationJvm = javaLauncher.launch(
 | 
			
		||||
				"remote-spring-application", createRemoteSpringApplicationClassPath(),
 | 
			
		||||
				RemoteSpringApplication.class.getName(),
 | 
			
		||||
				"--spring.devtools.remote.secret=secret", "http://localhost:" + port);
 | 
			
		||||
				"--spring.devtools.remote.secret=secret", "http://localhost:12345");
 | 
			
		||||
		awaitRemoteSpringApplication(remoteSpringApplicationJvm.getStandardOut());
 | 
			
		||||
		return new LaunchedApplication(new File("target/remote"),
 | 
			
		||||
				applicationJvm.getStandardOut(), applicationJvm.getProcess(),
 | 
			
		||||
				remoteSpringApplicationJvm.getProcess());
 | 
			
		||||
| 
						 | 
				
			
			@ -66,4 +68,40 @@ abstract class RemoteApplicationLauncher implements ApplicationLauncher {
 | 
			
		|||
		return StringUtils.collectionToDelimitedString(entries, File.pathSeparator);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private int awaitServerPort(File standardOut) throws Exception {
 | 
			
		||||
		long end = System.currentTimeMillis() + 30000;
 | 
			
		||||
		File serverPortFile = new File("target/server.port");
 | 
			
		||||
		while (serverPortFile.length() == 0) {
 | 
			
		||||
			if (System.currentTimeMillis() > end) {
 | 
			
		||||
				throw new IllegalStateException(String.format(
 | 
			
		||||
						"server.port file was not written within 30 seconds. "
 | 
			
		||||
								+ "Application output:%n%s",
 | 
			
		||||
						FileCopyUtils.copyToString(new FileReader(standardOut))));
 | 
			
		||||
			}
 | 
			
		||||
			Thread.sleep(100);
 | 
			
		||||
		}
 | 
			
		||||
		FileReader portReader = new FileReader(serverPortFile);
 | 
			
		||||
		int port = Integer.valueOf(FileCopyUtils.copyToString(portReader));
 | 
			
		||||
		return port;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void awaitRemoteSpringApplication(File standardOut) throws Exception {
 | 
			
		||||
		long end = System.currentTimeMillis() + 30000;
 | 
			
		||||
		while (!standardOut.exists()) {
 | 
			
		||||
			if (System.currentTimeMillis() > end) {
 | 
			
		||||
				throw new IllegalStateException(
 | 
			
		||||
						"Standard out file was not written " + "within 30 seconds");
 | 
			
		||||
			}
 | 
			
		||||
			Thread.sleep(100);
 | 
			
		||||
		}
 | 
			
		||||
		while (!FileCopyUtils.copyToString(new FileReader(standardOut))
 | 
			
		||||
				.contains("Started RemoteSpringApplication")) {
 | 
			
		||||
			if (System.currentTimeMillis() > end) {
 | 
			
		||||
				throw new IllegalStateException(
 | 
			
		||||
						"RemoteSpringApplication did not start within 30 seconds");
 | 
			
		||||
			}
 | 
			
		||||
			Thread.sleep(100);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 | 
			
		|||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
 | 
			
		||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Sample Application to show Tomcat running two connectors
 | 
			
		||||
| 
						 | 
				
			
			@ -34,11 +33,6 @@ import org.springframework.util.SocketUtils;
 | 
			
		|||
@SpringBootApplication
 | 
			
		||||
public class SampleTomcatTwoConnectorsApplication {
 | 
			
		||||
 | 
			
		||||
	@Bean
 | 
			
		||||
	public Integer port() {
 | 
			
		||||
		return SocketUtils.findAvailableTcpPort();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Bean
 | 
			
		||||
	public ServletWebServerFactory servletContainer() {
 | 
			
		||||
		TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +42,7 @@ public class SampleTomcatTwoConnectorsApplication {
 | 
			
		|||
 | 
			
		||||
	private Connector createStandardConnector() {
 | 
			
		||||
		Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
 | 
			
		||||
		connector.setPort(port());
 | 
			
		||||
		connector.setPort(0);
 | 
			
		||||
		return connector;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,19 +22,26 @@ import java.net.HttpURLConnection;
 | 
			
		|||
import javax.net.ssl.HostnameVerifier;
 | 
			
		||||
import javax.net.ssl.HttpsURLConnection;
 | 
			
		||||
import javax.net.ssl.SSLContext;
 | 
			
		||||
import javax.net.ssl.SSLSession;
 | 
			
		||||
import javax.net.ssl.TrustManager;
 | 
			
		||||
import javax.net.ssl.X509TrustManager;
 | 
			
		||||
 | 
			
		||||
import org.apache.catalina.Service;
 | 
			
		||||
import org.apache.catalina.connector.Connector;
 | 
			
		||||
import org.junit.BeforeClass;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import sample.tomcat.multiconnector.SampleTomcatTwoConnectorsApplicationTests.Ports;
 | 
			
		||||
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 | 
			
		||||
import org.springframework.boot.test.context.TestConfiguration;
 | 
			
		||||
import org.springframework.boot.web.context.WebServerInitializedEvent;
 | 
			
		||||
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
 | 
			
		||||
import org.springframework.boot.web.server.LocalServerPort;
 | 
			
		||||
import org.springframework.context.ApplicationContext;
 | 
			
		||||
import org.springframework.context.ApplicationListener;
 | 
			
		||||
import org.springframework.context.annotation.Import;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
 | 
			
		||||
| 
						 | 
				
			
			@ -53,10 +60,11 @@ import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		|||
@RunWith(SpringRunner.class)
 | 
			
		||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
 | 
			
		||||
@DirtiesContext
 | 
			
		||||
@Import(Ports.class)
 | 
			
		||||
public class SampleTomcatTwoConnectorsApplicationTests {
 | 
			
		||||
 | 
			
		||||
	@LocalServerPort
 | 
			
		||||
	private String port;
 | 
			
		||||
	private int port;
 | 
			
		||||
 | 
			
		||||
	@Autowired
 | 
			
		||||
	private ApplicationContext context;
 | 
			
		||||
| 
						 | 
				
			
			@ -97,27 +105,19 @@ public class SampleTomcatTwoConnectorsApplicationTests {
 | 
			
		|||
	public void testHello() throws Exception {
 | 
			
		||||
		RestTemplate template = new RestTemplate();
 | 
			
		||||
		final MySimpleClientHttpRequestFactory factory = new MySimpleClientHttpRequestFactory(
 | 
			
		||||
				new HostnameVerifier() {
 | 
			
		||||
 | 
			
		||||
					@Override
 | 
			
		||||
					public boolean verify(final String hostname,
 | 
			
		||||
							final SSLSession session) {
 | 
			
		||||
						return true; // these guys are alright by me...
 | 
			
		||||
					}
 | 
			
		||||
				});
 | 
			
		||||
				(hostname, session) -> true);
 | 
			
		||||
		template.setRequestFactory(factory);
 | 
			
		||||
 | 
			
		||||
		Ports ports = this.context.getBean(Ports.class);
 | 
			
		||||
		assertThat(ports.getHttpsPort()).isEqualTo(this.port);
 | 
			
		||||
		assertThat(ports.getHttpPort()).isNotEqualTo(this.port);
 | 
			
		||||
		ResponseEntity<String> entity = template.getForEntity(
 | 
			
		||||
				"http://localhost:" + this.context.getBean("port") + "/hello",
 | 
			
		||||
				String.class);
 | 
			
		||||
				"http://localhost:" + ports.getHttpPort() + "/hello", String.class);
 | 
			
		||||
		assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
 | 
			
		||||
		assertThat(entity.getBody()).isEqualTo("hello");
 | 
			
		||||
 | 
			
		||||
		ResponseEntity<String> httpsEntity = template
 | 
			
		||||
				.getForEntity("https://localhost:" + this.port + "/hello", String.class);
 | 
			
		||||
		assertThat(httpsEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
 | 
			
		||||
		assertThat(httpsEntity.getBody()).isEqualTo("hello");
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -141,4 +141,35 @@ public class SampleTomcatTwoConnectorsApplicationTests {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@TestConfiguration
 | 
			
		||||
	static class Ports implements ApplicationListener<WebServerInitializedEvent> {
 | 
			
		||||
 | 
			
		||||
		private int httpPort;
 | 
			
		||||
 | 
			
		||||
		private int httpsPort;
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void onApplicationEvent(WebServerInitializedEvent event) {
 | 
			
		||||
			Service service = ((TomcatWebServer) event.getWebServer()).getTomcat()
 | 
			
		||||
					.getService();
 | 
			
		||||
			for (Connector connector : service.findConnectors()) {
 | 
			
		||||
				if (connector.getSecure()) {
 | 
			
		||||
					this.httpsPort = connector.getLocalPort();
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					this.httpPort = connector.getLocalPort();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		int getHttpPort() {
 | 
			
		||||
			return this.httpPort;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		int getHttpsPort() {
 | 
			
		||||
			return this.httpsPort;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,13 +37,13 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
 | 
			
		|||
import org.springframework.boot.test.context.SpringBootTest;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 | 
			
		||||
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
 | 
			
		||||
import org.springframework.boot.web.server.LocalServerPort;
 | 
			
		||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
 | 
			
		||||
import org.springframework.context.ConfigurableApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.test.annotation.DirtiesContext;
 | 
			
		||||
import org.springframework.test.context.junit4.SpringRunner;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
import org.springframework.web.socket.client.WebSocketConnectionManager;
 | 
			
		||||
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,20 +51,21 @@ import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		|||
 | 
			
		||||
@RunWith(SpringRunner.class)
 | 
			
		||||
@SpringBootTest(classes = { SampleJettyWebSocketsApplication.class,
 | 
			
		||||
		CustomContainerConfiguration.class }, webEnvironment = WebEnvironment.DEFINED_PORT)
 | 
			
		||||
		CustomContainerConfiguration.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
 | 
			
		||||
@DirtiesContext
 | 
			
		||||
public class CustomContainerWebSocketsApplicationTests {
 | 
			
		||||
 | 
			
		||||
	private static Log logger = LogFactory
 | 
			
		||||
			.getLog(CustomContainerWebSocketsApplicationTests.class);
 | 
			
		||||
 | 
			
		||||
	private static int PORT = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
	@LocalServerPort
 | 
			
		||||
	private int port;
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void echoEndpoint() throws Exception {
 | 
			
		||||
		ConfigurableApplicationContext context = new SpringApplicationBuilder(
 | 
			
		||||
				ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class)
 | 
			
		||||
						.properties("websocket.uri:ws://localhost:" + PORT
 | 
			
		||||
						.properties("websocket.uri:ws://localhost:" + this.port
 | 
			
		||||
								+ "/ws/echo/websocket")
 | 
			
		||||
						.run("--spring.main.web_environment=false");
 | 
			
		||||
		long count = context.getBean(ClientConfiguration.class).latch.getCount();
 | 
			
		||||
| 
						 | 
				
			
			@ -80,8 +81,8 @@ public class CustomContainerWebSocketsApplicationTests {
 | 
			
		|||
	public void reverseEndpoint() throws Exception {
 | 
			
		||||
		ConfigurableApplicationContext context = new SpringApplicationBuilder(
 | 
			
		||||
				ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class)
 | 
			
		||||
						.properties(
 | 
			
		||||
								"websocket.uri:ws://localhost:" + PORT + "/ws/reverse")
 | 
			
		||||
						.properties("websocket.uri:ws://localhost:" + this.port
 | 
			
		||||
								+ "/ws/reverse")
 | 
			
		||||
						.run("--spring.main.web_environment=false");
 | 
			
		||||
		long count = context.getBean(ClientConfiguration.class).latch.getCount();
 | 
			
		||||
		AtomicReference<String> messagePayloadReference = context
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +97,7 @@ public class CustomContainerWebSocketsApplicationTests {
 | 
			
		|||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public ServletWebServerFactory webServerFactory() {
 | 
			
		||||
			return new JettyServletWebServerFactory("/ws", PORT);
 | 
			
		||||
			return new JettyServletWebServerFactory("/ws", 0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,13 +37,13 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
 | 
			
		|||
import org.springframework.boot.test.context.SpringBootTest;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 | 
			
		||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
 | 
			
		||||
import org.springframework.boot.web.server.LocalServerPort;
 | 
			
		||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
 | 
			
		||||
import org.springframework.context.ConfigurableApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.test.annotation.DirtiesContext;
 | 
			
		||||
import org.springframework.test.context.junit4.SpringRunner;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
import org.springframework.web.socket.client.WebSocketConnectionManager;
 | 
			
		||||
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,20 +51,21 @@ import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		|||
 | 
			
		||||
@RunWith(SpringRunner.class)
 | 
			
		||||
@SpringBootTest(classes = { SampleTomcatWebSocketApplication.class,
 | 
			
		||||
		CustomContainerConfiguration.class }, webEnvironment = WebEnvironment.DEFINED_PORT)
 | 
			
		||||
		CustomContainerConfiguration.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
 | 
			
		||||
@DirtiesContext
 | 
			
		||||
public class CustomContainerWebSocketsApplicationTests {
 | 
			
		||||
 | 
			
		||||
	private static Log logger = LogFactory
 | 
			
		||||
			.getLog(CustomContainerWebSocketsApplicationTests.class);
 | 
			
		||||
 | 
			
		||||
	private static int PORT = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
	@LocalServerPort
 | 
			
		||||
	private int port;
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void echoEndpoint() throws Exception {
 | 
			
		||||
		ConfigurableApplicationContext context = new SpringApplicationBuilder(
 | 
			
		||||
				ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class)
 | 
			
		||||
						.properties("websocket.uri:ws://localhost:" + PORT
 | 
			
		||||
						.properties("websocket.uri:ws://localhost:" + this.port
 | 
			
		||||
								+ "/ws/echo/websocket")
 | 
			
		||||
						.run("--spring.main.web_environment=false");
 | 
			
		||||
		long count = context.getBean(ClientConfiguration.class).latch.getCount();
 | 
			
		||||
| 
						 | 
				
			
			@ -80,8 +81,8 @@ public class CustomContainerWebSocketsApplicationTests {
 | 
			
		|||
	public void reverseEndpoint() throws Exception {
 | 
			
		||||
		ConfigurableApplicationContext context = new SpringApplicationBuilder(
 | 
			
		||||
				ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class)
 | 
			
		||||
						.properties(
 | 
			
		||||
								"websocket.uri:ws://localhost:" + PORT + "/ws/reverse")
 | 
			
		||||
						.properties("websocket.uri:ws://localhost:" + this.port
 | 
			
		||||
								+ "/ws/reverse")
 | 
			
		||||
						.run("--spring.main.web_environment=false");
 | 
			
		||||
		long count = context.getBean(ClientConfiguration.class).latch.getCount();
 | 
			
		||||
		AtomicReference<String> messagePayloadReference = context
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +97,7 @@ public class CustomContainerWebSocketsApplicationTests {
 | 
			
		|||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public ServletWebServerFactory webServerFactory() {
 | 
			
		||||
			return new TomcatServletWebServerFactory("/ws", PORT);
 | 
			
		||||
			return new TomcatServletWebServerFactory("/ws", 0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,13 +37,13 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
 | 
			
		|||
import org.springframework.boot.test.context.SpringBootTest;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 | 
			
		||||
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
 | 
			
		||||
import org.springframework.boot.web.server.LocalServerPort;
 | 
			
		||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
 | 
			
		||||
import org.springframework.context.ConfigurableApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.test.annotation.DirtiesContext;
 | 
			
		||||
import org.springframework.test.context.junit4.SpringRunner;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
import org.springframework.web.socket.client.WebSocketConnectionManager;
 | 
			
		||||
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,20 +51,21 @@ import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		|||
 | 
			
		||||
@RunWith(SpringRunner.class)
 | 
			
		||||
@SpringBootTest(classes = { SampleUndertowWebSocketsApplication.class,
 | 
			
		||||
		CustomContainerConfiguration.class }, webEnvironment = WebEnvironment.DEFINED_PORT)
 | 
			
		||||
		CustomContainerConfiguration.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
 | 
			
		||||
@DirtiesContext
 | 
			
		||||
public class CustomContainerWebSocketsApplicationTests {
 | 
			
		||||
 | 
			
		||||
	private static Log logger = LogFactory
 | 
			
		||||
			.getLog(CustomContainerWebSocketsApplicationTests.class);
 | 
			
		||||
 | 
			
		||||
	private static int PORT = SocketUtils.findAvailableTcpPort();
 | 
			
		||||
	@LocalServerPort
 | 
			
		||||
	private int port;
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void echoEndpoint() throws Exception {
 | 
			
		||||
		ConfigurableApplicationContext context = new SpringApplicationBuilder(
 | 
			
		||||
				ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class)
 | 
			
		||||
						.properties("websocket.uri:ws://localhost:" + PORT
 | 
			
		||||
						.properties("websocket.uri:ws://localhost:" + this.port
 | 
			
		||||
								+ "/ws/echo/websocket")
 | 
			
		||||
						.run("--spring.main.web_environment=false");
 | 
			
		||||
		long count = context.getBean(ClientConfiguration.class).latch.getCount();
 | 
			
		||||
| 
						 | 
				
			
			@ -80,8 +81,8 @@ public class CustomContainerWebSocketsApplicationTests {
 | 
			
		|||
	public void reverseEndpoint() throws Exception {
 | 
			
		||||
		ConfigurableApplicationContext context = new SpringApplicationBuilder(
 | 
			
		||||
				ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class)
 | 
			
		||||
						.properties(
 | 
			
		||||
								"websocket.uri:ws://localhost:" + PORT + "/ws/reverse")
 | 
			
		||||
						.properties("websocket.uri:ws://localhost:" + this.port
 | 
			
		||||
								+ "/ws/reverse")
 | 
			
		||||
						.run("--spring.main.web_environment=false");
 | 
			
		||||
		long count = context.getBean(ClientConfiguration.class).latch.getCount();
 | 
			
		||||
		AtomicReference<String> messagePayloadReference = context
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +97,7 @@ public class CustomContainerWebSocketsApplicationTests {
 | 
			
		|||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public ServletWebServerFactory webServerFactory() {
 | 
			
		||||
			return new UndertowServletWebServerFactory("/ws", PORT);
 | 
			
		||||
			return new UndertowServletWebServerFactory("/ws", 0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,7 +54,6 @@ import org.springframework.boot.web.server.WebServerException;
 | 
			
		|||
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory;
 | 
			
		||||
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests;
 | 
			
		||||
import org.springframework.test.util.ReflectionTestUtils;
 | 
			
		||||
import org.springframework.util.SocketUtils;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.junit.Assert.fail;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +91,7 @@ public class TomcatServletWebServerFactoryTests
 | 
			
		|||
	public void tomcatEngineNames() throws Exception {
 | 
			
		||||
		TomcatServletWebServerFactory factory = getFactory();
 | 
			
		||||
		this.webServer = factory.getWebServer();
 | 
			
		||||
		factory.setPort(SocketUtils.findAvailableTcpPort(40000));
 | 
			
		||||
		factory.setPort(0);
 | 
			
		||||
		TomcatWebServer tomcatWebServer = (TomcatWebServer) factory.getWebServer();
 | 
			
		||||
		// Make sure that the names are different
 | 
			
		||||
		String firstName = ((TomcatWebServer) this.webServer).getTomcat().getEngine()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue