Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS-537 - Coverage is with LCOV report that contains relative paths #5083

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
Expand Down Expand Up @@ -52,17 +53,27 @@ class LCOVParser {

private static final Logger LOG = LoggerFactory.getLogger(LCOVParser.class);

private LCOVParser(List<String> lines, SensorContext context, FileLocator fileLocator) {
private static record Line(String content, File reportFile) {}

private LCOVParser(List<Line> lines, SensorContext context, FileLocator fileLocator) {
this.context = context;
this.fileLocator = fileLocator;
this.coverageByFile = parse(lines);
}

static LCOVParser create(SensorContext context, List<File> files, FileLocator fileLocator) {
final List<String> lines = new LinkedList<>();
final List<Line> lines = new LinkedList<>();
for (File file : files) {
try (Stream<String> fileLines = Files.lines(file.toPath())) {
lines.addAll(fileLines.toList());
lines.addAll(
fileLines
.toList()
.stream()
.map(content -> {
return new Line(content, file);
})
.toList()
);
} catch (IOException e) {
throw new IllegalArgumentException("Could not read content from file: " + file, e);
}
Expand All @@ -82,21 +93,21 @@ int inconsistenciesNumber() {
return inconsistenciesCounter;
}

private Map<InputFile, NewCoverage> parse(List<String> lines) {
private Map<InputFile, NewCoverage> parse(List<Line> lines) {
final Map<InputFile, FileData> files = new HashMap<>();
FileData fileData = null;
int reportLineNum = 0;

for (String line : lines) {
for (Line line : lines) {
reportLineNum++;
if (line.startsWith(SF)) {
if (line.content.startsWith(SF)) {
fileData = files.computeIfAbsent(inputFileForSourceFile(line), inputFile ->
inputFile == null ? null : new FileData(inputFile)
);
} else if (fileData != null) {
if (line.startsWith(DA)) {
if (line.content.startsWith(DA)) {
parseLineCoverage(fileData, reportLineNum, line);
} else if (line.startsWith(BRDA)) {
} else if (line.content.startsWith(BRDA)) {
parseBranchCoverage(fileData, reportLineNum, line);
}
}
Expand All @@ -112,10 +123,10 @@ private Map<InputFile, NewCoverage> parse(List<String> lines) {
return coveredFiles;
}

private void parseBranchCoverage(FileData fileData, int reportLineNum, String line) {
private void parseBranchCoverage(FileData fileData, int reportLineNum, Line line) {
try {
// BRDA:<line number>,<block number>,<branch number>,<taken>
String[] tokens = line.substring(BRDA.length()).trim().split(",");
String[] tokens = line.content.substring(BRDA.length()).trim().split(",");
String lineNumber = tokens[0];
String branchNumber = tokens[1] + tokens[2];
String taken = tokens[3];
Expand All @@ -130,10 +141,10 @@ private void parseBranchCoverage(FileData fileData, int reportLineNum, String li
}
}

private void parseLineCoverage(FileData fileData, int reportLineNum, String line) {
private void parseLineCoverage(FileData fileData, int reportLineNum, Line line) {
try {
// DA:<line number>,<execution count>[,<checksum>]
String execution = line.substring(DA.length());
String execution = line.content.substring(DA.length());
String executionCount = execution.substring(execution.indexOf(',') + 1);
String lineNumber = execution.substring(0, execution.indexOf(','));

Expand All @@ -154,18 +165,34 @@ private void logWrongDataWarning(String dataType, int reportLineNum, Exception e
}

@CheckForNull
private InputFile inputFileForSourceFile(String line) {
// SF:<absolute path to the source file>
String filePath = line.substring(SF.length());
// some tools (like Istanbul, Karma) provide relative paths, so let's consider them relative to project directory
InputFile inputFile = context
private InputFile inputFileForSourceFile(Line line) {
// SF:<path to the source file>
var reportFilePath = Path.of(line.content.substring(SF.length()));
var actualFilePath = reportFilePath;

// if the path is relative, we try to locate it relatively to the project root
if (!actualFilePath.isAbsolute()) {
var exists = context
.fileSystem()
.hasFiles(context.fileSystem().predicates().hasPath(actualFilePath.toString()));

// if it does not exist, we try to locate it relatively to the report parent directory
if (!exists) {
actualFilePath = line.reportFile.getParentFile().toPath().resolve(actualFilePath);
}
}

var filePathAsString = actualFilePath.toString();

var inputFile = context
.fileSystem()
.inputFile(context.fileSystem().predicates().hasPath(filePath));
.inputFile(context.fileSystem().predicates().hasPath(filePathAsString));

if (inputFile == null) {
inputFile = fileLocator.getInputFile(filePath);
inputFile = fileLocator.getInputFile(filePathAsString);
}
if (inputFile == null) {
unresolvedPaths.add(filePath);
unresolvedPaths.add(reportFilePath.toString());
}
return inputFile;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ void test_unresolved_path() {
coverageSensor.execute(context);
String fileName =
File.separator + "reports" + File.separator + "report_with_unresolved_path.lcov";
assertThat(logTester.logs(Level.WARN))
var logs = logTester.logs(Level.WARN);

assertThat(logs)
.contains(
"Could not resolve 2 file paths in [" + moduleBaseDir.getAbsolutePath() + fileName + "]"
)
Expand All @@ -192,6 +194,22 @@ void test_unresolved_path() {
);
}

@Test
void test_relative_path() {
logTester.setLevel(Level.INFO);
settings.setProperty(
JavaScriptPlugin.LCOV_REPORT_PATHS,
"reports/report_with_relative_path.lcov"
);
coverageSensor.execute(context);
var logs = logTester.logs(Level.WARN);

assertThat(logs).isEmpty();
assertThat(context.lineHits("moduleKey:file1.js", 1)).isEqualTo(1);
assertThat(context.lineHits("moduleKey:file1.js", 2)).isEqualTo(1);
assertThat(context.lineHits("moduleKey:file1.js", 3)).isEqualTo(0);
}

@Test
void test_unresolved_path_with_debug_log() {
logTester.setLevel(Level.DEBUG);
Expand Down