|
|
|
@ -22,11 +22,9 @@ import java.util.Random; |
|
|
|
|
|
|
|
|
|
|
|
import javax.net.ServerSocketFactory; |
|
|
|
import javax.net.ServerSocketFactory; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.util.Assert; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Simple utility methods for finding available ports on {@code localhost} for |
|
|
|
* Simple utility for finding available TCP ports on {@code localhost} for use in |
|
|
|
* use in integration testing scenarios. |
|
|
|
* integration testing scenarios. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>{@code SocketUtils} was removed from the public API in {@code spring-core} |
|
|
|
* <p>{@code SocketUtils} was removed from the public API in {@code spring-core} |
|
|
|
* in Spring Framework 6.0 and reintroduced as {@code TestSocketUtils}, which is |
|
|
|
* in Spring Framework 6.0 and reintroduced as {@code TestSocketUtils}, which is |
|
|
|
@ -47,59 +45,42 @@ import org.springframework.util.Assert; |
|
|
|
* @author Arjen Poutsma |
|
|
|
* @author Arjen Poutsma |
|
|
|
* @author Gunnar Hillert |
|
|
|
* @author Gunnar Hillert |
|
|
|
* @author Gary Russell |
|
|
|
* @author Gary Russell |
|
|
|
* @since 4.0 |
|
|
|
* @since 6.0 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public abstract class TestSocketUtils { |
|
|
|
public abstract class TestSocketUtils { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* The default minimum value for port ranges used when finding an available |
|
|
|
* The minimum value for port ranges used when finding an available TCP port. |
|
|
|
* socket port. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private static final int PORT_RANGE_MIN = 1024; |
|
|
|
private static final int PORT_RANGE_MIN = 1024; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* The default maximum value for port ranges used when finding an available |
|
|
|
* The maximum value for port ranges used when finding an available TCP port. |
|
|
|
* socket port. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private static final int PORT_RANGE_MAX = 65535; |
|
|
|
private static final int PORT_RANGE_MAX = 65535; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final int PORT_RANGE = PORT_RANGE_MAX - PORT_RANGE_MIN; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final int MAX_ATTEMPTS = 1_000; |
|
|
|
|
|
|
|
|
|
|
|
private static final Random random = new Random(System.nanoTime()); |
|
|
|
private static final Random random = new Random(System.nanoTime()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Find an available TCP port randomly selected from the range |
|
|
|
* Find an available TCP port randomly selected from the range [1024, 65535]. |
|
|
|
* [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. |
|
|
|
|
|
|
|
* @return an available TCP port number |
|
|
|
* @return an available TCP port number |
|
|
|
* @throws IllegalStateException if no available port could be found |
|
|
|
* @throws IllegalStateException if no available port could be found |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public static int findAvailableTcpPort() { |
|
|
|
public static int findAvailableTcpPort() { |
|
|
|
return findAvailablePort(PORT_RANGE_MIN, PORT_RANGE_MAX); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Find an available port for this {@code SocketType}, randomly selected |
|
|
|
|
|
|
|
* from the range [{@code minPort}, {@code maxPort}]. |
|
|
|
|
|
|
|
* @param minPort the minimum port number |
|
|
|
|
|
|
|
* @param maxPort the maximum port number |
|
|
|
|
|
|
|
* @return an available port number for this socket type |
|
|
|
|
|
|
|
* @throws IllegalStateException if no available port could be found |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private static int findAvailablePort(int minPort, int maxPort) { |
|
|
|
|
|
|
|
Assert.isTrue(minPort > 0, "'minPort' must be greater than 0"); |
|
|
|
|
|
|
|
Assert.isTrue(maxPort >= minPort, "'maxPort' must be greater than or equal to 'minPort'"); |
|
|
|
|
|
|
|
Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to " + PORT_RANGE_MAX); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int portRange = maxPort - minPort; |
|
|
|
|
|
|
|
int candidatePort; |
|
|
|
int candidatePort; |
|
|
|
int searchCounter = 0; |
|
|
|
int searchCounter = 0; |
|
|
|
do { |
|
|
|
do { |
|
|
|
if (searchCounter > portRange) { |
|
|
|
if (searchCounter > MAX_ATTEMPTS) { |
|
|
|
throw new IllegalStateException(String.format( |
|
|
|
throw new IllegalStateException(String.format( |
|
|
|
"Could not find an available TCP port in the range [%d, %d] after %d attempts", |
|
|
|
"Could not find an available TCP port in the range [%d, %d] after %d attempts", |
|
|
|
minPort, maxPort, searchCounter)); |
|
|
|
PORT_RANGE_MIN, PORT_RANGE_MAX, MAX_ATTEMPTS)); |
|
|
|
} |
|
|
|
} |
|
|
|
candidatePort = findRandomPort(minPort, maxPort); |
|
|
|
candidatePort = PORT_RANGE_MIN + random.nextInt(PORT_RANGE + 1); |
|
|
|
searchCounter++; |
|
|
|
searchCounter++; |
|
|
|
} |
|
|
|
} |
|
|
|
while (!isPortAvailable(candidatePort)); |
|
|
|
while (!isPortAvailable(candidatePort)); |
|
|
|
@ -108,20 +89,7 @@ public abstract class TestSocketUtils { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Find a pseudo-random port number within the range |
|
|
|
* Determine if the specified TCP port is currently available on {@code localhost}. |
|
|
|
* [{@code minPort}, {@code maxPort}]. |
|
|
|
|
|
|
|
* @param minPort the minimum port number |
|
|
|
|
|
|
|
* @param maxPort the maximum port number |
|
|
|
|
|
|
|
* @return a random port number within the specified range |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private static int findRandomPort(int minPort, int maxPort) { |
|
|
|
|
|
|
|
int portRange = maxPort - minPort; |
|
|
|
|
|
|
|
return minPort + random.nextInt(portRange + 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Determine if the specified port for this {@code SocketType} is |
|
|
|
|
|
|
|
* currently available on {@code localhost}. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private static boolean isPortAvailable(int port) { |
|
|
|
private static boolean isPortAvailable(int port) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
|