Skip to content

Commit

Permalink
Replace segments with bitmaps in per-test code coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
nikita-tkachenko-datadog committed Jul 4, 2024
1 parent 1496a6c commit 3762731
Show file tree
Hide file tree
Showing 16 changed files with 68 additions and 174 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import datadog.trace.civisibility.source.SourcePathResolver;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
Expand Down Expand Up @@ -134,7 +133,7 @@ public boolean report(Long testSessionId, Long testSuiteId, long spanId) {

List<TestReportFileEntry> fileEntries = new ArrayList<>(coveredPaths.size());
for (String path : coveredPaths) {
TestReportFileEntry fileEntry = new TestReportFileEntry(path, Collections.emptyList());
TestReportFileEntry fileEntry = new TestReportFileEntry(path, null);
fileEntries.add(fileEntry);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package datadog.trace.civisibility.coverage;

import datadog.trace.api.civisibility.coverage.TestReportFileEntry;
import java.util.List;
import java.util.BitSet;
import org.jacoco.core.analysis.IClassCoverage;
import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.ICoverageVisitor;

public class SourceAnalyzer implements ICoverageVisitor {

private final List<TestReportFileEntry.Segment> segments;
private final BitSet coveredLines;

public SourceAnalyzer(List<TestReportFileEntry.Segment> segments) {
this.segments = segments;
public SourceAnalyzer(BitSet coveredLines) {
this.coveredLines = coveredLines;
}

@Override
Expand All @@ -26,17 +25,10 @@ public void visitCoverage(IClassCoverage coverage) {
}

int lastLine = coverage.getLastLine();
int line = firstLine;
while (line <= lastLine) {

for (int line = firstLine; line <= lastLine; line++) {
if (coverage.getLine(line).getStatus() >= ICounter.FULLY_COVERED) {
int start = line++;
while (line <= lastLine && coverage.getLine(line).getStatus() >= ICounter.FULLY_COVERED) {
line++;
}
segments.add(new TestReportFileEntry.Segment(start, -1, line - 1, -1, -1));

} else {
line++;
coveredLines.set(line);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
import datadog.trace.civisibility.source.Utils;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
Expand Down Expand Up @@ -107,7 +106,7 @@ public boolean report(Long testSessionId, Long testSuiteId, long spanId) {
return false;
}

Map<String, List<TestReportFileEntry.Segment>> segmentsBySourcePath = new HashMap<>();
Map<String, BitSet> coveredLinesBySourcePath = new HashMap<>();
for (Map.Entry<Class<?>, ExecutionDataAdapter> e : probeActivations.entrySet()) {
ExecutionDataAdapter executionDataAdapter = e.getValue();
String className = executionDataAdapter.getClassName();
Expand All @@ -132,15 +131,15 @@ public boolean report(Long testSessionId, Long testSuiteId, long spanId) {
}

try (InputStream is = Utils.getClassStream(clazz)) {
List<TestReportFileEntry.Segment> segments =
segmentsBySourcePath.computeIfAbsent(sourcePath, key -> new ArrayList<>());
BitSet coveredLines =
coveredLinesBySourcePath.computeIfAbsent(sourcePath, key -> new BitSet());

ExecutionDataStore store = new ExecutionDataStore();
store.put(executionDataAdapter.toExecutionData(totalProbeCount));

// TODO optimize this part to avoid parsing
// the same class multiple times for different test cases
Analyzer analyzer = new Analyzer(store, new SourceAnalyzer(segments));
Analyzer analyzer = new Analyzer(store, new SourceAnalyzer(coveredLines));
analyzer.analyzeClass(is, null);

} catch (Exception exception) {
Expand All @@ -153,16 +152,11 @@ public boolean report(Long testSessionId, Long testSuiteId, long spanId) {
}
}

List<TestReportFileEntry> fileEntries = new ArrayList<>(segmentsBySourcePath.size());
for (Map.Entry<String, List<TestReportFileEntry.Segment>> e :
segmentsBySourcePath.entrySet()) {
List<TestReportFileEntry> fileEntries = new ArrayList<>(coveredLinesBySourcePath.size());
for (Map.Entry<String, BitSet> e : coveredLinesBySourcePath.entrySet()) {
String sourcePath = e.getKey();

List<TestReportFileEntry.Segment> segments = e.getValue();
segments.sort(Comparator.naturalOrder());

List<TestReportFileEntry.Segment> compressedSegments = getCompressedSegments(segments);
fileEntries.add(new TestReportFileEntry(sourcePath, compressedSegments));
BitSet coveredLines = e.getValue();
fileEntries.add(new TestReportFileEntry(sourcePath, coveredLines));
}

for (String nonCodeResource : nonCodeResources) {
Expand All @@ -175,8 +169,7 @@ public boolean report(Long testSessionId, Long testSuiteId, long spanId) {
CiVisibilityCountMetric.CODE_COVERAGE_ERRORS, 1, CoverageErrorType.PATH);
continue;
}
TestReportFileEntry fileEntry =
new TestReportFileEntry(resourcePath, Collections.emptyList());
TestReportFileEntry fileEntry = new TestReportFileEntry(resourcePath, null);
fileEntries.add(fileEntry);
}

Expand All @@ -193,29 +186,6 @@ public boolean report(Long testSessionId, Long testSuiteId, long spanId) {
}
}

private static List<TestReportFileEntry.Segment> getCompressedSegments(
List<TestReportFileEntry.Segment> segments) {
List<TestReportFileEntry.Segment> compressedSegments = new ArrayList<>();

int startLine = -1, endLine = -1;
for (TestReportFileEntry.Segment segment : segments) {
if (segment.getStartLine() <= endLine + 1) {
endLine = Math.max(endLine, segment.getEndLine());
} else {
if (startLine > 0) {
compressedSegments.add(new TestReportFileEntry.Segment(startLine, -1, endLine, -1, -1));
}
startLine = segment.getStartLine();
endLine = segment.getEndLine();
}
}

if (startLine > 0) {
compressedSegments.add(new TestReportFileEntry.Segment(startLine, -1, endLine, -1, -1));
}
return compressedSegments;
}

@Nullable
@Override
public TestReport getReport() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "src/test/java/datadog/smoke/TestSucceed.java",
"segments" : [ [ 11, -1, 12, -1, -1 ] ]
"bitmap" : "ABg="
}, {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "src/test/java/datadog/smoke/TestSucceed.java",
"segments" : [ [ 7, -1, 7, -1, -1 ], [ 10, -1, 11, -1, -1 ] ]
"bitmap" : "gAw="
}, {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id_2},
"span_id" : ${content_span_id_2},
"files" : [ {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 8, -1, 8, -1, -1 ] ]
"bitmap" : "AAE="
}, {
"filename" : "src/test/java/datadog/smoke/TestSucceedJunit5.java",
"segments" : [ [ 10, -1, 11, -1, -1 ] ]
"bitmap" : "AAw="
} ]
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "submodule-a/src/test/java/datadog/smoke/TestSucceed.java",
"segments" : [ [ 11, -1, 12, -1, -1 ] ]
"bitmap" : "ABg="
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id_2},
"span_id" : ${content_span_id_2},
"files" : [ {
"filename" : "submodule-b/src/test/java/datadog/smoke/TestSucceed.java",
"segments" : [ [ 11, -1, 12, -1, -1 ] ]
"bitmap" : "ABg="
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "src/test/java/datadog/smoke/TestSucceed.java",
"segments" : [ [ 11, -1, 12, -1, -1 ] ]
"bitmap" : "ABg="
}, {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,53 @@
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
}, {
"filename" : "src/test/java/datadog/smoke/TestFailed.java",
"segments" : [ [ 7, -1, 7, -1, -1 ], [ 11, -1, 11, -1, -1 ] ]
"bitmap" : "gAg="
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_2},
"files" : [ {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
}, {
"filename" : "src/test/java/datadog/smoke/TestFailed.java",
"segments" : [ [ 7, -1, 7, -1, -1 ], [ 11, -1, 11, -1, -1 ] ]
"bitmap" : "gAg="
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_3},
"files" : [ {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
}, {
"filename" : "src/test/java/datadog/smoke/TestFailed.java",
"segments" : [ [ 7, -1, 7, -1, -1 ], [ 11, -1, 11, -1, -1 ] ]
"bitmap" : "gAg="
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_4},
"files" : [ {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
}, {
"filename" : "src/test/java/datadog/smoke/TestFailed.java",
"segments" : [ [ 7, -1, 7, -1, -1 ], [ 11, -1, 11, -1, -1 ] ]
"bitmap" : "gAg="
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_5},
"files" : [ {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
}, {
"filename" : "src/test/java/datadog/smoke/TestFailed.java",
"segments" : [ [ 7, -1, 7, -1, -1 ], [ 11, -1, 11, -1, -1 ] ]
"bitmap" : "gAg="
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "src/test/java/datadog/smoke/TestSucceed.java",
"segments" : [ [ 7, -1, 7, -1, -1 ], [ 11, -1, 12, -1, -1 ] ]
"bitmap" : "gBg="
}, {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "src/test/java/datadog/smoke/TestSucceed.java",
"segments" : [ ]
"filename" : "src/test/java/datadog/smoke/TestSucceed.java"
}, {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ ]
"filename" : "src/main/java/datadog/smoke/Calculator.java"
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "src/test/java/datadog/smoke/TestSucceed.java",
"segments" : [ [ 7, -1, 7, -1, -1 ], [ 11, -1, 12, -1, -1 ] ]
"bitmap" : "gBg="
}, {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "src/test/java/datadog/smoke/TestSucceedPropertyAssertion.java",
"segments" : [ ]
"filename" : "src/test/java/datadog/smoke/TestSucceedPropertyAssertion.java"
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
"span_id" : ${content_parent_id},
"files" : [ {
"filename" : "src/test/java/datadog/smoke/calculator/CalculatorSteps.java",
"segments" : [ [ 13, -1, 13, -1, -1 ], [ 19, -1, 20, -1, -1 ], [ 24, -1, 27, -1, -1 ], [ 30, -1, 34, -1, -1 ], [ 36, -1, 40, -1, -1 ], [ 42, -1, 43, -1, -1 ], [ 49, -1, 51, -1, -1 ], [ 53, -1, 53, -1, -1 ], [ 56, -1, 56, -1, -1 ] ]
"bitmap" : "ACAYz/cNLgE="
}, {
"filename" : "src/test/resources/datadog/smoke/basic_arithmetic.feature",
"segments" : [ ]
"filename" : "src/test/resources/datadog/smoke/basic_arithmetic.feature"
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "src/test/java/datadog/smoke/TestSucceed.java",
"segments" : [ [ 7, -1, 7, -1, -1 ], [ 11, -1, 12, -1, -1 ] ]
"bitmap" : "gBg="
}, {
"filename" : "src/main/java/datadog/smoke/Calculator.java",
"segments" : [ [ 5, -1, 5, -1, -1 ] ]
"bitmap" : "IA=="
} ]
} ]
Loading

0 comments on commit 3762731

Please sign in to comment.