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

zhfeng pushed a commit to branch 3.8.x
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit 532ebde6edfd4705247a2532b8ec8d3e87236878
Author: James Netherton <jamesnether...@gmail.com>
AuthorDate: Thu Sep 19 12:58:42 2024 +0100

    Avoid UDP port clashes in tests
    
    Fixes #6489
---
 .../camel/quarkus/test/AvailablePortFinder.java    | 64 ++++++++++++++++++----
 .../component/netty/udp/NettyUdpTestResource.java  |  2 +
 .../component/syslog/it/SyslogTestResource.java    |  3 +-
 3 files changed, 57 insertions(+), 12 deletions(-)

diff --git 
a/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/AvailablePortFinder.java
 
b/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/AvailablePortFinder.java
index 4fce970396..c125c45d20 100644
--- 
a/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/AvailablePortFinder.java
+++ 
b/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/AvailablePortFinder.java
@@ -17,8 +17,7 @@
 package org.apache.camel.quarkus.test;
 
 import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
+import java.net.DatagramSocket;
 import java.net.ServerSocket;
 import java.util.HashMap;
 import java.util.Map;
@@ -51,22 +50,30 @@ public final class AvailablePortFinder {
     }
 
     /**
-     * Gets the next available port.
+     * Gets the next available TCP port.
      *
      * @throws IllegalStateException if there are no ports available
      * @return                       the available port
      */
     public static int getNextAvailable() {
+        return getNextAvailable(Protocol.TCP);
+    }
+
+    /**
+     * Gets the next available port for the given protocol.
+     *
+     * @param  protocol              the network protocol to reserve the port 
for. Either TCP or UDP
+     * @throws IllegalStateException if there are no ports available
+     * @return                       the available port
+     */
+    public static int getNextAvailable(Protocol protocol) {
         // Using AvailablePortFinder in native applications can be problematic
         // E.g The reserved port may be allocated at build time and preserved 
indefinitely at runtime. I.e it never changes on each execution of the native 
application
         logWarningIfNativeApplication();
 
         while (true) {
-            try (ServerSocket ss = new ServerSocket()) {
-                ss.setReuseAddress(true);
-                ss.bind(new InetSocketAddress((InetAddress) null, 0), 1);
-
-                int port = ss.getLocalPort();
+            try {
+                int port = protocol.getPort();
                 if (!isQuarkusReservedPort(port)) {
                     String callerClassName = getCallerClassName();
                     String value = RESERVED_PORTS.putIfAbsent(port, 
callerClassName);
@@ -82,20 +89,34 @@ public final class AvailablePortFinder {
     }
 
     /**
-     * Reserve a list of random and not in use network ports and place them in 
Map.
+     * Reserve a list of random and not in use TCP network ports and places 
them in Map.
      */
     public static Map<String, Integer> reserveNetworkPorts(String... names) {
         return reserveNetworkPorts(Function.identity(), names);
     }
 
     /**
-     * Reserve a list of random and not in use network ports and place them in 
Map.
+     * Reserve a list of random and not in use network ports for the given 
protocol and places them in Map.
+     */
+    public static Map<String, Integer> reserveNetworkPorts(Protocol protocol, 
String... names) {
+        return reserveNetworkPorts(protocol, Function.identity(), names);
+    }
+
+    /**
+     * Reserve a list of random and not in use TCP network ports and places 
them in Map.
      */
     public static <T> Map<String, T> reserveNetworkPorts(Function<Integer, T> 
converter, String... names) {
+        return reserveNetworkPorts(Protocol.TCP, converter, names);
+    }
+
+    /**
+     * Reserve a list of random and not in use network ports for the given 
protocol and places them in Map.
+     */
+    public static <T> Map<String, T> reserveNetworkPorts(Protocol protocol, 
Function<Integer, T> converter, String... names) {
         Map<String, T> reservedPorts = new HashMap<>();
 
         for (String name : names) {
-            reservedPorts.put(name, converter.apply(getNextAvailable()));
+            reservedPorts.put(name, 
converter.apply(getNextAvailable(protocol)));
         }
 
         return reservedPorts;
@@ -139,4 +160,25 @@ public final class AvailablePortFinder {
                     + "Pass the reserved port to the native application under 
test with QuarkusTestResource or via an HTTP request");
         }
     }
+
+    public enum Protocol {
+        TCP,
+        UDP;
+
+        int getPort() throws IOException {
+            if (this.equals(TCP)) {
+                try (ServerSocket socket = new ServerSocket()) {
+                    socket.setReuseAddress(true);
+                    socket.bind(null);
+                    return socket.getLocalPort();
+                }
+            }
+
+            try (DatagramSocket socket = new DatagramSocket()) {
+                // NOTE: There's no need for socket.bind as it happens during 
DatagramSocket instantiation
+                socket.setReuseAddress(true);
+                return socket.getLocalPort();
+            }
+        }
+    }
 }
diff --git 
a/integration-tests/netty/src/test/java/org/apache/camel/quarkus/component/netty/udp/NettyUdpTestResource.java
 
b/integration-tests/netty/src/test/java/org/apache/camel/quarkus/component/netty/udp/NettyUdpTestResource.java
index 776c7af0b7..f05caea245 100644
--- 
a/integration-tests/netty/src/test/java/org/apache/camel/quarkus/component/netty/udp/NettyUdpTestResource.java
+++ 
b/integration-tests/netty/src/test/java/org/apache/camel/quarkus/component/netty/udp/NettyUdpTestResource.java
@@ -21,11 +21,13 @@ import java.util.Objects;
 
 import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
 import org.apache.camel.quarkus.test.AvailablePortFinder;
+import org.apache.camel.quarkus.test.AvailablePortFinder.Protocol;
 
 public class NettyUdpTestResource implements 
QuarkusTestResourceLifecycleManager {
     @Override
     public Map<String, String> start() {
         return AvailablePortFinder.reserveNetworkPorts(
+                Protocol.UDP,
                 Objects::toString,
                 "camel.netty.test-udp-port",
                 "camel.netty.test-codec-udp-port",
diff --git 
a/integration-tests/syslog/src/test/java/org/apache/camel/quarkus/component/syslog/it/SyslogTestResource.java
 
b/integration-tests/syslog/src/test/java/org/apache/camel/quarkus/component/syslog/it/SyslogTestResource.java
index d875db16dc..e42d4ff501 100644
--- 
a/integration-tests/syslog/src/test/java/org/apache/camel/quarkus/component/syslog/it/SyslogTestResource.java
+++ 
b/integration-tests/syslog/src/test/java/org/apache/camel/quarkus/component/syslog/it/SyslogTestResource.java
@@ -21,12 +21,13 @@ import java.util.Objects;
 
 import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
 import org.apache.camel.quarkus.test.AvailablePortFinder;
+import org.apache.camel.quarkus.test.AvailablePortFinder.Protocol;
 
 public class SyslogTestResource implements QuarkusTestResourceLifecycleManager 
{
 
     @Override
     public Map<String, String> start() {
-        return AvailablePortFinder.reserveNetworkPorts(Objects::toString, 
"camel.netty.rfc5425.port",
+        return AvailablePortFinder.reserveNetworkPorts(Protocol.UDP, 
Objects::toString, "camel.netty.rfc5425.port",
                 "camel.netty.rfc3164.port");
     }
 

Reply via email to