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 12, 2024
1 parent 9272c4c commit c86195f
Show file tree
Hide file tree
Showing 47 changed files with 258 additions and 467 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ protected TestReport report(

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

TestReport report = new TestReport(testSessionId, testSuiteId, testSpanId, fileEntries);
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.HashSet;
import java.util.IdentityHashMap;
Expand Down Expand Up @@ -68,7 +67,7 @@ protected TestReport report(
return null;
}

Map<String, List<TestReportFileEntry.Segment>> segmentsBySourcePath = new HashMap<>();
Map<String, BitSet> coveredLinesBySourcePath = new HashMap<>();
for (Map.Entry<Class<?>, ExecutionDataAdapter> e : combinedExecutionData.entrySet()) {
ExecutionDataAdapter executionDataAdapter = e.getValue();
String className = executionDataAdapter.getClassName();
Expand All @@ -84,15 +83,14 @@ protected TestReport report(
}

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());

// 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 @@ -105,16 +103,11 @@ protected TestReport report(
}
}

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 : combinedNonCodeResources) {
Expand All @@ -126,7 +119,7 @@ protected TestReport report(
metrics.add(CiVisibilityCountMetric.CODE_COVERAGE_ERRORS, 1, CoverageErrorType.PATH);
continue;
}
fileEntries.add(new TestReportFileEntry(resourcePath, Collections.emptyList()));
fileEntries.add(new TestReportFileEntry(resourcePath, null));
}

TestReport report = new TestReport(testSessionId, testSuiteId, testSpanId, fileEntries);
Expand All @@ -141,29 +134,6 @@ protected TestReport report(
}
}

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;
}

public static final class Factory implements CoverageStore.Factory {

private final Map<String, Integer> probeCounts = new ConcurrentHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package datadog.trace.civisibility.coverage.line;

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 @@ -3,7 +3,6 @@
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature"
} ]
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,55 @@
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_2},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_3},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_4},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_5},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_6},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_7},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_8},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,55 @@
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_2},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_3},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_4},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_5},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_6},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_7},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_8},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_with_examples.feature"
} ]
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_slow.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_slow.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_2},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_slow.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_slow.feature"
} ]
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,20 @@
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_2},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id_3},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature"
} ]
} ]
} ]
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" : "org/example/cucumber/calculator/basic_arithmetic_failed.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_failed.feature"
} ]
} ]
} ]
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
"test_suite_id" : ${content_test_suite_id},
"span_id" : ${content_span_id},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic.feature"
} ]
}, {
"test_session_id" : ${content_test_session_id},
"test_suite_id" : ${content_test_suite_id_2},
"span_id" : ${content_span_id_2},
"files" : [ {
"filename" : "org/example/cucumber/calculator/basic_arithmetic_failed.feature",
"segments" : [ ]
"filename" : "org/example/cucumber/calculator/basic_arithmetic_failed.feature"
} ]
} ]
} ]
Loading

0 comments on commit c86195f

Please sign in to comment.