]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11795 Drop persistit and move coverage measures computation to CE side
authorJulien HENRY <julien.henry@sonarsource.com>
Tue, 5 Mar 2019 08:59:43 +0000 (09:59 +0100)
committerSonarTech <sonartech@sonarsource.com>
Fri, 8 Mar 2019 19:20:55 +0000 (20:20 +0100)
48 files changed:
build.gradle
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/CoverageMeasuresStep.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/NewCoverageMeasuresStep.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/batch/BatchReportReaderImplTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportCoverageMeasuresStepTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportNewCoverageMeasuresStepTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ViewsNewCoverageMeasuresStepTest.java
sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java
sonar-core/src/test/java/org/sonar/core/metric/ScannerMetricsTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputComponent.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/sensor/coverage/CoverageType.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
sonar-plugin-api/src/test/java/org/sonar/api/issue/NoSonarFilterTest.java
sonar-scanner-engine/build.gradle
sonar-scanner-engine/src/main/java/org/sonar/scanner/DefaultFileLinesContext.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/DefaultFileLinesContextFactory.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/CoveragePublisher.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MeasuresPublisher.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionPublisher.java [new file with mode: 0644]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/measure/MeasureCache.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/measure/MeasureValueCoder.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/source/ZeroCoverageSensor.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/Storage.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/Storages.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/StoragesManager.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/package-info.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/index/AbstractCachesTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/branch/BranchMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/coverage/CoverageMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/scm/ScmMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CoveragePublisherTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/measure/MeasureCacheTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/storage/StorageTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/storage/StoragesManagerTest.java [deleted file]
sonar-scanner-engine/src/test/java/org/sonar/scanner/storage/StoragesTest.java [deleted file]
sonar-scanner-protocol/src/main/java/org/sonar/scanner/protocol/output/ScannerReportWriter.java
sonar-scanner-protocol/src/test/java/org/sonar/scanner/protocol/output/ScannerReportReaderTest.java
sonar-scanner-protocol/src/test/java/org/sonar/scanner/protocol/output/ScannerReportWriterTest.java

index ad1bf2566bc08fb82c2d3d20a15f65d6bbc6583e..f442ce1f62aa95fd97021fbb717313dc4b94141e 100644 (file)
@@ -226,9 +226,6 @@ subprojects {
       dependency 'org.reflections:reflections:0.9.9'
       dependency 'org.simpleframework:simple:4.1.21'
       dependency 'org.sonarsource.orchestrator:sonar-orchestrator:3.22.0.1791'
-      dependency('org.sonarsource:sonar-persistit:3.3.2') {
-        exclude 'commons-logging:commons-logging'
-      }
       dependency 'org.sonarsource.update-center:sonar-update-center-common:1.18.0.487'
       dependency 'org.subethamail:subethasmtp:3.1.7'
       dependency 'xml-apis:xml-apis:1.4.01'
index d9c9baec0bd1302147961a94fde40499cea1aa24..507db1be6dcece548829f53412eb2f853d731a19 100644 (file)
 package org.sonar.ce.task.projectanalysis.step;
 
 import com.google.common.collect.ImmutableList;
+import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
+import org.sonar.ce.task.projectanalysis.component.Component;
+import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit;
+import org.sonar.ce.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
 import org.sonar.ce.task.projectanalysis.component.PathAwareCrawler;
 import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
+import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter;
 import org.sonar.ce.task.projectanalysis.formula.Formula;
 import org.sonar.ce.task.projectanalysis.formula.FormulaExecutorComponentVisitor;
 import org.sonar.ce.task.projectanalysis.formula.coverage.LinesAndConditionsWithUncoveredFormula;
 import org.sonar.ce.task.projectanalysis.formula.coverage.LinesAndConditionsWithUncoveredMetricKeys;
 import org.sonar.ce.task.projectanalysis.formula.coverage.SingleWithUncoveredFormula;
 import org.sonar.ce.task.projectanalysis.formula.coverage.SingleWithUncoveredMetricKeys;
+import org.sonar.ce.task.projectanalysis.measure.Measure;
 import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
+import org.sonar.ce.task.projectanalysis.metric.Metric;
 import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
 import org.sonar.ce.task.step.ComputationStep;
+import org.sonar.core.util.CloseableIterator;
+import org.sonar.scanner.protocol.output.ScannerReport;
 
+import static java.lang.Math.min;
 import static org.sonar.api.measures.CoreMetrics.BRANCH_COVERAGE_KEY;
 import static org.sonar.api.measures.CoreMetrics.CONDITIONS_TO_COVER_KEY;
 import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY;
@@ -57,20 +67,91 @@ public class CoverageMeasuresStep implements ComputationStep {
   private final TreeRootHolder treeRootHolder;
   private final MetricRepository metricRepository;
   private final MeasureRepository measureRepository;
+  private final BatchReportReader reportReader;
+  private final Metric linesToCoverMetric;
+  private final Metric uncoveredLinesMetric;
+  private final Metric conditionsToCoverMetric;
+  private final Metric uncoveredConditionsMetric;
 
+  /**
+   * Constructor used when processing a Report (ie. a {@link BatchReportReader} instance is available in the container)
+   */
+  public CoverageMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository, BatchReportReader reportReader) {
+    this.treeRootHolder = treeRootHolder;
+    this.metricRepository = metricRepository;
+    this.measureRepository = measureRepository;
+    this.reportReader = reportReader;
+    this.linesToCoverMetric = metricRepository.getByKey(LINES_TO_COVER_KEY);
+    this.uncoveredLinesMetric = metricRepository.getByKey(UNCOVERED_LINES_KEY);
+    this.conditionsToCoverMetric = metricRepository.getByKey(CONDITIONS_TO_COVER_KEY);
+    this.uncoveredConditionsMetric = metricRepository.getByKey(UNCOVERED_CONDITIONS_KEY);
+  }
+
+  /**
+   * Constructor used when processing Views (ie. no {@link BatchReportReader} instance is available in the container)
+   */
   public CoverageMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository) {
     this.treeRootHolder = treeRootHolder;
     this.metricRepository = metricRepository;
     this.measureRepository = measureRepository;
+    this.linesToCoverMetric = metricRepository.getByKey(LINES_TO_COVER_KEY);
+    this.uncoveredLinesMetric = metricRepository.getByKey(UNCOVERED_LINES_KEY);
+    this.conditionsToCoverMetric = metricRepository.getByKey(CONDITIONS_TO_COVER_KEY);
+    this.uncoveredConditionsMetric = metricRepository.getByKey(UNCOVERED_CONDITIONS_KEY);
+    this.reportReader = null;
   }
 
   @Override
   public void execute(ComputationStep.Context context) {
+    if (reportReader != null) {
+      new DepthTraversalTypeAwareCrawler(new FileCoverageVisitor(reportReader)).visit(treeRootHolder.getReportTreeRoot());
+    }
     new PathAwareCrawler<>(
       FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository).buildFor(COVERAGE_FORMULAS))
         .visit(treeRootHolder.getReportTreeRoot());
   }
 
+  private class FileCoverageVisitor extends TypeAwareVisitorAdapter {
+
+    private final BatchReportReader reportReader;
+
+    private FileCoverageVisitor(BatchReportReader reportReader) {
+      super(CrawlerDepthLimit.FILE, Order.POST_ORDER);
+      this.reportReader = reportReader;
+    }
+
+    @Override
+    public void visitFile(Component file) {
+      try (CloseableIterator<ScannerReport.LineCoverage> lineCoverage = reportReader.readComponentCoverage(file.getReportAttributes().getRef())) {
+        int linesToCover = 0;
+        int coveredLines = 0;
+        int conditionsToCover = 0;
+        int coveredConditions = 0;
+        while (lineCoverage.hasNext()) {
+          final ScannerReport.LineCoverage line = lineCoverage.next();
+          if (line.getHasHitsCase() == ScannerReport.LineCoverage.HasHitsCase.HITS) {
+            linesToCover++;
+            if (line.getHits()) {
+              coveredLines++;
+            }
+          }
+          if (line.getHasCoveredConditionsCase() == ScannerReport.LineCoverage.HasCoveredConditionsCase.COVERED_CONDITIONS) {
+            conditionsToCover += line.getConditions();
+            coveredConditions += min(line.getCoveredConditions(), line.getConditions());
+          }
+        }
+        if (linesToCover > 0) {
+          measureRepository.add(file, linesToCoverMetric, Measure.newMeasureBuilder().create(linesToCover));
+          measureRepository.add(file, uncoveredLinesMetric, Measure.newMeasureBuilder().create(linesToCover - coveredLines));
+        }
+        if (conditionsToCover > 0) {
+          measureRepository.add(file, conditionsToCoverMetric, Measure.newMeasureBuilder().create(conditionsToCover));
+          measureRepository.add(file, uncoveredConditionsMetric, Measure.newMeasureBuilder().create(conditionsToCover - coveredConditions));
+        }
+      }
+    }
+  }
+
   private static class CodeCoverageFormula extends LinesAndConditionsWithUncoveredFormula {
     public CodeCoverageFormula() {
       super(
index 64bce16d146441dd921461e5e03f45d323734bc6..ff71dc779ecd48824412adfdca66d59c5d6e2053 100644 (file)
@@ -23,14 +23,11 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.apache.commons.lang.ObjectUtils;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.PathAwareCrawler;
 import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
@@ -51,7 +48,14 @@ import org.sonar.ce.task.projectanalysis.metric.Metric;
 import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
 import org.sonar.ce.task.projectanalysis.source.NewLinesRepository;
 import org.sonar.ce.task.step.ComputationStep;
-
+import org.sonar.core.util.CloseableIterator;
+import org.sonar.scanner.protocol.output.ScannerReport;
+
+import static java.lang.Math.min;
+import static org.sonar.api.measures.CoreMetrics.NEW_CONDITIONS_TO_COVER_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_LINES_TO_COVER_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_UNCOVERED_CONDITIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_UNCOVERED_LINES_KEY;
 import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
 
 /**
@@ -70,16 +74,19 @@ public class NewCoverageMeasuresStep implements ComputationStep {
   private final MeasureRepository measureRepository;
   @Nullable
   private final NewLinesRepository newLinesRepository;
+  @Nullable
+  private final BatchReportReader reportReader;
 
   /**
    * Constructor used when processing a Report (ie. a {@link NewLinesRepository} instance is available in the container)
    */
   public NewCoverageMeasuresStep(TreeRootHolder treeRootHolder,
-    MeasureRepository measureRepository, MetricRepository metricRepository, NewLinesRepository newLinesRepository) {
+    MeasureRepository measureRepository, MetricRepository metricRepository, NewLinesRepository newLinesRepository, BatchReportReader reportReader) {
     this.treeRootHolder = treeRootHolder;
     this.metricRepository = metricRepository;
     this.measureRepository = measureRepository;
     this.newLinesRepository = newLinesRepository;
+    this.reportReader = reportReader;
   }
 
   /**
@@ -90,6 +97,7 @@ public class NewCoverageMeasuresStep implements ComputationStep {
     this.metricRepository = metricRepository;
     this.measureRepository = measureRepository;
     this.newLinesRepository = null;
+    this.reportReader = null;
   }
 
   @Override
@@ -97,8 +105,8 @@ public class NewCoverageMeasuresStep implements ComputationStep {
     new PathAwareCrawler<>(
       FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository)
         .buildFor(
-          Iterables.concat(NewLinesAndConditionsCoverageFormula.from(newLinesRepository), FORMULAS)))
-      .visit(treeRootHolder.getRoot());
+          Iterables.concat(NewLinesAndConditionsCoverageFormula.from(newLinesRepository, reportReader), FORMULAS)))
+            .visit(treeRootHolder.getRoot());
   }
 
   @Override
@@ -106,46 +114,12 @@ public class NewCoverageMeasuresStep implements ComputationStep {
     return "Compute new coverage";
   }
 
-  private static class NewLinesAndConditionsCoverageFormula extends NewLinesAndConditionsFormula {
-
-    private static final NewCoverageOutputMetricKeys OUTPUT_METRIC_KEYS = new NewCoverageOutputMetricKeys(
-      CoreMetrics.NEW_LINES_TO_COVER_KEY, CoreMetrics.NEW_UNCOVERED_LINES_KEY,
-      CoreMetrics.NEW_CONDITIONS_TO_COVER_KEY, CoreMetrics.NEW_UNCOVERED_CONDITIONS_KEY);
-    private static final Iterable<Formula<?>> VIEWS_FORMULAS = variationSumFormulas(OUTPUT_METRIC_KEYS);
-
-    private NewLinesAndConditionsCoverageFormula(NewLinesRepository newLinesRepository) {
-      super(newLinesRepository,
-        new NewCoverageInputMetricKeys(
-          CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, CoreMetrics.CONDITIONS_BY_LINE_KEY, CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY),
-        OUTPUT_METRIC_KEYS);
-    }
-
-    public static Iterable<Formula<?>> from(@Nullable NewLinesRepository newLinesRepository) {
-      if (newLinesRepository == null) {
-        return VIEWS_FORMULAS;
-      }
-      return Collections.singleton(new NewLinesAndConditionsCoverageFormula(newLinesRepository));
-    }
-
-    /**
-     * Creates a List of {@link org.sonar.ce.task.projectanalysis.formula.SumFormula.IntSumFormula} for each
-     * metric key of the specified {@link NewCoverageOutputMetricKeys} instance.
-     */
-    private static Iterable<Formula<?>> variationSumFormulas(NewCoverageOutputMetricKeys outputMetricKeys) {
-      return ImmutableList.of(
-        new VariationSumFormula(outputMetricKeys.getNewLinesToCover()),
-        new VariationSumFormula(outputMetricKeys.getNewUncoveredLines()),
-        new VariationSumFormula(outputMetricKeys.getNewConditionsToCover()),
-        new VariationSumFormula(outputMetricKeys.getNewUncoveredConditions()));
-    }
-  }
-
   private static class NewCoverageFormula extends LinesAndConditionsWithUncoveredVariationFormula {
     public NewCoverageFormula() {
       super(
         new LinesAndConditionsWithUncoveredMetricKeys(
-          CoreMetrics.NEW_LINES_TO_COVER_KEY, CoreMetrics.NEW_CONDITIONS_TO_COVER_KEY,
-          CoreMetrics.NEW_UNCOVERED_LINES_KEY, CoreMetrics.NEW_UNCOVERED_CONDITIONS_KEY),
+          NEW_LINES_TO_COVER_KEY, NEW_CONDITIONS_TO_COVER_KEY,
+          NEW_UNCOVERED_LINES_KEY, NEW_UNCOVERED_CONDITIONS_KEY),
         CoreMetrics.NEW_COVERAGE_KEY);
     }
   }
@@ -153,7 +127,7 @@ public class NewCoverageMeasuresStep implements ComputationStep {
   private static class NewBranchCoverageFormula extends SingleWithUncoveredVariationFormula {
     public NewBranchCoverageFormula() {
       super(
-        new SingleWithUncoveredMetricKeys(CoreMetrics.NEW_CONDITIONS_TO_COVER_KEY, CoreMetrics.NEW_UNCOVERED_CONDITIONS_KEY),
+        new SingleWithUncoveredMetricKeys(NEW_CONDITIONS_TO_COVER_KEY, NEW_UNCOVERED_CONDITIONS_KEY),
         CoreMetrics.NEW_BRANCH_COVERAGE_KEY);
     }
   }
@@ -161,25 +135,39 @@ public class NewCoverageMeasuresStep implements ComputationStep {
   private static class NewLineCoverageFormula extends SingleWithUncoveredVariationFormula {
     public NewLineCoverageFormula() {
       super(
-        new SingleWithUncoveredMetricKeys(CoreMetrics.NEW_LINES_TO_COVER_KEY, CoreMetrics.NEW_UNCOVERED_LINES_KEY),
+        new SingleWithUncoveredMetricKeys(NEW_LINES_TO_COVER_KEY, NEW_UNCOVERED_LINES_KEY),
         CoreMetrics.NEW_LINE_COVERAGE_KEY);
     }
   }
 
-  public static class NewLinesAndConditionsFormula implements Formula<NewCoverageCounter> {
+  public static class NewLinesAndConditionsCoverageFormula implements Formula<NewCoverageCounter> {
     private final NewLinesRepository newLinesRepository;
-    private final NewCoverageInputMetricKeys inputMetricKeys;
-    private final NewCoverageOutputMetricKeys outputMetricKeys;
+    private final BatchReportReader reportReader;
+    private static final Iterable<Formula<?>> VIEWS_FORMULAS = variationSumFormulas();
 
-    public NewLinesAndConditionsFormula(NewLinesRepository newLinesRepository, NewCoverageInputMetricKeys inputMetricKeys, NewCoverageOutputMetricKeys outputMetricKeys) {
+    private NewLinesAndConditionsCoverageFormula(NewLinesRepository newLinesRepository, BatchReportReader reportReader) {
       this.newLinesRepository = newLinesRepository;
-      this.inputMetricKeys = inputMetricKeys;
-      this.outputMetricKeys = outputMetricKeys;
+      this.reportReader = reportReader;
+    }
+
+    public static Iterable<Formula<?>> from(@Nullable NewLinesRepository newLinesRepository, @Nullable BatchReportReader reportReader) {
+      if (newLinesRepository == null || reportReader == null) {
+        return VIEWS_FORMULAS;
+      }
+      return Collections.singleton(new NewLinesAndConditionsCoverageFormula(newLinesRepository, reportReader));
+    }
+
+    private static Iterable<Formula<?>> variationSumFormulas() {
+      return ImmutableList.of(
+        new VariationSumFormula(NEW_LINES_TO_COVER_KEY),
+        new VariationSumFormula(NEW_UNCOVERED_LINES_KEY),
+        new VariationSumFormula(NEW_CONDITIONS_TO_COVER_KEY),
+        new VariationSumFormula(NEW_UNCOVERED_CONDITIONS_KEY));
     }
 
     @Override
     public NewCoverageCounter createNewCounter() {
-      return new NewCoverageCounter(newLinesRepository, inputMetricKeys);
+      return new NewCoverageCounter(newLinesRepository, reportReader);
     }
 
     @Override
@@ -192,16 +180,16 @@ public class NewCoverageMeasuresStep implements ComputationStep {
     }
 
     private int computeValueForMetric(NewCoverageCounter counter, Metric metric) {
-      if (metric.getKey().equals(outputMetricKeys.getNewLinesToCover())) {
+      if (metric.getKey().equals(NEW_LINES_TO_COVER_KEY)) {
         return counter.getNewLines();
       }
-      if (metric.getKey().equals(outputMetricKeys.getNewUncoveredLines())) {
+      if (metric.getKey().equals(NEW_UNCOVERED_LINES_KEY)) {
         return counter.getNewLines() - counter.getNewCoveredLines();
       }
-      if (metric.getKey().equals(outputMetricKeys.getNewConditionsToCover())) {
+      if (metric.getKey().equals(NEW_CONDITIONS_TO_COVER_KEY)) {
         return counter.getNewConditions();
       }
-      if (metric.getKey().equals(outputMetricKeys.getNewUncoveredConditions())) {
+      if (metric.getKey().equals(NEW_UNCOVERED_CONDITIONS_KEY)) {
         return counter.getNewConditions() - counter.getNewCoveredConditions();
       }
       throw new IllegalArgumentException("Unsupported metric " + metric.getKey());
@@ -210,10 +198,10 @@ public class NewCoverageMeasuresStep implements ComputationStep {
     @Override
     public String[] getOutputMetricKeys() {
       return new String[] {
-        outputMetricKeys.getNewLinesToCover(),
-        outputMetricKeys.getNewUncoveredLines(),
-        outputMetricKeys.getNewConditionsToCover(),
-        outputMetricKeys.getNewUncoveredConditions()
+        NEW_LINES_TO_COVER_KEY,
+        NEW_UNCOVERED_LINES_KEY,
+        NEW_CONDITIONS_TO_COVER_KEY,
+        NEW_UNCOVERED_CONDITIONS_KEY
       };
     }
   }
@@ -224,11 +212,11 @@ public class NewCoverageMeasuresStep implements ComputationStep {
     private final IntValue newConditions = new IntValue();
     private final IntValue newCoveredConditions = new IntValue();
     private final NewLinesRepository newLinesRepository;
-    private final NewCoverageInputMetricKeys metricKeys;
+    private final BatchReportReader reportReader;
 
-    public NewCoverageCounter(NewLinesRepository newLinesRepository, NewCoverageInputMetricKeys metricKeys) {
+    public NewCoverageCounter(NewLinesRepository newLinesRepository, BatchReportReader reportReader) {
       this.newLinesRepository = newLinesRepository;
-      this.metricKeys = metricKeys;
+      this.reportReader = reportReader;
     }
 
     @Override
@@ -255,46 +243,25 @@ public class NewCoverageMeasuresStep implements ComputationStep {
       newConditions.increment(0);
       newCoveredConditions.increment(0);
 
-      Optional<Measure> hitsByLineMeasure = context.getMeasure(metricKeys.getCoverageLineHitsData());
-      Map<Integer, Integer> hitsByLine = parseCountByLine(hitsByLineMeasure);
-      Map<Integer, Integer> conditionsByLine = parseCountByLine(context.getMeasure(metricKeys.getConditionsByLine()));
-      Map<Integer, Integer> coveredConditionsByLine = parseCountByLine(context.getMeasure(metricKeys.getCoveredConditionsByLine()));
-
-      for (Map.Entry<Integer, Integer> entry : hitsByLine.entrySet()) {
-        int lineId = entry.getKey();
-        int hits = entry.getValue();
-        int conditions = (Integer) ObjectUtils.defaultIfNull(conditionsByLine.get(lineId), 0);
-        int coveredConditions = (Integer) ObjectUtils.defaultIfNull(coveredConditionsByLine.get(lineId), 0);
-        if (newLinesSet.get().contains(lineId)) {
-          analyze(hits, conditions, coveredConditions);
+      try (CloseableIterator<ScannerReport.LineCoverage> lineCoverage = reportReader.readComponentCoverage(component.getReportAttributes().getRef())) {
+        while (lineCoverage.hasNext()) {
+          final ScannerReport.LineCoverage line = lineCoverage.next();
+          int lineId = line.getLine();
+          if (newLinesSet.get().contains(lineId)) {
+            if (line.getHasHitsCase() == ScannerReport.LineCoverage.HasHitsCase.HITS) {
+              newLines.increment(1);
+              if (line.getHits()) {
+                newCoveredLines.increment(1);
+              }
+            }
+            if (line.getHasCoveredConditionsCase() == ScannerReport.LineCoverage.HasCoveredConditionsCase.COVERED_CONDITIONS) {
+              newConditions.increment(line.getConditions());
+              newCoveredConditions.increment(min(line.getCoveredConditions(), line.getConditions()));
+            }
+          }
         }
       }
-    }
-
-    private static Map<Integer, Integer> parseCountByLine(Optional<Measure> measure) {
-      if (measure.isPresent() && measure.get().getValueType() != Measure.ValueType.NO_VALUE) {
-        return KeyValueFormat.parseIntInt(measure.get().getStringValue());
-      }
-      return Collections.emptyMap();
-    }
 
-    void analyze(int hits, int conditions, int coveredConditions) {
-      incrementLines(hits);
-      incrementConditions(conditions, coveredConditions);
-    }
-
-    private void incrementLines(int hits) {
-      newLines.increment(1);
-      if (hits > 0) {
-        newCoveredLines.increment(1);
-      }
-    }
-
-    private void incrementConditions(int conditions, int coveredConditions) {
-      newConditions.increment(conditions);
-      if (conditions > 0) {
-        newCoveredConditions.increment(coveredConditions);
-      }
     }
 
     boolean hasNewCode() {
@@ -318,59 +285,4 @@ public class NewCoverageMeasuresStep implements ComputationStep {
     }
   }
 
-  @Immutable
-  public static final class NewCoverageOutputMetricKeys {
-    private final String newLinesToCover;
-    private final String newUncoveredLines;
-    private final String newConditionsToCover;
-    private final String newUncoveredConditions;
-
-    public NewCoverageOutputMetricKeys(String newLinesToCover, String newUncoveredLines, String newConditionsToCover, String newUncoveredConditions) {
-      this.newLinesToCover = newLinesToCover;
-      this.newUncoveredLines = newUncoveredLines;
-      this.newConditionsToCover = newConditionsToCover;
-      this.newUncoveredConditions = newUncoveredConditions;
-    }
-
-    public String getNewLinesToCover() {
-      return newLinesToCover;
-    }
-
-    public String getNewUncoveredLines() {
-      return newUncoveredLines;
-    }
-
-    public String getNewConditionsToCover() {
-      return newConditionsToCover;
-    }
-
-    public String getNewUncoveredConditions() {
-      return newUncoveredConditions;
-    }
-  }
-
-  @Immutable
-  public static class NewCoverageInputMetricKeys {
-    private final String coverageLineHitsData;
-    private final String conditionsByLine;
-    private final String coveredConditionsByLine;
-
-    public NewCoverageInputMetricKeys(String coverageLineHitsData, String conditionsByLine, String coveredConditionsByLine) {
-      this.coverageLineHitsData = coverageLineHitsData;
-      this.conditionsByLine = conditionsByLine;
-      this.coveredConditionsByLine = coveredConditionsByLine;
-    }
-
-    public String getCoverageLineHitsData() {
-      return coverageLineHitsData;
-    }
-
-    public String getConditionsByLine() {
-      return conditionsByLine;
-    }
-
-    public String getCoveredConditionsByLine() {
-      return coveredConditionsByLine;
-    }
-  }
 }
index c2c8b96f421ea484775b2e3cf98ebf8bc57d28ec..792ce499906bdef78258e1d5bbe14f7b9848a1dc 100644 (file)
@@ -99,7 +99,7 @@ public class BatchReportReaderImplTest {
 
   @Test
   public void verify_readComponentMeasures_returns_measures() {
-    writer.writeComponentMeasures(COMPONENT_REF, of(MEASURE));
+    writer.appendComponentMeasure(COMPONENT_REF, MEASURE);
 
     try (CloseableIterator<ScannerReport.Measure> measures = underTest.readComponentMeasures(COMPONENT_REF)) {
       assertThat(measures.next()).isEqualTo(MEASURE);
@@ -109,7 +109,7 @@ public class BatchReportReaderImplTest {
 
   @Test
   public void readComponentMeasures_is_not_cached() {
-    writer.writeComponentMeasures(COMPONENT_REF, of(MEASURE));
+    writer.appendComponentMeasure(COMPONENT_REF, MEASURE);
 
     assertThat(underTest.readComponentMeasures(COMPONENT_REF)).isNotSameAs(underTest.readComponentMeasures(COMPONENT_REF));
   }
index 6ddde6255350cd7fde710802544611667082ede5..052e07e127769d6b64ad5b610c1ca1759d257d9c 100644 (file)
@@ -23,6 +23,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.measures.CoreMetrics;
+import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
 import org.sonar.ce.task.projectanalysis.component.FileAttributes;
 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
 import org.sonar.ce.task.projectanalysis.formula.coverage.LinesAndConditionsWithUncoveredMetricKeys;
@@ -30,8 +31,14 @@ import org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry;
 import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
 import org.sonar.ce.task.step.TestComputationStepContext;
+import org.sonar.scanner.protocol.output.ScannerReport;
 
+import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.measures.CoreMetrics.CONDITIONS_TO_COVER_KEY;
+import static org.sonar.api.measures.CoreMetrics.LINES_TO_COVER_KEY;
+import static org.sonar.api.measures.CoreMetrics.UNCOVERED_CONDITIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES_KEY;
 import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
 import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
 import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT;
@@ -62,7 +69,10 @@ public class ReportCoverageMeasuresStepTest {
   @Rule
   public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
 
-  CoverageMeasuresStep underTest = new CoverageMeasuresStep(treeRootHolder, metricRepository, measureRepository);
+  @Rule
+  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+
+  CoverageMeasuresStep underTest = new CoverageMeasuresStep(treeRootHolder, metricRepository, measureRepository, reportReader);
 
   @Before
   public void setUp() throws Exception {
@@ -79,32 +89,33 @@ public class ReportCoverageMeasuresStepTest {
   }
 
   @Test
-  public void verify_aggregates_values_for_ut_lines_and_conditions() {
-    LinesAndConditionsWithUncoveredMetricKeys metricKeys = new LinesAndConditionsWithUncoveredMetricKeys(
-      CoreMetrics.LINES_TO_COVER_KEY, CoreMetrics.CONDITIONS_TO_COVER_KEY,
-      CoreMetrics.UNCOVERED_LINES_KEY, CoreMetrics.UNCOVERED_CONDITIONS_KEY);
-    verify_lines_and_conditions_aggregates_values(metricKeys);
-  }
-
-  private void verify_lines_and_conditions_aggregates_values(LinesAndConditionsWithUncoveredMetricKeys metricKeys) {
-    measureRepository
-      .addRawMeasure(FILE_1_REF, metricKeys.getLines(), newMeasureBuilder().create(3000))
-      .addRawMeasure(FILE_1_REF, metricKeys.getConditions(), newMeasureBuilder().create(300))
-      .addRawMeasure(FILE_1_REF, metricKeys.getUncoveredLines(), newMeasureBuilder().create(30))
-      .addRawMeasure(FILE_1_REF, metricKeys.getUncoveredConditions(), newMeasureBuilder().create(9))
-
-      .addRawMeasure(FILE_2_REF, metricKeys.getLines(), newMeasureBuilder().create(2000))
-      .addRawMeasure(FILE_2_REF, metricKeys.getConditions(), newMeasureBuilder().create(400))
-      .addRawMeasure(FILE_2_REF, metricKeys.getUncoveredLines(), newMeasureBuilder().create(200))
-      .addRawMeasure(FILE_2_REF, metricKeys.getUncoveredConditions(), newMeasureBuilder().create(16));
+  public void verify_aggregates_values_for_lines_and_conditions() {
+
+    reportReader.putCoverage(FILE_1_REF,
+      asList(
+        ScannerReport.LineCoverage.newBuilder().setLine(2).setHits(false).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(3).setHits(true).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(4).setHits(true).setConditions(4).setCoveredConditions(1).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(5).setConditions(8).setCoveredConditions(2).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(6).setHits(false).setConditions(3).setCoveredConditions(0).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(7).setHits(false).build()));
+
+    reportReader.putCoverage(FILE_2_REF,
+      asList(
+        ScannerReport.LineCoverage.newBuilder().setLine(2).setHits(true).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(3).setHits(false).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(5).setHits(true).setConditions(5).setCoveredConditions(1).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(6).setConditions(10).setCoveredConditions(3).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(7).setHits(false).setConditions(1).setCoveredConditions(0).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(8).setHits(false).build()));
 
     underTest.execute(new TestComputationStepContext());
 
     MeasureRepoEntry[] nonFileRepoEntries = {
-      entryOf(metricKeys.getLines(), newMeasureBuilder().create(5000)),
-      entryOf(metricKeys.getConditions(), newMeasureBuilder().create(700)),
-      entryOf(metricKeys.getUncoveredLines(), newMeasureBuilder().create(230)),
-      entryOf(metricKeys.getUncoveredConditions(), newMeasureBuilder().create(25))
+      entryOf(LINES_TO_COVER_KEY, newMeasureBuilder().create(5 + 5)),
+      entryOf(CONDITIONS_TO_COVER_KEY, newMeasureBuilder().create(4 + 8 + 3 + 5 + 10 + 1)),
+      entryOf(UNCOVERED_LINES_KEY, newMeasureBuilder().create(3 + 3)),
+      entryOf(UNCOVERED_CONDITIONS_KEY, newMeasureBuilder().create(3 + 6 + 3 + 4 + 7 + 1))
     };
 
     assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_REF))).contains(nonFileRepoEntries);
@@ -114,8 +125,8 @@ public class ReportCoverageMeasuresStepTest {
   @Test
   public void verify_aggregates_values_for_code_line_and_branch_coverage() {
     LinesAndConditionsWithUncoveredMetricKeys metricKeys = new LinesAndConditionsWithUncoveredMetricKeys(
-      CoreMetrics.LINES_TO_COVER_KEY, CoreMetrics.CONDITIONS_TO_COVER_KEY,
-      CoreMetrics.UNCOVERED_LINES_KEY, CoreMetrics.UNCOVERED_CONDITIONS_KEY);
+      LINES_TO_COVER_KEY, CONDITIONS_TO_COVER_KEY,
+      UNCOVERED_LINES_KEY, UNCOVERED_CONDITIONS_KEY);
     String codeCoverageKey = CoreMetrics.COVERAGE_KEY;
     String lineCoverageKey = CoreMetrics.LINE_COVERAGE_KEY;
     String branchCoverageKey = CoreMetrics.BRANCH_COVERAGE_KEY;
index 3fe2036216c85687d4cb227ef6e7de7aac47c5a2..9721f72e7a0d20b533844e73b932eef8c41d080d 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.ce.task.projectanalysis.step;
 
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Optional;
@@ -27,6 +26,7 @@ import java.util.Set;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.measures.CoreMetrics;
+import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.FileAttributes;
 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
@@ -38,14 +38,13 @@ import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
 import org.sonar.ce.task.projectanalysis.source.NewLinesRepository;
 import org.sonar.ce.task.step.TestComputationStepContext;
+import org.sonar.scanner.protocol.output.ScannerReport;
 
+import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.guava.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_BY_LINE_KEY;
-import static org.sonar.api.measures.CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY;
-import static org.sonar.api.measures.CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY;
 import static org.sonar.api.measures.CoreMetrics.NEW_CONDITIONS_TO_COVER_KEY;
 import static org.sonar.api.measures.CoreMetrics.NEW_LINES_TO_COVER_KEY;
 import static org.sonar.api.measures.CoreMetrics.NEW_UNCOVERED_CONDITIONS_KEY;
@@ -84,9 +83,6 @@ public class ReportNewCoverageMeasuresStepTest {
   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
   @Rule
   public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(CoreMetrics.COVERAGE_LINE_HITS_DATA)
-    .add(CoreMetrics.CONDITIONS_BY_LINE)
-    .add(CoreMetrics.COVERED_CONDITIONS_BY_LINE)
     .add(CoreMetrics.NEW_LINES_TO_COVER)
     .add(CoreMetrics.NEW_UNCOVERED_LINES)
     .add(CoreMetrics.NEW_CONDITIONS_TO_COVER)
@@ -97,8 +93,12 @@ public class ReportNewCoverageMeasuresStepTest {
 
   @Rule
   public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+  @Rule
+  public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+
   private NewLinesRepository newLinesRepository = mock(NewLinesRepository.class);
-  private NewCoverageMeasuresStep underTest = new NewCoverageMeasuresStep(treeRootHolder, measureRepository, metricRepository, newLinesRepository);
+  private NewCoverageMeasuresStep underTest = new NewCoverageMeasuresStep(treeRootHolder, measureRepository, metricRepository, newLinesRepository, reportReader);
   public static final ReportComponent FILE_COMPONENT = ReportComponent.builder(Component.Type.FILE, FILE_1_REF)
     .setFileAttributes(new FileAttributes(false, null, 1)).build();
 
@@ -143,9 +143,11 @@ public class ReportNewCoverageMeasuresStepTest {
     treeRootHolder.setRoot(FILE_COMPONENT);
     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
     when(newLinesRepository.getNewLines(FILE_COMPONENT)).thenReturn(Optional.of(Collections.emptySet()));
-    measureRepository.addRawMeasure(FILE_COMPONENT.getReportAttributes().getRef(), COVERAGE_LINE_HITS_DATA_KEY, newMeasureBuilder().create("2=1;3=1"));
-    measureRepository.addRawMeasure(FILE_COMPONENT.getReportAttributes().getRef(), CONDITIONS_BY_LINE_KEY, newMeasureBuilder().create("2=1"));
-    measureRepository.addRawMeasure(FILE_COMPONENT.getReportAttributes().getRef(), COVERED_CONDITIONS_BY_LINE_KEY, newMeasureBuilder().create("2=1"));
+
+    reportReader.putCoverage(FILE_COMPONENT.getReportAttributes().getRef(),
+      asList(
+        ScannerReport.LineCoverage.newBuilder().setLine(2).setHits(true).setConditions(1).setCoveredConditions(1).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(3).setHits(true).build()));
 
     underTest.execute(new TestComputationStepContext());
 
@@ -166,106 +168,90 @@ public class ReportNewCoverageMeasuresStepTest {
   public void verify_computation_of_measures_for_new_lines_for_FILE() {
     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
 
-    String coverageLineHitsData = COVERAGE_LINE_HITS_DATA_KEY;
-    String newLinesToCover = NEW_LINES_TO_COVER_KEY;
-    String newUncoveredLines = NEW_UNCOVERED_LINES_KEY;
-    String newConditionsToCover = NEW_CONDITIONS_TO_COVER_KEY;
-    String newUncoveredConditions = NEW_UNCOVERED_CONDITIONS_KEY;
-
-    verify_computation_of_measures_for_new_lines(coverageLineHitsData,
-      newLinesToCover, newUncoveredLines, newConditionsToCover, newUncoveredConditions);
-  }
-
-  private void verify_computation_of_measures_for_new_lines(String coverageLineHitsData,
-    String newLinesToCover, String newUncoveredLines, String newConditionsToCover, String newUncoveredConditions) {
     treeRootHolder.setRoot(FILE_COMPONENT);
     setNewLines(FILE_1, 1, 2, 4);
 
-    measureRepository.addRawMeasure(FILE_COMPONENT.getReportAttributes().getRef(), coverageLineHitsData, newMeasureBuilder().create("2=0;3=2;4=3"));
+    reportReader.putCoverage(FILE_COMPONENT.getReportAttributes().getRef(),
+      asList(
+        ScannerReport.LineCoverage.newBuilder().setLine(2).setHits(false).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(3).setHits(true).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(4).setHits(true).build()));
 
     underTest.execute(new TestComputationStepContext());
 
     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_COMPONENT.getReportAttributes().getRef()))).contains(
-      entryOf(newLinesToCover, createMeasure(2d)),
-      entryOf(newUncoveredLines, createMeasure(1d)),
-      entryOf(newConditionsToCover, createMeasure(0d)),
-      entryOf(newUncoveredConditions, createMeasure(0d)));
+      entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(2d)),
+      entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(1d)),
+      entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(0d)),
+      entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(0d)));
   }
 
   @Test
   public void verify_computation_of_measures_for_new_conditions_for_FILE() {
     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
-
-    String coverageLineHitsData = COVERAGE_LINE_HITS_DATA_KEY;
-    String conditionsByLine = CONDITIONS_BY_LINE_KEY;
-    String coveredConditionsByLine = COVERED_CONDITIONS_BY_LINE_KEY;
-    String newLinesToCover = NEW_LINES_TO_COVER_KEY;
-    String newUncoveredLines = NEW_UNCOVERED_LINES_KEY;
-    String newConditionsToCover = NEW_CONDITIONS_TO_COVER_KEY;
-    String newUncoveredConditions = NEW_UNCOVERED_CONDITIONS_KEY;
-
-    verify_computation_of_measures_for_new_conditions(new MetricKeys(coverageLineHitsData, conditionsByLine, coveredConditionsByLine,
-      newLinesToCover, newUncoveredLines, newConditionsToCover, newUncoveredConditions));
+    verify_computation_of_measures_for_new_conditions();
   }
 
   @Test
   public void verify_aggregation_of_measures_for_new_conditions() {
     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
 
-    String coverageLineHitsData = CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY;
-    String conditionsByLine = CoreMetrics.CONDITIONS_BY_LINE_KEY;
-    String coveredConditionsByLine = CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY;
-    String newLinesToCover = NEW_LINES_TO_COVER_KEY;
-    String newUncoveredLines = NEW_UNCOVERED_LINES_KEY;
-    String newConditionsToCover = NEW_CONDITIONS_TO_COVER_KEY;
-    String newUncoveredConditions = NEW_UNCOVERED_CONDITIONS_KEY;
-
-    MetricKeys metricKeys = new MetricKeys(coverageLineHitsData, conditionsByLine, coveredConditionsByLine,
-      newLinesToCover, newUncoveredLines, newConditionsToCover, newUncoveredConditions);
-
     treeRootHolder.setRoot(MULTIPLE_FILES_TREE);
-    defineNewLinesAndMeasures(FILE_1, metricKeys, new MeasureValues(3, 4, 1), new MeasureValues(0, 3, 2));
-    defineNewLinesAndMeasures(FILE_2, metricKeys, new MeasureValues(0, 14, 6), new MeasureValues(0, 13, 7));
-    defineNewLinesAndMeasures(FILE_3, metricKeys, new MeasureValues(3, 4, 1), new MeasureValues(1, 13, 7));
+    defineNewLinesAndLineCoverage(FILE_1, new LineCoverageValues(3, 4, 1), new LineCoverageValues(0, 3, 2));
+    defineNewLinesAndLineCoverage(FILE_2, new LineCoverageValues(0, 14, 6), new LineCoverageValues(0, 13, 7));
+    defineNewLinesAndLineCoverage(FILE_3, new LineCoverageValues(3, 4, 1), new LineCoverageValues(1, 13, 7));
 
     underTest.execute(new TestComputationStepContext());
 
     // files
     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).contains(
-      entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
-      entryOf(metricKeys.newUncoveredLines, createMeasure(3d)),
-      entryOf(metricKeys.newConditionsToCover, createMeasure(7d)),
-      entryOf(metricKeys.newUncoveredConditions, createMeasure(4d)));
+      entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
+      entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(3d)),
+      entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(7d)),
+      entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(4d)));
     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).contains(
-      entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
-      entryOf(metricKeys.newUncoveredLines, createMeasure(4d)),
-      entryOf(metricKeys.newConditionsToCover, createMeasure(27d)),
-      entryOf(metricKeys.newUncoveredConditions, createMeasure(14d)));
+      entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
+      entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(4d)),
+      entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(27d)),
+      entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(14d)));
     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_3_REF))).contains(
-      entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
-      entryOf(metricKeys.newUncoveredLines, createMeasure(2d)),
-      entryOf(metricKeys.newConditionsToCover, createMeasure(17d)),
-      entryOf(metricKeys.newUncoveredConditions, createMeasure(9d)));
+      entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
+      entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(2d)),
+      entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(17d)),
+      entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(9d)));
     // directories
     assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_1_REF))).contains(
-      entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
-      entryOf(metricKeys.newUncoveredLines, createMeasure(3d)),
-      entryOf(metricKeys.newConditionsToCover, createMeasure(7d)),
-      entryOf(metricKeys.newUncoveredConditions, createMeasure(4d)));
+      entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
+      entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(3d)),
+      entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(7d)),
+      entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(4d)));
     assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_2_REF))).contains(
-      entryOf(metricKeys.newLinesToCover, createMeasure(10d)),
-      entryOf(metricKeys.newUncoveredLines, createMeasure(6d)),
-      entryOf(metricKeys.newConditionsToCover, createMeasure(44d)),
-      entryOf(metricKeys.newUncoveredConditions, createMeasure(23d)));
+      entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(10d)),
+      entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(6d)),
+      entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(44d)),
+      entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(23d)));
     // submodule
-    MeasureRepoEntry[] repoEntriesFromProject = {entryOf(metricKeys.newLinesToCover, createMeasure(15d)),
-      entryOf(metricKeys.newUncoveredLines, createMeasure(9d)),
-      entryOf(metricKeys.newConditionsToCover, createMeasure(51d)),
-      entryOf(metricKeys.newUncoveredConditions, createMeasure(27d))};
+    MeasureRepoEntry[] repoEntriesFromProject = {entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(15d)),
+      entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(9d)),
+      entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(51d)),
+      entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(27d))};
     // project
     assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).contains(repoEntriesFromProject);
   }
 
+  private void defineNewLinesAndLineCoverage(Component c, LineCoverageValues line4, LineCoverageValues line6) {
+    setNewLines(c, 1, 2, 4, 5, 6, 7);
+
+    reportReader.putCoverage(c.getReportAttributes().getRef(),
+      asList(
+        ScannerReport.LineCoverage.newBuilder().setLine(2).setHits(false).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(3).setHits(true).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(4).setHits(line4.lineHits > 0).setConditions(line4.conditions).setCoveredConditions(line4.coveredConditions).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(5).setHits(true).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(6).setHits(line6.lineHits > 0).setConditions(line6.conditions).setCoveredConditions(line6.coveredConditions).build(),
+        ScannerReport.LineCoverage.newBuilder().setLine(7).setHits(false).build()));
+  }
+
   @Test
   public void verify_aggregates_variations_for_new_code_line_and_branch_Coverage() {
     LinesAndConditionsWithUncoveredMetricKeys metricKeys = new LinesAndConditionsWithUncoveredMetricKeys(
@@ -330,60 +316,29 @@ public class ReportNewCoverageMeasuresStepTest {
       entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(0d)));
   }
 
-  private void defineNewLinesAndMeasures(Component c, MetricKeys metricKeys, MeasureValues line4, MeasureValues line6) {
-    setNewLines(c, 1, 2, 4, 5, 6, 7);
-    measureRepository.addRawMeasure(c.getReportAttributes().getRef(), metricKeys.coverageLineHitsData,
-      newMeasureBuilder().create("2=0;3=2;4=" + line4.lineHits + ";5=1;6=" + line6.lineHits + ";7=0"));
-    measureRepository
-      .addRawMeasure(c.getReportAttributes().getRef(), metricKeys.conditionsByLine, newMeasureBuilder().create("4=" + line4.coveredConditions + ";6=" + line6.coveredConditions));
-    measureRepository.addRawMeasure(c.getReportAttributes().getRef(), metricKeys.coveredConditionsByLine,
-      newMeasureBuilder().create("4=" + line4.uncoveredConditions + ";6=" + line6.uncoveredConditions));
-  }
-
-  private static final class MetricKeys {
-    private final String coverageLineHitsData;
-    private final String conditionsByLine;
-    private final String coveredConditionsByLine;
-    private final String newLinesToCover;
-    private final String newUncoveredLines;
-    private final String newConditionsToCover;
-    private final String newUncoveredConditions;
-
-    public MetricKeys(String coverageLineHitsData, String conditionsByLine, String coveredConditionsByLine,
-      String newLinesToCover, String newUncoveredLines, String newConditionsToCover, String newUncoveredConditions) {
-      this.coverageLineHitsData = coverageLineHitsData;
-      this.conditionsByLine = conditionsByLine;
-      this.coveredConditionsByLine = coveredConditionsByLine;
-      this.newLinesToCover = newLinesToCover;
-      this.newUncoveredLines = newUncoveredLines;
-      this.newConditionsToCover = newConditionsToCover;
-      this.newUncoveredConditions = newUncoveredConditions;
-    }
-  }
-
-  private static final class MeasureValues {
+  private static final class LineCoverageValues {
     private final int lineHits;
+    private final int conditions;
     private final int coveredConditions;
-    private final int uncoveredConditions;
 
-    public MeasureValues(int lineHits, int coveredConditions, int uncoveredConditions) {
+    public LineCoverageValues(int lineHits, int conditions, int coveredConditions) {
       this.lineHits = lineHits;
+      this.conditions = conditions;
       this.coveredConditions = coveredConditions;
-      this.uncoveredConditions = uncoveredConditions;
     }
   }
 
-  private void verify_computation_of_measures_for_new_conditions(MetricKeys metricKeys) {
+  private void verify_computation_of_measures_for_new_conditions() {
     treeRootHolder.setRoot(FILE_COMPONENT);
-    defineNewLinesAndMeasures(FILE_COMPONENT, metricKeys, new MeasureValues(3, 4, 1), new MeasureValues(0, 3, 2));
+    defineNewLinesAndLineCoverage(FILE_COMPONENT, new LineCoverageValues(3, 4, 1), new LineCoverageValues(0, 3, 2));
 
     underTest.execute(new TestComputationStepContext());
 
     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_COMPONENT.getReportAttributes().getRef()))).contains(
-      entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
-      entryOf(metricKeys.newUncoveredLines, createMeasure(3d)),
-      entryOf(metricKeys.newConditionsToCover, createMeasure(7d)),
-      entryOf(metricKeys.newUncoveredConditions, createMeasure(4d)));
+      entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(5d)),
+      entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(3d)),
+      entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(7d)),
+      entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(4d)));
   }
 
   private static Measure createMeasure(Double expectedVariation) {
@@ -394,7 +349,7 @@ public class ReportNewCoverageMeasuresStepTest {
 
   private void setNewLines(Component c, Integer... lines) {
     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
-    Set<Integer> newLines = new HashSet<>(Arrays.asList(lines));
+    Set<Integer> newLines = new HashSet<>(asList(lines));
     when(newLinesRepository.getNewLines(c)).thenReturn(Optional.of(newLines));
   }
 }
index 90bfbfc1312850ef9cd917ec1975ac07df21958a..110b509e90135079c3290d5c64a6ca3797585c99 100644 (file)
@@ -28,12 +28,10 @@ import org.sonar.ce.task.projectanalysis.formula.coverage.LinesAndConditionsWith
 import org.sonar.ce.task.projectanalysis.measure.Measure;
 import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
-import org.sonar.ce.task.projectanalysis.source.NewLinesRepository;
 import org.sonar.ce.task.step.TestComputationStepContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.guava.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
 import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT_VIEW;
 import static org.sonar.ce.task.projectanalysis.component.Component.Type.SUBVIEW;
 import static org.sonar.ce.task.projectanalysis.component.Component.Type.VIEW;
@@ -75,9 +73,6 @@ public class ViewsNewCoverageMeasuresStepTest {
 
   @Rule
   public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
-    .add(CoreMetrics.COVERAGE_LINE_HITS_DATA)
-    .add(CoreMetrics.CONDITIONS_BY_LINE)
-    .add(CoreMetrics.COVERED_CONDITIONS_BY_LINE)
     .add(CoreMetrics.NEW_LINES_TO_COVER)
     .add(CoreMetrics.NEW_UNCOVERED_LINES)
     .add(CoreMetrics.NEW_CONDITIONS_TO_COVER)
index ee6830f2100770856e1a3e8ea011e05baca730f6..63ddb0b92c39420507c3c9e9faa61b6e96f66fc5 100644 (file)
@@ -26,10 +26,10 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Stream;
 import javax.annotation.concurrent.Immutable;
-import org.sonar.api.scanner.ScannerSide;
 import org.sonar.api.ce.ComputeEngineSide;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.measures.Metrics;
+import org.sonar.api.scanner.ScannerSide;
 
 import static org.sonar.api.measures.CoreMetrics.CLASSES;
 import static org.sonar.api.measures.CoreMetrics.COGNITIVE_COMPLEXITY;
@@ -37,22 +37,14 @@ import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES;
 import static org.sonar.api.measures.CoreMetrics.COMPLEXITY;
 import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_CLASSES;
 import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_FUNCTIONS;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.COVERAGE_LINE_HITS_DATA;
-import static org.sonar.api.measures.CoreMetrics.COVERED_CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.DIRECTORIES;
 import static org.sonar.api.measures.CoreMetrics.EXECUTABLE_LINES_DATA;
-import static org.sonar.api.measures.CoreMetrics.FILES;
 import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION;
 import static org.sonar.api.measures.CoreMetrics.FUNCTIONS;
 import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION;
 import static org.sonar.api.measures.CoreMetrics.GENERATED_LINES;
 import static org.sonar.api.measures.CoreMetrics.GENERATED_NCLOC;
-import static org.sonar.api.measures.CoreMetrics.LINES_TO_COVER;
 import static org.sonar.api.measures.CoreMetrics.NCLOC;
 import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA;
-import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION;
 import static org.sonar.api.measures.CoreMetrics.PUBLIC_API;
 import static org.sonar.api.measures.CoreMetrics.PUBLIC_UNDOCUMENTED_API;
 import static org.sonar.api.measures.CoreMetrics.SKIPPED_TESTS;
@@ -61,8 +53,6 @@ import static org.sonar.api.measures.CoreMetrics.TESTS;
 import static org.sonar.api.measures.CoreMetrics.TEST_ERRORS;
 import static org.sonar.api.measures.CoreMetrics.TEST_EXECUTION_TIME;
 import static org.sonar.api.measures.CoreMetrics.TEST_FAILURES;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_CONDITIONS;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES;
 import static org.sonar.core.util.stream.MoreCollectors.toSet;
 
 /**
@@ -81,13 +71,10 @@ public class ScannerMetrics {
     NCLOC_DATA,
     GENERATED_NCLOC,
     COMMENT_LINES,
-    NCLOC_LANGUAGE_DISTRIBUTION,
 
     PUBLIC_API,
     PUBLIC_UNDOCUMENTED_API,
 
-    FILES,
-    DIRECTORIES,
     CLASSES,
     FUNCTIONS,
     STATEMENTS,
@@ -105,14 +92,6 @@ public class ScannerMetrics {
     TEST_FAILURES,
     TEST_EXECUTION_TIME,
 
-    LINES_TO_COVER,
-    UNCOVERED_LINES,
-    COVERAGE_LINE_HITS_DATA,
-    CONDITIONS_TO_COVER,
-    UNCOVERED_CONDITIONS,
-    COVERED_CONDITIONS_BY_LINE,
-    CONDITIONS_BY_LINE,
-
     EXECUTABLE_LINES_DATA);
 
   private final Set<Metric> metrics;
index 38e4f9fd4a8e33505a98853356dd6649335a3cc8..b0599f24be27eaf802fec2a1861470be0c11ec23 100644 (file)
@@ -35,7 +35,7 @@ public class ScannerMetricsTest {
 
   @Test
   public void check_number_of_allowed_core_metrics() {
-    assertThat(SENSOR_METRICS_WITHOUT_METRIC_PLUGIN).hasSize(32);
+    assertThat(SENSOR_METRICS_WITHOUT_METRIC_PLUGIN).hasSize(22);
   }
 
   @Test
index 9908523fc9ab5a24807176094a354d6377453074..19a5cce029bd79058d6641a0123a5573a63fda81 100644 (file)
  */
 package org.sonar.api.batch.fs.internal;
 
+import java.util.HashSet;
+import java.util.Set;
 import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.measure.Metric;
 
 /**
  * @since 5.2
  */
 public abstract class DefaultInputComponent implements InputComponent {
   private int id;
+  private Set<String> storedMetricKeys = new HashSet<>();
 
   public DefaultInputComponent(int scannerId) {
     this.id = scannerId;
@@ -57,4 +61,12 @@ public abstract class DefaultInputComponent implements InputComponent {
   public String toString() {
     return "[key=" + key() + "]";
   }
+
+  public void setHasMeasureFor(Metric metric) {
+    storedMetricKeys.add(metric.key());
+  }
+
+  public boolean hasMeasureFor(Metric metric) {
+    return storedMetricKeys.contains(metric.key());
+  }
 }
index c0fd7c38bcce7a60efdf6ad88c209a5491946438..cf72686859d9124e7bfa20f284af11a6be9c7449 100644 (file)
@@ -31,10 +31,12 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.apache.commons.io.ByteOrderMark;
@@ -43,6 +45,8 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.TextPointer;
 import org.sonar.api.batch.fs.TextRange;
 
+import static com.google.common.base.Preconditions.checkState;
+
 /**
  * @since 4.2
  * To create {@link InputFile} in tests, use {@link TestInputFileBuilder}.
@@ -55,15 +59,17 @@ public class DefaultInputFile extends DefaultInputComponent implements InputFile
   private final String contents;
   private final Consumer<DefaultInputFile> metadataGenerator;
 
-  private Status status;
-  private Charset charset;
-  private Metadata metadata;
   private boolean published;
   private boolean excludedForCoverage;
   private boolean excludedForDuplication;
-  private final Set<Integer> noSonarLines = new HashSet<>();
   private boolean ignoreAllIssues;
-  private Collection<int[]> ignoreIssuesOnlineRanges = new ArrayList<>();
+  // Lazy init to save memory
+  private BitSet noSonarLines;
+  private Status status;
+  private Charset charset;
+  private Metadata metadata;
+  private Collection<int[]> ignoreIssuesOnlineRanges;
+  private BitSet executableLines;
 
   public DefaultInputFile(DefaultIndexedFile indexedFile, Consumer<DefaultInputFile> metadataGenerator) {
     this(indexedFile, metadataGenerator, null);
@@ -90,7 +96,7 @@ public class DefaultInputFile extends DefaultInputComponent implements InputFile
   public InputStream inputStream() throws IOException {
     return contents != null ? new ByteArrayInputStream(contents.getBytes(charset()))
       : new BOMInputStream(Files.newInputStream(path()),
-      ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
+        ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
   }
 
   @Override
@@ -245,16 +251,16 @@ public class DefaultInputFile extends DefaultInputComponent implements InputFile
 
   public int[] originalLineStartOffsets() {
     checkMetadata();
-    Preconditions.checkState(metadata.originalLineStartOffsets() != null, "InputFile is not properly initialized.");
-    Preconditions.checkState(metadata.originalLineStartOffsets().length == metadata.lines(),
+    checkState(metadata.originalLineStartOffsets() != null, "InputFile is not properly initialized.");
+    checkState(metadata.originalLineStartOffsets().length == metadata.lines(),
       "InputFile is not properly initialized. 'originalLineStartOffsets' property length should be equal to 'lines'");
     return metadata.originalLineStartOffsets();
   }
 
   public int[] originalLineEndOffsets() {
     checkMetadata();
-    Preconditions.checkState(metadata.originalLineEndOffsets() != null, "InputFile is not properly initialized.");
-    Preconditions.checkState(metadata.originalLineEndOffsets().length == metadata.lines(),
+    checkState(metadata.originalLineEndOffsets() != null, "InputFile is not properly initialized.");
+    checkState(metadata.originalLineEndOffsets().length == metadata.lines(),
       "InputFile is not properly initialized. 'originalLineEndOffsets' property length should be equal to 'lines'");
     return metadata.originalLineEndOffsets();
   }
@@ -383,11 +389,17 @@ public class DefaultInputFile extends DefaultInputComponent implements InputFile
   }
 
   public void noSonarAt(Set<Integer> noSonarLines) {
-    this.noSonarLines.addAll(noSonarLines);
+    if (this.noSonarLines == null) {
+      this.noSonarLines = new BitSet(lines());
+    }
+    noSonarLines.forEach(l -> this.noSonarLines.set(l - 1));
   }
 
   public boolean hasNoSonarAt(int line) {
-    return this.noSonarLines.contains(line);
+    if (this.noSonarLines == null) {
+      return false;
+    }
+    return this.noSonarLines.get(line - 1);
   }
 
   public boolean isIgnoreAllIssues() {
@@ -399,13 +411,29 @@ public class DefaultInputFile extends DefaultInputComponent implements InputFile
   }
 
   public void addIgnoreIssuesOnLineRanges(Collection<int[]> lineRanges) {
+    if (this.ignoreIssuesOnlineRanges == null) {
+      this.ignoreIssuesOnlineRanges = new ArrayList<>();
+    }
     this.ignoreIssuesOnlineRanges.addAll(lineRanges);
   }
 
   public boolean isIgnoreAllIssuesOnLine(@Nullable Integer line) {
-    if (line == null) {
+    if (line == null || ignoreIssuesOnlineRanges == null) {
       return false;
     }
     return ignoreIssuesOnlineRanges.stream().anyMatch(r -> r[0] <= line && line <= r[1]);
   }
+
+  public void setExecutableLines(Set<Integer> executableLines) {
+    checkState(this.executableLines == null, "Executable lines have already been saved for file: {}", this.toString());
+    this.executableLines = new BitSet(lines());
+    executableLines.forEach(l -> this.executableLines.set(l - 1));
+  }
+
+  public Optional<Set<Integer>> getExecutableLines() {
+    if (this.executableLines == null) {
+      return Optional.empty();
+    }
+    return Optional.of(this.executableLines.stream().map(i -> i + 1).boxed().collect(Collectors.toSet()));
+  }
 }
index de201f005970e5e166645161b77438c677a5aed3..c63f94ce6eb2b4a83fef2da1fc860ea739e7d91a 100644 (file)
  */
 package org.sonar.api.batch.sensor.coverage;
 
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import org.sonar.api.measures.Metric;
-
-import static java.util.Arrays.asList;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.COVERAGE_LINE_HITS_DATA;
-import static org.sonar.api.measures.CoreMetrics.COVERED_CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.IT_CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.IT_CONDITIONS_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.IT_COVERAGE_LINE_HITS_DATA;
-import static org.sonar.api.measures.CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.IT_LINES_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.IT_UNCOVERED_CONDITIONS;
-import static org.sonar.api.measures.CoreMetrics.IT_UNCOVERED_LINES;
-import static org.sonar.api.measures.CoreMetrics.LINES_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_CONDITIONS_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_LINES_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_UNCOVERED_CONDITIONS;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_UNCOVERED_LINES;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_CONDITIONS;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES;
-
 /**
  * Different coverage categories.
  * @since 5.2
@@ -56,63 +28,8 @@ import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES;
 @Deprecated
 public enum CoverageType {
 
-  UNIT(LINES_TO_COVER, UNCOVERED_LINES, COVERAGE_LINE_HITS_DATA, CONDITIONS_TO_COVER, UNCOVERED_CONDITIONS, COVERED_CONDITIONS_BY_LINE, CONDITIONS_BY_LINE),
-  IT(IT_LINES_TO_COVER, IT_UNCOVERED_LINES, IT_COVERAGE_LINE_HITS_DATA, IT_CONDITIONS_TO_COVER, IT_UNCOVERED_CONDITIONS, IT_COVERED_CONDITIONS_BY_LINE, IT_CONDITIONS_BY_LINE),
-  OVERALL(OVERALL_LINES_TO_COVER, OVERALL_UNCOVERED_LINES, OVERALL_COVERAGE_LINE_HITS_DATA, OVERALL_CONDITIONS_TO_COVER, OVERALL_UNCOVERED_CONDITIONS,
-    OVERALL_COVERED_CONDITIONS_BY_LINE, OVERALL_CONDITIONS_BY_LINE);
-
-  private final Metric linesToCover;
-  private final Metric uncoveredLines;
-  private final Metric lineHitsData;
-  private final Metric conditionsToCover;
-  private final Metric uncoveredConditions;
-  private final Metric coveredConditionsByLine;
-  private final Metric conditionsByLine;
-  private final Set<Metric> all;
-
-  CoverageType(Metric linesToCover, Metric uncoveredLines, Metric lineHitsData, Metric conditionsToCover, Metric uncoveredConditions, Metric coveredConditionsByLine,
-    Metric conditionsByLine) {
-    this.linesToCover = linesToCover;
-    this.uncoveredLines = uncoveredLines;
-    this.lineHitsData = lineHitsData;
-    this.conditionsToCover = conditionsToCover;
-    this.uncoveredConditions = uncoveredConditions;
-    this.coveredConditionsByLine = coveredConditionsByLine;
-    this.conditionsByLine = conditionsByLine;
-    this.all = Collections.unmodifiableSet(new LinkedHashSet<>(
-      asList(linesToCover, uncoveredLines, lineHitsData, conditionsToCover, uncoveredConditions, coveredConditionsByLine, conditionsByLine)));
-  }
-
-  public Set<Metric> allMetrics() {
-    return all;
-  }
-
-  public Metric linesToCover() {
-    return linesToCover;
-  }
-
-  public Metric uncoveredLines() {
-    return uncoveredLines;
-  }
-
-  public Metric lineHitsData() {
-    return lineHitsData;
-  }
-
-  public Metric conditionsToCover() {
-    return conditionsToCover;
-  }
-
-  public Metric uncoveredConditions() {
-    return uncoveredConditions;
-  }
-
-  public Metric coveredConditionsByLine() {
-    return coveredConditionsByLine;
-  }
-
-  public Metric conditionsByLine() {
-    return conditionsByLine;
-  }
+  UNIT,
+  IT,
+  OVERALL;
 
 }
index b04a30671caf263138a80f927e363bf59dca522e..d15be6890ac03c26f37ca693fb117a001840e2d1 100644 (file)
@@ -538,9 +538,6 @@ public final class CoreMetrics {
 
   public static final String LINES_TO_COVER_KEY = "lines_to_cover";
 
-  /**
-   * Use {@link CoverageMeasuresBuilder} to build measure for this metric.
-   */
   public static final Metric<Integer> LINES_TO_COVER = new Metric.Builder(LINES_TO_COVER_KEY, "Lines to Cover", Metric.ValueType.INT)
     .setDescription("Lines to cover")
     .setDirection(Metric.DIRECTION_WORST)
@@ -559,9 +556,6 @@ public final class CoreMetrics {
 
   public static final String UNCOVERED_LINES_KEY = "uncovered_lines";
 
-  /**
-   * Use {@link CoverageMeasuresBuilder} to build measure for this metric.
-   */
   public static final Metric<Integer> UNCOVERED_LINES = new Metric.Builder(UNCOVERED_LINES_KEY, "Uncovered Lines", Metric.ValueType.INT)
     .setDescription("Uncovered lines")
     .setDirection(Metric.DIRECTION_WORST)
@@ -599,30 +593,8 @@ public final class CoreMetrics {
     .setDeleteHistoricalData(true)
     .create();
 
-  /**
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final String COVERAGE_LINE_HITS_DATA_KEY = "coverage_line_hits_data";
-
-  /**
-   * Key-value pairs, where key - is a number of line, and value - is a number of hits for this line.
-   * Use {@link CoverageMeasuresBuilder} to build measure for this metric.
-   *
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final Metric<String> COVERAGE_LINE_HITS_DATA = new Metric.Builder(COVERAGE_LINE_HITS_DATA_KEY, "Coverage Hits by Line", Metric.ValueType.DATA)
-    .setDescription("Coverage hits by line")
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .create();
-
   public static final String CONDITIONS_TO_COVER_KEY = "conditions_to_cover";
 
-  /**
-   * Use {@link CoverageMeasuresBuilder} to build measure for this metric.
-   */
   public static final Metric<Integer> CONDITIONS_TO_COVER = new Metric.Builder(CONDITIONS_TO_COVER_KEY, "Conditions to Cover", Metric.ValueType.INT)
     .setDescription("Conditions to cover")
     .setDomain(DOMAIN_COVERAGE)
@@ -639,9 +611,6 @@ public final class CoreMetrics {
 
   public static final String UNCOVERED_CONDITIONS_KEY = "uncovered_conditions";
 
-  /**
-   * Use {@link CoverageMeasuresBuilder} to build measure for this metric.
-   */
   public static final Metric<Integer> UNCOVERED_CONDITIONS = new Metric.Builder(UNCOVERED_CONDITIONS_KEY, "Uncovered Conditions", Metric.ValueType.INT)
     .setDescription("Uncovered conditions")
     .setDirection(Metric.DIRECTION_WORST)
@@ -679,763 +648,6 @@ public final class CoreMetrics {
     .setDeleteHistoricalData(true)
     .create();
 
-  /**
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final String CONDITIONS_BY_LINE_KEY = "conditions_by_line";
-
-  /**
-   * Use {@link CoverageMeasuresBuilder} to build measure for this metric.
-   *
-   * @since 2.7
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final Metric<String> CONDITIONS_BY_LINE = new Metric.Builder(CONDITIONS_BY_LINE_KEY, "Conditions by Line", Metric.ValueType.DATA)
-    .setDescription("Conditions by line")
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .create();
-
-  /**
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final String COVERED_CONDITIONS_BY_LINE_KEY = "covered_conditions_by_line";
-
-  /**
-   * Use {@link CoverageMeasuresBuilder} to build measure for this metric.
-   *
-   * @since 2.7
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final Metric<String> COVERED_CONDITIONS_BY_LINE = new Metric.Builder(COVERED_CONDITIONS_BY_LINE_KEY, "Covered Conditions by Line", Metric.ValueType.DATA)
-    .setDescription("Covered conditions by line")
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .create();
-
-  // --------------------------------------------------------------------------------------------------------------------
-  //
-  // INTEGRATION TESTS
-  //
-  // --------------------------------------------------------------------------------------------------------------------
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String IT_COVERAGE_KEY = "it_coverage";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> IT_COVERAGE = new Metric.Builder(IT_COVERAGE_KEY, "IT Coverage", Metric.ValueType.PERCENT)
-    .setDescription("Integration tests coverage")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_IT_COVERAGE_KEY = "new_it_coverage";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> NEW_IT_COVERAGE = new Metric.Builder(NEW_IT_COVERAGE_KEY, "Coverage by IT on New Code", Metric.ValueType.PERCENT)
-    .setDescription("Integration tests coverage of new/changed code")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String IT_LINES_TO_COVER_KEY = "it_lines_to_cover";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> IT_LINES_TO_COVER = new Metric.Builder(IT_LINES_TO_COVER_KEY, "IT Lines to Cover", Metric.ValueType.INT)
-    .setDescription("Lines to cover by Integration Tests")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setDomain(DOMAIN_COVERAGE)
-    .setQualitative(false)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_IT_LINES_TO_COVER_KEY = "new_it_lines_to_cover";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> NEW_IT_LINES_TO_COVER = new Metric.Builder(NEW_IT_LINES_TO_COVER_KEY, "Lines to Cover by IT on New Code", Metric.ValueType.INT)
-    .setDescription("Lines to cover on new code by integration tests")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setQualitative(false)
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String IT_UNCOVERED_LINES_KEY = "it_uncovered_lines";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> IT_UNCOVERED_LINES = new Metric.Builder(IT_UNCOVERED_LINES_KEY, "IT Uncovered Lines", Metric.ValueType.INT)
-    .setDescription("Uncovered lines by integration tests")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setQualitative(false)
-    .setDomain(DOMAIN_COVERAGE)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_IT_UNCOVERED_LINES_KEY = "new_it_uncovered_lines";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> NEW_IT_UNCOVERED_LINES = new Metric.Builder(NEW_IT_UNCOVERED_LINES_KEY, "Uncovered Lines by IT on New Code", Metric.ValueType.INT)
-    .setDescription("New lines that are not covered by integration tests")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setDomain(DOMAIN_COVERAGE)
-    .setBestValue(0.0)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String IT_LINE_COVERAGE_KEY = "it_line_coverage";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> IT_LINE_COVERAGE = new Metric.Builder(IT_LINE_COVERAGE_KEY, "IT Line Coverage", Metric.ValueType.PERCENT)
-    .setDescription("Line coverage by integration tests")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_IT_LINE_COVERAGE_KEY = "new_it_line_coverage";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> NEW_IT_LINE_COVERAGE = new Metric.Builder(NEW_IT_LINE_COVERAGE_KEY, "Line Coverage by IT on New Code", Metric.ValueType.PERCENT)
-    .setDescription("Integration tests line coverage of added/changed code")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final String IT_COVERAGE_LINE_HITS_DATA_KEY = "it_coverage_line_hits_data";
-
-  /**
-   * @since 2.12
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final Metric<String> IT_COVERAGE_LINE_HITS_DATA = new Metric.Builder(IT_COVERAGE_LINE_HITS_DATA_KEY, "IT Coverage Hits by Line", Metric.ValueType.DATA)
-    .setDescription("Coverage hits by line by integration tests")
-    .setDirection(Metric.DIRECTION_NONE)
-    .setQualitative(false)
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String IT_CONDITIONS_TO_COVER_KEY = "it_conditions_to_cover";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> IT_CONDITIONS_TO_COVER = new Metric.Builder(IT_CONDITIONS_TO_COVER_KEY, "IT Branches to Cover", Metric.ValueType.INT)
-    .setDescription("Integration Tests conditions to cover")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(false)
-    .setDomain(DOMAIN_COVERAGE)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_IT_CONDITIONS_TO_COVER_KEY = "new_it_conditions_to_cover";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> NEW_IT_CONDITIONS_TO_COVER = new Metric.Builder(NEW_IT_CONDITIONS_TO_COVER_KEY, "Branches to Cover by IT on New Code", Metric.ValueType.INT)
-    .setDescription("Branches to cover by Integration Tests on New Code")
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String IT_UNCOVERED_CONDITIONS_KEY = "it_uncovered_conditions";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> IT_UNCOVERED_CONDITIONS = new Metric.Builder(IT_UNCOVERED_CONDITIONS_KEY, "IT Uncovered Conditions", Metric.ValueType.INT)
-    .setDescription("Uncovered conditions by integration tests")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setDomain(DOMAIN_COVERAGE)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_IT_UNCOVERED_CONDITIONS_KEY = "new_it_uncovered_conditions";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> NEW_IT_UNCOVERED_CONDITIONS = new Metric.Builder(NEW_IT_UNCOVERED_CONDITIONS_KEY, "Uncovered Conditions by IT on New Code",
-    Metric.ValueType.INT)
-    .setDescription("New conditions that are not covered by integration tests")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setDomain(DOMAIN_COVERAGE)
-    .setBestValue(0.0)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String IT_BRANCH_COVERAGE_KEY = "it_branch_coverage";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> IT_BRANCH_COVERAGE = new Metric.Builder(IT_BRANCH_COVERAGE_KEY, "IT Condition Coverage", Metric.ValueType.PERCENT)
-    .setDescription("Condition coverage by integration tests")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_IT_BRANCH_COVERAGE_KEY = "new_it_branch_coverage";
-
-  /**
-   * @since 2.12
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> NEW_IT_BRANCH_COVERAGE = new Metric.Builder(NEW_IT_BRANCH_COVERAGE_KEY, "Condition Coverage by IT on New Code", Metric.ValueType.PERCENT)
-    .setDescription("Integration tests condition coverage of new/changed code")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final String IT_CONDITIONS_BY_LINE_KEY = "it_conditions_by_line";
-
-  /**
-   * @since 2.12
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final Metric<String> IT_CONDITIONS_BY_LINE = new Metric.Builder(IT_CONDITIONS_BY_LINE_KEY, "IT Conditions by Line", Metric.ValueType.DATA)
-    .setDescription("IT conditions by line")
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .create();
-
-  /**
-   * @since 2.12
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final String IT_COVERED_CONDITIONS_BY_LINE_KEY = "it_covered_conditions_by_line";
-
-  /**
-   * @since 2.12
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final Metric<String> IT_COVERED_CONDITIONS_BY_LINE = new Metric.Builder(IT_COVERED_CONDITIONS_BY_LINE_KEY, "IT Covered Conditions by Line", Metric.ValueType.DATA)
-    .setDescription("IT covered conditions by line")
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .create();
-
-  // --------------------------------------------------------------------------------------------------------------------
-  //
-  // OVERALL TESTS
-  //
-  // --------------------------------------------------------------------------------------------------------------------
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String OVERALL_COVERAGE_KEY = "overall_coverage";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> OVERALL_COVERAGE = new Metric.Builder(OVERALL_COVERAGE_KEY, "Overall Coverage", Metric.ValueType.PERCENT)
-    .setDescription("Overall test coverage")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_OVERALL_COVERAGE_KEY = "new_overall_coverage";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> NEW_OVERALL_COVERAGE = new Metric.Builder(NEW_OVERALL_COVERAGE_KEY, "Overall Coverage on New Code", Metric.ValueType.PERCENT)
-    .setDescription("Overall coverage of new/changed code")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String OVERALL_LINES_TO_COVER_KEY = "overall_lines_to_cover";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> OVERALL_LINES_TO_COVER = new Metric.Builder(OVERALL_LINES_TO_COVER_KEY, "Overall Lines to Cover", Metric.ValueType.INT)
-    .setDescription("Overall lines to cover by all tests")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setDomain(DOMAIN_COVERAGE)
-    .setQualitative(false)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_OVERALL_LINES_TO_COVER_KEY = "new_overall_lines_to_cover";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> NEW_OVERALL_LINES_TO_COVER = new Metric.Builder(NEW_OVERALL_LINES_TO_COVER_KEY, "Overall Lines to Cover on New Code", Metric.ValueType.INT)
-    .setDescription("New lines to cover by all tests")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setQualitative(false)
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String OVERALL_UNCOVERED_LINES_KEY = "overall_uncovered_lines";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> OVERALL_UNCOVERED_LINES = new Metric.Builder(OVERALL_UNCOVERED_LINES_KEY, "Overall Uncovered Lines", Metric.ValueType.INT)
-    .setDescription("Uncovered lines by all tests")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setQualitative(false)
-    .setDomain(DOMAIN_COVERAGE)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_OVERALL_UNCOVERED_LINES_KEY = "new_overall_uncovered_lines";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> NEW_OVERALL_UNCOVERED_LINES = new Metric.Builder(NEW_OVERALL_UNCOVERED_LINES_KEY, "Overall Uncovered Lines on New Code", Metric.ValueType.INT)
-    .setDescription("New lines that are not covered by any tests")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setDomain(DOMAIN_COVERAGE)
-    .setBestValue(0.0)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String OVERALL_LINE_COVERAGE_KEY = "overall_line_coverage";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> OVERALL_LINE_COVERAGE = new Metric.Builder(OVERALL_LINE_COVERAGE_KEY, "Overall Line Coverage", Metric.ValueType.PERCENT)
-    .setDescription("Line coverage by all tests")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_OVERALL_LINE_COVERAGE_KEY = "new_overall_line_coverage";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> NEW_OVERALL_LINE_COVERAGE = new Metric.Builder(NEW_OVERALL_LINE_COVERAGE_KEY, "Overall Line Coverage on New Code", Metric.ValueType.PERCENT)
-    .setDescription("Line coverage of added/changed code by all tests")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final String OVERALL_COVERAGE_LINE_HITS_DATA_KEY = "overall_coverage_line_hits_data";
-
-  /**
-   * @since 3.3
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final Metric<String> OVERALL_COVERAGE_LINE_HITS_DATA = new Metric.Builder(OVERALL_COVERAGE_LINE_HITS_DATA_KEY, "Overall Coverage Hits by Line",
-    Metric.ValueType.DATA)
-    .setDescription("Coverage hits by all tests and by line")
-    .setDirection(Metric.DIRECTION_NONE)
-    .setQualitative(false)
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String OVERALL_CONDITIONS_TO_COVER_KEY = "overall_conditions_to_cover";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> OVERALL_CONDITIONS_TO_COVER = new Metric.Builder(OVERALL_CONDITIONS_TO_COVER_KEY, "Overall Branches to Cover", Metric.ValueType.INT)
-    .setDescription("Branches to cover by all tests")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(false)
-    .setDomain(DOMAIN_COVERAGE)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_OVERALL_CONDITIONS_TO_COVER_KEY = "new_overall_conditions_to_cover";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> NEW_OVERALL_CONDITIONS_TO_COVER = new Metric.Builder(NEW_OVERALL_CONDITIONS_TO_COVER_KEY, "Overall Branches to Cover on New Code",
-    Metric.ValueType.INT)
-    .setDescription("New branches to cover by all tests")
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String OVERALL_UNCOVERED_CONDITIONS_KEY = "overall_uncovered_conditions";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> OVERALL_UNCOVERED_CONDITIONS = new Metric.Builder(OVERALL_UNCOVERED_CONDITIONS_KEY, "Overall Uncovered Conditions", Metric.ValueType.INT)
-    .setDescription("Uncovered conditions by all tests")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setDomain(DOMAIN_COVERAGE)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_OVERALL_UNCOVERED_CONDITIONS_KEY = "new_overall_uncovered_conditions";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Integer> NEW_OVERALL_UNCOVERED_CONDITIONS = new Metric.Builder(NEW_OVERALL_UNCOVERED_CONDITIONS_KEY, "Overall Uncovered Conditions on New Code",
-    Metric.ValueType.INT)
-    .setDescription("New conditions that are not covered by any test")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setDomain(DOMAIN_COVERAGE)
-    .setBestValue(0.0)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String OVERALL_BRANCH_COVERAGE_KEY = "overall_branch_coverage";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> OVERALL_BRANCH_COVERAGE = new Metric.Builder(OVERALL_BRANCH_COVERAGE_KEY, "Overall Condition Coverage", Metric.ValueType.PERCENT)
-    .setDescription("Condition coverage by all tests")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final String NEW_OVERALL_BRANCH_COVERAGE_KEY = "new_overall_branch_coverage";
-
-  /**
-   * @since 3.3
-   * @deprecated since 6.2 all coverage reports are merged in the same measures
-   */
-  @Deprecated
-  public static final Metric<Double> NEW_OVERALL_BRANCH_COVERAGE = new Metric.Builder(NEW_OVERALL_BRANCH_COVERAGE_KEY, "Overall Condition Coverage on New Code",
-    Metric.ValueType.PERCENT)
-    .setDescription("Condition coverage of new/changed code by all tests")
-    .setDirection(Metric.DIRECTION_BETTER)
-    .setQualitative(true)
-    .setDomain(DOMAIN_COVERAGE)
-    .setWorstValue(0.0)
-    .setBestValue(100.0)
-    .setDeleteHistoricalData(true)
-    .setHidden(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final String OVERALL_CONDITIONS_BY_LINE_KEY = "overall_conditions_by_line";
-
-  /**
-   * @since 3.3
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final Metric<String> OVERALL_CONDITIONS_BY_LINE = new Metric.Builder(OVERALL_CONDITIONS_BY_LINE_KEY, "Overall Conditions by Line", Metric.ValueType.DATA)
-    .setDescription("Overall conditions by all tests and by line")
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .create();
-
-  /**
-   * @since 3.3
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final String OVERALL_COVERED_CONDITIONS_BY_LINE_KEY = "overall_covered_conditions_by_line";
-
-  /**
-   * @since 3.3
-   * @deprecated since 5.2 soon to be removed
-   */
-  @Deprecated
-  public static final Metric<String> OVERALL_COVERED_CONDITIONS_BY_LINE = new Metric.Builder(OVERALL_COVERED_CONDITIONS_BY_LINE_KEY, "Overall Covered Conditions by Line",
-    Metric.ValueType.DATA)
-    .setDescription("Overall covered conditions by all tests and by line")
-    .setDomain(DOMAIN_COVERAGE)
-    .setDeleteHistoricalData(true)
-    .create();
-
   // --------------------------------------------------------------------------------------------------------------------
   //
   // DUPLICATIONS
index 0665df118786dbab5dbd358fe0f87fb5404f717a..b28f70876fd521349f0d1928da345357894bcd9a 100644 (file)
@@ -31,7 +31,7 @@ public class NoSonarFilterTest {
 
   @Test
   public void should_store_nosonar_lines_on_inputfile() {
-    DefaultInputFile f = TestInputFileBuilder.create("module1", "myfile.java").build();
+    DefaultInputFile f = TestInputFileBuilder.create("module1", "myfile.java").setLines(8).build();
     new NoSonarFilter().noSonarInFile(f, new HashSet<>(Arrays.asList(1,4)));
 
      assertThat(f.hasNoSonarAt(1)).isTrue();
index 9ad0ce807ba2e908917deb07666d924faf61a610..77c26c7466d8e0a67cec1b400ec9b7a8013462d2 100644 (file)
@@ -26,7 +26,6 @@ dependencies {
   compile 'org.slf4j:jul-to-slf4j'
   compile 'org.slf4j:log4j-over-slf4j'
   compile 'org.slf4j:slf4j-api'
-  compile 'org.sonarsource:sonar-persistit'
   compile project(':sonar-core')
   compile project(':sonar-scanner-protocol')
   compile project(':sonar-ws')
index 7ef71bbb22142a400594acdcd754daf66c54d2a9..eecbbd15e8406d466f7324e111f91c3995fcbadb 100644 (file)
@@ -32,15 +32,12 @@ import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.FileLinesContext;
 import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.api.utils.KeyValueFormat.Converter;
-import org.sonar.scanner.scan.measure.MeasureCache;
 
 import static java.util.stream.Collectors.toMap;
 
 public class DefaultFileLinesContext implements FileLinesContext {
   private final InputFile inputFile;
   private final MetricFinder metricFinder;
-  private final MeasureCache measureCache;
 
   /**
    * metric key -> line -> value
@@ -48,11 +45,10 @@ public class DefaultFileLinesContext implements FileLinesContext {
   private final Map<String, Map<Integer, Object>> map = new HashMap<>();
   private final SensorStorage sensorStorage;
 
-  public DefaultFileLinesContext(SensorStorage sensorStorage, InputFile inputFile, MetricFinder metricFinder, MeasureCache measureCache) {
+  public DefaultFileLinesContext(SensorStorage sensorStorage, InputFile inputFile, MetricFinder metricFinder) {
     this.sensorStorage = sensorStorage;
     this.inputFile = inputFile;
     this.metricFinder = metricFinder;
-    this.measureCache = measureCache;
   }
 
   @Override
@@ -68,13 +64,6 @@ public class DefaultFileLinesContext implements FileLinesContext {
     Preconditions.checkArgument(line <= inputFile.lines(), "Line %s is out of range for file %s. File has %s lines.", line, inputFile, inputFile.lines());
   }
 
-  public Integer getIntValue(String metricKey, int line) {
-    Preconditions.checkNotNull(metricKey);
-    checkLineRange(line);
-    Map<Integer, Object> lines = map.computeIfAbsent(metricKey, k -> loadData(k, KeyValueFormat.newIntegerConverter()));
-    return (Integer) lines.get(line);
-  }
-
   @Override
   public void setStringValue(String metricKey, int line, String value) {
     Preconditions.checkNotNull(metricKey);
@@ -84,13 +73,6 @@ public class DefaultFileLinesContext implements FileLinesContext {
     setValue(metricKey, line, value);
   }
 
-  public String getStringValue(String metricKey, int line) {
-    Preconditions.checkNotNull(metricKey);
-    checkLineRange(line);
-    Map<Integer, Object> lines = map.computeIfAbsent(metricKey, k -> loadData(k, KeyValueFormat.newStringConverter()));
-    return (String) lines.get(line);
-  }
-
   private void setValue(String metricKey, int line, Object value) {
     map.computeIfAbsent(metricKey, k -> new HashMap<>())
       .put(line, value);
@@ -123,20 +105,9 @@ public class DefaultFileLinesContext implements FileLinesContext {
     return lines;
   }
 
-  private Map<Integer, Object> loadData(String metricKey, Converter<? extends Object> converter) {
-    DefaultMeasure<?> measure = measureCache.byMetric(inputFile.key(), metricKey);
-    String data = measure != null ? (String) measure.value() : null;
-    if (data != null) {
-      return ImmutableMap.copyOf(KeyValueFormat.parse(data, KeyValueFormat.newIntegerConverter(), converter));
-    }
-    // no such measure
-    return ImmutableMap.of();
-  }
-
   /**
    * Checks that measure was not saved.
    *
-   * @see #loadData(String, Converter)
    * @see #save()
    */
   private static boolean shouldSave(Map<Integer, Object> lines) {
index 8ed50b887106780f3b1dae2dbca60fcf535d422f..209f3544810685d7b9ea50ddf0672454446b4b80 100644 (file)
@@ -25,24 +25,21 @@ import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
 import org.sonar.api.measures.FileLinesContext;
 import org.sonar.api.measures.FileLinesContextFactory;
-import org.sonar.scanner.scan.measure.MeasureCache;
 
 @Immutable
 public class DefaultFileLinesContextFactory implements FileLinesContextFactory {
 
   private final SensorStorage sensorStorage;
   private final MetricFinder metricFinder;
-  private final MeasureCache measureCache;
 
-  public DefaultFileLinesContextFactory(SensorStorage sensorStorage, MetricFinder metricFinder, MeasureCache measureCache) {
+  public DefaultFileLinesContextFactory(SensorStorage sensorStorage, MetricFinder metricFinder) {
     this.sensorStorage = sensorStorage;
     this.metricFinder = metricFinder;
-    this.measureCache = measureCache;
   }
 
   @Override
   public FileLinesContext createFor(InputFile inputFile) {
-    return new DefaultFileLinesContext(sensorStorage, inputFile, metricFinder, measureCache);
+    return new DefaultFileLinesContext(sensorStorage, inputFile, metricFinder);
   }
 
 }
index 4857692b80cee11eb37803c718629d30a420fb04..302f263a92f20803e4c042316aa8d97ef46d47f0 100644 (file)
@@ -52,7 +52,6 @@ import org.sonar.scanner.repository.MetricsRepositoryProvider;
 import org.sonar.scanner.repository.settings.DefaultGlobalSettingsLoader;
 import org.sonar.scanner.repository.settings.GlobalSettingsLoader;
 import org.sonar.scanner.scan.ProjectScanContainer;
-import org.sonar.scanner.storage.StoragesManager;
 
 public class GlobalContainer extends ComponentContainer {
   private static final Logger LOG = Loggers.get(GlobalContainer.class);
@@ -90,7 +89,6 @@ public class GlobalContainer extends ComponentContainer {
 
       new SonarQubeVersion(apiVersion),
       SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.SCANNER),
-      StoragesManager.class,
       new GlobalServerSettingsProvider(),
       new GlobalConfigurationProvider(),
       new ScannerWsClientProvider(),
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/CoveragePublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/CoveragePublisher.java
deleted file mode 100644 (file)
index d2bb71b..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.report;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import javax.annotation.Nonnull;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.scanner.protocol.output.ScannerReport.LineCoverage;
-import org.sonar.scanner.protocol.output.ScannerReport.LineCoverage.Builder;
-import org.sonar.scanner.protocol.output.ScannerReportWriter;
-import org.sonar.scanner.scan.filesystem.InputComponentStore;
-import org.sonar.scanner.scan.measure.MeasureCache;
-
-public class CoveragePublisher implements ReportPublisherStep {
-
-  private final InputComponentStore componentStore;
-  private final MeasureCache measureCache;
-
-  public CoveragePublisher(InputComponentStore componentStore, MeasureCache measureCache) {
-    this.componentStore = componentStore;
-    this.measureCache = measureCache;
-  }
-
-  @Override
-  public void publish(ScannerReportWriter writer) {
-    for (final DefaultInputFile inputFile : componentStore.allFilesToPublish()) {
-      Map<Integer, LineCoverage.Builder> coveragePerLine = new LinkedHashMap<>();
-
-      int lineCount = inputFile.lines();
-      applyLineMeasure(inputFile.key(), lineCount, CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, coveragePerLine,
-        (value, builder) -> builder.setHits(Integer.parseInt(value) > 0));
-      applyLineMeasure(inputFile.key(), lineCount, CoreMetrics.CONDITIONS_BY_LINE_KEY, coveragePerLine,
-        (value, builder) -> builder.setConditions(Integer.parseInt(value)));
-      applyLineMeasure(inputFile.key(), lineCount, CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY, coveragePerLine,
-        (value, builder) -> builder.setCoveredConditions(Integer.parseInt(value)));
-
-      writer.writeComponentCoverage(inputFile.scannerId(), coveragePerLine.values().stream().map(BuildCoverage.INSTANCE).collect(Collectors.toList()));
-    }
-  }
-
-  void applyLineMeasure(String inputFileKey, int lineCount, String metricKey, Map<Integer, LineCoverage.Builder> coveragePerLine, MeasureOperation op) {
-    DefaultMeasure<?> measure = measureCache.byMetric(inputFileKey, metricKey);
-    if (measure != null) {
-      Map<Integer, String> lineMeasures = KeyValueFormat.parseIntString((String) measure.value());
-      for (Map.Entry<Integer, String> lineMeasure : lineMeasures.entrySet()) {
-        int lineIdx = lineMeasure.getKey();
-        if (lineIdx <= lineCount) {
-          String value = lineMeasure.getValue();
-          if (StringUtils.isNotEmpty(value)) {
-            LineCoverage.Builder coverageBuilder = coveragePerLine.get(lineIdx);
-            if (coverageBuilder == null) {
-              coverageBuilder = LineCoverage.newBuilder();
-              coverageBuilder.setLine(lineIdx);
-              coveragePerLine.put(lineIdx, coverageBuilder);
-            }
-            op.apply(value, coverageBuilder);
-          }
-        }
-      }
-    }
-  }
-
-  interface MeasureOperation {
-    void apply(String value, LineCoverage.Builder builder);
-  }
-
-  private enum BuildCoverage implements Function<Builder, LineCoverage> {
-    INSTANCE;
-
-    @Override
-    public LineCoverage apply(@Nonnull Builder input) {
-      return input.build();
-    }
-  }
-
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MeasuresPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MeasuresPublisher.java
deleted file mode 100644 (file)
index 7569216..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.report;
-
-import com.google.common.collect.Iterables;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-import org.sonar.api.batch.fs.InputComponent;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputFile.Type;
-import org.sonar.api.batch.fs.internal.DefaultInputComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.measure.Metric;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.test.MutableTestPlan;
-import org.sonar.api.test.TestCase.Status;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.scanner.deprecated.test.TestPlanBuilder;
-import org.sonar.scanner.protocol.output.ScannerReport;
-import org.sonar.scanner.protocol.output.ScannerReport.Measure.BoolValue;
-import org.sonar.scanner.protocol.output.ScannerReport.Measure.DoubleValue;
-import org.sonar.scanner.protocol.output.ScannerReport.Measure.IntValue;
-import org.sonar.scanner.protocol.output.ScannerReport.Measure.LongValue;
-import org.sonar.scanner.protocol.output.ScannerReport.Measure.StringValue;
-import org.sonar.scanner.protocol.output.ScannerReportWriter;
-import org.sonar.scanner.scan.filesystem.InputComponentStore;
-import org.sonar.scanner.scan.measure.MeasureCache;
-
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_TO_COVER_KEY;
-import static org.sonar.api.measures.CoreMetrics.LINES_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.LINES_TO_COVER_KEY;
-import static org.sonar.api.measures.CoreMetrics.SKIPPED_TESTS;
-import static org.sonar.api.measures.CoreMetrics.SKIPPED_TESTS_KEY;
-import static org.sonar.api.measures.CoreMetrics.TESTS;
-import static org.sonar.api.measures.CoreMetrics.TESTS_KEY;
-import static org.sonar.api.measures.CoreMetrics.TEST_ERRORS;
-import static org.sonar.api.measures.CoreMetrics.TEST_ERRORS_KEY;
-import static org.sonar.api.measures.CoreMetrics.TEST_EXECUTION_TIME;
-import static org.sonar.api.measures.CoreMetrics.TEST_EXECUTION_TIME_KEY;
-import static org.sonar.api.measures.CoreMetrics.TEST_FAILURES;
-import static org.sonar.api.measures.CoreMetrics.TEST_FAILURES_KEY;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_CONDITIONS;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_CONDITIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES_KEY;
-
-public class MeasuresPublisher implements ReportPublisherStep {
-
-  private final InputComponentStore componentStore;
-  private final MeasureCache measureCache;
-  private final TestPlanBuilder testPlanBuilder;
-
-  public MeasuresPublisher(InputComponentStore componentStore, MeasureCache measureCache, TestPlanBuilder testPlanBuilder) {
-    this.componentStore = componentStore;
-    this.measureCache = measureCache;
-    this.testPlanBuilder = testPlanBuilder;
-  }
-
-  @Override
-  public void publish(ScannerReportWriter writer) {
-    final ScannerReport.Measure.Builder builder = ScannerReport.Measure.newBuilder();
-
-    for (final InputComponent c : componentStore.all()) {
-      DefaultInputComponent component = (DefaultInputComponent) c;
-      if (component.isFile()) {
-        DefaultInputFile file = (DefaultInputFile) component;
-        // Recompute all coverage measures from line data to take into account the possible merge of several reports
-        updateCoverageFromLineData(file);
-        // Recompute test execution measures from MutableTestPlan to take into account the possible merge of several reports
-        updateTestExecutionFromTestPlan(file);
-      }
-
-      Iterable<DefaultMeasure<?>> scannerMeasures = measureCache.byComponentKey(component.key());
-      if (scannerMeasures.iterator().hasNext()) {
-        writer.writeComponentMeasures(component.scannerId(), StreamSupport.stream(scannerMeasures.spliterator(), false)
-          .map(input -> {
-            if (input.value() == null) {
-              throw new IllegalArgumentException(
-                String.format("Measure on metric '%s' and component '%s' has no value, but it's not allowed", input.metric().key(), component.key()));
-            }
-            builder.clear();
-            builder.setMetricKey(input.metric().key());
-            setValueAccordingToType(builder, input);
-            return builder.build();
-          }).collect(Collectors.toList()));
-      }
-    }
-  }
-
-  private static void setValueAccordingToType(ScannerReport.Measure.Builder builder, DefaultMeasure<?> measure) {
-    Serializable value = measure.value();
-    Metric<?> metric = measure.metric();
-    if (Boolean.class.equals(metric.valueType())) {
-      builder.setBooleanValue(BoolValue.newBuilder().setValue(((Boolean) value).booleanValue()));
-    } else if (Integer.class.equals(metric.valueType())) {
-      builder.setIntValue(IntValue.newBuilder().setValue(((Number) value).intValue()));
-    } else if (Double.class.equals(metric.valueType())) {
-      builder.setDoubleValue(DoubleValue.newBuilder().setValue(((Number) value).doubleValue()));
-    } else if (String.class.equals(metric.valueType())) {
-      builder.setStringValue(StringValue.newBuilder().setValue((String) value));
-    } else if (Long.class.equals(metric.valueType())) {
-      builder.setLongValue(LongValue.newBuilder().setValue(((Number) value).longValue()));
-    } else {
-      throw new UnsupportedOperationException("Unsupported type :" + metric.valueType());
-    }
-  }
-
-  private void updateTestExecutionFromTestPlan(final InputFile inputFile) {
-    final MutableTestPlan testPlan = testPlanBuilder.getTestPlanByFile(inputFile);
-    if (testPlan == null || Iterables.isEmpty(testPlan.testCases())) {
-      return;
-    }
-    long nonSkippedTests = StreamSupport.stream(testPlan.testCases().spliterator(), false).filter(t -> t.status() != Status.SKIPPED).count();
-    measureCache.put(inputFile.key(), TESTS_KEY, new DefaultMeasure<Integer>().forMetric(TESTS).withValue((int) nonSkippedTests));
-    long executionTime = StreamSupport.stream(testPlan.testCases().spliterator(), false).mapToLong(t -> t.durationInMs() != null ? t.durationInMs().longValue() : 0L).sum();
-    measureCache.put(inputFile.key(), TEST_EXECUTION_TIME_KEY, new DefaultMeasure<Long>().forMetric(TEST_EXECUTION_TIME).withValue(executionTime));
-    long errorTests = StreamSupport.stream(testPlan.testCases().spliterator(), false).filter(t -> t.status() == Status.ERROR).count();
-    measureCache.put(inputFile.key(), TEST_ERRORS_KEY, new DefaultMeasure<Integer>().forMetric(TEST_ERRORS).withValue((int) errorTests));
-    long skippedTests = StreamSupport.stream(testPlan.testCases().spliterator(), false).filter(t -> t.status() == Status.SKIPPED).count();
-    measureCache.put(inputFile.key(), SKIPPED_TESTS_KEY, new DefaultMeasure<Integer>().forMetric(SKIPPED_TESTS).withValue((int) skippedTests));
-    long failedTests = StreamSupport.stream(testPlan.testCases().spliterator(), false).filter(t -> t.status() == Status.FAILURE).count();
-    measureCache.put(inputFile.key(), TEST_FAILURES_KEY, new DefaultMeasure<Integer>().forMetric(TEST_FAILURES).withValue((int) failedTests));
-  }
-
-  private void updateCoverageFromLineData(final InputFile inputFile) {
-    if (inputFile.type() != Type.MAIN) {
-      return;
-    }
-    DefaultMeasure<String> lineHitsMeasure = (DefaultMeasure<String>) measureCache.byMetric(inputFile.key(), CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY);
-    if (lineHitsMeasure != null) {
-      Map<Integer, Integer> lineHits = KeyValueFormat.parseIntInt(lineHitsMeasure.value());
-      measureCache.put(inputFile.key(), LINES_TO_COVER_KEY, new DefaultMeasure<Integer>().forMetric(LINES_TO_COVER).withValue(lineHits.keySet().size()));
-      measureCache.put(inputFile.key(), UNCOVERED_LINES_KEY,
-        new DefaultMeasure<Integer>().forMetric(UNCOVERED_LINES).withValue((int) lineHits.values()
-          .stream()
-          .filter(hit -> hit == 0)
-          .count()));
-    }
-    DefaultMeasure<String> conditionsMeasure = (DefaultMeasure<String>) measureCache.byMetric(inputFile.key(), CoreMetrics.CONDITIONS_BY_LINE_KEY);
-    DefaultMeasure<String> coveredConditionsMeasure = (DefaultMeasure<String>) measureCache.byMetric(inputFile.key(), CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY);
-    if (conditionsMeasure != null) {
-      Map<Integer, Integer> conditions = KeyValueFormat.parseIntInt(conditionsMeasure.value());
-      Map<Integer, Integer> coveredConditions = coveredConditionsMeasure != null ? KeyValueFormat.parseIntInt(coveredConditionsMeasure.value()) : Collections.emptyMap();
-      measureCache.put(inputFile.key(), CONDITIONS_TO_COVER_KEY, new DefaultMeasure<Integer>().forMetric(CONDITIONS_TO_COVER).withValue(conditions
-        .values()
-        .stream()
-        .mapToInt(Integer::intValue)
-        .sum()));
-      measureCache.put(inputFile.key(), UNCOVERED_CONDITIONS_KEY,
-        new DefaultMeasure<Integer>().forMetric(UNCOVERED_CONDITIONS)
-          .withValue((int) conditions.keySet()
-            .stream()
-            .mapToInt(line -> conditions.get(line) - coveredConditions.get(line))
-            .sum()));
-    }
-  }
-
-}
index 2843699a626249fc41779663df0500b9d1e71ef8..5ed8769d2f9ed0cdb4359ac9257e470ec676dc7f 100644 (file)
@@ -45,6 +45,7 @@ import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
 import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
@@ -83,6 +84,7 @@ public class ReportPublisher implements Startable {
 
   private Path reportDir;
   private ScannerReportWriter writer;
+  private ScannerReportReader reader;
 
   public ReportPublisher(ScanProperties properties, ScannerWsClient wsClient, Server server, AnalysisContextReportPublisher contextPublisher,
     InputModuleHierarchy moduleHierarchy, GlobalAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers, BranchConfiguration branchConfiguration) {
@@ -101,6 +103,7 @@ public class ReportPublisher implements Startable {
   public void start() {
     reportDir = moduleHierarchy.root().getWorkDir().resolve("scanner-report");
     writer = new ScannerReportWriter(reportDir.toFile());
+    reader = new ScannerReportReader(reportDir.toFile());
     contextPublisher.init(writer);
 
     if (!analysisMode.isMediumTest()) {
@@ -126,6 +129,10 @@ public class ReportPublisher implements Startable {
     return writer;
   }
 
+  public ScannerReportReader getReader() {
+    return reader;
+  }
+
   public void execute() {
     String taskId = null;
     File report = generateReportFile();
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionPublisher.java
new file mode 100644 (file)
index 0000000..9c19a88
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.scanner.report;
+
+import com.google.common.collect.Iterables;
+import java.util.Objects;
+import java.util.stream.StreamSupport;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.test.MutableTestPlan;
+import org.sonar.api.test.TestCase;
+import org.sonar.api.test.TestCase.Status;
+import org.sonar.scanner.deprecated.test.TestPlanBuilder;
+import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.scanner.protocol.output.ScannerReportWriter;
+import org.sonar.scanner.scan.filesystem.InputComponentStore;
+
+import static org.sonar.api.measures.CoreMetrics.SKIPPED_TESTS;
+import static org.sonar.api.measures.CoreMetrics.TESTS;
+import static org.sonar.api.measures.CoreMetrics.TEST_ERRORS;
+import static org.sonar.api.measures.CoreMetrics.TEST_EXECUTION_TIME;
+import static org.sonar.api.measures.CoreMetrics.TEST_FAILURES;
+import static org.sonar.scanner.sensor.DefaultSensorStorage.toReportMeasure;
+
+public class TestExecutionPublisher implements ReportPublisherStep {
+
+  private final InputComponentStore componentStore;
+  private final TestPlanBuilder testPlanBuilder;
+
+  public TestExecutionPublisher(InputComponentStore componentStore, TestPlanBuilder testPlanBuilder) {
+    this.componentStore = componentStore;
+    this.testPlanBuilder = testPlanBuilder;
+  }
+
+  @Override
+  public void publish(ScannerReportWriter writer) {
+    final ScannerReport.Measure.Builder builder = ScannerReport.Measure.newBuilder();
+
+    for (final InputComponent c : componentStore.all()) {
+      DefaultInputComponent component = (DefaultInputComponent) c;
+      if (component.isFile()) {
+        DefaultInputFile file = (DefaultInputFile) component;
+        // Recompute test execution measures from MutableTestPlan to take into account the possible merge of several reports
+        updateTestExecutionFromTestPlan(file, writer);
+      }
+    }
+  }
+
+  private void updateTestExecutionFromTestPlan(final InputFile inputFile, ScannerReportWriter writer) {
+    final MutableTestPlan testPlan = testPlanBuilder.getTestPlanByFile(inputFile);
+    if (testPlan == null || Iterables.isEmpty(testPlan.testCases())) {
+      return;
+    }
+    long nonSkippedTests = StreamSupport.stream(testPlan.testCases().spliterator(), false).filter(t -> t.status() != Status.SKIPPED).count();
+    appendMeasure(inputFile, writer, new DefaultMeasure<Integer>().forMetric(TESTS).withValue((int) nonSkippedTests));
+    long executionTime = StreamSupport.stream(testPlan.testCases().spliterator(), false).map(TestCase::durationInMs).filter(Objects::nonNull).mapToLong(Long::longValue).sum();
+    appendMeasure(inputFile, writer, new DefaultMeasure<Long>().forMetric(TEST_EXECUTION_TIME).withValue(executionTime));
+    long errorTests = StreamSupport.stream(testPlan.testCases().spliterator(), false).filter(t -> t.status() == Status.ERROR).count();
+    appendMeasure(inputFile, writer, new DefaultMeasure<Integer>().forMetric(TEST_ERRORS).withValue((int) errorTests));
+    long skippedTests = StreamSupport.stream(testPlan.testCases().spliterator(), false).filter(t -> t.status() == Status.SKIPPED).count();
+    appendMeasure(inputFile, writer, new DefaultMeasure<Integer>().forMetric(SKIPPED_TESTS).withValue((int) skippedTests));
+    long failedTests = StreamSupport.stream(testPlan.testCases().spliterator(), false).filter(t -> t.status() == Status.FAILURE).count();
+    appendMeasure(inputFile, writer, new DefaultMeasure<Integer>().forMetric(TEST_FAILURES).withValue((int) failedTests));
+  }
+
+  private void appendMeasure(InputFile inputFile, ScannerReportWriter writer, DefaultMeasure measure) {
+    writer.appendComponentMeasure(((DefaultInputComponent) inputFile).scannerId(), toReportMeasure(measure));
+  }
+
+}
index b18e5db8faed78bd4215873563ff6db899dd3d98..dc242a2b4bd448c59cbdbaf0afb6e22ffca6c43f 100644 (file)
@@ -69,11 +69,10 @@ import org.sonar.scanner.report.AnalysisWarningsPublisher;
 import org.sonar.scanner.report.ChangedLinesPublisher;
 import org.sonar.scanner.report.ComponentsPublisher;
 import org.sonar.scanner.report.ContextPropertiesPublisher;
-import org.sonar.scanner.report.CoveragePublisher;
-import org.sonar.scanner.report.MeasuresPublisher;
 import org.sonar.scanner.report.MetadataPublisher;
 import org.sonar.scanner.report.ReportPublisher;
 import org.sonar.scanner.report.SourcePublisher;
+import org.sonar.scanner.report.TestExecutionPublisher;
 import org.sonar.scanner.repository.ContextPropertiesCache;
 import org.sonar.scanner.repository.DefaultProjectRepositoriesLoader;
 import org.sonar.scanner.repository.DefaultQualityProfileLoader;
@@ -107,7 +106,6 @@ import org.sonar.scanner.scan.filesystem.ProjectFileIndexer;
 import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator;
 import org.sonar.scanner.scan.filesystem.StatusDetection;
 import org.sonar.scanner.scan.measure.DefaultMetricFinder;
-import org.sonar.scanner.scan.measure.MeasureCache;
 import org.sonar.scanner.scm.ScmChangedFilesProvider;
 import org.sonar.scanner.scm.ScmConfiguration;
 import org.sonar.scanner.scm.ScmPublisher;
@@ -116,7 +114,6 @@ import org.sonar.scanner.sensor.ProjectSensorContext;
 import org.sonar.scanner.sensor.ProjectSensorExtensionDictionnary;
 import org.sonar.scanner.sensor.ProjectSensorOptimizer;
 import org.sonar.scanner.sensor.ProjectSensorsExecutor;
-import org.sonar.scanner.storage.Storages;
 
 import static org.sonar.api.batch.InstantiationStrategy.PER_BATCH;
 import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
@@ -155,7 +152,6 @@ public class ProjectScanContainer extends ComponentContainer {
       ProjectReactorValidator.class,
       MetricProvider.class,
       ProjectInfo.class,
-      Storages.class,
       new RulesProvider(),
       new BranchConfigurationProvider(),
       new ProjectBranchesProvider(),
@@ -205,9 +201,6 @@ public class ProjectScanContainer extends ComponentContainer {
       Languages.class,
       DefaultLanguagesRepository.class,
 
-      // Measures
-      MeasureCache.class,
-
       // issue exclusions
       IssueInclusionPatternInitializer.class,
       IssueExclusionPatternInitializer.class,
@@ -237,8 +230,7 @@ public class ProjectScanContainer extends ComponentContainer {
       ActiveRulesPublisher.class,
       AnalysisWarningsPublisher.class,
       ComponentsPublisher.class,
-      MeasuresPublisher.class,
-      CoveragePublisher.class,
+      TestExecutionPublisher.class,
       SourcePublisher.class,
       ChangedLinesPublisher.class,
 
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/measure/MeasureCache.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/measure/MeasureCache.java
deleted file mode 100644 (file)
index 68b30bf..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.scan.measure;
-
-import com.google.common.base.Preconditions;
-import javax.annotation.CheckForNull;
-import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.scanner.storage.Storage;
-import org.sonar.scanner.storage.Storage.Entry;
-import org.sonar.scanner.storage.Storages;
-
-/**
- * Cache of all measures. This cache is shared amongst all project modules.
- */
-public class MeasureCache {
-
-  private final Storage<DefaultMeasure<?>> cache;
-
-  public MeasureCache(Storages caches, MetricFinder metricFinder) {
-    caches.registerValueCoder(DefaultMeasure.class, new MeasureValueCoder(metricFinder));
-    cache = caches.createCache("measures");
-  }
-
-  public Iterable<Entry<DefaultMeasure<?>>> entries() {
-    return cache.entries();
-  }
-
-  public Iterable<DefaultMeasure<?>> all() {
-    return cache.values();
-  }
-
-  public Iterable<DefaultMeasure<?>> byComponentKey(String effectiveKey) {
-    return cache.values(effectiveKey);
-  }
-
-  @CheckForNull
-  public DefaultMeasure<?> byMetric(String componentKey, String metricKey) {
-    return cache.get(componentKey, metricKey);
-  }
-
-  public MeasureCache put(String componentKey, String metricKey, DefaultMeasure<?> measure) {
-    Preconditions.checkNotNull(componentKey);
-    Preconditions.checkNotNull(metricKey);
-    cache.put(componentKey, metricKey, measure);
-    return this;
-  }
-
-  public boolean contains(String componentKey, String metricKey) {
-    Preconditions.checkNotNull(componentKey);
-    Preconditions.checkNotNull(metricKey);
-    return cache.containsKey(componentKey, metricKey);
-  }
-
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/measure/MeasureValueCoder.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/measure/MeasureValueCoder.java
deleted file mode 100644 (file)
index c7d87a1..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.scan.measure;
-
-import com.persistit.Value;
-import com.persistit.encoding.CoderContext;
-import com.persistit.encoding.ValueCoder;
-import java.io.Serializable;
-import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-
-class MeasureValueCoder implements ValueCoder {
-
-  private final MetricFinder metricFinder;
-
-  public MeasureValueCoder(MetricFinder metricFinder) {
-    this.metricFinder = metricFinder;
-  }
-
-  @Override
-  public void put(Value value, Object object, CoderContext context) {
-    DefaultMeasure<?> m = (DefaultMeasure<?>) object;
-    org.sonar.api.batch.measure.Metric<?> metric = m.metric();
-    value.putString(metric.key());
-    value.put(m.value());
-  }
-
-  @Override
-  public Object get(Value value, Class clazz, CoderContext context) {
-    String metricKey = value.getString();
-    org.sonar.api.batch.measure.Metric<?> metric = metricFinder.findByKey(metricKey);
-    if (metric == null) {
-      throw new IllegalStateException("Unknow metric with key " + metricKey);
-    }
-    return new DefaultMeasure()
-      .forMetric(metric)
-      .withValue((Serializable) value.get());
-  }
-}
index ab27aa0b0fa71d1105488c619db58468328e789b..42965a37d98155380e316c2f967877fbd91c4200 100644 (file)
  */
 package org.sonar.scanner.sensor;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
+import java.io.Serializable;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeMap;
+import java.util.SortedMap;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 import javax.annotation.Nullable;
 import org.sonar.api.batch.fs.InputComponent;
 import org.sonar.api.batch.fs.InputDir;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultInputComponent;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.measure.Metric;
@@ -51,10 +50,12 @@ import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule;
 import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
 import org.sonar.api.config.Configuration;
+import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.core.metric.ScannerMetrics;
+import org.sonar.core.util.CloseableIterator;
 import org.sonar.duplications.block.Block;
 import org.sonar.duplications.internal.pmd.PmdBlockChunker;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
@@ -67,52 +68,15 @@ import org.sonar.scanner.report.ReportPublisher;
 import org.sonar.scanner.report.ScannerReportUtils;
 import org.sonar.scanner.repository.ContextPropertiesCache;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
-import org.sonar.scanner.scan.measure.MeasureCache;
 
+import static java.lang.Math.max;
 import static java.util.Arrays.asList;
 import static java.util.Collections.unmodifiableSet;
 import static java.util.stream.Collectors.toList;
-import static org.sonar.api.measures.CoreMetrics.BRANCH_COVERAGE;
 import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_DATA_KEY;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_BY_LINE_KEY;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.CONDITIONS_TO_COVER_KEY;
-import static org.sonar.api.measures.CoreMetrics.COVERAGE;
-import static org.sonar.api.measures.CoreMetrics.COVERAGE_LINE_HITS_DATA;
-import static org.sonar.api.measures.CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY;
-import static org.sonar.api.measures.CoreMetrics.COVERED_CONDITIONS_BY_LINE;
-import static org.sonar.api.measures.CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_BRANCH_COVERAGE_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_CONDITIONS_BY_LINE_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_CONDITIONS_TO_COVER_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_COVERAGE_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_COVERAGE_LINE_HITS_DATA_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_LINES_TO_COVER_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_LINE_COVERAGE_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_UNCOVERED_CONDITIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.IT_UNCOVERED_LINES_KEY;
 import static org.sonar.api.measures.CoreMetrics.LINES_KEY;
-import static org.sonar.api.measures.CoreMetrics.LINES_TO_COVER;
-import static org.sonar.api.measures.CoreMetrics.LINES_TO_COVER_KEY;
-import static org.sonar.api.measures.CoreMetrics.LINE_COVERAGE;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_BRANCH_COVERAGE_KEY;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_CONDITIONS_BY_LINE_KEY;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_CONDITIONS_TO_COVER_KEY;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_COVERAGE_KEY;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA_KEY;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE_KEY;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_LINES_TO_COVER_KEY;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_LINE_COVERAGE_KEY;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_UNCOVERED_CONDITIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.OVERALL_UNCOVERED_LINES_KEY;
 import static org.sonar.api.measures.CoreMetrics.PUBLIC_DOCUMENTED_API_DENSITY_KEY;
 import static org.sonar.api.measures.CoreMetrics.TEST_SUCCESS_DENSITY_KEY;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_CONDITIONS;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_CONDITIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES;
-import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES_KEY;
 
 public class DefaultSensorStorage implements SensorStorage {
 
@@ -140,51 +104,9 @@ public class DefaultSensorStorage implements SensorStorage {
     TEST_SUCCESS_DENSITY_KEY,
     PUBLIC_DOCUMENTED_API_DENSITY_KEY)));
 
-  private static final Set<String> COVERAGE_METRIC_KEYS = unmodifiableSet(new HashSet<>(asList(
-    UNCOVERED_LINES_KEY,
-    LINES_TO_COVER_KEY,
-    UNCOVERED_CONDITIONS_KEY,
-    CONDITIONS_TO_COVER_KEY,
-    CONDITIONS_BY_LINE_KEY,
-    COVERED_CONDITIONS_BY_LINE_KEY,
-    COVERAGE_LINE_HITS_DATA_KEY)));
-
-  private static final Set<String> COVERAGE_BY_LINE_METRIC_KEYS = unmodifiableSet(new HashSet<>(asList(
-    COVERAGE_LINE_HITS_DATA_KEY,
-    COVERED_CONDITIONS_BY_LINE_KEY,
-    CONDITIONS_BY_LINE_KEY)));
-
-  private static final Map<String, Metric> DEPRECATED_COVERAGE_METRICS_MAPPING;
-
-  static {
-    Map<String, Metric> map = new HashMap<>();
-    map.put(IT_COVERAGE_KEY, COVERAGE);
-    map.put(IT_LINE_COVERAGE_KEY, LINE_COVERAGE);
-    map.put(IT_BRANCH_COVERAGE_KEY, BRANCH_COVERAGE);
-    map.put(IT_UNCOVERED_LINES_KEY, UNCOVERED_LINES);
-    map.put(IT_LINES_TO_COVER_KEY, LINES_TO_COVER);
-    map.put(IT_UNCOVERED_CONDITIONS_KEY, UNCOVERED_CONDITIONS);
-    map.put(IT_CONDITIONS_TO_COVER_KEY, CONDITIONS_TO_COVER);
-    map.put(IT_CONDITIONS_BY_LINE_KEY, CONDITIONS_BY_LINE);
-    map.put(IT_COVERED_CONDITIONS_BY_LINE_KEY, COVERED_CONDITIONS_BY_LINE);
-    map.put(IT_COVERAGE_LINE_HITS_DATA_KEY, COVERAGE_LINE_HITS_DATA);
-    map.put(OVERALL_COVERAGE_KEY, COVERAGE);
-    map.put(OVERALL_LINE_COVERAGE_KEY, LINE_COVERAGE);
-    map.put(OVERALL_BRANCH_COVERAGE_KEY, BRANCH_COVERAGE);
-    map.put(OVERALL_UNCOVERED_LINES_KEY, UNCOVERED_LINES);
-    map.put(OVERALL_LINES_TO_COVER_KEY, LINES_TO_COVER);
-    map.put(OVERALL_UNCOVERED_CONDITIONS_KEY, UNCOVERED_CONDITIONS);
-    map.put(OVERALL_CONDITIONS_TO_COVER_KEY, CONDITIONS_TO_COVER);
-    map.put(OVERALL_CONDITIONS_BY_LINE_KEY, CONDITIONS_BY_LINE);
-    map.put(OVERALL_COVERED_CONDITIONS_BY_LINE_KEY, COVERED_CONDITIONS_BY_LINE);
-    map.put(OVERALL_COVERAGE_LINE_HITS_DATA_KEY, COVERAGE_LINE_HITS_DATA);
-    DEPRECATED_COVERAGE_METRICS_MAPPING = Collections.unmodifiableMap(map);
-  }
-
   private final MetricFinder metricFinder;
   private final IssuePublisher moduleIssues;
   private final ReportPublisher reportPublisher;
-  private final MeasureCache measureCache;
   private final SonarCpdBlockIndex index;
   private final ContextPropertiesCache contextPropertiesCache;
   private final Configuration settings;
@@ -193,13 +115,12 @@ public class DefaultSensorStorage implements SensorStorage {
   private final Set<String> alreadyLogged = new HashSet<>();
 
   public DefaultSensorStorage(MetricFinder metricFinder, IssuePublisher moduleIssues, Configuration settings,
-                              ReportPublisher reportPublisher, MeasureCache measureCache, SonarCpdBlockIndex index,
-                              ContextPropertiesCache contextPropertiesCache, ScannerMetrics scannerMetrics, BranchConfiguration branchConfiguration) {
+    ReportPublisher reportPublisher, SonarCpdBlockIndex index,
+    ContextPropertiesCache contextPropertiesCache, ScannerMetrics scannerMetrics, BranchConfiguration branchConfiguration) {
     this.metricFinder = metricFinder;
     this.moduleIssues = moduleIssues;
     this.settings = settings;
     this.reportPublisher = reportPublisher;
-    this.measureCache = measureCache;
     this.index = index;
     this.contextPropertiesCache = contextPropertiesCache;
     this.scannerMetrics = scannerMetrics;
@@ -243,107 +164,48 @@ public class DefaultSensorStorage implements SensorStorage {
       return;
     }
 
-    DefaultMeasure measureToSave;
-    if (DEPRECATED_COVERAGE_METRICS_MAPPING.containsKey(metric.key())) {
-      metric = DEPRECATED_COVERAGE_METRICS_MAPPING.get(metric.key());
-      measureToSave = new DefaultMeasure<>()
-        .forMetric(metric)
-        .on(measure.inputComponent())
-        .withValue(measure.value());
-    } else {
-      measureToSave = measure;
-    }
-
     if (!scannerMetrics.getMetrics().contains(metric)) {
       throw new UnsupportedOperationException("Metric '" + metric.key() + "' should not be computed by a Sensor");
     }
 
-    if (COVERAGE_METRIC_KEYS.contains(metric.key())) {
-      logOnce(metric.key(), "Coverage measure for metric '{}' should not be saved directly by a Sensor. Plugin should be updated to use SensorContext::newCoverage instead.",
-        metric.key());
-      if (!component.isFile()) {
-        throw new UnsupportedOperationException("Saving coverage measure is only allowed on files. Attempt to save '" + metric.key() + "' on '" + component.key() + "'");
-      }
-      if (((DefaultInputFile) component).isExcludedForCoverage()) {
-        return;
-      }
-      saveCoverageMetricInternal((InputFile) component, metric, measureToSave);
-    } else {
-      if (measureCache.contains(component.key(), metric.key())) {
-        throw new UnsupportedOperationException("Can not add the same measure twice on " + component + ": " + measure);
-      }
-      measureCache.put(component.key(), metric.key(), measureToSave);
+    if (((DefaultInputComponent) component).hasMeasureFor(metric)) {
+      throw new UnsupportedOperationException("Can not add the same measure twice on " + component + ": " + measure);
     }
-  }
-
-  private void saveCoverageMetricInternal(InputFile file, Metric<?> metric, DefaultMeasure<?> measure) {
-    if (COVERAGE_BY_LINE_METRIC_KEYS.contains(metric.key())) {
-      validateCoverageMeasure((String) measure.value(), file);
-      DefaultMeasure<?> previousMeasure = measureCache.byMetric(file.key(), metric.key());
-      if (previousMeasure != null) {
-        measureCache.put(file.key(), metric.key(), new DefaultMeasure<String>()
-          .forMetric((Metric<String>) metric)
-          .withValue(mergeCoverageLineMetric(metric, (String) previousMeasure.value(), (String) measure.value())));
+    ((DefaultInputComponent) component).setHasMeasureFor(metric);
+    if (metric.key().equals(CoreMetrics.EXECUTABLE_LINES_DATA_KEY)) {
+      if (component.isFile()) {
+        ((DefaultInputFile) component).setExecutableLines(
+          KeyValueFormat.parseIntInt((String) measure.value()).entrySet().stream().filter(e -> e.getValue() > 0).map(Map.Entry::getKey).collect(Collectors.toSet()));
       } else {
-        measureCache.put(file.key(), metric.key(), measure);
+        throw new IllegalArgumentException("Executable lines can only be saved on files");
       }
     } else {
-      // Other coverage metrics are all integer values. Just erase value, it will be recomputed at the end anyway
-      measureCache.put(file.key(), metric.key(), measure);
+      reportPublisher.getWriter().appendComponentMeasure(((DefaultInputComponent) component).scannerId(), toReportMeasure(measure));
     }
   }
 
-  /**
-   * Merge the two line coverage data measures. For lines hits use the sum, and for conditions
-   * keep max value in case they both contains a value for the same line.
-   */
-  static String mergeCoverageLineMetric(Metric<?> metric, String value1, String value2) {
-    Map<Integer, Integer> data1 = KeyValueFormat.parseIntInt(value1);
-    Map<Integer, Integer> data2 = KeyValueFormat.parseIntInt(value2);
-    if (metric.key().equals(COVERAGE_LINE_HITS_DATA_KEY)) {
-      return KeyValueFormat.format(Stream.of(data1, data2)
-        .map(Map::entrySet)
-        .flatMap(Collection::stream)
-        .collect(
-          Collectors.toMap(
-            Map.Entry::getKey,
-            Map.Entry::getValue,
-            Integer::sum,
-            TreeMap::new)));
-    } else {
-      return KeyValueFormat.format(Stream.of(data1, data2)
-        .map(Map::entrySet)
-        .flatMap(Collection::stream)
-        .collect(
-          Collectors.toMap(
-            Map.Entry::getKey,
-            Map.Entry::getValue,
-            Integer::max,
-            TreeMap::new)));
-    }
-  }
-
-  static void validateCoverageMeasure(String value, InputFile inputFile) {
-    Map<Integer, Integer> m = KeyValueFormat.parseIntInt(value);
-    validatePositiveLine(m, inputFile.toString());
-    validateMaxLine(m, inputFile);
-  }
-
-  private static void validateMaxLine(Map<Integer, Integer> m, InputFile inputFile) {
-    int maxLine = inputFile.lines();
-
-    for (int line : m.keySet()) {
-      if (line > maxLine) {
-        throw new IllegalStateException(String.format("Can't create measure for line %d for file '%s' with %d lines", line, inputFile, maxLine));
-      }
-    }
+  public static ScannerReport.Measure toReportMeasure(DefaultMeasure measureToSave) {
+    ScannerReport.Measure.Builder builder = ScannerReport.Measure.newBuilder();
+    builder.setMetricKey(measureToSave.metric().key());
+    setValueAccordingToType(builder, measureToSave);
+    return builder.build();
   }
 
-  private static void validatePositiveLine(Map<Integer, Integer> m, String filePath) {
-    for (int l : m.keySet()) {
-      if (l <= 0) {
-        throw new IllegalStateException(String.format("Measure with line %d for file '%s' must be > 0", l, filePath));
-      }
+  private static void setValueAccordingToType(ScannerReport.Measure.Builder builder, DefaultMeasure<?> measure) {
+    Serializable value = measure.value();
+    Metric<?> metric = measure.metric();
+    if (Boolean.class.equals(metric.valueType())) {
+      builder.setBooleanValue(ScannerReport.Measure.BoolValue.newBuilder().setValue((Boolean) value));
+    } else if (Integer.class.equals(metric.valueType())) {
+      builder.setIntValue(ScannerReport.Measure.IntValue.newBuilder().setValue(((Number) value).intValue()));
+    } else if (Double.class.equals(metric.valueType())) {
+      builder.setDoubleValue(ScannerReport.Measure.DoubleValue.newBuilder().setValue(((Number) value).doubleValue()));
+    } else if (String.class.equals(metric.valueType())) {
+      builder.setStringValue(ScannerReport.Measure.StringValue.newBuilder().setValue((String) value));
+    } else if (Long.class.equals(metric.valueType())) {
+      builder.setLongValue(ScannerReport.Measure.LongValue.newBuilder().setValue(((Number) value).longValue()));
+    } else {
+      throw new UnsupportedOperationException("Unsupported type :" + metric.valueType());
     }
   }
 
@@ -462,22 +324,51 @@ public class DefaultSensorStorage implements SensorStorage {
   public void store(DefaultCoverage defaultCoverage) {
     DefaultInputFile inputFile = (DefaultInputFile) defaultCoverage.inputFile();
     inputFile.setPublished(true);
-    if (defaultCoverage.linesToCover() > 0) {
-      saveCoverageMetricInternal(inputFile, LINES_TO_COVER, new DefaultMeasure<Integer>().forMetric(LINES_TO_COVER).withValue(defaultCoverage.linesToCover()));
-      saveCoverageMetricInternal(inputFile, UNCOVERED_LINES,
-        new DefaultMeasure<Integer>().forMetric(UNCOVERED_LINES).withValue(defaultCoverage.linesToCover() - defaultCoverage.coveredLines()));
-      saveCoverageMetricInternal(inputFile, COVERAGE_LINE_HITS_DATA,
-        new DefaultMeasure<String>().forMetric(COVERAGE_LINE_HITS_DATA).withValue(KeyValueFormat.format(defaultCoverage.hitsByLine())));
+
+    Map<Integer, ScannerReport.LineCoverage.Builder> coveragePerLine = reloadExistingCoverage(inputFile);
+
+    int lineCount = inputFile.lines();
+    mergeLineCoverageValues(lineCount, defaultCoverage.hitsByLine(), coveragePerLine, (value, builder) -> builder.setHits(builder.getHits() || value > 0));
+    mergeLineCoverageValues(lineCount, defaultCoverage.conditionsByLine(), coveragePerLine, (value, builder) -> builder.setConditions(max(value, builder.getConditions())));
+    mergeLineCoverageValues(lineCount, defaultCoverage.coveredConditionsByLine(), coveragePerLine,
+      (value, builder) -> builder.setCoveredConditions(max(value, builder.getCoveredConditions())));
+
+    reportPublisher.getWriter().writeComponentCoverage(inputFile.scannerId(),
+      coveragePerLine.values().stream().map(ScannerReport.LineCoverage.Builder::build).collect(Collectors.toList()));
+
+  }
+
+  private Map<Integer, ScannerReport.LineCoverage.Builder> reloadExistingCoverage(DefaultInputFile inputFile) {
+    Map<Integer, ScannerReport.LineCoverage.Builder> coveragePerLine = new LinkedHashMap<>();
+    try (CloseableIterator<ScannerReport.LineCoverage> lineCoverageCloseableIterator = reportPublisher.getReader().readComponentCoverage(inputFile.scannerId())) {
+      while (lineCoverageCloseableIterator.hasNext()) {
+        final ScannerReport.LineCoverage lineCoverage = lineCoverageCloseableIterator.next();
+        coveragePerLine.put(lineCoverage.getLine(), ScannerReport.LineCoverage.newBuilder(lineCoverage));
+      }
+    }
+    return coveragePerLine;
+  }
+
+  interface LineCoverageOperation {
+    void apply(Integer value, ScannerReport.LineCoverage.Builder builder);
+  }
+
+  private void mergeLineCoverageValues(int lineCount, SortedMap<Integer, Integer> valueByLine, Map<Integer, ScannerReport.LineCoverage.Builder> coveragePerLine,
+    LineCoverageOperation op) {
+    for (Map.Entry<Integer, Integer> lineMeasure : valueByLine.entrySet()) {
+      int lineIdx = lineMeasure.getKey();
+      if (lineIdx <= lineCount) {
+        Integer value = lineMeasure.getValue();
+        op.apply(value, coveragePerLine.computeIfAbsent(lineIdx, line -> ScannerReport.LineCoverage.newBuilder().setLine(line)));
+      }
     }
-    if (defaultCoverage.conditions() > 0) {
-      saveCoverageMetricInternal(inputFile, CONDITIONS_TO_COVER,
-        new DefaultMeasure<Integer>().forMetric(CONDITIONS_TO_COVER).withValue(defaultCoverage.conditions()));
-      saveCoverageMetricInternal(inputFile, UNCOVERED_CONDITIONS,
-        new DefaultMeasure<Integer>().forMetric(UNCOVERED_CONDITIONS).withValue(defaultCoverage.conditions() - defaultCoverage.coveredConditions()));
-      saveCoverageMetricInternal(inputFile, COVERED_CONDITIONS_BY_LINE,
-        new DefaultMeasure<String>().forMetric(COVERED_CONDITIONS_BY_LINE).withValue(KeyValueFormat.format(defaultCoverage.coveredConditionsByLine())));
-      saveCoverageMetricInternal(inputFile, CONDITIONS_BY_LINE,
-        new DefaultMeasure<String>().forMetric(CONDITIONS_BY_LINE).withValue(KeyValueFormat.format(defaultCoverage.conditionsByLine())));
+  }
+
+  private static void validatePositiveLine(Map<Integer, Integer> m, String filePath) {
+    for (int l : m.keySet()) {
+      if (l <= 0) {
+        throw new IllegalStateException(String.format("Measure with line %d for file '%s' must be > 0", l, filePath));
+      }
     }
   }
 
index ffec3a709ef1ae4647364a44cbd7c12fdb441c46..f549ec6216c3aab710ac949efe4232f3ac68fb31 100644 (file)
  */
 package org.sonar.scanner.source;
 
-import com.google.common.collect.Sets;
-import java.util.Map;
 import java.util.Set;
-import java.util.stream.StreamSupport;
 import org.sonar.api.batch.Phase;
 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.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.measure.Metric;
-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.coverage.CoverageType;
 import org.sonar.api.batch.sensor.coverage.NewCoverage;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.scanner.scan.measure.MeasureCache;
-
-import static org.sonar.core.util.stream.MoreCollectors.toSet;
+import org.sonar.api.scanner.sensor.ProjectSensor;
+import org.sonar.scanner.report.ReportPublisher;
 
 @Phase(name = Phase.Name.POST)
-public final class ZeroCoverageSensor implements Sensor {
+public final class ZeroCoverageSensor implements ProjectSensor {
 
-  private final MeasureCache measureCache;
+  private final ReportPublisher reportPublisher;
 
-  public ZeroCoverageSensor(MeasureCache measureCache) {
-    this.measureCache = measureCache;
+  public ZeroCoverageSensor(ReportPublisher reportPublisher) {
+    this.reportPublisher = reportPublisher;
   }
 
   @Override
   public void describe(SensorDescriptor descriptor) {
-    descriptor.name("Zero Coverage Sensor")
-      .global();
+    descriptor.name("Zero Coverage Sensor");
   }
 
   @Override
@@ -63,32 +52,26 @@ public final class ZeroCoverageSensor implements Sensor {
       if (((DefaultInputFile) f).isExcludedForCoverage()) {
         continue;
       }
-      if (!isCoverageMeasuresAlreadyDefined(f)) {
-        DefaultMeasure<String> execLines = (DefaultMeasure<String>) measureCache.byMetric(f.key(), CoreMetrics.EXECUTABLE_LINES_DATA_KEY);
-        if (execLines != null) {
+      if (!isCoverageAlreadyDefined(f)) {
+        ((DefaultInputFile) f).getExecutableLines().ifPresent(execLines -> {
           storeZeroCoverageForEachExecutableLine(context, f, execLines);
-        }
+        });
       }
     }
   }
 
-  private static void storeZeroCoverageForEachExecutableLine(final SensorContext context, InputFile f, DefaultMeasure<String> execLines) {
+  private static void storeZeroCoverageForEachExecutableLine(final SensorContext context, InputFile f, Set<Integer> executableLines) {
     NewCoverage newCoverage = context.newCoverage().onFile(f);
-    Map<Integer, Integer> lineMeasures = KeyValueFormat.parseIntInt((String) execLines.value());
-    for (Map.Entry<Integer, Integer> lineMeasure : lineMeasures.entrySet()) {
-      int lineIdx = lineMeasure.getKey();
-      if (lineIdx <= f.lines() && lineMeasure.getValue() > 0) {
+    for (Integer lineIdx : executableLines) {
+      if (lineIdx <= f.lines()) {
         newCoverage.lineHits(lineIdx, 0);
       }
     }
     newCoverage.save();
   }
 
-  private boolean isCoverageMeasuresAlreadyDefined(InputFile f) {
-    Set<String> metricKeys = StreamSupport.stream(measureCache.byComponentKey(f.key()).spliterator(), false)
-      .map(m -> m.metric().key()).collect(toSet());
-    Set<String> allCoverageMetricKeys = CoverageType.UNIT.allMetrics().stream().map(Metric::key).collect(toSet());
-    return !Sets.intersection(metricKeys, allCoverageMetricKeys).isEmpty();
+  private boolean isCoverageAlreadyDefined(InputFile f) {
+    return reportPublisher.getReader().hasCoverage(((DefaultInputFile) f).scannerId());
   }
 
 }
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/Storage.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/Storage.java
deleted file mode 100644 (file)
index c7b6463..0000000
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.storage;
-
-import com.persistit.Exchange;
-import com.persistit.Key;
-import com.persistit.KeyFilter;
-import com.persistit.exception.PersistitException;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import org.apache.commons.lang.builder.ToStringBuilder;
-
-/**
- * <p>
- * This storage is not thread-safe, due to direct usage of {@link com.persistit.Exchange}
- * </p>
- */
-public class Storage<V> {
-
-  private final String name;
-  private final Exchange exchange;
-
-  Storage(String name, Exchange exchange) {
-    this.name = name;
-    this.exchange = exchange;
-  }
-
-  public Storage<V> put(Object key, V value) {
-    resetKey(key);
-    return doPut(value);
-  }
-
-  public Storage<V> put(Object firstKey, Object secondKey, V value) {
-    resetKey(firstKey, secondKey);
-    return doPut(value);
-  }
-
-  public Storage<V> put(Object firstKey, Object secondKey, Object thirdKey, V value) {
-    resetKey(firstKey, secondKey, thirdKey);
-    return doPut(value);
-  }
-
-  public Storage<V> put(Object[] key, V value) {
-    resetKey(key);
-    return doPut(value);
-  }
-
-  private Storage<V> doPut(V value) {
-    try {
-      exchange.getValue().put(value);
-      exchange.store();
-      return this;
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to put element in the storage '" + name + "'", e);
-    }
-  }
-
-  /**
-   * Returns the value object associated with keys, or null if not found.
-   */
-  public V get(Object key) {
-    resetKey(key);
-    return doGet();
-  }
-
-  /**
-   * Returns the value object associated with keys, or null if not found.
-   */
-  @CheckForNull
-  public V get(Object firstKey, Object secondKey) {
-    resetKey(firstKey, secondKey);
-    return doGet();
-  }
-
-  /**
-   * Returns the value object associated with keys, or null if not found.
-   */
-  @CheckForNull
-  public V get(Object firstKey, Object secondKey, Object thirdKey) {
-    resetKey(firstKey, secondKey, thirdKey);
-    return doGet();
-  }
-
-  /**
-   * Returns the value object associated with keys, or null if not found.
-   */
-  @CheckForNull
-  public V get(Object[] key) {
-    resetKey(key);
-    return doGet();
-  }
-
-  @SuppressWarnings("unchecked")
-  @CheckForNull
-  private V doGet() {
-    try {
-      exchange.fetch();
-      if (!exchange.getValue().isDefined()) {
-        return null;
-      }
-      return (V) exchange.getValue().get();
-    } catch (Exception e) {
-      // TODO add parameters to message
-      throw new IllegalStateException("Fail to get element from cache " + name, e);
-    }
-  }
-
-  public boolean containsKey(Object key) {
-    resetKey(key);
-    return doContainsKey();
-  }
-
-  public boolean containsKey(Object firstKey, Object secondKey) {
-    resetKey(firstKey, secondKey);
-    return doContainsKey();
-  }
-
-  public boolean containsKey(Object firstKey, Object secondKey, Object thirdKey) {
-    resetKey(firstKey, secondKey, thirdKey);
-    return doContainsKey();
-  }
-
-  public boolean containsKey(Object[] key) {
-    resetKey(key);
-    return doContainsKey();
-  }
-
-  private boolean doContainsKey() {
-    try {
-      exchange.fetch();
-      return exchange.isValueDefined();
-    } catch (Exception e) {
-      // TODO add parameters to message
-      throw new IllegalStateException("Fail to check if element is in cache " + name, e);
-    }
-  }
-
-  public boolean remove(Object key) {
-    resetKey(key);
-    return doRemove();
-  }
-
-  public boolean remove(Object firstKey, Object secondKey) {
-    resetKey(firstKey, secondKey);
-    return doRemove();
-  }
-
-  public boolean remove(Object firstKey, Object secondKey, Object thirdKey) {
-    resetKey(firstKey, secondKey, thirdKey);
-    return doRemove();
-  }
-
-  public boolean remove(Object[] key) {
-    resetKey(key);
-    return doRemove();
-  }
-
-  private boolean doRemove() {
-    try {
-      return exchange.remove();
-    } catch (Exception e) {
-      // TODO add parameters to message
-      throw new IllegalStateException("Fail to get element from cache " + name, e);
-    }
-  }
-
-  /**
-   * Removes everything in the specified group.
-   */
-  public Storage<V> clear(Object key) {
-    resetKey(key);
-    return doClear();
-  }
-
-  public Storage<V> clear(Object firstKey, Object secondKey) {
-    resetKey(firstKey, secondKey);
-    return doClear();
-  }
-
-  public Storage<V> clear(Object firstKey, Object secondKey, Object thirdKey) {
-    resetKey(firstKey, secondKey, thirdKey);
-    return doClear();
-  }
-
-  public Storage<V> clear(Object[] key) {
-    resetKey(key);
-    return doClear();
-  }
-
-  private Storage<V> doClear() {
-    try {
-      Key to = new Key(exchange.getKey());
-      to.append(Key.AFTER);
-      exchange.removeKeyRange(exchange.getKey(), to);
-      return this;
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to clear values from cache " + name, e);
-    }
-  }
-
-  /**
-   * Clears the default as well as all group caches.
-   */
-  public void clear() {
-    try {
-      exchange.clear();
-      exchange.removeAll();
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to clear cache", e);
-    }
-  }
-
-  /**
-   * Returns the set of cache keys associated with this group.
-   * TODO implement a lazy-loading equivalent with Iterator/Iterable
-   *
-   * @return The set of cache keys for this group.
-   */
-  @SuppressWarnings("rawtypes")
-  public Set keySet(Object key) {
-    try {
-      Set<Object> keys = new LinkedHashSet<>();
-      exchange.clear();
-      Exchange iteratorExchange = new Exchange(exchange);
-      iteratorExchange.append(key);
-      iteratorExchange.append(Key.BEFORE);
-      while (iteratorExchange.next(false)) {
-        keys.add(iteratorExchange.getKey().indexTo(-1).decode());
-      }
-      return keys;
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to get keys from cache " + name, e);
-    }
-  }
-
-  @SuppressWarnings("rawtypes")
-  public Set keySet(Object firstKey, Object secondKey) {
-    try {
-      Set<Object> keys = new LinkedHashSet<>();
-      exchange.clear();
-      Exchange iteratorExchange = new Exchange(exchange);
-      iteratorExchange.append(firstKey);
-      iteratorExchange.append(secondKey);
-      iteratorExchange.append(Key.BEFORE);
-      while (iteratorExchange.next(false)) {
-        keys.add(iteratorExchange.getKey().indexTo(-1).decode());
-      }
-      return keys;
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to get keys from cache " + name, e);
-    }
-  }
-
-  /**
-   * Returns the set of keys associated with this cache.
-   *
-   * @return The set containing the keys for this cache.
-   */
-  public Set<Object> keySet() {
-    try {
-      Set<Object> keys = new LinkedHashSet<>();
-      exchange.clear();
-      Exchange iteratorExchange = new Exchange(exchange);
-      iteratorExchange.append(Key.BEFORE);
-      while (iteratorExchange.next(false)) {
-        keys.add(iteratorExchange.getKey().indexTo(-1).decode());
-      }
-      return keys;
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to get keys from cache " + name, e);
-    }
-  }
-
-  /**
-   * Lazy-loading values for given keys
-   */
-  public Iterable<V> values(Object firstKey, Object secondKey) {
-    return new ValueIterable<>(exchange, firstKey, secondKey);
-  }
-
-  /**
-   * Lazy-loading values for a given key
-   */
-  public Iterable<V> values(Object firstKey) {
-    return new ValueIterable<>(exchange, firstKey);
-  }
-
-  /**
-   * Lazy-loading values
-   */
-  public Iterable<V> values() {
-    return new ValueIterable<>(exchange);
-  }
-
-  public Iterable<Entry<V>> entries() {
-    return new EntryIterable<>(exchange);
-  }
-
-  public Iterable<Entry<V>> entries(Object firstKey) {
-    return new EntryIterable<>(exchange, firstKey);
-  }
-
-  private void resetKey(Object key) {
-    exchange.clear();
-    exchange.append(key);
-  }
-
-  private void resetKey(Object first, Object second) {
-    exchange.clear();
-    exchange.append(first).append(second);
-  }
-
-  private void resetKey(Object first, Object second, Object third) {
-    exchange.clear();
-    exchange.append(first).append(second).append(third);
-  }
-
-  private void resetKey(Object[] keys) {
-    exchange.clear();
-    for (Object o : keys) {
-      exchange.append(o);
-    }
-  }
-
-  //
-  // LAZY ITERATORS AND ITERABLES
-  //
-
-  private static class ValueIterable<T> implements Iterable<T> {
-    private final Exchange originExchange;
-    private final Object[] keys;
-
-    private ValueIterable(Exchange originExchange, Object... keys) {
-      this.originExchange = originExchange;
-      this.keys = keys;
-    }
-
-    @Override
-    public Iterator<T> iterator() {
-      originExchange.clear();
-      KeyFilter filter = new KeyFilter();
-      for (Object key : keys) {
-        originExchange.append(key);
-        filter = filter.append(KeyFilter.simpleTerm(key));
-      }
-      originExchange.append(Key.BEFORE);
-      Exchange iteratorExchange = new Exchange(originExchange);
-      return new ValueIterator<>(iteratorExchange, filter);
-    }
-  }
-
-  private static class ValueIterator<T> implements Iterator<T> {
-    private final Exchange exchange;
-    private final KeyFilter keyFilter;
-
-    private ValueIterator(Exchange exchange, KeyFilter keyFilter) {
-      this.exchange = exchange;
-      this.keyFilter = keyFilter;
-    }
-
-    @Override
-    public boolean hasNext() {
-      try {
-        return exchange.hasNext(keyFilter);
-      } catch (PersistitException e) {
-        throw new IllegalStateException(e);
-      }
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public T next() {
-      try {
-        exchange.next(keyFilter);
-      } catch (PersistitException e) {
-        throw new IllegalStateException(e);
-      }
-      if (exchange.getValue().isDefined()) {
-        return (T) exchange.getValue().get();
-      }
-      throw new NoSuchElementException();
-    }
-
-    @Override
-    public void remove() {
-      throw new UnsupportedOperationException("Removing an item is not supported");
-    }
-  }
-
-  private static class EntryIterable<T> implements Iterable<Entry<T>> {
-    private final Exchange originExchange;
-    private final Object[] keys;
-
-    private EntryIterable(Exchange originExchange, Object... keys) {
-      this.originExchange = originExchange;
-      this.keys = keys;
-    }
-
-    @Override
-    public Iterator<Entry<T>> iterator() {
-      originExchange.clear();
-      KeyFilter filter = new KeyFilter();
-      for (Object key : keys) {
-        originExchange.append(key);
-        filter = filter.append(KeyFilter.simpleTerm(key));
-      }
-      originExchange.append(Key.BEFORE);
-      Exchange iteratorExchange = new Exchange(originExchange);
-      return new EntryIterator<>(iteratorExchange, filter);
-    }
-  }
-
-  private static class EntryIterator<T> implements Iterator<Entry<T>> {
-    private final Exchange exchange;
-    private final KeyFilter keyFilter;
-
-    private EntryIterator(Exchange exchange, KeyFilter keyFilter) {
-      this.exchange = exchange;
-      this.keyFilter = keyFilter;
-    }
-
-    @Override
-    public boolean hasNext() {
-      try {
-        return exchange.hasNext(keyFilter);
-      } catch (PersistitException e) {
-        throw new IllegalStateException(e);
-      }
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Entry<T> next() {
-      try {
-        exchange.next(keyFilter);
-      } catch (PersistitException e) {
-        throw new IllegalStateException(e);
-      }
-      if (exchange.getValue().isDefined()) {
-        T value = (T) exchange.getValue().get();
-        Key key = exchange.getKey();
-        Object[] array = new Object[key.getDepth()];
-        for (int i = 0; i < key.getDepth(); i++) {
-          array[i] = key.indexTo(i - key.getDepth()).decode();
-        }
-        return new Entry<>(array, value);
-      }
-      throw new NoSuchElementException();
-    }
-
-    @Override
-    public void remove() {
-      throw new UnsupportedOperationException("Removing an item is not supported");
-    }
-  }
-
-  public static class Entry<V> {
-    private final Object[] key;
-    private final V value;
-
-    Entry(Object[] key, V value) {
-      this.key = key;
-      this.value = value;
-    }
-
-    public Object[] key() {
-      return key;
-    }
-
-    public V value() {
-      return value;
-    }
-
-    @Override
-    public String toString() {
-      return ToStringBuilder.reflectionToString(this);
-    }
-  }
-
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/Storages.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/Storages.java
deleted file mode 100644 (file)
index 23827eb..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.storage;
-
-import com.google.common.base.Preconditions;
-import com.persistit.Exchange;
-import com.persistit.Persistit;
-import com.persistit.Value;
-import com.persistit.Volume;
-import com.persistit.encoding.CoderManager;
-import com.persistit.encoding.ValueCoder;
-import com.persistit.exception.PersistitException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import org.picocontainer.Startable;
-
-public class Storages implements Startable {
-  private final Map<String, Exchange> cacheMap = new HashMap<>();
-  private Persistit persistit;
-  private Volume volume;
-
-  public Storages(StoragesManager storagesManager) {
-    persistit = storagesManager.persistit();
-    doStart();
-  }
-
-  @Override
-  public void start() {
-    // done in constructor
-  }
-
-  private void doStart() {
-    try {
-      persistit.flush();
-      volume = persistit.createTemporaryVolume();
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to create a cache volume", e);
-    }
-  }
-
-  public void registerValueCoder(Class<?> clazz, ValueCoder coder) {
-    CoderManager cm = persistit.getCoderManager();
-    cm.registerValueCoder(clazz, coder);
-  }
-
-  public <V> Storage<V> createCache(String cacheName) {
-    Preconditions.checkState(volume != null && volume.isOpened(), "Caches are not initialized");
-    Preconditions.checkState(!cacheMap.containsKey(cacheName), "Cache is already created: %s", cacheName);
-    try {
-      Exchange exchange = persistit.getExchange(volume, cacheName, true);
-      exchange.setMaximumValueSize(Value.MAXIMUM_SIZE);
-      Storage<V> cache = new Storage<>(cacheName, exchange);
-      cacheMap.put(cacheName, exchange);
-      return cache;
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to create cache: " + cacheName, e);
-    }
-  }
-
-  @Override
-  public void stop() {
-    for (Entry<String, Exchange> e : cacheMap.entrySet()) {
-      persistit.releaseExchange(e.getValue());
-    }
-
-    cacheMap.clear();
-
-    if (volume != null) {
-      try {
-        volume.close();
-        volume.delete();
-      } catch (PersistitException e) {
-        throw new IllegalStateException("Fail to close caches", e);
-      }
-      volume = null;
-    }
-  }
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/StoragesManager.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/StoragesManager.java
deleted file mode 100644 (file)
index 3f1b1d9..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.storage;
-
-import com.persistit.Persistit;
-import com.persistit.exception.PersistitException;
-import com.persistit.logging.Slf4jAdapter;
-import java.io.File;
-import java.util.Properties;
-import org.picocontainer.Startable;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.utils.TempFolder;
-
-import static org.sonar.core.util.FileUtils.deleteQuietly;
-
-/**
- * Factory of storages
- *
- * @since 3.6
- */
-public class StoragesManager implements Startable {
-  private File tempDir;
-  private Persistit persistit;
-  private final TempFolder tempFolder;
-
-  public StoragesManager(TempFolder tempFolder) {
-    this.tempFolder = tempFolder;
-    initPersistit();
-  }
-
-  private void initPersistit() {
-    try {
-      tempDir = tempFolder.newDir("caches");
-      persistit = new Persistit();
-      persistit.setPersistitLogger(new Slf4jAdapter(LoggerFactory.getLogger("PERSISTIT")));
-      Properties props = new Properties();
-      props.setProperty("datapath", tempDir.getAbsolutePath());
-      props.setProperty("logpath", "${datapath}/log");
-      props.setProperty("logfile", "${logpath}/persistit_${timestamp}.log");
-      props.setProperty("buffer.count.8192", "10");
-      props.setProperty("journalpath", "${datapath}/journal");
-      props.setProperty("tmpvoldir", "${datapath}");
-      props.setProperty("volume.1", "${datapath}/persistit,create,pageSize:8192,initialPages:10,extensionPages:100,maximumPages:25000");
-      props.setProperty("jmx", "false");
-      persistit.setProperties(props);
-      persistit.initialize();
-
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to start caches", e);
-    }
-  }
-
-  @Override
-  public void start() {
-    // already started in constructor
-  }
-
-  @Override
-  public void stop() {
-    if (persistit != null) {
-      try {
-        persistit.close(false);
-        persistit = null;
-      } catch (PersistitException e) {
-        throw new IllegalStateException("Fail to close caches", e);
-      }
-    }
-    deleteQuietly(tempDir);
-    tempDir = null;
-  }
-
-  File tempDir() {
-    return tempDir;
-  }
-
-  Persistit persistit() {
-    return persistit;
-  }
-}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/package-info.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/storage/package-info.java
deleted file mode 100644 (file)
index 8187995..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.scanner.storage;
-
-import javax.annotation.ParametersAreNonnullByDefault;
index 7d28d4972305af11f1100f5c6e85159cc9c701ea..6bd3a77f43c7d00e651e5e46ab5406b9921d61f4 100644 (file)
@@ -31,13 +31,9 @@ import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.sensor.internal.SensorStorage;
 import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.scanner.scan.measure.MeasureCache;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -56,7 +52,6 @@ public class DefaultFileLinesContextTest {
 
   private DefaultFileLinesContext fileLineMeasures;
 
-  private MeasureCache measureCache;
   private SensorStorage sensorStorage;
   private DefaultInputFile file;
 
@@ -77,11 +72,9 @@ public class DefaultFileLinesContextTest {
     when(metricFinder.<String>findByKey(BRANCHES_METRIC_KEY)).thenReturn(branchesMetric);
     when(metricFinder.<String>findByKey(CoreMetrics.NCLOC_DATA_KEY)).thenReturn(CoreMetrics.NCLOC_DATA);
     when(metricFinder.<String>findByKey(CoreMetrics.EXECUTABLE_LINES_DATA_KEY)).thenReturn(CoreMetrics.EXECUTABLE_LINES_DATA);
-    measureCache = mock(MeasureCache.class);
     sensorStorage = mock(SensorStorage.class);
     file = new TestInputFileBuilder("foo", "src/foo.php").initMetadata("Foo\nbar\nbiz").build();
-    fileLineMeasures = new DefaultFileLinesContext(sensorStorage, file, metricFinder,
-      measureCache);
+    fileLineMeasures = new DefaultFileLinesContext(sensorStorage, file, metricFinder);
   }
 
   @Test
@@ -158,36 +151,5 @@ public class DefaultFileLinesContextTest {
     fileLineMeasures.setIntValue(HITS_METRIC_KEY, 1, 2);
   }
 
-  @Test
-  public void shouldLoadIntValues() {
-    when(measureCache.byMetric("foo:src/foo.php", HITS_METRIC_KEY)).thenReturn(new DefaultMeasure().withValue("1=2;3=4"));
-
-    assertThat(fileLineMeasures.getIntValue(HITS_METRIC_KEY, 1), is(2));
-    assertThat(fileLineMeasures.getIntValue(HITS_METRIC_KEY, 3), is(4));
-    assertThat("no measure on line", fileLineMeasures.getIntValue(HITS_METRIC_KEY, 2), nullValue());
-  }
-
-  @Test
-  public void shouldLoadStringValues() {
-    when(measureCache.byMetric("foo:src/foo.php", AUTHOR_METRIC_KEY)).thenReturn(new DefaultMeasure().withValue("1=simon;3=evgeny"));
-
-    assertThat(fileLineMeasures.getStringValue(AUTHOR_METRIC_KEY, 1), is("simon"));
-    assertThat(fileLineMeasures.getStringValue(AUTHOR_METRIC_KEY, 3), is("evgeny"));
-    assertThat("no measure on line", fileLineMeasures.getStringValue(AUTHOR_METRIC_KEY, 2), nullValue());
-  }
-
-  @Test(expected = UnsupportedOperationException.class)
-  public void shouldNotModifyAfterLoad() {
-    when(measureCache.byMetric("foo:src/foo.php", AUTHOR_METRIC_KEY)).thenReturn(new DefaultMeasure().withValue("1=simon;3=evgeny"));
-
-    fileLineMeasures.getStringValue(AUTHOR_METRIC_KEY, 1);
-    fileLineMeasures.setStringValue(AUTHOR_METRIC_KEY, 1, "evgeny");
-  }
-
-  @Test
-  public void shouldNotFailIfNoMeasureInIndex() {
-    assertThat(fileLineMeasures.getIntValue(HITS_METRIC_KEY, 1), nullValue());
-    assertThat(fileLineMeasures.getStringValue(AUTHOR_METRIC_KEY, 1), nullValue());
-  }
 
 }
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/index/AbstractCachesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/index/AbstractCachesTest.java
deleted file mode 100644 (file)
index c2b1580..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.index;
-
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.CoreProperties;
-import org.sonar.scanner.bootstrap.GlobalTempFolderProvider;
-import org.sonar.scanner.bootstrap.RawScannerProperties;
-import org.sonar.scanner.storage.Storages;
-import org.sonar.scanner.storage.StoragesManager;
-
-public abstract class AbstractCachesTest {
-  @ClassRule
-  public static TemporaryFolder temp = new TemporaryFolder();
-
-  protected static StoragesManager cachesManager;
-  protected Storages caches;
-
-  private static StoragesManager createCacheOnTemp() {
-    Map<String, String> props = ImmutableMap.of(CoreProperties.WORKING_DIRECTORY, temp.getRoot().getAbsolutePath(),
-      CoreProperties.GLOBAL_WORKING_DIRECTORY, temp.getRoot().getAbsolutePath());
-
-    return new StoragesManager(new GlobalTempFolderProvider().provide(new RawScannerProperties(props)));
-  }
-
-  @BeforeClass
-  public static void startClass() {
-    cachesManager = createCacheOnTemp();
-    cachesManager.start();
-  }
-
-  @Before
-  public void start() {
-    caches = new Storages(cachesManager);
-    caches.start();
-  }
-
-  @After
-  public void stop() {
-    if (caches != null) {
-      caches.stop();
-      caches = null;
-    }
-  }
-
-  @AfterClass
-  public static void stopClass() {
-    if (cachesManager != null) {
-      cachesManager.stop();
-    }
-  }
-}
index 7c52194f8dec7f2238765cf5949d2b98244acb6b..f376d56999eb9c2a463238316e1a4ea23c205cc6 100644 (file)
@@ -25,13 +25,15 @@ import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import org.apache.commons.io.FileUtils;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.fs.internal.FileMetadata;
-import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.mediumtest.AnalysisResult;
+import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.repository.FileData;
 import org.sonar.scanner.scan.branch.BranchType;
@@ -63,6 +65,9 @@ public class BranchMediumTest {
     Path filepath = baseDir.toPath().resolve(FILE_PATH);
     Files.write(filepath, FILE_CONTENT.getBytes());
 
+    Path xooUtCoverageFile = baseDir.toPath().resolve(FILE_PATH + ".coverage");
+    FileUtils.write(xooUtCoverageFile.toFile(), "1:2:2:1", StandardCharsets.UTF_8);
+
     String md5sum = new FileMetadata()
       .readMetadata(Files.newInputStream(filepath), StandardCharsets.UTF_8, FILE_PATH)
       .hash();
@@ -73,15 +78,18 @@ public class BranchMediumTest {
   public void should_not_skip_report_for_unchanged_files_in_short_branch() {
     // sanity check, normally report gets generated
     AnalysisResult result = getResult(tester);
-    assertThat(getResult(tester).getReportComponent(result.inputFile(FILE_PATH))).isNotNull();
-    int fileId = 2;
+    final DefaultInputFile file = (DefaultInputFile) result.inputFile(FILE_PATH);
+    assertThat(getResult(tester).getReportComponent(file)).isNotNull();
+    int fileId = file.scannerId();
     assertThat(result.getReportReader().readChangesets(fileId)).isNotNull();
     assertThat(result.getReportReader().hasCoverage(fileId)).isTrue();
     assertThat(result.getReportReader().readFileSource(fileId)).isNotNull();
 
     // file is not skipped for short branches (need coverage, duplications coming soon)
     AnalysisResult result2 = getResult(tester.setBranchType(BranchType.SHORT));
-    assertThat(result2.getReportComponent(result2.inputFile(FILE_PATH))).isNotNull();
+    final DefaultInputFile fileOnShortBranch = (DefaultInputFile) result2.inputFile(FILE_PATH);
+    assertThat(result2.getReportComponent(fileOnShortBranch)).isNotNull();
+    fileId = fileOnShortBranch.scannerId();
     assertThat(result2.getReportReader().readChangesets(fileId)).isNull();
     assertThat(result2.getReportReader().hasCoverage(fileId)).isTrue();
     assertThat(result2.getReportReader().readFileSource(fileId)).isNull();
@@ -108,10 +116,8 @@ public class BranchMediumTest {
     return tester
       .newAnalysis()
       .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.task", "scan")
         .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
         .put("sonar.projectKey", PROJECT_KEY)
-        .put("sonar.sources", ".")
         .put("sonar.scm.provider", "xoo")
         .build())
       .execute();
index 0b6744565debb931af820a883857b38281c2e190..c51d03d37858e4cf5b39daddbf1da2be9ec2f20a 100644 (file)
@@ -23,22 +23,18 @@ import com.google.common.collect.ImmutableMap;
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.Map;
 import org.apache.commons.io.FileUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.mediumtest.AnalysisResult;
+import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.xoo.XooPlugin;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
 
 public class CoverageMediumTest {
 
@@ -77,13 +73,6 @@ public class CoverageMediumTest {
     assertThat(result.coverageFor(file, 2).getHits()).isTrue();
     assertThat(result.coverageFor(file, 2).getConditions()).isEqualTo(2);
     assertThat(result.coverageFor(file, 2).getCoveredConditions()).isEqualTo(1);
-
-    Map<String, List<org.sonar.scanner.protocol.output.ScannerReport.Measure>> allMeasures = result.allMeasures();
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value")
-      .contains(tuple(CoreMetrics.LINES_TO_COVER_KEY, 2),
-        tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0),
-        tuple(CoreMetrics.CONDITIONS_TO_COVER_KEY, 2),
-        tuple(CoreMetrics.UNCOVERED_CONDITIONS_KEY, 1));
   }
 
   @Test
@@ -98,7 +87,7 @@ public class CoverageMediumTest {
     File xooUtCoverageFile = new File(srcDir, "sample.xoo.coverage");
     FileUtils.write(xooUtCoverageFile, "2:2:2:2\n4:0", StandardCharsets.UTF_8);
     File xooItCoverageFile = new File(srcDir, "sample.xoo.itcoverage");
-    FileUtils.write(xooItCoverageFile, "2:2:2:1\n3:1\n5:0", StandardCharsets.UTF_8);
+    FileUtils.write(xooItCoverageFile, "2:0:2:1\n3:1\n5:0", StandardCharsets.UTF_8);
 
     AnalysisResult result = tester.newAnalysis()
       .properties(ImmutableMap.<String, String>builder()
@@ -113,16 +102,6 @@ public class CoverageMediumTest {
     assertThat(result.coverageFor(file, 2).getConditions()).isEqualTo(2);
     assertThat(result.coverageFor(file, 2).getCoveredConditions()).isEqualTo(2);
     assertThat(result.coverageFor(file, 3).getHits()).isTrue();
-
-    Map<String, List<org.sonar.scanner.protocol.output.ScannerReport.Measure>> allMeasures = result.allMeasures();
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value", "stringValue.value")
-      .contains(tuple(CoreMetrics.LINES_TO_COVER_KEY, 4, ""), // 2, 3, 4, 5
-        tuple(CoreMetrics.UNCOVERED_LINES_KEY, 2, ""), // 4, 5
-        tuple(CoreMetrics.CONDITIONS_TO_COVER_KEY, 2, ""), // 2 x 2
-        tuple(CoreMetrics.UNCOVERED_CONDITIONS_KEY, 0, ""),
-        tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "2=4;3=1;4=0;5=0"),
-        tuple(CoreMetrics.CONDITIONS_BY_LINE_KEY, 0, "2=2"),
-        tuple(CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY, 0, "2=2"));
   }
 
   @Test
@@ -148,11 +127,6 @@ public class CoverageMediumTest {
 
     InputFile file = result.inputFile("src/sample.xoo");
     assertThat(result.coverageFor(file, 2)).isNull();
-
-    Map<String, List<org.sonar.scanner.protocol.output.ScannerReport.Measure>> allMeasures = result.allMeasures();
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey")
-      .doesNotContain(CoreMetrics.LINES_TO_COVER_KEY, CoreMetrics.UNCOVERED_LINES_KEY, CoreMetrics.CONDITIONS_TO_COVER_KEY,
-        CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY);
   }
 
   @Test
@@ -306,13 +280,6 @@ public class CoverageMediumTest {
 
     assertThat(result.coverageFor(file, 3).getHits()).isFalse();
     assertThat(result.coverageFor(file, 4)).isNull();
-
-    Map<String, List<org.sonar.scanner.protocol.output.ScannerReport.Measure>> allMeasures = result.allMeasures();
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value")
-      .contains(tuple(CoreMetrics.LINES_TO_COVER_KEY, 2),
-        tuple(CoreMetrics.UNCOVERED_LINES_KEY, 2));
-
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey").doesNotContain(CoreMetrics.CONDITIONS_TO_COVER_KEY, CoreMetrics.UNCOVERED_CONDITIONS_KEY);
   }
 
   // SONAR-9557
@@ -359,18 +326,6 @@ public class CoverageMediumTest {
     assertThat(result.coverageFor(file2, 3)).isNull();
     assertThat(result.coverageFor(file2, 4)).isNull();
 
-    Map<String, List<org.sonar.scanner.protocol.output.ScannerReport.Measure>> allMeasures = result.allMeasures();
-
-    assertThat(allMeasures.get("com.foo.project:module1/src/sample1.xoo")).extracting("metricKey", "intValue.value")
-      .contains(tuple(CoreMetrics.LINES_TO_COVER_KEY, 2),
-        tuple(CoreMetrics.UNCOVERED_LINES_KEY, 2));
-
-    assertThat(allMeasures.get("com.foo.project:module1/src/sample1.xoo")).extracting("metricKey").doesNotContain(CoreMetrics.CONDITIONS_TO_COVER_KEY,
-      CoreMetrics.UNCOVERED_CONDITIONS_KEY);
-
-    assertThat(allMeasures.get("com.foo.project:module1/src/sample2.xoo")).extracting("metricKey").doesNotContain(CoreMetrics.LINES_TO_COVER_KEY,
-      CoreMetrics.CONDITIONS_TO_COVER_KEY,
-      CoreMetrics.UNCOVERED_CONDITIONS_KEY, CoreMetrics.UNCOVERED_LINES_KEY);
   }
 
 }
index e41b31e8d601c85363fd05d3fe6d123b7078c9e7..1fc4d93676ca2a93c09fd3c01ba044bcdf4e708a 100644 (file)
@@ -26,13 +26,11 @@ import java.util.List;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.scanner.mediumtest.AnalysisResult;
+import org.sonar.scanner.mediumtest.ScannerMediumTester;
 import org.sonar.xoo.XooPlugin;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
 
 public class GenericCoverageMediumTest {
   private final List<String> logs = new ArrayList<>();
@@ -60,27 +58,11 @@ public class GenericCoverageMediumTest {
 
     assertThat(result.coverageFor(noConditions, 7).getHits()).isFalse();
 
-    assertThat(result.allMeasures().get(noConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value")
-      .containsOnly(
-        tuple(CoreMetrics.LINES_TO_COVER_KEY, 2, ""),
-        tuple(CoreMetrics.UNCOVERED_LINES_KEY, 1, ""),
-        tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "6=1;7=0"));
-
     InputFile withConditions = result.inputFile("xources/hello/WithConditions.xoo");
     assertThat(result.coverageFor(withConditions, 3).getHits()).isTrue();
     assertThat(result.coverageFor(withConditions, 3).getConditions()).isEqualTo(2);
     assertThat(result.coverageFor(withConditions, 3).getCoveredConditions()).isEqualTo(1);
 
-    assertThat(result.allMeasures().get(withConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value")
-      .containsOnly(
-        tuple(CoreMetrics.LINES_TO_COVER_KEY, 1, ""),
-        tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0, ""),
-        tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "3=1"),
-        tuple(CoreMetrics.CONDITIONS_TO_COVER_KEY, 2, ""),
-        tuple(CoreMetrics.UNCOVERED_CONDITIONS_KEY, 1, ""),
-        tuple(CoreMetrics.CONDITIONS_BY_LINE_KEY, 0, "3=2"),
-        tuple(CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY, 0, "3=1")
-    );
     assertThat(logs).noneMatch(l -> l.contains("Please use 'sonar.coverageReportPaths'"));
 
   }
@@ -117,28 +99,11 @@ public class GenericCoverageMediumTest {
 
     assertThat(result.coverageFor(noConditions, 7).getHits()).isTrue();
 
-    assertThat(result.allMeasures().get(noConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value")
-      .containsOnly(
-        tuple(CoreMetrics.LINES_TO_COVER_KEY, 2, ""),
-        tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0, ""),
-        tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "6=1;7=1"));
-
     InputFile withConditions = result.inputFile("xources/hello/WithConditions.xoo");
     assertThat(result.coverageFor(withConditions, 3).getHits()).isTrue();
     assertThat(result.coverageFor(withConditions, 3).getConditions()).isEqualTo(2);
     assertThat(result.coverageFor(withConditions, 3).getCoveredConditions()).isEqualTo(2);
 
-    assertThat(result.allMeasures().get(withConditions.key())).extracting("metricKey", "intValue.value", "stringValue.value")
-      .containsOnly(
-        tuple(CoreMetrics.LINES_TO_COVER_KEY, 1, ""),
-        tuple(CoreMetrics.UNCOVERED_LINES_KEY, 0, ""),
-        tuple(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, 0, "3=2"),
-        tuple(CoreMetrics.CONDITIONS_TO_COVER_KEY, 2, ""),
-        tuple(CoreMetrics.UNCOVERED_CONDITIONS_KEY, 0, ""),
-        tuple(CoreMetrics.CONDITIONS_BY_LINE_KEY, 0, "3=2"),
-        tuple(CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY, 0, "3=2")
-    );
-    
     assertThat(logs).noneMatch(l -> l.contains("Please use 'sonar.coverageReportPaths'"));
   }
   
index 395dff17b10663b0b09331cb9348d4ee92a80c62..34e57146bfee6f1c3a9a39036be7f9630cc1346b 100644 (file)
@@ -64,66 +64,6 @@ public class MeasuresMediumTest {
     srcDir.mkdir();
   }
 
-  @Test
-  public void applyExclusionsOnCoverageMeasures() throws IOException {
-    File xooFile = new File(srcDir, "sample.xoo");
-    FileUtils.write(xooFile, "Sample xoo\n\ncontent", StandardCharsets.UTF_8);
-
-    File measures = new File(srcDir, "sample.xoo.measures");
-    FileUtils.write(measures, "lines_to_cover:2", StandardCharsets.UTF_8);
-
-    AnalysisResult result = tester.newAnalysis()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.sources", "src")
-        .build())
-      .execute();
-
-    Map<String, List<Measure>> allMeasures = result.allMeasures();
-
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value")
-      .containsOnly(tuple("lines_to_cover", 2));
-
-    result = tester.newAnalysis()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.sources", "src")
-        .put("sonar.coverage.exclusions", "src/sample.xoo")
-        .build())
-      .execute();
-
-    allMeasures = result.allMeasures();
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value")
-      .isEmpty();
-  }
-
-  @Test
-  public void deprecatedCoverageMeasuresAreConverted() throws IOException {
-    File xooFile = new File(srcDir, "sample.xoo");
-    FileUtils.write(xooFile, "Sample xoo\n\ncontent", StandardCharsets.UTF_8);
-
-    File measures = new File(srcDir, "sample.xoo.measures");
-    FileUtils.write(measures, "it_lines_to_cover:2", StandardCharsets.UTF_8);
-
-    AnalysisResult result = tester.newAnalysis()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.sources", "src")
-        .build())
-      .execute();
-
-    Map<String, List<Measure>> allMeasures = result.allMeasures();
-
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value")
-      .containsOnly(tuple("lines_to_cover", 2));
-
-    assertThat(logTester.logs(LoggerLevel.WARN))
-      .contains("Coverage measure for metric 'lines_to_cover' should not be saved directly by a Sensor. Plugin should be updated to use SensorContext::newCoverage instead.");
-  }
-
   @Test
   public void failIfTryingToSaveServerSideMeasure() throws IOException {
     File xooFile = new File(srcDir, "sample.xoo");
index 42d7f836bf59ff12492824dc55ebecd45facca0a..62ea71126ae71940c20592c8cd8a911cf533fa45 100644 (file)
@@ -80,12 +80,8 @@ public class ScmMediumTest {
 
     tester.newAnalysis()
       .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.scm.provider", "xoo")
         .build())
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CoveragePublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CoveragePublisherTest.java
deleted file mode 100644 (file)
index f1c75d6..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.report;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.core.util.CloseableIterator;
-import org.sonar.scanner.protocol.output.ScannerReport.LineCoverage;
-import org.sonar.scanner.protocol.output.ScannerReportReader;
-import org.sonar.scanner.protocol.output.ScannerReportWriter;
-import org.sonar.scanner.scan.branch.BranchConfiguration;
-import org.sonar.scanner.scan.filesystem.InputComponentStore;
-import org.sonar.scanner.scan.measure.MeasureCache;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class CoveragePublisherTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  private MeasureCache measureCache;
-  private CoveragePublisher publisher;
-
-  private DefaultInputFile inputFile;
-
-  @Before
-  public void prepare() throws IOException {
-    String moduleKey = "foo";
-    inputFile = new TestInputFileBuilder(moduleKey, "src/Foo.php").setLines(5).build();
-    DefaultInputProject rootModule = TestInputFileBuilder.newDefaultInputProject(moduleKey, temp.newFolder());
-    InputComponentStore componentCache = new InputComponentStore(mock(BranchConfiguration.class));
-    componentCache.put(moduleKey, inputFile);
-
-    measureCache = mock(MeasureCache.class);
-    when(measureCache.byMetric(anyString(), anyString())).thenReturn(null);
-    publisher = new CoveragePublisher(componentCache, measureCache);
-  }
-
-  @Test
-  public void publishCoverage() throws Exception {
-
-    DefaultMeasure<String> utLineHits = new DefaultMeasure<String>().forMetric(CoreMetrics.COVERAGE_LINE_HITS_DATA).withValue("2=1;3=1;5=0;6=3");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY)).thenReturn((DefaultMeasure) utLineHits);
-
-    DefaultMeasure<String> conditionsByLine = new DefaultMeasure<String>().forMetric(CoreMetrics.CONDITIONS_BY_LINE).withValue("3=4");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.CONDITIONS_BY_LINE_KEY)).thenReturn((DefaultMeasure) conditionsByLine);
-
-    DefaultMeasure<String> coveredConditionsByUts = new DefaultMeasure<String>().forMetric(CoreMetrics.COVERED_CONDITIONS_BY_LINE).withValue("3=2");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY)).thenReturn((DefaultMeasure) coveredConditionsByUts);
-
-    File outputDir = temp.newFolder();
-    ScannerReportWriter writer = new ScannerReportWriter(outputDir);
-
-    publisher.publish(writer);
-
-    try (CloseableIterator<LineCoverage> it = new ScannerReportReader(outputDir).readComponentCoverage(inputFile.scannerId())) {
-      assertThat(it.next()).isEqualTo(LineCoverage.newBuilder()
-        .setLine(2)
-        .setHits(true)
-        .build());
-      assertThat(it.next()).isEqualTo(LineCoverage.newBuilder()
-        .setLine(3)
-        .setHits(true)
-        .setConditions(4)
-        .setCoveredConditions(2)
-        .build());
-      assertThat(it.next()).isEqualTo(LineCoverage.newBuilder()
-        .setLine(5)
-        .setHits(false)
-        .build());
-    }
-
-  }
-}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java
deleted file mode 100644 (file)
index 6af538c..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.report;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import org.apache.commons.lang.exception.ExceptionUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.core.util.CloseableIterator;
-import org.sonar.scanner.deprecated.test.TestPlanBuilder;
-import org.sonar.scanner.protocol.output.ScannerReport;
-import org.sonar.scanner.protocol.output.ScannerReportReader;
-import org.sonar.scanner.protocol.output.ScannerReportWriter;
-import org.sonar.scanner.scan.branch.BranchConfiguration;
-import org.sonar.scanner.scan.filesystem.InputComponentStore;
-import org.sonar.scanner.scan.measure.MeasureCache;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class MeasuresPublisherTest {
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  private MeasureCache measureCache;
-  private MeasuresPublisher publisher;
-
-  private File outputDir;
-  private ScannerReportWriter writer;
-  private DefaultInputFile inputFile;
-  private DefaultInputProject project;
-
-  @Before
-  public void prepare() throws IOException {
-    String projectKey = "foo";
-    project = TestInputFileBuilder.newDefaultInputProject(projectKey, temp.newFolder());
-    inputFile = new TestInputFileBuilder(projectKey, "src/Foo.php").setPublish(true).build();
-    InputComponentStore componentCache = new InputComponentStore(mock(BranchConfiguration.class));
-    componentCache.put(projectKey, inputFile);
-    measureCache = mock(MeasureCache.class);
-    when(measureCache.byComponentKey(anyString())).thenReturn(Collections.<DefaultMeasure<?>>emptyList());
-    publisher = new MeasuresPublisher(componentCache, measureCache, mock(TestPlanBuilder.class));
-    outputDir = temp.newFolder();
-    writer = new ScannerReportWriter(outputDir);
-  }
-
-  @Test
-  public void publishMeasures() throws Exception {
-    DefaultMeasure<Integer> measure = new DefaultMeasure<Integer>().forMetric(CoreMetrics.LINES_TO_COVER)
-      .withValue(2);
-    // String value
-    DefaultMeasure<String> stringMeasure = new DefaultMeasure<String>().forMetric(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)
-      .withValue("foo bar");
-    when(measureCache.byComponentKey(inputFile.key())).thenReturn(asList(measure, stringMeasure));
-
-    publisher.publish(writer);
-    ScannerReportReader reader = new ScannerReportReader(outputDir);
-
-    assertThat(reader.readComponentMeasures(project.scannerId())).hasSize(0);
-    try (CloseableIterator<ScannerReport.Measure> componentMeasures = reader.readComponentMeasures(inputFile.scannerId())) {
-      assertThat(componentMeasures).hasSize(2);
-    }
-  }
-
-  @Test
-  public void fail_with_IAE_when_measure_has_no_value() throws Exception {
-    DefaultMeasure<Integer> measure = new DefaultMeasure<Integer>().forMetric(CoreMetrics.LINES_TO_COVER);
-    when(measureCache.byComponentKey(inputFile.key())).thenReturn(Collections.singletonList(measure));
-
-    try {
-      publisher.publish(writer);
-      fail();
-    } catch (RuntimeException e) {
-      assertThat(ExceptionUtils.getFullStackTrace(e)).contains("Measure on metric 'lines_to_cover' and component 'foo:src/Foo.php' has no value, but it's not allowed");
-    }
-  }
-
-}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/measure/MeasureCacheTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/measure/MeasureCacheTest.java
deleted file mode 100644 (file)
index f3e08e9..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.scan.measure;
-
-import java.util.Iterator;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.scanner.index.AbstractCachesTest;
-import org.sonar.scanner.storage.Storage.Entry;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class MeasureCacheTest extends AbstractCachesTest {
-
-  private static final String COMPONENT_KEY = "struts";
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  private MetricFinder metricFinder;
-
-  private MeasureCache measureCache;
-
-  @Before
-  public void start() {
-    super.start();
-    metricFinder = mock(MetricFinder.class);
-    when(metricFinder.<Integer>findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
-    when(metricFinder.<String>findByKey(CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY)).thenReturn(CoreMetrics.COVERAGE_LINE_HITS_DATA);
-    measureCache = new MeasureCache(caches, metricFinder);
-  }
-
-  @Test
-  public void should_add_measure() {
-    assertThat(measureCache.entries()).hasSize(0);
-    assertThat(measureCache.byComponentKey(COMPONENT_KEY)).hasSize(0);
-
-    DefaultMeasure<?> m = new DefaultMeasure().forMetric(CoreMetrics.NCLOC).withValue(1.0);
-    measureCache.put(COMPONENT_KEY, CoreMetrics.NCLOC_KEY, m);
-
-    assertThat(measureCache.contains(COMPONENT_KEY, CoreMetrics.NCLOC_KEY)).isTrue();
-    assertThat(measureCache.entries()).hasSize(1);
-    Iterator<Entry<DefaultMeasure<?>>> iterator = measureCache.entries().iterator();
-    iterator.hasNext();
-    Entry<DefaultMeasure<?>> next = iterator.next();
-    assertThat(next.value()).isEqualTo(m);
-    assertThat(next.key()[0]).isEqualTo(COMPONENT_KEY);
-
-    assertThat(measureCache.byComponentKey(COMPONENT_KEY)).hasSize(1);
-    assertThat(measureCache.byComponentKey(COMPONENT_KEY).iterator().next()).isEqualTo(m);
-  }
-
-  /**
-   * This test fails with stock PersisitIt.
-   */
-  @Test
-  public void should_add_measure_with_too_big_data_for_persistit_pre_patch() {
-    assertThat(measureCache.entries()).hasSize(0);
-    assertThat(measureCache.byComponentKey(COMPONENT_KEY)).hasSize(0);
-
-    StringBuilder data = new StringBuilder(4_500_000);
-    for (int i = 0; i < 4_500_000; i++) {
-      data.append('a');
-    }
-    DefaultMeasure<?> m = new DefaultMeasure().forMetric(CoreMetrics.COVERAGE_LINE_HITS_DATA).withValue(data.toString());
-    measureCache.put(COMPONENT_KEY, CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, m);
-
-    assertThat(measureCache.contains(COMPONENT_KEY, CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY)).isTrue();
-    assertThat(measureCache.entries()).hasSize(1);
-    Iterator<Entry<DefaultMeasure<?>>> iterator = measureCache.entries().iterator();
-    iterator.hasNext();
-    Entry<DefaultMeasure<?>> next = iterator.next();
-    assertThat(next.value()).isEqualTo(m);
-    assertThat(next.key()[0]).isEqualTo(COMPONENT_KEY);
-
-    assertThat(measureCache.byComponentKey(COMPONENT_KEY)).hasSize(1);
-    assertThat(measureCache.byComponentKey(COMPONENT_KEY).iterator().next()).isEqualTo(m);
-
-  }
-
-  @Test
-  public void should_add_measure_with_too_big_data_for_persistit() {
-    assertThat(measureCache.entries()).hasSize(0);
-    assertThat(measureCache.byComponentKey(COMPONENT_KEY)).hasSize(0);
-
-    // Limit is 64Mo
-    StringBuilder data = new StringBuilder(64 * 1024 * 1024 + 1);
-    for (int i = 0; i < 64 * 1024 * 1024 + 1; i++) {
-      data.append('a');
-    }
-    DefaultMeasure<?> m = new DefaultMeasure().forMetric(CoreMetrics.COVERAGE_LINE_HITS_DATA).withValue(data.toString());
-
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Fail to put element in the storage 'measures'");
-
-    measureCache.put(COMPONENT_KEY, CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, m);
-  }
-
-  @Test
-  public void should_get_measures() {
-    String projectKey = "struts";
-    String dirKey = "struts:foo/bar";
-    String file1Key = "struts:foo/bar/File1.txt";
-    String file2Key = "struts:foo/bar/File2.txt";
-
-    assertThat(measureCache.entries()).hasSize(0);
-
-    assertThat(measureCache.byComponentKey(projectKey)).hasSize(0);
-    assertThat(measureCache.byComponentKey(dirKey)).hasSize(0);
-
-    DefaultMeasure<?> mFile1 = new DefaultMeasure().forMetric(CoreMetrics.NCLOC).withValue(1.0);
-    measureCache.put(file1Key, CoreMetrics.NCLOC_DATA_KEY, mFile1);
-    DefaultMeasure<?> mFile2 = new DefaultMeasure().forMetric(CoreMetrics.NCLOC).withValue(3.0);
-    measureCache.put(file2Key, CoreMetrics.NCLOC_DATA_KEY, mFile2);
-
-    assertThat(measureCache.entries()).hasSize(2);
-    assertThat(measureCache.byComponentKey(projectKey)).hasSize(0);
-    assertThat(measureCache.byComponentKey(dirKey)).hasSize(0);
-
-    DefaultMeasure<?> mDir = new DefaultMeasure().forMetric(CoreMetrics.NCLOC).withValue(4.0);
-    measureCache.put(dirKey, CoreMetrics.NCLOC_DATA_KEY, mDir);
-
-    assertThat(measureCache.entries()).hasSize(3);
-    assertThat(measureCache.byComponentKey(projectKey)).hasSize(0);
-    assertThat(measureCache.byComponentKey(dirKey)).hasSize(1);
-    assertThat(measureCache.byComponentKey(dirKey).iterator().next()).isEqualTo(mDir);
-
-    DefaultMeasure<?> mProj = new DefaultMeasure().forMetric(CoreMetrics.NCLOC).withValue(4.0);
-    measureCache.put(projectKey, CoreMetrics.NCLOC_DATA_KEY, mProj);
-
-    assertThat(measureCache.entries()).hasSize(4);
-    assertThat(measureCache.byComponentKey(projectKey)).hasSize(1);
-    assertThat(measureCache.byComponentKey(projectKey).iterator().next()).isEqualTo(mProj);
-    assertThat(measureCache.byComponentKey(dirKey)).hasSize(1);
-    assertThat(measureCache.byComponentKey(dirKey).iterator().next()).isEqualTo(mDir);
-  }
-
-}
index 96aef89bfc00894e1f52605a9231ef57081b663f..264e666429f6a4bf2d74b807fa5a1192df522c07 100644 (file)
@@ -19,9 +19,8 @@
  */
 package org.sonar.scanner.sensor;
 
-import com.google.common.collect.ImmutableMap;
+import java.io.File;
 import java.io.IOException;
-import java.util.Map;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -48,20 +47,19 @@ import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
 import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.core.metric.ScannerMetrics;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
 import org.sonar.scanner.issue.IssuePublisher;
 import org.sonar.scanner.protocol.output.FileStructure;
+import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.report.ReportPublisher;
 import org.sonar.scanner.repository.ContextPropertiesCache;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
-import org.sonar.scanner.scan.measure.MeasureCache;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.data.MapEntry.entry;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -79,11 +77,12 @@ public class DefaultSensorStorageTest {
   private DefaultSensorStorage underTest;
   private MapSettings settings;
   private IssuePublisher moduleIssues;
-  private MeasureCache measureCache;
   private ScannerReportWriter reportWriter;
   private ContextPropertiesCache contextPropertiesCache = new ContextPropertiesCache();
   private BranchConfiguration branchConfiguration;
   private DefaultInputProject project;
+  private ScannerReportReader reportReader;
+  private ReportPublisher reportPublisher;
 
   @Before
   public void prepare() throws Exception {
@@ -94,17 +93,18 @@ public class DefaultSensorStorageTest {
 
     settings = new MapSettings();
     moduleIssues = mock(IssuePublisher.class);
-    measureCache = mock(MeasureCache.class);
 
-    ReportPublisher reportPublisher = mock(ReportPublisher.class);
-    reportWriter = new ScannerReportWriter(temp.newFolder());
+    reportPublisher = mock(ReportPublisher.class);
+    final File reportDir = temp.newFolder();
+    reportWriter = new ScannerReportWriter(reportDir);
+    reportReader = new ScannerReportReader(reportDir);
     when(reportPublisher.getWriter()).thenReturn(reportWriter);
+    when(reportPublisher.getReader()).thenReturn(reportReader);
 
     branchConfiguration = mock(BranchConfiguration.class);
 
     underTest = new DefaultSensorStorage(metricFinder,
-      moduleIssues, settings.asConfig(), reportPublisher, measureCache,
-      mock(SonarCpdBlockIndex.class), contextPropertiesCache, new ScannerMetrics(), branchConfiguration);
+      moduleIssues, settings.asConfig(), reportPublisher, mock(SonarCpdBlockIndex.class), contextPropertiesCache, new ScannerMetrics(), branchConfiguration);
 
     project = new DefaultInputProject(ProjectDefinition.create()
       .setKey("foo")
@@ -132,7 +132,7 @@ public class DefaultSensorStorageTest {
       .forMetric(CoreMetrics.LINES)
       .withValue(10));
 
-    verifyNoMoreInteractions(measureCache);
+    verifyNoMoreInteractions(reportPublisher);
   }
 
   @Test
@@ -145,7 +145,7 @@ public class DefaultSensorStorageTest {
       .forMetric(CoreMetrics.LINES)
       .withValue(10));
 
-    verifyNoMoreInteractions(measureCache);
+    verifyNoMoreInteractions(reportPublisher);
   }
 
   @Test
@@ -209,35 +209,32 @@ public class DefaultSensorStorageTest {
 
   @Test
   public void should_save_file_measure() {
-    InputFile file = new TestInputFileBuilder("foo", "src/Foo.php").build();
+    DefaultInputFile file = new TestInputFileBuilder("foo", "src/Foo.php")
+      .build();
 
-    ArgumentCaptor<DefaultMeasure> argumentCaptor = ArgumentCaptor.forClass(DefaultMeasure.class);
-    when(measureCache.put(eq(file.key()), eq(CoreMetrics.NCLOC_KEY), argumentCaptor.capture())).thenReturn(null);
     underTest.store(new DefaultMeasure()
       .on(file)
       .forMetric(CoreMetrics.NCLOC)
       .withValue(10));
 
-    DefaultMeasure m = argumentCaptor.getValue();
-    assertThat(m.value()).isEqualTo(10);
-    assertThat(m.metric()).isEqualTo(CoreMetrics.NCLOC);
+    ScannerReport.Measure m = reportReader.readComponentMeasures(file.scannerId()).next();
+    assertThat(m.getIntValue().getValue()).isEqualTo(10);
+    assertThat(m.getMetricKey()).isEqualTo(CoreMetrics.NCLOC_KEY);
   }
 
   @Test
   public void should_not_skip_file_measures_on_short_lived_branch_or_pull_request_when_file_status_is_SAME() {
-    InputFile file = new TestInputFileBuilder("foo", "src/Foo.php").setStatus(InputFile.Status.SAME).build();
+    DefaultInputFile file = new TestInputFileBuilder("foo", "src/Foo.php").setStatus(InputFile.Status.SAME).build();
     when(branchConfiguration.isShortOrPullRequest()).thenReturn(true);
 
-    ArgumentCaptor<DefaultMeasure> argumentCaptor = ArgumentCaptor.forClass(DefaultMeasure.class);
-    when(measureCache.put(eq(file.key()), eq(CoreMetrics.LINES_TO_COVER_KEY), argumentCaptor.capture())).thenReturn(null);
     underTest.store(new DefaultMeasure()
       .on(file)
-      .forMetric(CoreMetrics.LINES_TO_COVER)
+      .forMetric(CoreMetrics.NCLOC)
       .withValue(10));
 
-    DefaultMeasure m = argumentCaptor.getValue();
-    assertThat(m.value()).isEqualTo(10);
-    assertThat(m.metric()).isEqualTo(CoreMetrics.LINES_TO_COVER);
+    ScannerReport.Measure m = reportReader.readComponentMeasures(file.scannerId()).next();
+    assertThat(m.getIntValue().getValue()).isEqualTo(10);
+    assertThat(m.getMetricKey()).isEqualTo(CoreMetrics.NCLOC_KEY);
   }
 
   @Test
@@ -272,17 +269,14 @@ public class DefaultSensorStorageTest {
     String projectKey = "myProject";
     DefaultInputModule module = new DefaultInputModule(ProjectDefinition.create().setKey(projectKey).setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder()));
 
-    ArgumentCaptor<DefaultMeasure> argumentCaptor = ArgumentCaptor.forClass(DefaultMeasure.class);
-    when(measureCache.put(eq(module.key()), eq(CoreMetrics.NCLOC_KEY), argumentCaptor.capture())).thenReturn(null);
-
     underTest.store(new DefaultMeasure()
       .on(module)
       .forMetric(CoreMetrics.NCLOC)
       .withValue(10));
 
-    DefaultMeasure m = argumentCaptor.getValue();
-    assertThat(m.value()).isEqualTo(10);
-    assertThat(m.metric()).isEqualTo(CoreMetrics.NCLOC);
+    ScannerReport.Measure m = reportReader.readComponentMeasures(module.scannerId()).next();
+    assertThat(m.getIntValue().getValue()).isEqualTo(10);
+    assertThat(m.getMetricKey()).isEqualTo(CoreMetrics.NCLOC_KEY);
   }
 
   @Test(expected = UnsupportedOperationException.class)
@@ -321,36 +315,4 @@ public class DefaultSensorStorageTest {
     assertThat(contextPropertiesCache.getAll()).containsOnly(entry("foo", "bar"));
   }
 
-  @Test
-  public void shouldValidateStrictlyPositiveLine() throws Exception {
-    InputFile file = new TestInputFileBuilder("module", "testfile").setModuleBaseDir(temp.newFolder().toPath()).build();
-    Map<Integer, Integer> map = ImmutableMap.of(0, 3);
-    String data = KeyValueFormat.format(map);
-
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("must be > 0");
-    underTest.validateCoverageMeasure(data, file);
-  }
-
-  @Test
-  public void shouldValidateMaxLine() throws Exception {
-    InputFile file = new TestInputFileBuilder("module", "testfile").setModuleBaseDir(temp.newFolder().toPath()).build();
-    Map<Integer, Integer> map = ImmutableMap.of(11, 3);
-    String data = KeyValueFormat.format(map);
-
-    thrown.expect(IllegalStateException.class);
-    underTest.validateCoverageMeasure(data, file);
-  }
-
-  @Test
-  public void mergeCoverageLineMetrics_should_be_sorted() {
-    assertThat(DefaultSensorStorage.mergeCoverageLineMetric(CoreMetrics.COVERAGE_LINE_HITS_DATA, "1=1", "1=1")).isEqualTo("1=2");
-    assertThat(DefaultSensorStorage.mergeCoverageLineMetric(CoreMetrics.COVERAGE_LINE_HITS_DATA, "1=1", "2=1")).isEqualTo("1=1;2=1");
-    assertThat(DefaultSensorStorage.mergeCoverageLineMetric(CoreMetrics.COVERAGE_LINE_HITS_DATA, "2=1", "1=1")).isEqualTo("1=1;2=1");
-
-    assertThat(DefaultSensorStorage.mergeCoverageLineMetric(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "1=1", "1=1")).isEqualTo("1=1");
-    assertThat(DefaultSensorStorage.mergeCoverageLineMetric(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "1=1", "2=1")).isEqualTo("1=1;2=1");
-    assertThat(DefaultSensorStorage.mergeCoverageLineMetric(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "2=1", "1=1")).isEqualTo("1=1;2=1");
-  }
-
 }
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/storage/StorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/storage/StorageTest.java
deleted file mode 100644 (file)
index 45e9e1e..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.storage;
-
-import com.google.common.collect.Iterables;
-import org.junit.Test;
-import org.sonar.scanner.index.AbstractCachesTest;
-import org.sonar.scanner.storage.Storage.Entry;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class StorageTest extends AbstractCachesTest {
-
-  @Test
-  public void one_part_key() {
-    Storage<String> cache = caches.createCache("capitals");
-
-    assertThat(cache.get("france")).isNull();
-
-    cache.put("france", "paris");
-    cache.put("italy", "rome");
-    assertThat(cache.get("france")).isEqualTo("paris");
-    assertThat(cache.keySet()).containsOnly("france", "italy");
-    assertThat(cache.keySet("france")).isEmpty();
-    Iterable<String> values = cache.values();
-    assertThat(values).containsOnly("paris", "rome");
-    assertThat(values).containsOnly("paris", "rome");
-    assertThat(cache.containsKey("france")).isTrue();
-
-    Iterable<Entry<String>> iterable = cache.entries();
-    Storage.Entry[] entries = Iterables.toArray(iterable, Storage.Entry.class);
-    assertThat(entries).hasSize(2);
-    assertThat(iterable).hasSize(2);
-    assertThat(entries[0].key()[0]).isEqualTo("france");
-    assertThat(entries[0].value()).isEqualTo("paris");
-    assertThat(entries[1].key()[0]).isEqualTo("italy");
-    assertThat(entries[1].value()).isEqualTo("rome");
-
-    cache.remove("france");
-    assertThat(cache.get("france")).isNull();
-    assertThat(cache.get("italy")).isEqualTo("rome");
-    assertThat(cache.keySet()).containsOnly("italy");
-    assertThat(cache.keySet("france")).isEmpty();
-    assertThat(cache.containsKey("france")).isFalse();
-    assertThat(cache.containsKey("italy")).isTrue();
-    assertThat(values).containsOnly("rome");
-
-    cache.clear();
-    assertThat(values).isEmpty();
-  }
-
-  @Test
-  public void test_key_being_prefix_of_another_key() throws Exception {
-    Storage<String> cache = caches.createCache("components");
-
-    cache.put("struts-el:org.apache.strutsel.taglib.html.ELButtonTag", "the Tag");
-    cache.put("struts-el:org.apache.strutsel.taglib.html.ELButtonTagBeanInfo", "the BeanInfo");
-
-    assertThat(cache.get("struts-el:org.apache.strutsel.taglib.html.ELButtonTag")).isEqualTo("the Tag");
-    assertThat(cache.get("struts-el:org.apache.strutsel.taglib.html.ELButtonTagBeanInfo")).isEqualTo("the BeanInfo");
-  }
-
-  @Test
-  public void two_parts_key() {
-    Storage<String> cache = caches.createCache("capitals");
-
-    assertThat(cache.get("europe", "france")).isNull();
-
-    cache.put("europe", "france", "paris");
-    cache.put("europe", "italy", "rome");
-    cache.put("asia", "china", "pekin");
-    assertThat(cache.get("europe")).isNull();
-    assertThat(cache.get("europe", "france")).isEqualTo("paris");
-    assertThat(cache.get("europe", "italy")).isEqualTo("rome");
-    assertThat(cache.get("europe")).isNull();
-    assertThat(cache.keySet("europe")).containsOnly("france", "italy");
-    assertThat(cache.keySet()).containsOnly("europe", "asia");
-    assertThat(cache.containsKey("europe")).isFalse();
-    assertThat(cache.containsKey("europe", "france")).isTrue();
-    assertThat(cache.containsKey("europe", "spain")).isFalse();
-    assertThat(cache.values()).containsOnly("paris", "rome", "pekin");
-    assertThat(cache.values("america")).isEmpty();
-    assertThat(cache.values("europe")).containsOnly("paris", "rome");
-    assertThat(cache.values("oceania")).isEmpty();
-
-    Iterable<Entry<String>> iterable = cache.entries();
-    Storage.Entry[] allEntries = Iterables.toArray(iterable, Storage.Entry.class);
-    assertThat(allEntries).hasSize(3);
-    assertThat(iterable).hasSize(3);
-    assertThat(allEntries[0].key()).isEqualTo(new String[] {"asia", "china"});
-    assertThat(allEntries[0].value()).isEqualTo("pekin");
-    assertThat(allEntries[1].key()).isEqualTo(new String[] {"europe", "france"});
-    assertThat(allEntries[1].value()).isEqualTo("paris");
-    assertThat(allEntries[2].key()).isEqualTo(new String[] {"europe", "italy"});
-    assertThat(allEntries[2].value()).isEqualTo("rome");
-
-    Iterable<Entry<String>> iterable2 = cache.entries("europe");
-    Storage.Entry[] subEntries = Iterables.toArray(iterable2, Storage.Entry.class);
-    assertThat(subEntries).hasSize(2);
-    assertThat(iterable2).hasSize(2);
-    assertThat(subEntries[0].key()).isEqualTo(new String[] {"europe", "france"});
-    assertThat(subEntries[0].value()).isEqualTo("paris");
-    assertThat(subEntries[1].key()).isEqualTo(new String[] {"europe", "italy"});
-    assertThat(subEntries[1].value()).isEqualTo("rome");
-
-    cache.remove("europe", "france");
-    assertThat(cache.values()).containsOnly("rome", "pekin");
-    assertThat(cache.get("europe", "france")).isNull();
-    assertThat(cache.get("europe", "italy")).isEqualTo("rome");
-    assertThat(cache.containsKey("europe", "france")).isFalse();
-    assertThat(cache.keySet("europe")).containsOnly("italy");
-
-    cache.clear("america");
-    assertThat(cache.keySet()).containsOnly("europe", "asia");
-    cache.clear();
-    assertThat(cache.keySet()).isEmpty();
-  }
-
-  @Test
-  public void three_parts_key() {
-    Storage<String> cache = caches.createCache("places");
-    assertThat(cache.get("europe", "france", "paris")).isNull();
-
-    cache.put("europe", "france", "paris", "eiffel tower");
-    cache.put("europe", "france", "annecy", "lake");
-    cache.put("europe", "france", "poitiers", "notre dame");
-    cache.put("europe", "italy", "rome", "colosseum");
-    cache.put("europe2", "ukrania", "kiev", "dunno");
-    cache.put("asia", "china", "pekin", "great wall");
-    cache.put("america", "us", "new york", "empire state building");
-    assertThat(cache.get("europe")).isNull();
-    assertThat(cache.get("europe", "france")).isNull();
-    assertThat(cache.get("europe", "france", "paris")).isEqualTo("eiffel tower");
-    assertThat(cache.get("europe", "france", "annecy")).isEqualTo("lake");
-    assertThat(cache.get("europe", "italy", "rome")).isEqualTo("colosseum");
-    assertThat(cache.keySet()).containsOnly("europe", "asia", "america", "europe2");
-    assertThat(cache.keySet("europe")).containsOnly("france", "italy");
-    assertThat(cache.keySet("europe", "france")).containsOnly("annecy", "paris", "poitiers");
-    assertThat(cache.containsKey("europe")).isFalse();
-    assertThat(cache.containsKey("europe", "france")).isFalse();
-    assertThat(cache.containsKey("europe", "france", "annecy")).isTrue();
-    assertThat(cache.containsKey("europe", "france", "biarritz")).isFalse();
-    assertThat(cache.values()).containsOnly("eiffel tower", "lake", "colosseum", "notre dame", "great wall", "empire state building", "dunno");
-    assertThat(cache.values("europe")).containsOnly("eiffel tower", "lake", "colosseum", "notre dame");
-    assertThat(cache.values("europe", "france")).containsOnly("eiffel tower", "lake", "notre dame");
-
-    Iterable<Entry<String>> iterable = cache.entries();
-    Storage.Entry[] allEntries = Iterables.toArray(iterable, Storage.Entry.class);
-    assertThat(allEntries).hasSize(7);
-    assertThat(iterable).hasSize(7);
-    assertThat(allEntries[0].key()).isEqualTo(new String[] {"america", "us", "new york"});
-    assertThat(allEntries[0].value()).isEqualTo("empire state building");
-    assertThat(allEntries[1].key()).isEqualTo(new String[] {"asia", "china", "pekin"});
-    assertThat(allEntries[1].value()).isEqualTo("great wall");
-    assertThat(allEntries[2].key()).isEqualTo(new String[] {"europe", "france", "annecy"});
-    assertThat(allEntries[2].value()).isEqualTo("lake");
-    assertThat(allEntries[3].key()).isEqualTo(new String[] {"europe", "france", "paris"});
-    assertThat(allEntries[3].value()).isEqualTo("eiffel tower");
-    assertThat(allEntries[4].key()).isEqualTo(new String[] {"europe", "france", "poitiers"});
-    assertThat(allEntries[4].value()).isEqualTo("notre dame");
-    assertThat(allEntries[5].key()).isEqualTo(new String[] {"europe", "italy", "rome"});
-    assertThat(allEntries[5].value()).isEqualTo("colosseum");
-
-    Iterable<Entry<String>> iterable2 = cache.entries("europe");
-    Storage.Entry[] subEntries = Iterables.toArray(iterable2, Storage.Entry.class);
-    assertThat(subEntries).hasSize(4);
-    assertThat(iterable2).hasSize(4);
-    assertThat(subEntries[0].key()).isEqualTo(new String[] {"europe", "france", "annecy"});
-    assertThat(subEntries[0].value()).isEqualTo("lake");
-    assertThat(subEntries[1].key()).isEqualTo(new String[] {"europe", "france", "paris"});
-    assertThat(subEntries[1].value()).isEqualTo("eiffel tower");
-    assertThat(subEntries[2].key()).isEqualTo(new String[] {"europe", "france", "poitiers"});
-    assertThat(subEntries[2].value()).isEqualTo("notre dame");
-    assertThat(subEntries[3].key()).isEqualTo(new String[] {"europe", "italy", "rome"});
-    assertThat(subEntries[3].value()).isEqualTo("colosseum");
-
-    cache.remove("europe", "france", "annecy");
-    assertThat(cache.values()).containsOnly("eiffel tower", "colosseum", "notre dame", "great wall", "empire state building", "dunno");
-    assertThat(cache.values("europe")).containsOnly("eiffel tower", "colosseum", "notre dame");
-    assertThat(cache.values("europe", "france")).containsOnly("eiffel tower", "notre dame");
-    assertThat(cache.get("europe", "france", "annecy")).isNull();
-    assertThat(cache.get("europe", "italy", "rome")).isEqualTo("colosseum");
-    assertThat(cache.containsKey("europe", "france")).isFalse();
-
-    cache.clear("europe", "italy");
-    assertThat(cache.values()).containsOnly("eiffel tower", "notre dame", "great wall", "empire state building", "dunno");
-
-    cache.clear("europe");
-    assertThat(cache.values()).containsOnly("great wall", "empire state building", "dunno");
-
-    cache.clear();
-    assertThat(cache.values()).isEmpty();
-  }
-
-  @Test
-  public void remove_versus_clear() {
-    Storage<String> cache = caches.createCache("capitals");
-    cache.put("europe", "france", "paris");
-    cache.put("europe", "italy", "rome");
-
-    // remove("europe") does not remove sub-keys
-    cache.remove("europe");
-    assertThat(cache.values()).containsOnly("paris", "rome");
-
-    // clear("europe") removes sub-keys
-    cache.clear("europe");
-    assertThat(cache.values()).isEmpty();
-  }
-
-  @Test
-  public void empty_cache() {
-    Storage<String> cache = caches.createCache("empty");
-
-    assertThat(cache.get("foo")).isNull();
-    assertThat(cache.get("foo", "bar")).isNull();
-    assertThat(cache.get("foo", "bar", "baz")).isNull();
-    assertThat(cache.keySet()).isEmpty();
-    assertThat(cache.keySet("foo")).isEmpty();
-    assertThat(cache.containsKey("foo")).isFalse();
-    assertThat(cache.containsKey("foo", "bar")).isFalse();
-    assertThat(cache.containsKey("foo", "bar", "baz")).isFalse();
-    assertThat(cache.values()).isEmpty();
-    assertThat(cache.values("foo")).isEmpty();
-
-    // do not fail
-    cache.remove("foo");
-    cache.remove("foo", "bar");
-    cache.remove("foo", "bar", "baz");
-    cache.clear("foo");
-    cache.clear("foo", "bar");
-    cache.clear("foo", "bar", "baz");
-    cache.clear();
-  }
-}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/storage/StoragesManagerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/storage/StoragesManagerTest.java
deleted file mode 100644 (file)
index 5c43aa7..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.storage;
-
-import java.io.File;
-import org.junit.Test;
-import org.sonar.scanner.index.AbstractCachesTest;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class StoragesManagerTest extends AbstractCachesTest {
-  @Test
-  public void should_stop_and_clean_temp_dir() {
-    File tempDir = cachesManager.tempDir();
-    assertThat(tempDir).isDirectory().exists();
-    assertThat(cachesManager.persistit()).isNotNull();
-    assertThat(cachesManager.persistit().isInitialized()).isTrue();
-
-    cachesManager.stop();
-
-    assertThat(tempDir).doesNotExist();
-    assertThat(cachesManager.tempDir()).isNull();
-    assertThat(cachesManager.persistit()).isNull();
-  }
-}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/storage/StoragesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/storage/StoragesTest.java
deleted file mode 100644 (file)
index e35ec4f..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.scanner.storage;
-
-import com.persistit.exception.PersistitException;
-import java.io.Serializable;
-import org.junit.Test;
-import org.sonar.scanner.index.AbstractCachesTest;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-
-public class StoragesTest extends AbstractCachesTest {
-  @Test
-  public void should_create_cache() {
-    Storage<Element> cache = caches.createCache("foo");
-    assertThat(cache).isNotNull();
-  }
-
-  @Test
-  public void should_not_create_cache_twice() {
-    caches.<Element>createCache("foo");
-    try {
-      caches.<Element>createCache("foo");
-      fail();
-    } catch (IllegalStateException e) {
-      // ok
-    }
-  }
-
-  @Test
-  public void should_clean_resources() {
-    Storage<String> c = caches.<String>createCache("test1");
-    for (int i = 0; i < 1_000_000; i++) {
-      c.put("a" + i, "a" + i);
-    }
-
-    caches.stop();
-
-    // manager continues up
-    assertThat(cachesManager.persistit().isInitialized()).isTrue();
-
-    caches = new Storages(cachesManager);
-    caches.start();
-    caches.createCache("test1");
-  }
-
-  @Test
-  public void leak_test() throws PersistitException {
-    caches.stop();
-
-    int len = 1 * 1024 * 1024;
-    StringBuilder sb = new StringBuilder(len);
-    for (int i = 0; i < len; i++) {
-      sb.append("a");
-    }
-
-    for (int i = 0; i < 3; i++) {
-      caches = new Storages(cachesManager);
-      caches.start();
-      Storage<String> c = caches.<String>createCache("test" + i);
-      c.put("key" + i, sb.toString());
-      cachesManager.persistit().flush();
-
-      caches.stop();
-    }
-  }
-
-  private static class Element implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-  }
-}
index e20e37ff852c5892b9de626f7c0ce5a9bef3926c..42292da429bb801b3bf63fa8340ff11d47e6e89e 100644 (file)
@@ -112,10 +112,13 @@ public class ScannerReportWriter {
     }
   }
 
-  public File writeComponentMeasures(int componentRef, Iterable<ScannerReport.Measure> measures) {
+  public void appendComponentMeasure(int componentRef, ScannerReport.Measure measure) {
     File file = fileStructure.fileFor(FileStructure.Domain.MEASURES, componentRef);
-    Protobuf.writeStream(measures, file, false);
-    return file;
+    try (OutputStream out = new BufferedOutputStream(new FileOutputStream(file, true))) {
+      measure.writeDelimitedTo(out);
+    } catch (Exception e) {
+      throw ContextException.of("Unable to write measure", e).addContext("file", file);
+    }
   }
 
   public File writeComponentChangesets(ScannerReport.Changesets changesets) {
index 928166b5a312424e399395541d436c73fa3a4ddf..b405c69cbe39f296ef508daaddcc9de8232c8108 100644 (file)
@@ -124,7 +124,7 @@ public class ScannerReportReaderTest {
     ScannerReportWriter writer = new ScannerReportWriter(dir);
     ScannerReport.Measure.Builder measure = ScannerReport.Measure.newBuilder()
       .setStringValue(StringValue.newBuilder().setValue("value_a"));
-    writer.writeComponentMeasures(1, asList(measure.build()));
+    writer.appendComponentMeasure(1, measure.build());
 
     assertThat(underTest.readComponentMeasures(1)).hasSize(1);
   }
index 3a6f84961dd742db2779ecef1a10591ad48a5150..ade53f3bca55abff333bc18b52fc95559c0b08b2 100644 (file)
@@ -183,7 +183,7 @@ public class ScannerReportWriterTest {
       .setDoubleValue(DoubleValue.newBuilder().setValue(2.5d).setData("text-value"))
       .build();
 
-    underTest.writeComponentMeasures(1, asList(measure));
+    underTest.appendComponentMeasure(1, measure);
 
     assertThat(underTest.hasComponentData(FileStructure.Domain.MEASURES, 1)).isTrue();
     File file = underTest.getFileStructure().fileFor(FileStructure.Domain.MEASURES, 1);