diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2014-09-05 14:03:30 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2014-09-05 14:04:10 +0200 |
commit | e1c3a706319c397b436a28b7921b695baf712063 (patch) | |
tree | 342c942f72b71c6f2843e71a893252f383342772 | |
parent | a967da0f1192287036132a5876be693485e94ae6 (diff) | |
download | sonarqube-e1c3a706319c397b436a28b7921b695baf712063.tar.gz sonarqube-e1c3a706319c397b436a28b7921b695baf712063.zip |
SONAR-5389 New test API for batch 2.0
72 files changed, 1544 insertions, 201 deletions
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java index 4f851f39cae..3044ef773ab 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java @@ -19,8 +19,6 @@ */ package org.sonar.plugins.core.sensors; -import com.google.common.base.Charsets; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import org.junit.Rule; import org.junit.Test; @@ -58,8 +56,8 @@ public class FileHashSensorTest { @Test public void store_file_hashes() throws Exception { when(fileCache.filesByModule("struts")).thenReturn(Lists.<InputFile>newArrayList( - new DeprecatedDefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"), - new DeprecatedDefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF"))); + new DeprecatedDefaultInputFile("foo", "src/Foo.java").setFile(temp.newFile()).setHash("ABC"), + new DeprecatedDefaultInputFile("foo", "src/Bar.java").setFile(temp.newFile()).setHash("DEF"))); SensorContext sensorContext = mock(SensorContext.class); sensor.analyse(project, sensorContext); @@ -72,8 +70,8 @@ public class FileHashSensorTest { public void store_file_hashes_for_branches() throws Exception { project = new Project("struts", "branch-2.x", "Struts 2.x"); when(fileCache.filesByModule("struts:branch-2.x")).thenReturn(Lists.<InputFile>newArrayList( - new DeprecatedDefaultInputFile("src/Foo.java").setFile(temp.newFile()).setHash("ABC"), - new DeprecatedDefaultInputFile("src/Bar.java").setFile(temp.newFile()).setHash("DEF"))); + new DeprecatedDefaultInputFile("foo", "src/Foo.java").setFile(temp.newFile()).setHash("ABC"), + new DeprecatedDefaultInputFile("foo", "src/Bar.java").setFile(temp.newFile()).setHash("DEF"))); SensorContext sensorContext = mock(SensorContext.class); sensor.analyse(project, sensorContext); diff --git a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/JavaCpdEngineTest.java b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/JavaCpdEngineTest.java index dcada895aab..f93e4484390 100644 --- a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/JavaCpdEngineTest.java +++ b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/JavaCpdEngineTest.java @@ -63,11 +63,10 @@ public class JavaCpdEngineTest { @Before public void before() throws IOException { when(context.measureBuilder()).thenReturn(new DefaultMeasureBuilder()); - inputFile = new DeprecatedDefaultInputFile("src/main/java/Foo.java"); + inputFile = new DeprecatedDefaultInputFile("foo", "src/main/java/Foo.java"); duplicationBuilder = spy(new DefaultDuplicationBuilder(inputFile)); when(context.duplicationBuilder(any(InputFile.class))).thenReturn(duplicationBuilder); inputFile.setFile(temp.newFile("Foo.java")); - inputFile.setKey("key1"); contextFactory = mock(FileLinesContextFactory.class); linesContext = mock(FileLinesContext.class); when(contextFactory.createFor(inputFile)).thenReturn(linesContext); @@ -135,7 +134,7 @@ public class JavaCpdEngineTest { inOrder.verify(duplicationBuilder).build(); verify(context).saveDuplications(inputFile, Arrays.asList( - new DuplicationGroup(new DuplicationGroup.Block("key1", 5, 200)) + new DuplicationGroup(new DuplicationGroup.Block("foo:src/main/java/Foo.java", 5, 200)) .addDuplicate(new DuplicationGroup.Block("key2", 15, 200)) .addDuplicate(new DuplicationGroup.Block("key3", 25, 200)) )); diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java index 3477fab825c..c7e43d9e0ab 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java @@ -20,10 +20,12 @@ package org.sonar.xoo; import org.sonar.api.SonarPlugin; +import org.sonar.xoo.lang.CoveragePerTestSensor; import org.sonar.xoo.lang.MeasureSensor; import org.sonar.xoo.lang.ScmActivitySensor; import org.sonar.xoo.lang.SymbolReferencesSensor; import org.sonar.xoo.lang.SyntaxHighlightingSensor; +import org.sonar.xoo.lang.TestCaseSensor; import org.sonar.xoo.lang.XooTokenizerSensor; import org.sonar.xoo.rule.CreateIssueByInternalKeySensor; import org.sonar.xoo.rule.OneIssueOnDirPerFileSensor; @@ -55,6 +57,8 @@ public class XooPlugin extends SonarPlugin { SyntaxHighlightingSensor.class, SymbolReferencesSensor.class, XooTokenizerSensor.class, + TestCaseSensor.class, + CoveragePerTestSensor.class, OneIssuePerLineSensor.class, OneIssueOnDirPerFileSensor.class, diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/CoveragePerTestSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/CoveragePerTestSensor.java new file mode 100644 index 00000000000..aee8297811e --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/CoveragePerTestSensor.java @@ -0,0 +1,110 @@ +/* + * 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.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.TestCase; +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 = LoggerFactory.getLogger(CoveragePerTestSensor.class); + + private static final String COVER_PER_TEST_EXTENSION = ".coveragePerTest"; + + private void processCoveragePerTest(InputFile inputFile, SensorContext context) { + File ioFile = inputFile.file(); + File testPlanFile = new File(ioFile.getParentFile(), ioFile.getName() + COVER_PER_TEST_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, context, line, inputFile); + } + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + } + + private void processLine(File testplanFile, 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)); + List<Integer> coveredLines = new ArrayList<Integer>(); + Iterator<String> lines = Splitter.on(",").split(split.next()).iterator(); + while (lines.hasNext()) { + coveredLines.add(Integer.parseInt(lines.next())); + } + TestCase testCase = context.getTestCase(testFile, testCaseName); + if (testCase == null) { + throw new IllegalStateException("No test case with name " + testCaseName + " on file " + testFile); + } + context.saveCoveragePerTest(testCase, mainFile, coveredLines); + } catch (Exception e) { + throw new IllegalStateException("Error processing line " + lineNumber + " of file " + testplanFile.getAbsolutePath(), e); + } + } + + @Override + public void describe(SensorDescriptor descriptor) { + descriptor + .name("Xoo Coverage Per Test Sensor") + .workOnLanguages(Xoo.KEY) + .workOnFileTypes(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); + } + } +} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java index c8232484a51..61131e8b87a 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java @@ -30,7 +30,6 @@ import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorDescriptor; import org.sonar.api.batch.sensor.symbol.Symbol; import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; -import org.sonar.api.measures.CoreMetrics; import org.sonar.xoo.Xoo; import java.io.File; @@ -88,7 +87,6 @@ public class SymbolReferencesSensor implements Sensor { public void describe(SensorDescriptor descriptor) { descriptor .name("Xoo Symbol Reference Sensor") - .provides(CoreMetrics.LINES) .workOnLanguages(Xoo.KEY) .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST); } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java index c9c9b886406..a930c9c8f4c 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java @@ -30,7 +30,6 @@ import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorDescriptor; import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder; import org.sonar.api.batch.sensor.highlighting.TypeOfText; -import org.sonar.api.measures.CoreMetrics; import org.sonar.xoo.Xoo; import java.io.File; @@ -86,7 +85,6 @@ public class SyntaxHighlightingSensor implements Sensor { public void describe(SensorDescriptor descriptor) { descriptor .name("Xoo Highlighting Sensor") - .provides(CoreMetrics.LINES) .workOnLanguages(Xoo.KEY) .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST); } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/TestCaseSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/TestCaseSensor.java new file mode 100644 index 00000000000..c4238b51e18 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/TestCaseSensor.java @@ -0,0 +1,108 @@ +/* + * 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.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.TestCase; +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 = LoggerFactory.getLogger(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(); + long duration = Long.parseLong(split.next()); + context.addTestCase(context.testCaseBuilder(testFile, name) + .type(TestCase.Type.valueOf(type)) + .status(TestCase.Status.valueOf(status)) + .message(message) + .stackTrace(stack) + .durationInMs(duration) + .build()); + } 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") + .workOnLanguages(Xoo.KEY) + .workOnFileTypes(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); + } + } +} diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java index bfe1fd99afa..96ea0ea923c 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java @@ -27,6 +27,6 @@ public class XooPluginTest { @Test public void provide_extensions() { - assertThat(new XooPlugin().getExtensions()).hasSize(11); + assertThat(new XooPlugin().getExtensions()).hasSize(13); } } diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java index c06d4f307d3..f12bee28275 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java @@ -72,7 +72,7 @@ public class MeasureSensorTest { @Test public void testNoExecutionIfNoMeasureFile() { - DefaultInputFile inputFile = new DefaultInputFile("src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); fileSystem.add(inputFile); sensor.execute(context); } @@ -81,7 +81,7 @@ public class MeasureSensorTest { public void testExecution() throws IOException { File measures = new File(baseDir, "src/foo.xoo.measures"); FileUtils.write(measures, "ncloc:12\nbranch_coverage:5.3\nsqale_index:300\nbool:true\ncomment_lines_data:1=1,2=1\n\n#comment"); - DefaultInputFile inputFile = new DefaultInputFile("src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); fileSystem.add(inputFile); Metric<Boolean> booleanMetric = new Metric.Builder("bool", "Bool", Metric.ValueType.BOOL) @@ -108,7 +108,7 @@ public class MeasureSensorTest { public void failIfMetricNotFound() throws IOException { File measures = new File(baseDir, "src/foo.xoo.measures"); FileUtils.write(measures, "unknow:12\n\n#comment"); - DefaultInputFile inputFile = new DefaultInputFile("src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); fileSystem.add(inputFile); when(context.measureBuilder()).thenReturn(new DefaultMeasureBuilder()); diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SymbolReferencesSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SymbolReferencesSensorTest.java index 68fd40d0f80..d5f6a30723e 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SymbolReferencesSensorTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SymbolReferencesSensorTest.java @@ -63,7 +63,7 @@ public class SymbolReferencesSensorTest { @Test public void testNoExecutionIfNoSymbolFile() { - DefaultInputFile inputFile = new DefaultInputFile("src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); fileSystem.add(inputFile); sensor.execute(context); } @@ -72,7 +72,7 @@ public class SymbolReferencesSensorTest { public void testExecution() throws IOException { File symbol = new File(baseDir, "src/foo.xoo.symbol"); FileUtils.write(symbol, "1,4,7\n12,15,23\n\n#comment"); - DefaultInputFile inputFile = new DefaultInputFile("src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); fileSystem.add(inputFile); SymbolTableBuilder symbolTableBuilder = mock(SymbolTableBuilder.class); when(context.symbolTableBuilder(inputFile)).thenReturn(symbolTableBuilder); diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java index 9918a3625ef..cad3b968113 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java @@ -63,7 +63,7 @@ public class SyntaxHighlightingSensorTest { @Test public void testNoExecutionIfNoSyntaxFile() { - DefaultInputFile inputFile = new DefaultInputFile("src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); fileSystem.add(inputFile); sensor.execute(context); } @@ -72,7 +72,7 @@ public class SyntaxHighlightingSensorTest { public void testExecution() throws IOException { File symbol = new File(baseDir, "src/foo.xoo.highlighting"); FileUtils.write(symbol, "1:4:k\n12:15:cppd\n\n#comment"); - DefaultInputFile inputFile = new DefaultInputFile("src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); fileSystem.add(inputFile); HighlightingBuilder builder = mock(HighlightingBuilder.class); when(context.highlightingBuilder(inputFile)).thenReturn(builder); diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/XooTokenizerSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/XooTokenizerSensorTest.java index 941798f9436..448d45cfcc5 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/XooTokenizerSensorTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/XooTokenizerSensorTest.java @@ -70,7 +70,7 @@ public class XooTokenizerSensorTest { @Test public void testNoExecutionIfExclusion() { - DefaultInputFile inputFile = new DefaultInputFile("src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); fileSystem.add(inputFile); settings.setProperty(CoreProperties.CPD_EXCLUSIONS, "**/foo.xoo"); sensor.execute(context); @@ -81,7 +81,7 @@ public class XooTokenizerSensorTest { public void testExecution() throws IOException { File source = new File(baseDir, "src/foo.xoo"); FileUtils.write(source, "token1 token2 token3\ntoken4"); - DefaultInputFile inputFile = new DefaultInputFile("src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setAbsolutePath(new File(baseDir, "src/foo.xoo").getAbsolutePath()).setLanguage("xoo"); fileSystem.add(inputFile); DuplicationTokenBuilder builder = mock(DuplicationTokenBuilder.class); when(context.duplicationTokenBuilder(inputFile)).thenReturn(builder); diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java index be3185f7b6d..403ec002b23 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java +++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java @@ -34,6 +34,7 @@ import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.issue.Issue; import org.sonar.api.batch.sensor.measure.Measure; import org.sonar.api.batch.sensor.symbol.Symbol; +import org.sonar.api.batch.sensor.test.TestCase; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; import org.sonar.api.platform.PluginMetadata; @@ -57,6 +58,8 @@ import org.sonar.batch.scan2.AnalyzerMeasureCache; import org.sonar.batch.scan2.ProjectScanContainer; import org.sonar.batch.scan2.ScanTaskObserver; import org.sonar.batch.symbol.SymbolData; +import org.sonar.batch.test.CoveragePerTestCache; +import org.sonar.batch.test.TestCaseCache; import org.sonar.core.plugins.DefaultPluginMetadata; import org.sonar.core.plugins.RemotePlugin; import org.sonar.core.source.SnapshotDataTypes; @@ -66,6 +69,7 @@ import javax.annotation.CheckForNull; import java.io.File; import java.io.FileReader; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; @@ -226,6 +230,8 @@ public class BatchMediumTester { private List<InputDir> inputDirs = new ArrayList<InputDir>(); private Map<InputFile, SyntaxHighlightingData> highlightingPerFile = new HashMap<InputFile, SyntaxHighlightingData>(); private Map<InputFile, SymbolData> symbolTablePerFile = new HashMap<InputFile, SymbolData>(); + private Map<String, Map<String, TestCase>> testCasesPerFile = new HashMap<String, Map<String, TestCase>>(); + private Map<String, Map<String, Map<String, List<Integer>>>> coveragePerTest = new HashMap<String, Map<String, Map<String, List<Integer>>>>(); @Override public void scanTaskCompleted(ProjectScanContainer container) { @@ -265,6 +271,27 @@ public class BatchMediumTester { duplications.put(effectiveKey, entry.value()); } + TestCaseCache testCaseCache = container.getComponentByType(TestCaseCache.class); + for (Entry<TestCase> entry : testCaseCache.entries()) { + String effectiveKey = entry.key()[0].toString(); + if (!testCasesPerFile.containsKey(effectiveKey)) { + testCasesPerFile.put(effectiveKey, new HashMap<String, TestCase>()); + } + testCasesPerFile.get(effectiveKey).put(entry.value().name(), entry.value()); + } + + CoveragePerTestCache coveragePerTestCache = container.getComponentByType(CoveragePerTestCache.class); + for (Entry<List<Integer>> entry : coveragePerTestCache.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>>()); + } + coveragePerTest.get(testFileKey).get(testName).put(entry.key()[2].toString(), entry.value()); + } } public List<Issue> issues() { @@ -287,6 +314,29 @@ public class BatchMediumTester { return duplications.get(((DefaultInputFile) inputFile).key()); } + public Collection<TestCase> testCasesFor(InputFile inputFile) { + String key = ((DefaultInputFile) inputFile).key(); + if (testCasesPerFile.containsKey(key)) { + return testCasesPerFile.get(key).values(); + } else { + return Collections.emptyList(); + } + } + + public TestCase 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 diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java index 545c480381a..37fe0b134bf 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java @@ -19,16 +19,20 @@ */ package org.sonar.batch.scan; +import com.google.common.base.Preconditions; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputDir; import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputFile.Type; import org.sonar.api.batch.fs.InputPath; import org.sonar.api.batch.measure.Metric; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.issue.Issue; import org.sonar.api.batch.sensor.measure.Measure; +import org.sonar.api.batch.sensor.test.TestCase; +import org.sonar.api.batch.sensor.test.internal.DefaultTestCase; import org.sonar.api.component.ResourcePerspectives; import org.sonar.api.config.Settings; import org.sonar.api.issue.Issuable; @@ -40,15 +44,21 @@ import org.sonar.api.measures.SumChildDistributionFormula; import org.sonar.api.resources.Directory; import org.sonar.api.resources.File; import org.sonar.api.resources.Project; +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.BlockCache; import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.index.ComponentDataCache; import org.sonar.batch.scan2.BaseSensorContext; import java.io.Serializable; +import java.util.List; /** * Implements {@link SensorContext} but forward everything to {@link org.sonar.api.batch.SensorContext} for backward compatibility. @@ -209,4 +219,71 @@ public class SensorContextAdaptor extends BaseSensorContext { .build(); } + @Override + public void addTestCase(TestCase testCase) { + File testRes = getTestResource(((DefaultTestCase) testCase).testFile()); + MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes); + 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 TestCase getTestCase(InputFile testFile, String testCaseName) { + File testRes = getTestResource(testFile); + MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes); + Iterable<MutableTestCase> testCases = testPlan.testCasesByName(testCaseName); + if (testCases.iterator().hasNext()) { + MutableTestCase testCase = testCases.iterator().next(); + return new DefaultTestCase(testFile, testCaseName, testCase.durationInMs(), TestCase.Status.of(testCase.status().name()), testCase.message(), TestCase.Type.valueOf(testCase + .type()), testCase.stackTrace()); + } + return null; + } + + @Override + public void saveCoveragePerTest(TestCase testCase, InputFile coveredFile, List<Integer> coveredLines) { + Preconditions.checkArgument(coveredFile.type() == Type.MAIN, "Should be a main file: " + coveredFile); + File testRes = getTestResource(((DefaultTestCase) testCase).testFile()); + File mainRes = getMainResource(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(testCase.name())) { + mutableTestCase.setCoverageBlock(testAbleFile, 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); + // Reload + testRes = sensorContext.getResource(testRes); + if (testRes == null) { + throw new IllegalArgumentException("Provided input file is not indexed or not a test file: " + testFile); + } + return testRes; + } + + private File getMainResource(InputFile mainFile) { + File mainRes = File.create(mainFile.relativePath()); + // Reload + mainRes = sensorContext.getResource(mainRes); + if (mainRes == null) { + throw new IllegalArgumentException("Provided input file is not indexed or not a main file: " + mainRes); + } + return mainRes; + } + } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultInputFileValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultInputFileValueCoder.java index 6dcfc9903b1..42398a58edc 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultInputFileValueCoder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultInputFileValueCoder.java @@ -34,6 +34,7 @@ class DefaultInputFileValueCoder implements ValueCoder { @Override public void put(Value value, Object object, CoderContext context) { DeprecatedDefaultInputFile f = (DeprecatedDefaultInputFile) object; + putUTFOrNull(value, f.moduleKey()); putUTFOrNull(value, f.relativePath()); value.putString(f.getFileBaseDir().toString()); putUTFOrNull(value, f.deprecatedKey()); @@ -45,7 +46,6 @@ class DefaultInputFileValueCoder implements ValueCoder { value.putString(f.status().name()); putUTFOrNull(value, f.hash()); value.put(f.lines()); - putUTFOrNull(value, f.key()); } private void putUTFOrNull(Value value, @Nullable String utfOrNull) { @@ -58,7 +58,8 @@ class DefaultInputFileValueCoder implements ValueCoder { @Override public Object get(Value value, Class clazz, CoderContext context) { - DeprecatedDefaultInputFile file = new DeprecatedDefaultInputFile(value.getString()); + String moduleKey = value.getString(); + DeprecatedDefaultInputFile file = new DeprecatedDefaultInputFile(moduleKey, value.getString()); file.setBasedir(new File(value.getString())); file.setDeprecatedKey(value.getString()); file.setSourceDirAbsolutePath(value.getString()); @@ -69,7 +70,6 @@ class DefaultInputFileValueCoder implements ValueCoder { file.setStatus(InputFile.Status.valueOf(value.getString())); file.setHash(value.getString()); file.setLines(value.getInt()); - file.setKey(value.getString()); return file; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java index 030febcd78d..f83cf29d5ef 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java @@ -171,9 +171,8 @@ public class FileIndexer implements BatchComponent { File parentDir = inputFile.file().getParentFile(); String relativePath = new PathResolver().relativePath(fs.baseDir(), parentDir); if (relativePath != null) { - DefaultInputDir inputDir = new DefaultInputDir(relativePath); + DefaultInputDir inputDir = new DefaultInputDir(fs.moduleKey(), relativePath); inputDir.setFile(parentDir); - inputDir.setKey(new StringBuilder().append(fs.moduleKey()).append(":").append(inputDir.relativePath()).toString()); status.markAsIndexed(inputDir); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java index cd7844fd4de..4e8ed7eedc9 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java @@ -82,7 +82,7 @@ class InputFileBuilder { LOG.warn("File '{}' is ignored. It is not located in module basedir '{}'.", file.getAbsolutePath(), fs.baseDir()); return null; } - DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile(relativePath); + DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile(moduleKey, relativePath); inputFile.setBasedir(fs.baseDir()); inputFile.setFile(file); return inputFile; @@ -94,7 +94,6 @@ class InputFileBuilder { @CheckForNull DeprecatedDefaultInputFile complete(DeprecatedDefaultInputFile inputFile, InputFile.Type type) { inputFile.setType(type); - inputFile.setKey(new StringBuilder().append(moduleKey).append(":").append(inputFile.relativePath()).toString()); inputFile.setBasedir(fs.baseDir()); FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(inputFile.file(), fs.encoding()); inputFile.setLines(metadata.lines); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java index 801744de2c7..df2950a554a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java @@ -26,6 +26,7 @@ import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; 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; /** * Cache of all measures. This cache is shared amongst all project modules. @@ -35,8 +36,8 @@ public class AnalyzerMeasureCache implements BatchComponent { // project key -> component key -> metric key -> measure private final Cache<DefaultMeasure> cache; - public AnalyzerMeasureCache(Caches caches, MetricFinder metricFinder) { - caches.registerValueCoder(DefaultMeasure.class, new DefaultMeasureValueCoder(metricFinder)); + public AnalyzerMeasureCache(Caches caches, MetricFinder metricFinder, InputPathCache inputPathCache) { + caches.registerValueCoder(DefaultMeasure.class, new DefaultMeasureValueCoder(metricFinder, inputPathCache)); cache = caches.createCache("measures"); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java index 1246d4ea630..48a74cccd81 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java @@ -35,6 +35,8 @@ import org.sonar.api.batch.sensor.issue.internal.DefaultIssueBuilder; import org.sonar.api.batch.sensor.measure.MeasureBuilder; import org.sonar.api.batch.sensor.measure.internal.DefaultMeasureBuilder; import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; +import org.sonar.api.batch.sensor.test.TestCaseBuilder; +import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseBuilder; import org.sonar.api.config.Settings; import org.sonar.batch.duplication.BlockCache; import org.sonar.batch.duplication.DefaultTokenBuilder; @@ -147,4 +149,9 @@ public abstract class BaseSensorContext implements SensorContext { } } + @Override + public TestCaseBuilder testCaseBuilder(InputFile testFile, String testCaseName) { + return new DefaultTestCaseBuilder(testFile, testCaseName); + } + } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultMeasureValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultMeasureValueCoder.java index 8b82a684dd0..0a1ee14339e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultMeasureValueCoder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultMeasureValueCoder.java @@ -23,25 +23,35 @@ 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.measure.Metric; import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; import org.sonar.api.batch.sensor.measure.internal.DefaultMeasureBuilder; +import org.sonar.batch.scan.filesystem.InputPathCache; import java.io.Serializable; class DefaultMeasureValueCoder implements ValueCoder { - private MetricFinder metricFinder; + private final MetricFinder metricFinder; + private final InputPathCache inputPathCache; - public DefaultMeasureValueCoder(MetricFinder metricFinder) { + public DefaultMeasureValueCoder(MetricFinder metricFinder, InputPathCache inputPathCache) { this.metricFinder = metricFinder; + this.inputPathCache = inputPathCache; } @Override public void put(Value value, Object object, CoderContext context) { DefaultMeasure m = (DefaultMeasure) object; - value.put(m.inputFile()); + DefaultInputFile inputFile = (DefaultInputFile) m.inputFile(); + if (inputFile != null) { + value.putString(inputFile.moduleKey()); + value.putString(inputFile.relativePath()); + } else { + value.putNull(); + } value.putUTF(m.metric().key()); value.put(m.value()); } @@ -49,8 +59,10 @@ class DefaultMeasureValueCoder implements ValueCoder { @Override public Object get(Value value, Class clazz, CoderContext context) { DefaultMeasureBuilder builder = new DefaultMeasureBuilder(); - InputFile f = (InputFile) value.get(); - if (f != null) { + String moduleKey = value.getString(); + if (moduleKey != null) { + String relativePath = value.getString(); + InputFile f = inputPathCache.getFile(moduleKey, relativePath); builder.onFile(f); } else { builder.onProject(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java index 2df3de1b0e5..e995b805490 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java @@ -19,10 +19,12 @@ */ package org.sonar.batch.scan2; +import com.google.common.base.Preconditions; import com.google.common.base.Strings; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputFile.Type; import org.sonar.api.batch.measure.Metric; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.DefaultActiveRule; @@ -30,6 +32,8 @@ import org.sonar.api.batch.sensor.issue.Issue; import org.sonar.api.batch.sensor.issue.internal.DefaultIssue; import org.sonar.api.batch.sensor.measure.Measure; import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; +import org.sonar.api.batch.sensor.test.TestCase; +import org.sonar.api.batch.sensor.test.internal.DefaultTestCase; import org.sonar.api.config.Settings; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.MessageException; @@ -38,9 +42,12 @@ import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.index.ComponentDataCache; import org.sonar.batch.issue.IssueFilters; import org.sonar.batch.scan.SensorContextAdaptor; +import org.sonar.batch.test.CoveragePerTestCache; +import org.sonar.batch.test.TestCaseCache; import org.sonar.core.component.ComponentKeys; import java.io.Serializable; +import java.util.List; public class DefaultSensorContext extends BaseSensorContext { @@ -49,16 +56,20 @@ public class DefaultSensorContext extends BaseSensorContext { private final ProjectDefinition def; private final ActiveRules activeRules; private final IssueFilters issueFilters; + private final TestCaseCache testCaseCache; + private final CoveragePerTestCache coveragePerTestCache; public DefaultSensorContext(ProjectDefinition def, AnalyzerMeasureCache measureCache, AnalyzerIssueCache issueCache, Settings settings, FileSystem fs, ActiveRules activeRules, IssueFilters issueFilters, ComponentDataCache componentDataCache, - BlockCache blockCache, DuplicationCache duplicationCache) { + BlockCache blockCache, DuplicationCache duplicationCache, TestCaseCache testCaseCache, CoveragePerTestCache coveragePerTestCache) { super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache); this.def = def; this.measureCache = measureCache; this.issueCache = issueCache; this.activeRules = activeRules; this.issueFilters = issueFilters; + this.testCaseCache = testCaseCache; + this.coveragePerTestCache = coveragePerTestCache; } @Override @@ -129,4 +140,24 @@ public class DefaultSensorContext extends BaseSensorContext { } } + @Override + public void addTestCase(TestCase testCase) { + if (testCaseCache.contains(((DefaultTestCase) testCase).testFile(), testCase.name())) { + throw new IllegalArgumentException("There is already a test case with the same name: " + testCase.name()); + } + testCaseCache.put(((DefaultTestCase) testCase).testFile(), testCase); + } + + @Override + public TestCase getTestCase(InputFile testFile, String testCaseName) { + return testCaseCache.get(testFile, testCaseName); + } + + @Override + public void saveCoveragePerTest(TestCase testCase, InputFile coveredFile, List<Integer> coveredLines) { + Preconditions.checkNotNull(testCase); + Preconditions.checkArgument(coveredFile.type() == Type.MAIN, "Should be a main file: " + coveredFile); + coveragePerTestCache.put(testCase, coveredFile, coveredLines); + } + } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java index b0a2b3e0af5..5922b613ffb 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java @@ -47,6 +47,8 @@ import org.sonar.batch.scan.ProjectSettings; import org.sonar.batch.scan.filesystem.InputPathCache; import org.sonar.batch.scan.maven.FakeMavenPluginExecutor; import org.sonar.batch.scan.maven.MavenPluginExecutor; +import org.sonar.batch.test.CoveragePerTestCache; +import org.sonar.batch.test.TestCaseCache; public class ProjectScanContainer extends ComponentContainer { public ProjectScanContainer(ComponentContainer taskContainer) { @@ -107,12 +109,17 @@ public class ProjectScanContainer extends ComponentContainer { // issues AnalyzerIssueCache.class, + // Syntax highlighting and symbols ComponentDataCache.class, // Duplications BlockCache.class, DuplicationCache.class, + // Tests + TestCaseCache.class, + CoveragePerTestCache.class, + ScanTaskObservers.class); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/test/CoveragePerTestCache.java b/sonar-batch/src/main/java/org/sonar/batch/test/CoveragePerTestCache.java new file mode 100644 index 00000000000..211cfb4ca88 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/test/CoveragePerTestCache.java @@ -0,0 +1,66 @@ +/* + * 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.TestCase; +import org.sonar.api.batch.sensor.test.internal.DefaultTestCase; +import org.sonar.batch.index.Cache; +import org.sonar.batch.index.Cache.Entry; +import org.sonar.batch.index.Caches; + +import javax.annotation.CheckForNull; + +import java.util.List; + +/** + * Cache of coverage per test. This cache is shared amongst all project modules. + */ +public class CoveragePerTestCache implements BatchComponent { + + private final Cache<List<Integer>> cache; + + public CoveragePerTestCache(Caches caches) { + cache = caches.createCache("coveragePerTest"); + } + + public Iterable<Entry<List<Integer>>> entries() { + return cache.entries(); + } + + @CheckForNull + public List<Integer> getCoveredLines(InputFile testFile, String testCaseName, InputFile mainFile) { + Preconditions.checkNotNull(testFile); + Preconditions.checkNotNull(testCaseName); + return cache.get(((DefaultInputFile) testFile).key(), testCaseName, ((DefaultInputFile) mainFile).key()); + } + + public CoveragePerTestCache put(TestCase testCase, InputFile mainFile, List<Integer> coveredLines) { + Preconditions.checkNotNull(testCase); + Preconditions.checkNotNull(mainFile); + Preconditions.checkNotNull(coveredLines); + cache.put(((DefaultInputFile) ((DefaultTestCase) testCase).testFile()).key(), testCase.name(), ((DefaultInputFile) mainFile).key(), coveredLines); + return this; + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/test/DefaultTestCaseValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/test/DefaultTestCaseValueCoder.java new file mode 100644 index 00000000000..7cb4b365249 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/test/DefaultTestCaseValueCoder.java @@ -0,0 +1,77 @@ +/* + * 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.TestCase; +import org.sonar.api.batch.sensor.test.internal.DefaultTestCase; +import org.sonar.batch.scan.filesystem.InputPathCache; + +import javax.annotation.Nullable; + +class DefaultTestCaseValueCoder implements ValueCoder { + + private InputPathCache inputPathCache; + + public DefaultTestCaseValueCoder(InputPathCache inputPathCache) { + this.inputPathCache = inputPathCache; + } + + public void put(Value value, Object object, CoderContext context) { + DefaultTestCase t = (DefaultTestCase) 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(); + } + } + + 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(); + TestCase.Type type = TestCase.Type.values()[value.getInt()]; + TestCase.Status status = TestCase.Status.values()[value.getInt()]; + return new DefaultTestCase(testFile, name, duration != -1 ? duration : null, status, message, type, stack); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/test/TestCaseCache.java b/sonar-batch/src/main/java/org/sonar/batch/test/TestCaseCache.java new file mode 100644 index 00000000000..e2de947e544 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/test/TestCaseCache.java @@ -0,0 +1,69 @@ +/* + * 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.TestCase; +import org.sonar.api.batch.sensor.test.internal.DefaultTestCase; +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 TestCaseCache implements BatchComponent { + + private final Cache<TestCase> cache; + + public TestCaseCache(Caches caches, InputPathCache inputPathCache) { + caches.registerValueCoder(DefaultTestCase.class, new DefaultTestCaseValueCoder(inputPathCache)); + cache = caches.createCache("testCases"); + } + + public Iterable<Entry<TestCase>> entries() { + return cache.entries(); + } + + @CheckForNull + public TestCase get(InputFile testFile, String testCaseName) { + Preconditions.checkNotNull(testFile); + Preconditions.checkNotNull(testCaseName); + return cache.get(((DefaultInputFile) testFile).key(), testCaseName); + } + + public TestCaseCache put(InputFile testFile, TestCase 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); + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/test/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/test/package-info.java new file mode 100644 index 00000000000..227ae02188b --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/test/package-info.java @@ -0,0 +1,27 @@ +/* + * 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. + */ +/** + * + */ +/** + * @author julien + * + */ +package org.sonar.batch.test;
\ No newline at end of file diff --git a/sonar-batch/src/test/java/org/sonar/batch/debt/SqaleRatingDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/debt/SqaleRatingDecoratorTest.java index 1b1840a8443..9948ee5b3c4 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/debt/SqaleRatingDecoratorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/debt/SqaleRatingDecoratorTest.java @@ -44,7 +44,10 @@ import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class SqaleRatingDecoratorTest { @@ -71,7 +74,7 @@ public class SqaleRatingDecoratorTest { settings = new Settings(); fs = new DefaultFileSystem(); - fs.add(new DefaultInputFile(file.getPath()) + fs.add(new DefaultInputFile("foo", file.getPath()) .setLanguage("java") .setFile(temp.newFile("Foo.java"))); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java index 3d8d7540787..d3710e64488 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java @@ -85,12 +85,10 @@ public class ResourceKeyMigrationTest extends AbstractDbUnitTestCase { private DefaultInputFile newInputFile(Project module, String path, String deprecatedKey, boolean isTest) { File file = new File(baseDir, path); - String effectiveKey = module.getKey() + ":" + path; String deprecatedEffectiveKey = module.getKey() + ":" + deprecatedKey; - return new DeprecatedDefaultInputFile(path) + return new DeprecatedDefaultInputFile(module.getKey(), path) .setDeprecatedKey(deprecatedEffectiveKey) .setFile(file) - .setKey(effectiveKey) .setType(isTest ? InputFile.Type.TEST : InputFile.Type.MAIN); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java index 5b97df2c7f5..c75f69fcb24 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java @@ -40,7 +40,10 @@ import java.io.IOException; import static com.google.common.base.Charsets.UTF_8; import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; public class IssueExclusionsLoaderTest { @@ -101,15 +104,13 @@ public class IssueExclusionsLoaderTest { @Test public void shouldAnalyzeProject() throws IOException { File javaFile1 = new File(baseDir, "src/main/java/Foo.java"); - fs.add(new DeprecatedDefaultInputFile("src/main/java/Foo.java") + fs.add(new DeprecatedDefaultInputFile("polop", "src/main/java/Foo.java") .setFile(javaFile1) - .setType(InputFile.Type.MAIN) - .setKey("polop:src/main/java/Foo.java")); + .setType(InputFile.Type.MAIN)); File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java"); - fs.add(new DeprecatedDefaultInputFile("src/test/java/FooTest.java") + fs.add(new DeprecatedDefaultInputFile("polop", "src/test/java/FooTest.java") .setFile(javaTestFile1) - .setType(InputFile.Type.TEST) - .setKey("polop:src/test/java/FooTest.java")); + .setType(InputFile.Type.TEST)); when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true); @@ -126,15 +127,13 @@ public class IssueExclusionsLoaderTest { @Test public void shouldAnalyseFilesOnlyWhenRegexConfigured() throws IOException { File javaFile1 = new File(baseDir, "src/main/java/Foo.java"); - fs.add(new DeprecatedDefaultInputFile("src/main/java/Foo.java") + fs.add(new DeprecatedDefaultInputFile("polop", "src/main/java/Foo.java") .setFile(javaFile1) - .setType(InputFile.Type.MAIN) - .setKey("polop:src/main/java/Foo.java")); + .setType(InputFile.Type.MAIN)); File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java"); - fs.add(new DeprecatedDefaultInputFile("src/test/java/FooTest.java") + fs.add(new DeprecatedDefaultInputFile("polop", "src/test/java/FooTest.java") .setFile(javaTestFile1) - .setType(InputFile.Type.TEST) - .setKey("polop:src/test/java/FooTest.java")); + .setType(InputFile.Type.TEST)); when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(false); scanner.execute(); @@ -149,10 +148,9 @@ public class IssueExclusionsLoaderTest { @Test public void shouldReportFailure() throws IOException { File phpFile1 = new File(baseDir, "src/Foo.php"); - fs.add(new DeprecatedDefaultInputFile("src/Foo.php") + fs.add(new DeprecatedDefaultInputFile("polop", "src/Foo.php") .setFile(phpFile1) - .setType(InputFile.Type.MAIN) - .setKey("polop:src/Foo.php")); + .setType(InputFile.Type.MAIN)); when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true); doThrow(new IOException("BUG")).when(regexpScanner).scan("polop:src/Foo.php", phpFile1, UTF_8); diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java index f3eebf971e3..df958e1ebfb 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java @@ -137,7 +137,7 @@ public class IssuesMediumTest { for (Issue issue : result.issues()) { if (issue.line() == 1) { foundIssueAtLine1 = true; - assertThat(issue.inputPath()).isEqualTo(new DefaultInputFile("src/sample.xoo")); + assertThat(issue.inputPath()).isEqualTo(new DefaultInputFile("com.foo.project", "src/sample.xoo")); assertThat(issue.message()).isEqualTo("This issue is generated on each line"); assertThat(issue.effortToFix()).isNull(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java index fb3e8d16edd..b75a46346a1 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java @@ -84,7 +84,7 @@ public class IssuesOnDirMediumTest { .start(); assertThat(result.issues()).hasSize(2); - assertThat(result.issues().iterator().next().inputPath()).isEqualTo(new DefaultInputDir("src")); + assertThat(result.issues().iterator().next().inputPath()).isEqualTo(new DefaultInputDir("com.foo.project", "src")); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java index 146b89eb316..3fb836a9095 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java @@ -97,7 +97,7 @@ public class MeasuresMediumTest { assertThat(result.measures()).contains(new DefaultMeasureBuilder<Integer>() .forMetric(CoreMetrics.LINES) - .onFile(new DefaultInputFile("src/sample.xoo")) + .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo")) .withValue(20) .build()); @@ -140,13 +140,13 @@ public class MeasuresMediumTest { assertThat(result.measures()).contains(new DefaultMeasureBuilder<Integer>() .forMetric(CoreMetrics.LINES) - .onFile(new DefaultInputFile("src/sample.xoo")) + .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo")) .withValue(5) .build()); assertThat(result.measures()).contains(new DefaultMeasureBuilder<String>() .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE) - .onFile(new DefaultInputFile("src/sample.xoo")) + .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo")) .withValue("1=julien;2=julien;3=julien;4=julien;5=simon") .build()); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/test/TestMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/test/TestMediumTest.java new file mode 100644 index 00000000000..1261ef7166d --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/test/TestMediumTest.java @@ -0,0 +1,130 @@ +/* + * 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.api.batch.fs.internal.DefaultInputFile; +import org.sonar.batch.mediumtest.BatchMediumTester; +import org.sonar.batch.mediumtest.BatchMediumTester.TaskResult; +import org.sonar.xoo.XooPlugin; + +import java.io.File; +import java.io.IOException; + +import static org.fest.assertions.Assertions.assertThat; + +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") + .bootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor")) + .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:::3\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); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java index a93bf9bae83..addf1f8bb0c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java @@ -107,7 +107,7 @@ public class SensorContextAdapterTest { @Test public void shouldRedirectFileMeasuresToSensorContext() { - InputFile file = new DefaultInputFile("src/Foo.php"); + InputFile file = new DefaultInputFile("foo", "src/Foo.php"); Measure<Integer> measure = adaptor.getMeasure(file, CoreMetrics.NCLOC_KEY); assertThat(measure).isNull(); @@ -122,7 +122,7 @@ public class SensorContextAdapterTest { @Test public void shouldAddMeasureToSensorContext() { - InputFile file = new DefaultInputFile("src/Foo.php"); + InputFile file = new DefaultInputFile("foo", "src/Foo.php"); ArgumentCaptor<org.sonar.api.measures.Measure> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class); when(sensorContext.saveMeasure(eq(file), argumentCaptor.capture())).thenReturn(null); @@ -140,7 +140,7 @@ public class SensorContextAdapterTest { @Test public void shouldAddIssue() { - InputFile file = new DefaultInputFile("src/Foo.php"); + InputFile file = new DefaultInputFile("foo", "src/Foo.php"); ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java index 0bb4b243226..a5f57f5c4c8 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java @@ -39,10 +39,10 @@ public class AdditionalFilePredicatesTest { public void key() throws Exception { FilePredicate predicate = new AdditionalFilePredicates.KeyPredicate("struts:Action.java"); - DefaultInputFile inputFile = new DeprecatedDefaultInputFile("Action.java").setKey("struts:Action.java"); + DefaultInputFile inputFile = new DeprecatedDefaultInputFile("struts", "Action.java"); assertThat(predicate.apply(inputFile)).isTrue(); - inputFile = new DeprecatedDefaultInputFile("Filter.java").setKey("struts:Filter.java"); + inputFile = new DeprecatedDefaultInputFile("struts", "Filter.java"); assertThat(predicate.apply(inputFile)).isFalse(); } @@ -50,10 +50,10 @@ public class AdditionalFilePredicatesTest { public void deprecated_key() throws Exception { FilePredicate predicate = new AdditionalFilePredicates.DeprecatedKeyPredicate("struts:Action.java"); - DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("Action.java").setDeprecatedKey("struts:Action.java"); + DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("struts", "Action.java").setDeprecatedKey("struts:Action.java"); assertThat(predicate.apply(inputFile)).isTrue(); - inputFile = new DeprecatedDefaultInputFile("Filter.java").setDeprecatedKey("struts:Filter.java"); + inputFile = new DeprecatedDefaultInputFile("struts", "Filter.java").setDeprecatedKey("struts:Filter.java"); assertThat(predicate.apply(inputFile)).isFalse(); } @@ -62,10 +62,10 @@ public class AdditionalFilePredicatesTest { File dir = temp.newFolder(); FilePredicate predicate = new AdditionalFilePredicates.SourceDirPredicate(dir.getAbsolutePath()); - DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("Action.java").setSourceDirAbsolutePath(dir.getAbsolutePath()); + DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("struts", "Action.java").setSourceDirAbsolutePath(dir.getAbsolutePath()); assertThat(predicate.apply(inputFile)).isTrue(); - inputFile = new DeprecatedDefaultInputFile("Filter.java").setSourceDirAbsolutePath(temp.newFolder().getAbsolutePath()); + inputFile = new DeprecatedDefaultInputFile("struts", "Filter.java").setSourceDirAbsolutePath(temp.newFolder().getAbsolutePath()); assertThat(predicate.apply(inputFile)).isFalse(); } @@ -73,10 +73,10 @@ public class AdditionalFilePredicatesTest { public void path_relative_to_source_dir() throws Exception { FilePredicate predicate = new AdditionalFilePredicates.SourceRelativePathPredicate("foo/Bar.php"); - DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("src/php/foo/Bar.php").setPathRelativeToSourceDir("foo/Bar.php"); + DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("foo", "src/php/foo/Bar.php").setPathRelativeToSourceDir("foo/Bar.php"); assertThat(predicate.apply(inputFile)).isTrue(); - inputFile = new DeprecatedDefaultInputFile("foo/Bar.php").setPathRelativeToSourceDir("Bar.php"); + inputFile = new DeprecatedDefaultInputFile("foo", "foo/Bar.php").setPathRelativeToSourceDir("Bar.php"); assertThat(predicate.apply(inputFile)).isFalse(); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java index 122b9c618de..8e90b2b3c68 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java @@ -161,7 +161,7 @@ public class ComponentIndexerTest { File javaFile1 = new File(baseDir, "src/main/java/foo/bar/Foo.java"); FileUtils.write(javaFile1, "\uFEFFpublic class Test", Charsets.UTF_8); - fs.add(new DeprecatedDefaultInputFile("src/main/java/foo/bar/Foo.java") + fs.add(new DeprecatedDefaultInputFile("foo", "src/main/java/foo/bar/Foo.java") .setPathRelativeToSourceDir("foo/bar/Foo.java") .setFile(javaFile1) .setLanguage("java")); @@ -186,7 +186,7 @@ public class ComponentIndexerTest { File javaFile1 = new File(baseDir, "src/main/java/foo/bar/Foo.java"); FileUtils.copyFile(getFile(testFile), javaFile1); - fs.add(new DeprecatedDefaultInputFile("src/main/java/foo/bar/Foo.java") + fs.add(new DeprecatedDefaultInputFile("foo", "src/main/java/foo/bar/Foo.java") .setPathRelativeToSourceDir("foo/bar/Foo.java") .setFile(javaFile1) .setLanguage("java")); @@ -212,7 +212,7 @@ public class ComponentIndexerTest { private DefaultInputFile newInputFile(String path, String content, String sourceRelativePath, String languageKey, boolean unitTest) throws IOException { File file = new File(baseDir, path); FileUtils.write(file, content); - return new DeprecatedDefaultInputFile(path) + return new DeprecatedDefaultInputFile("foo", path) .setPathRelativeToSourceDir(sourceRelativePath) .setFile(file) .setLanguage(languageKey) diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java index 4d87aed7cd3..b26bb8cc0e7 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java @@ -163,8 +163,8 @@ public class DefaultModuleFileSystemTest { new Project("foo"), settings, fileIndexer, initializer, componentIndexer); File mainFile = temp.newFile(); - InputFile mainInput = new DeprecatedDefaultInputFile("Main.java").setFile(mainFile).setType(InputFile.Type.MAIN); - InputFile testInput = new DeprecatedDefaultInputFile("Test.java").setFile(temp.newFile()).setType(InputFile.Type.TEST); + InputFile mainInput = new DeprecatedDefaultInputFile("foo", "Main.java").setFile(mainFile).setType(InputFile.Type.MAIN); + InputFile testInput = new DeprecatedDefaultInputFile("foo", "Test.java").setFile(temp.newFile()).setType(InputFile.Type.TEST); when(moduleInputFileCache.inputFiles()).thenReturn(Lists.newArrayList(mainInput, testInput)); fs.index(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java index 02f314e6b71..60cc12871d5 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java @@ -49,7 +49,7 @@ public class DeprecatedFileFiltersTest { public void no_filters() throws Exception { DeprecatedFileFilters filters = new DeprecatedFileFilters(); - InputFile inputFile = new DeprecatedDefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile()); + InputFile inputFile = new DeprecatedDefaultInputFile("foo", "src/main/java/Foo.java").setFile(temp.newFile()); assertThat(filters.accept(inputFile)).isTrue(); } @@ -59,7 +59,7 @@ public class DeprecatedFileFiltersTest { File basedir = temp.newFolder(); File file = temp.newFile(); - InputFile inputFile = new DeprecatedDefaultInputFile("src/main/java/Foo.java") + InputFile inputFile = new DeprecatedDefaultInputFile("foo", "src/main/java/Foo.java") .setSourceDirAbsolutePath(new File(basedir, "src/main/java").getAbsolutePath()) .setPathRelativeToSourceDir("Foo.java") .setFile(file) diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java index 6255bd6629b..8b864f2c491 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java @@ -43,7 +43,7 @@ public class ExclusionFiltersTest { filter.prepare(); java.io.File file = temp.newFile(); - DefaultInputFile inputFile = new DefaultInputFile("src/main/java/com/mycompany/FooDao.java").setFile(file); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/main/java/com/mycompany/FooDao.java").setFile(file); assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isTrue(); assertThat(filter.accept(inputFile, InputFile.Type.TEST)).isTrue(); } @@ -56,10 +56,10 @@ public class ExclusionFiltersTest { filter.prepare(); java.io.File file = temp.newFile(); - DefaultInputFile inputFile = new DefaultInputFile("src/main/java/com/mycompany/FooDao.java").setFile(file); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/main/java/com/mycompany/FooDao.java").setFile(file); assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isTrue(); - inputFile = new DefaultInputFile("src/main/java/com/mycompany/Foo.java").setFile(file); + inputFile = new DefaultInputFile("foo", "src/main/java/com/mycompany/Foo.java").setFile(file); assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isFalse(); } @@ -73,10 +73,10 @@ public class ExclusionFiltersTest { java.io.File file = temp.newFile(); - DefaultInputFile inputFile = new DefaultInputFile("src/main/java/com/mycompany/Foo.java").setFile(file); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/main/java/com/mycompany/Foo.java").setFile(file); assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isFalse(); - inputFile = new DefaultInputFile("src/main/java/com/mycompany/FooDto.java").setFile(file); + inputFile = new DefaultInputFile("foo", "src/main/java/com/mycompany/FooDto.java").setFile(file); assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isTrue(); } @@ -91,14 +91,14 @@ public class ExclusionFiltersTest { filter.prepare(); java.io.File file = temp.newFile(); - DefaultInputFile inputFile = new DefaultInputFile("src/main/java/com/mycompany/FooDao.java").setFile(file); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/main/java/com/mycompany/FooDao.java").setFile(file); assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isFalse(); - inputFile = new DefaultInputFile("src/main/java/com/mycompany/Foo.java").setFile(file); + inputFile = new DefaultInputFile("foo", "src/main/java/com/mycompany/Foo.java").setFile(file); assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isTrue(); // source exclusions do not apply to tests - inputFile = new DefaultInputFile("src/test/java/com/mycompany/FooDao.java").setFile(file); + inputFile = new DefaultInputFile("foo", "src/test/java/com/mycompany/FooDao.java").setFile(file); assertThat(filter.accept(inputFile, InputFile.Type.TEST)).isTrue(); } @@ -114,10 +114,10 @@ public class ExclusionFiltersTest { filter.prepare(); - DefaultInputFile inputFile = new DefaultInputFile("src/main/java/org/bar/Foo.java").setFile(includedFile); + DefaultInputFile inputFile = new DefaultInputFile("foo", "src/main/java/org/bar/Foo.java").setFile(includedFile); assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isTrue(); - inputFile = new DefaultInputFile("src/main/java/org/bar/Bar.java").setFile(excludedFile); + inputFile = new DefaultInputFile("foo", "src/main/java/org/bar/Bar.java").setFile(excludedFile); assertThat(filter.accept(inputFile, InputFile.Type.MAIN)).isFalse(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java index 03dbec79af8..7008b0450c0 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java @@ -55,9 +55,9 @@ public class InputPathCacheTest { @Test public void should_add_input_file() throws Exception { InputPathCache cache = new InputPathCache(caches); - DefaultInputFile fooFile = new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile("Foo.java")); + DefaultInputFile fooFile = new DefaultInputFile("foo", "src/main/java/Foo.java").setFile(temp.newFile("Foo.java")); cache.put("struts", fooFile); - cache.put("struts-core", new DeprecatedDefaultInputFile("src/main/java/Bar.java") + cache.put("struts-core", new DeprecatedDefaultInputFile("foo", "src/main/java/Bar.java") .setBasedir(temp.newFolder()) .setDeprecatedKey("foo") .setSourceDirAbsolutePath("foo") @@ -67,7 +67,6 @@ public class InputPathCacheTest { .setStatus(Status.ADDED) .setHash("xyz") .setLines(1) - .setKey("foo") .setFile(temp.newFile("Bar.java"))); assertThat(cache.getFile("struts", "src/main/java/Foo.java").relativePath()) diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java index b8281a3cdcf..a892042a8d4 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java @@ -183,7 +183,7 @@ public class LanguageDetectionTest { private InputFile newInputFile(String path) throws IOException { File basedir = temp.newFolder(); - return new DefaultInputFile(path).setFile(new File(basedir, path)); + return new DefaultInputFile("foo", path).setFile(new File(basedir, path)); } static class MockLanguage implements Language { diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java index 6cd93d93da0..207ea46546c 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java @@ -87,10 +87,8 @@ public class JsonReportTest { mode = mock(AnalysisMode.class); when(mode.isPreview()).thenReturn(true); userFinder = mock(UserFinder.class); - DefaultInputDir inputDir = new DefaultInputDir("src/main/java/org/apache/struts"); - inputDir.setKey("struts:src/main/java/org/apache/struts"); - DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("src/main/java/org/apache/struts/Action.java"); - inputFile.setKey("struts:src/main/java/org/apache/struts/Action.java"); + DefaultInputDir inputDir = new DefaultInputDir("struts", "src/main/java/org/apache/struts"); + DeprecatedDefaultInputFile inputFile = new DeprecatedDefaultInputFile("struts", "src/main/java/org/apache/struts/Action.java"); inputFile.setStatus(InputFile.Status.CHANGED); InputPathCache fileCache = mock(InputPathCache.class); when(fileCache.all()).thenReturn(Arrays.<InputPath>asList(inputDir, inputFile)); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan2/AnalyzerOptimizerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan2/AnalyzerOptimizerTest.java index 6c21f0c1184..0f79c6521cd 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan2/AnalyzerOptimizerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan2/AnalyzerOptimizerTest.java @@ -19,8 +19,6 @@ */ package org.sonar.batch.scan2; -import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -30,7 +28,9 @@ import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; +import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; import org.sonar.api.rule.RuleKey; + import static org.fest.assertions.Assertions.assertThat; public class AnalyzerOptimizerTest { @@ -59,7 +59,7 @@ public class AnalyzerOptimizerTest { .workOnLanguages("java", "php"); assertThat(optimizer.shouldExecute(descriptor)).isFalse(); - fs.add(new DefaultInputFile("src/Foo.java").setLanguage("java")); + fs.add(new DefaultInputFile("foo", "src/Foo.java").setLanguage("java")); assertThat(optimizer.shouldExecute(descriptor)).isTrue(); } @@ -69,10 +69,10 @@ public class AnalyzerOptimizerTest { .workOnFileTypes(InputFile.Type.MAIN); assertThat(optimizer.shouldExecute(descriptor)).isFalse(); - fs.add(new DefaultInputFile("tests/FooTest.java").setType(InputFile.Type.TEST)); + fs.add(new DefaultInputFile("foo", "tests/FooTest.java").setType(InputFile.Type.TEST)); assertThat(optimizer.shouldExecute(descriptor)).isFalse(); - fs.add(new DefaultInputFile("src/Foo.java").setType(InputFile.Type.MAIN)); + fs.add(new DefaultInputFile("foo", "src/Foo.java").setType(InputFile.Type.MAIN)); assertThat(optimizer.shouldExecute(descriptor)).isTrue(); } @@ -83,11 +83,11 @@ public class AnalyzerOptimizerTest { .workOnFileTypes(InputFile.Type.MAIN); assertThat(optimizer.shouldExecute(descriptor)).isFalse(); - fs.add(new DefaultInputFile("tests/FooTest.java").setLanguage("java").setType(InputFile.Type.TEST)); - fs.add(new DefaultInputFile("src/Foo.cbl").setLanguage("cobol").setType(InputFile.Type.MAIN)); + fs.add(new DefaultInputFile("foo", "tests/FooTest.java").setLanguage("java").setType(InputFile.Type.TEST)); + fs.add(new DefaultInputFile("foo", "src/Foo.cbl").setLanguage("cobol").setType(InputFile.Type.MAIN)); assertThat(optimizer.shouldExecute(descriptor)).isFalse(); - fs.add(new DefaultInputFile("src/Foo.java").setLanguage("java").setType(InputFile.Type.MAIN)); + fs.add(new DefaultInputFile("foo", "src/Foo.java").setLanguage("java").setType(InputFile.Type.MAIN)); assertThat(optimizer.shouldExecute(descriptor)).isTrue(); } diff --git a/sonar-core/src/test/java/org/sonar/core/component/ComponentKeysTest.java b/sonar-core/src/test/java/org/sonar/core/component/ComponentKeysTest.java index 2e372c4261c..3c4d0e78063 100644 --- a/sonar-core/src/test/java/org/sonar/core/component/ComponentKeysTest.java +++ b/sonar-core/src/test/java/org/sonar/core/component/ComponentKeysTest.java @@ -41,7 +41,7 @@ public class ComponentKeysTest { Library library = new Library("junit:junit", "4.7"); assertThat(ComponentKeys.createEffectiveKey(project, library)).isEqualTo("junit:junit"); - InputFile file = new DefaultInputFile("foo/Bar.php"); + InputFile file = new DefaultInputFile("foo", "foo/Bar.php"); assertThat(ComponentKeys.createEffectiveKey("my_project", file)).isEqualTo("my_project:foo/Bar.php"); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java index 26fc37a0030..71026d52d33 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java @@ -22,8 +22,6 @@ package org.sonar.api.batch.fs.internal; import org.sonar.api.batch.fs.InputDir; import org.sonar.api.utils.PathUtils; -import javax.annotation.CheckForNull; - import java.io.File; import java.io.Serializable; @@ -33,10 +31,11 @@ import java.io.Serializable; public class DefaultInputDir implements InputDir, Serializable { private final String relativePath; + private final String moduleKey; private String absolutePath; - private String key; - public DefaultInputDir(String relativePath) { + public DefaultInputDir(String moduleKey, String relativePath) { + this.moduleKey = moduleKey; this.relativePath = PathUtils.sanitize(relativePath); } @@ -45,12 +44,7 @@ public class DefaultInputDir implements InputDir, Serializable { return relativePath; } - /** - * Marked as nullable just for the unit tests that do not call {@link #setFile(java.io.File)} - * previously. - */ @Override - @CheckForNull public String absolutePath() { return absolutePath; } @@ -63,13 +57,12 @@ public class DefaultInputDir implements InputDir, Serializable { return new File(absolutePath); } - /** - * Component key. It's marked as nullable just for the unit tests that - * do not previously call {@link #setKey(String)}. - */ - @CheckForNull + public String moduleKey() { + return moduleKey; + } + public String key() { - return key; + return new StringBuilder().append(moduleKey).append(":").append(relativePath).toString(); } public DefaultInputDir setAbsolutePath(String s) { @@ -82,11 +75,6 @@ public class DefaultInputDir implements InputDir, Serializable { return this; } - public DefaultInputDir setKey(String s) { - this.key = s; - return this; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -97,16 +85,16 @@ public class DefaultInputDir implements InputDir, Serializable { } DefaultInputDir that = (DefaultInputDir) o; - return relativePath.equals(that.relativePath); + return moduleKey.equals(that.moduleKey) && relativePath.equals(that.relativePath); } @Override public int hashCode() { - return relativePath.hashCode(); + return moduleKey.hashCode() + relativePath.hashCode() * 13; } @Override public String toString() { - return "[relative=" + relativePath + ", abs=" + absolutePath + "]"; + return "[moduleKey=" + moduleKey + ", relative=" + relativePath + ", abs=" + absolutePath + "]"; } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java index 34611ea5d98..6816e2f1296 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java @@ -31,15 +31,16 @@ import java.io.Serializable; public class DefaultInputFile implements InputFile, Serializable { private final String relativePath; + private final String moduleKey; private String absolutePath; private String language; private Type type = Type.MAIN; private Status status; private String hash; private int lines; - private String key; - public DefaultInputFile(String relativePath) { + public DefaultInputFile(String moduleKey, String relativePath) { + this.moduleKey = moduleKey; this.relativePath = PathUtils.sanitize(relativePath); } @@ -95,7 +96,11 @@ public class DefaultInputFile implements InputFile, Serializable { * Component key. */ public String key() { - return key; + return new StringBuilder().append(moduleKey).append(":").append(relativePath).toString(); + } + + public String moduleKey() { + return moduleKey; } public DefaultInputFile setAbsolutePath(String s) { @@ -133,11 +138,6 @@ public class DefaultInputFile implements InputFile, Serializable { return this; } - public DefaultInputFile setKey(String s) { - this.key = s; - return this; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -148,16 +148,16 @@ public class DefaultInputFile implements InputFile, Serializable { } DefaultInputFile that = (DefaultInputFile) o; - return relativePath.equals(that.relativePath); + return moduleKey.equals(that.moduleKey) && relativePath.equals(that.relativePath); } @Override public int hashCode() { - return relativePath.hashCode(); + return moduleKey.hashCode() + relativePath.hashCode() * 13; } @Override public String toString() { - return "[relative=" + relativePath + ", abs=" + absolutePath + "]"; + return "[moduleKey=" + moduleKey + ", relative=" + relativePath + ", abs=" + absolutePath + "]"; } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java index 7c82aa501d0..a599b6ff656 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java @@ -37,8 +37,8 @@ public class DeprecatedDefaultInputFile extends DefaultInputFile implements org. private String sourceDirAbsolutePath; private String pathRelativeToSourceDir; - public DeprecatedDefaultInputFile(String relativePath) { - super(relativePath); + public DeprecatedDefaultInputFile(String moduleKey, String relativePath) { + super(moduleKey, relativePath); } /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java index 22521ce0115..22d915c20fc 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java @@ -19,6 +19,7 @@ */ package org.sonar.api.batch.rule; +import org.sonar.api.BatchComponent; import org.sonar.api.rule.RuleKey; import javax.annotation.CheckForNull; @@ -28,7 +29,7 @@ import java.util.Collection; /** * @since 4.2 */ -public interface Rules { +public interface Rules extends BatchComponent { @CheckForNull Rule find(RuleKey key); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java index 7465126c3e1..f2102986b38 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java @@ -33,6 +33,8 @@ import org.sonar.api.batch.sensor.issue.IssueBuilder; import org.sonar.api.batch.sensor.measure.Measure; import org.sonar.api.batch.sensor.measure.MeasureBuilder; import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder; +import org.sonar.api.batch.sensor.test.TestCase; +import org.sonar.api.batch.sensor.test.TestCaseBuilder; import org.sonar.api.config.Settings; import javax.annotation.CheckForNull; @@ -149,7 +151,43 @@ public interface SensorContext { /** * Register all duplications of an {@link InputFile}. Use {@link #duplicationBuilder(InputFile)} to create * list of duplications. + * @since 4.5 */ void saveDuplications(InputFile inputFile, List<DuplicationGroup> duplications); + // ------------ TESTS ------------ + + /** + * Create a new test case for the given test file. + * @param testFile An {@link InputFile} with type {@link InputFile.Type#TEST} + * @param testCaseName name of the test case + * @since 5.0 + */ + TestCaseBuilder testCaseBuilder(InputFile testFile, String testCaseName); + + /** + * Add a new test case. + * Use {@link #testCaseBuilder(InputFile, String)} to create a new {@link TestCase} + * @throws IllegalArgumentException if a test case with same name was already added on the same file. + * @since 5.0 + */ + void addTestCase(TestCase testCase); + + /** + * Get a {@link TestCase} that has been previously added to the context with {@link #addTestCase(TestCase)}. + * @since 5.0 + */ + @CheckForNull + TestCase getTestCase(InputFile testFile, String testCaseName); + + /** + * Register coverage of a given test case on another main file. TestCase should have been registered using {@link #testPlanBuilder(InputFile)} + * @param testFile test file containing the test case + * @param testCaseName name of the test case + * @param coveredFile main file that is covered + * @param coveredLines list of covered lines + * @since 5.0 + */ + void saveCoveragePerTest(TestCase testCase, InputFile coveredFile, List<Integer> coveredLines); + } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCase.java new file mode 100644 index 00000000000..a4e95e62e40 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCase.java @@ -0,0 +1,69 @@ +/* + * 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 javax.annotation.Nullable; + +/** + * Represents a single test in a test plan. + * @since 5.0 + * + */ +public interface TestCase { + enum Status { + OK, FAILURE, ERROR, SKIPPED; + + public static Status of(@Nullable String s) { + return s == null ? null : valueOf(s.toUpperCase()); + } + } + + enum Type { + UNIT, INTEGRATION; + } + + /** + * Duration in milliseconds + */ + Long durationInMs(); + + Type type(); + + /** + * Status of execution of the test. + */ + Status status(); + + /** + * Name of this test case. + */ + String name(); + + /** + * Message (usually in case of {@link Status#ERROR} or {@link Status#FAILURE}). + */ + String message(); + + /** + * Stacktrace (usually in case of {@link Status#ERROR}). + */ + String stackTrace(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseBuilder.java new file mode 100644 index 00000000000..9667ff794aa --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseBuilder.java @@ -0,0 +1,61 @@ +/* + * 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.sensor.test.TestCase.Status; +import org.sonar.api.batch.sensor.test.TestCase.Type; + +/** + * Builder to create a new TestCase on a test file. + * @since 5.0 + */ +public interface TestCaseBuilder { + + /** + * Duration in milliseconds + */ + TestCaseBuilder durationInMs(long duration); + + /** + * Status of execution of the test. + */ + TestCaseBuilder status(Status status); + + /** + * Message (usually in case of {@link Status#ERROR} or {@link Status#FAILURE}). + */ + TestCaseBuilder message(String message); + + /** + * Type of test. + */ + TestCaseBuilder type(Type type); + + /** + * Stacktrace (usually in case of {@link Status#ERROR}). + */ + TestCaseBuilder stackTrace(String stackTrace); + + /** + * Call this method only once when your are done with defining the test case. + */ + TestCase build(); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCase.java new file mode 100644 index 00000000000..a6616abcb8f --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCase.java @@ -0,0 +1,137 @@ +/* + * 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.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.test.TestCase; + +import javax.annotation.CheckForNull; + +public class DefaultTestCase implements TestCase { + + private final InputFile testFile; + private final String name; + private final Long duration; + private final Status status; + private final String message; + private final Type type; + private final String stackTrace; + + public DefaultTestCase(InputFile testFile, String name, Long duration, Status status, String message, Type type, String stackTrace) { + this.testFile = testFile; + this.name = name; + this.duration = duration; + this.status = status; + this.message = message; + this.type = type; + this.stackTrace = stackTrace; + } + + 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; + } + + // 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; + } + DefaultTestCase rhs = (DefaultTestCase) 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(); + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("file", testFile) + .append("name", name) + .append("duration", duration) + .append("status", status) + .append("message", message) + .append("type", type) + .append("stackTrace", stackTrace) + .toString(); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseBuilder.java new file mode 100644 index 00000000000..0b6e34ee07b --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseBuilder.java @@ -0,0 +1,86 @@ +/* + * 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.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.test.TestCase; +import org.sonar.api.batch.sensor.test.TestCase.Status; +import org.sonar.api.batch.sensor.test.TestCase.Type; +import org.sonar.api.batch.sensor.test.TestCaseBuilder; + +import javax.annotation.Nullable; + +public class DefaultTestCaseBuilder implements TestCaseBuilder { + + private final InputFile testFile; + private final String name; + private Long duration; + private TestCase.Status status = Status.OK; + private String message; + private TestCase.Type type = Type.UNIT; + private String stackTrace; + + public DefaultTestCaseBuilder(InputFile testFile, String name) { + Preconditions.checkArgument(testFile.type() == InputFile.Type.TEST, "Should be a test file: " + testFile); + Preconditions.checkArgument(StringUtils.isNotBlank(name), "Test name should not be blank"); + this.testFile = testFile; + this.name = name; + } + + @Override + public TestCaseBuilder durationInMs(long duration) { + Preconditions.checkArgument(duration >= 0, "Test duration must be positive (got: " + duration + ")"); + this.duration = duration; + return this; + } + + @Override + public TestCaseBuilder status(TestCase.Status status) { + Preconditions.checkNotNull(status); + this.status = status; + return this; + } + + @Override + public TestCaseBuilder message(@Nullable String message) { + this.message = message; + return this; + } + + @Override + public TestCaseBuilder type(TestCase.Type type) { + this.type = type; + return this; + } + + @Override + public TestCaseBuilder stackTrace(@Nullable String stackTrace) { + this.stackTrace = stackTrace; + return this; + } + + @Override + public TestCase build() { + return new DefaultTestCase(this.testFile, this.name, this.duration, this.status, this.message, this.type, this.stackTrace); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/package-info.java new file mode 100644 index 00000000000..02a89291200 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/package-info.java @@ -0,0 +1,21 @@ +/* + * 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;
\ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/package-info.java new file mode 100644 index 00000000000..c0e60bb0977 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/package-info.java @@ -0,0 +1,21 @@ +/* + * 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;
\ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java index a656a76bbb1..dfecc85f0a4 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java @@ -19,10 +19,16 @@ */ package org.sonar.api.test; +import org.sonar.api.batch.sensor.SensorContext; + import javax.annotation.Nullable; import java.util.List; +/** + * @deprecated since 5.0 use {@link SensorContext#testPlanBuilder(org.sonar.api.batch.fs.InputFile)} + */ +@Deprecated public interface MutableTestCase extends TestCase { MutableTestCase setStatus(@Nullable Status s); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestPlan.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestPlan.java index 22bccb8d9fb..7a1f9c8cd24 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestPlan.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestPlan.java @@ -19,8 +19,13 @@ */ package org.sonar.api.test; +import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.component.MutablePerspective; +/** + * @deprecated since 5.0 use {@link SensorContext#testPlanBuilder(org.sonar.api.batch.fs.InputFile)} + */ +@Deprecated public interface MutableTestPlan extends TestPlan<MutableTestCase>, MutablePerspective { MutableTestCase addTestCase(String name); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestable.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestable.java index be9c30892b1..2d91cb885e9 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestable.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestable.java @@ -19,8 +19,13 @@ */ package org.sonar.api.test; +import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.component.MutablePerspective; +/** + * @deprecated since 5.0 use {@link SensorContext#testPlanBuilder(org.sonar.api.batch.fs.InputFile)} + */ +@Deprecated public interface MutableTestable extends Testable, MutablePerspective { } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java index abe7025a02a..70dccba3976 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java @@ -21,6 +21,10 @@ package org.sonar.api.test; import javax.annotation.Nullable; +/** + * @deprecated since 5.0 see {@link org.sonar.api.batch.sensor.test.TestCase} + */ +@Deprecated public interface TestCase { enum Status { OK, FAILURE, ERROR, SKIPPED; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestPlan.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestPlan.java index dbb864426f5..affb39bfe5e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/TestPlan.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/TestPlan.java @@ -21,6 +21,10 @@ package org.sonar.api.test; import org.sonar.api.component.Perspective; +/** + * @deprecated since 5.0 + */ +@Deprecated public interface TestPlan<T extends TestCase> extends Perspective { Iterable<T> testCases(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java b/sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java index 7091b6bee86..1857c49642b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java @@ -19,12 +19,17 @@ */ package org.sonar.api.test; +import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.component.Perspective; import java.util.List; import java.util.Map; import java.util.SortedSet; +/** + * @deprecated since 5.0 use {@link SensorContext#testPlanBuilder(org.sonar.api.batch.fs.InputFile)} + */ +@Deprecated public interface Testable extends Perspective { List<TestCase> testCases(); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java index 95888fecfe9..3539bea9566 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java @@ -45,7 +45,7 @@ public class DefaultFilePredicatesTest { @Before public void before() throws IOException { - javaFile = new DefaultInputFile("src/main/java/struts/Action.java") + javaFile = new DefaultInputFile("foo", "src/main/java/struts/Action.java") .setFile(temp.newFile("Action.java")) .setLanguage("java") .setStatus(InputFile.Status.ADDED); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java index 678fdc5687b..aacc7abfb9b 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java @@ -80,12 +80,12 @@ public class DefaultFileSystemTest { assertThat(fs.inputFiles(fs.predicates().all())).isEmpty(); - fs.add(new DefaultInputFile("src/Foo.php").setLanguage("php").setFile(temp.newFile())); - fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile())); - fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile())); + fs.add(new DefaultInputFile("foo", "src/Foo.php").setLanguage("php").setFile(temp.newFile())); + fs.add(new DefaultInputFile("foo", "src/Bar.java").setLanguage("java").setFile(temp.newFile())); + fs.add(new DefaultInputFile("foo", "src/Baz.java").setLanguage("java").setFile(temp.newFile())); // no language - fs.add(new DefaultInputFile("src/readme.txt").setFile(temp.newFile())); + fs.add(new DefaultInputFile("foo", "src/readme.txt").setFile(temp.newFile())); assertThat(fs.inputFile(fs.predicates().hasRelativePath("src/Bar.java"))).isNotNull(); assertThat(fs.inputFile(fs.predicates().hasRelativePath("does/not/exist"))).isNull(); @@ -119,8 +119,8 @@ public class DefaultFileSystemTest { thrown.expectMessage("expected one element"); DefaultFileSystem fs = new DefaultFileSystem(); - fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile())); - fs.add(new DefaultInputFile("src/Baz.java").setLanguage("java").setFile(temp.newFile())); + fs.add(new DefaultInputFile("foo", "src/Bar.java").setLanguage("java").setFile(temp.newFile())); + fs.add(new DefaultInputFile("foo", "src/Baz.java").setLanguage("java").setFile(temp.newFile())); fs.inputFile(fs.predicates().all()); } @@ -128,7 +128,7 @@ public class DefaultFileSystemTest { @Test public void input_file_supports_non_indexed_predicates() throws Exception { DefaultFileSystem fs = new DefaultFileSystem(); - fs.add(new DefaultInputFile("src/Bar.java").setLanguage("java").setFile(temp.newFile())); + fs.add(new DefaultInputFile("foo", "src/Bar.java").setLanguage("java").setFile(temp.newFile())); // it would fail if more than one java file assertThat(fs.inputFile(fs.predicates().hasLanguage("java"))).isNotNull(); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputDirTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputDirTest.java index ca11cd02bcc..49157e92a44 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputDirTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputDirTest.java @@ -35,11 +35,10 @@ public class DefaultInputDirTest { @Test public void test() throws Exception { File dir = temp.newFolder("src"); - DefaultInputDir inputDir = new DefaultInputDir("src") - .setFile(dir) - .setKey("ABCDE"); + DefaultInputDir inputDir = new DefaultInputDir("ABCDE", "src") + .setFile(dir); - assertThat(inputDir.key()).isEqualTo("ABCDE"); + assertThat(inputDir.key()).isEqualTo("ABCDE:src"); assertThat(inputDir.file().getAbsolutePath()).isEqualTo(dir.getAbsolutePath()); assertThat(inputDir.relativePath()).isEqualTo("src"); assertThat(new File(inputDir.relativePath())).isRelative(); @@ -50,22 +49,20 @@ public class DefaultInputDirTest { @Test public void testEqualsAndHashCode() throws Exception { File dir1 = temp.newFolder("src"); - DefaultInputDir inputDir1 = new DefaultInputDir("src") - .setFile(dir1) - .setKey("ABCDE"); + DefaultInputDir inputDir1 = new DefaultInputDir("ABCDE", "src") + .setFile(dir1); File dir2 = temp.newFolder("src2"); - DefaultInputDir inputDir2 = new DefaultInputDir("src") - .setFile(dir2) - .setKey("ABCDE"); + DefaultInputDir inputDir2 = new DefaultInputDir("ABCDE", "src") + .setFile(dir2); assertThat(inputDir1.equals(inputDir1)).isTrue(); assertThat(inputDir1.equals(inputDir2)).isTrue(); assertThat(inputDir1.equals("foo")).isFalse(); - assertThat(inputDir1.hashCode()).isEqualTo(114148); + assertThat(inputDir1.hashCode()).isEqualTo(63545559); - assertThat(inputDir1.toString()).contains("[relative=src, abs="); + assertThat(inputDir1.toString()).contains("[moduleKey=ABCDE, relative=src, abs="); } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java index b96821ffd69..e96f29e82e0 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java @@ -35,9 +35,8 @@ public class DefaultInputFileTest { @Test public void test() throws Exception { - DefaultInputFile inputFile = new DefaultInputFile("src/Foo.php") + DefaultInputFile inputFile = new DefaultInputFile("ABCDE", "src/Foo.php") .setFile(temp.newFile("Foo.php")) - .setKey("ABCDE") .setHash("1234") .setLines(42) .setLanguage("php") @@ -57,9 +56,9 @@ public class DefaultInputFileTest { @Test public void test_equals_and_hashcode() throws Exception { - DefaultInputFile f1 = new DefaultInputFile("src/Foo.php"); - DefaultInputFile f1a = new DefaultInputFile("src/Foo.php"); - DefaultInputFile f2 = new DefaultInputFile("src/Bar.php"); + DefaultInputFile f1 = new DefaultInputFile("ABCDE", "src/Foo.php"); + DefaultInputFile f1a = new DefaultInputFile("ABCDE", "src/Foo.php"); + DefaultInputFile f2 = new DefaultInputFile("ABCDE", "src/Bar.php"); assertThat(f1).isEqualTo(f1); assertThat(f1).isEqualTo(f1a); @@ -73,7 +72,7 @@ public class DefaultInputFileTest { @Test public void test_toString() throws Exception { - DefaultInputFile file = new DefaultInputFile("src/Foo.php").setAbsolutePath("/path/to/src/Foo.php"); - assertThat(file.toString()).isEqualTo("[relative=src/Foo.php, abs=/path/to/src/Foo.php]"); + DefaultInputFile file = new DefaultInputFile("ABCDE", "src/Foo.php").setAbsolutePath("/path/to/src/Foo.php"); + assertThat(file.toString()).isEqualTo("[moduleKey=ABCDE, relative=src/Foo.php, abs=/path/to/src/Foo.php]"); } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java index 321efa8b681..b1f07a138b1 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java @@ -36,11 +36,10 @@ public class DeprecatedDefaultInputFileTest { @Test public void test() throws Exception { - DeprecatedDefaultInputFile inputFile = (DeprecatedDefaultInputFile) new DeprecatedDefaultInputFile("src/Foo.php") + DeprecatedDefaultInputFile inputFile = (DeprecatedDefaultInputFile) new DeprecatedDefaultInputFile("ABCDE", "src/Foo.php") .setPathRelativeToSourceDir("Foo.php") .setDeprecatedKey("deprecated") .setFile(temp.newFile("Foo.php")) - .setKey("ABCDE") .setHash("1234") .setLines(42) .setLanguage("php") @@ -62,9 +61,9 @@ public class DeprecatedDefaultInputFileTest { @Test public void test_equals_and_hashcode() throws Exception { - DefaultInputFile f1 = new DefaultInputFile("src/Foo.php"); - DefaultInputFile f1a = new DefaultInputFile("src/Foo.php"); - DefaultInputFile f2 = new DefaultInputFile("src/Bar.php"); + DefaultInputFile f1 = new DefaultInputFile("ABCDE", "src/Foo.php"); + DefaultInputFile f1a = new DefaultInputFile("ABCDE", "src/Foo.php"); + DefaultInputFile f2 = new DefaultInputFile("ABCDE", "src/Bar.php"); assertThat(f1).isEqualTo(f1); assertThat(f1).isEqualTo(f1a); @@ -78,7 +77,7 @@ public class DeprecatedDefaultInputFileTest { @Test public void test_toString() throws Exception { - DefaultInputFile file = new DefaultInputFile("src/Foo.php").setAbsolutePath("/path/to/src/Foo.php"); - assertThat(file.toString()).isEqualTo("[relative=src/Foo.php, abs=/path/to/src/Foo.php]"); + DefaultInputFile file = new DefaultInputFile("ABCDE", "src/Foo.php").setAbsolutePath("/path/to/src/Foo.php"); + assertThat(file.toString()).isEqualTo("[moduleKey=ABCDE, relative=src/Foo.php, abs=/path/to/src/Foo.php]"); } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java index 01d6dabd0fb..87f6aa3b245 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java @@ -38,16 +38,16 @@ public class PathPatternTest { assertThat(pattern.toString()).isEqualTo("**/*Foo.java"); File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java"); - InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file); + InputFile inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/MyFoo.java").setFile(file); assertThat(pattern.match(inputFile)).isTrue(); // case sensitive by default file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA"); - inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file); + inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/MyFoo.JAVA").setFile(file); assertThat(pattern.match(inputFile)).isFalse(); file = new File(temp.newFolder(), "src/main/java/org/Other.java"); - inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file); + inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/Other.java").setFile(file); assertThat(pattern.match(inputFile)).isFalse(); } @@ -56,11 +56,11 @@ public class PathPatternTest { PathPattern pattern = PathPattern.create("**/*Foo.java"); File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA"); - InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file); + InputFile inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/MyFoo.JAVA").setFile(file); assertThat(pattern.match(inputFile, false)).isTrue(); file = new File(temp.newFolder(), "src/main/java/org/Other.java"); - inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file); + inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/Other.java").setFile(file); assertThat(pattern.match(inputFile, false)).isFalse(); } @@ -70,16 +70,16 @@ public class PathPatternTest { assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java"); File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java"); - InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.java").setFile(file); + InputFile inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/MyFoo.java").setFile(file); assertThat(pattern.match(inputFile)).isTrue(); // case sensitive by default file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA"); - inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file); + inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/MyFoo.JAVA").setFile(file); assertThat(pattern.match(inputFile)).isFalse(); file = new File(temp.newFolder(), "src/main/java/org/Other.java"); - inputFile = new DefaultInputFile("src/main/java/org/Other.java").setFile(file); + inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/Other.java").setFile(file); assertThat(pattern.match(inputFile)).isFalse(); } @@ -89,17 +89,17 @@ public class PathPatternTest { assertThat(pattern.toString()).isEqualTo("file:**/src/main/**Foo.java"); File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.JAVA"); - InputFile inputFile = new DefaultInputFile("src/main/java/org/MyFoo.JAVA").setFile(file); + InputFile inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/MyFoo.JAVA").setFile(file); assertThat(pattern.match(inputFile, false)).isTrue(); file = new File(temp.newFolder(), "src/main/java/org/Other.JAVA"); - inputFile = new DefaultInputFile("src/main/java/org/Other.JAVA").setFile(file); + inputFile = new DefaultInputFile("ABCDE", "src/main/java/org/Other.JAVA").setFile(file); assertThat(pattern.match(inputFile, false)).isFalse(); } @Test public void create_array_of_patterns() throws Exception { - PathPattern[] patterns = PathPattern.create(new String[]{ + PathPattern[] patterns = PathPattern.create(new String[] { "**/src/main/**Foo.java", "file:**/src/main/**Bar.java" }); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplicationBuilderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplicationBuilderTest.java index 17a813dbf35..d586e6855eb 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplicationBuilderTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplicationBuilderTest.java @@ -32,13 +32,13 @@ public class DefaultDuplicationBuilderTest { @Test public void test() { - DefaultDuplicationBuilder builder = new DefaultDuplicationBuilder(new DefaultInputFile("foo.php").setKey("foo:foo.php")); + DefaultDuplicationBuilder builder = new DefaultDuplicationBuilder(new DefaultInputFile("foo", "foo.php")); List<DuplicationGroup> duplicationGroup = builder.originBlock(1, 11) - .isDuplicatedBy(new DefaultInputFile("foo.php"), 40, 50) - .isDuplicatedBy(new DefaultInputFile("foo2.php"), 1, 10) + .isDuplicatedBy(new DefaultInputFile("foo", "foo.php"), 40, 50) + .isDuplicatedBy(new DefaultInputFile("foo", "foo2.php"), 1, 10) .originBlock(20, 30) - .isDuplicatedBy(new DefaultInputFile("foo3.php"), 30, 40) + .isDuplicatedBy(new DefaultInputFile("foo", "foo3.php"), 30, 40) .build(); assertThat(duplicationGroup).hasSize(2); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java index 7e98d6e3591..6c0d12da82c 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java @@ -36,14 +36,14 @@ public class DefaultIssueTest { @Test public void build_file_issue() { Issue issue = new DefaultIssueBuilder() - .onFile(new DefaultInputFile("src/Foo.php")) + .onFile(new DefaultInputFile("foo", "src/Foo.php")) .ruleKey(RuleKey.of("repo", "rule")) .atLine(1) .effortToFix(10.0) .message("Wrong way!") .build(); - assertThat(issue.inputPath()).isEqualTo(new DefaultInputFile("src/Foo.php")); + assertThat(issue.inputPath()).isEqualTo(new DefaultInputFile("foo", "src/Foo.php")); assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule")); assertThat(issue.line()).isEqualTo(1); assertThat(issue.effortToFix()).isEqualTo(10.0); @@ -72,7 +72,7 @@ public class DefaultIssueTest { thrown.expectMessage("onProject already called"); new DefaultIssueBuilder() .onProject() - .onFile(new DefaultInputFile("src/Foo.php")) + .onFile(new DefaultInputFile("foo", "src/Foo.php")) .ruleKey(RuleKey.of("repo", "rule")) .atLine(1) .effortToFix(10.0) diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java index b894ffec092..8d3faf23810 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java @@ -37,11 +37,11 @@ public class DefaultMeasureTest { public void build_file_measure() { Measure<Integer> issue = new DefaultMeasureBuilder<Integer>() .forMetric(CoreMetrics.LINES) - .onFile(new DefaultInputFile("src/Foo.php")) + .onFile(new DefaultInputFile("foo", "src/Foo.php")) .withValue(3) .build(); - assertThat(issue.inputFile()).isEqualTo(new DefaultInputFile("src/Foo.php")); + assertThat(issue.inputFile()).isEqualTo(new DefaultInputFile("foo", "src/Foo.php")); assertThat(issue.metric()).isEqualTo(CoreMetrics.LINES); assertThat(issue.value()).isEqualTo(3); } @@ -65,7 +65,7 @@ public class DefaultMeasureTest { thrown.expectMessage("onProject already called"); new DefaultMeasureBuilder<Integer>() .onProject() - .onFile(new DefaultInputFile("src/Foo.php")) + .onFile(new DefaultInputFile("foo", "src/Foo.php")) .withValue(3) .build(); } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseBuilderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseBuilderTest.java new file mode 100644 index 00000000000..27a9777b6ee --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseBuilderTest.java @@ -0,0 +1,71 @@ +/* + * 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.TestCase.Status; +import org.sonar.api.batch.sensor.test.TestCase.Type; + +import static org.fest.assertions.Assertions.assertThat; + +public class DefaultTestCaseBuilderTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private InputFile parent = new DefaultInputFile("foo", "src/Foo.php").setType(InputFile.Type.TEST); + + @Test + public void testBuilder() throws Exception { + DefaultTestCaseBuilder builder = new DefaultTestCaseBuilder(parent, "myTest"); + assertThat(builder.durationInMs(1) + .message("message") + .stackTrace("stack") + .status(Status.ERROR) + .type(Type.UNIT) + .build()).isEqualTo(new DefaultTestCase(parent, "myTest", 1L, Status.ERROR, "message", Type.UNIT, "stack")); + } + + @Test + public void testBuilderWithDefaultValues() throws Exception { + DefaultTestCaseBuilder builder = new DefaultTestCaseBuilder(parent, "myTest"); + assertThat(builder.build()).isEqualTo( + new DefaultTestCase(parent, "myTest", null, Status.OK, null, Type.UNIT, null)); + } + + @Test + public void testInvalidDuration() throws Exception { + DefaultTestCaseBuilder builder = new DefaultTestCaseBuilder(parent, "myTest"); + + thrown.expect(IllegalArgumentException.class); + + builder.durationInMs(-3) + .message("message") + .stackTrace("stack") + .status(Status.ERROR) + .type(Type.UNIT) + .build(); + } + +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseTest.java new file mode 100644 index 00000000000..ec5668ac3ca --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseTest.java @@ -0,0 +1,63 @@ +/* + * 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.Test; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.test.TestCase.Status; +import org.sonar.api.batch.sensor.test.TestCase.Type; + +import static org.fest.assertions.Assertions.assertThat; + +public class DefaultTestCaseTest { + + private InputFile parent = new DefaultInputFile("foo", "src/Foo.php"); + + @Test + public void testDefaultTestCaseTest() { + DefaultTestCase testCase1 = new DefaultTestCase(parent, "myTest", 1L, Status.ERROR, "message", Type.UNIT, "stack"); + + assertThat(testCase1.name()).isEqualTo("myTest"); + assertThat(testCase1.durationInMs()).isEqualTo(1L); + assertThat(testCase1.status()).isEqualTo(Status.ERROR); + assertThat(testCase1.message()).isEqualTo("message"); + assertThat(testCase1.type()).isEqualTo(Type.UNIT); + assertThat(testCase1.stackTrace()).isEqualTo("stack"); + } + + @Test + public void testEqualsHashCodeToString() { + DefaultTestCase testCase1 = new DefaultTestCase(parent, "myTest", 1L, Status.ERROR, "message", Type.UNIT, "stack"); + DefaultTestCase testCase1a = new DefaultTestCase(parent, "myTest", 1L, Status.ERROR, "message", Type.UNIT, "stack"); + DefaultTestCase testCase2 = new DefaultTestCase(new DefaultInputFile("foo2", "src/Foo.php"), "myTest2", 2L, Status.FAILURE, "message2", Type.INTEGRATION, null); + + assertThat(testCase1).isEqualTo(testCase1); + assertThat(testCase1).isEqualTo(testCase1a); + assertThat(testCase1).isNotEqualTo(testCase2); + assertThat(testCase1).isNotEqualTo(null); + assertThat(testCase1).isNotEqualTo("foo"); + + assertThat(testCase1.toString()).isEqualTo( + "DefaultTestCase[file=[moduleKey=foo, relative=src/Foo.php, abs=null],name=myTest,duration=1,status=ERROR,message=message,type=UNIT,stackTrace=stack]"); + assertThat(testCase1.hashCode()).isEqualTo(testCase1a.hashCode()); + } + +} |