Skip to content
This repository has been archived by the owner on Jul 8, 2019. It is now read-only.

Commit

Permalink
Fix #48 - Angular CLI-generated LCOV files fail to map to source Type…
Browse files Browse the repository at this point in the history
…Script (#80)

- Fix Angular CLI LCOV parser issue #48
- Extend code coverage of LCOV parser
  • Loading branch information
Pablissimo authored Dec 29, 2016
1 parent 0daa50c commit 7722e7a
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 1 deletion.
11 changes: 10 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<groupId>com.pablissimo.sonar</groupId>
<artifactId>sonar-typescript-plugin</artifactId>
<packaging>sonar-plugin</packaging>
<version>0.97-SNAPSHOT</version>
<version>0.98-SNAPSHOT</version>

<name>TypeScript</name>
<description>Analyse TypeScript projects</description>
Expand Down Expand Up @@ -117,6 +117,15 @@
</dependencies>

<build>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
<includes>
<include>**/*</include>
</includes>
</testResource>
</testResources>

<plugins>
<plugin>
<groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/pablissimo/sonar/LCOVParserImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,15 @@ private FileData loadCurrentFileData(final Map<InputFile, FileData> files, Strin
FileData fileData = null;
// some tools (like Istanbul, Karma) provide relative paths, so let's consider them relative to project directory
InputFile inputFile = context.fileSystem().inputFile(context.fileSystem().predicates().hasPath(filePath));

// Try to accommodate Angular projects that, when the angular template loader's used
// by checking for a ! in the filepath if the path isn't found - have a bash at seeking
// everything after the ! as a second fallback pass
if (inputFile == null && filePath.contains("!") && (filePath.indexOf("!") + 1) < filePath.length()) {
String amendedPath = filePath.substring(filePath.indexOf("!") + 1);
inputFile = context.fileSystem().inputFile(context.fileSystem().predicates().hasPath(amendedPath));
}

if (inputFile != null) {
fileData = files.get(inputFile);
if (fileData == null) {
Expand Down
144 changes: 144 additions & 0 deletions src/test/java/com/pablissimo/sonar/LCOVParserImplTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package com.pablissimo.sonar;

import static org.junit.Assert.*;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.coverage.NewCoverage;
import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
import org.sonar.api.batch.sensor.internal.SensorContextTester;

public class LCOVParserImplTest {
LOCSensor sensor;

SensorContextTester sensorContext;
DefaultInputFile inputFile;

@Before
public void setUp() throws Exception {
this.sensorContext = SensorContextTester.create(new File(""));

this.inputFile =
new DefaultInputFile("", "path/to/file.ts")
.setLanguage(TypeScriptLanguage.LANGUAGE_KEY)
.setLines(3);

this.sensorContext.fileSystem().add(this.inputFile);
}

@Test
public void parsesBasicLcovFiles() {
Map<InputFile, NewCoverage> coverage = executeForTestCase("basic");
DefaultCoverage c = (DefaultCoverage) coverage.get(this.inputFile);

assertEquals((Integer) 3, c.hitsByLine().get(1));
assertEquals((Integer) 0, c.hitsByLine().get(2));
assertEquals((Integer) 1, c.hitsByLine().get(3));

assertEquals(3, c.linesToCover());
}

@Test
public void parsesAngularTemplateLoaderOutput() {
Map<InputFile, NewCoverage> coverage = executeForTestCase("angular");
DefaultCoverage c = (DefaultCoverage) coverage.get(this.inputFile);

assertEquals((Integer) 3, c.hitsByLine().get(1));
assertEquals((Integer) 0, c.hitsByLine().get(2));
assertEquals((Integer) 1, c.hitsByLine().get(3));

assertEquals(3, c.linesToCover());
}

@Test
public void handlesNoContent() {
Map<InputFile, NewCoverage> coverage = executeForTestCase("blank");

assertNotNull(coverage);
assertEquals(0, coverage.size());
}

@Test
public void handlesNoLineHitsForASingleFile() {
Map<InputFile, NewCoverage> coverage = executeForTestCase("nolinehits");
DefaultCoverage c = (DefaultCoverage) coverage.get(this.inputFile);

assertEquals(1, coverage.size());

assertNotNull(c);
assertNull(c.hitsByLine().get(1));
assertNull(c.hitsByLine().get(2));
assertNull(c.hitsByLine().get(3));
}

@Test
public void ignoresFilesNotPartOfAnalysisSet() {
Map<InputFile, NewCoverage> coverage = executeForTestCase("existingandnot");
DefaultCoverage c = (DefaultCoverage) coverage.get(this.inputFile);

assertNotNull(c);
assertEquals(1, coverage.size());
}

@Test
public void handlesFilesEndingWithExclamationMarkIfNotPartOfSet() {
Map<InputFile, NewCoverage> coverage = executeForTestCase("angularendswithbang");

assertNotNull(coverage);
assertEquals(0, coverage.size());
}

@Test
public void handlesOutOfRangeLineNumbers() {
Map<InputFile, NewCoverage> coverage = executeForTestCase("outofrangelines");
DefaultCoverage c = (DefaultCoverage) coverage.get(this.inputFile);

assertNotNull(c);
assertEquals(1, coverage.size());

assertEquals((Integer) 3, c.hitsByLine().get(1));
}

@Test(expected = IllegalArgumentException.class)
public void createThrowsWhenFileDoesNotExist() {
File nonExistent = new File("whatever");
LCOVParserImpl.create(this.sensorContext, nonExistent);
}

@Test(expected = IllegalArgumentException.class)
public void parseFileThrowsWhenFileDoesNotExist() {
File nonExistent = new File("whatever");
LCOVParser parser = getParser(resource("basic"));

parser.parseFile(nonExistent);
}

private Map<InputFile, NewCoverage> executeForTestCase(String testName) {
File lcovFile = resource(testName);
LCOVParser parser = getParser(lcovFile);

return parser.parseFile(lcovFile);
}

private LCOVParser getParser(File lcovFile) {
return LCOVParserImpl.create(this.sensorContext, lcovFile);
}

private File resource(String testName) {
URL lcovUrl = LCOVParserImplTest.class.getClassLoader().getResource("./lcov/" + testName + ".lcov");

try {
File lcovFile = new File(lcovUrl.toURI());
return lcovFile;
}
catch (URISyntaxException e) {
return null;
}
}
}
5 changes: 5 additions & 0 deletions src/test/resources/lcov/angular.lcov
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
SF:path/to/template/loader.js!path/to/file.ts
DA:1,3
DA:2,0
DA:3,1
end_of_record
3 changes: 3 additions & 0 deletions src/test/resources/lcov/angularendswithbang.lcov
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SF:path/to/template/loader.js!
DA:1,3
end_of_record
5 changes: 5 additions & 0 deletions src/test/resources/lcov/basic.lcov
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
SF:path/to/file.ts
DA:1,3
DA:2,0
DA:3,1
end_of_record
Empty file.
8 changes: 8 additions & 0 deletions src/test/resources/lcov/existingandnot.lcov
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
SF:path/to/file.ts
DA:1,3
DA:2,0
DA:3,1
end_of_record
SF:path/to/nonexistent/file.ts
DA:1,1
end_of_record
2 changes: 2 additions & 0 deletions src/test/resources/lcov/nolinehits.lcov
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SF:path/to/file.ts
end_of_record
5 changes: 5 additions & 0 deletions src/test/resources/lcov/outofrangelines.lcov
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
SF:path/to/file.ts
DA:0,3
DA:1,3
DA:4,3
end_of_record

0 comments on commit 7722e7a

Please sign in to comment.