You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2022/01/20 19:03:40 UTC

[logging-log4j2] branch master updated: Add a delay if an ephemeral port has not been allocated yet.

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

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/master by this push:
     new 9c9fe49  Add a delay if an ephemeral port has not been allocated yet.
9c9fe49 is described below

commit 9c9fe49d487cd12a47ed10acd3ef1654394b186b
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Thu Jan 20 14:03:36 2022 -0500

    Add a delay if an ephemeral port has not been allocated yet.
---
 .../core/net/SocketAppenderReconnectTest.java      | 63 ++++++++++++++--------
 1 file changed, 40 insertions(+), 23 deletions(-)

diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/SocketAppenderReconnectTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/SocketAppenderReconnectTest.java
index e7655e0..a4ff396 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/SocketAppenderReconnectTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/SocketAppenderReconnectTest.java
@@ -16,19 +16,11 @@
  */
 package org.apache.logging.log4j.core.net;
 
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.appender.AppenderLoggingException;
-import org.apache.logging.log4j.core.config.Configuration;
-import org.apache.logging.log4j.core.config.Configurator;
-import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
-import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
-import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
-import org.apache.logging.log4j.core.net.TcpSocketManager.HostResolver;
-import org.apache.logging.log4j.status.StatusLogger;
-import org.junit.jupiter.api.Test;
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -49,14 +41,27 @@ import java.util.concurrent.TimeoutException;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
-import static org.awaitility.Awaitility.await;
-import static org.junit.jupiter.api.Assertions.*;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.AppenderLoggingException;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
+import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
+import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
+import org.apache.logging.log4j.core.net.TcpSocketManager.HostResolver;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.junit.jupiter.api.Test;
 
 /**
  * Tests reconnection support of {@link org.apache.logging.log4j.core.appender.SocketAppender}.
  */
 class SocketAppenderReconnectTest {
 
+    private static final long DEFAULT_POLL_MILLIS = 1_000L;
+    private static final int EPHEMERAL_PORT = 0;
     private static final Logger LOGGER = StatusLogger.getLogger();
 
     /**
@@ -69,9 +74,9 @@ class SocketAppenderReconnectTest {
         try (final LineReadingTcpServer server = new LineReadingTcpServer()) {
 
             // Start the server.
-            server.start("Main", 0);
+            server.start("Main", EPHEMERAL_PORT);
             final int port = server.serverSocket.getLocalPort();
-
+            
             // Initialize the logger context.
             final LoggerContext loggerContext = initContext(port);
             try {
@@ -106,8 +111,8 @@ class SocketAppenderReconnectTest {
              final LineReadingTcpServer secondaryServer = new LineReadingTcpServer()) {
 
             // Start servers.
-            primaryServer.start("Primary", 0);
-            secondaryServer.start("Secondary", 0);
+            primaryServer.start("Primary", EPHEMERAL_PORT);
+            secondaryServer.start("Secondary", EPHEMERAL_PORT);
 
             // Mock the host resolver.
             final FixedHostResolver hostResolver = FixedHostResolver.ofServers(primaryServer, secondaryServer);
@@ -117,6 +122,7 @@ class SocketAppenderReconnectTest {
                 // Initialize the logger context.
                 final LoggerContext loggerContext = initContext(
                         // Passing an invalid port, since the resolution is supposed to be performed by the mocked host resolver anyway.
+                        // Here, 0 does NOT mean an ephemeral port.
                         0);
                 try {
 
@@ -200,7 +206,7 @@ class SocketAppenderReconnectTest {
 
     private static void awaitUntilSucceeds(final Runnable runnable) {
         // These figures are collected via trial-and-error; nothing scientific to look for here.
-        final long pollIntervalMillis = 1_000L;
+        final long pollIntervalMillis = DEFAULT_POLL_MILLIS;
         final long timeoutSeconds = 120L;
         await()
                 .pollInterval(pollIntervalMillis, TimeUnit.MILLISECONDS)
@@ -233,6 +239,8 @@ class SocketAppenderReconnectTest {
      */
     private static final class LineReadingTcpServer implements AutoCloseable {
 
+        private static final int UNBOUND_PORT = -1;
+
         private volatile boolean running;
 
         private ServerSocket serverSocket;
@@ -250,6 +258,16 @@ class SocketAppenderReconnectTest {
                 running = true;
                 serverSocket = createServerSocket(port);
                 readerThread = createReaderThread(name);
+                // Make sure the server socket is ready.
+                if (serverSocket.getLocalPort() == UNBOUND_PORT || !serverSocket.isBound()) {
+                    try {
+                        Thread.sleep(DEFAULT_POLL_MILLIS);
+                    } catch (InterruptedException e) {
+                        throw new IllegalStateException(e);
+                    }
+                }
+                assertNotEquals(UNBOUND_PORT, serverSocket.getLocalPort(),
+                    () -> String.format("Server socket is not bound to port %s (0 = ephemeral). This can only happen if a machine runs out of ports.", port));
             }
         }
 
@@ -263,9 +281,8 @@ class SocketAppenderReconnectTest {
         private Thread createReaderThread(final String name) {
             final String threadName = "LineReadingTcpSocketServerReader-" + name;
             final Thread thread = new Thread(this::acceptClients, threadName);
-            thread.setDaemon(true);     // Avoid blocking JVM exit.
-            thread.setUncaughtExceptionHandler((ignored, error) ->
-                    LOGGER.error("uncaught reader thread exception", error));
+            thread.setDaemon(true); // Avoid blocking JVM exit.
+            thread.setUncaughtExceptionHandler((ignored, error) -> LOGGER.error("uncaught reader thread exception", error));
             thread.start();
             return thread;
         }