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 620300ccd489..c6841a02b32e 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 @@ private 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 static int getNextAvailable() { } /** - * 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 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 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 Map reserveNetworkPorts(Function 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 Map reserveNetworkPorts(Protocol protocol, Function converter, String... names) { Map 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 @@ private static void logWarningIfNativeApplication() { + "Pass the reserved port to the native application under test with QuarkusTestResourceLifecycleManager 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 776c7af0b772..f05caea2459b 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 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 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 d875db16dc0a..e42d4ff5015a 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 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 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"); }