Fix unit test for bindOnInit.
authorrjung <rjung@13f79535-47bb-0310-9956-ffa450edef68>
Sun, 12 Jun 2011 15:47:53 +0000 (15:47 +0000)
committerrjung <rjung@13f79535-47bb-0310-9956-ffa450edef68>
Sun, 12 Jun 2011 15:47:53 +0000 (15:47 +0000)
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

test/org/apache/tomcat/util/net/TestXxxEndpoint.java
webapps/docs/changelog.xml

index 208f89f..ea95126 100644 (file)
@@ -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();
index a711723..edd485e 100644 (file)
   General, Catalina, Coyote, Jasper, Cluster, Web applications, Extras, Tribes,
   Other
 -->
+<section name="Tomcat 7.0.17 (markt)">
+  <subsection name="Catalina">
+    <changelog>
+    </changelog>
+  </subsection>
+  <subsection name="Coyote">
+    <changelog>
+      <fix>
+        Fix unit test for bindOnInit which was failing for APR on some platforms.
+        (rjung)
+      </fix>
+    </changelog>
+  </subsection>
+</section>
 <section name="Tomcat 7.0.16 (markt)">
   <subsection name="Catalina">
     <changelog>