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:
Trustin Lee 2014-10-17 15:01:51 +09:00
parent e1787e6876
commit d63413754e

View File

@ -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.
* *