From c6b392c4bd54cc8037eecb0d9a5d380da9a65bef Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Mon, 03 Aug 2026 07:56:05 +0000
Subject: [PATCH] [#800] Allocate the replication test listen ports per invocation (#803)

---
 opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java                                   |    5 +++--
 opendj-server-legacy/src/test/java/org/opends/server/replication/server/AssuredReplicationServerTest.java |   21 ++++++++-------------
 opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AssuredReplicationPluginTest.java |   16 ++++++++++++++--
 opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/FractionalReplicationTest.java    |   17 ++++-------------
 4 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java b/opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java
index fdd3d63..436f379 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java
@@ -833,12 +833,13 @@
         sockets[i] = bindFreePort();
         ports[i] = sockets[i].getLocalPort();
       }
-      close(sockets);
       return ports;
     }
     finally
     {
-      
+      // Close them all, including when an allocation failed halfway: a socket which stays bound
+      // holds its port in listen state, and bindFreePort() hands out each number only once.
+      close(sockets);
     }
   }
 
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AssuredReplicationPluginTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AssuredReplicationPluginTest.java
index 117384b..f59bce4 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AssuredReplicationPluginTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/AssuredReplicationPluginTest.java
@@ -77,6 +77,7 @@
 import org.opends.server.types.SearchResultEntry;
 import org.opends.server.util.StaticUtils;
 import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
@@ -172,8 +173,6 @@
   {
     super.setUp();
 
-    replServerPort = findFreePort();
-
     // Create base dns for each tested modes
     addEntry("dn: " + SAFE_DATA_DN,
         "objectClass: top",
@@ -186,6 +185,19 @@
         "objectClass: organizationalUnit");
   }
 
+  /**
+   * Allocates the listen port of the fake replication server, for one invocation only: each of them
+   * starts a fake replication server again, and a port which is bound again and again is exposed,
+   * for the whole time it is not bound, to anything in this JVM which may take it in the meantime.
+   * Both the fake replication server and the domain configuration entry which points at it are
+   * created by the test method itself, hence after this.
+   */
+  @BeforeMethod
+  public void findReplicationServerPort() throws IOException
+  {
+    replServerPort = findFreePort();
+  }
+
   /** Add an entry in the database. */
   private void addEntry(String... ldifLines) throws Exception
   {
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/FractionalReplicationTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/FractionalReplicationTest.java
index 8dc59bd..50dd7aa 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/FractionalReplicationTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/FractionalReplicationTest.java
@@ -55,7 +55,6 @@
 import org.opends.server.types.Attributes;
 import org.opends.server.types.Entry;
 import org.opends.server.types.Modification;
-import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
@@ -129,18 +128,6 @@
     }
   }
 
-  /**
-   * Before starting the tests configure some stuff
-   */
-  @BeforeClass
-  @Override
-  public void setUp() throws Exception
-  {
-    super.setUp();
-
-    replServerPort = findFreePort();
-  }
-
   /** Returns a bunch of single values for fractional-exclude configuration attribute. */
   @DataProvider
   private Object[][] testExcludePrecommitProvider()
@@ -373,6 +360,10 @@
 
   private void initTest() throws Exception
   {
+    // Allocate the listen port of the replication server for this invocation only: a port which is
+    // bound again and again is exposed, for the whole time it is not bound, to anything in this JVM
+    // which may take it in the meantime.
+    replServerPort = findFreePort();
     replicationDomain = null;
     fractionalDomainCfgEntry = null;
     replicationServer = null;
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/server/AssuredReplicationServerTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/server/AssuredReplicationServerTest.java
index b58b9cd..4ec1133 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/server/AssuredReplicationServerTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/server/AssuredReplicationServerTest.java
@@ -24,6 +24,7 @@
 import static org.opends.server.util.CollectionUtils.*;
 import static org.testng.Assert.*;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.InetSocketAddress;
@@ -71,7 +72,6 @@
 import org.opends.server.replication.service.ReplicationDomain;
 import org.opends.server.types.DirectoryException;
 import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
@@ -196,20 +196,15 @@
     }
   }
 
-  /**
-   * Before starting the tests configure some stuff.
-   */
-  @BeforeClass
-  @Override
-  public void setUp() throws Exception
+  private void initTest() throws IOException
   {
-    super.setUp();
-
+    /*
+     * Allocate the listen ports of the real replication servers for this invocation only. The test
+     * methods of this class run several hundred times, each of them creating a replication server
+     * again, and a port which is bound again and again is exposed, for the whole time it is not
+     * bound, to anything in this JVM which may take it in the meantime.
+     */
     rsPorts = TestCaseUtils.findFreePorts(4);
-  }
-
-  private void initTest()
-  {
     fakeRDs = new FakeReplicationDomain[13];
     fakeRs1 = fakeRs2 = fakeRs3 = null;
     rs1 = rs2 = rs3 = rs4 = null;

--
Gitblit v1.10.0