This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch 2.7.x in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 38cd4194f2a2ce04ebe391737f9565c1f8098e8d Author: James Netherton <[email protected]> AuthorDate: Wed Feb 16 09:43:01 2022 +0000 Improve available port discovery in tests Fixes #3199 --- .../camel/quarkus/test/AvailablePortFinder.java | 40 ++++++++++++++++++++-- .../quarkus/component/as2/it/As2TestResource.java | 1 + .../component/avro/rpc/it/AvroRpcTestResource.java | 1 + .../quarkus/component/ftp/it/FtpTestResource.java | 2 ++ .../component/sftp/it/SftpTestResource.java | 2 ++ .../component/grpc/it/GrpcServerTestResource.java | 1 + .../quarkus/component/hl7/it/Hl7TestResource.java | 2 +- .../component/http/it/HttpTestResource.java | 1 + .../component/hystrix/it/HystrixTestResource.java | 1 + .../quarkus/component/lra/it/LraTestResource.java | 1 + .../lumberjack/it/LumberjackTestResource.java | 2 +- .../quarkus/component/mllp/it/MllpResource.java | 4 ++- .../quarkus/component/mllp/it/MllpRoutes.java | 11 +++--- .../camel/quarkus/component/mllp/it/MllpTest.java | 2 ++ .../component/mllp/it/MllpTestResource.java} | 11 +++--- .../component/nagios/it/NagiosTestResource.java | 1 + .../component/netty/tcp/NettyTcpTestResource.java | 1 + .../component/oaipmh/it/MockOaipmhServer.java | 1 + .../sap/netweaver/it/SapNetweaverTestResource.java | 1 + .../component/syslog/it/SyslogTestResource.java | 2 +- 20 files changed, 71 insertions(+), 17 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 ee1825d..4fce970 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 @@ -23,6 +23,7 @@ import java.net.ServerSocket; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import org.eclipse.microprofile.config.Config; @@ -35,9 +36,11 @@ import org.slf4j.LoggerFactory; */ public final class AvailablePortFinder { private static final Logger LOGGER = LoggerFactory.getLogger(AvailablePortFinder.class); + private static final Map<Integer, String> RESERVED_PORTS = new ConcurrentHashMap<>(); private static final String[] QUARKUS_PORT_PROPERTIES = new String[] { "quarkus.http.test-port", "quarkus.http.test-ssl-port", + "quarkus.https.test-port", }; /** @@ -54,6 +57,10 @@ public final class AvailablePortFinder { * @return the available port */ public static int getNextAvailable() { + // 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); @@ -61,8 +68,12 @@ public final class AvailablePortFinder { int port = ss.getLocalPort(); if (!isQuarkusReservedPort(port)) { - LOGGER.info("getNextAvailable() -> {}", port); - return port; + String callerClassName = getCallerClassName(); + String value = RESERVED_PORTS.putIfAbsent(port, callerClassName); + if (value == null) { + LOGGER.info("{} reserved port {}", callerClassName, port); + return port; + } } } catch (IOException e) { throw new IllegalStateException("Cannot find free port", e); @@ -90,6 +101,16 @@ public final class AvailablePortFinder { return reservedPorts; } + public static void releaseReservedPorts() { + String callerClassName = getCallerClassName(); + RESERVED_PORTS.entrySet() + .stream() + .filter(entry -> entry.getValue().equals(callerClassName)) + .peek(entry -> LOGGER.info("Releasing port {} reserved by {}", entry.getKey(), entry.getValue())) + .map(Map.Entry::getKey) + .forEach(RESERVED_PORTS::remove); + } + private static boolean isQuarkusReservedPort(int port) { Config config = ConfigProvider.getConfig(); for (String property : QUARKUS_PORT_PROPERTIES) { @@ -103,4 +124,19 @@ public final class AvailablePortFinder { } return false; } + + private static String getCallerClassName() { + return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) + .walk(s -> s.map(StackWalker.StackFrame::getClassName) + .filter(className -> !className.equals(AvailablePortFinder.class.getName())) + .findFirst() + .orElseThrow(IllegalStateException::new)); + } + + private static void logWarningIfNativeApplication() { + if (System.getProperty("org.graalvm.nativeimage.kind") != null) { + LOGGER.warn("Usage of AvailablePortFinder in the native application is discouraged. " + + "Pass the reserved port to the native application under test with QuarkusTestResource or via an HTTP request"); + } + } } diff --git a/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2TestResource.java b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2TestResource.java index 59a2f01..00df5fb 100644 --- a/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2TestResource.java +++ b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2TestResource.java @@ -31,5 +31,6 @@ public class As2TestResource implements QuarkusTestResourceLifecycleManager { @Override public void stop() { + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/avro-rpc/src/test/java/org/apache/camel/quarkus/component/avro/rpc/it/AvroRpcTestResource.java b/integration-tests/avro-rpc/src/test/java/org/apache/camel/quarkus/component/avro/rpc/it/AvroRpcTestResource.java index 7e01972..900ae33 100644 --- a/integration-tests/avro-rpc/src/test/java/org/apache/camel/quarkus/component/avro/rpc/it/AvroRpcTestResource.java +++ b/integration-tests/avro-rpc/src/test/java/org/apache/camel/quarkus/component/avro/rpc/it/AvroRpcTestResource.java @@ -106,6 +106,7 @@ public class AvroRpcTestResource implements QuarkusTestResourceLifecycleManager if (specificNettyServer != null) { specificNettyServer.close(); } + AvailablePortFinder.releaseReservedPorts(); } @Override diff --git a/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/ftp/it/FtpTestResource.java b/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/ftp/it/FtpTestResource.java index d750632..64ab8cf 100644 --- a/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/ftp/it/FtpTestResource.java +++ b/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/ftp/it/FtpTestResource.java @@ -136,6 +136,8 @@ public class FtpTestResource implements QuarkusTestResourceLifecycleManager { } catch (Exception e) { LOGGER.warn("Failed delete usr file: {}, {}", usrFile, e); } + + AvailablePortFinder.releaseReservedPorts(); } protected ListenerFactory createListenerFactory(int port) { diff --git a/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpTestResource.java b/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpTestResource.java index 8385e1b..a27f151 100644 --- a/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpTestResource.java +++ b/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpTestResource.java @@ -97,5 +97,7 @@ public class SftpTestResource implements QuarkusTestResourceLifecycleManager { } catch (Exception e) { LOGGER.warn("Failed delete sftp home: {}, {}", sftpHome, e); } + + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java b/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java index eb947fd..aabf55f 100644 --- a/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java +++ b/integration-tests/grpc/src/test/java/org/apache/camel/quarkus/component/grpc/it/GrpcServerTestResource.java @@ -65,5 +65,6 @@ public class GrpcServerTestResource implements QuarkusTestResourceLifecycleManag } catch (Exception e) { LOGGER.error("Could not stop gRPC server", e); } + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/hl7/src/test/java/org/apache/camel/quarkus/component/hl7/it/Hl7TestResource.java b/integration-tests/hl7/src/test/java/org/apache/camel/quarkus/component/hl7/it/Hl7TestResource.java index 3ab8ed5..bf74e65 100644 --- a/integration-tests/hl7/src/test/java/org/apache/camel/quarkus/component/hl7/it/Hl7TestResource.java +++ b/integration-tests/hl7/src/test/java/org/apache/camel/quarkus/component/hl7/it/Hl7TestResource.java @@ -32,6 +32,6 @@ public class Hl7TestResource implements QuarkusTestResourceLifecycleManager { @Override public void stop() { - // Noop + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTestResource.java b/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTestResource.java index 7a5392f..13c4828 100644 --- a/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTestResource.java +++ b/integration-tests/http/src/test/java/org/apache/camel/quarkus/component/http/it/HttpTestResource.java @@ -59,5 +59,6 @@ public class HttpTestResource implements QuarkusTestResourceLifecycleManager { if (container != null) { container.stop(); } + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/hystrix/src/test/java/org/apache/camel/quarkus/component/hystrix/it/HystrixTestResource.java b/integration-tests/hystrix/src/test/java/org/apache/camel/quarkus/component/hystrix/it/HystrixTestResource.java index 3b5b5db..9632930 100644 --- a/integration-tests/hystrix/src/test/java/org/apache/camel/quarkus/component/hystrix/it/HystrixTestResource.java +++ b/integration-tests/hystrix/src/test/java/org/apache/camel/quarkus/component/hystrix/it/HystrixTestResource.java @@ -30,5 +30,6 @@ public class HystrixTestResource implements QuarkusTestResourceLifecycleManager @Override public void stop() { + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/lra/src/test/java/org/apache/camel/quarkus/component/lra/it/LraTestResource.java b/integration-tests/lra/src/test/java/org/apache/camel/quarkus/component/lra/it/LraTestResource.java index 7ef35b7..191c1b1 100644 --- a/integration-tests/lra/src/test/java/org/apache/camel/quarkus/component/lra/it/LraTestResource.java +++ b/integration-tests/lra/src/test/java/org/apache/camel/quarkus/component/lra/it/LraTestResource.java @@ -76,5 +76,6 @@ public class LraTestResource implements QuarkusTestResourceLifecycleManager { } catch (Exception e) { // ignored } + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/lumberjack/src/test/java/org/apache/camel/quarkus/component/lumberjack/it/LumberjackTestResource.java b/integration-tests/lumberjack/src/test/java/org/apache/camel/quarkus/component/lumberjack/it/LumberjackTestResource.java index 2c24cb1..ad53495 100644 --- a/integration-tests/lumberjack/src/test/java/org/apache/camel/quarkus/component/lumberjack/it/LumberjackTestResource.java +++ b/integration-tests/lumberjack/src/test/java/org/apache/camel/quarkus/component/lumberjack/it/LumberjackTestResource.java @@ -31,6 +31,6 @@ public class LumberjackTestResource implements QuarkusTestResourceLifecycleManag @Override public void stop() { - + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/mllp/src/main/java/org/apache/camel/quarkus/component/mllp/it/MllpResource.java b/integration-tests/mllp/src/main/java/org/apache/camel/quarkus/component/mllp/it/MllpResource.java index c90ba32..192a841 100644 --- a/integration-tests/mllp/src/main/java/org/apache/camel/quarkus/component/mllp/it/MllpResource.java +++ b/integration-tests/mllp/src/main/java/org/apache/camel/quarkus/component/mllp/it/MllpResource.java @@ -30,6 +30,7 @@ import org.apache.camel.ProducerTemplate; import org.apache.camel.component.mllp.MllpComponent; import org.apache.camel.component.mllp.MllpConstants; import org.apache.camel.component.mock.MockEndpoint; +import org.eclipse.microprofile.config.ConfigProvider; @Path("/mllp") @ApplicationScoped @@ -64,7 +65,8 @@ public class MllpResource { @POST @Produces(MediaType.TEXT_PLAIN) public String getWithCharsetFromMsh18(String message) { - String mllpHostPort = String.format("mllp:%s:%d", MllpRoutes.MLLP_HOST, MllpRoutes.MLLP_PORT); + Integer mllpPort = ConfigProvider.getConfig().getValue("mllp.test.port", Integer.class); + String mllpHostPort = String.format("mllp:%s:%d", MllpRoutes.MLLP_HOST, mllpPort); Exchange exchange = producerTemplate.request(mllpHostPort, e -> e.getMessage().setBody(message)); String ack = exchange.getMessage().getHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT_STRING, String.class); return ack.split("\r")[0]; diff --git a/integration-tests/mllp/src/main/java/org/apache/camel/quarkus/component/mllp/it/MllpRoutes.java b/integration-tests/mllp/src/main/java/org/apache/camel/quarkus/component/mllp/it/MllpRoutes.java index 2b61637..026b6a9 100644 --- a/integration-tests/mllp/src/main/java/org/apache/camel/quarkus/component/mllp/it/MllpRoutes.java +++ b/integration-tests/mllp/src/main/java/org/apache/camel/quarkus/component/mllp/it/MllpRoutes.java @@ -20,28 +20,29 @@ import io.quarkus.runtime.annotations.RegisterForReflection; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mllp.MllpConstants; import org.apache.camel.component.mllp.MllpInvalidMessageException; -import org.apache.camel.quarkus.test.AvailablePortFinder; +import org.eclipse.microprofile.config.ConfigProvider; @RegisterForReflection(targets = MllpInvalidMessageException.class, fields = false) public class MllpRoutes extends RouteBuilder { public static final String MLLP_HOST = "localhost"; - public static final int MLLP_PORT = AvailablePortFinder.getNextAvailable(); @Override public void configure() throws Exception { + Integer mllpPort = ConfigProvider.getConfig().getValue("mllp.test.port", Integer.class); + onException(MllpInvalidMessageException.class) .to("mock:invalid"); - fromF("mllp://%s:%d?validatePayload=true", MLLP_HOST, MLLP_PORT) + fromF("mllp://%s:%d?validatePayload=true", MLLP_HOST, mllpPort) .convertBodyTo(String.class); from("direct:validMessage") - .toF("mllp://%s:%d", MLLP_HOST, MLLP_PORT) + .toF("mllp://%s:%d", MLLP_HOST, mllpPort) .setBody(header(MllpConstants.MLLP_ACKNOWLEDGEMENT)); from("direct:invalidMessage") - .toF("mllp://%s:%d?exchangePattern=InOnly", MLLP_HOST, MLLP_PORT) + .toF("mllp://%s:%d?exchangePattern=InOnly", MLLP_HOST, mllpPort) .setBody(header(MllpConstants.MLLP_ACKNOWLEDGEMENT)); } } diff --git a/integration-tests/mllp/src/test/java/org/apache/camel/quarkus/component/mllp/it/MllpTest.java b/integration-tests/mllp/src/test/java/org/apache/camel/quarkus/component/mllp/it/MllpTest.java index e85f3ca..339786e 100644 --- a/integration-tests/mllp/src/test/java/org/apache/camel/quarkus/component/mllp/it/MllpTest.java +++ b/integration-tests/mllp/src/test/java/org/apache/camel/quarkus/component/mllp/it/MllpTest.java @@ -16,6 +16,7 @@ */ package org.apache.camel.quarkus.component.mllp.it; +import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.restassured.RestAssured; import org.junit.jupiter.api.Test; @@ -23,6 +24,7 @@ import org.junit.jupiter.api.Test; import static org.hamcrest.Matchers.containsString; @QuarkusTest +@QuarkusTestResource(MllpTestResource.class) class MllpTest { private static final String HL7_MESSAGE = "MSH|^~\\&|REQUESTING|ICE|INHOUSE|RTH00|20210331095020||ORM^O01|1|D|2.3|||AL|NE||\r" diff --git a/integration-tests/syslog/src/test/java/org/apache/camel/quarkus/component/syslog/it/SyslogTestResource.java b/integration-tests/mllp/src/test/java/org/apache/camel/quarkus/component/mllp/it/MllpTestResource.java similarity index 76% copy from integration-tests/syslog/src/test/java/org/apache/camel/quarkus/component/syslog/it/SyslogTestResource.java copy to integration-tests/mllp/src/test/java/org/apache/camel/quarkus/component/mllp/it/MllpTestResource.java index b0b5ccd..32058b3 100644 --- a/integration-tests/syslog/src/test/java/org/apache/camel/quarkus/component/syslog/it/SyslogTestResource.java +++ b/integration-tests/mllp/src/test/java/org/apache/camel/quarkus/component/mllp/it/MllpTestResource.java @@ -14,24 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.syslog.it; +package org.apache.camel.quarkus.component.mllp.it; +import java.util.Collections; import java.util.Map; -import java.util.Objects; import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; import org.apache.camel.quarkus.test.AvailablePortFinder; -public class SyslogTestResource implements QuarkusTestResourceLifecycleManager { +public class MllpTestResource implements QuarkusTestResourceLifecycleManager { @Override public Map<String, String> start() { - return AvailablePortFinder.reserveNetworkPorts(Objects::toString, "camel.netty.rfc5425.port", - "camel.netty.rfc3164.port"); + return Collections.singletonMap("mllp.test.port", Integer.toString(AvailablePortFinder.getNextAvailable())); } @Override public void stop() { - + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/nagios/src/test/java/org/apache/camel/quarkus/component/nagios/it/NagiosTestResource.java b/integration-tests/nagios/src/test/java/org/apache/camel/quarkus/component/nagios/it/NagiosTestResource.java index bf1d3c1..62d178f 100644 --- a/integration-tests/nagios/src/test/java/org/apache/camel/quarkus/component/nagios/it/NagiosTestResource.java +++ b/integration-tests/nagios/src/test/java/org/apache/camel/quarkus/component/nagios/it/NagiosTestResource.java @@ -78,6 +78,7 @@ public class NagiosTestResource implements QuarkusTestResourceLifecycleManager { if (context != null) { context.shutdown(); } + AvailablePortFinder.releaseReservedPorts(); } @Override diff --git a/integration-tests/netty/src/test/java/org/apache/camel/quarkus/component/netty/tcp/NettyTcpTestResource.java b/integration-tests/netty/src/test/java/org/apache/camel/quarkus/component/netty/tcp/NettyTcpTestResource.java index b1f0fbf..ba0e829 100644 --- a/integration-tests/netty/src/test/java/org/apache/camel/quarkus/component/netty/tcp/NettyTcpTestResource.java +++ b/integration-tests/netty/src/test/java/org/apache/camel/quarkus/component/netty/tcp/NettyTcpTestResource.java @@ -39,5 +39,6 @@ public class NettyTcpTestResource implements QuarkusTestResourceLifecycleManager @Override public void stop() { + AvailablePortFinder.releaseReservedPorts(); } } diff --git a/integration-tests/oaipmh/src/test/java/org/apache/camel/quarkus/component/oaipmh/it/MockOaipmhServer.java b/integration-tests/oaipmh/src/test/java/org/apache/camel/quarkus/component/oaipmh/it/MockOaipmhServer.java index fb4a236..e5e6b51 100644 --- a/integration-tests/oaipmh/src/test/java/org/apache/camel/quarkus/component/oaipmh/it/MockOaipmhServer.java +++ b/integration-tests/oaipmh/src/test/java/org/apache/camel/quarkus/component/oaipmh/it/MockOaipmhServer.java @@ -104,6 +104,7 @@ public final class MockOaipmhServer { public void stop() { server.stop(); + AvailablePortFinder.releaseReservedPorts(); } public int getHttpPort() { diff --git a/integration-tests/sap-netweaver/src/test/java/org/apache/camel/quarkus/component/sap/netweaver/it/SapNetweaverTestResource.java b/integration-tests/sap-netweaver/src/test/java/org/apache/camel/quarkus/component/sap/netweaver/it/SapNetweaverTestResource.java index fac3c5b..d56178d 100644 --- a/integration-tests/sap-netweaver/src/test/java/org/apache/camel/quarkus/component/sap/netweaver/it/SapNetweaverTestResource.java +++ b/integration-tests/sap-netweaver/src/test/java/org/apache/camel/quarkus/component/sap/netweaver/it/SapNetweaverTestResource.java @@ -31,5 +31,6 @@ public class SapNetweaverTestResource implements QuarkusTestResourceLifecycleMan @Override public void stop() { + AvailablePortFinder.releaseReservedPorts(); } } 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 b0b5ccd..d875db1 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 @@ -32,6 +32,6 @@ public class SyslogTestResource implements QuarkusTestResourceLifecycleManager { @Override public void stop() { - + AvailablePortFinder.releaseReservedPorts(); } }
