8000 Add line probe exploration tests · DataDog/dd-trace-java@3423769 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3423769

Browse files
committed
Add line probe exploration tests
Refactor InstrumentTheWorld config to take a string indicating the usage of method or line probe for the process. Rename jobs to indicate line or method probes
1 parent 0e18e0e commit 3423769

File tree

17 files changed

+218
-39
lines changed

17 files changed

+218
-39
lines changed

.gitlab/exploration-tests.yml

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,32 +45,62 @@ build-exploration-tests-image:
4545
- "*_surefire-reports.tar.gz"
4646
- "*_debugger-dumps.tar.gz"
4747

48-
exploration-tests-jsoup:
48+
exploration-tests-method-jsoup:
4949
needs: [ build ]
5050
dependencies:
5151
- build
5252
<<: *common-exploration-tests
5353
variables:
5454
PROJECT: jsoup
5555
script:
56-
- ./run-exploration-tests.sh "$PROJECT" "mvn verify" "include_${PROJECT}.txt" "exclude_${PROJECT}.txt"
56+
- ./run-exploration-tests.sh "method" "$PROJECT" "mvn verify" "include_${PROJECT}.txt" "exclude_${PROJECT}.txt"
5757

58-
exploration-tests-jackson-core:
58+
exploration-tests-line-jsoup:
59+
needs: [ build ]
60+
dependencies:
61+
- build
62+
<<: *common-exploration-tests
63+
variables:
64+
PROJECT: jsoup
65+
script:
66+
- ./run-exploration-tests.sh "line" "$PROJECT" "mvn verify" "include_${PROJECT}.txt" "exclude_${PROJECT}.txt"
67+
68+
exploration-tests-method-jackson-core:
69+
needs: [ build ]
70+
dependencies:
71+
- build
72+
<<: *common-exploration-tests
73+
variables:
74+
PROJECT: jackson-core
75+
script:
76+
- ./run-exploration-tests.sh "method" "$PROJECT" "mvn verify" "include_${PROJECT}.txt" "exclude_${PROJECT}.txt"
77+
78+
exploration-tests-line-jackson-core:
5979
needs: [ build ]
6080
dependencies:
6181
- build
6282
<<: *common-exploration-tests
6383
variables:
6484
PROJECT: jackson-core
6585
script:
66-
- ./run-exploration-tests.sh "$PROJECT" "mvn verify" "include_${PROJECT}.txt" "exclude_${PROJECT}.txt"
86+
- ./run-exploration-tests.sh "line" "$PROJECT" "mvn verify" "include_${PROJECT}.txt" "exclude_${PROJECT}.txt"
87+
88+
exploration-tests-method-jackson-databind:
89+
needs: [ build ]
90+
dependencies:
91+
- build
92+
<<: *common-exploration-tests
93+
variables:
94+
PROJECT: jackson-databind
95+
script:
96+
- ./run-exploration-tests.sh "method" "$PROJECT" "./mvnw verify" "include_${PROJECT}.txt" "exclude_$PROJECT.txt"
6797

68-
exploration-tests-jackson-databind:
98+
exploration-tests-line-jackson-databind:
6999
needs: [ build ]
70100
dependencies:
71101
- build
72102
<<: *common-exploration-tests
73103
variables:
74104
PROJECT: jackson-databind
75105
script:
76-
- ./run-exploration-tests.sh "$PROJECT" "./mvnw verify" "exclude_$PROJECT.txt"
106+
- ./run-exploration-tests.sh "line" "$PROJECT" "./mvnw verify" "include_${PROJECT}.txt" "exclude_line_$PROJECT.txt"

dd-java-agent/agent-debugger/exploration-tests/Dockerfile.exploration-tests

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ COPY jackson-core_exploration-tests.patch .
2929
RUN cd jackson-core && git apply /exploration-tests/jackson-core_exploration-tests.patch
3030
RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && cd jackson-core && mvn verify -DskipTests=true"
3131
RUN git clone -b 2.16 https://github.com/FasterXML/jackson-databind.git
32+
COPY jackson-databind_exploration-tests.patch .
33+
# fix tests that are failing because too deep recrursion
34+
RUN cd jackson-databind && git apply /exploration-tests/jackson-databind_exploration-tests.patch
3235
RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && cd jackson-databind && mvn verify -DskipTests=true"
3336

3437
# Netty
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
com/fasterxml/jackson/databind/BaseTest
2+
com/fasterxml/jackson/databind/BaseMapTest*
23
com/fasterxml/jackson/databind/type/TypeFactory
34

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
com/fasterxml/jackson/databind/BaseTest
2+
com/fasterxml/jackson/databind/BaseMapTest*
3+
com/fasterxml/jackson/databind/type/TypeFactory

dd-java-agent/agent-debugger/exploration-tests/jackson-core_exploration-tests.patch

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,27 @@ index 2f7957d1..7a8ea388 100644
1111
int count = errorCount.get();
1212

1313
if (count > 0) {
14+
diff --git forkSrcPrefix/src/test/java/com/fasterxml/jackson/core/io/schubfach/DoubleToDecimalTest.java forkDstPrefix/src/test/java/com/fasterxml/jackson/core/io/schubfach/DoubleToDecimalTest.java
15+
index 9752fd990959aa0b07382973d37c6f84b7a08fea..f8e6296e91fe1a8965c27727f111d7ffc77e434d 100644
16+
--- forkSrcPrefix/src/test/java/com/fasterxml/jackson/core/io/schubfach/DoubleToDecimalTest.java
17+
+++ forkDstPrefix/src/test/java/com/fasterxml/jackson/core/io/schubfach/DoubleToDecimalTest.java
18+
@@ -142,6 +142,6 @@ public class DoubleToDecimalTest {
19+
@Test
20+
void randomNumberTests() {
21+
// 29-Nov-2022, tatu: Reduce from 1M due to slowness
22+
- DoubleToDecimalChecker.randomNumberTests(250_000, new Random());
23+
+ DoubleToDecimalChecker.randomNumberTests(25_000, new Random());
24+
}
25+
}
26+
diff --git forkSrcPrefix/src/test/java/com/fasterxml/jackson/core/io/schubfach/FloatToDecimalTest.java forkDstPrefix/src/test/java/com/fasterxml/jackson/core/io/schubfach/FloatToDecimalTest.java
27+
index f6893940dd4aeeb4f4e17c7a21fc11a4594c369a..8563578eaa7b30b376f03e17ef3c25d3baa09f0e 100644
28+
--- forkSrcPrefix/src/test/java/com/fasterxml/jackson/core/io/schubfach/FloatToDecimalTest.java
29+
+++ forkDstPrefix/src/test/java/com/fasterxml/jackson/core/io/schubfach/FloatToDecimalTest.java
30+
@@ -119,6 +119,6 @@ public class FloatToDecimalTest {
31+
32+
@Test
33+
void randomNumberTests() {
34+
- FloatToDecimalChecker.randomNumberTests(1_000_000, new Random());
35+
+ FloatToDecimalChecker.randomNumberTests(25_000, new Random());
36+
}
37+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
diff --git forkSrcPrefix/src/test/java/com/fasterxml/jackson/databind/misc/ThreadSafety1759Test.java forkDstPrefix/src/test/java/com/fasterxml/jackson/databind/misc/ThreadSafety1759Test.java
2+
index 68c52b600550268242d16614e6143104ce37961d..29f453c8c0e07d139edd095d1614dd287aa5d283 100644
3+
--- forkSrcPrefix/src/test/java/com/fasterxml/jackson/databind/misc/ThreadSafety1759Test.java
4+
+++ forkDstPrefix/src/test/java/com/fasterxml/jackson/databind/misc/ThreadSafety1759Test.java
5+
@@ -41,7 +41,7 @@ public class ThreadSafety1759Test extends BaseMapTest
6+
}
7+
executor.shutdown();
8+
for (Future<Throwable> f : results) {
9+
- Throwable t = f.get(5, TimeUnit.SECONDS);
10+
+ Throwable t = f.get(30, TimeUnit.SECONDS);
11+
if (t != null) {
12+
fail("Exception during processing: "+t.getMessage());
13+
}
14+
diff --git forkSrcPrefix/src/test/java/com/fasterxml/jackson/databind/ser/dos/CyclicDataSerTest.java forkDstPrefix/src/test/java/com/fasterxml/jackson/databind/ser/dos/CyclicDataSerTest.java
15+
index aff54f8c731181eb17158c8329134b267529cd75..72673defcbfa493c707e2beab3b83573b43e6208 100644
16+
--- forkSrcPrefix/src/test/java/com/fasterxml/jackson/databind/ser/dos/CyclicDataSerTest.java
17+
+++ forkDstPrefix/src/test/java/com/fasterxml/jackson/databind/ser/dos/CyclicDataSerTest.java
18+
@@ -46,16 +46,16 @@ public class CyclicDataSerTest
19+
}
20+
21+
public void testListWithSelfReference() throws Exception {
22+
- List<Object> list = new ArrayList<>();
23+
- list.add(list);
24+
- try {
25+
- writeAndMap(MAPPER, list);
26+
- fail("expected DatabindException");
27+
- } catch (DatabindException e) {
28+
- String exceptionPrefix = String.format("Document nesting depth (%d) exceeds the maximum allowed",
29+
- StreamWriteConstraints.DEFAULT_MAX_DEPTH + 1);
30+
- assertTrue("DatabindException message is as expected?",
31+
- e.getMessage().startsWith(exceptionPrefix));
32+
- }
33+
+// List<Object> list = new ArrayList<>();
34+
+// list.add(list);
35+
+// try {
36+
+// writeAndMap(MAPPER, list);
37+
+// fail("expected DatabindException");
38+
+// } catch (DatabindException e) {
39+
+// String exceptionPrefix = String.format("Document nesting depth (%d) exceeds the maximum allowed",
40+
+// StreamWriteConstraints.DEFAULT_MAX_DEPTH + 1);
41+
+// assertTrue("DatabindExcept B41A ion message is as expected?",
42+
+// e.getMessage().startsWith(exceptionPrefix));
43+
+// }
44+
}
45+
}
46+
diff --git forkSrcPrefix/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepJsonNodeSerTest.java forkDstPrefix/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepJsonNodeSerTest.java
47+
index 0a4860bc91101ae60d15bfd9f978207926a1a97a..58601f3ad33cc48ad27cb3914daf9d3146e1b181 100644
48+
--- forkSrcPrefix/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepJsonNodeSerTest.java
49+
+++ forkDstPrefix/src/test/java/com/fasterxml/jackson/databind/deser/dos/DeepJsonNodeSerTest.java
50+
@@ -41,9 +41,9 @@ public class DeepJsonNodeSerTest extends BaseMapTest
51+
52+
public void testDeepNodeSerNoStreamingLimits() throws Exception
53+
{
54+
- JsonNode jsonNode = NO_LIMITS_MAPPER.readTree(_nestedDoc(TEST_NESTING));
55+
- String json = NO_LIMITS_MAPPER.writeValueAsString(jsonNode);
56+
- assertNotNull(json);
57+
+// JsonNode jsonNode = NO_LIMITS_MAPPER.readTree(_nestedDoc(TEST_NESTING));
58+
+// String json = NO_LIMITS_MAPPER.writeValueAsString(jsonNode);
59+
+// assertNotNull(json);
60+
}
61+
62+
private String _nestedDoc(int nesting) {

dd-java-agent/agent-debugger/exploration-tests/run-exploration-tests.sh

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#!/usr/bin/env bash
22
set -uo pipefail
3-
NAME=$1
4-
COMMAND=$2
5-
PROJECT_INCLUDE_FILE=${3:-}
6-
PROJECT_EXCLUDE_FILE=${4:-}
3+
ITW_TYPE=${1:-"method"}
4+
NAME=$2
5+
COMMAND=$3
6+
PROJECT_INCLUDE_FILE=${4:-}
7+
PROJECT_EXCLUDE_FILE=${5:-}
78
echo " === running debugger java exploration tests === "
8-
export JAVA_TOOL_OPTIONS="-javaagent:`pwd`/dd-java-agent.jar -Ddatadog.slf4j.simpleLogger.log.com.datadog.debugger=debug -Ddd.trace.enabled=false -Ddd.dynamic.instrumentation.enabled=true -Ddd.dynamic.instrumentation.instrument.the.world=true -Ddd.dynamic.instrumentation.classfile.dump.enabled=true -Ddd.dynamic.instrumentation.verify.bytecode=false -Ddd.dynamic.instrumentation.include.files=/exploration-tests/$PROJECT_INCLUDE_FILE -Ddd.dynamic.instrumentation.exclude.files=/exploration-tests/$PROJECT_EXCLUDE_FILE"
9+
export JAVA_TOOL_OPTIONS="-javaagent:`pwd`/dd-java-agent.jar -Ddatadog.slf4j.simpleLogger.log.com.datadog.debugger=debug -Ddd.trace.enabled=false -Ddd.dynamic.instrumentation.enabled=true -Ddd.dynamic.instrumentation.instrument.the.world=$ITW_TYPE -Ddd.dynamic.instrumentation.classfile.dump.enabled=true -Ddd.dynamic.instrumentation.verify.bytecode=false -Ddd.dynamic.instrumentation.include.files=/exploration-tests/$PROJECT_INCLUDE_FILE -Ddd.dynamic.instrumentation.exclude.files=/exploration-tests/$PROJECT_EXCLUDE_FILE"
910
echo "$JAVA_TOOL_OPTIONS"
1011
cd $NAME
1112
echo "Building repository $NAME..."

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerAgent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public static synchronized void run(Instrumentation inst, SharedCommunicationObj
8989
}
9090
if (config.isDynamicInstrumentationEnabled()) {
9191
startDynamicInstrumentation();
92-
if (config.isDynamicInstrumentationInstrumentTheWorld()) {
92+
if (config.getDynamicInstrumentationInstrumentTheWorld() != null) {
9393
setupInstrumentTheWorldTransformer(config, instrumentation, sink);
9494
}
9595
}

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerTransformer.java

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import java.util.Map;
5353
import java.util.Set;
5454
import java.util.concurrent.ConcurrentHashMap;
55+
import java.util.function.BiConsumer;
5556
import java.util.regex.Pattern;
5657
import net.bytebuddy.description.type.TypeDescription;
5758
import net.bytebuddy.pool.TypePool;
@@ -103,6 +104,7 @@ public class DebuggerTransformer implements ClassFileTransformer {
103104
private final Set<String> includeMethods;
104105
private final Trie includeTrie;
105106
private final Map<String, LogProbe> instrumentTheWorldProbes;
107+
private final BiConsumer<MethodInfo, List<ProbeDefinition>> probeCreator;
106108

107109
public interface InstrumentationListener {
108110
void instrumentationResult(ProbeDefinition definition, InstrumentationResult result);
@@ -119,7 +121,8 @@ public DebuggerTransformer(
119121
this.denyListHelper = new DenyListHelper(configuration.getDenyList());
120122
this.listener = listener;
121123
this.debuggerSink = debuggerSink;
122-
this.instrumentTheWorld = config.isDynamicInstrumentationInstrumentTheWorld();
124+
String itwType = config.getDynamicInstrumentationInstrumentTheWorld();
125+
this.instrumentTheWorld = itwType != null;
123126
if (this.instrumentTheWorld) {
124127
instrumentTheWorldProbes = new ConcurrentHashMap<>();
125128
excludeTrie = new Trie();
@@ -138,6 +141,17 @@ public DebuggerTransformer(
138141
includeTrie,
139142
includeClasses,
140143
includeMethods);
144+
if (itwType.equals("method")) {
145+
probeCreator = this::createMethodProbe;
146+
} else if (itwType.equals("line")) {
147+
probeCreator = this::createLineProbes;
148+
} else {
149+
log.warn(
150+
"Invalid value for 'dd.debugger.instrument-the-world' property: {}. "
151+
+ "Valid values are 'method' or 'line'.",
152+
itwType);
153+
probeCreator = null;
154+
}
141155
} else {
142156
instrumentTheWorldProbes = null;
143157
excludeTrie = null;
@@ -146,6 +160,7 @@ public DebuggerTransformer(
146160
includeTrie = null;
147161
includeClasses = null;
148162
includeMethods = null;
163+
probeCreator = null;
149164
}
150165
}
151166

@@ -211,8 +226,7 @@ public byte[] transform(
211226
ProtectionDomain protectionDomain,
212227
byte[] classfileBuffer) {
213228
if (instrumentTheWorld) {
214-
return transformTheWorld(
215-
loader, classFilePath, classBeingRedefined, protectionDomain, classfileBuffer);
229+
return transformTheWorld(loader, classFilePath, protectionDomain, classfileBuffer);
216230
}
217231
if (skipInstrumentation(loader, classFilePath)) {
218232
return null;
@@ -264,7 +278,6 @@ private boolean skipInstrumentation(ClassLoader loader, String classFilePath) {
264278
private byte[] transformTheWorld(
265279
ClassLoader loader,
266280
String classFilePath,
267-
Class<?> classBeingRedefined,
268281
ProtectionDomain protectionDomain,
269282
byte[] classfileBuffer) {
270283
try {
@@ -303,16 +316,11 @@ private byte[] transformTheWorld(
303316
}
304317
List<ProbeDefinition> probes = new ArrayList<>();
305318
Set<String> methodNames = new HashSet<>();
319+
ClassFileLines classFileLines = new ClassFileLines(classNode);
306320
for (MethodNode methodNode : classNode.methods) {
307321
if (isMethodIncludedForTransformation(methodNode, classNode, methodNames)) {
308-
LogProbe probe =
309-
LogProbe.builder()
310-
.probeId(RandomUtils.randomUUID().toString(), 0)
311-
.where(classNode.name, methodNode.name)
312-
.captureSnapshot(false)
313-
.build();
314-
probes.add(probe);
315-
instrumentTheWorldProbes.put(probe.getProbeId().getEncodedId(), probe);
322+
MethodInfo methodInfo = new MethodInfo(loader, classNode, methodNode, classFileLines);
323+
probeCreator.accept(methodInfo, probes);
316324
}
317325
}
318326
boolean transformed = performInstrumentation(loader, classFilePath, probes, classNode);
@@ -342,6 +350,39 @@ private boolean isMethodIncludedForTransformation(
342350
return methodNames.add(methodNode.name);
343351
}
344352

353+
private void createMethodProbe(MethodInfo methodInfo, List<ProbeDefinition> probes) {
354+
LogProbe probe =
355+
LogProbe.builder()
356+
.probeId(RandomUtils.randomUUID().toString(), 0)
357+
.where(methodInfo.getClassNode().name, methodInfo.getMethodNode().name)
358+
.captureSnapshot(false)
359+
.build();
360+
probes.add(probe);
361+
instrumentTheWorldProbes.put(probe.getProbeId().getEncodedId(), probe);
362+
}
363+
364+
private void createLineProbes(MethodInfo methodInfo, List<ProbeDefinition> probes) {
365+
if (methodInfo.getMethodName().equals("<init>")) {
366+
// skip constructor for now to avoid dealing with code before super calls
367+
return;
368+
}
369+
if ((methodInfo.getMethodNode().access & Opcodes.ACC_SYNTHETIC) != 0) {
370+
// skip synthetic methods
371+
return;
372+
}
373+
List<Integer> lineNumbers = methodInfo.getLineNumbers();
374+
for (Integer lineNumber : lineNumbers) {
375+
LogProbe probe =
376+
LogProbe.builder()
377+
.probeId(RandomUtils.randomUUID().toString(), 0)
378+
.where(methodInfo.getSourceFileName(), lineNumber)
379+
.captureSnapshot(false)
380+
.build();
381+
probes.add(probe);
382+
instrumentTheWorldProbes.put(probe.getProbeId().getEncodedId(), probe);
383+
}
384+
}
385+
345386
private boolean isClassLoaderRelated(ClassNode classNode) {
346387
return classNode.superName.equals("java/lang/ClassLoader")
347388
|| classNode.superName.equals("java/net/URLClassLoader")

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ private void collectLocalVariables(AbstractInsnNode location, InsnList insnList)
910910
}
911911

912912
if (methodNode.localVariables == null || methodNode.localVariables.isEmpty()) {
913-
if (!Config.get().isDynamicInstrumentationInstrumentTheWorld()) {
913+
if (Config.get().getDynamicInstrumentationInstrumentTheWorld() == null) {
914914
reportWarning("Missing local variable debug info");
915915
}
916916 57AE
// no local variables info - bail out
@@ -1136,7 +1136,7 @@ private static List<FieldNode> extractStaticFields(
11361136
}
11371137
}
11381138
}
1139-
if (!Config.get().isDynamicInstrumentationInstrumentTheWorld()) {
1139+
if (Config.get().getDynamicInstrumentationInstrumentTheWorld() == null) {
11401140
// Collects inherited static fields only if the ITW mode is not enabled
11411141
// because it can lead to LinkageError: attempted duplicate class definition
11421142
// for example, when a probe is located in method overridden in enum element

0 commit comments

Comments
 (0)
0