@@ -20,12 +20,10 @@ | |||
package org.sonar.xoo; | |||
import org.sonar.api.SonarPlugin; | |||
import org.sonar.xoo.lang.CoveragePerTestSensor; | |||
import org.sonar.xoo.lang.DependencySensor; | |||
import org.sonar.xoo.lang.MeasureSensor; | |||
import org.sonar.xoo.lang.SymbolReferencesSensor; | |||
import org.sonar.xoo.lang.SyntaxHighlightingSensor; | |||
import org.sonar.xoo.lang.TestCaseSensor; | |||
import org.sonar.xoo.lang.XooCpdMapping; | |||
import org.sonar.xoo.lang.XooTokenizer; | |||
import org.sonar.xoo.rule.ChecksSensor; | |||
@@ -76,8 +74,6 @@ public class XooPlugin extends SonarPlugin { | |||
MeasureSensor.class, | |||
SyntaxHighlightingSensor.class, | |||
SymbolReferencesSensor.class, | |||
TestCaseSensor.class, | |||
CoveragePerTestSensor.class, | |||
DependencySensor.class, | |||
ChecksSensor.class, | |||
RandomAccessSensor.class, |
@@ -1,113 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.xoo.lang; | |||
import com.google.common.base.Splitter; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.batch.fs.FilePredicates; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.sensor.Sensor; | |||
import org.sonar.api.batch.sensor.SensorContext; | |||
import org.sonar.api.batch.sensor.SensorDescriptor; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.xoo.Xoo; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
/** | |||
* Parse files *.xoo.coveragePerTest | |||
*/ | |||
public class CoveragePerTestSensor implements Sensor { | |||
private static final Logger LOG = Loggers.get(CoveragePerTestSensor.class); | |||
private static final String COVER_PER_TEST_EXTENSION = ".coveragePerTest"; | |||
private void processCoveragePerTest(InputFile inputFile, SensorContext context) { | |||
File ioFile = inputFile.file(); | |||
File coverPerTestFile = new File(ioFile.getParentFile(), ioFile.getName() + COVER_PER_TEST_EXTENSION); | |||
if (coverPerTestFile.exists()) { | |||
LOG.debug("Processing " + coverPerTestFile.getAbsolutePath()); | |||
try { | |||
List<String> lines = FileUtils.readLines(coverPerTestFile, context.fileSystem().encoding().name()); | |||
int lineNumber = 0; | |||
for (String line : lines) { | |||
lineNumber++; | |||
if (StringUtils.isBlank(line) || line.startsWith("#")) { | |||
continue; | |||
} | |||
processLine(coverPerTestFile, lineNumber, context, line, inputFile); | |||
} | |||
} catch (IOException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
} | |||
private void processLine(File coverPerTest, int lineNumber, SensorContext context, String line, InputFile testFile) { | |||
try { | |||
Iterator<String> split = Splitter.on(":").split(line).iterator(); | |||
String testCaseName = split.next(); | |||
String mainFileRelativePath = split.next(); | |||
FileSystem fs = context.fileSystem(); | |||
InputFile mainFile = fs.inputFile(fs.predicates().hasRelativePath(mainFileRelativePath)); | |||
if (mainFile == null) { | |||
throw new IllegalStateException("Unable to find file " + mainFileRelativePath); | |||
} | |||
List<Integer> coveredLines = new ArrayList<Integer>(); | |||
Iterator<String> lines = Splitter.on(",").split(split.next()).iterator(); | |||
while (lines.hasNext()) { | |||
coveredLines.add(Integer.parseInt(lines.next())); | |||
} | |||
context.newTestCaseCoverage() | |||
.testFile(testFile) | |||
.testName(testCaseName) | |||
.cover(mainFile) | |||
.onLines(coveredLines) | |||
.save(); | |||
} catch (Exception e) { | |||
throw new IllegalStateException("Error processing line " + lineNumber + " of file " + coverPerTest.getAbsolutePath(), e); | |||
} | |||
} | |||
@Override | |||
public void describe(SensorDescriptor descriptor) { | |||
descriptor | |||
.name("Xoo Coverage Per Test Sensor") | |||
.onlyOnLanguages(Xoo.KEY) | |||
.onlyOnFileType(InputFile.Type.TEST); | |||
} | |||
@Override | |||
public void execute(SensorContext context) { | |||
FileSystem fs = context.fileSystem(); | |||
FilePredicates p = fs.predicates(); | |||
for (InputFile file : fs.inputFiles(p.and(p.hasLanguages(Xoo.KEY), p.hasType(InputFile.Type.TEST)))) { | |||
processCoveragePerTest(file, context); | |||
} | |||
} | |||
} |
@@ -1,112 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.xoo.lang; | |||
import com.google.common.base.Splitter; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.batch.fs.FilePredicates; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.sensor.Sensor; | |||
import org.sonar.api.batch.sensor.SensorContext; | |||
import org.sonar.api.batch.sensor.SensorDescriptor; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.xoo.Xoo; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
/** | |||
* Parse files *.xoo.testplan | |||
*/ | |||
public class TestCaseSensor implements Sensor { | |||
private static final Logger LOG = Loggers.get(TestCaseSensor.class); | |||
private static final String TESTPLAN_EXTENSION = ".testplan"; | |||
private void processFileTestPlan(InputFile inputFile, SensorContext context) { | |||
File ioFile = inputFile.file(); | |||
File testPlanFile = new File(ioFile.getParentFile(), ioFile.getName() + TESTPLAN_EXTENSION); | |||
if (testPlanFile.exists()) { | |||
LOG.debug("Processing " + testPlanFile.getAbsolutePath()); | |||
try { | |||
List<String> lines = FileUtils.readLines(testPlanFile, context.fileSystem().encoding().name()); | |||
int lineNumber = 0; | |||
for (String line : lines) { | |||
lineNumber++; | |||
if (StringUtils.isBlank(line) || line.startsWith("#")) { | |||
continue; | |||
} | |||
processLine(testPlanFile, lineNumber, line, context, inputFile); | |||
} | |||
} catch (IOException e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
} | |||
private void processLine(File testplanFile, int lineNumber, String line, SensorContext context, InputFile testFile) { | |||
try { | |||
Iterator<String> split = Splitter.on(":").split(line).iterator(); | |||
String name = split.next(); | |||
String type = split.next(); | |||
String status = split.next(); | |||
String message = split.next(); | |||
String stack = split.next(); | |||
String durationStr = StringUtils.trimToNull(split.next()); | |||
TestCaseExecution test = context.newTestCaseExecution() | |||
.inTestFile(testFile) | |||
.name(name) | |||
.ofType(TestCaseExecution.Type.valueOf(type)) | |||
.status(TestCaseExecution.Status.valueOf(status)) | |||
.message(StringUtils.trimToNull(message)) | |||
.stackTrace(StringUtils.trimToNull(stack)); | |||
if (durationStr != null) { | |||
test.durationInMs(Long.parseLong(durationStr)); | |||
} | |||
test.save(); | |||
} catch (Exception e) { | |||
throw new IllegalStateException("Error processing line " + lineNumber + " of file " + testplanFile.getAbsolutePath(), e); | |||
} | |||
} | |||
@Override | |||
public void describe(SensorDescriptor descriptor) { | |||
descriptor | |||
.name("Xoo TestPlan Sensor") | |||
.onlyOnLanguages(Xoo.KEY) | |||
.onlyOnFileType(InputFile.Type.TEST); | |||
} | |||
@Override | |||
public void execute(SensorContext context) { | |||
FileSystem fs = context.fileSystem(); | |||
FilePredicates p = fs.predicates(); | |||
for (InputFile file : fs.inputFiles(p.and(p.hasLanguages(Xoo.KEY), p.hasType(InputFile.Type.TEST)))) { | |||
processFileTestPlan(file, context); | |||
} | |||
} | |||
} |
@@ -1,109 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.xoo.lang; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.batch.fs.InputFile.Type; | |||
import org.sonar.api.batch.fs.internal.DefaultFileSystem; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.SensorContext; | |||
import org.sonar.api.batch.sensor.SensorStorage; | |||
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; | |||
import org.sonar.api.batch.sensor.test.TestCaseCoverage; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseCoverage; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.Arrays; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.when; | |||
public class CoveragePerTestSensorTest { | |||
private CoveragePerTestSensor sensor; | |||
private SensorContext context = mock(SensorContext.class); | |||
private DefaultFileSystem fileSystem; | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
private File baseDir; | |||
@Before | |||
public void prepare() throws IOException { | |||
baseDir = temp.newFolder(); | |||
sensor = new CoveragePerTestSensor(); | |||
fileSystem = new DefaultFileSystem(baseDir.toPath()); | |||
when(context.fileSystem()).thenReturn(fileSystem); | |||
} | |||
@Test | |||
public void testDescriptor() { | |||
sensor.describe(new DefaultSensorDescriptor()); | |||
} | |||
@Test | |||
public void testNoExecutionIfCoveragePerTestFile() { | |||
DefaultInputFile testFile = new DefaultInputFile("foo", "test/fooTest.xoo").setLanguage("xoo") | |||
.setType(Type.TEST); | |||
fileSystem.add(testFile); | |||
sensor.execute(context); | |||
} | |||
@Test | |||
public void testExecution() throws IOException { | |||
File coverPerTest = new File(baseDir, "test/fooTest.xoo.coveragePerTest"); | |||
FileUtils.write(coverPerTest, "test1:src/foo.xoo:1,2,3,4\ntest2:src/foo.xoo:5,6,7\n\n#comment"); | |||
DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setLanguage("xoo"); | |||
DefaultInputFile testFile = new DefaultInputFile("foo", "test/fooTest.xoo").setLanguage("xoo") | |||
.setType(Type.TEST); | |||
fileSystem.add(inputFile); | |||
fileSystem.add(testFile); | |||
final SensorStorage sensorStorage = mock(SensorStorage.class); | |||
when(context.newTestCaseCoverage()).thenAnswer(new Answer<TestCaseCoverage>() { | |||
@Override | |||
public TestCaseCoverage answer(InvocationOnMock invocation) throws Throwable { | |||
return new DefaultTestCaseCoverage(sensorStorage); | |||
} | |||
}); | |||
sensor.execute(context); | |||
verify(sensorStorage).store(new DefaultTestCaseCoverage() | |||
.testFile(testFile) | |||
.testName("test1") | |||
.cover(inputFile) | |||
.onLines(Arrays.asList(1, 2, 3, 4))); | |||
verify(sensorStorage).store(new DefaultTestCaseCoverage() | |||
.testFile(testFile) | |||
.testName("test2") | |||
.cover(inputFile) | |||
.onLines(Arrays.asList(5, 6, 7))); | |||
} | |||
} |
@@ -1,109 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.xoo.lang; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.batch.fs.InputFile.Type; | |||
import org.sonar.api.batch.fs.internal.DefaultFileSystem; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.SensorContext; | |||
import org.sonar.api.batch.sensor.SensorStorage; | |||
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.when; | |||
public class TestCaseSensorTest { | |||
private TestCaseSensor sensor; | |||
private SensorContext context = mock(SensorContext.class); | |||
private DefaultFileSystem fileSystem; | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
private File baseDir; | |||
@Before | |||
public void prepare() throws IOException { | |||
baseDir = temp.newFolder(); | |||
sensor = new TestCaseSensor(); | |||
fileSystem = new DefaultFileSystem(baseDir.toPath()); | |||
when(context.fileSystem()).thenReturn(fileSystem); | |||
} | |||
@Test | |||
public void testDescriptor() { | |||
sensor.describe(new DefaultSensorDescriptor()); | |||
} | |||
@Test | |||
public void testNoExecutionIfNoTestFile() { | |||
DefaultInputFile testFile = new DefaultInputFile("foo", "test/fooTest.xoo").setLanguage("xoo") | |||
.setType(Type.TEST); | |||
fileSystem.add(testFile); | |||
sensor.execute(context); | |||
} | |||
@Test | |||
public void testExecution() throws IOException { | |||
File testPlan = new File(baseDir, "test/fooTest.xoo.testplan"); | |||
FileUtils.write(testPlan, "test1:UNIT:OK:::10\ntest2:INTEGRATION:ERROR:message:stack:15\n\n#comment"); | |||
DefaultInputFile testFile = new DefaultInputFile("foo", "test/fooTest.xoo").setLanguage("xoo") | |||
.setType(Type.TEST); | |||
fileSystem.add(testFile); | |||
final SensorStorage sensorStorage = mock(SensorStorage.class); | |||
when(context.newTestCaseExecution()).thenAnswer(new Answer<TestCaseExecution>() { | |||
@Override | |||
public TestCaseExecution answer(InvocationOnMock invocation) throws Throwable { | |||
return new DefaultTestCaseExecution(sensorStorage); | |||
} | |||
}); | |||
sensor.execute(context); | |||
verify(sensorStorage).store(new DefaultTestCaseExecution(null) | |||
.inTestFile(testFile) | |||
.name("test1") | |||
.durationInMs(10)); | |||
verify(sensorStorage).store(new DefaultTestCaseExecution(null) | |||
.inTestFile(testFile) | |||
.name("test2") | |||
.ofType(TestCaseExecution.Type.INTEGRATION) | |||
.status(TestCaseExecution.Status.ERROR) | |||
.message("message") | |||
.stackTrace("stack") | |||
.durationInMs(15)); | |||
} | |||
} |
@@ -31,8 +31,6 @@ import org.sonar.api.batch.sensor.duplication.Duplication; | |||
import org.sonar.api.batch.sensor.highlighting.TypeOfText; | |||
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; | |||
import org.sonar.api.batch.sensor.symbol.Symbol; | |||
import org.sonar.api.batch.sensor.test.TestCaseCoverage; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
import org.sonar.api.issue.Issue; | |||
import org.sonar.api.issue.internal.DefaultIssue; | |||
import org.sonar.api.measures.Measure; | |||
@@ -47,8 +45,6 @@ import org.sonar.batch.scan.ProjectScanContainer; | |||
import org.sonar.batch.scan.filesystem.InputPathCache; | |||
import org.sonar.batch.scan.measure.MeasureCache; | |||
import org.sonar.batch.symbol.SymbolData; | |||
import org.sonar.batch.test.TestCaseCoverageCache; | |||
import org.sonar.batch.test.TestCaseExecutionCache; | |||
import org.sonar.core.source.SnapshotDataTypes; | |||
import javax.annotation.CheckForNull; | |||
@@ -73,8 +69,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver { | |||
private Map<String, InputDir> inputDirs = new HashMap<>(); | |||
private Map<InputFile, SyntaxHighlightingData> highlightingPerFile = new HashMap<>(); | |||
private Map<InputFile, SymbolData> symbolTablePerFile = new HashMap<>(); | |||
private Map<String, Map<String, TestCaseExecution>> testCasesPerFile = new HashMap<>(); | |||
private Map<String, Map<String, Map<String, List<Integer>>>> coveragePerTest = new HashMap<>(); | |||
private Map<String, Map<String, Integer>> dependencies = new HashMap<>(); | |||
@Override | |||
@@ -114,33 +108,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver { | |||
} | |||
} | |||
private void storeCoveragePerTest(ProjectScanContainer container) { | |||
TestCaseCoverageCache testCaseCoverageCache = container.getComponentByType(TestCaseCoverageCache.class); | |||
for (Entry<TestCaseCoverage> entry : testCaseCoverageCache.entries()) { | |||
String testFileKey = entry.key()[0].toString(); | |||
if (!coveragePerTest.containsKey(testFileKey)) { | |||
coveragePerTest.put(testFileKey, new HashMap<String, Map<String, List<Integer>>>()); | |||
} | |||
String testName = entry.key()[1].toString(); | |||
if (!coveragePerTest.get(testFileKey).containsKey(testName)) { | |||
coveragePerTest.get(testFileKey).put(testName, new HashMap<String, List<Integer>>()); | |||
} | |||
TestCaseCoverage value = entry.value(); | |||
coveragePerTest.get(testFileKey).get(testName).put(entry.key()[2].toString(), value != null ? value.coveredLines() : null); | |||
} | |||
} | |||
private void storeTestCases(ProjectScanContainer container) { | |||
TestCaseExecutionCache testCaseCache = container.getComponentByType(TestCaseExecutionCache.class); | |||
for (Entry<TestCaseExecution> entry : testCaseCache.entries()) { | |||
String effectiveKey = entry.key()[0].toString(); | |||
if (!testCasesPerFile.containsKey(effectiveKey)) { | |||
testCasesPerFile.put(effectiveKey, new HashMap<String, TestCaseExecution>()); | |||
} | |||
testCasesPerFile.get(effectiveKey).put(entry.value().name(), entry.value()); | |||
} | |||
} | |||
private void storeDuplication(ProjectScanContainer container) { | |||
DuplicationCache duplicationCache = container.getComponentByType(DuplicationCache.class); | |||
for (String effectiveKey : duplicationCache.componentKeys()) { | |||
@@ -214,29 +181,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver { | |||
return duplications.get(((DefaultInputFile) inputFile).key()); | |||
} | |||
public Collection<TestCaseExecution> testCasesFor(InputFile inputFile) { | |||
String key = ((DefaultInputFile) inputFile).key(); | |||
if (testCasesPerFile.containsKey(key)) { | |||
return testCasesPerFile.get(key).values(); | |||
} else { | |||
return Collections.emptyList(); | |||
} | |||
} | |||
public TestCaseExecution testCase(InputFile inputFile, String testCaseName) { | |||
return testCasesPerFile.get(((DefaultInputFile) inputFile).key()).get(testCaseName); | |||
} | |||
public List<Integer> coveragePerTest(InputFile testFile, String testCaseName, InputFile mainFile) { | |||
String testKey = ((DefaultInputFile) testFile).key(); | |||
String mainKey = ((DefaultInputFile) mainFile).key(); | |||
if (coveragePerTest.containsKey(testKey) && coveragePerTest.get(testKey).containsKey(testCaseName) && coveragePerTest.get(testKey).get(testCaseName).containsKey(mainKey)) { | |||
return coveragePerTest.get(testKey).get(testCaseName).get(mainKey); | |||
} else { | |||
return Collections.emptyList(); | |||
} | |||
} | |||
/** | |||
* Get highlighting types at a given position in an inputfile | |||
* @param charIndex 0-based offset in file |
@@ -1,118 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan2; | |||
import com.google.common.base.Objects; | |||
import com.google.common.base.Preconditions; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.google.common.collect.Maps; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.measure.MetricFinder; | |||
import org.sonar.api.batch.sensor.SensorStorage; | |||
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; | |||
import org.sonar.api.measures.FileLinesContext; | |||
import org.sonar.api.utils.KeyValueFormat; | |||
import java.util.Map; | |||
public class DefaultFileLinesContext implements FileLinesContext { | |||
private final SensorStorage sensorStorage; | |||
private final InputFile inputFile; | |||
/** | |||
* metric key -> line -> value | |||
*/ | |||
private final Map<String, Map<Integer, Object>> map = Maps.newHashMap(); | |||
private MetricFinder metricFinder; | |||
public DefaultFileLinesContext(MetricFinder metricFinder, SensorStorage sensorStorage, InputFile inputFile) { | |||
this.metricFinder = metricFinder; | |||
this.sensorStorage = sensorStorage; | |||
this.inputFile = inputFile; | |||
} | |||
@Override | |||
public void setIntValue(String metricKey, int line, int value) { | |||
Preconditions.checkNotNull(metricKey); | |||
Preconditions.checkArgument(line > 0); | |||
setValue(metricKey, line, value); | |||
} | |||
@Override | |||
public Integer getIntValue(String metricKey, int line) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override | |||
public void setStringValue(String metricKey, int line, String value) { | |||
Preconditions.checkNotNull(metricKey); | |||
Preconditions.checkArgument(line > 0); | |||
Preconditions.checkNotNull(value); | |||
setValue(metricKey, line, value); | |||
} | |||
@Override | |||
public String getStringValue(String metricKey, int line) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
private Map<Integer, Object> getOrCreateLines(String metricKey) { | |||
Map<Integer, Object> lines = map.get(metricKey); | |||
if (lines == null) { | |||
lines = Maps.newHashMap(); | |||
map.put(metricKey, lines); | |||
} | |||
return lines; | |||
} | |||
private void setValue(String metricKey, int line, Object value) { | |||
getOrCreateLines(metricKey).put(line, value); | |||
} | |||
@Override | |||
public void save() { | |||
for (Map.Entry<String, Map<Integer, Object>> entry : map.entrySet()) { | |||
String metricKey = entry.getKey(); | |||
org.sonar.api.batch.measure.Metric<String> metric = metricFinder.findByKey(metricKey); | |||
if (metric == null) { | |||
throw new IllegalStateException("Unable to find metric with key: " + metricKey); | |||
} | |||
Map<Integer, Object> lines = entry.getValue(); | |||
String data = KeyValueFormat.format(lines); | |||
new DefaultMeasure<String>(sensorStorage) | |||
.forMetric(metric) | |||
.onFile(inputFile) | |||
.withValue(data) | |||
.save(); | |||
entry.setValue(ImmutableMap.copyOf(lines)); | |||
} | |||
} | |||
@Override | |||
public String toString() { | |||
return Objects.toStringHelper(this) | |||
.add("map", map) | |||
.toString(); | |||
} | |||
} |
@@ -1,59 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan2; | |||
import org.sonar.api.batch.bootstrap.ProjectDefinition; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.measure.MetricFinder; | |||
import org.sonar.api.batch.sensor.SensorStorage; | |||
import org.sonar.api.measures.FileLinesContext; | |||
import org.sonar.api.measures.FileLinesContextFactory; | |||
import org.sonar.api.resources.Resource; | |||
import org.sonar.batch.scan.filesystem.InputPathCache; | |||
public class DefaultFileLinesContextFactory implements FileLinesContextFactory { | |||
private final SensorStorage sensorStorage; | |||
private final MetricFinder metricFinder; | |||
private final ProjectDefinition def; | |||
private final InputPathCache fileCache; | |||
public DefaultFileLinesContextFactory(InputPathCache fileCache, MetricFinder metricFinder, SensorStorage sensorStorage, | |||
ProjectDefinition def) { | |||
this.fileCache = fileCache; | |||
this.metricFinder = metricFinder; | |||
this.sensorStorage = sensorStorage; | |||
this.def = def; | |||
} | |||
@Override | |||
public FileLinesContext createFor(Resource model) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override | |||
public FileLinesContext createFor(InputFile inputFile) { | |||
if (fileCache.getFile(def.getKey(), inputFile.relativePath()) == null) { | |||
throw new IllegalStateException("InputFile is not indexed: " + inputFile); | |||
} | |||
return new DefaultFileLinesContext(metricFinder, sensorStorage, inputFile); | |||
} | |||
} |
@@ -1,21 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
@javax.annotation.ParametersAreNonnullByDefault | |||
package org.sonar.batch.scan2; |
@@ -36,12 +36,6 @@ import org.sonar.api.batch.sensor.issue.internal.DefaultIssue; | |||
import org.sonar.api.batch.sensor.measure.NewMeasure; | |||
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; | |||
import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; | |||
import org.sonar.api.batch.sensor.test.Coverage; | |||
import org.sonar.api.batch.sensor.test.TestCaseCoverage; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultCoverage; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseCoverage; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.batch.highlighting.DefaultHighlightingBuilder; | |||
import org.sonar.batch.index.ComponentDataCache; | |||
@@ -113,21 +107,6 @@ public class DefaultSensorContext implements SensorContext { | |||
return new DefaultDuplication(sensorStorage); | |||
} | |||
@Override | |||
public Coverage newCoverage() { | |||
return new DefaultCoverage(sensorStorage); | |||
} | |||
@Override | |||
public TestCaseExecution newTestCaseExecution() { | |||
return new DefaultTestCaseExecution(sensorStorage); | |||
} | |||
@Override | |||
public TestCaseCoverage newTestCaseCoverage() { | |||
return new DefaultTestCaseCoverage(sensorStorage); | |||
} | |||
@Override | |||
public NewDependency newDependency() { | |||
return new DefaultDependency(sensorStorage); |
@@ -33,9 +33,6 @@ import org.sonar.api.batch.sensor.issue.Issue; | |||
import org.sonar.api.batch.sensor.issue.Issue.Severity; | |||
import org.sonar.api.batch.sensor.measure.Measure; | |||
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; | |||
import org.sonar.api.batch.sensor.test.TestCaseCoverage; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution; | |||
import org.sonar.api.component.ResourcePerspectives; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.api.design.Dependency; | |||
@@ -52,10 +49,6 @@ import org.sonar.api.resources.Qualifiers; | |||
import org.sonar.api.resources.Resource; | |||
import org.sonar.api.resources.Scopes; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.test.MutableTestCase; | |||
import org.sonar.api.test.MutableTestPlan; | |||
import org.sonar.api.test.MutableTestable; | |||
import org.sonar.api.test.Testable; | |||
import org.sonar.batch.duplication.DuplicationCache; | |||
import org.sonar.batch.index.BatchResource; | |||
import org.sonar.batch.index.ComponentDataCache; | |||
@@ -182,40 +175,6 @@ public class DefaultSensorStorage implements SensorStorage { | |||
.build(); | |||
} | |||
@Override | |||
public void store(TestCaseExecution testCase) { | |||
File testRes = getTestResource(((DefaultTestCaseExecution) testCase).testFile()); | |||
MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes); | |||
if (testPlan != null) { | |||
testPlan | |||
.addTestCase(testCase.name()) | |||
.setDurationInMs(testCase.durationInMs()) | |||
.setType(testCase.type().name()) | |||
.setStatus(org.sonar.api.test.TestCase.Status.valueOf(testCase.status().name())) | |||
.setMessage(testCase.message()) | |||
.setStackTrace(testCase.stackTrace()); | |||
} | |||
} | |||
@Override | |||
public void store(TestCaseCoverage testCaseCoverage) { | |||
File testRes = getTestResource(testCaseCoverage.testFile()); | |||
File mainRes = getMainResource(testCaseCoverage.coveredFile()); | |||
Testable testAbleFile = perspectives.as(MutableTestable.class, mainRes); | |||
if (testAbleFile != null) { | |||
MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes); | |||
if (testPlan != null) { | |||
for (MutableTestCase mutableTestCase : testPlan.testCasesByName(testCaseCoverage.testName())) { | |||
mutableTestCase.setCoverageBlock(testAbleFile, testCaseCoverage.coveredLines()); | |||
} | |||
} else { | |||
throw new IllegalStateException("Unable to get MutableTestPlan perspective from " + testRes); | |||
} | |||
} else { | |||
throw new IllegalStateException("Unable to get MutableTestable perspective from " + mainRes); | |||
} | |||
} | |||
private File getTestResource(InputFile testFile) { | |||
File testRes = File.create(testFile.relativePath()); | |||
testRes.setQualifier(Qualifiers.UNIT_TEST_FILE); |
@@ -1,81 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.test; | |||
import com.persistit.Value; | |||
import com.persistit.encoding.CoderContext; | |||
import com.persistit.encoding.ValueCoder; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseCoverage; | |||
import org.sonar.batch.scan.filesystem.InputPathCache; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
class DefaultTestCaseCoverageValueCoder implements ValueCoder { | |||
private InputPathCache inputPathCache; | |||
public DefaultTestCaseCoverageValueCoder(InputPathCache inputPathCache) { | |||
this.inputPathCache = inputPathCache; | |||
} | |||
@Override | |||
public void put(Value value, Object object, CoderContext context) { | |||
DefaultTestCaseCoverage t = (DefaultTestCaseCoverage) object; | |||
value.putUTF(((DefaultInputFile) t.testFile()).moduleKey()); | |||
value.putUTF(((DefaultInputFile) t.testFile()).relativePath()); | |||
value.putUTF(t.testName()); | |||
value.putUTF(((DefaultInputFile) t.coveredFile()).moduleKey()); | |||
value.putUTF(((DefaultInputFile) t.coveredFile()).relativePath()); | |||
value.put(t.coveredLines().size()); | |||
for (Integer line : t.coveredLines()) { | |||
value.put(line.intValue()); | |||
} | |||
} | |||
@Override | |||
public Object get(Value value, Class clazz, CoderContext context) { | |||
String testModuleKey = value.getString(); | |||
String testRelativePath = value.getString(); | |||
InputFile testFile = inputPathCache.getFile(testModuleKey, testRelativePath); | |||
if (testFile == null) { | |||
throw new IllegalStateException("Unable to load InputFile " + testModuleKey + ":" + testRelativePath); | |||
} | |||
String name = value.getString(); | |||
String mainModuleKey = value.getString(); | |||
String mainRelativePath = value.getString(); | |||
InputFile mainFile = inputPathCache.getFile(mainModuleKey, mainRelativePath); | |||
if (mainFile == null) { | |||
throw new IllegalStateException("Unable to load InputFile " + mainModuleKey + ":" + mainRelativePath); | |||
} | |||
int size = value.getInt(); | |||
List<Integer> lines = new ArrayList<Integer>(size); | |||
for (int i = 0; i < size; i++) { | |||
lines.add(value.getInt()); | |||
} | |||
return new DefaultTestCaseCoverage() | |||
.testFile(testFile) | |||
.testName(name) | |||
.cover(mainFile) | |||
.onLines(lines); | |||
} | |||
} |
@@ -1,90 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.test; | |||
import com.persistit.Value; | |||
import com.persistit.encoding.CoderContext; | |||
import com.persistit.encoding.ValueCoder; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution; | |||
import org.sonar.batch.scan.filesystem.InputPathCache; | |||
import javax.annotation.Nullable; | |||
class DefaultTestCaseExecutionValueCoder implements ValueCoder { | |||
private InputPathCache inputPathCache; | |||
public DefaultTestCaseExecutionValueCoder(InputPathCache inputPathCache) { | |||
this.inputPathCache = inputPathCache; | |||
} | |||
@Override | |||
public void put(Value value, Object object, CoderContext context) { | |||
DefaultTestCaseExecution t = (DefaultTestCaseExecution) object; | |||
value.putUTF(((DefaultInputFile) t.testFile()).moduleKey()); | |||
value.putUTF(((DefaultInputFile) t.testFile()).relativePath()); | |||
value.putUTF(t.name()); | |||
putUTFOrNull(value, t.message()); | |||
putUTFOrNull(value, t.stackTrace()); | |||
Long durationInMs = t.durationInMs(); | |||
value.put(durationInMs != null ? durationInMs.longValue() : -1); | |||
value.put(t.type().ordinal()); | |||
value.put(t.status().ordinal()); | |||
} | |||
private void putUTFOrNull(Value value, @Nullable String utfOrNull) { | |||
if (utfOrNull != null) { | |||
value.putUTF(utfOrNull); | |||
} else { | |||
value.putNull(); | |||
} | |||
} | |||
@Override | |||
public Object get(Value value, Class clazz, CoderContext context) { | |||
String moduleKey = value.getString(); | |||
String relativePath = value.getString(); | |||
InputFile testFile = inputPathCache.getFile(moduleKey, relativePath); | |||
if (testFile == null) { | |||
throw new IllegalStateException("Unable to load InputFile " + moduleKey + ":" + relativePath); | |||
} | |||
String name = value.getString(); | |||
String message = value.getString(); | |||
String stack = value.getString(); | |||
long duration = value.getLong(); | |||
TestCaseExecution.Type type = TestCaseExecution.Type.values()[value.getInt()]; | |||
TestCaseExecution.Status status = TestCaseExecution.Status.values()[value.getInt()]; | |||
DefaultTestCaseExecution testCaseExecution = new DefaultTestCaseExecution(); | |||
testCaseExecution | |||
.inTestFile(testFile) | |||
.ofType(type) | |||
.name(name) | |||
.status(status) | |||
.message(message) | |||
.stackTrace(stack); | |||
if (duration != -1) { | |||
testCaseExecution.durationInMs(duration); | |||
} | |||
return testCaseExecution; | |||
} | |||
} |
@@ -1,65 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.test; | |||
import com.google.common.base.Preconditions; | |||
import org.sonar.api.BatchComponent; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.test.TestCaseCoverage; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseCoverage; | |||
import org.sonar.batch.index.Cache; | |||
import org.sonar.batch.index.Cache.Entry; | |||
import org.sonar.batch.index.Caches; | |||
import org.sonar.batch.scan.filesystem.InputPathCache; | |||
import javax.annotation.CheckForNull; | |||
/** | |||
* Cache of coverage per test. This cache is shared amongst all project modules. | |||
*/ | |||
public class TestCaseCoverageCache implements BatchComponent { | |||
private final Cache<TestCaseCoverage> cache; | |||
public TestCaseCoverageCache(Caches caches, InputPathCache inputPathCache) { | |||
caches.registerValueCoder(DefaultTestCaseCoverage.class, new DefaultTestCaseCoverageValueCoder(inputPathCache)); | |||
cache = caches.createCache("testCaseCoverage"); | |||
} | |||
public Iterable<Entry<TestCaseCoverage>> entries() { | |||
return cache.entries(); | |||
} | |||
@CheckForNull | |||
public TestCaseCoverage getCoverage(InputFile testFile, String testCaseName, InputFile mainFile) { | |||
Preconditions.checkNotNull(testFile); | |||
Preconditions.checkNotNull(testCaseName); | |||
Preconditions.checkNotNull(mainFile); | |||
return cache.get(((DefaultInputFile) testFile).key(), testCaseName, ((DefaultInputFile) mainFile).key()); | |||
} | |||
public TestCaseCoverageCache put(TestCaseCoverage coverage) { | |||
Preconditions.checkNotNull(coverage); | |||
cache.put(((DefaultInputFile) coverage.testFile()).key(), coverage.testName(), ((DefaultInputFile) coverage.coveredFile()).key(), coverage); | |||
return this; | |||
} | |||
} |
@@ -1,69 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.test; | |||
import com.google.common.base.Preconditions; | |||
import org.sonar.api.BatchComponent; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution; | |||
import org.sonar.batch.index.Cache; | |||
import org.sonar.batch.index.Cache.Entry; | |||
import org.sonar.batch.index.Caches; | |||
import org.sonar.batch.scan.filesystem.InputPathCache; | |||
import javax.annotation.CheckForNull; | |||
/** | |||
* Cache of all TestCases. This cache is shared amongst all project modules. | |||
*/ | |||
public class TestCaseExecutionCache implements BatchComponent { | |||
private final Cache<TestCaseExecution> cache; | |||
public TestCaseExecutionCache(Caches caches, InputPathCache inputPathCache) { | |||
caches.registerValueCoder(DefaultTestCaseExecution.class, new DefaultTestCaseExecutionValueCoder(inputPathCache)); | |||
cache = caches.createCache("testCaseExecutions"); | |||
} | |||
public Iterable<Entry<TestCaseExecution>> entries() { | |||
return cache.entries(); | |||
} | |||
@CheckForNull | |||
public TestCaseExecution get(InputFile testFile, String testCaseName) { | |||
Preconditions.checkNotNull(testFile); | |||
Preconditions.checkNotNull(testCaseName); | |||
return cache.get(((DefaultInputFile) testFile).key(), testCaseName); | |||
} | |||
public TestCaseExecutionCache put(InputFile testFile, TestCaseExecution testCase) { | |||
Preconditions.checkNotNull(testFile); | |||
Preconditions.checkNotNull(testCase); | |||
cache.put(((DefaultInputFile) testFile).key(), testCase.name(), testCase); | |||
return this; | |||
} | |||
public boolean contains(InputFile testFile, String name) { | |||
return cache.containsKey(((DefaultInputFile) testFile).key(), name); | |||
} | |||
} |
@@ -1,24 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
@ParametersAreNonnullByDefault | |||
package org.sonar.batch.test; | |||
import javax.annotation.ParametersAreNonnullByDefault; | |||
@@ -1,128 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.mediumtest.test; | |||
import com.google.common.collect.ImmutableMap; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.junit.rules.TestName; | |||
import org.sonar.batch.mediumtest.BatchMediumTester; | |||
import org.sonar.batch.mediumtest.TaskResult; | |||
import org.sonar.xoo.XooPlugin; | |||
import java.io.File; | |||
import java.io.IOException; | |||
public class TestMediumTest { | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@Rule | |||
public TestName testName = new TestName(); | |||
public BatchMediumTester tester = BatchMediumTester.builder() | |||
.registerPlugin("xoo", new XooPlugin()) | |||
.addDefaultQProfile("xoo", "Sonar Way") | |||
.build(); | |||
@Before | |||
public void prepare() { | |||
tester.start(); | |||
} | |||
@After | |||
public void stop() { | |||
tester.stop(); | |||
} | |||
@Test | |||
public void populateTestCaseOnTempProject() throws IOException { | |||
File baseDir = temp.newFolder(); | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
File testDir = new File(baseDir, "test"); | |||
testDir.mkdir(); | |||
File xooTestFile = new File(testDir, "sampleTest.xoo"); | |||
File xooTestPlanFile = new File(testDir, "sampleTest.xoo.testplan"); | |||
FileUtils.write(xooTestFile, "Sample test xoo\ncontent"); | |||
FileUtils.write(xooTestPlanFile, "test1:UNIT:OK:::\ntest2:INTEGRATION:ERROR:Assertion failure:A very long stack:12"); | |||
TaskResult result = tester.newTask() | |||
.properties(ImmutableMap.<String, String>builder() | |||
.put("sonar.task", "scan") | |||
.put("sonar.projectBaseDir", baseDir.getAbsolutePath()) | |||
.put("sonar.projectKey", "com.foo.project") | |||
.put("sonar.projectName", "Foo Project") | |||
.put("sonar.projectVersion", "1.0-SNAPSHOT") | |||
.put("sonar.projectDescription", "Description of Foo Project") | |||
.put("sonar.sources", "src") | |||
.put("sonar.tests", "test") | |||
.build()) | |||
.start(); | |||
// assertThat(result.testCasesFor(new DefaultInputFile("com.foo.project", "test/sampleTest.xoo"))).hasSize(2); | |||
} | |||
@Test | |||
public void populateTestCaseAndCoveragePerTestOnTempProject() throws IOException { | |||
File baseDir = temp.newFolder(); | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
File testDir = new File(baseDir, "test"); | |||
testDir.mkdir(); | |||
File xooMainFile = new File(srcDir, "sample.xoo"); | |||
File xooTestFile = new File(testDir, "sampleTest.xoo"); | |||
File xooTestPlanFile = new File(testDir, "sampleTest.xoo.testplan"); | |||
File xooTestCoverageFile = new File(testDir, "sampleTest.xoo.coveragePerTest"); | |||
FileUtils.write(xooMainFile, "Sample xoo\ncontent"); | |||
FileUtils.write(xooTestFile, "Sample test xoo\ncontent"); | |||
FileUtils.write(xooTestPlanFile, "test1:UNIT:OK:::3\ntest2:INTEGRATION:ERROR:Assertion failure:A very long stack:12"); | |||
FileUtils.write(xooTestCoverageFile, "test1:src/sample.xoo:1,2,3,8,9,10\ntest2:src/sample.xoo:3,4"); | |||
// TaskResult result = tester.newTask() | |||
// .properties(ImmutableMap.<String, String>builder() | |||
// .put("sonar.task", "scan") | |||
// .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) | |||
// .put("sonar.projectKey", "com.foo.project") | |||
// .put("sonar.projectName", "Foo Project") | |||
// .put("sonar.projectVersion", "1.0-SNAPSHOT") | |||
// .put("sonar.projectDescription", "Description of Foo Project") | |||
// .put("sonar.sources", "src") | |||
// .put("sonar.tests", "test") | |||
// .build()) | |||
// .start(); | |||
// | |||
// assertThat(result.coveragePerTest(new DefaultInputFile("com.foo.project", "test/sampleTest.xoo"), "test1", new | |||
// DefaultInputFile("com.foo.project", "src/sample.xoo"))) | |||
// .containsExactly(1, 2, 3, 8, 9, 10); | |||
// assertThat(result.coveragePerTest(new DefaultInputFile("com.foo.project", "test/sampleTest.xoo"), "test2", new | |||
// DefaultInputFile("com.foo.project", "src/sample.xoo"))) | |||
// .containsExactly(3, 4); | |||
} | |||
} |
@@ -31,9 +31,6 @@ import org.sonar.api.batch.sensor.issue.Issue; | |||
import org.sonar.api.batch.sensor.measure.Measure; | |||
import org.sonar.api.batch.sensor.measure.NewMeasure; | |||
import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; | |||
import org.sonar.api.batch.sensor.test.Coverage; | |||
import org.sonar.api.batch.sensor.test.TestCaseCoverage; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
import org.sonar.api.config.Settings; | |||
import java.io.Serializable; | |||
@@ -102,23 +99,7 @@ public interface SensorContext { | |||
// ------------ TESTS ------------ | |||
/** | |||
* Create a new coverage report. | |||
* Don't forget to call {@link Coverage#save()} once all parameters are provided. | |||
*/ | |||
Coverage newCoverage(); | |||
/** | |||
* Create a new test case execution report. | |||
* Don't forget to call {@link TestCaseExecution#save()} once all parameters are provided. | |||
*/ | |||
TestCaseExecution newTestCaseExecution(); | |||
/** | |||
* Create a new test case coverage report. | |||
* Don't forget to call {@link TestCaseCoverage#save()} once all parameters are provided. | |||
*/ | |||
TestCaseCoverage newTestCaseCoverage(); | |||
// TODO | |||
// ------------ DEPENDENCIES ------------ | |||
@@ -23,8 +23,6 @@ import org.sonar.api.batch.sensor.dependency.Dependency; | |||
import org.sonar.api.batch.sensor.duplication.Duplication; | |||
import org.sonar.api.batch.sensor.issue.Issue; | |||
import org.sonar.api.batch.sensor.measure.Measure; | |||
import org.sonar.api.batch.sensor.test.TestCaseCoverage; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
/** | |||
* Interface for storing data computed by sensors. | |||
@@ -38,10 +36,6 @@ public interface SensorStorage { | |||
void store(Duplication duplication); | |||
void store(TestCaseExecution testCaseExecution); | |||
void store(Dependency dependency); | |||
void store(TestCaseCoverage testCaseCoverage); | |||
} |
@@ -1,103 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.batch.sensor.test; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.measure.Metric; | |||
import org.sonar.api.measures.CoreMetrics; | |||
/** | |||
* @since 5.0 | |||
*/ | |||
public interface Coverage { | |||
public enum CoverageType { | |||
UNIT(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.COVERAGE_LINE_HITS_DATA, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS, | |||
CoreMetrics.CONDITIONS_BY_LINE, CoreMetrics.COVERED_CONDITIONS_BY_LINE), | |||
INTEGRATION(CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.IT_COVERAGE_LINE_HITS_DATA, CoreMetrics.IT_CONDITIONS_TO_COVER, | |||
CoreMetrics.IT_UNCOVERED_CONDITIONS, CoreMetrics.IT_CONDITIONS_BY_LINE, CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE), | |||
OVERALL(CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA, CoreMetrics.OVERALL_CONDITIONS_TO_COVER, | |||
CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, CoreMetrics.OVERALL_CONDITIONS_BY_LINE, CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE); | |||
private Metric<Integer> linesToCover; | |||
private Metric<Integer> uncoveredLines; | |||
private Metric<String> lineHitsData; | |||
private Metric<Integer> conditionsToCover; | |||
private Metric<Integer> uncoveredConditions; | |||
private Metric<String> conditionsByLine; | |||
private Metric<String> coveredConditionsByLine; | |||
private CoverageType(Metric<Integer> linesToCover, Metric<Integer> uncoveredLines, Metric<String> lineHitsData, Metric<Integer> conditionsToCover, | |||
Metric<Integer> uncoveredConditions, Metric<String> conditionsByLine, Metric<String> coveredConditionsByLine) { | |||
this.linesToCover = linesToCover; | |||
this.uncoveredLines = uncoveredLines; | |||
this.lineHitsData = lineHitsData; | |||
this.conditionsToCover = conditionsToCover; | |||
this.uncoveredConditions = uncoveredConditions; | |||
this.conditionsByLine = conditionsByLine; | |||
this.coveredConditionsByLine = coveredConditionsByLine; | |||
} | |||
public Metric<Integer> linesToCover() { | |||
return linesToCover; | |||
} | |||
public Metric<Integer> uncoveredLines() { | |||
return uncoveredLines; | |||
} | |||
public Metric<String> lineHitsData() { | |||
return lineHitsData; | |||
} | |||
public Metric<Integer> conditionsToCover() { | |||
return conditionsToCover; | |||
} | |||
public Metric<Integer> uncoveredConditions() { | |||
return uncoveredConditions; | |||
} | |||
public Metric<String> conditionsByLine() { | |||
return conditionsByLine; | |||
} | |||
public Metric<String> coveredConditionsByLine() { | |||
return coveredConditionsByLine; | |||
} | |||
} | |||
/** | |||
* The file you are storing coverage on. | |||
*/ | |||
Coverage onFile(InputFile inputFile); | |||
Coverage ofType(CoverageType type); | |||
Coverage lineHits(int line, int hits); | |||
Coverage conditions(int line, int conditions, int coveredConditions); | |||
/** | |||
* Call this method only once when your are done with defining the test case coverage. | |||
*/ | |||
void save(); | |||
} |
@@ -1,77 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.batch.sensor.test; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import java.util.List; | |||
/** | |||
* Represents line coverage produced by a single test in a test file on a single main file. | |||
* @since 5.0 | |||
*/ | |||
public interface TestCaseCoverage { | |||
/** | |||
* InputFile where this test is located. | |||
*/ | |||
InputFile testFile(); | |||
/** | |||
* Set file where this test is located. Mandatory. | |||
*/ | |||
TestCaseCoverage testFile(InputFile testFile); | |||
/** | |||
* Name of this test case. | |||
*/ | |||
String testName(); | |||
/** | |||
* Set name of this test. Name is mandatory. | |||
*/ | |||
TestCaseCoverage testName(String name); | |||
/** | |||
* InputFile covered by this test. | |||
*/ | |||
InputFile coveredFile(); | |||
/** | |||
* Set file covered by this test. Mandatory. | |||
*/ | |||
TestCaseCoverage cover(InputFile mainFile); | |||
/** | |||
* List of line numbers (1-based) covered by this test. | |||
*/ | |||
List<Integer> coveredLines(); | |||
/** | |||
* Set list of line numbers (1-based) covered by this test. Mandatory. | |||
*/ | |||
TestCaseCoverage onLines(List<Integer> lines); | |||
/** | |||
* Call this method only once when your are done with defining the test case coverage. | |||
*/ | |||
void save(); | |||
} |
@@ -1,125 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.batch.sensor.test; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import javax.annotation.Nullable; | |||
/** | |||
* Represents result of execution of a single test in a test file. | |||
* @since 5.0 | |||
*/ | |||
public interface TestCaseExecution { | |||
/** | |||
* Test execution status. | |||
*/ | |||
enum Status { | |||
OK, FAILURE, ERROR, SKIPPED; | |||
public static Status of(@Nullable String s) { | |||
return s == null ? null : valueOf(s.toUpperCase()); | |||
} | |||
} | |||
/** | |||
* Test type. | |||
*/ | |||
enum Type { | |||
UNIT, INTEGRATION; | |||
} | |||
/** | |||
* InputFile where this test is located. | |||
*/ | |||
InputFile testFile(); | |||
/** | |||
* Set file where this test is located. Mandatory. | |||
*/ | |||
TestCaseExecution inTestFile(InputFile testFile); | |||
/** | |||
* Duration in milliseconds | |||
*/ | |||
Long durationInMs(); | |||
/** | |||
* Duration in milliseconds | |||
*/ | |||
TestCaseExecution durationInMs(long duration); | |||
/** | |||
* Name of this test case. | |||
*/ | |||
String name(); | |||
/** | |||
* Set name of this test. Name is mandatory. | |||
*/ | |||
TestCaseExecution name(String name); | |||
/** | |||
* Status of execution of the test. | |||
*/ | |||
Status status(); | |||
/** | |||
* Status of execution of the test. | |||
*/ | |||
TestCaseExecution status(Status status); | |||
/** | |||
* Message (usually in case of {@link Status#ERROR} or {@link Status#FAILURE}). | |||
*/ | |||
String message(); | |||
/** | |||
* Message (usually in case of {@link Status#ERROR} or {@link Status#FAILURE}). | |||
*/ | |||
TestCaseExecution message(String message); | |||
/** | |||
* Type of test. | |||
*/ | |||
Type type(); | |||
/** | |||
* Type of test. | |||
*/ | |||
TestCaseExecution ofType(Type type); | |||
/** | |||
* Stacktrace (usually in case of {@link Status#ERROR}). | |||
*/ | |||
String stackTrace(); | |||
/** | |||
* Set stacktrace (usually in case of {@link Status#ERROR}). | |||
*/ | |||
TestCaseExecution stackTrace(String stackTrace); | |||
/** | |||
* Call this method only once when your are done with defining the test case execution. | |||
*/ | |||
void save(); | |||
} |
@@ -1,153 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.batch.sensor.test.internal; | |||
import com.google.common.base.Preconditions; | |||
import com.google.common.collect.Maps; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.InputFile.Type; | |||
import org.sonar.api.batch.sensor.SensorStorage; | |||
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; | |||
import org.sonar.api.batch.sensor.test.Coverage; | |||
import org.sonar.api.utils.KeyValueFormat; | |||
import java.util.SortedMap; | |||
public final class DefaultCoverage implements Coverage { | |||
private static final String INPUT_FILE_SHOULD_BE_NON_NULL = "InputFile should be non null"; | |||
private InputFile file; | |||
private CoverageType type; | |||
private int totalCoveredLines = 0, totalConditions = 0, totalCoveredConditions = 0; | |||
private SortedMap<Integer, Integer> hitsByLine = Maps.newTreeMap(); | |||
private SortedMap<Integer, Integer> conditionsByLine = Maps.newTreeMap(); | |||
private SortedMap<Integer, Integer> coveredConditionsByLine = Maps.newTreeMap(); | |||
protected final transient SensorStorage storage; | |||
private transient boolean saved = false; | |||
public DefaultCoverage() { | |||
this.storage = null; | |||
} | |||
public DefaultCoverage(SensorStorage storage) { | |||
this.storage = storage; | |||
} | |||
@Override | |||
public DefaultCoverage lineHits(int lineId, int hits) { | |||
Preconditions.checkArgument(lineId >= 1, "Line number should be positive and non zero [" + file.relativePath() + ":" + lineId + "]"); | |||
Preconditions.checkArgument(hits >= 0, "Hits should be positive [" + file.relativePath() + ":" + lineId + "]"); | |||
Preconditions.checkArgument(!hitsByLine.containsKey(lineId), "Hits already saved on line [" + file.relativePath() + ":" + lineId + "]"); | |||
hitsByLine.put(lineId, hits); | |||
if (hits > 0) { | |||
totalCoveredLines += 1; | |||
} | |||
return this; | |||
} | |||
@Override | |||
public DefaultCoverage conditions(int lineId, int conditions, int coveredConditions) { | |||
Preconditions.checkArgument(lineId >= 1, "Line number should be positive and non zero [" + file.relativePath() + ":" + lineId + "]"); | |||
Preconditions.checkArgument(conditions >= 0, "Number of conditions should be positive [" + file.relativePath() + ":" + lineId + "]"); | |||
Preconditions.checkArgument(coveredConditions >= 0, "Number of covered conditions should be positive [" + file.relativePath() + ":" + lineId + "]"); | |||
Preconditions.checkArgument(conditions >= coveredConditions, "Number of covered conditions can't exceed conditions [" + file.relativePath() + ":" + lineId + "]"); | |||
Preconditions.checkArgument(!conditionsByLine.containsKey(lineId), "Conditions already saved on line [" + file.relativePath() + ":" + lineId + "]"); | |||
totalConditions += conditions; | |||
totalCoveredConditions += coveredConditions; | |||
conditionsByLine.put(lineId, conditions); | |||
coveredConditionsByLine.put(lineId, coveredConditions); | |||
return this; | |||
} | |||
public InputFile file() { | |||
return file; | |||
} | |||
@Override | |||
public DefaultCoverage onFile(InputFile inputFile) { | |||
Preconditions.checkNotNull(inputFile, INPUT_FILE_SHOULD_BE_NON_NULL); | |||
Preconditions.checkArgument(inputFile.type() == Type.MAIN, "Coverage is only supported on main files [" + inputFile.relativePath() + "]"); | |||
this.file = inputFile; | |||
return this; | |||
} | |||
public CoverageType type() { | |||
return type; | |||
} | |||
@Override | |||
public DefaultCoverage ofType(CoverageType type) { | |||
Preconditions.checkNotNull(type); | |||
this.type = type; | |||
return this; | |||
} | |||
@Override | |||
public void save() { | |||
Preconditions.checkNotNull(this.storage, "No persister on this object"); | |||
Preconditions.checkState(!saved, "This object was already saved"); | |||
Preconditions.checkNotNull(this.file, "File is mandatory on Coverage"); | |||
Preconditions.checkNotNull(this.type, "Type is mandatory on Coverage"); | |||
if (!hitsByLine.isEmpty()) { | |||
new DefaultMeasure<Integer>(storage) | |||
.onFile(file) | |||
.forMetric(type.linesToCover()) | |||
.withValue(hitsByLine.size()) | |||
.save(); | |||
new DefaultMeasure<Integer>(storage) | |||
.onFile(file) | |||
.forMetric(type.uncoveredLines()) | |||
.withValue(hitsByLine.size() - totalCoveredLines) | |||
.save(); | |||
new DefaultMeasure<String>(storage) | |||
.onFile(file) | |||
.forMetric(type.lineHitsData()) | |||
.withValue(KeyValueFormat.format(hitsByLine)) | |||
.save(); | |||
} | |||
if (totalConditions > 0) { | |||
new DefaultMeasure<Integer>(storage) | |||
.onFile(file) | |||
.forMetric(type.conditionsToCover()) | |||
.withValue(totalConditions) | |||
.save(); | |||
new DefaultMeasure<Integer>(storage) | |||
.onFile(file) | |||
.forMetric(type.uncoveredConditions()) | |||
.withValue(totalConditions - totalCoveredConditions) | |||
.save(); | |||
new DefaultMeasure<String>(storage) | |||
.onFile(file) | |||
.forMetric(type.coveredConditionsByLine()) | |||
.withValue(KeyValueFormat.format(coveredConditionsByLine)) | |||
.save(); | |||
new DefaultMeasure<String>(storage) | |||
.onFile(file) | |||
.forMetric(type.conditionsByLine()) | |||
.withValue(KeyValueFormat.format(conditionsByLine)) | |||
.save(); | |||
} | |||
this.saved = true; | |||
} | |||
} |
@@ -1,138 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.batch.sensor.test.internal; | |||
import com.google.common.base.Preconditions; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.apache.commons.lang.builder.EqualsBuilder; | |||
import org.apache.commons.lang.builder.HashCodeBuilder; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.sensor.SensorStorage; | |||
import org.sonar.api.batch.sensor.internal.DefaultStorable; | |||
import org.sonar.api.batch.sensor.test.TestCaseCoverage; | |||
import java.util.Collections; | |||
import java.util.List; | |||
public class DefaultTestCaseCoverage extends DefaultStorable implements TestCaseCoverage { | |||
private InputFile testFile; | |||
private InputFile mainFile; | |||
private String name; | |||
private List<Integer> lines; | |||
public DefaultTestCaseCoverage() { | |||
super(null); | |||
} | |||
public DefaultTestCaseCoverage(SensorStorage storage) { | |||
super(storage); | |||
} | |||
@Override | |||
public InputFile testFile() { | |||
return testFile; | |||
} | |||
@Override | |||
public DefaultTestCaseCoverage testFile(InputFile testFile) { | |||
Preconditions.checkNotNull(testFile, "TestFile cannot be null"); | |||
Preconditions.checkArgument(testFile.type() == InputFile.Type.TEST, "Should be a test file: " + testFile); | |||
this.testFile = testFile; | |||
return this; | |||
} | |||
@Override | |||
public InputFile coveredFile() { | |||
return mainFile; | |||
} | |||
@Override | |||
public DefaultTestCaseCoverage cover(InputFile mainFile) { | |||
Preconditions.checkNotNull(mainFile, "InputFile cannot be null"); | |||
Preconditions.checkArgument(mainFile.type() == InputFile.Type.MAIN, "Should be a main file: " + mainFile); | |||
this.mainFile = mainFile; | |||
return this; | |||
} | |||
@Override | |||
public DefaultTestCaseCoverage testName(String name) { | |||
Preconditions.checkArgument(StringUtils.isNotBlank(name), "Test name is mandatory and should not be blank"); | |||
this.name = name; | |||
return this; | |||
} | |||
@Override | |||
public String testName() { | |||
return name; | |||
} | |||
@Override | |||
public List<Integer> coveredLines() { | |||
return Collections.unmodifiableList(lines); | |||
} | |||
@Override | |||
public DefaultTestCaseCoverage onLines(List<Integer> lines) { | |||
Preconditions.checkNotNull(lines, "Lines list cannot be null"); | |||
Preconditions.checkArgument(!lines.isEmpty(), "No need to register test coverage if no line is covered"); | |||
this.lines = lines; | |||
return this; | |||
} | |||
@Override | |||
public void doSave() { | |||
Preconditions.checkNotNull(testFile, "TestFile is mandatory"); | |||
Preconditions.checkNotNull(mainFile, "MainFile is mandatory"); | |||
Preconditions.checkNotNull(name, "Test name is mandatory"); | |||
Preconditions.checkNotNull(lines, "Lines are mandatory"); | |||
storage.store(this); | |||
} | |||
// Just for unit tests | |||
@Override | |||
public boolean equals(Object obj) { | |||
if (obj == null) { | |||
return false; | |||
} | |||
if (obj == this) { | |||
return true; | |||
} | |||
if (obj.getClass() != getClass()) { | |||
return false; | |||
} | |||
DefaultTestCaseCoverage rhs = (DefaultTestCaseCoverage) obj; | |||
return new EqualsBuilder() | |||
.append(testFile, rhs.testFile) | |||
.append(name, rhs.name) | |||
.append(mainFile, rhs.mainFile) | |||
.append(lines.toArray(), rhs.lines.toArray()) | |||
.isEquals(); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return new HashCodeBuilder(13, 43) | |||
.append(testFile) | |||
.append(name) | |||
.append(mainFile) | |||
.toHashCode(); | |||
} | |||
} |
@@ -1,181 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.batch.sensor.test.internal; | |||
import com.google.common.base.Preconditions; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.apache.commons.lang.builder.EqualsBuilder; | |||
import org.apache.commons.lang.builder.HashCodeBuilder; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.sensor.SensorStorage; | |||
import org.sonar.api.batch.sensor.internal.DefaultStorable; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
public class DefaultTestCaseExecution extends DefaultStorable implements TestCaseExecution { | |||
private InputFile testFile; | |||
private String name; | |||
private Long duration; | |||
private TestCaseExecution.Status status = Status.OK; | |||
private String message; | |||
private TestCaseExecution.Type type = Type.UNIT; | |||
private String stackTrace; | |||
public DefaultTestCaseExecution() { | |||
super(null); | |||
} | |||
public DefaultTestCaseExecution(SensorStorage storage) { | |||
super(storage); | |||
} | |||
@Override | |||
public DefaultTestCaseExecution inTestFile(InputFile testFile) { | |||
Preconditions.checkNotNull(testFile, "TestFile cannot be null"); | |||
Preconditions.checkArgument(testFile.type() == InputFile.Type.TEST, "Should be a test file: " + testFile); | |||
this.testFile = testFile; | |||
return this; | |||
} | |||
@Override | |||
public DefaultTestCaseExecution name(String name) { | |||
Preconditions.checkArgument(StringUtils.isNotBlank(name), "Test name is mandatory and should not be blank"); | |||
this.name = name; | |||
return this; | |||
} | |||
@Override | |||
public DefaultTestCaseExecution durationInMs(long duration) { | |||
Preconditions.checkArgument(duration >= 0, "Test duration must be positive (got: " + duration + ")"); | |||
this.duration = duration; | |||
return this; | |||
} | |||
@Override | |||
public DefaultTestCaseExecution status(TestCaseExecution.Status status) { | |||
Preconditions.checkNotNull(status); | |||
this.status = status; | |||
return this; | |||
} | |||
@Override | |||
public DefaultTestCaseExecution message(@Nullable String message) { | |||
this.message = message; | |||
return this; | |||
} | |||
@Override | |||
public DefaultTestCaseExecution ofType(TestCaseExecution.Type type) { | |||
Preconditions.checkNotNull(type); | |||
this.type = type; | |||
return this; | |||
} | |||
@Override | |||
public DefaultTestCaseExecution stackTrace(@Nullable String stackTrace) { | |||
this.stackTrace = stackTrace; | |||
return this; | |||
} | |||
@Override | |||
public InputFile testFile() { | |||
return testFile; | |||
} | |||
@CheckForNull | |||
@Override | |||
public Long durationInMs() { | |||
return duration; | |||
} | |||
@Override | |||
public Type type() { | |||
return type; | |||
} | |||
@Override | |||
public Status status() { | |||
return status; | |||
} | |||
@Override | |||
public String name() { | |||
return name; | |||
} | |||
@CheckForNull | |||
@Override | |||
public String message() { | |||
return message; | |||
} | |||
@CheckForNull | |||
@Override | |||
public String stackTrace() { | |||
return stackTrace; | |||
} | |||
@Override | |||
public void doSave() { | |||
Preconditions.checkNotNull(testFile, "TestFile is mandatory"); | |||
Preconditions.checkNotNull(name, "Test name is mandatory"); | |||
storage.store(this); | |||
} | |||
// Just for unit tests | |||
@Override | |||
public boolean equals(Object obj) { | |||
if (obj == null) { | |||
return false; | |||
} | |||
if (obj == this) { | |||
return true; | |||
} | |||
if (obj.getClass() != getClass()) { | |||
return false; | |||
} | |||
DefaultTestCaseExecution rhs = (DefaultTestCaseExecution) obj; | |||
return new EqualsBuilder() | |||
.append(testFile, rhs.testFile) | |||
.append(name, rhs.name) | |||
.append(duration, rhs.duration) | |||
.append(status, rhs.status) | |||
.append(message, rhs.message) | |||
.append(type, rhs.type) | |||
.append(stackTrace, rhs.stackTrace) | |||
.isEquals(); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return new HashCodeBuilder(13, 43) | |||
.append(testFile) | |||
.append(name) | |||
.append(duration) | |||
.append(status) | |||
.append(message) | |||
.append(type) | |||
.append(stackTrace) | |||
.toHashCode(); | |||
} | |||
} |
@@ -1,22 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
@javax.annotation.ParametersAreNonnullByDefault | |||
package org.sonar.api.batch.sensor.test.internal; | |||
@@ -1,22 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
@javax.annotation.ParametersAreNonnullByDefault | |||
package org.sonar.api.batch.sensor.test; | |||
@@ -1,274 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.batch.sensor.test.internal; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.SensorStorage; | |||
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; | |||
import org.sonar.api.batch.sensor.test.Coverage.CoverageType; | |||
import org.sonar.api.measures.CoreMetrics; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.verifyNoMoreInteractions; | |||
public class DefaultCoverageTest { | |||
@Rule | |||
public ExpectedException thrown = ExpectedException.none(); | |||
private InputFile main = new DefaultInputFile("foo", "src/Foo.php").setType(InputFile.Type.MAIN); | |||
@Test | |||
public void testCreation() { | |||
DefaultCoverage coverage = new DefaultCoverage() | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.lineHits(1, 2) | |||
.lineHits(2, 5) | |||
.conditions(1, 2, 1); | |||
assertThat(coverage.file()).isEqualTo(main); | |||
assertThat(coverage.type()).isEqualTo(CoverageType.UNIT); | |||
} | |||
@Test | |||
public void testSaveLines() { | |||
SensorStorage storage = mock(SensorStorage.class); | |||
new DefaultCoverage(storage) | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.lineHits(1, 2) | |||
.lineHits(2, 5) | |||
.lineHits(3, 0) | |||
.lineHits(4, 0) | |||
.save(); | |||
verify(storage).store(new DefaultMeasure<Integer>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.LINES_TO_COVER) | |||
.withValue(4)); | |||
verify(storage).store(new DefaultMeasure<Integer>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.UNCOVERED_LINES) | |||
.withValue(2)); | |||
verify(storage).store(new DefaultMeasure<String>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.COVERAGE_LINE_HITS_DATA) | |||
.withValue("1=2;2=5;3=0;4=0")); | |||
verifyNoMoreInteractions(storage); | |||
} | |||
@Test | |||
public void testSaveConditions() { | |||
SensorStorage storage = mock(SensorStorage.class); | |||
new DefaultCoverage(storage) | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.conditions(1, 2, 1) | |||
.save(); | |||
verify(storage).store(new DefaultMeasure<Integer>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.CONDITIONS_TO_COVER) | |||
.withValue(2)); | |||
verify(storage).store(new DefaultMeasure<Integer>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.UNCOVERED_CONDITIONS) | |||
.withValue(1)); | |||
verify(storage).store(new DefaultMeasure<String>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.COVERED_CONDITIONS_BY_LINE) | |||
.withValue("1=1")); | |||
verify(storage).store(new DefaultMeasure<String>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.CONDITIONS_BY_LINE) | |||
.withValue("1=2")); | |||
verifyNoMoreInteractions(storage); | |||
} | |||
@Test | |||
public void testSaveLinesAndConditions() { | |||
SensorStorage storage = mock(SensorStorage.class); | |||
new DefaultCoverage(storage) | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.lineHits(1, 2) | |||
.lineHits(2, 5) | |||
.lineHits(3, 0) | |||
.lineHits(4, 0) | |||
.conditions(1, 2, 1) | |||
.save(); | |||
verify(storage).store(new DefaultMeasure<Integer>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.LINES_TO_COVER) | |||
.withValue(4)); | |||
verify(storage).store(new DefaultMeasure<Integer>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.UNCOVERED_LINES) | |||
.withValue(2)); | |||
verify(storage).store(new DefaultMeasure<String>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.COVERAGE_LINE_HITS_DATA) | |||
.withValue("1=2;2=5;3=0;4=0")); | |||
verify(storage).store(new DefaultMeasure<Integer>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.CONDITIONS_TO_COVER) | |||
.withValue(2)); | |||
verify(storage).store(new DefaultMeasure<Integer>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.UNCOVERED_CONDITIONS) | |||
.withValue(1)); | |||
verify(storage).store(new DefaultMeasure<String>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.COVERED_CONDITIONS_BY_LINE) | |||
.withValue("1=1")); | |||
verify(storage).store(new DefaultMeasure<String>() | |||
.onFile(main) | |||
.forMetric(CoreMetrics.CONDITIONS_BY_LINE) | |||
.withValue("1=2")); | |||
verifyNoMoreInteractions(storage); | |||
} | |||
@Test | |||
public void dontSaveTwice() { | |||
SensorStorage storage = mock(SensorStorage.class); | |||
DefaultCoverage coverage = new DefaultCoverage(storage) | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.lineHits(1, 2) | |||
.lineHits(2, 5) | |||
.lineHits(3, 0) | |||
.lineHits(4, 0); | |||
coverage.save(); | |||
thrown.expect(IllegalStateException.class); | |||
thrown.expectMessage("This object was already saved"); | |||
coverage.save(); | |||
} | |||
@Test | |||
public void fileIsMain() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Coverage is only supported on main files [test/FooTest.php]"); | |||
new DefaultCoverage() | |||
.onFile(new DefaultInputFile("foo", "test/FooTest.php").setType(InputFile.Type.TEST)) | |||
.ofType(CoverageType.UNIT); | |||
} | |||
@Test | |||
public void lineHitsValidation() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Line number should be positive and non zero [src/Foo.php:0]"); | |||
new DefaultCoverage() | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.lineHits(0, 2); | |||
} | |||
@Test | |||
public void hitsPositive() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Hits should be positive [src/Foo.php:1]"); | |||
new DefaultCoverage() | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.lineHits(1, -1); | |||
} | |||
@Test | |||
public void hitsNoDuplicate() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Hits already saved on line [src/Foo.php:1]"); | |||
new DefaultCoverage() | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.lineHits(1, 2) | |||
.lineHits(1, 1); | |||
} | |||
@Test | |||
public void lineConditionValidation() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Line number should be positive and non zero [src/Foo.php:0]"); | |||
new DefaultCoverage() | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.conditions(0, 2, 2); | |||
} | |||
@Test | |||
public void conditionsPositive() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Number of conditions should be positive [src/Foo.php:1]"); | |||
new DefaultCoverage() | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.conditions(1, -1, 0); | |||
} | |||
@Test | |||
public void coveredConditionsPositive() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Number of covered conditions should be positive [src/Foo.php:1]"); | |||
new DefaultCoverage() | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.conditions(1, 1, -1); | |||
} | |||
@Test | |||
public void coveredConditionsVsConditions() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Number of covered conditions can't exceed conditions [src/Foo.php:1]"); | |||
new DefaultCoverage() | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.conditions(1, 2, 3); | |||
} | |||
@Test | |||
public void conditionsNoDuplicate() { | |||
thrown.expect(IllegalArgumentException.class); | |||
thrown.expectMessage("Conditions already saved on line [src/Foo.php:1]"); | |||
new DefaultCoverage() | |||
.onFile(main) | |||
.ofType(CoverageType.UNIT) | |||
.conditions(1, 4, 3) | |||
.conditions(1, 4, 2); | |||
} | |||
} |
@@ -1,83 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.batch.sensor.test.internal; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import java.util.Arrays; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class DefaultTestCaseCoverageTest { | |||
@Rule | |||
public ExpectedException thrown = ExpectedException.none(); | |||
private InputFile mainFile = new DefaultInputFile("foo", "src/Foo.php").setType(InputFile.Type.MAIN); | |||
private InputFile testFile = new DefaultInputFile("foo", "test/FooTest.php").setType(InputFile.Type.TEST); | |||
@Test | |||
public void testCreation() throws Exception { | |||
DefaultTestCaseCoverage testCaseCoverage = new DefaultTestCaseCoverage() | |||
.testFile(testFile) | |||
.testName("myTest") | |||
.cover(mainFile) | |||
.onLines(Arrays.asList(1, 2, 3)); | |||
assertThat(testCaseCoverage.testName()).isEqualTo("myTest"); | |||
assertThat(testCaseCoverage.testFile()).isEqualTo(testFile); | |||
assertThat(testCaseCoverage.coveredFile()).isEqualTo(mainFile); | |||
assertThat(testCaseCoverage.coveredLines()).containsExactly(1, 2, 3); | |||
} | |||
@Test | |||
public void testEqualsHashCodeToString() { | |||
DefaultTestCaseCoverage testCaseCoverage1 = new DefaultTestCaseCoverage() | |||
.testFile(testFile) | |||
.testName("myTest") | |||
.cover(mainFile) | |||
.onLines(Arrays.asList(1, 2, 3)); | |||
DefaultTestCaseCoverage testCaseCoverage1a = new DefaultTestCaseCoverage() | |||
.testFile(testFile) | |||
.testName("myTest") | |||
.cover(mainFile) | |||
.onLines(Arrays.asList(1, 2, 3)); | |||
DefaultTestCaseCoverage testCaseCoverage2 = new DefaultTestCaseCoverage() | |||
.testFile(testFile) | |||
.testName("myTest2") | |||
.cover(mainFile) | |||
.onLines(Arrays.asList(1, 3, 3)); | |||
assertThat(testCaseCoverage1).isEqualTo(testCaseCoverage1); | |||
assertThat(testCaseCoverage1).isEqualTo(testCaseCoverage1a); | |||
assertThat(testCaseCoverage1).isNotEqualTo(testCaseCoverage2); | |||
assertThat(testCaseCoverage1).isNotEqualTo(null); | |||
assertThat(testCaseCoverage1).isNotEqualTo("foo"); | |||
assertThat(testCaseCoverage1.toString()) | |||
.isEqualTo( | |||
"DefaultTestCaseCoverage[testFile=[moduleKey=foo, relative=test/FooTest.php, basedir=null],mainFile=[moduleKey=foo, relative=src/Foo.php, basedir=null],name=myTest,lines=[1, 2, 3]]"); | |||
assertThat(testCaseCoverage1.hashCode()).isEqualTo(testCaseCoverage1a.hashCode()); | |||
} | |||
} |
@@ -1,123 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.batch.sensor.test.internal; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution.Status; | |||
import org.sonar.api.batch.sensor.test.TestCaseExecution.Type; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class DefaultTestCaseExecutionTest { | |||
@Rule | |||
public ExpectedException thrown = ExpectedException.none(); | |||
private InputFile parent = new DefaultInputFile("foo", "src/Foo.php").setType(InputFile.Type.TEST); | |||
@Test | |||
public void testCreation() throws Exception { | |||
DefaultTestCaseExecution testCase = new DefaultTestCaseExecution(null) | |||
.inTestFile(parent) | |||
.name("myTest") | |||
.durationInMs(1) | |||
.message("message") | |||
.stackTrace("stack") | |||
.status(Status.ERROR) | |||
.ofType(Type.UNIT); | |||
assertThat(testCase.name()).isEqualTo("myTest"); | |||
assertThat(testCase.testFile()).isEqualTo(parent); | |||
assertThat(testCase.durationInMs()).isEqualTo(1L); | |||
assertThat(testCase.message()).isEqualTo("message"); | |||
assertThat(testCase.stackTrace()).isEqualTo("stack"); | |||
assertThat(testCase.status()).isEqualTo(Status.ERROR); | |||
assertThat(testCase.type()).isEqualTo(Type.UNIT); | |||
} | |||
@Test | |||
public void testCreationWithDefaultValues() throws Exception { | |||
DefaultTestCaseExecution testCase = new DefaultTestCaseExecution(null) | |||
.inTestFile(parent) | |||
.name("myTest"); | |||
assertThat(testCase.name()).isEqualTo("myTest"); | |||
assertThat(testCase.testFile()).isEqualTo(parent); | |||
assertThat(testCase.durationInMs()).isNull(); | |||
assertThat(testCase.message()).isNull(); | |||
assertThat(testCase.stackTrace()).isNull(); | |||
assertThat(testCase.status()).isEqualTo(Status.OK); | |||
assertThat(testCase.type()).isEqualTo(Type.UNIT); | |||
} | |||
@Test | |||
public void testInvalidDuration() throws Exception { | |||
DefaultTestCaseExecution builder = new DefaultTestCaseExecution(null) | |||
.inTestFile(parent) | |||
.name("myTest"); | |||
thrown.expect(IllegalArgumentException.class); | |||
builder.durationInMs(-3); | |||
} | |||
@Test | |||
public void testEqualsHashCodeToString() { | |||
DefaultTestCaseExecution testCase1 = new DefaultTestCaseExecution(null) | |||
.inTestFile(parent) | |||
.name("myTest") | |||
.durationInMs(1) | |||
.message("message") | |||
.stackTrace("stack") | |||
.status(Status.ERROR) | |||
.ofType(Type.UNIT); | |||
DefaultTestCaseExecution testCase1a = new DefaultTestCaseExecution(null) | |||
.inTestFile(parent) | |||
.name("myTest") | |||
.durationInMs(1) | |||
.message("message") | |||
.stackTrace("stack") | |||
.status(Status.ERROR) | |||
.ofType(Type.UNIT); | |||
DefaultTestCaseExecution testCase2 = new DefaultTestCaseExecution(null) | |||
.inTestFile(new DefaultInputFile("foo2", "src/Foo.php").setType(InputFile.Type.TEST)) | |||
.name("myTest2") | |||
.durationInMs(2) | |||
.message("message2") | |||
.stackTrace("null") | |||
.status(Status.FAILURE) | |||
.ofType(Type.INTEGRATION); | |||
assertThat(testCase1).isEqualTo(testCase1); | |||
assertThat(testCase1).isEqualTo(testCase1a); | |||
assertThat(testCase1).isNotEqualTo(testCase2); | |||
assertThat(testCase1).isNotEqualTo(null); | |||
assertThat(testCase1).isNotEqualTo("foo"); | |||
assertThat(testCase1.toString()).isEqualTo( | |||
"DefaultTestCaseExecution[testFile=[moduleKey=foo, relative=src/Foo.php, basedir=null],name=myTest,duration=1,status=ERROR,message=message,type=UNIT,stackTrace=stack]"); | |||
assertThat(testCase1.hashCode()).isEqualTo(testCase1a.hashCode()); | |||
} | |||
} |