Make TestUtils.getFreePort() check both TCP and UDP
Motivation: We see occational failures in the datagram tests saying 'address already in use' when we attempt to bind on a port returned by TestUtils.getFreePort(). It turns out that TestUtils.getFreePort() only checks if TCP port is available. Modifications: Also check if UDP port is available, so that the datagram tests do not fail because of the 'address already in use' error during a bind attempt. Result: Less chance of datagram test failures
This commit is contained in:
parent
e1787e6876
commit
d63413754e
@ -19,6 +19,7 @@ import io.netty.util.NetUtil;
|
|||||||
import org.junit.rules.TestName;
|
import org.junit.rules.TestName;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.nio.channels.Channel;
|
import java.nio.channels.Channel;
|
||||||
@ -58,29 +59,66 @@ public final class TestUtils {
|
|||||||
*/
|
*/
|
||||||
public static int getFreePort() {
|
public static int getFreePort() {
|
||||||
for (int i = 0; i < NUM_CANDIDATES; i ++) {
|
for (int i = 0; i < NUM_CANDIDATES; i ++) {
|
||||||
int port = nextCandidatePort();
|
final int port = nextCandidatePort();
|
||||||
try {
|
final InetSocketAddress wildcardAddr = new InetSocketAddress(port);
|
||||||
// Ensure it is possible to bind on both wildcard and loopback.
|
final InetSocketAddress loopbackAddr = new InetSocketAddress(NetUtil.LOCALHOST4, port);
|
||||||
ServerSocket ss;
|
|
||||||
ss = new ServerSocket();
|
|
||||||
ss.setReuseAddress(false);
|
|
||||||
ss.bind(new InetSocketAddress(port));
|
|
||||||
ss.close();
|
|
||||||
|
|
||||||
ss = new ServerSocket();
|
|
||||||
ss.setReuseAddress(false);
|
|
||||||
ss.bind(new InetSocketAddress(NetUtil.LOCALHOST, port));
|
|
||||||
ss.close();
|
|
||||||
|
|
||||||
|
// Ensure it is possible to bind on wildcard/loopback and tcp/udp.
|
||||||
|
if (isTcpPortAvailable(wildcardAddr) &&
|
||||||
|
isTcpPortAvailable(loopbackAddr) &&
|
||||||
|
isUdpPortAvailable(wildcardAddr) &&
|
||||||
|
isUdpPortAvailable(loopbackAddr)) {
|
||||||
return port;
|
return port;
|
||||||
} catch (IOException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException("unable to find a free port");
|
throw new RuntimeException("unable to find a free port");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isTcpPortAvailable(InetSocketAddress localAddress) {
|
||||||
|
ServerSocket ss = null;
|
||||||
|
try {
|
||||||
|
ss = new ServerSocket();
|
||||||
|
ss.setReuseAddress(false);
|
||||||
|
ss.bind(localAddress);
|
||||||
|
ss.close();
|
||||||
|
ss = null;
|
||||||
|
return true;
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
// Unavailable
|
||||||
|
} finally {
|
||||||
|
if (ss != null) {
|
||||||
|
try {
|
||||||
|
ss.close();
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isUdpPortAvailable(InetSocketAddress localAddress) {
|
||||||
|
DatagramSocket ds = null;
|
||||||
|
try {
|
||||||
|
ds = new DatagramSocket(null);
|
||||||
|
ds.setReuseAddress(false);
|
||||||
|
ds.bind(localAddress);
|
||||||
|
ds.close();
|
||||||
|
ds = null;
|
||||||
|
return true;
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
// Unavailable
|
||||||
|
} finally {
|
||||||
|
if (ds != null) {
|
||||||
|
ds.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return {@code true} if SCTP is supported by the running os.
|
* Return {@code true} if SCTP is supported by the running os.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user