Skip to content

Commit 2e72584

Browse files
authored
Merge branch 'master' into alejandro.gonzalez/APPSEC-61873-3
2 parents 77ec572 + 3123b19 commit 2e72584

File tree

42 files changed

+1480
-564
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1480
-564
lines changed

buildSrc/src/main/kotlin/dd-trace-java.configure-tests.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ tasks.withType<Test>().configureEach {
4646
// Use a task-specific user prefs directory
4747
systemProperty("java.util.prefs.userRoot", layout.buildDirectory.dir("tmp/userPrefs/$name").get().asFile.absolutePath)
4848

49+
// Enable JUnit 5 auto-detection so ConfigInversionExtension (STRICT mode) is loaded automatically
50+
systemProperty("junit.jupiter.extensions.autodetection.enabled", "true")
51+
4952
// Split up tests that want to run forked in their own separate JVM for generated tasks
5053
if (name.startsWith("forkedTest") || name.endsWith("ForkedTest")) {
5154
setExcludes(emptyList())

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/AsyncResultDecorator.java

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,6 @@
1111
*/
1212
public abstract class AsyncResultDecorator extends BaseDecorator {
1313

14-
private static final ClassValue<AsyncResultExtension> EXTENSION_CLASS_VALUE =
15-
new ClassValue<AsyncResultExtension>() {
16-
@Override
17-
protected AsyncResultExtension computeValue(Class<?> type) {
18-
return AsyncResultExtensions.registered().stream()
19-
.filter(extension -> extension.supports(type))
20-
.findFirst()
21-
.orElse(null);
22-
}
23-
};
24-
2514
/**
2615
* Look for asynchronous result and decorate it with span finisher. If the result is not
2716
* asynchronous, it will be return unmodified and span will be finished.
@@ -33,12 +22,9 @@ protected AsyncResultExtension computeValue(Class<?> type) {
3322
*/
3423
public Object wrapAsyncResultOrFinishSpan(
3524
final Object result, final Class<?> methodReturnType, final AgentSpan span) {
36-
AsyncResultExtension extension;
37-
if (result != null && (extension = EXTENSION_CLASS_VALUE.get(methodReturnType)) != null) {
38-
Object applied = extension.apply(result, span);
39-
if (applied != null) {
40-
return applied;
41-
}
25+
Object applied = AsyncResultExtensions.wrapAsyncResult(result, methodReturnType, span);
26+
if (applied != null) {
27+
return applied;
4228
}
4329
// If no extension was applied, immediately finish the span and return the original result
4430
span.finish();

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/AsyncResultExtensions.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,32 @@ public final class AsyncResultExtensions {
1616
private static final List<AsyncResultExtension> EXTENSIONS =
1717
new CopyOnWriteArrayList<>(singletonList(new CompletableAsyncResultExtension()));
1818

19+
private static final ClassValue<AsyncResultExtension> EXTENSION_CLASS_VALUE =
20+
new ClassValue<AsyncResultExtension>() {
21+
@Override
22+
protected AsyncResultExtension computeValue(Class<?> type) {
23+
return EXTENSIONS.stream()
24+
.filter(extension -> extension.supports(type))
25+
.findFirst()
26+
.orElse(null);
27+
}
28+
};
29+
30+
/**
31+
* Wraps a supported async result so the span is finished when the async computation completes.
32+
*
33+
* @return the wrapped async result, or {@code null} if the result type is unsupported or no
34+
* wrapping is applied
35+
*/
36+
public static Object wrapAsyncResult(
37+
final Object result, final Class<?> resultType, final AgentSpan span) {
38+
AsyncResultExtension extension;
39+
if (result != null && (extension = EXTENSION_CLASS_VALUE.get(resultType)) != null) {
40+
return extension.apply(result, span);
41+
}
42+
return null;
43+
}
44+
1945
/**
2046
* Registers an extension to add supported async types.
2147
*
@@ -36,11 +62,6 @@ public static void register(AsyncResultExtension extension) {
3662
}
3763
}
3864

39-
/** Returns the list of currently registered extensions. */
40-
public static List<AsyncResultExtension> registered() {
41-
return EXTENSIONS;
42-
}
43-
4465
static final class CompletableAsyncResultExtension implements AsyncResultExtension {
4566
@Override
4667
public boolean supports(Class<?> result) {

dd-java-agent/agent-ci-visibility/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ dependencies {
3737
testImplementation group: 'org.skyscreamer', name: 'jsonassert', version: '1.5.1'
3838
testImplementation group: 'org.freemarker', name: 'freemarker', version: '2.3.31'
3939
testImplementation group: 'org.msgpack', name: 'jackson-dataformat-msgpack', version: '0.9.6'
40+
testImplementation libs.bundles.mockito
4041
}
4142

4243
tasks.named("shadowJar", ShadowJar) {

dd-java-agent/agent-ci-visibility/civisibility-instrumentation-test-fixtures/src/main/groovy/datadog/trace/civisibility/CiVisibilityInstrumentationTest.groovy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ abstract class CiVisibilityInstrumentationTest extends InstrumentationSpecificat
128128
def metricCollector = Stub(CiVisibilityMetricCollectorImpl)
129129

130130
def sourcePathResolver = Stub(SourcePathResolver)
131-
sourcePathResolver.getSourcePath(_ as Class) >> DUMMY_SOURCE_PATH
132-
sourcePathResolver.getResourcePath(_ as String) >> {
133-
String path -> path
131+
sourcePathResolver.getSourcePaths(_ as Class) >> [DUMMY_SOURCE_PATH]
132+
sourcePathResolver.getResourcePaths(_ as String) >> {
133+
String path -> [path]
134134
}
135135

136136
def codeowners = Stub(Codeowners)

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/ConcurrentCoverageStore.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import datadog.trace.api.civisibility.coverage.CoverageProbes;
55
import datadog.trace.api.civisibility.coverage.CoverageStore;
66
import datadog.trace.api.civisibility.coverage.TestReport;
7-
import datadog.trace.civisibility.source.SourceResolutionException;
87
import java.util.Collection;
98
import java.util.Map;
109
import java.util.concurrent.ConcurrentHashMap;
@@ -37,18 +36,13 @@ private T create(Thread thread) {
3736

3837
@Override
3938
public boolean report(DDTraceId testSessionId, Long testSuiteId, long testSpanId) {
40-
try {
41-
report = report(testSessionId, testSuiteId, testSpanId, probes.values());
42-
return report != null && report.isNotEmpty();
43-
} catch (SourceResolutionException e) {
44-
return false;
45-
}
39+
report = report(testSessionId, testSuiteId, testSpanId, probes.values());
40+
return report != null && report.isNotEmpty();
4641
}
4742

4843
@Nullable
4944
protected abstract TestReport report(
50-
DDTraceId testSessionId, Long testSuiteId, long testSpanId, Collection<T> probes)
51-
throws SourceResolutionException;
45+
DDTraceId testSessionId, Long testSuiteId, long testSpanId, Collection<T> probes);
5246

5347
@Nullable
5448
@Override

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/file/FileCoverageStore.java

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import datadog.trace.api.civisibility.telemetry.tag.CoverageErrorType;
1212
import datadog.trace.civisibility.coverage.ConcurrentCoverageStore;
1313
import datadog.trace.civisibility.source.SourcePathResolver;
14-
import datadog.trace.civisibility.source.SourceResolutionException;
1514
import java.util.ArrayList;
1615
import java.util.Collection;
1716
import java.util.Collections;
@@ -47,61 +46,54 @@ private FileCoverageStore(
4746
@Nullable
4847
@Override
4948
protected TestReport report(
50-
DDTraceId testSessionId, Long testSuiteId, long testSpanId, Collection<FileProbes> probes)
51-
throws SourceResolutionException {
52-
try {
53-
Set<Class<?>> combinedClasses = Collections.newSetFromMap(new IdentityHashMap<>());
54-
Collection<String> combinedNonCodeResources = new HashSet<>();
55-
56-
for (FileProbes probe : probes) {
57-
combinedClasses.addAll(probe.getCoveredClasses());
58-
combinedNonCodeResources.addAll(probe.getNonCodeResources());
59-
}
49+
DDTraceId testSessionId, Long testSuiteId, long testSpanId, Collection<FileProbes> probes) {
50+
Set<Class<?>> combinedClasses = Collections.newSetFromMap(new IdentityHashMap<>());
51+
Collection<String> combinedNonCodeResources = new HashSet<>();
6052

61-
if (combinedClasses.isEmpty() && combinedNonCodeResources.isEmpty()) {
62-
return null;
63-
}
53+
for (FileProbes probe : probes) {
54+
combinedClasses.addAll(probe.getCoveredClasses());
55+
combinedNonCodeResources.addAll(probe.getNonCodeResources());
56+
}
6457

65-
Set<String> coveredPaths = set(combinedClasses.size() + combinedNonCodeResources.size());
66-
for (Class<?> clazz : combinedClasses) {
67-
String sourcePath = sourcePathResolver.getSourcePath(clazz);
68-
if (sourcePath == null) {
69-
log.debug(
70-
"Skipping coverage reporting for {} because source path could not be determined",
71-
clazz);
72-
metrics.add(CiVisibilityCountMetric.CODE_COVERAGE_ERRORS, 1, CoverageErrorType.PATH);
73-
continue;
74-
}
75-
coveredPaths.add(sourcePath);
76-
}
58+
if (combinedClasses.isEmpty() && combinedNonCodeResources.isEmpty()) {
59+
return null;
60+
}
7761

78-
for (String nonCodeResource : combinedNonCodeResources) {
79-
String resourcePath = sourcePathResolver.getResourcePath(nonCodeResource);
80-
if (resourcePath == null) {
81-
log.debug(
82-
"Skipping coverage reporting for {} because resource path could not be determined",
83-
nonCodeResource);
84-
metrics.add(CiVisibilityCountMetric.CODE_COVERAGE_ERRORS, 1, CoverageErrorType.PATH);
85-
continue;
86-
}
87-
coveredPaths.add(resourcePath);
62+
Set<String> coveredPaths = set(combinedClasses.size() + combinedNonCodeResources.size());
63+
for (Class<?> clazz : combinedClasses) {
64+
Collection<String> sourcePaths = sourcePathResolver.getSourcePaths(clazz);
65+
if (sourcePaths.isEmpty()) {
66+
log.debug(
67+
"Skipping coverage reporting for {} because source path could not be determined",
68+
clazz);
69+
metrics.add(CiVisibilityCountMetric.CODE_COVERAGE_ERRORS, 1, CoverageErrorType.PATH);
70+
continue;
8871
}
72+
coveredPaths.addAll(sourcePaths);
73+
}
8974

90-
List<TestReportFileEntry> fileEntries = new ArrayList<>(coveredPaths.size());
91-
for (String path : coveredPaths) {
92-
fileEntries.add(new TestReportFileEntry(path, null));
75+
for (String nonCodeResource : combinedNonCodeResources) {
76+
Collection<String> resourcePaths = sourcePathResolver.getResourcePaths(nonCodeResource);
77+
if (resourcePaths.isEmpty()) {
78+
log.debug(
79+
"Skipping coverage reporting for {} because resource path could not be determined",
80+
nonCodeResource);
81+
metrics.add(CiVisibilityCountMetric.CODE_COVERAGE_ERRORS, 1, CoverageErrorType.PATH);
82+
continue;
9383
}
84+
coveredPaths.addAll(resourcePaths);
85+
}
9486

95-
TestReport report = new TestReport(testSessionId, testSuiteId, testSpanId, fileEntries);
96-
metrics.add(
97-
CiVisibilityDistributionMetric.CODE_COVERAGE_FILES,
98-
report.getTestReportFileEntries().size());
99-
return report;
100-
101-
} catch (Exception e) {
102-
metrics.add(CiVisibilityCountMetric.CODE_COVERAGE_ERRORS, 1);
103-
throw e;
87+
List<TestReportFileEntry> fileEntries = new ArrayList<>(coveredPaths.size());
88+
for (String path : coveredPaths) {
89+
fileEntries.add(new TestReportFileEntry(path, null));
10490
}
91+
92+
TestReport report = new TestReport(testSessionId, testSuiteId, testSpanId, fileEntries);
93+
metrics.add(
94+
CiVisibilityDistributionMetric.CODE_COVERAGE_FILES,
95+
report.getTestReportFileEntries().size());
96+
return report;
10597
}
10698

10799
private static <T> Set<T> set(int size) {

0 commit comments

Comments
 (0)