]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8281 Rework Sensor storage to merge multiple coverage reports
authorJulien HENRY <julien.henry@sonarsource.com>
Fri, 14 Oct 2016 15:36:53 +0000 (17:36 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Tue, 18 Oct 2016 14:00:26 +0000 (16:00 +0200)
41 files changed:
it/it-projects/analysis/xoo-multi-languages/src/sample/Sample.xoo.measures
it/it-projects/analysis/xoo-multi-languages/src/sample/Sample.xoo2.measures
it/it-projects/analysis/xoo-sample-with-spaces/v1/my sources/main/xoo/sample/My Sample.xoo.measures
it/it-projects/analysis/xoo-sample-with-spaces/v2/my sources/main/xoo/sample/My Sample.xoo.measures
it/it-projects/dbCleaner/files/after/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/NewHelloA1.xoo.measures
it/it-projects/dbCleaner/files/before/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo.measures
it/it-projects/dbCleaner/modules/after/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo.measures
it/it-projects/dbCleaner/modules/before/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo.measures
it/it-projects/dbCleaner/xoo-multi-modules-sample/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo.measures
it/it-projects/issue/xoo-sample-v2/src/main/xoo/sample/Sample.xoo.measures
it/it-projects/qualitygate/xoo-sample/src/sample/Sample.xoo.measures
it/it-projects/qualitygate/xoo-sample/src/sample/Sample2.xoo.measures
it/it-projects/shared/xoo-sample-module-move-v1/module_a/src/main/xoo/sample/Sample.xoo.measures
it/it-projects/shared/xoo-sample-module-move-v2/new_module/module_a/src/main/xoo/sample/Sample.xoo.measures
it/it-projects/shared/xoo-sample-non-associated/src/main/xoo/sample/Sample.xoo.measures
it/it-projects/shared/xoo-sample-with-root-dir/src/main/xoo/sample/Sample.xoo.measures
it/it-projects/shared/xoo-sample/src/main/xoo/sample/Sample.xoo.measures
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/sensor/coverage/internal/DefaultCoverage.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/DefaultFileLinesContext.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/deprecated/DeprecatedSensorContext.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/index/Cache.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/index/DefaultIndex.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/CoveragePublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MeasuresPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/measure/MeasureCache.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/measure/MeasureValueCoder.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/coverage/CoverageConstants.java [deleted file]
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/coverage/CoverageExclusions.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/source/ZeroCoverageSensor.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/index/DefaultIndexTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/coverage/CoverageMediumTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CoveragePublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MeasuresPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/measure/MeasureCacheTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/coverage/CoverageExclusionsTest.java

index ab1671431fc4c4da1950ee8f0c976c06737422ed..5dc0154b75d8fa5170d7f82b1bc99a9711c09502 100644 (file)
@@ -5,6 +5,3 @@ classes:1
 comment_lines:3
 public_api:5
 public_undocumented_api:2
-duplicated_files:1
-duplicated_blocks:2
-duplicated_lines:3
index ab1671431fc4c4da1950ee8f0c976c06737422ed..5dc0154b75d8fa5170d7f82b1bc99a9711c09502 100644 (file)
@@ -5,6 +5,3 @@ classes:1
 comment_lines:3
 public_api:5
 public_undocumented_api:2
-duplicated_files:1
-duplicated_blocks:2
-duplicated_lines:3
index 3f73ea8f695b61b5d3dc12c4cf441d116ee5dbfc..641332a5013fcf0203ca4d358b95e113896d397a 100644 (file)
@@ -6,6 +6,3 @@ classes:1
 comment_lines:3
 public_api:5
 public_undocumented_api:2
-duplicated_files:1
-duplicated_blocks:2
-duplicated_lines:3
index 3f73ea8f695b61b5d3dc12c4cf441d116ee5dbfc..641332a5013fcf0203ca4d358b95e113896d397a 100644 (file)
@@ -6,6 +6,3 @@ classes:1
 comment_lines:3
 public_api:5
 public_undocumented_api:2
-duplicated_files:1
-duplicated_blocks:2
-duplicated_lines:3
index 8cb5c5ed65584def83d441870104ec0ab6eed3c6..dfbfb619ed6453675a983bcf8e3d92c8e11c0bb1 100644 (file)
@@ -5,6 +5,3 @@ classes:1
 comment_lines:6
 public_api:5
 public_undocumented_api:2
-duplicated_files:1
-duplicated_blocks:2
-duplicated_lines:3
index 4f638a7a00bc4583997dd75a22dc29d9a752d19d..f67312c10043ccb59b84c84abeab016607d0aea4 100644 (file)
@@ -1,8 +1,6 @@
 ncloc:13
 complexity:7
-coverage:89.0
 test_execution_time:630
-sqale_index:4830
 #Used by dashboard/widgets tests
 complexity_in_classes:3
 classes:1
index 768513ad374635cdf6f6538c89097b1969a312db..22e229b6ed0da194f6d2d54db67f31679e08ac98 100644 (file)
@@ -1,8 +1,6 @@
 ncloc:13
 complexity:7
-coverage:89.0
 test_execution_time:630
-sqale_index:4830
 complexity_in_classes:3
 classes:1
 comment_lines:3
index 3f73ea8f695b61b5d3dc12c4cf441d116ee5dbfc..641332a5013fcf0203ca4d358b95e113896d397a 100644 (file)
@@ -6,6 +6,3 @@ classes:1
 comment_lines:3
 public_api:5
 public_undocumented_api:2
-duplicated_files:1
-duplicated_blocks:2
-duplicated_lines:3
index 3f73ea8f695b61b5d3dc12c4cf441d116ee5dbfc..641332a5013fcf0203ca4d358b95e113896d397a 100644 (file)
@@ -6,6 +6,3 @@ classes:1
 comment_lines:3
 public_api:5
 public_undocumented_api:2
-duplicated_files:1
-duplicated_blocks:2
-duplicated_lines:3
index 3f73ea8f695b61b5d3dc12c4cf441d116ee5dbfc..641332a5013fcf0203ca4d358b95e113896d397a 100644 (file)
@@ -6,6 +6,3 @@ classes:1
 comment_lines:3
 public_api:5
 public_undocumented_api:2
-duplicated_files:1
-duplicated_blocks:2
-duplicated_lines:3
index 3f73ea8f695b61b5d3dc12c4cf441d116ee5dbfc..641332a5013fcf0203ca4d358b95e113896d397a 100644 (file)
@@ -6,6 +6,3 @@ classes:1
 comment_lines:3
 public_api:5
 public_undocumented_api:2
-duplicated_files:1
-duplicated_blocks:2
-duplicated_lines:3
index e1b3dc647b81b73aebe8490187a4d7fda15f039f..e847647d54c40c24fb4f38f20f345ef9daca207b 100644 (file)
  */
 package org.sonar.core.metric;
 
-import com.google.common.base.Function;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
-import javax.annotation.Nullable;
+import java.util.stream.Collectors;
 import org.sonar.api.batch.ScannerSide;
 import org.sonar.api.ce.ComputeEngineSide;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.measures.Metrics;
 
-import static com.google.common.collect.FluentIterable.from;
-import static java.util.Arrays.asList;
 import static org.sonar.api.measures.CoreMetrics.ACCESSORS;
 import static org.sonar.api.measures.CoreMetrics.CLASSES;
 import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES;
@@ -44,31 +42,18 @@ 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.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;
 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.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.PUBLIC_API;
 import static org.sonar.api.measures.CoreMetrics.PUBLIC_UNDOCUMENTED_API;
 import static org.sonar.api.measures.CoreMetrics.SKIPPED_TESTS;
@@ -129,21 +114,7 @@ public class ScannerMetrics {
     COVERED_CONDITIONS_BY_LINE,
     CONDITIONS_BY_LINE,
 
-    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_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);
+    EXECUTABLE_LINES_DATA);
 
   private final Set<Metric> metrics;
 
@@ -160,16 +131,9 @@ public class ScannerMetrics {
   }
 
   private static Iterable<Metric> getPluginMetrics(Metrics[] metricsRepositories) {
-    return from(asList(metricsRepositories)).transformAndConcat(FlattenMetrics.INSTANCE);
-  }
-
-  private enum FlattenMetrics implements Function<Metrics, List<Metric>> {
-    INSTANCE;
-
-    @Nullable
-    @Override
-    public List<Metric> apply(Metrics input) {
-      return input.getMetrics();
-    }
+    return Arrays.stream(metricsRepositories)
+      .map(Metrics::getMetrics)
+      .flatMap(List::stream)
+      .collect(Collectors.toList());
   }
 }
index 346da60709abfe0a476913f4057ee337e96e4303..80c9231b2c151d0095b71b38f5fbfd386228ac43 100644 (file)
@@ -36,7 +36,7 @@ public class ScannerMetricsTest {
 
   @Test
   public void check_number_of_allowed_core_metrics() throws Exception {
-    assertThat(SENSOR_METRICS_WITHOUT_METRIC_PLUGIN.getMetrics()).hasSize(47);
+    assertThat(SENSOR_METRICS_WITHOUT_METRIC_PLUGIN.getMetrics()).hasSize(34);
   }
 
   @Test
index 96e5f9737badd8424bd9bbf562270758c9eae420..bb0090fd8e83b0752bf62cb2883ee6b12827d538 100644 (file)
@@ -139,7 +139,6 @@ public class DefaultCoverage extends DefaultStorable implements NewCoverage {
   @Override
   public void doSave() {
     validateFile();
-    Preconditions.checkNotNull(type, "Call ofType() first");
     storage.store(this);
   }
 
index 06b0e1a889ed03523f6d0000113bce94cfaafa35..9700220b47f01403c13a61ac44c7d41ef5edd351 100644 (file)
@@ -63,7 +63,6 @@ public class Measure<G extends Serializable> implements Serializable {
   protected String url;
   protected Integer personId;
   protected PersistenceMode persistenceMode = PersistenceMode.FULL;
-  private boolean fromCore;
 
   public Measure(String metricKey) {
     this.metricKey = metricKey;
@@ -640,20 +639,6 @@ public class Measure<G extends Serializable> implements Serializable {
       && isZeroVariation(variation1, variation2, variation3, variation4, variation5);
   }
 
-  /**
-   * For internal use
-   */
-  public boolean isFromCore() {
-    return fromCore;
-  }
-
-  /**
-   * For internal use
-   */
-  public void setFromCore(boolean fromCore) {
-    this.fromCore = fromCore;
-  }
-
   private static boolean isZeroVariation(Double... variations) {
     for (Double variation : variations) {
       if (variation != null && NumberUtils.compare(variation, 0.0) != 0) {
index ca5dc73c1c92af6af87649374306e719ad880b29..2a22d573b1e7d65ef3ddf3b938c5c68915213c42 100644 (file)
@@ -28,9 +28,9 @@ import java.util.Map;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.sensor.SensorContext;
+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.measures.Measure;
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.api.utils.KeyValueFormat.Converter;
 import org.sonar.scanner.scan.measure.MeasureCache;
@@ -152,8 +152,8 @@ public class DefaultFileLinesContext implements FileLinesContext {
   }
 
   private Map loadData(String metricKey, Converter converter) {
-    Measure measure = measureCache.byMetric(inputFile.key(), metricKey);
-    String data = measure != null ? measure.getData() : null;
+    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));
     }
index bd97a527353c44b2286174d2baca515ae59e087e..8a5df01a5597a5640ba4c62a4e221002a91c8aeb 100644 (file)
@@ -42,20 +42,17 @@ import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
 import org.sonar.scanner.index.DefaultIndex;
 import org.sonar.scanner.sensor.DefaultSensorContext;
-import org.sonar.scanner.sensor.coverage.CoverageExclusions;
 
 public class DeprecatedSensorContext extends DefaultSensorContext implements SensorContext {
 
   private final DefaultIndex index;
   private final Project project;
-  private final CoverageExclusions coverageFilter;
 
   public DeprecatedSensorContext(InputModule module, DefaultIndex index, Project project, Settings settings, FileSystem fs, ActiveRules activeRules,
-    AnalysisMode analysisMode, CoverageExclusions coverageFilter, SensorStorage sensorStorage, SonarRuntime sonarRuntime) {
+    AnalysisMode analysisMode, SensorStorage sensorStorage, SonarRuntime sonarRuntime) {
     super(module, settings, fs, activeRules, analysisMode, sensorStorage, sonarRuntime);
     this.index = index;
     this.project = project;
-    this.coverageFilter = coverageFilter;
 
   }
 
@@ -124,19 +121,13 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen
   @Override
   public Measure saveMeasure(Resource resource, Metric metric, Double value) {
     Measure<?> measure = new Measure(metric, value);
-    coverageFilter.validate(measure, resource.getPath());
     return saveMeasure(resource, measure);
   }
 
   @Override
   public Measure saveMeasure(Resource resource, Measure measure) {
     Resource resourceOrProject = resourceOrProject(resource);
-
-    if (coverageFilter.accept(resourceOrProject, measure)) {
-      return index.addMeasure(resourceOrProject, measure);
-    } else {
-      return measure;
-    }
+    return index.addMeasure(resourceOrProject, measure);
   }
 
   @Override
@@ -155,13 +146,11 @@ public class DeprecatedSensorContext extends DefaultSensorContext implements Sen
   @Override
   public Measure saveMeasure(InputFile inputFile, Metric metric, Double value) {
     Measure<?> measure = new Measure(metric, value);
-    coverageFilter.validate(measure, inputFile);
     return saveMeasure(getResource(inputFile), measure);
   }
 
   @Override
   public Measure saveMeasure(InputFile inputFile, Measure measure) {
-    coverageFilter.validate(measure, inputFile);
     return saveMeasure(getResource(inputFile), measure);
   }
 
index 1b6028d41f8fc2f065c7f57fa8865c28aa58e2a9..40ae68cfe7f716c3d6735128ee10eb2a90db5af2 100644 (file)
@@ -24,13 +24,11 @@ import com.persistit.Exchange;
 import com.persistit.Key;
 import com.persistit.KeyFilter;
 import com.persistit.exception.PersistitException;
-import org.apache.commons.lang.builder.ToStringBuilder;
-
-import javax.annotation.CheckForNull;
-
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Set;
+import javax.annotation.CheckForNull;
+import org.apache.commons.lang.builder.ToStringBuilder;
 
 /**
  * <p>
@@ -73,7 +71,7 @@ public class Cache<V> {
       exchange.store();
       return this;
     } catch (Exception e) {
-      throw new IllegalStateException("Fail to put element in the cache " + name, e);
+      throw new IllegalStateException("Fail to put element in the storage '" + name + "'", e);
     }
   }
 
index cf929bc3271c4092cb3cae655eb9766013728921..23d1c4b8a66debf141ee1ba6c3a300909ca802b1 100644 (file)
@@ -37,16 +37,21 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.design.Dependency;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.MeasuresFilter;
 import org.sonar.api.measures.MeasuresFilters;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metric.ValueType;
 import org.sonar.api.resources.File;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.resources.ResourceUtils;
 import org.sonar.api.scan.filesystem.PathResolver;
 import org.sonar.core.component.ComponentKeys;
+import org.sonar.core.util.stream.Collectors;
 import org.sonar.scanner.DefaultProjectTree;
 import org.sonar.scanner.scan.measure.MeasureCache;
 import org.sonar.scanner.sensor.DefaultSensorStorage;
@@ -58,15 +63,17 @@ public class DefaultIndex {
   private final BatchComponentCache componentCache;
   private final MeasureCache measureCache;
   private final DefaultProjectTree projectTree;
+  private final MetricFinder metricFinder;
   // caches
   private DefaultSensorStorage sensorStorage;
   private Project currentProject;
   private Map<Resource, Bucket> buckets = Maps.newLinkedHashMap();
 
-  public DefaultIndex(BatchComponentCache componentCache, DefaultProjectTree projectTree, MeasureCache measureCache) {
+  public DefaultIndex(BatchComponentCache componentCache, DefaultProjectTree projectTree, MeasureCache measureCache, MetricFinder metricFinder) {
     this.componentCache = componentCache;
     this.projectTree = projectTree;
     this.measureCache = measureCache;
+    this.metricFinder = metricFinder;
   }
 
   public void start() {
@@ -143,25 +150,83 @@ public class DefaultIndex {
     if (indexedResource == null) {
       return null;
     }
-    Collection<Measure> unfiltered = new ArrayList<>();
+    Collection<DefaultMeasure<?>> unfiltered = new ArrayList<>();
     if (filter instanceof MeasuresFilters.MetricFilter) {
       // optimization
-      Measure byMetric = measureCache.byMetric(indexedResource, ((MeasuresFilters.MetricFilter<M>) filter).filterOnMetricKey());
+      DefaultMeasure<?> byMetric = measureCache.byMetric(indexedResource.getEffectiveKey(), ((MeasuresFilters.MetricFilter<M>) filter).filterOnMetricKey());
       if (byMetric != null) {
         unfiltered.add(byMetric);
       }
     } else {
-      for (Measure measure : measureCache.byResource(indexedResource)) {
+      for (DefaultMeasure<?> measure : measureCache.byComponentKey(indexedResource.getEffectiveKey())) {
         unfiltered.add(measure);
       }
     }
-    return filter.filter(unfiltered);
+    return filter.filter(unfiltered.stream().map(DefaultIndex::toDeprecated).collect(Collectors.toList()));
+  }
+
+  private static Measure toDeprecated(org.sonar.api.batch.sensor.measure.Measure<?> measure) {
+    org.sonar.api.measures.Measure deprecatedMeasure = new org.sonar.api.measures.Measure((Metric<?>) measure.metric());
+    setValueAccordingToMetricType(measure, deprecatedMeasure);
+    return deprecatedMeasure;
+  }
+
+  private static void setValueAccordingToMetricType(org.sonar.api.batch.sensor.measure.Measure<?> measure, Measure measureToSave) {
+    ValueType deprecatedType = ((Metric<?>) measure.metric()).getType();
+    switch (deprecatedType) {
+      case BOOL:
+        measureToSave.setValue(Boolean.TRUE.equals(measure.value()) ? 1.0 : 0.0);
+        break;
+      case INT:
+      case MILLISEC:
+      case WORK_DUR:
+      case FLOAT:
+      case PERCENT:
+      case RATING:
+        measureToSave.setValue(((Number) measure.value()).doubleValue());
+        break;
+      case STRING:
+      case LEVEL:
+      case DATA:
+      case DISTRIB:
+        measureToSave.setData((String) measure.value());
+        break;
+      default:
+        throw new UnsupportedOperationException("Unsupported type :" + deprecatedType);
+    }
   }
 
   public Measure addMeasure(Resource resource, Measure measure) {
     Bucket bucket = getBucket(resource);
     if (bucket != null) {
-      sensorStorage.saveMeasure(resource, measure);
+      if (sensorStorage.isDeprecatedMetric(measure.getMetricKey())) {
+        // Ignore deprecated metrics
+        return measure;
+      }
+      org.sonar.api.batch.measure.Metric<?> metric = metricFinder.findByKey(measure.getMetricKey());
+      if (metric == null) {
+        throw new UnsupportedOperationException("Unknown metric: " + measure.getMetricKey());
+      }
+      DefaultMeasure<?> newMeasure;
+      if (Boolean.class.equals(metric.valueType())) {
+        newMeasure = new DefaultMeasure<Boolean>().forMetric((Metric<Boolean>) metric)
+          .withValue(measure.getValue() != 0.0);
+      } else if (Integer.class.equals(metric.valueType())) {
+        newMeasure = new DefaultMeasure<Integer>().forMetric((Metric<Integer>) metric)
+          .withValue(measure.getValue().intValue());
+      } else if (Double.class.equals(metric.valueType())) {
+        newMeasure = new DefaultMeasure<Double>().forMetric((Metric<Double>) metric)
+          .withValue(measure.getValue().doubleValue());
+      } else if (String.class.equals(metric.valueType())) {
+        newMeasure = new DefaultMeasure<String>().forMetric((Metric<String>) metric)
+          .withValue(measure.getData());
+      } else if (Long.class.equals(metric.valueType())) {
+        newMeasure = new DefaultMeasure<Long>().forMetric((Metric<Long>) metric)
+          .withValue(measure.getValue().longValue());
+      } else {
+        throw new UnsupportedOperationException("Unsupported type :" + metric.valueType());
+      }
+      sensorStorage.saveMeasure(componentCache.get(resource).inputComponent(), newMeasure);
     }
     return measure;
   }
index 49f12b154c8cfd381e9016a2322dddbc968e7e81..cf17785dab8411a189d6f7d8c59631f0d60b1124 100644 (file)
@@ -26,15 +26,15 @@ import java.util.Map;
 import javax.annotation.Nonnull;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
 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.scan.measure.MeasureCache;
 import org.sonar.scanner.index.BatchComponent;
 import org.sonar.scanner.index.BatchComponentCache;
+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.measure.MeasureCache;
 
 public class CoveragePublisher implements ReportPublisherStep {
 
@@ -112,7 +112,7 @@ public class CoveragePublisher implements ReportPublisherStep {
   }
 
   void applyLineMeasure(String inputFileKey, int lineCount, String metricKey, Map<Integer, LineCoverage.Builder> coveragePerLine, MeasureOperation op) {
-    Measure measure = measureCache.byMetric(inputFileKey, metricKey);
+    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()) {
index 74e2d43c0ff5b8ed01fdeb40ce57526f9a2f2b79..e00f9793cb1e093346ead3d0ceb11e33a82eb42b 100644 (file)
 package org.sonar.scanner.report;
 
 import com.google.common.base.Function;
-import com.google.common.base.Predicate;
 import java.io.Serializable;
-import java.util.Set;
 import javax.annotation.Nonnull;
 import org.sonar.api.batch.measure.Metric;
-import org.sonar.api.measures.Measure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.core.metric.ScannerMetrics;
 import org.sonar.scanner.index.BatchComponent;
 import org.sonar.scanner.index.BatchComponentCache;
@@ -35,16 +33,14 @@ 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.scan.measure.MeasureCache;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
+import org.sonar.scanner.scan.measure.MeasureCache;
 
-import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
-import static com.google.common.collect.Sets.newHashSet;
 
 public class MeasuresPublisher implements ReportPublisherStep {
 
-  private static final class MeasureToReportMeasure implements Function<Measure, ScannerReport.Measure> {
+  private static final class MeasureToReportMeasure implements Function<DefaultMeasure, ScannerReport.Measure> {
     private final BatchComponent resource;
     private final ScannerReport.Measure.Builder builder = ScannerReport.Measure.newBuilder();
 
@@ -53,69 +49,44 @@ public class MeasuresPublisher implements ReportPublisherStep {
     }
 
     @Override
-    public ScannerReport.Measure apply(@Nonnull Measure input) {
+    public ScannerReport.Measure apply(@Nonnull DefaultMeasure input) {
       validateMeasure(input, resource.key());
       return toReportMeasure(builder, input);
     }
 
-    private static void validateMeasure(Measure measure, String componentKey) {
-      if (measure.getValue() == null && measure.getData() == null) {
-        throw new IllegalArgumentException(String.format("Measure on metric '%s' and component '%s' has no value, but it's not allowed", measure.getMetricKey(), componentKey));
+    private static void validateMeasure(DefaultMeasure measure, String componentKey) {
+      if (measure.value() == null) {
+        throw new IllegalArgumentException(String.format("Measure on metric '%s' and component '%s' has no value, but it's not allowed", measure.metric().key(), componentKey));
       }
     }
 
-    private ScannerReport.Measure toReportMeasure(ScannerReport.Measure.Builder builder, Measure measure) {
+    private static ScannerReport.Measure toReportMeasure(ScannerReport.Measure.Builder builder, DefaultMeasure measure) {
       builder.clear();
-      builder.setMetricKey(measure.getMetricKey());
+      builder.setMetricKey(measure.metric().key());
       setValueAccordingToType(builder, measure);
       return builder.build();
     }
 
-    private void setValueAccordingToType(ScannerReport.Measure.Builder builder, Measure measure) {
+    private static void setValueAccordingToType(ScannerReport.Measure.Builder builder, DefaultMeasure measure) {
       Serializable value = measure.value();
-      String data = measure.getData() != null ? measure.getData() : "";
-      switch (measure.getMetric().getType()) {
-        case INT:
-        case RATING:
-          builder.setIntValue(IntValue.newBuilder().setValue(((Number) value).intValue()).setData(data));
-          break;
-        case FLOAT:
-        case PERCENT:
-          builder.setDoubleValue(DoubleValue.newBuilder().setValue(((Number) value).doubleValue()).setData(data));
-          break;
-        case BOOL:
-          builder.setBooleanValue(BoolValue.newBuilder().setValue(((Boolean) value).booleanValue()).setData(data));
-          break;
-        case WORK_DUR:
-        case MILLISEC:
-          builder.setLongValue(LongValue.newBuilder().setValue(((Number) value).longValue()).setData(data));
-          break;
-        case STRING:
-        case DATA:
-        case LEVEL:
-        case DISTRIB:
-          builder.setStringValue(StringValue.newBuilder().setValue((String) value));
-          break;
-        default:
-          throw new IllegalStateException("Unknown metric type: " + measure.getMetric().getType());
+      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 static final class IsMetricAllowed implements Predicate<Measure> {
-    private final Set<String> allowedMetricKeys;
-
-    private IsMetricAllowed(Set<String> allowedMetricKeys) {
-      this.allowedMetricKeys = allowedMetricKeys;
-    }
-
-    @Override
-    public boolean apply(Measure input) {
-      return allowedMetricKeys.contains(input.getMetricKey());
-    }
-  }
-
   private static final class MetricToKey implements Function<Metric, String> {
     @Override
     public String apply(Metric input) {
@@ -135,12 +106,9 @@ public class MeasuresPublisher implements ReportPublisherStep {
 
   @Override
   public void publish(ScannerReportWriter writer) {
-    final Set<String> allowedMetricKeys = newHashSet(transform(scannerMetrics.getMetrics(), new MetricToKey()));
     for (final BatchComponent resource : resourceCache.all()) {
-      Iterable<Measure> batchMeasures = measureCache.byResource(resource.resource());
-      Iterable<org.sonar.scanner.protocol.output.ScannerReport.Measure> reportMeasures = transform(
-        filter(batchMeasures, new IsMetricAllowed(allowedMetricKeys)),
-        new MeasureToReportMeasure(resource));
+      Iterable<DefaultMeasure<?>> scannerMeasures = measureCache.byComponentKey(resource.key());
+      Iterable<ScannerReport.Measure> reportMeasures = transform(scannerMeasures, new MeasureToReportMeasure(resource));
       writer.writeComponentMeasures(resource.batchId(), reportMeasures);
     }
   }
index 8792e32d9b94604346bd949aca33bb8da136250e..b0e9b87ceeb9426bd2f76bdcb55929425fdbb910 100644 (file)
@@ -23,11 +23,10 @@ import com.google.common.base.Preconditions;
 import javax.annotation.CheckForNull;
 import org.sonar.api.batch.ScannerSide;
 import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.Resource;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.scanner.index.Cache;
-import org.sonar.scanner.index.Caches;
 import org.sonar.scanner.index.Cache.Entry;
+import org.sonar.scanner.index.Caches;
 
 /**
  * Cache of all measures. This cache is shared amongst all project modules.
@@ -35,50 +34,41 @@ import org.sonar.scanner.index.Cache.Entry;
 @ScannerSide
 public class MeasureCache {
 
-  private final Cache<Measure> cache;
+  private final Cache<DefaultMeasure<?>> cache;
 
   public MeasureCache(Caches caches, MetricFinder metricFinder) {
-    caches.registerValueCoder(Measure.class, new MeasureValueCoder(metricFinder));
+    caches.registerValueCoder(DefaultMeasure.class, new MeasureValueCoder(metricFinder));
     cache = caches.createCache("measures");
   }
 
-  public Iterable<Entry<Measure>> entries() {
+  public Iterable<Entry<DefaultMeasure<?>>> entries() {
     return cache.entries();
   }
 
-  public Iterable<Measure> all() {
+  public Iterable<DefaultMeasure<?>> all() {
     return cache.values();
   }
 
-  public Iterable<Measure> byResource(Resource r) {
-    return byComponentKey(r.getEffectiveKey());
-  }
-
-  public Iterable<Measure> byComponentKey(String effectiveKey) {
+  public Iterable<DefaultMeasure<?>> byComponentKey(String effectiveKey) {
     return cache.values(effectiveKey);
   }
 
   @CheckForNull
-  public Measure byMetric(Resource r, String metricKey) {
-    return byMetric(r.getEffectiveKey(), metricKey);
-  }
-
-  @CheckForNull
-  public Measure byMetric(String componentKey, String metricKey) {
+  public DefaultMeasure<?> byMetric(String componentKey, String metricKey) {
     return cache.get(componentKey, metricKey);
   }
 
-  public MeasureCache put(Resource resource, Measure measure) {
-    Preconditions.checkNotNull(resource.getEffectiveKey());
-    Preconditions.checkNotNull(measure.getMetricKey());
-    cache.put(resource.getEffectiveKey(), measure.getMetricKey(), measure);
+  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(Resource resource, Measure measure) {
-    Preconditions.checkNotNull(resource.getEffectiveKey());
-    Preconditions.checkNotNull(measure.getMetricKey());
-    return cache.containsKey(resource.getEffectiveKey(), measure.getMetricKey());
+  public boolean contains(String componentKey, String metricKey) {
+    Preconditions.checkNotNull(componentKey);
+    Preconditions.checkNotNull(metricKey);
+    return cache.containsKey(componentKey, metricKey);
   }
 
 }
index f13151a590264d35175b3853209364364317ff3d..15655a1f46c4037d6914cfba432951c689faf724 100644 (file)
@@ -22,11 +22,9 @@ package org.sonar.scanner.scan.measure;
 import com.persistit.Value;
 import com.persistit.encoding.CoderContext;
 import com.persistit.encoding.ValueCoder;
-import javax.annotation.Nullable;
+import java.io.Serializable;
 import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.PersistenceMode;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 
 class MeasureValueCoder implements ValueCoder {
 
@@ -38,57 +36,22 @@ class MeasureValueCoder implements ValueCoder {
 
   @Override
   public void put(Value value, Object object, CoderContext context) {
-    Measure<?> m = (Measure) object;
-    value.putUTF(m.getMetricKey());
-    value.put(m.getValue());
-    putUTFOrNull(value, m.getData());
-    putUTFOrNull(value, m.getDescription());
-    value.putString(m.getAlertStatus() != null ? m.getAlertStatus().name() : null);
-    putUTFOrNull(value, m.getAlertText());
-    value.putDate(m.getDate());
-    value.put(m.getVariation1());
-    value.put(m.getVariation2());
-    value.put(m.getVariation3());
-    value.put(m.getVariation4());
-    value.put(m.getVariation5());
-    putUTFOrNull(value, m.getUrl());
-    Integer personId = m.getPersonId();
-    value.put(personId != null ? personId.intValue() : null);
-    PersistenceMode persistenceMode = m.getPersistenceMode();
-    value.putString(persistenceMode != null ? persistenceMode.name() : null);
-  }
-
-  private static void putUTFOrNull(Value value, @Nullable String utfOrNull) {
-    if (utfOrNull != null) {
-      value.putUTF(utfOrNull);
-    } else {
-      value.putNull();
-    }
+    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) {
-    Measure<?> m = new Measure();
     String metricKey = value.getString();
-    org.sonar.api.batch.measure.Metric metric = metricFinder.findByKey(metricKey);
+    org.sonar.api.batch.measure.Metric<?> metric = metricFinder.findByKey(metricKey);
     if (metric == null) {
       throw new IllegalStateException("Unknow metric with key " + metricKey);
     }
-    m.setMetric((org.sonar.api.measures.Metric) metric);
-    m.setRawValue(value.isNull(true) ? null : value.getDouble());
-    m.setData(value.getString());
-    m.setDescription(value.getString());
-    m.setAlertStatus(value.isNull(true) ? null : Metric.Level.valueOf(value.getString()));
-    m.setAlertText(value.getString());
-    m.setDate(value.getDate());
-    m.setVariation1(value.isNull(true) ? null : value.getDouble());
-    m.setVariation2(value.isNull(true) ? null : value.getDouble());
-    m.setVariation3(value.isNull(true) ? null : value.getDouble());
-    m.setVariation4(value.isNull(true) ? null : value.getDouble());
-    m.setVariation5(value.isNull(true) ? null : value.getDouble());
-    m.setUrl(value.getString());
-    m.setPersonId(value.isNull(true) ? null : value.getInt());
-    m.setPersistenceMode(value.isNull(true) ? null : PersistenceMode.valueOf(value.getString()));
+    DefaultMeasure<?> m = new DefaultMeasure()
+      .forMetric(metric)
+      .withValue((Serializable) value.get());
     return m;
   }
 }
index 1c2f90b686f33b8f9fd9de0375e6d330337a2066..41478c716c113f2408e221f1ad94029fbaf2d9c3 100644 (file)
@@ -23,9 +23,14 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.collect.Iterables;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.annotation.Nonnull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -33,8 +38,8 @@ import org.sonar.api.batch.fs.InputComponent;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.TextRange;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.measure.Metric;
 import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.sensor.coverage.CoverageType;
 import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage;
 import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
 import org.sonar.api.batch.sensor.error.AnalysisError;
@@ -46,17 +51,12 @@ import org.sonar.api.batch.sensor.measure.Measure;
 import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
 import org.sonar.api.config.Settings;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Resource;
 import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.api.utils.SonarException;
+import org.sonar.core.metric.ScannerMetrics;
 import org.sonar.duplications.block.Block;
 import org.sonar.duplications.internal.pmd.PmdBlockChunker;
 import org.sonar.scanner.cpd.deprecated.DefaultCpdBlockIndexer;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
-import org.sonar.scanner.index.BatchComponent;
 import org.sonar.scanner.index.BatchComponentCache;
 import org.sonar.scanner.issue.ModuleIssues;
 import org.sonar.scanner.protocol.output.FileStructure;
@@ -68,26 +68,77 @@ import org.sonar.scanner.repository.ContextPropertiesCache;
 import org.sonar.scanner.scan.measure.MeasureCache;
 import org.sonar.scanner.sensor.coverage.CoverageExclusions;
 
+import static org.sonar.api.measures.CoreMetrics.BRANCH_COVERAGE;
+import static org.sonar.api.measures.CoreMetrics.COMMENTED_OUT_CODE_LINES_KEY;
+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;
+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.DEPENDENCY_MATRIX_KEY;
+import static org.sonar.api.measures.CoreMetrics.DIRECTORY_CYCLES_KEY;
+import static org.sonar.api.measures.CoreMetrics.DIRECTORY_EDGES_WEIGHT_KEY;
+import static org.sonar.api.measures.CoreMetrics.DIRECTORY_FEEDBACK_EDGES_KEY;
+import static org.sonar.api.measures.CoreMetrics.DIRECTORY_TANGLES_KEY;
+import static org.sonar.api.measures.CoreMetrics.DIRECTORY_TANGLE_INDEX_KEY;
+import static org.sonar.api.measures.CoreMetrics.FILE_CYCLES_KEY;
+import static org.sonar.api.measures.CoreMetrics.FILE_EDGES_WEIGHT_KEY;
+import static org.sonar.api.measures.CoreMetrics.FILE_FEEDBACK_EDGES_KEY;
+import static org.sonar.api.measures.CoreMetrics.FILE_TANGLES_KEY;
+import static org.sonar.api.measures.CoreMetrics.FILE_TANGLE_INDEX_KEY;
+import static org.sonar.api.measures.CoreMetrics.IT_BRANCH_COVERAGE;
+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;
+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_LINE_COVERAGE;
+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;
+import static org.sonar.api.measures.CoreMetrics.LINES_TO_COVER;
+import static org.sonar.api.measures.CoreMetrics.LINE_COVERAGE;
+import static org.sonar.api.measures.CoreMetrics.OVERALL_BRANCH_COVERAGE;
+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;
+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_LINE_COVERAGE;
+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.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_LINES;
+
 public class DefaultSensorStorage implements SensorStorage {
 
   private static final Logger LOG = LoggerFactory.getLogger(DefaultSensorStorage.class);
 
-  private static final List<Metric> INTERNAL_METRICS = Arrays.<Metric>asList(
+  private static final List<Metric<?>> INTERNAL_METRICS = Arrays.<Metric<?>>asList(
     // Computed by LinesSensor
-    CoreMetrics.LINES);
+    LINES);
 
   private static final List<String> DEPRECATED_METRICS_KEYS = Arrays.asList(
-    CoreMetrics.DEPENDENCY_MATRIX_KEY,
-    CoreMetrics.DIRECTORY_CYCLES_KEY,
-    CoreMetrics.DIRECTORY_EDGES_WEIGHT_KEY,
-    CoreMetrics.DIRECTORY_FEEDBACK_EDGES_KEY,
-    CoreMetrics.DIRECTORY_TANGLE_INDEX_KEY,
-    CoreMetrics.DIRECTORY_TANGLES_KEY,
-    CoreMetrics.FILE_CYCLES_KEY,
-    CoreMetrics.FILE_EDGES_WEIGHT_KEY,
-    CoreMetrics.FILE_FEEDBACK_EDGES_KEY,
-    CoreMetrics.FILE_TANGLE_INDEX_KEY,
-    CoreMetrics.FILE_TANGLES_KEY);
+    DEPENDENCY_MATRIX_KEY,
+    DIRECTORY_CYCLES_KEY,
+    DIRECTORY_EDGES_WEIGHT_KEY,
+    DIRECTORY_FEEDBACK_EDGES_KEY,
+    DIRECTORY_TANGLE_INDEX_KEY,
+    DIRECTORY_TANGLES_KEY,
+    FILE_CYCLES_KEY,
+    FILE_EDGES_WEIGHT_KEY,
+    FILE_FEEDBACK_EDGES_KEY,
+    FILE_TANGLE_INDEX_KEY,
+    FILE_TANGLES_KEY,
+    COMMENTED_OUT_CODE_LINES_KEY);
+
+  private static final List<String> COMPUTED_ON_CE_SIDE_METRICS_KEYS = Arrays.asList(
+    TEST_SUCCESS_DENSITY_KEY,
+    PUBLIC_DOCUMENTED_API_DENSITY_KEY);
 
   private final MetricFinder metricFinder;
   private final ModuleIssues moduleIssues;
@@ -98,12 +149,16 @@ public class DefaultSensorStorage implements SensorStorage {
   private final SonarCpdBlockIndex index;
   private final ContextPropertiesCache contextPropertiesCache;
   private final Settings settings;
+  private final ScannerMetrics scannerMetrics;
+  private final Map<Metric<?>, Metric<?>> deprecatedCoverageMetricMapping = new IdentityHashMap<>();
+  private final Set<Metric<?>> coverageMetrics = new HashSet<>();
+  private final Set<Metric<?>> byLineMetrics = new HashSet<>();
 
   public DefaultSensorStorage(MetricFinder metricFinder, ModuleIssues moduleIssues,
     Settings settings,
     CoverageExclusions coverageExclusions, BatchComponentCache componentCache, ReportPublisher reportPublisher,
     MeasureCache measureCache, SonarCpdBlockIndex index,
-    ContextPropertiesCache contextPropertiesCache) {
+    ContextPropertiesCache contextPropertiesCache, ScannerMetrics scannerMetrics) {
     this.metricFinder = metricFinder;
     this.moduleIssues = moduleIssues;
     this.settings = settings;
@@ -113,83 +168,163 @@ public class DefaultSensorStorage implements SensorStorage {
     this.measureCache = measureCache;
     this.index = index;
     this.contextPropertiesCache = contextPropertiesCache;
-  }
+    this.scannerMetrics = scannerMetrics;
 
-  private Metric findMetricOrFail(String metricKey) {
-    Metric m = (Metric) metricFinder.findByKey(metricKey);
-    if (m == null) {
-      throw new IllegalStateException("Unknow metric with key: " + metricKey);
-    }
-    return m;
+    coverageMetrics.add(UNCOVERED_LINES);
+    coverageMetrics.add(LINES_TO_COVER);
+    coverageMetrics.add(UNCOVERED_CONDITIONS);
+    coverageMetrics.add(CONDITIONS_TO_COVER);
+    coverageMetrics.add(CONDITIONS_BY_LINE);
+    coverageMetrics.add(COVERED_CONDITIONS_BY_LINE);
+    coverageMetrics.add(COVERAGE_LINE_HITS_DATA);
+
+    byLineMetrics.add(COVERAGE_LINE_HITS_DATA);
+    byLineMetrics.add(COVERED_CONDITIONS_BY_LINE);
+    byLineMetrics.add(CONDITIONS_BY_LINE);
+
+    deprecatedCoverageMetricMapping.put(IT_COVERAGE, COVERAGE);
+    deprecatedCoverageMetricMapping.put(IT_LINE_COVERAGE, LINE_COVERAGE);
+    deprecatedCoverageMetricMapping.put(IT_BRANCH_COVERAGE, BRANCH_COVERAGE);
+    deprecatedCoverageMetricMapping.put(IT_UNCOVERED_LINES, UNCOVERED_LINES);
+    deprecatedCoverageMetricMapping.put(IT_LINES_TO_COVER, LINES_TO_COVER);
+    deprecatedCoverageMetricMapping.put(IT_UNCOVERED_CONDITIONS, UNCOVERED_CONDITIONS);
+    deprecatedCoverageMetricMapping.put(IT_CONDITIONS_TO_COVER, CONDITIONS_TO_COVER);
+    deprecatedCoverageMetricMapping.put(IT_CONDITIONS_BY_LINE, CONDITIONS_BY_LINE);
+    deprecatedCoverageMetricMapping.put(IT_COVERED_CONDITIONS_BY_LINE, COVERED_CONDITIONS_BY_LINE);
+    deprecatedCoverageMetricMapping.put(IT_COVERAGE_LINE_HITS_DATA, COVERAGE_LINE_HITS_DATA);
+    deprecatedCoverageMetricMapping.put(OVERALL_COVERAGE, COVERAGE);
+    deprecatedCoverageMetricMapping.put(OVERALL_LINE_COVERAGE, LINE_COVERAGE);
+    deprecatedCoverageMetricMapping.put(OVERALL_BRANCH_COVERAGE, BRANCH_COVERAGE);
+    deprecatedCoverageMetricMapping.put(OVERALL_UNCOVERED_LINES, UNCOVERED_LINES);
+    deprecatedCoverageMetricMapping.put(OVERALL_LINES_TO_COVER, LINES_TO_COVER);
+    deprecatedCoverageMetricMapping.put(OVERALL_UNCOVERED_CONDITIONS, UNCOVERED_CONDITIONS);
+    deprecatedCoverageMetricMapping.put(OVERALL_CONDITIONS_TO_COVER, CONDITIONS_TO_COVER);
+    deprecatedCoverageMetricMapping.put(OVERALL_CONDITIONS_BY_LINE, CONDITIONS_BY_LINE);
+    deprecatedCoverageMetricMapping.put(OVERALL_COVERED_CONDITIONS_BY_LINE, COVERED_CONDITIONS_BY_LINE);
+    deprecatedCoverageMetricMapping.put(OVERALL_COVERAGE_LINE_HITS_DATA, COVERAGE_LINE_HITS_DATA);
   }
 
   @Override
   public void store(Measure newMeasure) {
-    DefaultMeasure<?> measure = (DefaultMeasure<?>) newMeasure;
-    org.sonar.api.measures.Metric m = findMetricOrFail(measure.metric().key());
-    org.sonar.api.measures.Measure measureToSave = new org.sonar.api.measures.Measure(m);
-    setValueAccordingToMetricType(newMeasure, m, measureToSave);
-    measureToSave.setFromCore(measure.isFromCore());
-    InputComponent inputComponent = newMeasure.inputComponent();
-    Resource resource = componentCache.get(inputComponent).resource();
-    if (coverageExclusions.accept(resource, measureToSave)) {
-      saveMeasure(resource, measureToSave);
-    }
+    saveMeasure(newMeasure.inputComponent(), (DefaultMeasure<?>) newMeasure);
   }
 
-  public void saveMeasure(Resource resource, org.sonar.api.measures.Measure measure) {
-    if (DEPRECATED_METRICS_KEYS.contains(measure.getMetricKey())) {
-      // Ignore deprecated metrics
+  public void saveMeasure(InputComponent component, DefaultMeasure<?> measure) {
+    if (isDeprecatedMetric(measure.metric().key()) || isComputedOnCeMetric(measure.metric().key())) {
+      LOG.debug("Metric '{}' should not be saved by Sensors. It will be ignored.", measure.metric().key());
+      // Ignore deprecated and CE side metrics
       return;
     }
-    org.sonar.api.batch.measure.Metric metric = metricFinder.findByKey(measure.getMetricKey());
+    Metric<?> metric = metricFinder.findByKey(measure.metric().key());
     if (metric == null) {
-      throw new SonarException("Unknown metric: " + measure.getMetricKey());
+      throw new UnsupportedOperationException("Unknown metric: " + measure.metric().key());
+    }
+    if (!scannerMetrics.getMetrics().contains(metric)) {
+      throw new UnsupportedOperationException("Metric '" + metric.key() + "' should not be computed by a Sensor");
     }
     if (!measure.isFromCore() && INTERNAL_METRICS.contains(metric)) {
       LOG.debug("Metric " + metric.key() + " is an internal metric computed by SonarQube. Provided value is ignored.");
+      return;
+    }
+    if (deprecatedCoverageMetricMapping.containsKey(metric)) {
+      metric = deprecatedCoverageMetricMapping.get(metric);
     }
-    if (measureCache.contains(resource, measure)) {
-      throw new SonarException("Can not add the same measure twice on " + resource + ": " + measure);
+
+    if (coverageMetrics.contains(metric)) {
+      if (!component.isFile()) {
+        throw new UnsupportedOperationException("Saving coverage metric is only allowed on files. Attempt to save '" + metric.key() + "' on '" + component.key() + "'");
+      }
+      if (coverageExclusions.isExcluded((InputFile) component)) {
+        return;
+      }
+      saveCoverageMetricInternal((InputFile) component, metric, measure);
+    } 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(), measure);
     }
-    measureCache.put(resource, measure);
   }
 
-  private void setValueAccordingToMetricType(Measure<?> measure, org.sonar.api.measures.Metric<?> m, org.sonar.api.measures.Measure measureToSave) {
-    switch (m.getType()) {
-      case BOOL:
-        measureToSave.setValue(Boolean.TRUE.equals(measure.value()) ? 1.0 : 0.0);
-        break;
-      case INT:
-      case MILLISEC:
-      case WORK_DUR:
-      case FLOAT:
-      case PERCENT:
-      case RATING:
-        measureToSave.setValue(((Number) measure.value()).doubleValue());
-        break;
-      case STRING:
-      case LEVEL:
-      case DATA:
-      case DISTRIB:
-        measureToSave.setData((String) measure.value());
-        break;
-      default:
-        throw new UnsupportedOperationException("Unsupported type :" + m.getType());
+  private void saveCoverageMetricInternal(InputFile file, Metric<?> metric, DefaultMeasure<?> measure) {
+    if (isLineMetrics(metric)) {
+      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(KeyValueFormat.format(mergeLineMetric((String) previousMeasure.value(), (String) measure.value()))));
+      } else {
+        measureCache.put(file.key(), metric.key(), measure);
+      }
+    } else {
+      // Other coverage metrics are all integer values
+      DefaultMeasure<?> previousMeasure = measureCache.byMetric(file.key(), metric.key());
+      if (previousMeasure != null) {
+        measureCache.put(file.key(), metric.key(), new DefaultMeasure<Integer>()
+          .forMetric((Metric<Integer>) metric)
+          .withValue(Math.max((Integer) previousMeasure.value(), (Integer) measure.value())));
+      } else {
+        measureCache.put(file.key(), metric.key(), measure);
+      }
     }
   }
 
-  @Override
-  public void store(Issue issue) {
-    moduleIssues.initAndAddIssue(issue);
+  /**
+   * Merge the two line data measures, keeping max value in case they both contains a value for the same line.
+   */
+  private Map<Integer, Integer> mergeLineMetric(String value1, String value2) {
+    Map<Integer, Integer> data1 = KeyValueFormat.parseIntInt(value1);
+    Map<Integer, Integer> data2 = KeyValueFormat.parseIntInt(value2);
+    return Stream.of(data1, data2)
+      .map(Map::entrySet)
+      .flatMap(Collection::stream)
+      .collect(
+        Collectors.toMap(
+          Map.Entry::getKey,
+          Map.Entry::getValue,
+          Integer::max));
+  }
+
+  public boolean isDeprecatedMetric(String metricKey) {
+    return DEPRECATED_METRICS_KEYS.contains(metricKey);
   }
 
-  private File getFile(InputFile file) {
-    BatchComponent r = componentCache.get(file);
-    if (r == null) {
-      throw new IllegalStateException("Provided input file is not indexed");
+  public boolean isComputedOnCeMetric(String metricKey) {
+    return COMPUTED_ON_CE_SIDE_METRICS_KEYS.contains(metricKey);
+  }
+
+  private boolean isLineMetrics(Metric<?> metric) {
+    return this.byLineMetrics.contains(metric);
+  }
+
+  public void validateCoverageMeasure(String value, InputFile inputFile) {
+    Map<Integer, Integer> m = KeyValueFormat.parseIntInt(value);
+    validatePositiveLine(m, inputFile.absolutePath());
+    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.absolutePath(), maxLine));
+      }
     }
-    return (File) r.resource();
+  }
+
+  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));
+      }
+    }
+  }
+
+  @Override
+  public void store(Issue issue) {
+    moduleIssues.initAndAddIssue(issue);
   }
 
   @Override
@@ -241,21 +376,25 @@ public class DefaultSensorStorage implements SensorStorage {
 
   @Override
   public void store(DefaultCoverage defaultCoverage) {
-    File file = getFile(defaultCoverage.inputFile());
-    if (coverageExclusions.hasMatchingPattern(file)) {
+    if (coverageExclusions.isExcluded(defaultCoverage.inputFile())) {
       return;
     }
-    CoverageType type = defaultCoverage.type();
     if (defaultCoverage.linesToCover() > 0) {
-      saveMeasure(file, new org.sonar.api.measures.Measure(type.linesToCover(), (double) defaultCoverage.linesToCover()));
-      saveMeasure(file, new org.sonar.api.measures.Measure(type.uncoveredLines(), (double) (defaultCoverage.linesToCover() - defaultCoverage.coveredLines())));
-      saveMeasure(file, new org.sonar.api.measures.Measure(type.lineHitsData()).setData(KeyValueFormat.format(defaultCoverage.hitsByLine())));
+      saveCoverageMetricInternal(defaultCoverage.inputFile(), LINES_TO_COVER, new DefaultMeasure<Integer>().forMetric(LINES_TO_COVER).withValue(defaultCoverage.linesToCover()));
+      saveCoverageMetricInternal(defaultCoverage.inputFile(), UNCOVERED_LINES,
+        new DefaultMeasure<Integer>().forMetric(UNCOVERED_LINES).withValue(defaultCoverage.linesToCover() - defaultCoverage.coveredLines()));
+      saveCoverageMetricInternal(defaultCoverage.inputFile(), COVERAGE_LINE_HITS_DATA,
+        new DefaultMeasure<String>().forMetric(COVERAGE_LINE_HITS_DATA).withValue(KeyValueFormat.format(defaultCoverage.hitsByLine())));
     }
     if (defaultCoverage.conditions() > 0) {
-      saveMeasure(file, new org.sonar.api.measures.Measure(type.conditionsToCover(), (double) defaultCoverage.conditions()));
-      saveMeasure(file, new org.sonar.api.measures.Measure(type.uncoveredConditions(), (double) (defaultCoverage.conditions() - defaultCoverage.coveredConditions())));
-      saveMeasure(file, new org.sonar.api.measures.Measure(type.coveredConditionsByLine()).setData(KeyValueFormat.format(defaultCoverage.coveredConditionsByLine())));
-      saveMeasure(file, new org.sonar.api.measures.Measure(type.conditionsByLine()).setData(KeyValueFormat.format(defaultCoverage.conditionsByLine())));
+      saveCoverageMetricInternal(defaultCoverage.inputFile(), CONDITIONS_TO_COVER,
+        new DefaultMeasure<Integer>().forMetric(CONDITIONS_TO_COVER).withValue(defaultCoverage.conditions()));
+      saveCoverageMetricInternal(defaultCoverage.inputFile(), UNCOVERED_CONDITIONS,
+        new DefaultMeasure<Integer>().forMetric(UNCOVERED_CONDITIONS).withValue(defaultCoverage.conditions() - defaultCoverage.coveredConditions()));
+      saveCoverageMetricInternal(defaultCoverage.inputFile(), COVERED_CONDITIONS_BY_LINE,
+        new DefaultMeasure<String>().forMetric(COVERED_CONDITIONS_BY_LINE).withValue(KeyValueFormat.format(defaultCoverage.coveredConditionsByLine())));
+      saveCoverageMetricInternal(defaultCoverage.inputFile(), CONDITIONS_BY_LINE,
+        new DefaultMeasure<String>().forMetric(CONDITIONS_BY_LINE).withValue(KeyValueFormat.format(defaultCoverage.conditionsByLine())));
     }
   }
 
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/coverage/CoverageConstants.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/coverage/CoverageConstants.java
deleted file mode 100644 (file)
index 1bf0867..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.sensor.coverage;
-
-import com.google.common.collect.ImmutableList;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Metric;
-
-import java.util.Collection;
-
-public class CoverageConstants {
-
-  public static final Collection<Metric> COVERAGE_METRICS = ImmutableList.<Metric>of(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER,
-    CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS,
-    CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS);
-
-  public static final Collection<Metric> LINE_COVERAGE_METRICS = ImmutableList.<Metric>of(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES,
-    CoreMetrics.NEW_LINES_TO_COVER);
-
-  public static final Collection<Metric> BRANCH_COVERAGE_METRICS = ImmutableList.<Metric>of(CoreMetrics.UNCOVERED_CONDITIONS, CoreMetrics.CONDITIONS_TO_COVER,
-    CoreMetrics.NEW_UNCOVERED_CONDITIONS, CoreMetrics.NEW_CONDITIONS_TO_COVER);
-  
-  private CoverageConstants() {
-  }
-}
index 58e17f9251bb30da2e9e7da413dc8b2daf8cc6c0..00ee9421845209a6d861412a97d90596d2dce043 100644 (file)
@@ -23,168 +23,41 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.CheckForNull;
+import org.picocontainer.Startable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.config.Settings;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.api.utils.WildcardPattern;
 
-public class CoverageExclusions {
+public class CoverageExclusions implements Startable {
 
   private static final Logger LOG = LoggerFactory.getLogger(CoverageExclusions.class);
 
   private final Settings settings;
-  private final Set<Metric> coverageMetrics;
-  private final Set<Metric> byLineMetrics;
-  private Collection<WildcardPattern> resourcePatterns;
+  private Collection<WildcardPattern> exclusionPatterns;
 
-  private final FileSystem fs;
-
-  public CoverageExclusions(Settings settings, FileSystem fs) {
+  public CoverageExclusions(Settings settings) {
     this.settings = settings;
-    this.fs = fs;
-    this.coverageMetrics = new HashSet<>();
-    this.byLineMetrics = new HashSet<>();
-    // UT
-    coverageMetrics.add(CoreMetrics.COVERAGE);
-    coverageMetrics.add(CoreMetrics.LINE_COVERAGE);
-    coverageMetrics.add(CoreMetrics.BRANCH_COVERAGE);
-    coverageMetrics.add(CoreMetrics.UNCOVERED_LINES);
-    coverageMetrics.add(CoreMetrics.LINES_TO_COVER);
-    coverageMetrics.add(CoreMetrics.UNCOVERED_CONDITIONS);
-    coverageMetrics.add(CoreMetrics.CONDITIONS_TO_COVER);
-    coverageMetrics.add(CoreMetrics.CONDITIONS_BY_LINE);
-    coverageMetrics.add(CoreMetrics.COVERED_CONDITIONS_BY_LINE);
-    coverageMetrics.add(CoreMetrics.COVERAGE_LINE_HITS_DATA);
-    coverageMetrics.add(CoreMetrics.NEW_LINES_TO_COVER);
-    coverageMetrics.add(CoreMetrics.NEW_UNCOVERED_LINES);
-    coverageMetrics.add(CoreMetrics.NEW_UNCOVERED_CONDITIONS);
-    // IT
-    coverageMetrics.add(CoreMetrics.IT_COVERAGE);
-    coverageMetrics.add(CoreMetrics.IT_LINE_COVERAGE);
-    coverageMetrics.add(CoreMetrics.IT_BRANCH_COVERAGE);
-    coverageMetrics.add(CoreMetrics.IT_UNCOVERED_LINES);
-    coverageMetrics.add(CoreMetrics.IT_LINES_TO_COVER);
-    coverageMetrics.add(CoreMetrics.IT_UNCOVERED_CONDITIONS);
-    coverageMetrics.add(CoreMetrics.IT_CONDITIONS_TO_COVER);
-    coverageMetrics.add(CoreMetrics.IT_CONDITIONS_BY_LINE);
-    coverageMetrics.add(CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE);
-    coverageMetrics.add(CoreMetrics.IT_COVERAGE_LINE_HITS_DATA);
-    coverageMetrics.add(CoreMetrics.NEW_IT_LINES_TO_COVER);
-    coverageMetrics.add(CoreMetrics.NEW_IT_UNCOVERED_LINES);
-    coverageMetrics.add(CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS);
-    // OVERALL
-    coverageMetrics.add(CoreMetrics.OVERALL_COVERAGE);
-    coverageMetrics.add(CoreMetrics.OVERALL_LINE_COVERAGE);
-    coverageMetrics.add(CoreMetrics.OVERALL_BRANCH_COVERAGE);
-    coverageMetrics.add(CoreMetrics.OVERALL_UNCOVERED_LINES);
-    coverageMetrics.add(CoreMetrics.OVERALL_LINES_TO_COVER);
-    coverageMetrics.add(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS);
-    coverageMetrics.add(CoreMetrics.OVERALL_CONDITIONS_TO_COVER);
-    coverageMetrics.add(CoreMetrics.OVERALL_CONDITIONS_BY_LINE);
-    coverageMetrics.add(CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE);
-    coverageMetrics.add(CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA);
-    coverageMetrics.add(CoreMetrics.NEW_OVERALL_LINES_TO_COVER);
-    coverageMetrics.add(CoreMetrics.NEW_OVERALL_UNCOVERED_LINES);
-    coverageMetrics.add(CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS);
-
-    byLineMetrics.add(CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA);
-    byLineMetrics.add(CoreMetrics.OVERALL_CONDITIONS_BY_LINE);
-    byLineMetrics.add(CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE);
-    byLineMetrics.add(CoreMetrics.COVERAGE_LINE_HITS_DATA);
-    byLineMetrics.add(CoreMetrics.COVERED_CONDITIONS_BY_LINE);
-    byLineMetrics.add(CoreMetrics.CONDITIONS_BY_LINE);
-    byLineMetrics.add(CoreMetrics.IT_COVERAGE_LINE_HITS_DATA);
-    byLineMetrics.add(CoreMetrics.IT_CONDITIONS_BY_LINE);
-    byLineMetrics.add(CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE);
-
-    initPatterns();
-  }
-
-  private boolean isLineMetrics(Metric<?> metric) {
-    return this.byLineMetrics.contains(metric);
-  }
-
-  public void validate(Measure<?> measure, InputFile inputFile) {
-    Metric<?> metric = measure.getMetric();
-
-    if (!isLineMetrics(metric)) {
-      return;
-    }
-
-    Map<Integer, Integer> m = KeyValueFormat.parseIntInt(measure.getData());
-    validatePositiveLine(m, inputFile.absolutePath());
-    validateMaxLine(m, inputFile);
-  }
-
-  @CheckForNull
-  private InputFile getInputFile(String filePath) {
-    return fs.inputFile(fs.predicates().hasRelativePath(filePath));
-  }
-
-  public void validate(Measure<?> measure, String filePath) {
-    Metric<?> metric = measure.getMetric();
-
-    if (!isLineMetrics(metric)) {
-      return;
-    }
-
-    InputFile inputFile = getInputFile(filePath);
-
-    if (inputFile == null) {
-      throw new IllegalStateException(String.format("Can't create measure for resource '%s': resource is not indexed as a file", filePath));
-    }
-
-    validate(measure, inputFile);
-  }
-
-  private static void validateMaxLine(Map<Integer, Integer> m, InputFile inputFile) {
-    int maxLine = inputFile.lines();
-
-    for (int l : m.keySet()) {
-      if (l > maxLine) {
-        throw new IllegalStateException(String.format("Can't create measure for line %d for file '%s' with %d lines", l, inputFile.absolutePath(), maxLine));
-      }
-    }
-  }
-
-  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));
-      }
-    }
   }
 
-  public boolean accept(Resource resource, Measure<?> measure) {
-    if (isCoverageMetric(measure.getMetric())) {
-      return !hasMatchingPattern(resource);
-    } else {
-      return true;
-    }
+  @Override
+  public void start() {
+    initPatterns();
   }
 
-  private boolean isCoverageMetric(Metric<?> metric) {
-    return this.coverageMetrics.contains(metric);
+  @Override
+  public void stop() {
+    // Nothing to do
   }
 
-  public boolean hasMatchingPattern(Resource resource) {
+  public boolean isExcluded(InputFile file) {
     boolean found = false;
-    Iterator<WildcardPattern> iterator = resourcePatterns.iterator();
+    Iterator<WildcardPattern> iterator = exclusionPatterns.iterator();
     while (!found && iterator.hasNext()) {
-      found = resource.matchFilePattern(iterator.next().toString());
+      found = iterator.next().match(file.relativePath());
     }
     return found;
   }
@@ -195,8 +68,8 @@ public class CoverageExclusions {
     for (String pattern : settings.getStringArray(CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY)) {
       builder.add(WildcardPattern.create(pattern));
     }
-    resourcePatterns = builder.build();
-    log("Excluded sources for coverage: ", resourcePatterns);
+    exclusionPatterns = builder.build();
+    log("Excluded sources for coverage: ", exclusionPatterns);
   }
 
   private static void log(String title, Collection<WildcardPattern> patterns) {
index 432ba9ba9328e461323545766374575b35b0a7c7..782a7976db8e85f098312f3b1b48d999c51cab91 100644 (file)
@@ -34,8 +34,8 @@ 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.measures.Measure;
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.scanner.scan.measure.MeasureCache;
 
@@ -46,10 +46,10 @@ import static com.google.common.collect.Sets.newHashSet;
 @Phase(name = Phase.Name.POST)
 public final class ZeroCoverageSensor implements Sensor {
 
-  private static final class MeasureToMetricKey implements Function<Measure, String> {
+  private static final class MeasureToMetricKey implements Function<DefaultMeasure<?>, String> {
     @Override
-    public String apply(Measure input) {
-      return input.getMetricKey();
+    public String apply(DefaultMeasure<?> input) {
+      return input.metric().key();
     }
   }
 
@@ -76,7 +76,7 @@ public final class ZeroCoverageSensor implements Sensor {
     FileSystem fs = context.fileSystem();
     for (InputFile f : fs.inputFiles(fs.predicates().hasType(Type.MAIN))) {
       if (!isCoverageMeasuresAlreadyDefined(f)) {
-        Measure execLines = measureCache.byMetric(f.key(), CoreMetrics.EXECUTABLE_LINES_DATA_KEY);
+        DefaultMeasure<String> execLines = (DefaultMeasure<String>) measureCache.byMetric(f.key(), CoreMetrics.EXECUTABLE_LINES_DATA_KEY);
         if (execLines != null) {
           storeZeroCoverageForEachExecutableLine(context, f, execLines);
         }
@@ -85,8 +85,8 @@ public final class ZeroCoverageSensor implements Sensor {
     }
   }
 
-  private static void storeZeroCoverageForEachExecutableLine(final SensorContext context, InputFile f, Measure execLines) {
-    NewCoverage newCoverage = context.newCoverage().ofType(CoverageType.UNIT).onFile(f);
+  private static void storeZeroCoverageForEachExecutableLine(final SensorContext context, InputFile f, DefaultMeasure<String> execLines) {
+    NewCoverage newCoverage = context.newCoverage().onFile(f);
     Map<Integer, String> lineMeasures = KeyValueFormat.parseIntString((String) execLines.value());
     for (Map.Entry<Integer, String> lineMeasure : lineMeasures.entrySet()) {
       int lineIdx = lineMeasure.getKey();
index 647b67e110d78d710554fb329ae2f5f7f9bec5a9..37d74deeb2474d9920e8ded1c78162a7e4effb74 100644 (file)
@@ -27,9 +27,8 @@ import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.sensor.internal.SensorContextTester;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.scanner.DefaultFileLinesContext;
 import org.sonar.scanner.scan.measure.MeasureCache;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -146,7 +145,7 @@ public class DefaultFileLinesContextTest {
 
   @Test
   public void shouldLoadIntValues() {
-    when(measureCache.byMetric("foo:src/foo.php", HITS_METRIC_KEY)).thenReturn(new Measure(HITS_METRIC_KEY).setData("1=2;3=4"));
+    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));
@@ -155,7 +154,7 @@ public class DefaultFileLinesContextTest {
 
   @Test
   public void shouldLoadStringValues() {
-    when(measureCache.byMetric("foo:src/foo.php", AUTHOR_METRIC_KEY)).thenReturn(new Measure(AUTHOR_METRIC_KEY).setData("1=simon;3=evgeny"));
+    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"));
@@ -164,7 +163,7 @@ public class DefaultFileLinesContextTest {
 
   @Test(expected = UnsupportedOperationException.class)
   public void shouldNotModifyAfterLoad() {
-    when(measureCache.byMetric("foo:src/foo.php", AUTHOR_METRIC_KEY)).thenReturn(new Measure(AUTHOR_METRIC_KEY).setData("1=simon;3=evgeny"));
+    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");
index 9d52431cd4f33d274a8a00c4e498373e80a06043..4c0565b2e09b8da0c32999ed5ed749233fd264af 100644 (file)
@@ -25,6 +25,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.MeasuresFilters;
 import org.sonar.api.profiles.RulesProfile;
@@ -64,7 +65,7 @@ public class DefaultIndexTest {
 
     DefaultProjectTree projectTree = mock(DefaultProjectTree.class);
     BatchComponentCache resourceCache = new BatchComponentCache();
-    index = new DefaultIndex(resourceCache, projectTree, mock(MeasureCache.class));
+    index = new DefaultIndex(resourceCache, projectTree, mock(MeasureCache.class), mock(MetricFinder.class));
 
     baseDir = temp.newFolder();
     project = new Project("project");
index e5c5f0e99db93bdd5043203a6961b8fb2f714e6e..ccc5440ae8663e9c532820f84161144ee0fe7687 100644 (file)
@@ -59,7 +59,7 @@ public class CoverageMediumTest {
   }
 
   @Test
-  public void unitTests() throws IOException {
+  public void singleReport() throws IOException {
 
     File baseDir = temp.getRoot();
     File srcDir = new File(baseDir, "src");
@@ -98,6 +98,46 @@ public class CoverageMediumTest {
         tuple(CoreMetrics.UNCOVERED_CONDITIONS_KEY, 1));
   }
 
+  @Test
+  public void twoReports() throws IOException {
+
+    File baseDir = temp.getRoot();
+    File srcDir = new File(baseDir, "src");
+    srcDir.mkdir();
+
+    File xooFile = new File(srcDir, "sample.xoo");
+    FileUtils.write(xooFile, "function foo() {\n  if (a && b) {\nalert('hello');\n}\n}");
+    File xooUtCoverageFile = new File(srcDir, "sample.xoo.coverage");
+    FileUtils.write(xooUtCoverageFile, "2:2:2:2");
+    File xooItCoverageFile = new File(srcDir, "sample.xoo.itcoverage");
+    FileUtils.write(xooItCoverageFile, "2:2:2:1\n3:1");
+
+    TaskResult result = tester.newTask()
+      .properties(ImmutableMap.<String, String>builder()
+        .put("sonar.task", "scan")
+        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
+        .put("sonar.projectKey", "com.foo.project")
+        .put("sonar.projectName", "Foo Project")
+        .put("sonar.projectVersion", "1.0-SNAPSHOT")
+        .put("sonar.projectDescription", "Description of Foo Project")
+        .put("sonar.sources", "src")
+        .build())
+      .start();
+
+    InputFile file = result.inputFile("src/sample.xoo");
+    assertThat(result.coverageFor(file, 2).getUtHits()).isTrue();
+    assertThat(result.coverageFor(file, 2).getConditions()).isEqualTo(2);
+    assertThat(result.coverageFor(file, 2).getUtCoveredConditions()).isEqualTo(2);
+    assertThat(result.coverageFor(file, 3).getUtHits()).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")
+      .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
   public void exclusions() throws IOException {
 
index d465419e59b7ef4ae24f0e53f3a0f9117d793ea8..6ce6b181fc96984b43185a403f317b786892e90c 100644 (file)
@@ -27,16 +27,15 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
 import org.sonar.api.resources.Project;
 import org.sonar.core.util.CloseableIterator;
-import org.sonar.scanner.protocol.output.ScannerReport.LineCoverage;
-import org.sonar.scanner.report.CoveragePublisher;
-import org.sonar.scanner.scan.measure.MeasureCache;
 import org.sonar.scanner.index.BatchComponentCache;
+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.measure.MeasureCache;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Matchers.anyString;
@@ -68,67 +67,14 @@ public class CoveragePublisherTest {
   @Test
   public void publishCoverage() throws Exception {
 
-    Measure utLineHits = new Measure<>(CoreMetrics.COVERAGE_LINE_HITS_DATA).setData("2=1;3=1;5=0;6=3");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY)).thenReturn(utLineHits);
-
-    Measure itsConditionsByLine = new Measure<>(CoreMetrics.IT_CONDITIONS_BY_LINE).setData("3=4");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.IT_CONDITIONS_BY_LINE_KEY)).thenReturn(itsConditionsByLine);
-
-    Measure conditionsByLine = new Measure<>(CoreMetrics.CONDITIONS_BY_LINE).setData("3=4");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.CONDITIONS_BY_LINE_KEY)).thenReturn(conditionsByLine);
-
-    Measure coveredConditionsByUts = new Measure<>(CoreMetrics.COVERED_CONDITIONS_BY_LINE).setData("3=2");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY)).thenReturn(coveredConditionsByUts);
-
-    Measure itLineHits = new Measure<>(CoreMetrics.IT_COVERAGE_LINE_HITS_DATA).setData("2=0;3=0;5=1");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.IT_COVERAGE_LINE_HITS_DATA_KEY)).thenReturn(itLineHits);
-
-    Measure coveredConditionsByIts = new Measure<>(CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE).setData("3=1");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE_KEY)).thenReturn(coveredConditionsByIts);
-
-    Measure overallCoveredConditions = new Measure<>(CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE).setData("3=2");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE_KEY)).thenReturn(overallCoveredConditions);
-
-    File outputDir = temp.newFolder();
-    ScannerReportWriter writer = new ScannerReportWriter(outputDir);
-
-    publisher.publish(writer);
-
-    try (CloseableIterator<LineCoverage> it = new ScannerReportReader(outputDir).readComponentCoverage(2)) {
-      assertThat(it.next()).isEqualTo(LineCoverage.newBuilder()
-        .setLine(2)
-        .setUtHits(true)
-        .setItHits(false)
-        .build());
-      assertThat(it.next()).isEqualTo(LineCoverage.newBuilder()
-        .setLine(3)
-        .setUtHits(true)
-        .setItHits(false)
-        .setConditions(4)
-        .setUtCoveredConditions(2)
-        .setItCoveredConditions(1)
-        .setOverallCoveredConditions(2)
-        .build());
-      assertThat(it.next()).isEqualTo(LineCoverage.newBuilder()
-        .setLine(5)
-        .setUtHits(false)
-        .setItHits(true)
-        .build());
-    }
-
-  }
-
-  @Test
-  public void publishCoverageOnlyUts() throws Exception {
-
-    Measure utLineHits = new Measure<>(CoreMetrics.COVERAGE_LINE_HITS_DATA).setData("2=1;3=1;5=0;6=3");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY)).thenReturn(utLineHits);
+    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);
 
-    Measure conditionsByLine = new Measure<>(CoreMetrics.CONDITIONS_BY_LINE).setData("3=4");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.CONDITIONS_BY_LINE_KEY)).thenReturn(conditionsByLine);
+    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);
 
-    Measure coveredConditionsByUts = new Measure<>(CoreMetrics.COVERED_CONDITIONS_BY_LINE).setData("3=2");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY)).thenReturn(coveredConditionsByUts);
+    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);
@@ -153,40 +99,4 @@ public class CoveragePublisherTest {
     }
 
   }
-
-  @Test
-  public void publishCoverageOnlyIts() throws Exception {
-
-    Measure itsConditionsByLine = new Measure<>(CoreMetrics.IT_CONDITIONS_BY_LINE).setData("3=4");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.IT_CONDITIONS_BY_LINE_KEY)).thenReturn(itsConditionsByLine);
-
-    Measure itLineHits = new Measure<>(CoreMetrics.IT_COVERAGE_LINE_HITS_DATA).setData("2=0;3=0;5=1");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.IT_COVERAGE_LINE_HITS_DATA_KEY)).thenReturn(itLineHits);
-
-    Measure coveredConditionsByIts = new Measure<>(CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE).setData("3=1");
-    when(measureCache.byMetric("foo:src/Foo.php", CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE_KEY)).thenReturn(coveredConditionsByIts);
-
-    File outputDir = temp.newFolder();
-    ScannerReportWriter writer = new ScannerReportWriter(outputDir);
-
-    publisher.publish(writer);
-
-    try (CloseableIterator<LineCoverage> it = new ScannerReportReader(outputDir).readComponentCoverage(2)) {
-      assertThat(it.next()).isEqualTo(LineCoverage.newBuilder()
-        .setLine(2)
-        .setItHits(false)
-        .build());
-      assertThat(it.next()).isEqualTo(LineCoverage.newBuilder()
-        .setLine(3)
-        .setItHits(false)
-        .setConditions(4)
-        .setItCoveredConditions(1)
-        .build());
-      assertThat(it.next()).isEqualTo(LineCoverage.newBuilder()
-        .setLine(5)
-        .setItHits(true)
-        .build());
-    }
-
-  }
 }
index b11d262f7eb8680978ec175c0a2c4f06ccd08a34..7f264b74152e6249304198c0d3da93032c879d68 100644 (file)
@@ -28,28 +28,28 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
 import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
 import org.sonar.core.metric.ScannerMetrics;
 import org.sonar.core.util.CloseableIterator;
 import org.sonar.scanner.index.BatchComponentCache;
 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.MeasuresPublisher;
 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.Matchers.any;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 public class MeasuresPublisherTest {
 
+  private static final String FILE_KEY = "foo:src/Foo.php";
+
   @Rule
   public ExpectedException thrown = ExpectedException.none();
 
@@ -65,22 +65,22 @@ public class MeasuresPublisherTest {
   public void prepare() {
     Project p = new Project("foo").setAnalysisDate(new Date(1234567L));
     BatchComponentCache resourceCache = new BatchComponentCache();
-    sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php");
+    sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey(FILE_KEY);
     resourceCache.add(p, null);
     resourceCache.add(sampleFile, null);
     measureCache = mock(MeasureCache.class);
-    when(measureCache.byResource(any(Resource.class))).thenReturn(Collections.<Measure>emptyList());
+    when(measureCache.byComponentKey(anyString())).thenReturn(Collections.<DefaultMeasure<?>>emptyList());
     publisher = new MeasuresPublisher(resourceCache, measureCache, new ScannerMetrics());
   }
 
   @Test
   public void publishMeasures() throws Exception {
-    Measure measure = new Measure<>(CoreMetrics.LINES_TO_COVER)
-      .setValue(2.0);
+    DefaultMeasure<Integer> measure = new DefaultMeasure<Integer>().forMetric(CoreMetrics.LINES_TO_COVER)
+      .withValue(2);
     // String value
-    Measure stringMeasure = new Measure<>(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)
-      .setData("foo bar");
-    when(measureCache.byResource(sampleFile)).thenReturn(asList(measure, stringMeasure));
+    DefaultMeasure<String> stringMeasure = new DefaultMeasure<String>().forMetric(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)
+      .withValue("foo bar");
+    when(measureCache.byComponentKey(FILE_KEY)).thenReturn(asList(measure, stringMeasure));
 
     File outputDir = temp.newFolder();
     ScannerReportWriter writer = new ScannerReportWriter(outputDir);
@@ -97,8 +97,8 @@ public class MeasuresPublisherTest {
 
   @Test
   public void fail_with_IAE_when_measure_has_no_value() throws Exception {
-    Measure measure = new Measure<>(CoreMetrics.LINES_TO_COVER);
-    when(measureCache.byResource(sampleFile)).thenReturn(Collections.singletonList(measure));
+    DefaultMeasure<Integer> measure = new DefaultMeasure<Integer>().forMetric(CoreMetrics.LINES_TO_COVER);
+    when(measureCache.byComponentKey(FILE_KEY)).thenReturn(Collections.singletonList(measure));
 
     File outputDir = temp.newFolder();
     ScannerReportWriter writer = new ScannerReportWriter(outputDir);
index 555baa35173853513695fafc3869d978c6101bf5..702fd8a31d5f32bef59fa9c292b37d5754dcfa45 100644 (file)
  */
 package org.sonar.scanner.scan.measure;
 
-import java.util.Date;
 import java.util.Iterator;
-import org.apache.commons.lang.builder.EqualsBuilder;
 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.api.measures.Measure;
-import org.sonar.api.measures.Metric.Level;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
 import org.sonar.scanner.index.AbstractCachesTest;
 import org.sonar.scanner.index.Cache.Entry;
 
@@ -42,6 +35,9 @@ 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();
 
@@ -54,60 +50,28 @@ public class MeasureCacheTest extends AbstractCachesTest {
     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() {
-    Project p = new Project("struts");
-
     assertThat(measureCache.entries()).hasSize(0);
-    assertThat(measureCache.byResource(p)).hasSize(0);
+    assertThat(measureCache.byComponentKey(COMPONENT_KEY)).hasSize(0);
 
-    Measure m = new Measure(CoreMetrics.NCLOC, 1.0);
-    measureCache.put(p, m);
+    DefaultMeasure<?> m = new DefaultMeasure().forMetric(CoreMetrics.NCLOC).withValue(1.0);
+    measureCache.put(COMPONENT_KEY, CoreMetrics.NCLOC_KEY, m);
 
-    assertThat(measureCache.contains(p, m)).isTrue();
+    assertThat(measureCache.contains(COMPONENT_KEY, CoreMetrics.NCLOC_KEY)).isTrue();
     assertThat(measureCache.entries()).hasSize(1);
-    Iterator<Entry<Measure>> iterator = measureCache.entries().iterator();
+    Iterator<Entry<DefaultMeasure<?>>> iterator = measureCache.entries().iterator();
     iterator.hasNext();
-    Entry<Measure> next = iterator.next();
+    Entry<DefaultMeasure<?>> next = iterator.next();
     assertThat(next.value()).isEqualTo(m);
-    assertThat(next.key()[0]).isEqualTo("struts");
+    assertThat(next.key()[0]).isEqualTo(COMPONENT_KEY);
 
-    assertThat(measureCache.byResource(p)).hasSize(1);
-    assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m);
-  }
-
-  @Test
-  public void should_add_measure_with_big_data() {
-    Project p = new Project("struts");
-
-    assertThat(measureCache.entries()).hasSize(0);
-
-    assertThat(measureCache.byResource(p)).hasSize(0);
-
-    Measure m = new Measure(CoreMetrics.NCLOC, 1.0).setDate(new Date());
-    m.setAlertText("foooooooooooooooooooooooooooooooooooo");
-    StringBuilder data = new StringBuilder();
-    for (int i = 0; i < 1_048_575; i++) {
-      data.append("a");
-    }
-
-    m.setData(data.toString());
-
-    measureCache.put(p, m);
-
-    assertThat(measureCache.contains(p, m)).isTrue();
-    assertThat(measureCache.entries()).hasSize(1);
-    Iterator<Entry<Measure>> iterator = measureCache.entries().iterator();
-    iterator.hasNext();
-    Entry<Measure> next = iterator.next();
-    assertThat(next.value()).isEqualTo(m);
-    assertThat(next.key()[0]).isEqualTo("struts");
-
-    assertThat(measureCache.byResource(p)).hasSize(1);
-    assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m);
+    assertThat(measureCache.byComponentKey(COMPONENT_KEY)).hasSize(1);
+    assertThat(measureCache.byComponentKey(COMPONENT_KEY).iterator().next()).isEqualTo(m);
   }
 
   /**
@@ -115,117 +79,84 @@ public class MeasureCacheTest extends AbstractCachesTest {
    */
   @Test
   public void should_add_measure_with_too_big_data_for_persistit_pre_patch() {
-    Project p = new Project("struts");
-
     assertThat(measureCache.entries()).hasSize(0);
+    assertThat(measureCache.byComponentKey(COMPONENT_KEY)).hasSize(0);
 
-    assertThat(measureCache.byResource(p)).hasSize(0);
-
-    Measure m = new Measure(CoreMetrics.NCLOC, 1.0).setDate(new Date());
-    StringBuilder data = new StringBuilder();
-    for (int i = 0; i < 500000; i++) {
-      data.append("some data");
+    StringBuilder data = new StringBuilder(4_500_000);
+    for (int i = 0; i < 4_500_000; i++) {
+      data.append('a');
     }
-    m.setData(data.toString());
-
-    measureCache.put(p, m);
+    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(p, m)).isTrue();
+    assertThat(measureCache.contains(COMPONENT_KEY, CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY)).isTrue();
     assertThat(measureCache.entries()).hasSize(1);
-    Iterator<Entry<Measure>> iterator = measureCache.entries().iterator();
+    Iterator<Entry<DefaultMeasure<?>>> iterator = measureCache.entries().iterator();
     iterator.hasNext();
-    Entry<Measure> next = iterator.next();
+    Entry<DefaultMeasure<?>> next = iterator.next();
     assertThat(next.value()).isEqualTo(m);
-    assertThat(next.key()[0]).isEqualTo("struts");
+    assertThat(next.key()[0]).isEqualTo(COMPONENT_KEY);
 
-    assertThat(measureCache.byResource(p)).hasSize(1);
-    assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m);
+    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() {
-    Project p = new Project("struts");
-
     assertThat(measureCache.entries()).hasSize(0);
+    assertThat(measureCache.byComponentKey(COMPONENT_KEY)).hasSize(0);
 
-    assertThat(measureCache.byResource(p)).hasSize(0);
-
-    Measure m = new Measure(CoreMetrics.NCLOC, 1.0).setDate(new Date());
-    StringBuilder data = new StringBuilder(64 * 1024 * 1024 + 1);
     // Limit is 64Mo
-    for (int i = 0; i < (64 * 1024 * 1024 + 1); i++) {
+    StringBuilder data = new StringBuilder(64 * 1024 * 1024 + 1);
+    for (int i = 0; i < 64 * 1024 * 1024 + 1; i++) {
       data.append('a');
     }
-    m.setData(data.toString());
+    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 cache measures");
+    thrown.expectMessage("Fail to put element in the storage 'measures'");
 
-    measureCache.put(p, m);
+    measureCache.put(COMPONENT_KEY, CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, m);
   }
 
   @Test
   public void should_get_measures() {
-    Project p = new Project("struts");
-    Resource dir = Directory.create("foo/bar").setEffectiveKey("struts:foo/bar");
-    Resource file1 = Directory.create("foo/bar/File1.txt").setEffectiveKey("struts:foo/bar/File1.txt");
-    Resource file2 = Directory.create("foo/bar/File2.txt").setEffectiveKey("struts:foo/bar/File2.txt");
+    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.byResource(p)).hasSize(0);
-    assertThat(measureCache.byResource(dir)).hasSize(0);
+    assertThat(measureCache.byComponentKey(projectKey)).hasSize(0);
+    assertThat(measureCache.byComponentKey(dirKey)).hasSize(0);
 
-    Measure mFile1 = new Measure(CoreMetrics.NCLOC, 1.0);
-    measureCache.put(file1, mFile1);
-    Measure mFile2 = new Measure(CoreMetrics.NCLOC, 3.0);
-    measureCache.put(file2, mFile2);
+    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.byResource(p)).hasSize(0);
-    assertThat(measureCache.byResource(dir)).hasSize(0);
+    assertThat(measureCache.byComponentKey(projectKey)).hasSize(0);
+    assertThat(measureCache.byComponentKey(dirKey)).hasSize(0);
 
-    Measure mDir = new Measure(CoreMetrics.NCLOC, 4.0);
-    measureCache.put(dir, mDir);
+    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.byResource(p)).hasSize(0);
-    assertThat(measureCache.byResource(dir)).hasSize(1);
-    assertThat(measureCache.byResource(dir).iterator().next()).isEqualTo(mDir);
+    assertThat(measureCache.byComponentKey(projectKey)).hasSize(0);
+    assertThat(measureCache.byComponentKey(dirKey)).hasSize(1);
+    assertThat(measureCache.byComponentKey(dirKey).iterator().next()).isEqualTo(mDir);
 
-    Measure mProj = new Measure(CoreMetrics.NCLOC, 4.0);
-    measureCache.put(p, mProj);
+    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.byResource(p)).hasSize(1);
-    assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(mProj);
-    assertThat(measureCache.byResource(dir)).hasSize(1);
-    assertThat(measureCache.byResource(dir).iterator().next()).isEqualTo(mDir);
+    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);
   }
 
-  @Test
-  public void test_measure_coder() throws Exception {
-    Resource file1 = File.create("foo/bar/File1.txt").setEffectiveKey("struts:foo/bar/File1.txt");
-
-    Measure measure = new Measure(CoreMetrics.NCLOC, 3.14);
-    measure.setData("data");
-    measure.setAlertStatus(Level.ERROR);
-    measure.setAlertText("alert");
-    measure.setDate(new Date());
-    measure.setDescription("description");
-    measure.setPersistenceMode(null);
-    measure.setPersonId(3);
-    measure.setUrl("http://foo");
-    measure.setVariation1(11.0);
-    measure.setVariation2(12.0);
-    measure.setVariation3(13.0);
-    measure.setVariation4(14.0);
-    measure.setVariation5(15.0);
-    measureCache.put(file1, measure);
-
-    Measure savedMeasure = measureCache.byResource(file1).iterator().next();
-    assertThat(EqualsBuilder.reflectionEquals(measure, savedMeasure)).isTrue();
-
-  }
 }
index e9ae12fd68819f59a0d925a9f79b25c6d41907aa..c78affbaa9bc56dafe297d771e8540d9755dc4fe 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.scanner.sensor;
 
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -32,13 +34,14 @@ import org.sonar.api.batch.measure.MetricFinder;
 import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
 import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
-import org.sonar.api.config.Settings;
 import org.sonar.api.config.MapSettings;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
 import org.sonar.api.resources.File;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
+import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.core.metric.ScannerMetrics;
 import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
 import org.sonar.scanner.index.BatchComponentCache;
 import org.sonar.scanner.issue.ModuleIssues;
@@ -66,10 +69,9 @@ public class DefaultSensorStorageTest {
   private DefaultSensorStorage underTest;
   private Settings settings;
   private ModuleIssues moduleIssues;
-  private Project project;
   private MeasureCache measureCache;
   private ContextPropertiesCache contextPropertiesCache = new ContextPropertiesCache();
-  private BatchComponentCache resourceCache;
+  private BatchComponentCache componentCache;
 
   @Before
   public void prepare() throws Exception {
@@ -78,24 +80,23 @@ public class DefaultSensorStorageTest {
     when(metricFinder.<String>findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
     settings = new MapSettings();
     moduleIssues = mock(ModuleIssues.class);
-    project = new Project("myProject");
     measureCache = mock(MeasureCache.class);
     CoverageExclusions coverageExclusions = mock(CoverageExclusions.class);
-    when(coverageExclusions.accept(any(Resource.class), any(Measure.class))).thenReturn(true);
-    resourceCache = new BatchComponentCache();
+    when(coverageExclusions.isExcluded(any(InputFile.class))).thenReturn(false);
+    componentCache = new BatchComponentCache();
     ReportPublisher reportPublisher = mock(ReportPublisher.class);
     when(reportPublisher.getWriter()).thenReturn(new ScannerReportWriter(temp.newFolder()));
     underTest = new DefaultSensorStorage(metricFinder,
-      moduleIssues, settings, coverageExclusions, resourceCache, reportPublisher, measureCache,
-      mock(SonarCpdBlockIndex.class), contextPropertiesCache);
+      moduleIssues, settings, coverageExclusions, componentCache, reportPublisher, measureCache,
+      mock(SonarCpdBlockIndex.class), contextPropertiesCache, new ScannerMetrics());
   }
 
   @Test
   public void shouldFailIfUnknownMetric() {
     InputFile file = new DefaultInputFile("foo", "src/Foo.php");
 
-    thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("Unknow metric with key: lines");
+    thrown.expect(UnsupportedOperationException.class);
+    thrown.expectMessage("Unknown metric: lines");
 
     underTest.store(new DefaultMeasure()
       .on(file)
@@ -107,36 +108,37 @@ public class DefaultSensorStorageTest {
   public void shouldSaveFileMeasureToSensorContext() {
     InputFile file = new DefaultInputFile("foo", "src/Foo.php");
 
-    ArgumentCaptor<org.sonar.api.measures.Measure> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
+    ArgumentCaptor<DefaultMeasure> argumentCaptor = ArgumentCaptor.forClass(DefaultMeasure.class);
     Resource sonarFile = File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php");
-    resourceCache.add(sonarFile, null).setInputComponent(file);
-    when(measureCache.put(eq(sonarFile), argumentCaptor.capture())).thenReturn(null);
+    componentCache.add(sonarFile, null).setInputComponent(file);
+    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));
 
-    org.sonar.api.measures.Measure m = argumentCaptor.getValue();
-    assertThat(m.getValue()).isEqualTo(10.0);
-    assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
+    DefaultMeasure m = argumentCaptor.getValue();
+    assertThat(m.value()).isEqualTo(10);
+    assertThat(m.metric()).isEqualTo(CoreMetrics.NCLOC);
   }
 
   @Test
   public void shouldSaveProjectMeasureToSensorContext() {
-    DefaultInputModule module = new DefaultInputModule(project.getEffectiveKey());
-    resourceCache.add(project, null).setInputComponent(module);
+    String projectKey = "myProject";
+    DefaultInputModule module = new DefaultInputModule(projectKey);
+    componentCache.add(new Project(projectKey), null).setInputComponent(module);
 
-    ArgumentCaptor<org.sonar.api.measures.Measure> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
-    when(measureCache.put(eq(project), argumentCaptor.capture())).thenReturn(null);
+    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));
 
-    org.sonar.api.measures.Measure m = argumentCaptor.getValue();
-    assertThat(m.getValue()).isEqualTo(10.0);
-    assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
+    DefaultMeasure m = argumentCaptor.getValue();
+    assertThat(m.value()).isEqualTo(10);
+    assertThat(m.metric()).isEqualTo(CoreMetrics.NCLOC);
   }
 
   @Test(expected = UnsupportedOperationException.class)
@@ -144,7 +146,7 @@ public class DefaultSensorStorageTest {
     Resource sonarFile = File.create("src/Foo.java").setEffectiveKey("foo:src/Foo.java");
     DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.java")
       .setModuleBaseDir(temp.newFolder().toPath());
-    resourceCache.add(sonarFile, null).setInputComponent(inputFile);
+    componentCache.add(sonarFile, null).setInputComponent(inputFile);
     DefaultHighlighting h = new DefaultHighlighting(null)
       .onFile(inputFile);
     underTest.store(h);
@@ -156,7 +158,7 @@ public class DefaultSensorStorageTest {
     Resource sonarFile = File.create("src/Foo.java").setEffectiveKey("foo:src/Foo.java");
     DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.java")
       .setModuleBaseDir(temp.newFolder().toPath());
-    resourceCache.add(sonarFile, null).setInputComponent(inputFile);
+    componentCache.add(sonarFile, null).setInputComponent(inputFile);
     DefaultSymbolTable st = new DefaultSymbolTable(null)
       .onFile(inputFile);
     underTest.store(st);
@@ -166,9 +168,28 @@ public class DefaultSensorStorageTest {
   @Test
   public void shouldStoreContextProperty() {
     underTest.storeProperty("foo", "bar");
-
     assertThat(contextPropertiesCache.getAll()).containsOnly(entry("foo", "bar"));
+  }
+
+  @Test
+  public void shouldValidateStrictlyPositiveLine() throws Exception {
+    DefaultInputFile file = new DefaultInputFile("module", "testfile").setModuleBaseDir(temp.newFolder().toPath());
+    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 {
+    DefaultInputFile file = new DefaultInputFile("module", "testfile").setModuleBaseDir(temp.newFolder().toPath());
+    Map<Integer, Integer> map = ImmutableMap.of(11, 3);
+    String data = KeyValueFormat.format(map);
+
+    thrown.expect(IllegalStateException.class);
+    underTest.validateCoverageMeasure(data, file);
   }
 
 }
index 3a59eecdce310004c0b531ccefe631b37463631e..68d4080cb9b5fbea68c118eceae58c4716230631 100644 (file)
  */
 package org.sonar.scanner.sensor.coverage;
 
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
 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.DefaultFileSystem;
+import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.config.MapSettings;
 import org.sonar.api.config.PropertyDefinitions;
 import org.sonar.api.config.Settings;
-import org.sonar.api.config.MapSettings;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.core.config.ExclusionProperties;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class CoverageExclusionsTest {
 
-  @Rule
-  public ExpectedException exception = ExpectedException.none();
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
   private Settings settings;
-  private DefaultFileSystem fs;
-
-  private CoverageExclusions filter;
+  private CoverageExclusions coverageExclusions;
 
   @Before
-  public void createFilter() {
+  public void prepare() {
     settings = new MapSettings(new PropertyDefinitions(ExclusionProperties.all()));
-    fs = new DefaultFileSystem(temp.getRoot());
-    filter = new CoverageExclusions(settings, fs);
-  }
-
-  @Test
-  public void shouldValidateStrictlyPositiveLine() {
-    DefaultInputFile file = new DefaultInputFile("module", "testfile");
-    Measure measure = mock(Measure.class);
-    Map<Integer, Integer> map = ImmutableMap.of(0, 3);
-
-    String data = KeyValueFormat.format(map);
-    when(measure.getMetric()).thenReturn(CoreMetrics.IT_CONDITIONS_BY_LINE);
-    when(measure.getData()).thenReturn(data);
-
-    fs.add(file);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("must be > 0");
-    filter.validate(measure, "testfile");
+    coverageExclusions = new CoverageExclusions(settings);
   }
 
   @Test
-  public void shouldValidateFileExists() {
-    DefaultInputFile file = new DefaultInputFile("module", "testfile");
-    Measure measure = mock(Measure.class);
-    Map<Integer, Integer> map = ImmutableMap.of(0, 3);
-
-    String data = KeyValueFormat.format(map);
-    when(measure.getMetric()).thenReturn(CoreMetrics.IT_CONDITIONS_BY_LINE);
-    when(measure.getData()).thenReturn(data);
-
-    fs.add(file);
-
-    exception.expect(IllegalStateException.class);
-    exception.expectMessage("resource is not indexed as a file");
-    filter.validate(measure, "dummy");
-  }
-
-  @Test
-  public void shouldValidateMaxLine() {
-    DefaultInputFile file = new DefaultInputFile("module", "testfile");
-    file.setLines(10);
-    Measure measure = mock(Measure.class);
-    Map<Integer, Integer> map = ImmutableMap.of(11, 3);
-
-    String data = KeyValueFormat.format(map);
-    when(measure.getMetric()).thenReturn(CoreMetrics.COVERED_CONDITIONS_BY_LINE);
-    when(measure.getData()).thenReturn(data);
-
-    exception.expect(IllegalStateException.class);
-    filter.validate(measure, file);
-  }
-
-  @Test
-  public void shouldNotFilterNonCoverageMetrics() {
-    Measure otherMeasure = mock(Measure.class);
-    when(otherMeasure.getMetric()).thenReturn(CoreMetrics.LINES);
-    assertThat(filter.accept(mock(Resource.class), otherMeasure)).isTrue();
-  }
-
-  @Test
-  public void shouldFilterFileBasedOnPattern() {
-    Resource resource = File.create("src/org/polop/File.php", null, false);
-    Measure coverageMeasure = mock(Measure.class);
-    when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.LINES_TO_COVER);
-
+  public void shouldExcludeFileBasedOnPattern() {
+    InputFile file = new DefaultInputFile("foo", "src/org/polop/File.php");
     settings.setProperty("sonar.coverage.exclusions", "src/org/polop/*");
-    filter.initPatterns();
-    assertThat(filter.accept(resource, coverageMeasure)).isFalse();
+    coverageExclusions.initPatterns();
+    assertThat(coverageExclusions.isExcluded(file)).isTrue();
   }
 
   @Test
-  public void shouldNotFilterFileBasedOnPattern() {
-    Resource resource = File.create("src/org/polop/File.php", null, false);
-    Measure coverageMeasure = mock(Measure.class);
-    when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.COVERAGE);
-
+  public void shouldNotExcludeFileBasedOnPattern() {
+    InputFile file = new DefaultInputFile("foo", "src/org/polop/File.php");
     settings.setProperty("sonar.coverage.exclusions", "src/org/other/*");
-    filter.initPatterns();
-    assertThat(filter.accept(resource, coverageMeasure)).isTrue();
+    coverageExclusions.initPatterns();
+    assertThat(coverageExclusions.isExcluded(file)).isFalse();
   }
 }