This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new 7cdebe9eaa Make test more robust
7cdebe9eaa is described below

commit 7cdebe9eaa60455bbe2922fb013b9834802b2a9a
Author: Mark Thomas <[email protected]>
AuthorDate: Sat Nov 7 17:40:44 2026 +0000

    Make test more robust
    
    Co-authored by: Claude / Sonnet 5.5
---
 test/org/apache/catalina/tribes/TesterUtil.java    |  6 +--
 .../tribes/membership/TestMcastService.java        | 50 ++++++++++++++--------
 2 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/test/org/apache/catalina/tribes/TesterUtil.java 
b/test/org/apache/catalina/tribes/TesterUtil.java
index 6b7dc256ff..b76e48f914 100644
--- a/test/org/apache/catalina/tribes/TesterUtil.java
+++ b/test/org/apache/catalina/tribes/TesterUtil.java
@@ -18,7 +18,6 @@ package org.apache.catalina.tribes;
 
 import java.io.IOException;
 import java.net.DatagramPacket;
-import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.MulticastSocket;
@@ -40,12 +39,13 @@ public class TesterUtil {
 
 
     /*
-     * Returns a UDP port that was free on the loopback interface when it was 
checked. Only for ports, such as a
+     * Returns a UDP port that was free on the wildcard address (the address 
McastService binds to) when it was
+     * checked. Only for ports, such as a
      * multicast group port, that cannot be left to the operating system 
because every member needs to know it in
      * advance. There is a small window in which another process may take the 
port before the caller binds it.
      */
     public static int getFreeUdpPort() throws IOException {
-        try (DatagramSocket socket = new DatagramSocket(0, 
InetAddress.getLoopbackAddress())) {
+        try (MulticastSocket socket = new MulticastSocket(0)) {
             return socket.getLocalPort();
         }
     }
diff --git a/test/org/apache/catalina/tribes/membership/TestMcastService.java 
b/test/org/apache/catalina/tribes/membership/TestMcastService.java
index 1aada231b6..5074812086 100644
--- a/test/org/apache/catalina/tribes/membership/TestMcastService.java
+++ b/test/org/apache/catalina/tribes/membership/TestMcastService.java
@@ -17,6 +17,7 @@
 package org.apache.catalina.tribes.membership;
 
 import java.io.ByteArrayInputStream;
+import java.net.BindException;
 import java.util.Properties;
 
 import org.junit.Assert;
@@ -31,6 +32,35 @@ import org.apache.catalina.tribes.io.XByteBuffer;
 
 public class TestMcastService {
 
+    private static final int MAX_START_ATTEMPTS = 5;
+
+    /*
+     * The multicast port has to be known in advance so it cannot be left to 
the operating system. That leaves a window
+     * between finding a free port and the service binding it in which 
something else may take it. If that happens,
+     * pick another port and try again.
+     */
+    private static McastService startService(Properties props) throws 
Exception {
+        BindException lastFailure = null;
+        for (int attempt = 0; attempt < MAX_START_ATTEMPTS; attempt++) {
+            props.setProperty("mcastPort", 
String.valueOf(TesterUtil.getFreeUdpPort()));
+
+            GroupChannel channel = new GroupChannel();
+            channel.setName("TestMcastService-" + System.nanoTime());
+
+            McastService service = new McastService();
+            service.setChannel(channel);
+            service.setProperties(props);
+            try {
+                service.start(Channel.MBR_TX_SEQ);
+                return service;
+            } catch (BindException e) {
+                lastFailure = e;
+            }
+        }
+        throw lastFailure;
+    }
+
+
     /*
      * The shutdown message that stop() broadcasts routinely fails when the 
network device is down or the socket is
      * already broken. That must not skip leaving the multicast group and 
closing the socket, nor prevent the service
@@ -38,10 +68,8 @@ public class TestMcastService {
      */
     @Test(timeout = 60000)
     public void testStopWithFailingShutdownSendCompletes() throws Exception {
-        int mcastPort = TesterUtil.getFreeUdpPort();
         StringBuilder properties = new StringBuilder();
         properties.append("mcastAddress=228.0.0.4\n");
-        properties.append("mcastPort=").append(mcastPort).append("\n");
         properties.append("tcpListenHost=127.0.0.1\n");
         properties.append("tcpListenPort=").append(0).append("\n");
         properties.append("tcpSecurePort=0\n");
@@ -52,15 +80,9 @@ public class TestMcastService {
         properties.append("recoveryCounter=10\n");
         properties.append("recoverySleepTime=3000\n");
 
-        GroupChannel channel = new GroupChannel();
-        channel.setName("TestMcastService-" + System.nanoTime());
-
-        McastService service = new McastService();
-        service.setChannel(channel);
         Properties props = new Properties();
         props.load(new 
ByteArrayInputStream(properties.toString().getBytes("UTF-8")));
-        service.setProperties(props);
-        service.start(Channel.MBR_TX_SEQ);
+        McastService service = startService(props);
 
         McastServiceImpl impl = service.impl;
         Assert.assertNotNull(impl);
@@ -168,10 +190,8 @@ public class TestMcastService {
      */
     @Test(timeout = 60000)
     public void testBroadcastRejectsPacketsTheSocketCannotCarry() throws 
Exception {
-        int mcastPort = TesterUtil.getFreeUdpPort();
         Properties props = new Properties();
         props.setProperty("mcastAddress", "228.0.0.4");
-        props.setProperty("mcastPort", String.valueOf(mcastPort));
         props.setProperty("tcpListenHost", "127.0.0.1");
         props.setProperty("tcpListenPort", "0");
         props.setProperty("tcpSecurePort", "0");
@@ -182,13 +202,7 @@ public class TestMcastService {
         props.setProperty("recoveryCounter", "10");
         props.setProperty("recoverySleepTime", "3000");
 
-        GroupChannel channel = new GroupChannel();
-        channel.setName("TestMcastService-" + System.nanoTime());
-
-        McastService service = new McastService();
-        service.setChannel(channel);
-        service.setProperties(props);
-        service.start(Channel.MBR_TX_SEQ);
+        McastService service = startService(props);
         try {
             // Build a packet just above the sendable size but still within 
the 65535 byte packet
             // limit the old check used, and small enough for this platform to 
actually send


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to