From 342c1e903c109b10080e41be18d8562df93556f6 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <902768+bizybot@users.noreply.github.com> Date: Thu, 4 Oct 2018 08:23:59 +1000 Subject: [PATCH] [TESTS] Set SO_LINGER and SO_REUSEADDR on the mock socket (#34211) In SessionFactoryLoadBalancingTests#testRoundRobinWithFailures() we kill ldap servers randomly and immediately bind to that port connecting to mock server socket. This is done to avoid someone else listening to this port. As the creation of mock socket and binding to the port is immediate, sometimes the earlier socket would be in TIME_WAIT state thereby having problems with either bind or connect. This commit sets the SO_REUSEADDR explicitly to true and also sets the linger on time to 0(as we are not writing any data) so as to allow re-use of the port and close immediately. Note: I could not find other places where this might be problematic but looking at test runs and netstat output I do see lot of sockets in TIME_WAIT. If we find that this needs to be addressed we can wrap ServerSocketFactory to set these options and use that with in memory ldap server configuration during tests. Closes #32190 --- .../SessionFactoryLoadBalancingTests.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactoryLoadBalancingTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactoryLoadBalancingTests.java index 1a9a5b4d56e63..f8bfa241736b9 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactoryLoadBalancingTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/support/SessionFactoryLoadBalancingTests.java @@ -8,6 +8,7 @@ import com.unboundid.ldap.listener.InMemoryDirectoryServer; import com.unboundid.ldap.sdk.LDAPConnection; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.common.SuppressForbidden; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; @@ -17,6 +18,7 @@ import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.xpack.core.common.socket.SocketAccess; import org.elasticsearch.xpack.core.security.authc.RealmConfig; import org.elasticsearch.xpack.core.security.authc.ldap.support.LdapSearchScope; import org.elasticsearch.xpack.core.ssl.SSLService; @@ -25,6 +27,7 @@ import java.io.IOException; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.Socket; import java.util.ArrayList; import java.util.Arrays; @@ -112,7 +115,7 @@ public void testRoundRobinWithFailures() throws Exception { // of the ldap server and the opening of the socket logger.debug("opening mock server socket listening on [{}]", port); Runnable runnable = () -> { - try (Socket socket = new MockSocket(InetAddress.getByName("localhost"), mockServerSocket.getLocalPort(), local, port)) { + try (Socket socket = openMockSocket(local, mockServerSocket.getLocalPort(), local, port)) { logger.debug("opened socket [{}]", socket); latch.countDown(); closeLatch.await(); @@ -149,6 +152,17 @@ public void testRoundRobinWithFailures() throws Exception { } } + @SuppressForbidden(reason = "Allow opening socket for test") + private MockSocket openMockSocket(InetAddress remoteAddress, int remotePort, InetAddress localAddress, int localPort) + throws IOException { + final MockSocket socket = new MockSocket(); + socket.setReuseAddress(true); // allow binding even if the previous socket is in timed wait state. + socket.setSoLinger(true, 0); // close immediately as we are not writing anything here. + socket.bind(new InetSocketAddress(localAddress, localPort)); + SocketAccess.doPrivileged(() -> socket.connect(new InetSocketAddress(localAddress, remotePort))); + return socket; + } + public void testFailover() throws Exception { assumeTrue("at least one ldap server should be present for this test", ldapServers.length > 1); logger.debug("using [{}] ldap servers, urls {}", ldapServers.length, ldapUrls());