From 9e00669b4604d31299d309ad22116d352acae10f Mon Sep 17 00:00:00 2001 From: rjung Date: Sun, 12 Jun 2011 15:47:53 +0000 Subject: [PATCH] Fix unit test for bindOnInit. Test failed when Java was binding sockets using IPv4 and APR using IPv6. Since the connector uses APR, and the test socket Java, both could bind at the same time. Observed on Solaris 10 Sparc. Fixed by also uding APR to bind the test socket. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1134938 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/tomcat/util/net/TestXxxEndpoint.java | 133 +++++++++++++++++++-- webapps/docs/changelog.xml | 14 +++ 2 files changed, 135 insertions(+), 12 deletions(-) diff --git a/test/org/apache/tomcat/util/net/TestXxxEndpoint.java b/test/org/apache/tomcat/util/net/TestXxxEndpoint.java index 208f89fa6..ea9512663 100644 --- a/test/org/apache/tomcat/util/net/TestXxxEndpoint.java +++ b/test/org/apache/tomcat/util/net/TestXxxEndpoint.java @@ -24,12 +24,94 @@ import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; + +import org.apache.tomcat.jni.Address; +import org.apache.tomcat.jni.Error; +import org.apache.tomcat.jni.Library; +import org.apache.tomcat.jni.OS; +import org.apache.tomcat.jni.Pool; +import org.apache.tomcat.jni.Socket; + /** * Test case for the Endpoint implementations. The testing framework will ensure * that each implementation is tested. */ public class TestXxxEndpoint extends TomcatBaseTest { + private static Log log = LogFactory.getLog(TestXxxEndpoint.class); + + private long createAprPool() { + + // Create the pool for the server socket + try { + return Pool.create(0); + } catch (UnsatisfiedLinkError e) { + log.error("Could not create socket pool", e); + return 0; + } + } + + private long createAprSocket(int port, long pool) + throws Exception { + /** + * Server socket "pointer". + */ + long serverSock = 0; + + String address = null; + // Create the APR address that will be bound + int family = Socket.APR_INET; + if (Library.APR_HAVE_IPV6) { + if (address == null) { + if (!OS.IS_BSD && !OS.IS_WIN32 && !OS.IS_WIN64) + family = Socket.APR_UNSPEC; + } else if (address.indexOf(':') >= 0) { + family = Socket.APR_UNSPEC; + } + } + + long inetAddress = 0; + try { + inetAddress = Address.info(address, family, + port, 0, pool); + // Create the APR server socket + serverSock = Socket.create(Address.getInfo(inetAddress).family, + Socket.SOCK_STREAM, + Socket.APR_PROTO_TCP, pool); + } catch (Exception ex) { + log.error("Could not create socket for address '" + address + "'"); + return 0; + } + + if (OS.IS_UNIX) { + Socket.optSet(serverSock, Socket.APR_SO_REUSEADDR, 1); + } + // Deal with the firewalls that tend to drop the inactive sockets + Socket.optSet(serverSock, Socket.APR_SO_KEEPALIVE, 1); + // Bind the server socket + int ret = Socket.bind(serverSock, inetAddress); + if (ret != 0) { + log.error("Could not bind: " + Error.strerror(ret)); + throw (new Exception(Error.strerror(ret))); + } + return serverSock; + } + + private void destroyAprSocket(long serverSock, long pool) { + if (serverSock != 0) { + Socket.shutdown(serverSock, Socket.APR_SHUTDOWN_READWRITE); + Socket.close(serverSock); + Socket.destroy(serverSock); + } + + if (pool != 0) { + Pool.destroy(pool); + pool = 0; + } + } + public void testStartStopBindOnInit() throws Exception { Tomcat tomcat = getTomcatInstance(); File appDir = new File(getBuildDirectory(), "webapps/examples"); @@ -40,19 +122,34 @@ public class TestXxxEndpoint extends TomcatBaseTest { tomcat.start(); tomcat.getConnector().stop(); - // This should throw an Exception Exception e = null; ServerSocket s = null; + long pool = 0; + long nativeSocket = 0; + boolean isApr = tomcat.getConnector().getProtocolHandlerClassName().contains("Apr"); try { - s = new ServerSocket(port); + // This should throw an Exception + if (isApr) { + pool = createAprPool(); + assertTrue(pool != 0); + nativeSocket = createAprSocket(port, pool); + assertTrue(nativeSocket != 0); + } else { + s = new ServerSocket(port); + } } catch (Exception e1) { e = e1; } finally { - if (s != null) { - try { + try { + if (isApr) { + destroyAprSocket(nativeSocket, pool); + } else if (s != null) { s.close(); - } catch (Exception e2) { /* Ignore */ } - } + } + } catch (Exception e2) { /* Ignore */ } + } + if (e != null) { + log.info("Exception was", e); } assertNotNull(e); tomcat.getConnector().start(); @@ -71,19 +168,31 @@ public class TestXxxEndpoint extends TomcatBaseTest { tomcat.start(); tomcat.getConnector().stop(); - // This should not throw an Exception Exception e = null; ServerSocket s = null; + long pool = 0; + long nativeSocket = 0; + boolean isApr = tomcat.getConnector().getProtocolHandlerClassName().contains("Apr"); try { - s = new ServerSocket(port); + // This should not throw an Exception + if (isApr) { + pool = createAprPool(); + assertTrue(pool != 0); + nativeSocket = createAprSocket(port, pool); + assertTrue(nativeSocket != 0); + } else { + s = new ServerSocket(port); + } } catch (Exception e1) { e = e1; } finally { - if (s != null) { - try { + try { + if (isApr) { + destroyAprSocket(nativeSocket, pool); + } else if (s != null) { s.close(); - } catch (Exception e2) { /* Ignore */ } - } + } + } catch (Exception e2) { /* Ignore */ } } assertNull(e); tomcat.getConnector().start(); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index a71172300..edd485ec4 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -42,6 +42,20 @@ General, Catalina, Coyote, Jasper, Cluster, Web applications, Extras, Tribes, Other --> +
+ + + + + + + + Fix unit test for bindOnInit which was failing for APR on some platforms. + (rjung) + + + +
-- 2.11.0