Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.mongodb.internal.diagnostics.ThreadDumpOnFailureExtension
1 change: 1 addition & 0 deletions driver-core/src/test/resources/junit-platform.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
junit.jupiter.extensions.autodetection.enabled=true
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

junit-platform.properties is included in driver-core’s testArtifacts JAR (see buildSrc/src/main/kotlin/conventions/test-artifacts.gradle.kts:26-29), and several other modules depend on :driver-core:testArtifacts for their tests (e.g., driver-sync/build.gradle.kts:37-39). That means this setting may unintentionally enable JUnit Jupiter extension autodetection beyond driver-core depending on classpath resource resolution. If the intent is to scope this behavior to a specific module/test task, consider enabling it via the Gradle Test task/system property instead, or placing a shared properties file in a deliberately shared test-resources location.

Suggested change
junit.jupiter.extensions.autodetection.enabled=true
# NOTE:
# This file is included in driver-core's testArtifacts JAR and is therefore
# visible on the test classpath of other modules that depend on :driver-core:testArtifacts.
# Enabling JUnit Jupiter extension autodetection here would unintentionally
# turn it on for those modules as well.
#
# If you need autodetection, configure it in the specific module or Gradle
# Test task instead (e.g. via system property junit.jupiter.extensions.autodetection.enabled=true),
# or in a module-local junit-platform.properties that is not shared via testArtifacts.
#
# Example (do NOT uncomment here unless you really want it shared globally):
# junit.jupiter.extensions.autodetection.enabled=true

Copilot uses AI. Check for mistakes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2008-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.mongodb.internal.diagnostics;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;


import com.mongodb.internal.diagnostics.logging.Logger;
import com.mongodb.internal.diagnostics.logging.Loggers;

import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestWatcher;


Comment on lines +19 to +30
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import order/grouping here is inconsistent with the repo’s established convention (typically project com.mongodb.* imports first, then org.*, then java.*, e.g. driver-core/src/test/unit/com/mongodb/internal/connection/ConnectionPoolTest.java:19-28). Reorder the imports to match the surrounding codebase style to keep diffs consistent and reduce merge noise.

Suggested change
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import com.mongodb.internal.diagnostics.logging.Logger;
import com.mongodb.internal.diagnostics.logging.Loggers;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestWatcher;
import com.mongodb.internal.diagnostics.logging.Logger;
import com.mongodb.internal.diagnostics.logging.Loggers;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestWatcher;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

Copilot uses AI. Check for mistakes.
/**
* A JUnit 5 extension that prints a thread dump to the log when a test fails.
*/
public final class ThreadDumpOnFailureExtension implements TestWatcher {

private static final Logger LOGGER = Loggers.getLogger(ThreadDumpOnFailureExtension.class.getSimpleName());

@Override
public void testFailed(final ExtensionContext context, final Throwable cause) {
String testName = context.getDisplayName();
String threadDump = getAllThreadsDump();
LOGGER.error("Test failed: " + testName + "\nThread dump:\n" + threadDump);
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testFailed ignores the provided cause, so the log entry won’t include the exception/stack trace that triggered the failure. Logging the throwable (e.g., using the error(String, Throwable) overload) would keep the failure reason adjacent to the thread dump in Evergreen/local logs.

Suggested change
LOGGER.error("Test failed: " + testName + "\nThread dump:\n" + threadDump);
LOGGER.error("Test failed: " + testName + "\nThread dump:\n" + threadDump, cause);

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

@strogiyotec strogiyotec Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the cause will already be provided on assertion fail I don't think duplicating it for thread dumps makes sense

}
Comment on lines +39 to +43
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logs a full JVM thread dump on every failed test. When failures cascade (e.g., environment outage causing many tests to fail), this can produce very large Evergreen logs and make the original failures harder to find. Consider throttling (e.g., only dump once per JVM via an AtomicBoolean, or once per test class) and/or adding a clear header/footer delimiter so each dump is easy to locate in the log stream.

Copilot uses AI. Check for mistakes.

private static String getAllThreadsDump() {
try {
final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(
threadMXBean.isObjectMonitorUsageSupported(),
threadMXBean.isSynchronizerUsageSupported()
);
StringBuilder sb = new StringBuilder(1024);
for (ThreadInfo info : threadInfos) {
sb.append(info);
}
return sb.toString();
} catch (final SecurityException exc) {
return "Unable to get thread dump due to security manager restrictions: " + exc.getMessage();
}
}
}
Loading