Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0724a10
Improve ReplicationDomainTest stability
maximthomas Oct 6, 2025
da48ba4
Improve ReplicationBroker concurrency stability
maximthomas Oct 6, 2025
b86736b
Print thread dump on a test failure
maximthomas Oct 9, 2025
75c2eab
print thread dump in test timer
maximthomas Oct 9, 2025
9f111a2
Extend thread dump for testing
maximthomas Oct 10, 2025
1c01649
revert the shutdown flag to volatile in ReplicationBroker due to test…
maximthomas Oct 10, 2025
2841446
Fix SchemaReplicationTest.pushSchemaFilesChange: wait for schema file…
maximthomas Oct 13, 2025
76f0a17
Additional test logging to diagnose
maximthomas Oct 13, 2025
deda956
Close ServerSocket on BindException
vharseko Oct 14, 2025
e50fc0f
enable trace logging for a failed test
maximthomas Oct 14, 2025
f7ac400
trace on replication tests failure
maximthomas Oct 15, 2025
9f0d385
fix ArrayIndexOutOfBoundsException in TestListener
maximthomas Oct 15, 2025
7c78d03
trace only for org.opends.server.replication.service package
maximthomas Oct 15, 2025
a680b36
shutdown server even if a test was skipped or failed
maximthomas Oct 16, 2025
ecf521d
Move Export threads to a Thread Pool Executor to shut down gracefully
maximthomas Oct 20, 2025
80cdb0e
Fix deadlock in the ReplicationBroker.stop() function
maximthomas Oct 21, 2025
616a526
Set trace for GenerationIdTest
maximthomas Oct 22, 2025
25f10e5
fix ReplicationDomainTest.exportAndImportAcross2ReplServers: wait for…
maximthomas Oct 23, 2025
1a51db7
Fix GenerationIdTest.testMultiRS: wait for all RS handshakes to complete
maximthomas Oct 29, 2025
044f887
Update copyright
maximthomas Oct 31, 2025
b74cfeb
Merge branch 'master' into improve-tests-stability
vharseko Oct 31, 2025
ed38723
Fix ReplicationDomainTest.exportAndImportAcross2ReplServers wait for …
maximthomas Nov 1, 2025
a4bd0a8
Add tracing to non-server tests
maximthomas Nov 1, 2025
41ec1ee
Enabled HostPort comparison tracing
maximthomas Nov 1, 2025
939befd
Fix HostPortTest.isEquivalentTo test
maximthomas Nov 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions opendj-server-legacy/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,8 @@
<org.opends.test.suppressOutput>true</org.opends.test.suppressOutput>
<org.opends.test.pauseOnFailure>false</org.opends.test.pauseOnFailure>
<org.opends.test.copyClassesToTestPackage>false</org.opends.test.copyClassesToTestPackage>
<org.opends.test.timeout>600000</org.opends.test.timeout><!--15 mins-->
<org.opends.test.trace.pattern>(org\.opends\.server\.replication\.service\..*)|(org\.opends\.server\.replication\.GenerationIdTest)|(org\.opends\.server\.types.\HostPortTest)</org.opends.test.trace.pattern>
</systemPropertyVariables>
<argLine>@{argLine}</argLine>
<reuseForks>false</reuseForks>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2016 ForgeRock AS.
* Portions Copyright 2023-2025 3A Systems LLC.
* Portions Copyright 2025 Wren Security.
*/
package org.opends.server.replication.service;
Expand Down Expand Up @@ -2665,14 +2666,16 @@ public void stop()
{
debugInfo("is stopping and will close the connection to RS(" + getRsServerId() + ")");
}
synchronized (startStopLock) {
if (shutdown) {
return;
}
}

domain.publishReplicaOfflineMsg();

synchronized (startStopLock)
{
if (shutdown)
{
return;
}
domain.publishReplicaOfflineMsg();
shutdown = true;
setConnectedRS(ConnectedRS.stopped());
stopRSHeartBeatMonitoring();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2008-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2016 ForgeRock AS.
* Portions Copyright 2025 3A Systems LLC.
*/
package org.opends.server.replication.service;

Expand All @@ -39,6 +40,9 @@
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
Expand Down Expand Up @@ -372,6 +376,11 @@ public ECLIncludes addIncludedAttributes(int serverId,
*/
protected volatile long generationId;

/**
* Thread pool for export thread tasks
*/
private final ExecutorService exportThreadPool = Executors.newCachedThreadPool();

/**
* Returns the {@link CSNGenerator} that will be used to
* generate {@link CSN} for this domain.
Expand Down Expand Up @@ -879,7 +888,10 @@ else if (msg instanceof InitializeRcvAckMsg)
// Do this work in a thread to allow replay thread continue working
ExportThread exportThread = new ExportThread(
initReqMsg.getSenderID(), initReqMsg.getInitWindow());
exportThread.start();
exportThreadPool.execute(() -> {
Thread.currentThread().setName(exportThread.getName());
exportThread.run();
});
}
}

Expand Down Expand Up @@ -1075,6 +1087,9 @@ public void run()
This server is not the initiator of the export so there is
nothing more to do locally.
*/
if (logger.isTraceEnabled()) {
logger.trace(LocalizableMessage.raw("[IE] got exception" + getName()), de);
}
}

if (logger.isTraceEnabled())
Expand Down Expand Up @@ -3016,6 +3031,13 @@ public void disableService()
{
broker.stop();
}
try {
exportThreadPool.shutdown();
boolean timedOut = exportThreadPool.awaitTermination(100, TimeUnit.SECONDS);
logger.info(LocalizableMessage.raw("export pool termination timed out: " + timedOut));
} catch (InterruptedException e) {
// Give up waiting.
}

// Stop the listener thread
if (listenerThread != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2006-2008 Sun Microsystems, Inc.
* Portions Copyright 2013-2016 ForgeRock AS.
* Portions Copyright 2025 3A Systems LLC.
*/
package org.opends.server.types;

Expand Down Expand Up @@ -459,6 +460,9 @@ public boolean isEquivalentTo(final HostPort other)
// Get and compare ports of RS1 and RS2
if (getPort() != other.getPort())
{
if(logger.isTraceEnabled()) {
logger.trace("port and host does not match " + this + "; " + other);
}
return false;
}

Expand All @@ -475,6 +479,9 @@ public boolean isEquivalentTo(final HostPort other)
}
else if (thisAddresses == null || otherAddresses == null)
{
if(logger.isTraceEnabled()) {
logger.trace("port and host does not match: " + this + "=" + thisAddresses + "; " + other + "=" + otherAddresses);
}
// One local address and one non-local.
return false;
}
Expand All @@ -490,10 +497,17 @@ else if (thisAddresses == null || otherAddresses == null)
}
}
}
if(logger.isTraceEnabled()) {
logger.trace("port and host does not match: " + this + "=" + thisAddresses + "; " + other + "=" + otherAddresses);
}

return false;
}
catch (UnknownHostException ex)
{
if(logger.isTraceEnabled()) {
logger.traceException(ex, "got exception when resolving hosts: " + this + " and " + other );
}
// Unknown RS: should not happen
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2006-2008 Sun Microsystems, Inc.
* Portions Copyright 2013-2015 ForgeRock AS.
* Portions Copyright 2025 3A Systems LLC.
*/
package org.opends.server;

Expand Down Expand Up @@ -48,7 +49,7 @@ public final void suppressOutput() {
TestCaseUtils.suppressOutput();
}

@AfterSuite
@AfterSuite(alwaysRun = true)
public final void shutdownServer() {
TestCaseUtils.shutdownServer(LocalizableMessage.raw("The current test suite has finished."));
TestCaseUtils.unsupressOutput();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.StringReader;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.net.BindException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
Expand Down Expand Up @@ -542,6 +543,9 @@ private static void setupLoggers()
ErrorLogger.getInstance().addLogPublisher(
(ErrorLogPublisher) getServerStartupTextErrorPublisher(ERROR_TEXT_WRITER));

}

public static void setupTrace() {
DebugLogger.getInstance().addPublisherIfRequired(DEBUG_TEXT_WRITER);
}

Expand Down Expand Up @@ -742,11 +746,20 @@ public synchronized static ServerSocket bindFreePort() throws IOException
{
for (; port > 1024;)
{
ServerSocket res=null;
try
{
return bindPort(port--);
res=bindPort(port--);
return res;
}
catch (BindException e){}
catch (BindException e){
if (res!=null) {
try {
res.close();
} catch (IOException ex) {}
}
res=null;
}
}
throw new BindException("Unable to bind to a free port");
}
Expand Down Expand Up @@ -1927,20 +1940,71 @@ public static void generateThreadDump(String id)
public static String generateThreadDump() {
final StringBuilder dump = new StringBuilder();
final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
final ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), 100);
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true);
for (ThreadInfo threadInfo : threadInfos) {
dump.append('"');
dump.append(threadInfo.getThreadName());
dump.append("\" ");
final Thread.State state = threadInfo.getThreadState();
dump.append("\n java.lang.Thread.State: ");
dump.append(state);
final StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
for (final StackTraceElement stackTraceElement : stackTraceElements) {
dump.append("\n at ");
dump.append(stackTraceElement);
dump.append("\"" + threadInfo.getThreadName() + "\"" +
(threadInfo.isDaemon() ? " daemon" : "") +
" prio=" + threadInfo.getPriority() +
" Id=" + threadInfo.getThreadId() + " " +
threadInfo.getThreadState());
if (threadInfo.getLockName() != null) {
dump.append(" on " + threadInfo.getLockName());
}
if (threadInfo.getLockOwnerName() != null) {
dump.append(" owned by \"" + threadInfo.getLockOwnerName() +
"\" Id=" + threadInfo.getLockOwnerId());
}
if (threadInfo.isSuspended()) {
dump.append(" (suspended)");
}
if (threadInfo.isInNative()) {
dump.append(" (in native)");
}
dump.append('\n');
StackTraceElement[] stackTrace = threadInfo.getStackTrace();
int i = 0;
for (; i < stackTrace.length; i++) {
StackTraceElement ste = stackTrace[i];
dump.append("\tat " + ste.toString());
dump.append('\n');
if (i == 0 && threadInfo.getLockInfo() != null) {
Thread.State ts = threadInfo.getThreadState();
switch (ts) {
case BLOCKED:
dump.append("\t- blocked on " + threadInfo.getLockInfo());
dump.append('\n');
break;
case WAITING:
case TIMED_WAITING:
dump.append("\t- waiting on " + threadInfo.getLockInfo());
dump.append('\n');
break;
default:
}
}
dump.append("\n\n");

for (MonitorInfo mi : threadInfo.getLockedMonitors()) {
if (mi.getLockedStackDepth() == i) {
dump.append("\t- locked " + mi);
dump.append('\n');
}
}
}
if (i < stackTrace.length) {
dump.append("\t...");
dump.append('\n');
}

LockInfo[] locks = threadInfo.getLockedSynchronizers();
if (locks.length > 0) {
dump.append("\n\tNumber of locked synchronizers = " + locks.length);
dump.append('\n');
for (LockInfo li : locks) {
dump.append("\t- " + li);
dump.append('\n');
}
}
dump.append('\n');
}
return dump.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
* Copyright 2008 Sun Microsystems, Inc.
* Portions Copyright 2013-2016 ForgeRock AS.
* Portions Copyright 2023 3A Systems, LLC.
* Portions Copyright 2023-2025 3A Systems, LLC.
*/
package org.opends.server;

Expand Down Expand Up @@ -155,11 +155,26 @@ public TestListener() throws Exception {
@Override
public void onStart(ITestContext testContext) {
super.onStart(testContext);

if (testContext.getAllTestMethods().length>0) {
TestCaseUtils.setTestName(testContext.getAllTestMethods()[0].getInstance().getClass().getName());
}

long testTimeout = 0;
try {
testTimeout = Long.parseLong(System.getProperty("org.opends.test.timeout", "0"));
} catch (NumberFormatException ignored) {}

for (int i = 0; i < testContext.getAllTestMethods().length; i++) {
testContext.getAllTestMethods()[i].setTimeOut(testTimeout);
}
if(System.getProperty("org.opends.test.trace.pattern") != null && testContext.getAllTestMethods().length > 0) {
String tracePattern = System.getProperty("org.opends.test.trace.pattern");
if(testContext.getAllTestMethods()[0].getInstance().getClass().getName().matches(tracePattern)) {
System.setProperty("org.opends.server.debug.target.1", "_global:enabled");
TestCaseUtils.setupTrace();
}
}

// Delete the previous report if it's there.
new File(testContext.getOutputDirectory(), REPORT_FILE_NAME).delete();
}
Expand All @@ -179,6 +194,7 @@ public void onFinish(ITestContext testContext) {
originalSystemErr.println("check state: "+paths.unitRoot);
}
}
System.clearProperty("org.opends.server.debug.target.1");
}

@Override
Expand Down Expand Up @@ -335,6 +351,7 @@ private void writeReportToScreen(File reportFile) {
@Override
public void onTestStart(ITestResult tr) {
super.onTestStart(tr);
originalSystemOut.println("-- Executing test: " + tr.getMethod());

enforceTestClassTypeAndAnnotations(tr);
checkForInterleavedBetweenClasses(tr);
Expand All @@ -358,6 +375,11 @@ public void onTestSuccess(ITestResult tr) {
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);
reportTestFailed(tr);
printThreadDump();
}

private void printThreadDump() {
originalSystemErr.println(TestCaseUtils.generateThreadDump());
}

private void reportTestFailed(ITestResult tr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,8 @@ public void testMultiRS() throws Exception
replServer3 = createReplicationServer(replServerId3, true, testCase);

connectServer1ToReplServer(replServer1);
Thread.sleep(2000); //wait for all RS handshakes to complete

debugInfo("Expect genId are set in all replServers.");
waitForStableGenerationId(EMPTY_DN_GENID);
disconnectFromReplServer(replServer1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2008-2010 Sun Microsystems, Inc.
* Portions Copyright 2012-2016 ForgeRock AS.
* Portions Copyright 2025 3A Systems LLC.
*/
package org.opends.server.replication;

Expand Down Expand Up @@ -234,6 +235,7 @@ public void pushSchemaFilesChange() throws Exception
@Override
public void call() throws Exception
{
assertTrue(schemaFile.exists());
String fileStr = readAsString(schemaFile);
assertTrue(fileStr.contains(stateStr), "The Schema persistentState (CSN:" + stateStr
+ ") has not been saved to " + schemaFile + " : " + fileStr);
Expand Down
Loading