From 8bc5a4d06236472de770780c07407f0558c4203c Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 12 Sep 2025 09:33:39 +0200 Subject: [PATCH 1/2] feat(testing): Improve instrumented test agent creation --- .../test/BootstrapClasspathSetupListener.java | 23 ++++++++++--------- .../agent/test/utils/ClasspathUtils.java | 21 ++++++++--------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/dd-java-agent/instrumentation-testing/src/main/java/datadog/trace/agent/test/BootstrapClasspathSetupListener.java b/dd-java-agent/instrumentation-testing/src/main/java/datadog/trace/agent/test/BootstrapClasspathSetupListener.java index 58a4c1cc9a7..9376a71a81b 100644 --- a/dd-java-agent/instrumentation-testing/src/main/java/datadog/trace/agent/test/BootstrapClasspathSetupListener.java +++ b/dd-java-agent/instrumentation-testing/src/main/java/datadog/trace/agent/test/BootstrapClasspathSetupListener.java @@ -1,10 +1,7 @@ package datadog.trace.agent.test; -import static com.google.common.base.StandardSystemProperty.JAVA_CLASS_PATH; -import static com.google.common.base.StandardSystemProperty.PATH_SEPARATOR; +import static java.io.File.pathSeparator; -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; import com.google.common.reflect.ClassPath; import datadog.trace.agent.test.utils.ClasspathUtils; import datadog.trace.bootstrap.BootstrapProxy; @@ -14,9 +11,11 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -111,26 +110,28 @@ private static ClassPath computeTestClasspath() { */ @SuppressForbidden private static ClassLoader buildJavaClassPathClassLoader() { - final ImmutableList.Builder urls = ImmutableList.builder(); - for (final String entry : Splitter.on(PATH_SEPARATOR.value()).split(JAVA_CLASS_PATH.value())) { + List urls = new ArrayList<>(); + String classPath = System.getProperty("java.class.path", ""); + for (String entry : classPath.split(pathSeparator)) { try { + File pathEntry = new File(entry); try { - urls.add(new File(entry).toURI().toURL()); - } catch (final SecurityException e) { // File.toURI checks to see if the file is a directory - urls.add(new URL("file", null, new File(entry).getAbsolutePath())); + urls.add(pathEntry.toURI().toURL()); + } catch (final SecurityException e) { + urls.add(new URL("file", null, pathEntry.getAbsolutePath())); } } catch (final MalformedURLException e) { System.err.printf( "Error injecting bootstrap jar: Malformed classpath entry: %s. %s%n", entry, e); } } - return new URLClassLoader(urls.build().toArray(new URL[0]), null); + return new URLClassLoader(urls.toArray(new URL[0]), null); } private static void setupBootstrapClasspath() { // Ensure there weren't any bootstrap classes loaded prematurely. Set prematureBootstrapClasses = new TreeSet<>(); - for (Class clazz : ByteBuddyAgent.getInstrumentation().getAllLoadedClasses()) { + for (Class clazz : ByteBuddyAgent.getInstrumentation().getAllLoadedClasses()) { if (isBootstrapClass(clazz) && clazz.getClassLoader() != null && !clazz.getName().equals("datadog.trace.api.DisableTestTrace") diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/ClasspathUtils.java b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/ClasspathUtils.java index 30a9b0f2727..30cd4104029 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/ClasspathUtils.java +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/ClasspathUtils.java @@ -47,27 +47,24 @@ public static byte[] convertToByteArray(final Class clazz) throws IOException * @param loader classloader used to load bytes * @param resourceNames names of resources to copy into the new jar * @return the location of the newly created jar. - * @throws IOException + * @throws IOException if the jar file cannot be created. */ public static URL createJarWithClasses(final ClassLoader loader, final String... resourceNames) throws IOException { - final File tmpJar = File.createTempFile(UUID.randomUUID().toString() + "", ".jar"); + final File tmpJar = File.createTempFile(UUID.randomUUID().toString(), ".jar"); tmpJar.deleteOnExit(); final Manifest manifest = new Manifest(); - final JarOutputStream target = new JarOutputStream(new FileOutputStream(tmpJar), manifest); - for (final String resourceName : resourceNames) { - InputStream is = null; - try { - is = loader.getResourceAsStream(resourceName); - addToJar(resourceName, convertToByteArray(is), target); - } finally { - if (null != is) { - is.close(); + try (final JarOutputStream target = + new JarOutputStream(new FileOutputStream(tmpJar), manifest)) { + for (final String resourceName : resourceNames) { + try (InputStream is = loader.getResourceAsStream(resourceName)) { + if (is != null) { + addToJar(resourceName, convertToByteArray(is), target); + } } } } - target.close(); return tmpJar.toURI().toURL(); } From 42171792f2ef068f10e48c19c4811b5d930554f8 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 12 Sep 2025 09:33:45 +0200 Subject: [PATCH 2/2] chore: typo --- .../play-ws-1/src/test/groovy/PlayWSClientTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dd-java-agent/instrumentation/play-ws-1/src/test/groovy/PlayWSClientTest.groovy b/dd-java-agent/instrumentation/play-ws-1/src/test/groovy/PlayWSClientTest.groovy index c26192c071a..db35a8baec7 100644 --- a/dd-java-agent/instrumentation/play-ws-1/src/test/groovy/PlayWSClientTest.groovy +++ b/dd-java-agent/instrumentation/play-ws-1/src/test/groovy/PlayWSClientTest.groovy @@ -54,7 +54,7 @@ class PlayJavaStreamedWSClientTest extends PlayWSClientTestBase { runInAdHocThread(callback) }).toCompletableFuture().get(5, TimeUnit.SECONDS) - // The status can be ready before the body so explicity call wait for body to be ready + // The status can be ready before the body so explicitly call wait for body to be ready wsResponse.getBodyAsSource().runFold("", { acc, out -> "" }, materializer) .toCompletableFuture().get(5, TimeUnit.SECONDS) return wsResponse.getStatus() @@ -119,7 +119,7 @@ class PlayScalaStreamedWSClientTest extends PlayWSClientTestBase { play.api.libs.ws.StandaloneWSResponse wsResponse = Await.result(futureResponse, Duration.apply(5, TimeUnit.SECONDS)) - // The status can be ready before the body so explicity call wait for body to be ready + // The status can be ready before the body so explicitly call wait for body to be ready Await.result( wsResponse.bodyAsSource().runFold("", { acc, out -> "" }, materializer), Duration.apply(5, TimeUnit.SECONDS))