]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5389 New test API for batch 2.0
authorJulien HENRY <julien.henry@sonarsource.com>
Fri, 5 Sep 2014 12:03:30 +0000 (14:03 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Fri, 5 Sep 2014 12:04:10 +0000 (14:04 +0200)
72 files changed:
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/FileHashSensorTest.java
plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/JavaCpdEngineTest.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/CoveragePerTestSensor.java [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/TestCaseSensor.java [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SymbolReferencesSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/XooTokenizerSensorTest.java
sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultInputFileValueCoder.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java
sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java
sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultMeasureValueCoder.java
sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java
sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/test/CoveragePerTestCache.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/test/DefaultTestCaseValueCoder.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/test/TestCaseCache.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/test/package-info.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/debt/SqaleRatingDecoratorTest.java
sonar-batch/src/test/java/org/sonar/batch/index/ResourceKeyMigrationTest.java
sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/test/TestMediumTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/AdditionalFilePredicatesTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DefaultModuleFileSystemTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/DeprecatedFileFiltersTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ExclusionFiltersTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/LanguageDetectionTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/report/JsonReportTest.java
sonar-batch/src/test/java/org/sonar/batch/scan2/AnalyzerOptimizerTest.java
sonar-core/src/test/java/org/sonar/core/component/ComponentKeysTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputDir.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFile.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCase.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/TestCaseBuilder.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCase.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseBuilder.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/internal/package-info.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/test/package-info.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestCase.java
sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestPlan.java
sonar-plugin-api/src/main/java/org/sonar/api/test/MutableTestable.java
sonar-plugin-api/src/main/java/org/sonar/api/test/TestCase.java
sonar-plugin-api/src/main/java/org/sonar/api/test/TestPlan.java
sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFileSystemTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputDirTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DeprecatedDefaultInputFileTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/PathPatternTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplicationBuilderTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseBuilderTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/test/internal/DefaultTestCaseTest.java [new file with mode: 0644]

index 4f851f39cae0454fb95e555ecdb36a2abbd06379..3044ef773ab03d5faa625b31ad4a334df47004d6 100644 (file)
@@ -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);
index dcada895aabfa8b617e1b2e47f49e749e4eef490..f93e4484390b08a3373063ec875e0f65ce2b9c8f 100644 (file)
@@ -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))
       ));
index 3477fab825c1b8cfa8656df33d6b05825b5e3ec7..c7e43d9e0abfd9c3779acff2ec5649644d15ceca 100644 (file)
 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 (file)
index 0000000..aee8297
--- /dev/null
@@ -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);
+    }
+  }
+}
index c8232484a510304810eefa3b6968b7e5e633c974..61131e8b87a2ea791f5992a013768b449d2b73db 100644 (file)
@@ -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);
   }
index c9c9b8864061014c908b2aab327c71dc76d42ff3..a930c9c8f4ced51695c0bb07928e4303d75647b1 100644 (file)
@@ -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 (file)
index 0000000..c4238b5
--- /dev/null
@@ -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);
+    }
+  }
+}
index bfe1fd99afa64f225fe06b75f05610e0080cf502..96ea0ea923c7380db2fc28df9434c9233249c525 100644 (file)
@@ -27,6 +27,6 @@ public class XooPluginTest {
 
   @Test
   public void provide_extensions() {
-    assertThat(new XooPlugin().getExtensions()).hasSize(11);
+    assertThat(new XooPlugin().getExtensions()).hasSize(13);
   }
 }
index c06d4f307d36f3931a0c509fcbae88214b370620..f12bee28275c07166b2312c79fffa0db6c3da7b9 100644 (file)
@@ -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());
index 68fd40d0f80beaf4bdabd2c2801344b0b6860a49..d5f6a30723e3c64762117da65213bf56c8b0a8c5 100644 (file)
@@ -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);
index 9918a3625ef8f16d33f9f8e37380003300e2f123..cad3b96811341f1103e97c73e9ffb7a25583ed7d 100644 (file)
@@ -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);
index 941798f9436eb37e5957fd80d1a2a19643375367..448d45cfcc50f36c8a969c479b8fa5991ba2d4c3 100644 (file)
@@ -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);
index be3185f7b6d6922a9b15b891d4fad19d53fbff29..403ec002b23539863359b81c28318b5ae6df5a69 100644 (file)
@@ -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
index 545c480381a432fdb92cbe2a21f151f54829777c..37fe0b134bfcb69e18146724c5d9588063384733 100644 (file)
  */
 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;
+  }
+
 }
index 6dcfc9903b1184b5c5d9e80e11d6781bc358f169..42398a58edc8c845fc7f508808bb9a40dd977e92 100644 (file)
@@ -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;
   }
 
index 030febcd78d6baf5e660e31aa01584254a1a626e..f83cf29d5efa2fa551c9b07694cfddfe2bc5ba2b 100644 (file)
@@ -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);
           }
         }
index cd7844fd4ded12c39304f7f0fd25aa8d10560e5f..4e8ed7eedc9e653256dac7419d0bc44f165892fb 100644 (file)
@@ -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);
index 801744de2c7b68ba9796964111d41ceafe449119..df2950a554a9a1e2516d1802221a4e180e9b7288 100644 (file)
@@ -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");
   }
 
index 1246d4ea630e91b4760faa43b0f121ae20f395db..48a74cccd814e792f15aca27717aa5e3bfec8252 100644 (file)
@@ -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);
+  }
+
 }
index 8b82a684dd0ea8b108e29d997b4b63438337dd6a..0a1ee14339e9f2f916ef73b86b614eab9f02aa9e 100644 (file)
@@ -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();
index 2df3de1b0e5490f92aa84609d0d523c9dce72176..e995b80549068190b533cd52542f1f66e9866137 100644 (file)
  */
 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);
+  }
+
 }
index b0a2b3e0af5e4ef8ca86b5a194c4d7faa7b6630c..5922b613ffb0a8a84c00c90f99ed7bfbea67eb3b 100644 (file)
@@ -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 (file)
index 0000000..211cfb4
--- /dev/null
@@ -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 (file)
index 0000000..7cb4b36
--- /dev/null
@@ -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 (file)
index 0000000..e2de947
--- /dev/null
@@ -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 (file)
index 0000000..227ae02
--- /dev/null
@@ -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
index 1b1840a84439ccb299fa92dd9ab1649b27a1e60e..9948ee5b3c4a7504b1658190d524dcd017eeef57 100644 (file)
@@ -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")));
 
index 3d8d75407876b831c311aa3231c5e803874a75ea..d3710e6448853141f66926f26347a3c48ff7cd16 100644 (file)
@@ -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);
   }
 
index 5b97df2c7f5cf269c1e5576e18e79e4bbb24a46b..c75f69fcb2432541b023a0cf9b882fc0487564c4 100644 (file)
@@ -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);
index f3eebf971e3e5a4767e92572029fe856d937e0b1..df958e1ebfb7b152d5a55717f3a2ab058e00427a 100644 (file)
@@ -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();
       }
index fb3e8d16edd3b63e73a05577c3cbb940ec31de51..b75a46346a18f1306318a9d49997d79cb2c9ba11 100644 (file)
@@ -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"));
 
   }
 
index 146b89eb3168f390bd03e7dc6c0a7ac67de9337f..3fb836a90953559a0846b07ce0eccb80cfad60cc 100644 (file)
@@ -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 (file)
index 0000000..1261ef7
--- /dev/null
@@ -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);
+  }
+}
index a93bf9bae83eb55b00de5ac89d99ea0fd2861034..addf1f8bb0c0dd4c1d64e33afd653fde233439c9 100644 (file)
@@ -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);
 
index 0bb4b2432268cc64788afa83417850e33a98ea8e..a5f57f5c4c8f812c00c3bf0e173e1b85c6f39abd 100644 (file)
@@ -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();
   }
 }
index 122b9c618deb6a69d684476f3dca3aac3d472afa..8e90b2b3c68e015211aabe1efff956ebb77c9788 100644 (file)
@@ -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)
index 4d87aed7cd33be2de90618599747c85fe7d0f920..b26bb8cc0e70f3c8a1b03cdfb4b47b08ee9c738d 100644 (file)
@@ -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();
index 02f314e6b719dbba3340187df987ca9b1fe2d94e..60cc12871d53d194d9062052b449555d76948b18 100644 (file)
@@ -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)
index 6255bd6629b9775ebd48baa6be6d175d999d30d6..8b864f2c4913b7958912deec924ca68994bf6e16 100644 (file)
@@ -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();
   }
 
index 03dbec79af8377cc84d56aef952765874bf442a4..7008b0450c0cf38a52b3230e8d92de89b9186471 100644 (file)
@@ -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())
index b8281a3cdcf6203466db3cdc16a310131aaaea92..a892042a8d4b598f97d46fcd0a4ae85919e5d45b 100644 (file)
@@ -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 {
index 6cd93d93da013ccb9e286f6a91c49331e73cc8b4..207ea46546c57313c44614a28e4a84b60d872d83 100644 (file)
@@ -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));
index 6c21f0c11848783ed4d02bb152c82927bcae58e8..0f79c6521cdd10368ef087c974a6ba360d568b07 100644 (file)
@@ -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();
   }
 
index 2e372c4261cc184ce3d449f6baaf40f7ff93b22f..3c4d0e78063dc47e87ece6f8442d808c94952de3 100644 (file)
@@ -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");
   }
 
index 26fc37a0030186441a46f2bdde6c7b51468f40f5..71026d52d3309df9433d37b0d7b5632ab0a81ffe 100644 (file)
@@ -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 + "]";
   }
 }
index 34611ea5d98a8958e781f2ea874437f95c6aae0a..6816e2f12963e7f98ab2a9888234db98c2d4acf3 100644 (file)
@@ -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 + "]";
   }
 }
index 7c82aa501d015ef6a3b7c8e4972dc362dc0dacec..a599b6ff6561c96bbcc28c9251a1da2c4bdfab05 100644 (file)
@@ -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);
   }
 
   /**
index 22521ce0115ec84d656a35917bab92cbab1a09c4..22d915c20fcf7676ed3ff6cb1681396af73a70e7 100644 (file)
@@ -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);
index 7465126c3e1c02339626683bebc60d792ae05671..f2102986b382da252cb69fcd822ae217823802d5 100644 (file)
@@ -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 (file)
index 0000000..a4e95e6
--- /dev/null
@@ -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 (file)
index 0000000..9667ff7
--- /dev/null
@@ -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 (file)
index 0000000..a6616ab
--- /dev/null
@@ -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 (file)
index 0000000..0b6e34e
--- /dev/null
@@ -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 (file)
index 0000000..02a8929
--- /dev/null
@@ -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 (file)
index 0000000..c0e60bb
--- /dev/null
@@ -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
index a656a76bbb1256ebe3d48278bf309fbc36f5302d..dfecc85f0a410c9a0d71fdd9390a544655f67b8c 100644 (file)
  */
 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);
 
index 22bccb8d9fb7b04e85c2552f34c0e8ed58b8dafc..7a1f9c8cd24d014ca9ced1d4748b323e4a76ff91 100644 (file)
  */
 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);
index be9c30892b1278e2e78ec57469217e728bba6bc7..2d91cb885e9731c7c629f01f495ebaf0ccf5393b 100644 (file)
  */
 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 {
 
 }
index abe7025a02ac56f3135c9a734d1815c0c7c3f99c..70dccba397670fe92e208c4730cbab0079f0035e 100644 (file)
@@ -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;
index dbb864426f5ff714febafbaa870f259527e5ab0c..affb39bfe5ea7328462b5359e6e22f1da6fcbabb 100644 (file)
@@ -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();
 
index 7091b6bee8666abbb2f62ad8c20dcd55cdf23a23..1857c49642b44d1d4187399b3dc716e130fae876 100644 (file)
  */
 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();
index 95888fecfe99e76f2f0dcdec6b057cbbef4296e7..3539bea956683eb857f540777d383d839d9adf57 100644 (file)
@@ -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);
index 678fdc5687b25f8a6df179aec386d20ee4686947..aacc7abfb9be6ead0007008f7761110cc510e58e 100644 (file)
@@ -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();
index ca11cd02bcc1eff1f10828e28bd91a94966cc727..49157e92a447065079d5479118914b8b3a2399a2 100644 (file)
@@ -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=");
 
   }
 
index b96821ffd69d1bfe3ffb7e4993f6fbad095bf841..e96f29e82e0903fa009c1a2ea0ada46b14a4cccd 100644 (file)
@@ -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]");
   }
 }
index 321efa8b6811e0d8c80eec233013885c4e566bab..b1f07a138b187da0c4bf75fd08cbdda4d7705ca2 100644 (file)
@@ -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]");
   }
 }
index 01d6dabd0fbb9d69926be7fa5ea89d36418bcd04..87f6aa3b2453609349199fa6cac8e61af28af43c 100644 (file)
@@ -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"
     });
index 17a813dbf3589a9da230fc6728b7d10d51ab1faf..d586e6855eb89eb0d8db2be1efa9c99c6abfccc4 100644 (file)
@@ -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);
index 7e98d6e359136064d6813f2e29ca85b37d64cb6a..6c0d12da82c17d4ec5b296c3d57ad738d14f5d57 100644 (file)
@@ -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)
index b894ffec0920529da84ce1450a26596a90df06cd..8d3faf2381001179413bf5446eeb04f5992011da 100644 (file)
@@ -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 (file)
index 0000000..27a9777
--- /dev/null
@@ -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 (file)
index 0000000..ec5668a
--- /dev/null
@@ -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());
+  }
+
+}